diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml
index 91bfd5d6f6aa6559c9c37f33cb58851e780bd363..4a09e61a466af4b49772fe1e4d210123868d41c7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/code_mirror_support.xml
@@ -50,7 +50,6 @@
  -->\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/addon/hint/show-hint.css">\n
 <script src="&dtml-portal_url;/codemirror/addon/hint/show-hint.js"></script>\n
-<script src="&dtml-portal_url;/codemirror/addon/hint/python-hint.js"></script>\n
 \n
 <!-- Code folding -->\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/addon/fold/foldgutter.css">\n
@@ -61,7 +60,7 @@
 \n
 <!-- Merge -->\n
 <link rel="stylesheet" href="&dtml-portal_url;/codemirror/addon/merge/merge.css">\n
-<script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/merge/dep/diff_match_patch.js"></script>\n
+<script type="text/javascript" src="&dtml-portal_url;/diff_match_patch/javascript/diff_match_patch_uncompressed.js"></script>\n
 <script type="text/javascript" src="&dtml-portal_url;/codemirror/addon/merge/merge.js"></script>\n
 \n
 <!-- Lint\n
@@ -400,11 +399,10 @@
    is_maximized = true;\n
  }\n
 \n
- function checkPythonSourceCode(cm, updateLinting, options) {\n
-// CodeMirror.registerHelper("lint", "python", function(text) {\n
+ function checkPythonSourceCode(text, updateLinting, options, cm) {\n
    $.post(\n
      \'&dtml-portal_url;/ERP5Site_checkPythonSourceCodeAsJSON\',\n
-     {\'data\': JSON.stringify({code: cm.getValue()})},\n
+     {\'data\': JSON.stringify({code: text})},\n
       function(data){\n
         var messages = data.annotations;\n
         var found = [];\n
@@ -440,8 +438,8 @@
     gutters: ["CodeMirror-lint-markers",\n
               "CodeMirror-linenumbers",\n
               "CodeMirror-foldgutter"],\n
-    lintWith: {"getAnnotations": checkPythonSourceCode,\n
-               "async": true}\n
+    lint: {"getAnnotations": checkPythonSourceCode,\n
+           "async": true}\n
     });\n
  //cm.foldCode(CodeMirror.Pos(8, 0));\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec/spec.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.gitattributes.xml
similarity index 66%
rename from bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec/spec.css.xml
rename to bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.gitattributes.xml
index c679d34439cb22965506f600c7f4f21cb31f7eeb..bcff434a8e20820026701aadc725c7dfa69f5a24 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec/spec.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.gitattributes.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>__name__</string> </key>
-            <value> <string>spec.css</string> </value>
+            <value> <string>.gitattributes</string> </value>
         </item>
         <item>
             <key> <string>_vars</string> </key>
@@ -24,11 +24,14 @@
         </item>
         <item>
             <key> <string>raw</string> </key>
-            <value> <string>.cm-s-default span.cm-preamble {color: #b26818; font-weight: bold;}\n
-.cm-s-default span.cm-macro {color: #b218b2;}\n
-.cm-s-default span.cm-section {color: green; font-weight: bold;}\n
-.cm-s-default span.cm-script {color: red;}\n
-.cm-s-default span.cm-issue {color: yellow;}\n
+            <value> <string>*.txt   text\n
+*.js    text\n
+*.html  text\n
+*.md    text\n
+*.json  text\n
+*.yml   text\n
+*.css   text\n
+*.svg   text\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.gitignore.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.gitignore.xml
new file mode 100644
index 0000000000000000000000000000000000000000..07cb5f265f9bad70f139bfc7759ef3826531b43e
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.gitignore.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>.gitignore</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>/node_modules\n
+/npm-debug.log\n
+test.html\n
+.tern-*\n
+*~\n
+*.swp\n
+.idea\n
+*.iml\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.travis.yml.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.travis.yml.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4aa461ffb390213963d0c72992813c66831358d8
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/.travis.yml.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>.travis.yml</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>language: node_js\n
+node_js:\n
+  - 0.8\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/AUTHORS.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/AUTHORS.xml
index 807396f2452b639ff821f40450d1b666c3778196..910bd1a5230db28d6ed8df6bc33d4d10bd8ca779 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/AUTHORS.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/AUTHORS.xml
@@ -28,29 +28,41 @@
 \n
 4r2r\n
 Aaron Brooks\n
+Abdelouahab\n
 Abe Fettig\n
+Adam Ahmed\n
 Adam King\n
 adanlobato\n
 Ad谩n Lobato\n
+Adrian Aichner\n
 aeroson\n
 Ahmad Amireh\n
 Ahmad M. Zawawi\n
 ahoward\n
 Akeksandr Motsjonov\n
+Alberto Gonz谩lez Palomo\n
 Alberto Pose\n
 Albert Xing\n
 Alexander Pavlov\n
 Alexander Schepanovski\n
+Alexander Shvets\n
 Alexander Solovyov\n
+Alexandre Bique\n
 alexey-k\n
 Alex Piggott\n
 Amsul\n
+amuntean\n
 Amy\n
 Ananya Sen\n
 anaran\n
 AndersMad\n
+Anders Nawroth\n
 Anderson Mesquita\n
+Andrea G\n
+Andreas Reischuck\n
 Andre von Houck\n
+Andrey Fedorov\n
+Andrey Klyuchnikov\n
 Andrey Lushnikov\n
 Andy Joslin\n
 Andy Kimball\n
@@ -62,52 +74,72 @@ Ansel Santosa\n
 Anthony Grimes\n
 Anton Kovalyov\n
 areos\n
+as3boyan\n
 AtomicPages LLC\n
 Atul Bhouraskar\n
 Aurelian Oancea\n
 Bastian Mu虉ller\n
+Bem Jones-Bey\n
 benbro\n
 Beni Cherniavsky-Paskin\n
 Benjamin DeCoste\n
 Ben Keen\n
 Bernhard Sirlinger\n
+Bert Chang\n
 Billy Moon\n
+binny\n
+B Krishna Chaitanya\n
 Blaine G\n
+blukat29\n
 boomyjee\n
 borawjm\n
 Brandon Frohs\n
 Brandon Wamboldt\n
 Brett Zamir\n
+Brian Grinstead\n
 Brian Sletten\n
 Bruce Mitchener\n
 Chandra Sekhar Pydi\n
 Charles Skelton\n
+Cheah Chu Yeow\n
 Chris Coyier\n
 Chris Granger\n
 Chris Houseknecht\n
 Chris Morgan\n
+Christian Oyarzun\n
 Christopher Brown\n
 ciaranj\n
 CodeAnimal\n
 ComFreek\n
 Curtis Gagliardi\n
 dagsta\n
+daines\n
+Dale Jung\n
+Dan Bentley\n
 Dan Heberden\n
 Daniel, Dao Quang Minh\n
+Daniele Di Sarli\n
 Daniel Faust\n
 Daniel Huigens\n
 Daniel KJ\n
 Daniel Neel\n
 Daniel Parnell\n
 Danny Yoo\n
+darealshinji\n
 Darius Roberts\n
+Dave Myers\n
 David Mignot\n
 David Pathakjee\n
+David V谩zquez\n
 deebugger\n
 Deep Thought\n
+Devon Carew\n
+dignifiedquire\n
+Dimage Sapelkin\n
 domagoj412\n
 Dominator008\n
 Domizio Demichelis\n
+Doug Wikle\n
 Drew Bratcher\n
 Drew Hintz\n
 Drew Khoury\n
@@ -121,6 +153,7 @@ Eric Allam\n
 eustas\n
 Fabien O\'Carroll\n
 Fabio Zendhi Nagao\n
+Faiza Alsaied\n
 Fauntleroy\n
 fbuchinger\n
 feizhang365\n
@@ -132,20 +165,30 @@ ForbesLindesay\n
 Forbes Lindesay\n
 Ford_Lawnmower\n
 Frank Wiegand\n
+Gabriel Gheorghian\n
+Gabriel Horner\n
 Gabriel Nahmias\n
 galambalazs\n
 Gautam Mehta\n
+gekkoe\n
+Gerard Braad\n
+Gergely Hegykozi\n
 Glenn Jorde\n
 Glenn Ruehle\n
 Golevka\n
 Gordon Smith\n
 Grant Skinner\n
 greengiant\n
+Gregory Koberger\n
 Guillaume Masse虂\n
 Guillaume Mass茅\n
+Gustavo Rodrigues\n
+Hakan Tunc\n
 Hans Engel\n
 Hardest\n
 Hasan Karahan\n
+Herculano Campos\n
+Hiroyuki Makino\n
 hitsthings\n
 Hocdoc\n
 Ian Beck\n
@@ -161,6 +204,7 @@ Ivan Kurnosov\n
 Jacob Lee\n
 Jakob Miland\n
 Jakub Vrana\n
+Jakub Vr谩na\n
 James Campos\n
 James Thorne\n
 Jamie Hill\n
@@ -169,15 +213,19 @@ jankeromnes\n
 Jan Keromnes\n
 Jan Odvarko\n
 Jan T. Sott\n
+Jared Forsyth\n
 Jason\n
+Jason Barnabe\n
 Jason Grout\n
 Jason Johnston\n
 Jason San Jose\n
 Jason Siefken\n
+Jaydeep Solanki\n
 Jean Boussier\n
 jeffkenton\n
 Jeff Pickhardt\n
 jem (graphite)\n
+Jeremy Parmenter\n
 Jochen Berger\n
 Johan Ask\n
 John Connor\n
@@ -187,19 +235,23 @@ John Van Der Loo\n
 Jonathan Malmaud\n
 jongalloway\n
 Jon Malmaud\n
+Jon Sangster\n
 Joost-Wim Boekesteijn\n
 Joseph Pecoraro\n
 Joshua Newman\n
+Josh Watzman\n
 jots\n
 jsoojeon\n
 Juan Benavides Romero\n
 Jucovschi Constantin\n
 Juho Vuori\n
+Justin Hileman\n
 jwallers@gmail.com\n
 kaniga\n
 Ken Newman\n
 Ken Rockot\n
 Kevin Sawicki\n
+Kevin Ushey\n
 Klaus Silveira\n
 Koh Zi Han, Cliff\n
 komakino\n
@@ -207,22 +259,31 @@ Konstantin Lopuhin\n
 koops\n
 ks-ifware\n
 kubelsmieci\n
+Lanfei\n
 Lanny\n
 Laszlo Vidacs\n
 leaf corcoran\n
+Leonid Khachaturov\n
+Leon Sorokin\n
 Leonya Khachaturov\n
 Liam Newman\n
 LM\n
+lochel\n
 Lorenzo Stoakes\n
 Luciano Longo\n
+Luke Stagner\n
 lynschinzer\n
 Maksim Lin\n
 Maksym Taran\n
+Malay Majithia\n
 Manuel Rego Casasnovas\n
 Marat Dreizin\n
+Marcel Gerber\n
 Marco Aur茅lio\n
 Marco Munizaga\n
+Marcus Bointon\n
 Marijn Haverbeke\n
+M谩rio Gon莽alves\n
 Mario Pietsch\n
 Mark Lentczner\n
 Marko Bonaci\n
@@ -231,15 +292,19 @@ Mart铆n Gait谩n\n
 Martin Haso艌\n
 Mason Malone\n
 Mateusz Paprocki\n
+Mathias Bynens\n
 mats cronqvist\n
 Matthew Beale\n
+Matthias Bussonnier\n
 Matthias BUSSONNIER\n
 Matt McDonald\n
 Matt Pass\n
 Matt Sacks\n
+mauricio\n
 Maximilian Hils\n
 Maxim Kraev\n
 Max Kirsch\n
+Max Xiantu\n
 mbarkhau\n
 Metatheos\n
 Micah Dubinko\n
@@ -256,6 +321,7 @@ MinRK\n
 Miraculix87\n
 misfo\n
 mloginov\n
+Moritz Schw枚rer\n
 mps\n
 mtaran-google\n
 Narciso Jaramillo\n
@@ -264,14 +330,25 @@ ndr\n
 nerbert\n
 nextrevision\n
 nguillaumin\n
+Ng Zhi An\n
 Nicholas Bollweg\n
+Nicholas Bollweg (Nick)\n
+Nick Small\n
 Niels van Groningen\n
+nightwing\n
 Nikita Beloglazov\n
 Nikita Vasilyev\n
 Nikolay Kostov\n
+nilp0inter\n
+Nisarg Jhaveri\n
 nlwillia\n
+Norman Rzepka\n
 pablo\n
 Page\n
+Panupong Pasupat\n
+paris\n
+Patil Arpith\n
+Patrick Stoica\n
 Patrick Strawderman\n
 Paul Garvin\n
 Paul Ivanov\n
@@ -279,14 +356,21 @@ Pavel Feldman\n
 Pavel Strashkin\n
 Pawe艂 Bartkiewicz\n
 peteguhl\n
+Peter Flynn\n
 peterkroon\n
 Peter Kroon\n
 prasanthj\n
 Prasanth J\n
+Radek Pi贸rkowski\n
 Rahul\n
+Randall Mason\n
+Randy Burden\n
 Randy Edmunds\n
 Rasmus Erik Voel Jensen\n
+Richard van der Meer\n
 Richard Z.H. Wang\n
+Robert Crossfield\n
+Roberto Abdelkader Mart铆nez P茅rez\n
 robertop23\n
 Robert Plummer\n
 Ruslan Osmanov\n
@@ -294,11 +378,14 @@ Ryan Prior\n
 sabaca\n
 Samuel Ainsworth\n
 sandeepshetty\n
+Sander AKA Redsandro\n
 santec\n
 Sascha Peilicke\n
 satchmorun\n
 sathyamoorthi\n
 SCLINIC\\jdecker\n
+Scott Aikin\n
+Scott Goodhew\n
 Sebastian Zaha\n
 shaund\n
 shaun gilchrist\n
@@ -306,9 +393,13 @@ Shawn A\n
 sheopory\n
 Shiv Deepak\n
 Shmuel Englard\n
+Shubham Jain\n
+silverwind\n
+snasa\n
 soliton4\n
 sonson\n
 spastorelli\n
+srajanpaliwal\n
 Stanislav Oaserele\n
 Stas Kobzar\n
 Stefan Borsje\n
@@ -316,12 +407,15 @@ Steffen Beyer\n
 Steve O\'Hara\n
 stoskov\n
 Taha Jahangir\n
+Takuji Shimokawa\n
 Tarmil\n
 tfjgeorge\n
 Thaddee Tyl\n
+TheHowl\n
 think\n
 Thomas Dvornik\n
 Thomas Schmid\n
+Tim Alby\n
 Tim Baumann\n
 Timothy Farrell\n
 Timothy Hatcher\n
@@ -333,14 +427,20 @@ Tom MacWright\n
 Tony Jian\n
 Travis Heppe\n
 Triangle717\n
+twifkak\n
 Vestimir Markov\n
 vf\n
+Vincent Woo\n
 Volker Mische\n
 wenli\n
 Wesley Wiser\n
+Will Binns-Smith\n
 William Jamieson\n
+William Stein\n
+Willy\n
 Wojtek Ptak\n
 Xavier Mendez\n
+Yassin N. Hassan\n
 YNH Webdev\n
 Yunchi Luo\n
 Yuvi Panda\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/CONTRIBUTING.md.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/CONTRIBUTING.md.xml
index e38956e521f6d48a4ade91d3059582bd6dff7a58..55830b18f7a2361db57646bed073bee2f52530c4 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/CONTRIBUTING.md.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/CONTRIBUTING.md.xml
@@ -33,17 +33,17 @@
 ## Getting help\n
 \n
 Community discussion, questions, and informal bug reporting is done on the\n
-[CodeMirror Google group](http://groups.google.com/group/codemirror).\n
+[discuss.CodeMirror forum](http://discuss.codemirror.net).\n
 \n
 ## Submitting bug reports\n
 \n
 The preferred way to report bugs is to use the\n
-[GitHub issue tracker](http://github.com/marijnh/CodeMirror/issues). Before\n
+[GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before\n
 reporting a bug, read these pointers.\n
 \n
 **Note:** The issue tracker is for *bugs*, not requests for help. Questions\n
 should be asked on the\n
-[CodeMirror Google group](http://groups.google.com/group/codemirror) instead.\n
+[discuss.CodeMirror forum](http://discuss.codemirror.net) instead.\n
 \n
 ### Reporting bugs effectively\n
 \n
@@ -74,7 +74,7 @@ should be asked on the\n
 ## Contributing code\n
 \n
 - Make sure you have a [GitHub Account](https://github.com/signup/free)\n
-- Fork [CodeMirror](https://github.com/marijnh/CodeMirror/)\n
+- Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)\n
   ([how to fork a repo](https://help.github.com/articles/fork-a-repo))\n
 - Make your changes\n
 - If your changes are easy to test or likely to regress, add tests.\n
@@ -96,6 +96,10 @@ should be asked on the\n
 - Note that the linter (`bin/lint`) which is run after each commit\n
   complains about unused variables and functions. Prefix their names\n
   with an underscore to muffle it.\n
+\n
+- CodeMirror does *not* follow JSHint or JSLint prescribed style.\n
+  Patches that try to \'fix\' code to pass one of these linters will be\n
+  unceremoniously discarded.\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/LICENSE.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/LICENSE.xml
index 134717d94c282d2b02d9573031efa80f8778729c..35c2a584ff256d377519a5d78a3a3e96043fe514 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/LICENSE.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/LICENSE.xml
@@ -26,7 +26,7 @@
             <key> <string>raw</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com> and others\n
+Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others\n
 \n
 Permission is hereby granted, free of charge, to any person obtaining a copy\n
 of this software and associated documentation files (the "Software"), to deal\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/README.md.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/README.md.xml
index 277e0af7f362070c5cdce593498e4bdc83b4ad6d..cce50795409b7a7b972c19ca6cf9d85a5c644366 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/README.md.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/README.md.xml
@@ -25,8 +25,8 @@
         <item>
             <key> <string>raw</string> </key>
             <value> <string># CodeMirror\n
-[![Build Status](https://secure.travis-ci.org/marijnh/CodeMirror.png?branch=master)](http://travis-ci.org/marijnh/CodeMirror)\n
-[![NPM version](https://badge.fury.io/js/codemirror.png)](http://badge.fury.io/js/codemirror)\n
+[![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)\n
+[![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)\n
 \n
 CodeMirror is a JavaScript component that provides a code editor in\n
 the browser. When a mode is available for the language you are coding\n
@@ -34,7 +34,7 @@ in, it will color your code, and optionally help with indentation.\n
 \n
 The project page is http://codemirror.net  \n
 The manual is at http://codemirror.net/doc/manual.html  \n
-The contributing guidelines are in [CONTRIBUTING.md](https://github.com/marijnh/CodeMirror/blob/master/CONTRIBUTING.md)\n
+The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/comment.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/comment.js.xml
index cb8db30c9c7868b1c2c7ebdb52a601a45fd0f9b2..a944ea7c8ec29d5779a35bbdbfc4c96f97a8bed8 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/comment.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/comment.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.99</string> </value>
+            <value> <string>ts21897117.58</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var noOptions = {};\n
@@ -35,8 +45,21 @@
   }\n
 \n
   CodeMirror.commands.toggleComment = function(cm) {\n
-    var from = cm.getCursor("start"), to = cm.getCursor("end");\n
-    cm.uncomment(from, to) || cm.lineComment(from, to);\n
+    var minLine = Infinity, ranges = cm.listSelections(), mode = null;\n
+    for (var i = ranges.length - 1; i >= 0; i--) {\n
+      var from = ranges[i].from(), to = ranges[i].to();\n
+      if (from.line >= minLine) continue;\n
+      if (to.line >= minLine) to = Pos(minLine, 0);\n
+      minLine = from.line;\n
+      if (mode == null) {\n
+        if (cm.uncomment(from, to)) mode = "un";\n
+        else { cm.lineComment(from, to); mode = "line"; }\n
+      } else if (mode == "un") {\n
+        cm.uncomment(from, to);\n
+      } else {\n
+        cm.lineComment(from, to);\n
+      }\n
+    }\n
   };\n
 \n
   CodeMirror.defineExtension("lineComment", function(from, to, options) {\n
@@ -110,7 +133,7 @@
   CodeMirror.defineExtension("uncomment", function(from, to, options) {\n
     if (!options) options = noOptions;\n
     var self = this, mode = self.getModeAt(from);\n
-    var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end);\n
+    var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);\n
 \n
     // Try finding line comments\n
     var lineString = options.lineComment || mode.lineComment, lines = [];\n
@@ -153,6 +176,17 @@
         !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||\n
         !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))\n
       return false;\n
+\n
+    // Avoid killing block comments completely outside the selection.\n
+    // Positions of the last startString before the start of the selection, and the first endString after it.\n
+    var lastStart = startLine.lastIndexOf(startString, from.ch);\n
+    var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);\n
+    if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;\n
+    // Positions of the first endString after the end of the selection, and the last startString before it.\n
+    firstEnd = endLine.indexOf(endString, to.ch);\n
+    var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);\n
+    lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;\n
+    if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;\n
 \n
     self.operation(function() {\n
       self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),\n
@@ -170,7 +204,7 @@
     });\n
     return true;\n
   });\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -181,7 +215,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6207</int> </value>
+            <value> <int>8008</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/continuecomment.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/continuecomment.js.xml
index 455fdade57719b1f5f05588411ab40ed3bfd6cec..5031a6aeb1820b27b956c5bee38ea1b9a3296c52 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/continuecomment.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/comment/continuecomment.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.86</string> </value>
+            <value> <string>ts21897117.72</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,49 +22,67 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   var modes = ["clike", "css", "javascript"];\n
 \n
   for (var i = 0; i < modes.length; ++i)\n
     CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});\n
 \n
   function continueComment(cm) {\n
-    var pos = cm.getCursor(), token = cm.getTokenAt(pos);\n
-    if (token.type != "comment" || cm.getOption("disableInput")) return CodeMirror.Pass;\n
-    var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;\n
+    if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+    var ranges = cm.listSelections(), mode, inserts = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var pos = ranges[i].head, token = cm.getTokenAt(pos);\n
+      if (token.type != "comment") return CodeMirror.Pass;\n
+      var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode;\n
+      if (!mode) mode = modeHere;\n
+      else if (mode != modeHere) return CodeMirror.Pass;\n
 \n
-    var insert;\n
-    if (mode.blockCommentStart && mode.blockCommentContinue) {\n
-      var end = token.string.indexOf(mode.blockCommentEnd);\n
-      var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;\n
-      if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {\n
-        // Comment ended, don\'t continue it\n
-      } else if (token.string.indexOf(mode.blockCommentStart) == 0) {\n
-        insert = full.slice(0, token.start);\n
-        if (!/^\\s*$/.test(insert)) {\n
-          insert = "";\n
-          for (var i = 0; i < token.start; ++i) insert += " ";\n
+      var insert = null;\n
+      if (mode.blockCommentStart && mode.blockCommentContinue) {\n
+        var end = token.string.indexOf(mode.blockCommentEnd);\n
+        var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;\n
+        if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {\n
+          // Comment ended, don\'t continue it\n
+        } else if (token.string.indexOf(mode.blockCommentStart) == 0) {\n
+          insert = full.slice(0, token.start);\n
+          if (!/^\\s*$/.test(insert)) {\n
+            insert = "";\n
+            for (var j = 0; j < token.start; ++j) insert += " ";\n
+          }\n
+        } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&\n
+                   found + mode.blockCommentContinue.length > token.start &&\n
+                   /^\\s*$/.test(full.slice(0, found))) {\n
+          insert = full.slice(0, found);\n
         }\n
-      } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&\n
-                 found + mode.blockCommentContinue.length > token.start &&\n
-                 /^\\s*$/.test(full.slice(0, found))) {\n
-        insert = full.slice(0, found);\n
+        if (insert != null) insert += mode.blockCommentContinue;\n
       }\n
-      if (insert != null) insert += mode.blockCommentContinue;\n
-    }\n
-    if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {\n
-      var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);\n
-      if (found > -1) {\n
-        insert = line.slice(0, found);\n
-        if (/\\S/.test(insert)) insert = null;\n
-        else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\\s*/)[0];\n
+      if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {\n
+        var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);\n
+        if (found > -1) {\n
+          insert = line.slice(0, found);\n
+          if (/\\S/.test(insert)) insert = null;\n
+          else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\\s*/)[0];\n
+        }\n
       }\n
+      if (insert == null) return CodeMirror.Pass;\n
+      inserts[i] = "\\n" + insert;\n
     }\n
 \n
-    if (insert != null)\n
-      cm.replaceSelection("\\n" + insert, "end");\n
-    else\n
-      return CodeMirror.Pass;\n
+    cm.operation(function() {\n
+      for (var i = ranges.length - 1; i >= 0; i--)\n
+        cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");\n
+    });\n
   }\n
 \n
   function continueLineCommentEnabled(cm) {\n
@@ -88,7 +106,7 @@
       cm.addKeyMap(map);\n
     }\n
   });\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -99,7 +117,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2529</int> </value>
+            <value> <int>3399</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/dialog/dialog.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/dialog/dialog.js.xml
index 7d93478fe1e29849ea00a4aa091a81d5946f1eab..fe50d48aab484867101dc620f82eb904158f98aa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/dialog/dialog.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/dialog/dialog.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403073.64</string> </value>
+            <value> <string>ts21897119.98</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,18 +22,28 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Open simple dialogs on top of an editor. Relies on dialog.css.\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   function dialogDiv(cm, template, bottom) {\n
     var wrap = cm.getWrapperElement();\n
     var dialog;\n
     dialog = wrap.appendChild(document.createElement("div"));\n
-    if (bottom) {\n
+    if (bottom)\n
       dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";\n
-    } else {\n
+    else\n
       dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";\n
-    }\n
+\n
     if (typeof template == "string") {\n
       dialog.innerHTML = template;\n
     } else { // Assuming it\'s a detached DOM element.\n
@@ -49,40 +59,59 @@
   }\n
 \n
   CodeMirror.defineExtension("openDialog", function(template, callback, options) {\n
+    if (!options) options = {};\n
+\n
     closeNotification(this, null);\n
-    var dialog = dialogDiv(this, template, options && options.bottom);\n
+\n
+    var dialog = dialogDiv(this, template, options.bottom);\n
     var closed = false, me = this;\n
-    function close() {\n
-      if (closed) return;\n
-      closed = true;\n
-      dialog.parentNode.removeChild(dialog);\n
+    function close(newVal) {\n
+      if (typeof newVal == \'string\') {\n
+        inp.value = newVal;\n
+      } else {\n
+        if (closed) return;\n
+        closed = true;\n
+        dialog.parentNode.removeChild(dialog);\n
+        me.focus();\n
+\n
+        if (options.onClose) options.onClose(dialog);\n
+      }\n
     }\n
+\n
     var inp = dialog.getElementsByTagName("input")[0], button;\n
     if (inp) {\n
-      if (options && options.value) inp.value = options.value;\n
+      if (options.value) {\n
+        inp.value = options.value;\n
+        inp.select();\n
+      }\n
+\n
+      if (options.onInput)\n
+        CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});\n
+      if (options.onKeyUp)\n
+        CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});\n
+\n
       CodeMirror.on(inp, "keydown", function(e) {\n
         if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }\n
-        if (e.keyCode == 13 || e.keyCode == 27) {\n
+        if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {\n
           inp.blur();\n
           CodeMirror.e_stop(e);\n
           close();\n
-          me.focus();\n
-          if (e.keyCode == 13) callback(inp.value);\n
         }\n
+        if (e.keyCode == 13) callback(inp.value, e);\n
       });\n
-      if (options && options.onKeyUp) {\n
-        CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});\n
-      }\n
-      if (options && options.value) inp.value = options.value;\n
+\n
+      if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);\n
+\n
       inp.focus();\n
-      CodeMirror.on(inp, "blur", close);\n
     } else if (button = dialog.getElementsByTagName("button")[0]) {\n
       CodeMirror.on(button, "click", function() {\n
         close();\n
         me.focus();\n
       });\n
+\n
+      if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);\n
+\n
       button.focus();\n
-      CodeMirror.on(button, "blur", close);\n
     }\n
     return close;\n
   });\n
@@ -127,8 +156,8 @@
   CodeMirror.defineExtension("openNotification", function(template, options) {\n
     closeNotification(this, close);\n
     var dialog = dialogDiv(this, template, options && options.bottom);\n
-    var duration = options && (options.duration === undefined ? 5000 : options.duration);\n
     var closed = false, doneTimer;\n
+    var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;\n
 \n
     function close() {\n
       if (closed) return;\n
@@ -141,10 +170,13 @@
       CodeMirror.e_preventDefault(e);\n
       close();\n
     });\n
+\n
     if (duration)\n
-      doneTimer = setTimeout(close, options.duration);\n
+      doneTimer = setTimeout(close, duration);\n
+\n
+    return close;\n
   });\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -155,7 +187,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4087</int> </value>
+            <value> <int>4875</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/fullscreen.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/fullscreen.js.xml
index 49a39df400db5eb792988cf6f0d288ff533de7d6..7ee4e35f817ef9aa1295a73a3ae929742de377aa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/fullscreen.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/fullscreen.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403076.22</string> </value>
+            <value> <string>ts21897117.34</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,19 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>(function() {\n
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {\n
@@ -50,8 +62,10 @@
     window.scrollTo(info.scrollLeft, info.scrollTop);\n
     cm.refresh();\n
   }\n
-})();\n
-</string> </value>
+});\n
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -59,7 +73,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1069</int> </value>
+            <value> <int>1494</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/panel.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/panel.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a792252370e50951f675634e5e264eff6e56d314
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/panel.js.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897117.22</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>panel.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  CodeMirror.defineExtension("addPanel", function(node, options) {\n
+    if (!this.state.panels) initPanels(this);\n
+\n
+    var info = this.state.panels;\n
+    if (options && options.position == "bottom")\n
+      info.wrapper.appendChild(node);\n
+    else\n
+      info.wrapper.insertBefore(node, info.wrapper.firstChild);\n
+    var height = (options && options.height) || node.offsetHeight;\n
+    this._setSize(null, info.heightLeft -= height);\n
+    info.panels++;\n
+    return new Panel(this, node, options, height);\n
+  });\n
+\n
+  function Panel(cm, node, options, height) {\n
+    this.cm = cm;\n
+    this.node = node;\n
+    this.options = options;\n
+    this.height = height;\n
+    this.cleared = false;\n
+  }\n
+\n
+  Panel.prototype.clear = function() {\n
+    if (this.cleared) return;\n
+    this.cleared = true;\n
+    var info = this.cm.state.panels;\n
+    this.cm._setSize(null, info.heightLeft += this.height);\n
+    info.wrapper.removeChild(this.node);\n
+    if (--info.panels == 0) removePanels(this.cm);\n
+  };\n
+\n
+  Panel.prototype.changed = function(height) {\n
+    var newHeight = height == null ? this.node.offsetHeight : height;\n
+    var info = this.cm.state.panels;\n
+    this.cm._setSize(null, info.height += (newHeight - this.height));\n
+    this.height = newHeight;\n
+  };\n
+\n
+  function initPanels(cm) {\n
+    var wrap = cm.getWrapperElement();\n
+    var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;\n
+    var height = parseInt(style.height);\n
+    var info = cm.state.panels = {\n
+      setHeight: wrap.style.height,\n
+      heightLeft: height,\n
+      panels: 0,\n
+      wrapper: document.createElement("div")\n
+    };\n
+    wrap.parentNode.insertBefore(info.wrapper, wrap);\n
+    var hasFocus = cm.hasFocus();\n
+    info.wrapper.appendChild(wrap);\n
+    if (hasFocus) cm.focus();\n
+\n
+    cm._setSize = cm.setSize;\n
+    if (height != null) cm.setSize = function(width, newHeight) {\n
+      if (newHeight == null) return this._setSize(width, newHeight);\n
+      info.setHeight = newHeight;\n
+      if (typeof newHeight != "number") {\n
+        var px = /^(\\d+\\.?\\d*)px$/.exec(newHeight);\n
+        if (px) {\n
+          newHeight = Number(px[1]);\n
+        } else {\n
+          info.wrapper.style.height = newHeight;\n
+          newHeight = info.wrapper.offsetHeight;\n
+          info.wrapper.style.height = "";\n
+        }\n
+      }\n
+      cm._setSize(width, info.heightLeft += (newHeight - height));\n
+      height = newHeight;\n
+    };\n
+  }\n
+\n
+  function removePanels(cm) {\n
+    var info = cm.state.panels;\n
+    cm.state.panels = null;\n
+\n
+    var wrap = cm.getWrapperElement();\n
+    info.wrapper.parentNode.replaceChild(wrap, info.wrapper);\n
+    wrap.style.height = info.setHeight;\n
+    cm.setSize = cm._setSize;\n
+    cm.setSize();\n
+  }\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3102</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/placeholder.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/placeholder.js.xml
index f20d34e088db63f83d298c7df11d450323a1ad56..6fd04864f05c5e113e7a1dc6e20d8440a17a3334 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/placeholder.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/placeholder.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403076.53</string> </value>
+            <value> <string>ts21897116.97</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   CodeMirror.defineOption("placeholder", "", function(cm, val, old) {\n
     var prev = old && old != CodeMirror.Init;\n
     if (val && !prev) {\n
@@ -69,7 +79,7 @@
   function isEmpty(cm) {\n
     return (cm.lineCount() === 1) && (cm.getLine(0) === "");\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -80,7 +90,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1546</int> </value>
+            <value> <int>1971</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/rulers.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/rulers.js.xml
index ab411dfdefd543f7d2e6265157ce020607ce069e..319a4045c80c5586d622b482068b58025f72a9f1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/rulers.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/display/rulers.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403076.09</string> </value>
+            <value> <string>ts21897117.47</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   CodeMirror.defineOption("rulers", false, function(cm, val, old) {\n
@@ -48,18 +58,25 @@
     var val = cm.getOption("rulers");\n
     var cw = cm.defaultCharWidth();\n
     var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;\n
-    var bot = -cm.display.scroller.offsetHeight;\n
+    var minH = cm.display.scroller.offsetHeight + 30;\n
     for (var i = 0; i < val.length; i++) {\n
       var elt = document.createElement("div");\n
-      var col, cls = null;\n
-      if (typeof val[i] == "number") {\n
-        col = val[i];\n
+      elt.className = "CodeMirror-ruler";\n
+      var col, cls = null, conf = val[i];\n
+      if (typeof conf == "number") {\n
+        col = conf;\n
       } else {\n
-        col = val[i].column;\n
+        col = conf.column;\n
+        if (conf.className) elt.className += " " + conf.className;\n
+        if (conf.color) elt.style.borderColor = conf.color;\n
+        if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;\n
+        if (conf.width) elt.style.borderLeftWidth = conf.width;\n
         cls = val[i].className;\n
       }\n
-      elt.className = "CodeMirror-ruler" + (cls ? " " + cls : "");\n
-      elt.style.cssText = "left: " + (left + col * cw) + "px; top: -50px; bottom: " + bot + "px";\n
+      elt.style.left = (left + col * cw) + "px";\n
+      elt.style.top = "-50px";\n
+      elt.style.bottom = "-20px";\n
+      elt.style.minHeight = minH + "px";\n
       cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv);\n
     }\n
   }\n
@@ -68,7 +85,7 @@
     clearRulers(cm);\n
     setRulers(cm);\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -79,7 +96,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1400</int> </value>
+            <value> <int>2134</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closebrackets.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closebrackets.js.xml
index 4546d561b8653a42be3431e66748947663d6f0b5..eb8388082261cd50ebb030bc40fdd86950d84912 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closebrackets.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closebrackets.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93404951.33</string> </value>
+            <value> <string>ts21897295.56</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,22 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   var DEFAULT_BRACKETS = "()[]{}\'\'\\"\\"";\n
   var DEFAULT_EXPLODE_ON_ENTER = "[]{}";\n
   var SPACE_CHAR_REGEX = /\\s/;\n
+\n
+  var Pos = CodeMirror.Pos;\n
 \n
   CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {\n
     if (old != CodeMirror.Init && old)\n
@@ -43,69 +55,132 @@
   });\n
 \n
   function charsAround(cm, pos) {\n
-    var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1),\n
-                          CodeMirror.Pos(pos.line, pos.ch + 1));\n
+    var str = cm.getRange(Pos(pos.line, pos.ch - 1),\n
+                          Pos(pos.line, pos.ch + 1));\n
     return str.length == 2 ? str : null;\n
   }\n
+\n
+  // Project the token type that will exists after the given char is\n
+  // typed, and use it to determine whether it would cause the start\n
+  // of a string token.\n
+  function enteringString(cm, pos, ch) {\n
+    var line = cm.getLine(pos.line);\n
+    var token = cm.getTokenAt(pos);\n
+    if (/\\bstring2?\\b/.test(token.type)) return false;\n
+    var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);\n
+    stream.pos = stream.start = token.start;\n
+    for (;;) {\n
+      var type1 = cm.getMode().token(stream, token.state);\n
+      if (stream.pos >= pos.ch + 1) return /\\bstring2?\\b/.test(type1);\n
+      stream.start = stream.pos;\n
+    }\n
+  }\n
 \n
   function buildKeymap(pairs) {\n
     var map = {\n
       name : "autoCloseBrackets",\n
       Backspace: function(cm) {\n
-        if (cm.somethingSelected() || cm.getOption("disableInput")) return CodeMirror.Pass;\n
-        var cur = cm.getCursor(), around = charsAround(cm, cur);\n
-        if (around && pairs.indexOf(around) % 2 == 0)\n
-          cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));\n
-        else\n
-          return CodeMirror.Pass;\n
+        if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+        var ranges = cm.listSelections();\n
+        for (var i = 0; i < ranges.length; i++) {\n
+          if (!ranges[i].empty()) return CodeMirror.Pass;\n
+          var around = charsAround(cm, ranges[i].head);\n
+          if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;\n
+        }\n
+        for (var i = ranges.length - 1; i >= 0; i--) {\n
+          var cur = ranges[i].head;\n
+          cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));\n
+        }\n
       }\n
     };\n
     var closingBrackets = "";\n
     for (var i = 0; i < pairs.length; i += 2) (function(left, right) {\n
-      if (left != right) closingBrackets += right;\n
-      function surround(cm) {\n
-        var selection = cm.getSelection();\n
-        cm.replaceSelection(left + selection + right);\n
-      }\n
-      function maybeOverwrite(cm) {\n
-        var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));\n
-        if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass;\n
-        else cm.execCommand("goCharRight");\n
-      }\n
+      closingBrackets += right;\n
       map["\'" + left + "\'"] = function(cm) {\n
-        if (left == "\'" && cm.getTokenAt(cm.getCursor()).type == "comment" ||\n
-            cm.getOption("disableInput"))\n
-          return CodeMirror.Pass;\n
-        if (cm.somethingSelected()) return surround(cm);\n
-        if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;\n
-        var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);\n
-        var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch), curChar = cur.ch > 0 ? line.charAt(cur.ch - 1) : "";\n
-        if (left == right && CodeMirror.isWordChar(curChar))\n
-          return CodeMirror.Pass;\n
-        if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))\n
-          cm.replaceSelection(left + right, {head: ahead, anchor: ahead});\n
-        else\n
-          return CodeMirror.Pass;\n
+        if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+        var ranges = cm.listSelections(), type, next;\n
+        for (var i = 0; i < ranges.length; i++) {\n
+          var range = ranges[i], cur = range.head, curType;\n
+          var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));\n
+          if (!range.empty()) {\n
+            curType = "surround";\n
+          } else if (left == right && next == right) {\n
+            if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)\n
+              curType = "skipThree";\n
+            else\n
+              curType = "skip";\n
+          } else if (left == right && cur.ch > 1 &&\n
+                     cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&\n
+                     (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) {\n
+            curType = "addFour";\n
+          } else if (left == \'"\' || left == "\'") {\n
+            if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both";\n
+            else return CodeMirror.Pass;\n
+          } else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) {\n
+            curType = "both";\n
+          } else {\n
+            return CodeMirror.Pass;\n
+          }\n
+          if (!type) type = curType;\n
+          else if (type != curType) return CodeMirror.Pass;\n
+        }\n
+\n
+        cm.operation(function() {\n
+          if (type == "skip") {\n
+            cm.execCommand("goCharRight");\n
+          } else if (type == "skipThree") {\n
+            for (var i = 0; i < 3; i++)\n
+              cm.execCommand("goCharRight");\n
+          } else if (type == "surround") {\n
+            var sels = cm.getSelections();\n
+            for (var i = 0; i < sels.length; i++)\n
+              sels[i] = left + sels[i] + right;\n
+            cm.replaceSelections(sels, "around");\n
+          } else if (type == "both") {\n
+            cm.replaceSelection(left + right, null);\n
+            cm.execCommand("goCharLeft");\n
+          } else if (type == "addFour") {\n
+            cm.replaceSelection(left + left + left + left, "before");\n
+            cm.execCommand("goCharRight");\n
+          }\n
+        });\n
+      };\n
+      if (left != right) map["\'" + right + "\'"] = function(cm) {\n
+        var ranges = cm.listSelections();\n
+        for (var i = 0; i < ranges.length; i++) {\n
+          var range = ranges[i];\n
+          if (!range.empty() ||\n
+              cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)\n
+            return CodeMirror.Pass;\n
+        }\n
+        cm.execCommand("goCharRight");\n
       };\n
-      if (left != right) map["\'" + right + "\'"] = maybeOverwrite;\n
     })(pairs.charAt(i), pairs.charAt(i + 1));\n
     return map;\n
   }\n
 \n
   function buildExplodeHandler(pairs) {\n
     return function(cm) {\n
-      var cur = cm.getCursor(), around = charsAround(cm, cur);\n
-      if (!around || pairs.indexOf(around) % 2 != 0 || cm.getOption("disableInput"))\n
-        return CodeMirror.Pass;\n
+      if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+      var ranges = cm.listSelections();\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        if (!ranges[i].empty()) return CodeMirror.Pass;\n
+        var around = charsAround(cm, ranges[i].head);\n
+        if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;\n
+      }\n
       cm.operation(function() {\n
-        var newPos = CodeMirror.Pos(cur.line + 1, 0);\n
-        cm.replaceSelection("\\n\\n", {anchor: newPos, head: newPos}, "+input");\n
-        cm.indentLine(cur.line + 1, null, true);\n
-        cm.indentLine(cur.line + 2, null, true);\n
+        cm.replaceSelection("\\n\\n", null);\n
+        cm.execCommand("goCharLeft");\n
+        ranges = cm.listSelections();\n
+        for (var i = 0; i < ranges.length; i++) {\n
+          var line = ranges[i].head.line;\n
+          cm.indentLine(line, null, true);\n
+          cm.indentLine(line + 1, null, true);\n
+        }\n
       });\n
     };\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -116,7 +191,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3497</int> </value>
+            <value> <int>6302</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closetag.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closetag.js.xml
index aca80eefc940649d3a0cd82298ff75e96d4fd0f4..ae1faac90688404e96d0a88ab3f925d69dbeb025 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closetag.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/closetag.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93404951.5</string> </value>
+            <value> <string>ts21897295.63</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Tag-closer extension for CodeMirror.\n
  *\n
@@ -46,7 +49,14 @@
  * See demos/closetag.html for a usage example.\n
  */\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../fold/xml-fold"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../fold/xml-fold"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {\n
     if (old != CodeMirror.Init && old)\n
       cm.removeKeyMap("autoCloseTags");\n
@@ -65,48 +75,82 @@
                     "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];\n
 \n
   function autoCloseGT(cm) {\n
-    var pos = cm.getCursor(), tok = cm.getTokenAt(pos);\n
-    var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;\n
-    if (inner.mode.name != "xml" || !state.tagName || cm.getOption("disableInput")) return CodeMirror.Pass;\n
+    if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+    var ranges = cm.listSelections(), replacements = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      if (!ranges[i].empty()) return CodeMirror.Pass;\n
+      var pos = ranges[i].head, tok = cm.getTokenAt(pos);\n
+      var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;\n
+      if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;\n
+\n
+      var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";\n
+      var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);\n
+      var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);\n
 \n
-    var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";\n
-    var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);\n
-    var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);\n
+      var tagName = state.tagName;\n
+      if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);\n
+      var lowerTagName = tagName.toLowerCase();\n
+      // Don\'t process the \'>\' at the end of an end-tag or self-closing tag\n
+      if (!tagName ||\n
+          tok.type == "string" && (tok.end != pos.ch || !/[\\"\\\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||\n
+          tok.type == "tag" && state.type == "closeTag" ||\n
+          tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />\n
+          dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||\n
+          closingTagExists(cm, tagName, pos, state, true))\n
+        return CodeMirror.Pass;\n
 \n
-    var tagName = state.tagName;\n
-    if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);\n
-    var lowerTagName = tagName.toLowerCase();\n
-    // Don\'t process the \'>\' at the end of an end-tag or self-closing tag\n
-    if (!tagName ||\n
-        tok.type == "string" && (tok.end != pos.ch || !/[\\"\\\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||\n
-        tok.type == "tag" && state.type == "closeTag" ||\n
-        tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />\n
-        dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||\n
-        CodeMirror.scanForClosingTag && CodeMirror.scanForClosingTag(cm, pos, tagName,\n
-                                                                     Math.min(cm.lastLine() + 1, pos.line + 50)))\n
-      return CodeMirror.Pass;\n
+      var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;\n
+      replacements[i] = {indent: indent,\n
+                         text: ">" + (indent ? "\\n\\n" : "") + "</" + tagName + ">",\n
+                         newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};\n
+    }\n
 \n
-    var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1;\n
-    var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1);\n
-    cm.replaceSelection(">" + (doIndent ? "\\n\\n" : "") + "</" + tagName + ">",\n
-                        {head: curPos, anchor: curPos});\n
-    if (doIndent) {\n
-      cm.indentLine(pos.line + 1, null, true);\n
-      cm.indentLine(pos.line + 2, null);\n
+    for (var i = ranges.length - 1; i >= 0; i--) {\n
+      var info = replacements[i];\n
+      cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");\n
+      var sel = cm.listSelections().slice(0);\n
+      sel[i] = {head: info.newPos, anchor: info.newPos};\n
+      cm.setSelections(sel);\n
+      if (info.indent) {\n
+        cm.indentLine(info.newPos.line, null, true);\n
+        cm.indentLine(info.newPos.line + 1, null, true);\n
+      }\n
     }\n
   }\n
 \n
   function autoCloseSlash(cm) {\n
-    var pos = cm.getCursor(), tok = cm.getTokenAt(pos);\n
-    var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;\n
-    if (tok.type == "string" || tok.string.charAt(0) != "<" ||\n
-        tok.start != pos.ch - 1 || inner.mode.name != "xml" ||\n
-        cm.getOption("disableInput"))\n
-      return CodeMirror.Pass;\n
-\n
-    var tagName = state.context && state.context.tagName;\n
-    if (tagName) cm.replaceSelection("/" + tagName + ">", "end");\n
-    else return CodeMirror.Pass;\n
+    if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+    var ranges = cm.listSelections(), replacements = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      if (!ranges[i].empty()) return CodeMirror.Pass;\n
+      var pos = ranges[i].head, tok = cm.getTokenAt(pos);\n
+      var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;\n
+      if (tok.type == "string" || tok.string.charAt(0) != "<" ||\n
+          tok.start != pos.ch - 1)\n
+        return CodeMirror.Pass;\n
+      // Kludge to get around the fact that we are not in XML mode\n
+      // when completing in JS/CSS snippet in htmlmixed mode. Does not\n
+      // work for other XML embedded languages (there is no general\n
+      // way to go from a mixed mode to its current XML state).\n
+      if (inner.mode.name != "xml") {\n
+        if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")\n
+          replacements[i] = "/script>";\n
+        else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")\n
+          replacements[i] = "/style>";\n
+        else\n
+          return CodeMirror.Pass;\n
+      } else {\n
+        if (!state.context || !state.context.tagName ||\n
+            closingTagExists(cm, state.context.tagName, pos, state))\n
+          return CodeMirror.Pass;\n
+        replacements[i] = "/" + state.context.tagName + ">";\n
+      }\n
+    }\n
+    cm.replaceSelections(replacements);\n
+    ranges = cm.listSelections();\n
+    for (var i = 0; i < ranges.length; i++)\n
+      if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)\n
+        cm.indentLine(ranges[i].head.line);\n
   }\n
 \n
   function indexOf(collection, elt) {\n
@@ -115,7 +159,28 @@
       if (collection[i] == elt) return i;\n
     return -1;\n
   }\n
-})();\n
+\n
+  // If xml-fold is loaded, we use its functionality to try and verify\n
+  // whether a given tag is actually unclosed.\n
+  function closingTagExists(cm, tagName, pos, state, newTag) {\n
+    if (!CodeMirror.scanForClosingTag) return false;\n
+    var end = Math.min(cm.lastLine() + 1, pos.line + 500);\n
+    var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);\n
+    if (!nextClose || nextClose.tag != tagName) return false;\n
+    var cx = state.context;\n
+    // If the immediate wrapping context contains onCx instances of\n
+    // the same tag, a closing tag only exists if there are at least\n
+    // that many closing tags of that type following.\n
+    for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;\n
+    pos = nextClose.to;\n
+    for (var i = 1; i < onCx; i++) {\n
+      var next = CodeMirror.scanForClosingTag(cm, pos, null, end);\n
+      if (!next || next.tag != tagName) return false;\n
+      pos = next.to;\n
+    }\n
+    return true;\n
+  }\n
+});\n
 
 
 ]]></string> </value>
@@ -126,7 +191,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4385</int> </value>
+            <value> <int>7331</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/continuelist.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/continuelist.js.xml
index 73dfe0845b35fe88197d8b5d0da8b98f67790dc3..d9f99c81bd5ec76ce2624ca2c78049714f7f2f4e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/continuelist.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/continuelist.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93404951.61</string> </value>
+            <value> <string>ts21897295.78</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,33 +22,57 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
-  \'use strict\';\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
 \n
-  var listRE = /^(\\s*)([*+-]|(\\d+)\\.)(\\s*)/,\n
-      unorderedBullets = \'*+-\';\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  var listRE = /^(\\s*)(>[> ]*|[*+-]\\s|(\\d+)\\.)(\\s*)/,\n
+      emptyListRE = /^(\\s*)(>[> ]*|[*+-]|(\\d+)\\.)(\\s*)$/,\n
+      unorderedListRE = /[*+-]\\s/;\n
 \n
   CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {\n
     if (cm.getOption("disableInput")) return CodeMirror.Pass;\n
+    var ranges = cm.listSelections(), replacements = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var pos = ranges[i].head, match;\n
+      var eolState = cm.getStateAfter(pos.line);\n
+      var inList = eolState.list !== false;\n
+      var inQuote = eolState.quote !== false;\n
 \n
-    var pos = cm.getCursor(),\n
-        inList = cm.getStateAfter(pos.line).list !== false,\n
-        match;\n
+      if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) {\n
+        cm.execCommand("newlineAndIndent");\n
+        return;\n
+      }\n
+      if (cm.getLine(pos.line).match(emptyListRE)) {\n
+        cm.replaceRange("", {\n
+          line: pos.line, ch: 0\n
+        }, {\n
+          line: pos.line, ch: pos.ch + 1\n
+        });\n
+        replacements[i] = "\\n";\n
 \n
-    if (!inList || !(match = cm.getLine(pos.line).match(listRE))) {\n
-      cm.execCommand(\'newlineAndIndent\');\n
-      return;\n
-    }\n
+      } else {\n
+        var indent = match[1], after = match[4];\n
+        var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0\n
+          ? match[2]\n
+          : (parseInt(match[3], 10) + 1) + ".";\n
 \n
-    var indent = match[1], after = match[4];\n
-    var bullet = unorderedBullets.indexOf(match[2]) >= 0\n
-      ? match[2]\n
-      : (parseInt(match[3], 10) + 1) + \'.\';\n
+        replacements[i] = "\\n" + indent + bullet + after;\n
+      }\n
+    }\n
 \n
-    cm.replaceSelection(\'\\n\' + indent + bullet + after, \'end\');\n
+    cm.replaceSelections(replacements);\n
   };\n
-\n
-}());\n
+});\n
 
 
 ]]></string> </value>
@@ -59,7 +83,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>725</int> </value>
+            <value> <int>1752</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchbrackets.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchbrackets.js.xml
index 256a93e3fb9b2db5ffd59f53d18f600b8b6c16f4..bc5fc4e7d0374cfe4e46e85dfa7e839d1bafc9cc 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchbrackets.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchbrackets.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93404951.7</string> </value>
+            <value> <string>ts21897295.92</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,76 +22,106 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   var ie_lt8 = /MSIE \\d/.test(navigator.userAgent) &&\n
     (document.documentMode == null || document.documentMode < 8);\n
 \n
   var Pos = CodeMirror.Pos;\n
 \n
   var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};\n
-  function findMatchingBracket(cm, where, strict) {\n
-    var state = cm.state.matchBrackets;\n
-    var maxScanLen = (state && state.maxScanLineLength) || 10000;\n
-    var maxScanLines = (state && state.maxScanLines) || 100;\n
 \n
-    var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;\n
+  function findMatchingBracket(cm, where, strict, config) {\n
+    var line = cm.getLineHandle(where.line), pos = where.ch - 1;\n
     var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];\n
     if (!match) return null;\n
-    var forward = match.charAt(1) == ">", d = forward ? 1 : -1;\n
-    if (strict && forward != (pos == cur.ch)) return null;\n
-    var style = cm.getTokenTypeAt(Pos(cur.line, pos + 1));\n
+    var dir = match.charAt(1) == ">" ? 1 : -1;\n
+    if (strict && (dir > 0) != (pos == where.ch)) return null;\n
+    var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));\n
+\n
+    var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);\n
+    if (found == null) return null;\n
+    return {from: Pos(where.line, pos), to: found && found.pos,\n
+            match: found && found.ch == match.charAt(0), forward: dir > 0};\n
+  }\n
 \n
-    var stack = [line.text.charAt(pos)], re = /[(){}[\\]]/;\n
-    function scan(line, lineNo, start) {\n
-      if (!line.text) return;\n
-      var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;\n
-      if (line.text.length > maxScanLen) return null;\n
-      if (start != null) pos = start + d;\n
-      for (; pos != end; pos += d) {\n
-        var ch = line.text.charAt(pos);\n
-        if (re.test(ch) && cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style) {\n
+  // bracketRegex is used to specify which type of bracket to scan\n
+  // should be a regexp, e.g. /[[\\]]/\n
+  //\n
+  // Note: If "where" is on an open bracket, then this bracket is ignored.\n
+  //\n
+  // Returns false when no bracket was found, null when it reached\n
+  // maxScanLines and gave up\n
+  function scanForBracket(cm, where, dir, style, config) {\n
+    var maxScanLen = (config && config.maxScanLineLength) || 10000;\n
+    var maxScanLines = (config && config.maxScanLines) || 1000;\n
+\n
+    var stack = [];\n
+    var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\\]]/;\n
+    var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)\n
+                          : Math.max(cm.firstLine() - 1, where.line - maxScanLines);\n
+    for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {\n
+      var line = cm.getLine(lineNo);\n
+      if (!line) continue;\n
+      var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;\n
+      if (line.length > maxScanLen) continue;\n
+      if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);\n
+      for (; pos != end; pos += dir) {\n
+        var ch = line.charAt(pos);\n
+        if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {\n
           var match = matching[ch];\n
-          if (match.charAt(1) == ">" == forward) stack.push(ch);\n
-          else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};\n
-          else if (!stack.length) return {pos: pos, match: true};\n
+          if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);\n
+          else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};\n
+          else stack.pop();\n
         }\n
       }\n
     }\n
-    for (var i = cur.line, found, e = forward ? Math.min(i + maxScanLines, cm.lineCount()) : Math.max(-1, i - maxScanLines); i != e; i+=d) {\n
-      if (i == cur.line) found = scan(line, i, pos);\n
-      else found = scan(cm.getLineHandle(i), i);\n
-      if (found) break;\n
-    }\n
-    return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos),\n
-            match: found && found.match, forward: forward};\n
+    return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;\n
   }\n
 \n
-  function matchBrackets(cm, autoclear) {\n
+  function matchBrackets(cm, autoclear, config) {\n
     // Disable brace matching in long lines, since it\'ll cause hugely slow updates\n
     var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;\n
-    var found = findMatchingBracket(cm);\n
-    if (!found || cm.getLine(found.from.line).length > maxHighlightLen ||\n
-       found.to && cm.getLine(found.to.line).length > maxHighlightLen)\n
-      return;\n
+    var marks = [], ranges = cm.listSelections();\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);\n
+      if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {\n
+        var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";\n
+        marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));\n
+        if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)\n
+          marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));\n
+      }\n
+    }\n
+\n
+    if (marks.length) {\n
+      // Kludge to work around the IE bug from issue #1193, where text\n
+      // input stops going to the textare whever this fires.\n
+      if (ie_lt8 && cm.state.focused) cm.display.input.focus();\n
 \n
-    var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";\n
-    var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style});\n
-    var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style});\n
-    // Kludge to work around the IE bug from issue #1193, where text\n
-    // input stops going to the textarea whenever this fires.\n
-    if (ie_lt8 && cm.state.focused) cm.display.input.focus();\n
-    var clear = function() {\n
-      cm.operation(function() { one.clear(); two && two.clear(); });\n
-    };\n
-    if (autoclear) setTimeout(clear, 800);\n
-    else return clear;\n
+      var clear = function() {\n
+        cm.operation(function() {\n
+          for (var i = 0; i < marks.length; i++) marks[i].clear();\n
+        });\n
+      };\n
+      if (autoclear) setTimeout(clear, 800);\n
+      else return clear;\n
+    }\n
   }\n
 \n
   var currentlyHighlighted = null;\n
   function doMatchBrackets(cm) {\n
     cm.operation(function() {\n
       if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}\n
-      if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);\n
+      currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);\n
     });\n
   }\n
 \n
@@ -105,10 +135,13 @@
   });\n
 \n
   CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});\n
-  CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){\n
-    return findMatchingBracket(this, pos, strict);\n
+  CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){\n
+    return findMatchingBracket(this, pos, strict, config);\n
+  });\n
+  CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){\n
+    return scanForBracket(this, pos, dir, style, config);\n
   });\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -119,7 +152,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3918</int> </value>
+            <value> <int>5268</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchtags.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchtags.js.xml
index 108a05d0525d916755a793178efa2ca6a32e42de..8cc782cde6f55e79145e53e66172d2b0e7301587 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchtags.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/matchtags.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93404951.83</string> </value>
+            <value> <string>ts21897296.03</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../fold/xml-fold"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../fold/xml-fold"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   CodeMirror.defineOption("matchTags", false, function(cm, val, old) {\n
@@ -74,10 +84,10 @@
     var found = CodeMirror.findMatchingTag(cm, cm.getCursor());\n
     if (found) {\n
       var other = found.at == "close" ? found.open : found.close;\n
-      if (other) cm.setSelection(other.to, other.from);\n
+      if (other) cm.extendSelection(other.to, other.from);\n
     }\n
   };\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -88,7 +98,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1878</int> </value>
+            <value> <int>2355</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/trailingspace.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/trailingspace.js.xml
index 635180a1655dc13179a1a42589dbd048500270f0..17fde6645f51cc6a64657fd145953989e4e65a03 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/trailingspace.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/edit/trailingspace.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93404941.22</string> </value>
+            <value> <string>ts21897285.4</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,20 +22,32 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {\n
-  if (prev == CodeMirror.Init) prev = false;\n
-  if (prev && !val)\n
-    cm.removeOverlay("trailingspace");\n
-  else if (!prev && val)\n
-    cm.addOverlay({\n
-      token: function(stream) {\n
-        for (var l = stream.string.length, i = l; i && /\\s/.test(stream.string.charAt(i - 1)); --i) {}\n
-        if (i > stream.pos) { stream.pos = i; return null; }\n
-        stream.pos = l;\n
-        return "trailingspace";\n
-      },\n
-      name: "trailingspace"\n
-    });\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {\n
+    if (prev == CodeMirror.Init) prev = false;\n
+    if (prev && !val)\n
+      cm.removeOverlay("trailingspace");\n
+    else if (!prev && val)\n
+      cm.addOverlay({\n
+        token: function(stream) {\n
+          for (var l = stream.string.length, i = l; i && /\\s/.test(stream.string.charAt(i - 1)); --i) {}\n
+          if (i > stream.pos) { stream.pos = i; return null; }\n
+          stream.pos = l;\n
+          return "trailingspace";\n
+        },\n
+        name: "trailingspace"\n
+      });\n
+  });\n
 });\n
 
 
@@ -47,7 +59,7 @@ CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>528</int> </value>
+            <value> <int>1003</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/brace-fold.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/brace-fold.js.xml
index 5ac9ed9e47327957c8510f5b494cc9e3bbf48d3f..8656951a152acc1582e91bffc3411f0d3157c4db 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/brace-fold.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/brace-fold.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403076.67</string> </value>
+            <value> <string>ts21897116.87</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerHelper("fold", "brace", function(cm, start) {\n
   var line = start.line, lineText = cm.getLine(line);\n
   var startCh, tokenType;\n
@@ -69,7 +82,6 @@ CodeMirror.registerHelper("fold", "brace", function(cm, start) {\n
   return {from: CodeMirror.Pos(line, startCh),\n
           to: CodeMirror.Pos(end, endCh)};\n
 });\n
-CodeMirror.braceRangeFinder = CodeMirror.fold.brace; // deprecated\n
 \n
 CodeMirror.registerHelper("fold", "import", function(cm, start) {\n
   function hasImport(line) {\n
@@ -94,7 +106,6 @@ CodeMirror.registerHelper("fold", "import", function(cm, start) {\n
   }\n
   return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};\n
 });\n
-CodeMirror.importRangeFinder = CodeMirror.fold["import"]; // deprecated\n
 \n
 CodeMirror.registerHelper("fold", "include", function(cm, start) {\n
   function hasInclude(line) {\n
@@ -114,7 +125,8 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) {\n
   return {from: CodeMirror.Pos(start, has + 1),\n
           to: cm.clipPos(CodeMirror.Pos(end))};\n
 });\n
-CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -125,7 +137,7 @@ CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3653</int> </value>
+            <value> <int>3904</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/comment-fold.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/comment-fold.js.xml
index 5bf8bc2a5ab247172d43dc54e7e9cafec8516000..71dad0d87411ba13556d5d1144333fbce994e08a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/comment-fold.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/comment-fold.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.24</string> </value>
+            <value> <string>ts21897116.29</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {\n
   return mode.blockCommentStart && mode.blockCommentEnd;\n
 }, function(cm, start) {\n
@@ -64,6 +77,8 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {\n
   return {from: CodeMirror.Pos(line, startCh),\n
           to: CodeMirror.Pos(end, endCh)};\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -74,7 +89,7 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1538</int> </value>
+            <value> <int>1999</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldcode.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldcode.js.xml
index 9413b639155885dafe4af9e9b3e5f46061522701..0c4bb044da97db07c87544b9708511cf5b6a0bc5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldcode.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldcode.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.02</string> </value>
+            <value> <string>ts21897116.45</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,14 +22,28 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   function doFold(cm, pos, options, force) {\n
-    var finder = options && (options.call ? options : options.rangeFinder);\n
-    if (!finder) finder = CodeMirror.fold.auto;\n
+    if (options && options.call) {\n
+      var finder = options;\n
+      options = null;\n
+    } else {\n
+      var finder = getOption(cm, options, "rangeFinder");\n
+    }\n
     if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);\n
-    var minSize = options && options.minFoldSize || 0;\n
+    var minSize = getOption(cm, options, "minFoldSize");\n
 \n
     function getRange(allowFolded) {\n
       var range = finder(cm, pos);\n
@@ -46,14 +60,17 @@
     }\n
 \n
     var range = getRange(true);\n
-    if (options && options.scanUp) while (!range && pos.line > cm.firstLine()) {\n
+    if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {\n
       pos = CodeMirror.Pos(pos.line - 1, 0);\n
       range = getRange(false);\n
     }\n
     if (!range || range.cleared || force === "unfold") return;\n
 \n
-    var myWidget = makeWidget(options);\n
-    CodeMirror.on(myWidget, "mousedown", function() { myRange.clear(); });\n
+    var myWidget = makeWidget(cm, options);\n
+    CodeMirror.on(myWidget, "mousedown", function(e) {\n
+      myRange.clear();\n
+      CodeMirror.e_preventDefault(e);\n
+    });\n
     var myRange = cm.markText(range.from, range.to, {\n
       replacedWith: myWidget,\n
       clearOnEnter: true,\n
@@ -65,8 +82,8 @@
     CodeMirror.signal(cm, "fold", cm, range.from, range.to);\n
   }\n
 \n
-  function makeWidget(options) {\n
-    var widget = (options && options.widget) || "\\u2194";\n
+  function makeWidget(cm, options) {\n
+    var widget = getOption(cm, options, "widget");\n
     if (typeof widget == "string") {\n
       var text = document.createTextNode(widget);\n
       widget = document.createElement("span");\n
@@ -92,9 +109,27 @@
       if (marks[i].__isFold) return true;\n
   });\n
 \n
-  CodeMirror.commands.fold = function(cm) {\n
+  CodeMirror.commands.toggleFold = function(cm) {\n
     cm.foldCode(cm.getCursor());\n
   };\n
+  CodeMirror.commands.fold = function(cm) {\n
+    cm.foldCode(cm.getCursor(), null, "fold");\n
+  };\n
+  CodeMirror.commands.unfold = function(cm) {\n
+    cm.foldCode(cm.getCursor(), null, "unfold");\n
+  };\n
+  CodeMirror.commands.foldAll = function(cm) {\n
+    cm.operation(function() {\n
+      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)\n
+        cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");\n
+    });\n
+  };\n
+  CodeMirror.commands.unfoldAll = function(cm) {\n
+    cm.operation(function() {\n
+      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)\n
+        cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");\n
+    });\n
+  };\n
 \n
   CodeMirror.registerHelper("fold", "combine", function() {\n
     var funcs = Array.prototype.slice.call(arguments, 0);\n
@@ -113,7 +148,25 @@
       if (cur) return cur;\n
     }\n
   });\n
-})();\n
+\n
+  var defaultOptions = {\n
+    rangeFinder: CodeMirror.fold.auto,\n
+    widget: "\\u2194",\n
+    minFoldSize: 0,\n
+    scanUp: false\n
+  };\n
+\n
+  CodeMirror.defineOption("foldOptions", null);\n
+\n
+  function getOption(cm, options, name) {\n
+    if (options && options[name] !== undefined)\n
+      return options[name];\n
+    var editorOptions = cm.options.foldOptions;\n
+    if (editorOptions && editorOptions[name] !== undefined)\n
+      return editorOptions[name];\n
+    return defaultOptions[name];\n
+  }\n
+});\n
 
 
 ]]></string> </value>
@@ -124,7 +177,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2941</int> </value>
+            <value> <int>4574</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.css.xml
index 89a4be3eba4c85c908370aba235e3462eae6321a..e9191b2af12e4a2eb7a6afe4488946e7af3f7b89 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.css.xml
@@ -36,7 +36,6 @@
 }\n
 .CodeMirror-foldgutter-open,\n
 .CodeMirror-foldgutter-folded {\n
-  color: #555;\n
   cursor: pointer;\n
 }\n
 .CodeMirror-foldgutter-open:after {\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.js.xml
index 40f55bd7f8b6d0856492c48e56e97f8c6ff450d0..435f337e3d1e065b0c804f5b39937fae835e275c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/foldgutter.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.13</string> </value>
+            <value> <string>ts21897116.36</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("./foldcode"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "./foldcode"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {\n
@@ -72,7 +82,7 @@
   function marker(spec) {\n
     if (typeof spec == "string") {\n
       var elt = document.createElement("div");\n
-      elt.className = spec;\n
+      elt.className = spec + " CodeMirror-guttermarker-subtle";\n
       return elt;\n
     } else {\n
       return spec.cloneNode(true);\n
@@ -145,7 +155,7 @@
     if (line >= state.from && line < state.to)\n
       updateFoldInfo(cm, line, line + 1);\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -156,7 +166,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3874</int> </value>
+            <value> <int>4372</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/indent-fold.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/indent-fold.js.xml
index fd1c6154f43beb3294391efc5ead97c05af6a577..3efdd73998115fb90a3bd984821d03786853fcf1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/indent-fold.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/indent-fold.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.31</string> </value>
+            <value> <string>ts21897116.2</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerHelper("fold", "indent", function(cm, start) {\n
   var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);\n
   if (!/\\S/.test(firstLine)) return;\n
@@ -51,7 +64,8 @@ CodeMirror.registerHelper("fold", "indent", function(cm, start) {\n
     to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)\n
   };\n
 });\n
-CodeMirror.indentRangeFinder = CodeMirror.fold.indent; // deprecated\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -62,7 +76,7 @@ CodeMirror.indentRangeFinder = CodeMirror.fold.indent; // deprecated\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1235</int> </value>
+            <value> <int>1627</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/markdown-fold.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/markdown-fold.js.xml
index a1795567c5a6e0abdd672ef60b8b9b843e794fef..1063da59f39538378059409b6c5f39fc4e34292a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/markdown-fold.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/markdown-fold.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403076.79</string> </value>
+            <value> <string>ts21897116.73</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerHelper("fold", "markdown", function(cm, start) {\n
   var maxDepth = 100;\n
 \n
@@ -56,6 +69,8 @@ CodeMirror.registerHelper("fold", "markdown", function(cm, start) {\n
     to: CodeMirror.Pos(end, cm.getLine(end).length)\n
   };\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -66,7 +81,7 @@ CodeMirror.registerHelper("fold", "markdown", function(cm, start) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1144</int> </value>
+            <value> <int>1605</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/xml-fold.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/xml-fold.js.xml
index a04301d1c0a34abc00ac63dca911b9851532acf9..7c540197aaf0889df44b56d02c96a1a955739105 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/xml-fold.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/fold/xml-fold.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403076.92</string> </value>
+            <value> <string>ts21897116.59</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var Pos = CodeMirror.Pos;\n
@@ -160,15 +170,14 @@
       }\n
     }\n
   });\n
-  CodeMirror.tagRangeFinder = CodeMirror.fold.xml; // deprecated\n
-\n
   CodeMirror.findMatchingTag = function(cm, pos, range) {\n
     var iter = new Iter(cm, pos.line, pos.ch, range);\n
     if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;\n
     var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);\n
     var start = end && toTagStart(iter);\n
-    if (!end || end == "selfClose" || !start || cmp(iter, pos) > 0) return;\n
+    if (!end || !start || cmp(iter, pos) > 0) return;\n
     var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};\n
+    if (end == "selfClose") return {open: here, close: null, at: "open"};\n
 \n
     if (start[1]) { // closing tag\n
       return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};\n
@@ -192,9 +201,9 @@
   // Used by addon/edit/closetag.js\n
   CodeMirror.scanForClosingTag = function(cm, pos, name, end) {\n
     var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);\n
-    return !!findMatchingClose(iter, name);\n
+    return findMatchingClose(iter, name);\n
   };\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -205,7 +214,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6161</int> </value>
+            <value> <int>6570</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/anyword-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/anyword-hint.js.xml
index 7bd966d132e299538a7bbe252039636eabc3c5cf..8f38bd0a895756299180cd4d2b44941cb653843c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/anyword-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/anyword-hint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.24</string> </value>
+            <value> <string>ts21897118.73</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var WORD = /[\\w$]+/, RANGE = 500;\n
@@ -31,8 +41,7 @@
     var word = options && options.word || WORD;\n
     var range = options && options.range || RANGE;\n
     var cur = editor.getCursor(), curLine = editor.getLine(cur.line);\n
-    var start = cur.ch, end = start;\n
-    while (end < curLine.length && word.test(curLine.charAt(end))) ++end;\n
+    var end = cur.ch, start = end;\n
     while (start && word.test(curLine.charAt(start - 1))) --start;\n
     var curWord = start != end && curLine.slice(start, end);\n
 \n
@@ -53,7 +62,7 @@
     }\n
     return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};\n
   });\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -64,7 +73,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1304</int> </value>
+            <value> <int>1653</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/css-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/css-hint.js.xml
index c3583eeb66300a516dc11dd15be0db2009f88e84..c349390d6a8a19c14ab0c2c5403a96a877833169 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/css-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/css-hint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.76</string> </value>
+            <value> <string>ts21897119.18</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,19 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>(function () {\n
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../../mode/css/css"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../../mode/css/css"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,\n
@@ -32,7 +44,7 @@
     var inner = CodeMirror.innerMode(cm.getMode(), token.state);\n
     if (inner.mode.name != "css") return;\n
 \n
-    var word = token.string, start = token.start, end = token.end;\n
+    var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);\n
     if (/[^\\w$_-]/.test(word)) {\n
       word = ""; start = end = cur.ch;\n
     }\n
@@ -46,7 +58,7 @@
           result.push(name);\n
     }\n
 \n
-    var st = token.state.state;\n
+    var st = inner.state.state;\n
     if (st == "pseudo" || token.type == "variable-3") {\n
       add(pseudoClasses);\n
     } else if (st == "block" || st == "maybeprop") {\n
@@ -65,8 +77,10 @@
       to: CodeMirror.Pos(cur.line, end)\n
     };\n
   });\n
-})();\n
-</string> </value>
+});\n
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -74,7 +88,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1455</int> </value>
+            <value> <int>1951</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/html-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/html-hint.js.xml
index e71500eab133f10f93dd3481eab6dc1dde497a59..54ba6001a9000f4786a1a41b6bf077066fd36b7c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/html-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/html-hint.js.xml
@@ -8,20 +8,12 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.35</string> </value>
+            <value> <string>ts21897119.52</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
             <value> <string>html-hint.js</string> </value>
         </item>
-        <item>
-            <key> <string>__propsets__</string> </key>
-            <value>
-              <tuple>
-                <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
-              </tuple>
-            </value>
-        </item>
         <item>
             <key> <string>content_type</string> </key>
             <value> <string>application/javascript</string> </value>
@@ -30,7 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function () {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("./xml-hint"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "./xml-hint"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
   var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");\n
   var targets = ["_blank", "_self", "_top", "_parent"];\n
   var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];\n
@@ -364,9 +368,8 @@
     if (options) for (var opt in options) local[opt] = options[opt];\n
     return CodeMirror.hint.xml(cm, local);\n
   }\n
-  CodeMirror.htmlHint = htmlHint; // deprecated\n
   CodeMirror.registerHelper("hint", "html", htmlHint);\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -377,7 +380,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>10911</int> </value>
+            <value> <int>11341</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
@@ -386,62 +389,4 @@
       </dictionary>
     </pickle>
   </record>
-  <record id="2" aka="AAAAAAAAAAI=">
-    <pickle>
-      <global name="PropertySheet" module="OFS.PropertySheets"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_md</string> </key>
-            <value>
-              <dictionary>
-                <item>
-                    <key> <string>xmlns</string> </key>
-                    <value> <unicode>http://apache.org/dav/props/</unicode> </value>
-                </item>
-              </dictionary>
-            </value>
-        </item>
-        <item>
-            <key> <string>_properties</string> </key>
-            <value>
-              <tuple>
-                <dictionary>
-                  <item>
-                      <key> <string>id</string> </key>
-                      <value> <unicode>executable</unicode> </value>
-                  </item>
-                  <item>
-                      <key> <string>meta</string> </key>
-                      <value>
-                        <dictionary>
-                          <item>
-                              <key> <string>__xml_attrs__</string> </key>
-                              <value>
-                                <dictionary/>
-                              </value>
-                          </item>
-                        </dictionary>
-                      </value>
-                  </item>
-                  <item>
-                      <key> <string>type</string> </key>
-                      <value> <string>string</string> </value>
-                  </item>
-                </dictionary>
-              </tuple>
-            </value>
-        </item>
-        <item>
-            <key> <string>executable</string> </key>
-            <value> <string>T</string> </value>
-        </item>
-        <item>
-            <key> <string>id</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
 </ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/javascript-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/javascript-hint.js.xml
index 09d8ca2451e540b01a8fb3dbf22e62ccafa395fb..6ed2e3a5edc09e9e60bc502cdc8dac0c976c7fe5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/javascript-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/javascript-hint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.83</string> </value>
+            <value> <string>ts21897119.08</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function () {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   var Pos = CodeMirror.Pos;\n
 \n
   function forEach(arr, f) {\n
@@ -44,15 +54,20 @@
 \n
   function scriptHint(editor, keywords, getToken, options) {\n
     // Find the token at the cursor\n
-    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;\n
+    var cur = editor.getCursor(), token = getToken(editor, cur);\n
     if (/\\b(?:string|comment)\\b/.test(token.type)) return;\n
     token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;\n
 \n
     // If it\'s not a \'word-style\' token, ignore the token.\n
     if (!/^[\\w$_]*$/.test(token.string)) {\n
-      token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,\n
-                       type: token.string == "." ? "property" : null};\n
+      token = {start: cur.ch, end: cur.ch, string: "", state: token.state,\n
+               type: token.string == "." ? "property" : null};\n
+    } else if (token.end > cur.ch) {\n
+      token.end = cur.ch;\n
+      token.string = token.string.slice(0, cur.ch - token.start);\n
     }\n
+\n
+    var tprop = token;\n
     // If it is a property, find out what it is a property of.\n
     while (tprop.type == "property") {\n
       tprop = getToken(editor, Pos(cur.line, tprop.start));\n
@@ -71,7 +86,6 @@
                       function (e, cur) {return e.getTokenAt(cur);},\n
                       options);\n
   };\n
-  CodeMirror.javascriptHint = javascriptHint; // deprecated\n
   CodeMirror.registerHelper("hint", "javascript", javascriptHint);\n
 \n
   function getCoffeeScriptToken(editor, cur) {\n
@@ -95,7 +109,6 @@
   function coffeescriptHint(editor, options) {\n
     return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);\n
   }\n
-  CodeMirror.coffeescriptHint = coffeescriptHint; // deprecated\n
   CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);\n
 \n
   var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +\n
@@ -109,7 +122,7 @@
                   "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");\n
 \n
   function getCompletions(token, context, keywords, options) {\n
-    var found = [], start = token.string;\n
+    var found = [], start = token.string, global = options && options.globalScope || window;\n
     function maybeAdd(str) {\n
       if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);\n
     }\n
@@ -127,32 +140,34 @@
       if (obj.type && obj.type.indexOf("variable") === 0) {\n
         if (options && options.additionalContext)\n
           base = options.additionalContext[obj.string];\n
-        base = base || window[obj.string];\n
+        if (!options || options.useGlobalScope !== false)\n
+          base = base || global[obj.string];\n
       } else if (obj.type == "string") {\n
         base = "";\n
       } else if (obj.type == "atom") {\n
         base = 1;\n
       } else if (obj.type == "function") {\n
-        if (window.jQuery != null && (obj.string == \'$\' || obj.string == \'jQuery\') &&\n
-            (typeof window.jQuery == \'function\'))\n
-          base = window.jQuery();\n
-        else if (window._ != null && (obj.string == \'_\') && (typeof window._ == \'function\'))\n
-          base = window._();\n
+        if (global.jQuery != null && (obj.string == \'$\' || obj.string == \'jQuery\') &&\n
+            (typeof global.jQuery == \'function\'))\n
+          base = global.jQuery();\n
+        else if (global._ != null && (obj.string == \'_\') && (typeof global._ == \'function\'))\n
+          base = global._();\n
       }\n
       while (base != null && context.length)\n
         base = base[context.pop().string];\n
       if (base != null) gatherCompletions(base);\n
     } else {\n
-      // If not, just look in the window object and any local scope\n
+      // If not, just look in the global object and any local scope\n
       // (reading into JS mode internals to get at the local and global variables)\n
       for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);\n
       for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);\n
-      gatherCompletions(window);\n
+      if (!options || options.useGlobalScope !== false)\n
+        gatherCompletions(global);\n
       forEach(keywords, maybeAdd);\n
     }\n
     return found;\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -163,7 +178,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5572</int> </value>
+            <value> <int>6163</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/pig-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/pig-hint.js.xml
deleted file mode 100644
index afc2967a2218bb18005ec7a9f002365a4f67d510..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/pig-hint.js.xml
+++ /dev/null
@@ -1,165 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.21</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>pig-hint.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-(function () {\n
-  "use strict";\n
-\n
-  function forEach(arr, f) {\n
-    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);\n
-  }\n
-\n
-  function arrayContains(arr, item) {\n
-    if (!Array.prototype.indexOf) {\n
-      var i = arr.length;\n
-      while (i--) {\n
-        if (arr[i] === item) {\n
-          return true;\n
-        }\n
-      }\n
-      return false;\n
-    }\n
-    return arr.indexOf(item) != -1;\n
-  }\n
-\n
-  function scriptHint(editor, _keywords, getToken) {\n
-    // Find the token at the cursor\n
-    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;\n
-    // If it\'s not a \'word-style\' token, ignore the token.\n
-\n
-    if (!/^[\\w$_]*$/.test(token.string)) {\n
-        token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,\n
-                         className: token.string == ":" ? "pig-type" : null};\n
-    }\n
-\n
-    if (!context) var context = [];\n
-    context.push(tprop);\n
-\n
-    var completionList = getCompletions(token, context);\n
-    completionList = completionList.sort();\n
-    //prevent autocomplete for last word, instead show dropdown with one word\n
-    if(completionList.length == 1) {\n
-      completionList.push(" ");\n
-    }\n
-\n
-    return {list: completionList,\n
-            from: CodeMirror.Pos(cur.line, token.start),\n
-            to: CodeMirror.Pos(cur.line, token.end)};\n
-  }\n
-\n
-  function pigHint(editor) {\n
-    return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});\n
-  }\n
-  CodeMirror.pigHint = pigHint; // deprecated\n
-  CodeMirror.registerHelper("hint", "pig", pigHint);\n
-\n
-  var pigKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "\n
-  + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "\n
-  + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "\n
-  + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "\n
-  + "NEQ MATCHES TRUE FALSE";\n
-  var pigKeywordsU = pigKeywords.split(" ");\n
-  var pigKeywordsL = pigKeywords.toLowerCase().split(" ");\n
-\n
-  var pigTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP";\n
-  var pigTypesU = pigTypes.split(" ");\n
-  var pigTypesL = pigTypes.toLowerCase().split(" ");\n
-\n
-  var pigBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "\n
-  + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "\n
-  + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "\n
-  + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "\n
-  + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "\n
-  + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "\n
-  + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA  "\n
-  + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "\n
-  + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "\n
-  + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER";\n
-  var pigBuiltinsU = pigBuiltins.split(" ").join("() ").split(" ");\n
-  var pigBuiltinsL = pigBuiltins.toLowerCase().split(" ").join("() ").split(" ");\n
-  var pigBuiltinsC = ("BagSize BinStorage Bloom BuildBloom ConstantSize CubeDimensions DoubleAbs "\n
-  + "DoubleAvg DoubleBase DoubleMax DoubleMin DoubleRound DoubleSum FloatAbs FloatAvg FloatMax "\n
-  + "FloatMin FloatRound FloatSum GenericInvoker IntAbs IntAvg IntMax IntMin IntSum "\n
-  + "InvokeForDouble InvokeForFloat InvokeForInt InvokeForLong InvokeForString Invoker "\n
-  + "IsEmpty JsonLoader JsonMetadata JsonStorage LongAbs LongAvg LongMax LongMin LongSum MapSize "\n
-  + "MonitoredUDF Nondeterministic OutputSchema PigStorage PigStreaming StringConcat StringMax "\n
-  + "StringMin StringSize TextLoader TupleSize Utf8StorageConverter").split(" ").join("() ").split(" ");\n
-\n
-  function getCompletions(token, context) {\n
-    var found = [], start = token.string;\n
-    function maybeAdd(str) {\n
-      if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);\n
-    }\n
-\n
-    function gatherCompletions(obj) {\n
-      if(obj == ":") {\n
-        forEach(pigTypesL, maybeAdd);\n
-      }\n
-      else {\n
-        forEach(pigBuiltinsU, maybeAdd);\n
-        forEach(pigBuiltinsL, maybeAdd);\n
-        forEach(pigBuiltinsC, maybeAdd);\n
-        forEach(pigTypesU, maybeAdd);\n
-        forEach(pigTypesL, maybeAdd);\n
-        forEach(pigKeywordsU, maybeAdd);\n
-        forEach(pigKeywordsL, maybeAdd);\n
-      }\n
-    }\n
-\n
-    if (context) {\n
-      // If this is a property, see if it belongs to some object we can\n
-      // find in the current environment.\n
-      var obj = context.pop(), base;\n
-\n
-      if (obj.type == "variable")\n
-          base = obj.string;\n
-      else if(obj.type == "variable-3")\n
-          base = ":" + obj.string;\n
-\n
-      while (base != null && context.length)\n
-        base = base[context.pop().string];\n
-      if (base != null) gatherCompletions(base);\n
-    }\n
-    return found;\n
-  }\n
-})();\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>5117</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/python-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/python-hint.js.xml
deleted file mode 100644
index f21215f4da07fe56ff008542bb2722301571a2d6..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/python-hint.js.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.08</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>python-hint.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-(function () {\n
-  function forEach(arr, f) {\n
-    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);\n
-  }\n
-\n
-  function arrayContains(arr, item) {\n
-    if (!Array.prototype.indexOf) {\n
-      var i = arr.length;\n
-      while (i--) {\n
-        if (arr[i] === item) {\n
-          return true;\n
-        }\n
-      }\n
-      return false;\n
-    }\n
-    return arr.indexOf(item) != -1;\n
-  }\n
-\n
-  function scriptHint(editor, _keywords, getToken) {\n
-    // Find the token at the cursor\n
-    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;\n
-    // If it\'s not a \'word-style\' token, ignore the token.\n
-\n
-    if (!/^[\\w$_]*$/.test(token.string)) {\n
-        token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,\n
-                         className: token.string == ":" ? "python-type" : null};\n
-    }\n
-\n
-    if (!context) var context = [];\n
-    context.push(tprop);\n
-\n
-    var completionList = getCompletions(token, context);\n
-    completionList = completionList.sort();\n
-\n
-    return {list: completionList,\n
-            from: CodeMirror.Pos(cur.line, token.start),\n
-            to: CodeMirror.Pos(cur.line, token.end)};\n
-  }\n
-\n
-  function pythonHint(editor) {\n
-    return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);});\n
-  }\n
-  CodeMirror.pythonHint = pythonHint; // deprecated\n
-  CodeMirror.registerHelper("hint", "python", pythonHint);\n
-\n
-  var pythonKeywords = "and del from not while as elif global or with assert else if pass yield"\n
-+ "break except import print class exec in raise continue finally is return def for lambda try";\n
-  var pythonKeywordsL = pythonKeywords.split(" ");\n
-  var pythonKeywordsU = pythonKeywords.toUpperCase().split(" ");\n
-\n
-  var pythonBuiltins = "abs divmod input open staticmethod all enumerate int ord str "\n
-+ "any eval isinstance pow sum basestring execfile issubclass print super"\n
-+ "bin file iter property tuple bool filter len range type"\n
-+ "bytearray float list raw_input unichr callable format locals reduce unicode"\n
-+ "chr frozenset long reload vars classmethod getattr map repr xrange"\n
-+ "cmp globals max reversed zip compile hasattr memoryview round __import__"\n
-+ "complex hash min set apply delattr help next setattr buffer"\n
-+ "dict hex object slice coerce dir id oct sorted intern ";\n
-  var pythonBuiltinsL = pythonBuiltins.split(" ").join("() ").split(" ");\n
-  var pythonBuiltinsU = pythonBuiltins.toUpperCase().split(" ").join("() ").split(" ");\n
-\n
-  function getCompletions(token, context) {\n
-    var found = [], start = token.string;\n
-    function maybeAdd(str) {\n
-      if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);\n
-    }\n
-\n
-    function gatherCompletions(_obj) {\n
-        forEach(pythonBuiltinsL, maybeAdd);\n
-        forEach(pythonBuiltinsU, maybeAdd);\n
-        forEach(pythonKeywordsL, maybeAdd);\n
-        forEach(pythonKeywordsU, maybeAdd);\n
-    }\n
-\n
-    if (context) {\n
-      // If this is a property, see if it belongs to some object we can\n
-      // find in the current environment.\n
-      var obj = context.pop(), base;\n
-\n
-      if (obj.type == "variable")\n
-          base = obj.string;\n
-      else if(obj.type == "variable-3")\n
-          base = ":" + obj.string;\n
-\n
-      while (base != null && context.length)\n
-        base = base[context.pop().string];\n
-      if (base != null) gatherCompletions(base);\n
-    }\n
-    return found;\n
-  }\n
-})();\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>3331</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.css.xml
index 03b2b0772fd62c3f144b5a6e5a984889d56ca5bd..0eb70ec4053b43e5d2b478ed2f64d500c74d5155 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.css.xml
@@ -58,7 +58,7 @@
   cursor: pointer;\n
 }\n
 \n
-.CodeMirror-hint-active {\n
+li.CodeMirror-hint-active {\n
   background: #08f;\n
   color: white;\n
 }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.js.xml
index f620e56cab1e7879a408c9c3c51f0639ea354456..9d94f85d3a98e268fef6bbb4b24533dda61fca7c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/show-hint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.18</string> </value>
+            <value> <string>ts21897118.88</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,34 +22,51 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var HINT_ELEMENT_CLASS        = "CodeMirror-hint";\n
   var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";\n
 \n
+  // This is the old interface, kept around for now to stay\n
+  // backwards-compatible.\n
   CodeMirror.showHint = function(cm, getHints, options) {\n
+    if (!getHints) return cm.showHint(options);\n
+    if (options && options.async) getHints.async = true;\n
+    var newOpts = {hint: getHints};\n
+    if (options) for (var prop in options) newOpts[prop] = options[prop];\n
+    return cm.showHint(newOpts);\n
+  };\n
+\n
+  CodeMirror.defineExtension("showHint", function(options) {\n
     // We want a single cursor position.\n
-    if (cm.somethingSelected()) return;\n
-    if (getHints == null) {\n
-      if (options && options.async) return;\n
-      else getHints = CodeMirror.hint.auto;\n
-    }\n
+    if (this.listSelections().length > 1 || this.somethingSelected()) return;\n
 \n
-    if (cm.state.completionActive) cm.state.completionActive.close();\n
+    if (this.state.completionActive) this.state.completionActive.close();\n
+    var completion = this.state.completionActive = new Completion(this, options);\n
+    var getHints = completion.options.hint;\n
+    if (!getHints) return;\n
 \n
-    var completion = cm.state.completionActive = new Completion(cm, getHints, options || {});\n
-    CodeMirror.signal(cm, "startCompletion", cm);\n
-    if (completion.options.async)\n
-      getHints(cm, function(hints) { completion.showHints(hints); }, completion.options);\n
+    CodeMirror.signal(this, "startCompletion", this);\n
+    if (getHints.async)\n
+      getHints(this, function(hints) { completion.showHints(hints); }, completion.options);\n
     else\n
-      return completion.showHints(getHints(cm, completion.options));\n
-  };\n
+      return completion.showHints(getHints(this, completion.options));\n
+  });\n
 \n
-  function Completion(cm, getHints, options) {\n
+  function Completion(cm, options) {\n
     this.cm = cm;\n
-    this.getHints = getHints;\n
-    this.options = options;\n
+    this.options = this.buildOptions(options);\n
     this.widget = this.onClose = null;\n
   }\n
 \n
@@ -70,7 +87,8 @@
     pick: function(data, i) {\n
       var completion = data.list[i];\n
       if (completion.hint) completion.hint(this.cm, data, completion);\n
-      else this.cm.replaceRange(getText(completion), completion.from||data.from, completion.to||data.to);\n
+      else this.cm.replaceRange(getText(completion), completion.from || data.from,\n
+                                completion.to || data.to, "complete");\n
       CodeMirror.signal(data, "pick", completion);\n
       this.close();\n
     },\n
@@ -78,7 +96,7 @@
     showHints: function(data) {\n
       if (!data || !data.list.length || !this.active()) return this.close();\n
 \n
-      if (this.options.completeSingle != false && data.list.length == 1)\n
+      if (this.options.completeSingle && data.list.length == 1)\n
         this.pick(data, 0);\n
       else\n
         this.showWidget(data);\n
@@ -89,7 +107,7 @@
       CodeMirror.signal(data, "shown");\n
 \n
       var debounce = 0, completion = this, finished;\n
-      var closeOn = this.options.closeCharacters || /[\\s()\\[\\]{};:>,]/;\n
+      var closeOn = this.options.closeCharacters;\n
       var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;\n
 \n
       var requestAnimationFrame = window.requestAnimationFrame || function(fn) {\n
@@ -108,15 +126,17 @@
       function update() {\n
         if (finished) return;\n
         CodeMirror.signal(data, "update");\n
-        if (completion.options.async)\n
-          completion.getHints(completion.cm, finishUpdate, completion.options);\n
+        var getHints = completion.options.hint;\n
+        if (getHints.async)\n
+          getHints(completion.cm, finishUpdate, completion.options);\n
         else\n
-          finishUpdate(completion.getHints(completion.cm, completion.options));\n
+          finishUpdate(getHints(completion.cm, completion.options));\n
       }\n
       function finishUpdate(data_) {\n
         data = data_;\n
         if (finished) return;\n
         if (!data || !data.list.length) return done();\n
+        if (completion.widget) completion.widget.close();\n
         completion.widget = new Widget(completion, data);\n
       }\n
 \n
@@ -141,6 +161,17 @@
       }\n
       this.cm.on("cursorActivity", activity);\n
       this.onClose = done;\n
+    },\n
+\n
+    buildOptions: function(options) {\n
+      var editor = this.cm.options.hintOptions;\n
+      var out = {};\n
+      for (var prop in defaultOptions) out[prop] = defaultOptions[prop];\n
+      if (editor) for (var prop in editor)\n
+        if (editor[prop] !== undefined) out[prop] = editor[prop];\n
+      if (options) for (var prop in options)\n
+        if (options[prop] !== undefined) out[prop] = options[prop];\n
+      return out;\n
     }\n
   };\n
 \n
@@ -149,7 +180,7 @@
     else return completion.text;\n
   }\n
 \n
-  function buildKeyMap(options, handle) {\n
+  function buildKeyMap(completion, handle) {\n
     var baseMap = {\n
       Up: function() {handle.moveFocus(-1);},\n
       Down: function() {handle.moveFocus(1);},\n
@@ -161,7 +192,8 @@
       Tab: handle.pick,\n
       Esc: handle.close\n
     };\n
-    var ourMap = options.customKeys ? {} : baseMap;\n
+    var custom = completion.options.customKeys;\n
+    var ourMap = custom ? {} : baseMap;\n
     function addBinding(key, val) {\n
       var bound;\n
       if (typeof val != "string")\n
@@ -173,12 +205,13 @@
         bound = val;\n
       ourMap[key] = bound;\n
     }\n
-    if (options.customKeys)\n
-      for (var key in options.customKeys) if (options.customKeys.hasOwnProperty(key))\n
-        addBinding(key, options.customKeys[key]);\n
-    if (options.extraKeys)\n
-      for (var key in options.extraKeys) if (options.extraKeys.hasOwnProperty(key))\n
-        addBinding(key, options.extraKeys[key]);\n
+    if (custom)\n
+      for (var key in custom) if (custom.hasOwnProperty(key))\n
+        addBinding(key, custom[key]);\n
+    var extra = completion.options.extraKeys;\n
+    if (extra)\n
+      for (var key in extra) if (extra.hasOwnProperty(key))\n
+        addBinding(key, extra[key]);\n
     return ourMap;\n
   }\n
 \n
@@ -192,11 +225,11 @@
   function Widget(completion, data) {\n
     this.completion = completion;\n
     this.data = data;\n
-    var widget = this, cm = completion.cm, options = completion.options;\n
+    var widget = this, cm = completion.cm;\n
 \n
     var hints = this.hints = document.createElement("ul");\n
     hints.className = "CodeMirror-hints";\n
-    this.selectedHint = options.getDefaultSelection ? options.getDefaultSelection(cm,options,data) : 0;\n
+    this.selectedHint = data.selectedHint || 0;\n
 \n
     var completions = data.list;\n
     for (var i = 0; i < completions.length; ++i) {\n
@@ -209,19 +242,19 @@
       elt.hintId = i;\n
     }\n
 \n
-    var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null);\n
+    var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);\n
     var left = pos.left, top = pos.bottom, below = true;\n
     hints.style.left = left + "px";\n
     hints.style.top = top + "px";\n
     // If we\'re at the edge of the screen, then we want the menu to appear on the left of the cursor.\n
     var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);\n
     var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);\n
-    (options.container || document.body).appendChild(hints);\n
+    (completion.options.container || document.body).appendChild(hints);\n
     var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;\n
     if (overlapY > 0) {\n
-      var height = box.bottom - box.top, curTop = box.top - (pos.bottom - pos.top);\n
+      var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);\n
       if (curTop - height > 0) { // Fits above cursor\n
-        hints.style.top = (top = curTop - height) + "px";\n
+        hints.style.top = (top = pos.top - height) + "px";\n
         below = false;\n
       } else if (height > winH) {\n
         hints.style.height = (winH - 5) + "px";\n
@@ -234,7 +267,7 @@
         }\n
       }\n
     }\n
-    var overlapX = box.left - winW;\n
+    var overlapX = box.right - winW;\n
     if (overlapX > 0) {\n
       if (box.right - box.left > winW) {\n
         hints.style.width = (winW - 5) + "px";\n
@@ -243,7 +276,7 @@
       hints.style.left = (left = pos.left - overlapX) + "px";\n
     }\n
 \n
-    cm.addKeyMap(this.keyMap = buildKeyMap(options, {\n
+    cm.addKeyMap(this.keyMap = buildKeyMap(completion, {\n
       moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },\n
       setFocus: function(n) { widget.changeActive(n); },\n
       menuSize: function() { return widget.screenAmount(); },\n
@@ -253,7 +286,7 @@
       data: data\n
     }));\n
 \n
-    if (options.closeOnUnfocus !== false) {\n
+    if (completion.options.closeOnUnfocus) {\n
       var closingOnBlur;\n
       cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });\n
       cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });\n
@@ -279,7 +312,7 @@
       var t = getHintElement(hints, e.target || e.srcElement);\n
       if (t && t.hintId != null) {\n
         widget.changeActive(t.hintId);\n
-        if (options.completeOnSingleClick) widget.pick();\n
+        if (completion.options.completeOnSingleClick) widget.pick();\n
       }\n
     });\n
 \n
@@ -299,7 +332,7 @@
       this.completion.cm.removeKeyMap(this.keyMap);\n
 \n
       var cm = this.completion.cm;\n
-      if (this.completion.options.closeOnUnfocus !== false) {\n
+      if (this.completion.options.closeOnUnfocus) {\n
         cm.off("blur", this.onBlur);\n
         cm.off("focus", this.onFocus);\n
       }\n
@@ -363,7 +396,21 @@
   });\n
 \n
   CodeMirror.commands.autocomplete = CodeMirror.showHint;\n
-})();\n
+\n
+  var defaultOptions = {\n
+    hint: CodeMirror.hint.auto,\n
+    completeSingle: true,\n
+    alignWithWord: true,\n
+    closeCharacters: /[\\s()\\[\\]{};:>,]/,\n
+    closeOnUnfocus: true,\n
+    completeOnSingleClick: false,\n
+    container: null,\n
+    customKeys: null,\n
+    extraKeys: null\n
+  };\n
+\n
+  CodeMirror.defineOption("hintOptions", null);\n
+});\n
 
 
 ]]></string> </value>
@@ -374,7 +421,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>12782</int> </value>
+            <value> <int>14333</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/sql-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/sql-hint.js.xml
index 18b9a07e2d53d181f2cb82319f96557156b356f8..ac17d3f6a6bb2f32e01c8367b28fa47ae8b29699 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/sql-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/sql-hint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.62</string> </value>
+            <value> <string>ts21897119.32</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,19 +22,31 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function () {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../../mode/sql/sql"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var tables;\n
+  var defaultTable;\n
   var keywords;\n
   var CONS = {\n
     QUERY_DIV: ";",\n
     ALIAS_KEYWORD: "AS"\n
   };\n
+  var Pos = CodeMirror.Pos;\n
 \n
   function getKeywords(editor) {\n
     var mode = editor.doc.modeOption;\n
-    if(mode === "sql") mode = "text/x-sql";\n
+    if (mode === "sql") mode = "text/x-sql";\n
     return CodeMirror.resolveMode(mode).keywords;\n
   }\n
 \n
@@ -45,50 +57,82 @@
   }\n
 \n
   function addMatches(result, search, wordlist, formatter) {\n
-    for(var word in wordlist) {\n
-      if(!wordlist.hasOwnProperty(word)) continue;\n
-      if(Array.isArray(wordlist)) {\n
+    for (var word in wordlist) {\n
+      if (!wordlist.hasOwnProperty(word)) continue;\n
+      if (Array.isArray(wordlist)) {\n
         word = wordlist[word];\n
       }\n
-      if(match(search, word)) {\n
+      if (match(search, word)) {\n
         result.push(formatter(word));\n
       }\n
     }\n
   }\n
 \n
-  function columnCompletion(result, editor) {\n
-    var cur = editor.getCursor();\n
-    var token = editor.getTokenAt(cur);\n
+  function nameCompletion(cur, token, result, editor) {\n
+    var useBacktick = (token.string.charAt(0) == "`");\n
     var string = token.string.substr(1);\n
-    var prevCur = CodeMirror.Pos(cur.line, token.start);\n
-    var table = editor.getTokenAt(prevCur).string;\n
-    if( !tables.hasOwnProperty( table ) ){\n
-      table = findTableByAlias(table, editor);\n
+    var prevToken = editor.getTokenAt(Pos(cur.line, token.start));\n
+    if (token.string.charAt(0) == "." || prevToken.string == "."){\n
+      //Suggest colunm names\n
+      if (prevToken.string == ".") {\n
+        var prevToken = editor.getTokenAt(Pos(cur.line, token.start - 1));\n
+      }\n
+      var table = prevToken.string;\n
+      //Check if backtick is used in table name. If yes, use it for columns too.\n
+      var useBacktickTable = false;\n
+      if (table.match(/`/g)) {\n
+        useBacktickTable = true;\n
+        table = table.replace(/`/g, "");\n
+      }\n
+      //Check if table is available. If not, find table by Alias\n
+      if (!tables.hasOwnProperty(table))\n
+        table = findTableByAlias(table, editor);\n
+      var columns = tables[table];\n
+      if (!columns) return;\n
+\n
+      if (useBacktick) {\n
+        addMatches(result, string, columns, function(w) {return "`" + w + "`";});\n
+      }\n
+      else if(useBacktickTable) {\n
+        addMatches(result, string, columns, function(w) {return ".`" + w + "`";});\n
+      }\n
+      else {\n
+        addMatches(result, string, columns, function(w) {return "." + w;});\n
+      }\n
     }\n
-    var columns = tables[table];\n
-    if(!columns) {\n
-      return;\n
+    else {\n
+      //Suggest table names or colums in defaultTable\n
+      while (token.start && string.charAt(0) == ".") {\n
+        token = editor.getTokenAt(Pos(cur.line, token.start - 1));\n
+        string = token.string + string;\n
+      }\n
+      if (useBacktick) {\n
+        addMatches(result, string, tables, function(w) {return "`" + w + "`";});\n
+        addMatches(result, string, defaultTable, function(w) {return "`" + w + "`";});\n
+      }\n
+      else {\n
+        addMatches(result, string, tables, function(w) {return w;});\n
+        addMatches(result, string, defaultTable, function(w) {return w;});\n
+      }\n
     }\n
-    addMatches(result, string, columns,\n
-        function(w) {return "." + w;});\n
   }\n
 \n
   function eachWord(lineText, f) {\n
-    if( !lineText ){return;}\n
+    if (!lineText) return;\n
     var excepted = /[,;]/g;\n
-    var words = lineText.split( " " );\n
-    for( var i = 0; i < words.length; i++ ){\n
-      f( words[i]?words[i].replace( excepted, \'\' ) : \'\' );\n
+    var words = lineText.split(" ");\n
+    for (var i = 0; i < words.length; i++) {\n
+      f(words[i]?words[i].replace(excepted, \'\') : \'\');\n
     }\n
   }\n
 \n
-  function convertCurToNumber( cur ){\n
+  function convertCurToNumber(cur) {\n
     // max characters of a line is 999,999.\n
-    return cur.line + cur.ch / Math.pow( 10, 6 );\n
+    return cur.line + cur.ch / Math.pow(10, 6);\n
   }\n
 \n
-  function convertNumberToCur( num ){\n
-    return CodeMirror.Pos(Math.floor( num ), +num.toString().split( \'.\' ).pop());\n
+  function convertNumberToCur(num) {\n
+    return Pos(Math.floor(num), +num.toString().split(\'.\').pop());\n
   }\n
 \n
   function findTableByAlias(alias, editor) {\n
@@ -99,26 +143,26 @@
     var table = "";\n
     var separator = [];\n
     var validRange = {\n
-      start: CodeMirror.Pos( 0, 0 ),\n
-      end: CodeMirror.Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).length )\n
+      start: Pos(0, 0),\n
+      end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)\n
     };\n
 \n
     //add separator\n
-    var indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV );\n
-    while( indexOfSeparator != -1 ){\n
-      separator.push( doc.posFromIndex(indexOfSeparator));\n
-      indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV, indexOfSeparator+1);\n
+    var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);\n
+    while(indexOfSeparator != -1) {\n
+      separator.push(doc.posFromIndex(indexOfSeparator));\n
+      indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);\n
     }\n
-    separator.unshift( CodeMirror.Pos( 0, 0 ) );\n
-    separator.push( CodeMirror.Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).text.length ) );\n
+    separator.unshift(Pos(0, 0));\n
+    separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));\n
 \n
-    //find valieRange\n
+    //find valid range\n
     var prevItem = 0;\n
-    var current = convertCurToNumber( editor.getCursor() );\n
-    for( var i=0; i< separator.length; i++){\n
-      var _v = convertCurToNumber( separator[i] );\n
-      if( current > prevItem && current <= _v ){\n
-        validRange = { start: convertNumberToCur( prevItem ), end: convertNumberToCur( _v ) };\n
+    var current = convertCurToNumber(editor.getCursor());\n
+    for (var i=0; i< separator.length; i++) {\n
+      var _v = convertCurToNumber(separator[i]);\n
+      if (current > prevItem && current <= _v) {\n
+        validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };\n
         break;\n
       }\n
       prevItem = _v;\n
@@ -126,48 +170,55 @@
 \n
     var query = doc.getRange(validRange.start, validRange.end, false);\n
 \n
-    for(var i=0; i < query.length; i++){\n
+    for (var i = 0; i < query.length; i++) {\n
       var lineText = query[i];\n
-      eachWord( lineText, function( word ){\n
+      eachWord(lineText, function(word) {\n
         var wordUpperCase = word.toUpperCase();\n
-        if( wordUpperCase === aliasUpperCase && tables.hasOwnProperty( previousWord ) ){\n
+        if (wordUpperCase === aliasUpperCase && tables.hasOwnProperty(previousWord)) {\n
             table = previousWord;\n
         }\n
-        if( wordUpperCase !== CONS.ALIAS_KEYWORD ){\n
+        if (wordUpperCase !== CONS.ALIAS_KEYWORD) {\n
           previousWord = word;\n
         }\n
       });\n
-      if( table ){ break; }\n
+      if (table) break;\n
     }\n
     return table;\n
   }\n
 \n
-  function sqlHint(editor, options) {\n
+  CodeMirror.registerHelper("hint", "sql", function(editor, options) {\n
     tables = (options && options.tables) || {};\n
+    var defaultTableName = options && options.defaultTable;\n
+    defaultTable = (defaultTableName && tables[defaultTableName] || []);\n
     keywords = keywords || getKeywords(editor);\n
+\n
     var cur = editor.getCursor();\n
-    var token = editor.getTokenAt(cur);\n
     var result = [];\n
-    var search = token.string.trim();\n
-\n
-    addMatches(result, search, keywords,\n
-        function(w) {return w.toUpperCase();});\n
-\n
-    addMatches(result, search, tables,\n
-        function(w) {return w;});\n
+    var token = editor.getTokenAt(cur), start, end, search;\n
+    if (token.end > cur.ch) {\n
+      token.end = cur.ch;\n
+      token.string = token.string.slice(0, cur.ch - token.start);\n
+    }\n
 \n
-    if(search.lastIndexOf(\'.\') === 0) {\n
-      columnCompletion(result, editor);\n
+    if (token.string.match(/^[.`\\w@]\\w*$/)) {\n
+      search = token.string;\n
+      start = token.start;\n
+      end = token.end;\n
+    } else {\n
+      start = end = cur.ch;\n
+      search = "";\n
+    }\n
+    if (search.charAt(0) == "." || search.charAt(0) == "`") {\n
+      nameCompletion(cur, token, result, editor);\n
+    } else {\n
+      addMatches(result, search, tables, function(w) {return w;});\n
+      addMatches(result, search, defaultTable, function(w) {return w;});\n
+      addMatches(result, search, keywords, function(w) {return w.toUpperCase();});\n
     }\n
 \n
-    return {\n
-      list: result,\n
-        from: CodeMirror.Pos(cur.line, token.start),\n
-        to: CodeMirror.Pos(cur.line, token.end)\n
-    };\n
-  }\n
-  CodeMirror.registerHelper("hint", "sql", sqlHint);\n
-})();\n
+    return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};\n
+  });\n
+});\n
 
 
 ]]></string> </value>
@@ -178,7 +229,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4259</int> </value>
+            <value> <int>6499</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/xml-hint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/xml-hint.js.xml
index f96737c5e25e199b32949c194197270c32572a59..57db42c6adf35d6dc1f06ce08f7926da0a59b11c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/xml-hint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/hint/xml-hint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.98</string> </value>
+            <value> <string>ts21897118.97</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var Pos = CodeMirror.Pos;\n
@@ -32,30 +42,55 @@
     var quote = (options && options.quoteChar) || \'"\';\n
     if (!tags) return;\n
     var cur = cm.getCursor(), token = cm.getTokenAt(cur);\n
+    if (token.end > cur.ch) {\n
+      token.end = cur.ch;\n
+      token.string = token.string.slice(0, cur.ch - token.start);\n
+    }\n
     var inner = CodeMirror.innerMode(cm.getMode(), token.state);\n
     if (inner.mode.name != "xml") return;\n
     var result = [], replaceToken = false, prefix;\n
-    var isTag = token.string.charAt(0) == "<";\n
-    if (!inner.state.tagName || isTag) { // Tag completion\n
-      if (isTag) {\n
-        prefix = token.string.slice(1);\n
-        replaceToken = true;\n
-      }\n
+    var tag = /\\btag\\b/.test(token.type) && !/>$/.test(token.string);\n
+    var tagName = tag && /^\\w/.test(token.string), tagStart;\n
+\n
+    if (tagName) {\n
+      var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);\n
+      var tagType = /<\\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;\n
+      if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);\n
+    } else if (tag && token.string == "<") {\n
+      tagType = "open";\n
+    } else if (tag && token.string == "</") {\n
+      tagType = "close";\n
+    }\n
+\n
+    if (!tag && !inner.state.tagName || tagType) {\n
+      if (tagName)\n
+        prefix = token.string;\n
+      replaceToken = tagType;\n
       var cx = inner.state.context, curTag = cx && tags[cx.tagName];\n
       var childList = cx ? curTag && curTag.children : tags["!top"];\n
-      if (childList) {\n
+      if (childList && tagType != "close") {\n
         for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)\n
           result.push("<" + childList[i]);\n
-      } else {\n
-        for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.lastIndexOf(prefix, 0) == 0))\n
-          result.push("<" + name);\n
+      } else if (tagType != "close") {\n
+        for (var name in tags)\n
+          if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))\n
+            result.push("<" + name);\n
       }\n
-      if (cx && (!prefix || ("/" + cx.tagName).lastIndexOf(prefix, 0) == 0))\n
+      if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))\n
         result.push("</" + cx.tagName + ">");\n
     } else {\n
       // Attribute completion\n
       var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;\n
-      if (!attrs) return;\n
+      var globalAttrs = tags["!attrs"];\n
+      if (!attrs && !globalAttrs) return;\n
+      if (!attrs) {\n
+        attrs = globalAttrs;\n
+      } else if (globalAttrs) { // Combine tag-local and global attributes\n
+        var set = {};\n
+        for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];\n
+        for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];\n
+        attrs = set;\n
+      }\n
       if (token.type == "string" || token.string == "=") { // A value\n
         var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),\n
                                  Pos(cur.line, token.type == "string" ? token.start : token.end));\n
@@ -64,9 +99,16 @@
         if (typeof atValues == \'function\') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget\n
         if (token.type == "string") {\n
           prefix = token.string;\n
+          var n = 0;\n
           if (/[\'"]/.test(token.string.charAt(0))) {\n
             quote = token.string.charAt(0);\n
             prefix = token.string.slice(1);\n
+            n++;\n
+          }\n
+          var len = token.string.length;\n
+          if (/[\'"]/.test(token.string.charAt(len - 1))) {\n
+            quote = token.string.charAt(len - 1);\n
+            prefix = token.string.substr(n, len - 2);\n
           }\n
           replaceToken = true;\n
         }\n
@@ -83,14 +125,13 @@
     }\n
     return {\n
       list: result,\n
-      from: replaceToken ? Pos(cur.line, token.start) : cur,\n
+      from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,\n
       to: replaceToken ? Pos(cur.line, token.end) : cur\n
     };\n
   }\n
 \n
-  CodeMirror.xmlHint = getHints; // deprecated\n
   CodeMirror.registerHelper("hint", "xml", getHints);\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -101,7 +142,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2964</int> </value>
+            <value> <int>4735</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/.css-lint.js.swp.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/.css-lint.js.swp.xml
new file mode 100644
index 0000000000000000000000000000000000000000..087487c08676221a6f04b253b4dcd3fa8920d1dd
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/.css-lint.js.swp.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21898627.73</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>.css-lint.js.swp</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/octet-stream</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">YjBuYW5vIDIuMy4AtX8AAMB7TQEAAAAAXhRNAWFybmF1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAEDWSwFtaW5qbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAABQNk0BL21udC9k
+YXZfZXJwNS9wb3J0YWxfc2tpbnMvZXJwNV9jb2RlX21pcnJvci9jb2RlbWlycm9yL2FkZG9uL2xp
+bnQvY3NzLWxpbnQuanMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQEAAAAAAACg300BAAAAAKDMTQEAAAAA
+AAAAAAAAAABhAQAAAAAAAKDfTQEAAAAAoMxNAQAAAAAAAAAAAAAAAEEBAAAAAAAAIM5NAQAAAACg
+300BAAAAAAAAAAAAAAAAIQEAAAAAAADgzE0BAAAAAFA2TQEAAAAAAAAAAAAAAAABAQAAAAAAAA==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1024</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/coffeescript-lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/coffeescript-lint.js.xml
index ba6db79b0a21db29a6b60ca1f2aa4fa65f753441..094f86ffb28cc3a239cfc8274b2c11a9dfbc57e7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/coffeescript-lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/coffeescript-lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.66</string> </value>
+            <value> <string>ts21897121.01</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js\n
 \n
 // declare global: coffeelint\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerHelper("lint", "coffeescript", function(text) {\n
   var found = [];\n
   var parseError = function(err) {\n
@@ -48,7 +61,8 @@ CodeMirror.registerHelper("lint", "coffeescript", function(text) {\n
   }\n
   return found;\n
 });\n
-CodeMirror.coffeeValidator = CodeMirror.lint.coffeescript; // deprecated\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -59,7 +73,7 @@ CodeMirror.coffeeValidator = CodeMirror.lint.coffeescript; // deprecated\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>882</int> </value>
+            <value> <int>1270</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/css-lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/css-lint.js.xml
index e615b6c36237322034b9311be9db36e5cabb5696..b647c7cf0d83631a6d0f45152209e62eed45c86e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/css-lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/css-lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.99</string> </value>
+            <value> <string>ts21898625.13</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,12 +22,26 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Depends on csslint.js from https://github.com/stubbornella/csslint\n
 \n
 // declare global: CSSLint\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerHelper("lint", "css", function(text) {\n
   var found = [];\n
+  if (!window.CSSLint) return found;\n
   var results = CSSLint.verify(text), messages = results.messages, message = null;\n
   for ( var i = 0; i < messages.length; i++) {\n
     message = messages[i];\n
@@ -41,6 +55,8 @@ CodeMirror.registerHelper("lint", "css", function(text) {\n
   }\n
   return found;\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -51,7 +67,7 @@ CodeMirror.registerHelper("lint", "css", function(text) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>648</int> </value>
+            <value> <int>1146</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/javascript-lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/javascript-lint.js.xml
index 7da47b3e40555951004ea2b473334370de38427a..85b68ae290ff853479fadceb7bef95877c560600 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/javascript-lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/javascript-lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403073.05</string> </value>
+            <value> <string>ts21897120.51</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
   // declare global: JSHINT\n
 \n
@@ -36,6 +46,7 @@
                  "Unclosed string", "Stopping, unable to continue" ];\n
 \n
   function validator(text, options) {\n
+    if (!window.JSHINT) return [];\n
     JSHINT(text, options);\n
     var errors = JSHINT.data().errors, result = [];\n
     if (errors) parseErrors(errors, result);\n
@@ -43,7 +54,6 @@
   }\n
 \n
   CodeMirror.registerHelper("lint", "javascript", validator);\n
-  CodeMirror.javascriptValidator = CodeMirror.lint.javascript; // deprecated\n
 \n
   function cleanup(error) {\n
     // All problems are warnings by default\n
@@ -147,7 +157,7 @@
       }\n
     }\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -158,7 +168,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4069</int> </value>
+            <value> <int>4452</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/json-lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/json-lint.js.xml
index f4906e42b683115080dd2353bd8c7c9af961c4be..ae10d7bca28ff1ac1489d81bae94787d5575db42 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/json-lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/json-lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403073.16</string> </value>
+            <value> <string>ts21897120.37</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,10 +20,25 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>// Depends on jsonlint.js from https://github.com/zaach/jsonlint\n
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// Depends on jsonlint.js from https://github.com/zaach/jsonlint\n
 \n
 // declare global: jsonlint\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.registerHelper("lint", "json", function(text) {\n
   var found = [];\n
   jsonlint.parseError = function(str, hash) {\n
@@ -36,8 +51,11 @@ CodeMirror.registerHelper("lint", "json", function(text) {\n
   catch(e) {}\n
   return found;\n
 });\n
-CodeMirror.jsonValidator = CodeMirror.lint.json; // deprecated\n
-</string> </value>
+\n
+});\n
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -45,7 +63,7 @@ CodeMirror.jsonValidator = CodeMirror.lint.json; // deprecated\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>556</int> </value>
+            <value> <int>954</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/lint.js.xml
index a17e74af8996081dded5ce87107a7effccc14caf..8eaf75d32fd10e396b4f0564aca4929d8ba650dc 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.72</string> </value>
+            <value> <string>ts21898385.1</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
   var GUTTER_ID = "CodeMirror-lint-markers";\n
-  var SEVERITIES = /^(?:error|warning)$/;\n
 \n
   function showTooltip(e, content) {\n
     var tt = document.createElement("div");\n
@@ -124,7 +133,7 @@
 \n
   function annotationTooltip(ann) {\n
     var severity = ann.severity;\n
-    if (!SEVERITIES.test(severity)) severity = "error";\n
+    if (!severity) severity = "error";\n
     var tip = document.createElement("div");\n
     tip.className = "CodeMirror-lint-message-" + severity;\n
     tip.appendChild(document.createTextNode(ann.message));\n
@@ -133,10 +142,11 @@
 \n
   function startLinting(cm) {\n
     var state = cm.state.lint, options = state.options;\n
+    var passOptions = options.options || options; // Support deprecated passing of `options` property in options\n
     if (options.async)\n
-      options.getAnnotations(cm, updateLinting, options);\n
+      options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm);\n
     else\n
-      updateLinting(cm, options.getAnnotations(cm.getValue(), options.options));\n
+      updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm));\n
   }\n
 \n
   function updateLinting(cm, annotationsNotSorted) {\n
@@ -155,7 +165,7 @@
       for (var i = 0; i < anns.length; ++i) {\n
         var ann = anns[i];\n
         var severity = ann.severity;\n
-        if (!SEVERITIES.test(severity)) severity = "error";\n
+        if (!severity) severity = "error";\n
         maxSeverity = getMaxSeverity(maxSeverity, severity);\n
 \n
         if (options.formatAnnotation) ann = options.formatAnnotation(ann);\n
@@ -184,25 +194,19 @@
     var target = e.target || e.srcElement;\n
     showTooltipFor(e, annotationTooltip(ann), target);\n
   }\n
-\n
-  // When the mouseover fires, the cursor might not actually be over\n
-  // the character itself yet. These pairs of x,y offsets are used to\n
-  // probe a few nearby points when no suitable marked range is found.\n
-  var nearby = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0];\n
 \n
   function onMouseOver(cm, e) {\n
-    if (!/\\bCodeMirror-lint-mark-/.test((e.target || e.srcElement).className)) return;\n
-    for (var i = 0; i < nearby.length; i += 2) {\n
-      var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i],\n
-                                                top: e.clientY + nearby[i + 1]}));\n
-      for (var j = 0; j < spans.length; ++j) {\n
-        var span = spans[j], ann = span.__annotation;\n
-        if (ann) return popupSpanTooltip(ann, e);\n
-      }\n
+    var target = e.target || e.srcElement;\n
+    if (!/\\bCodeMirror-lint-mark-/.test(target.className)) return;\n
+    var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;\n
+    var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));\n
+    for (var i = 0; i < spans.length; ++i) {\n
+      var ann = spans[i].__annotation;\n
+      if (ann) return popupSpanTooltip(ann, e);\n
     }\n
   }\n
 \n
-  function optionHandler(cm, val, old) {\n
+  CodeMirror.defineOption("lint", false, function(cm, val, old) {\n
     if (old && old != CodeMirror.Init) {\n
       clearMarks(cm);\n
       cm.off("change", onChange);\n
@@ -220,11 +224,8 @@
 \n
       startLinting(cm);\n
     }\n
-  }\n
-\n
-  CodeMirror.defineOption("lintWith", false, optionHandler); // deprecated\n
-  CodeMirror.defineOption("lint", false, optionHandler); // deprecated\n
-})();\n
+  });\n
+});\n
 
 
 ]]></string> </value>
@@ -235,7 +236,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6962</int> </value>
+            <value> <int>7036</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/yaml-lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/yaml-lint.js.xml
index 712ee7a44f1e3e4166e7b3a1ca0dbc007d8783db..b2f0a0212417857c55b4b2c6d839cb5f828603b5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/yaml-lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/lint/yaml-lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.85</string> </value>
+            <value> <string>ts21897120.75</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,22 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>// Depends on js-yaml.js from https://github.com/nodeca/js-yaml\n
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+// Depends on js-yaml.js from https://github.com/nodeca/js-yaml\n
 \n
 // declare global: jsyaml\n
 \n
@@ -33,8 +48,11 @@ CodeMirror.registerHelper("lint", "yaml", function(text) {\n
   }\n
   return found;\n
 });\n
-CodeMirror.yamlValidator = CodeMirror.lint.yaml; // deprecated\n
-</string> </value>
+\n
+});\n
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -42,7 +60,7 @@ CodeMirror.yamlValidator = CodeMirror.lint.yaml; // deprecated\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>450</int> </value>
+            <value> <int>848</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/copy_of_merge.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/copy_of_merge.js.xml
deleted file mode 100644
index dea70760251683491ac040aaccdc3dee172e1ce3..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/copy_of_merge.js.xml
+++ /dev/null
@@ -1,523 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403073.5</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>copy_of_merge.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-(function() {\n
-  "use strict";\n
-  // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL\n
-\n
-  var Pos = CodeMirror.Pos;\n
-  var svgNS = "http://www.w3.org/2000/svg";\n
-\n
-  function DiffView(mv, type) {\n
-    this.mv = mv;\n
-    this.type = type;\n
-    this.classes = type == "left"\n
-      ? {chunk: "CodeMirror-merge-l-chunk",\n
-         start: "CodeMirror-merge-l-chunk-start",\n
-         end: "CodeMirror-merge-l-chunk-end",\n
-         insert: "CodeMirror-merge-l-inserted",\n
-         del: "CodeMirror-merge-l-deleted",\n
-         connect: "CodeMirror-merge-l-connect"}\n
-      : {chunk: "CodeMirror-merge-r-chunk",\n
-         start: "CodeMirror-merge-r-chunk-start",\n
-         end: "CodeMirror-merge-r-chunk-end",\n
-         insert: "CodeMirror-merge-r-inserted",\n
-         del: "CodeMirror-merge-r-deleted",\n
-         connect: "CodeMirror-merge-r-connect"};\n
-  }\n
-\n
-  DiffView.prototype = {\n
-    constructor: DiffView,\n
-    init: function(pane, orig, options) {\n
-      this.edit = this.mv.edit;\n
-      this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options)));\n
-\n
-      this.diff = getDiff(asString(orig), asString(options.value));\n
-      this.diffOutOfDate = false;\n
-\n
-      this.showDifferences = options.showDifferences !== false;\n
-      this.forceUpdate = registerUpdate(this);\n
-      setScrollLock(this, true, false);\n
-      registerScroll(this);\n
-    },\n
-    setShowDifferences: function(val) {\n
-      val = val !== false;\n
-      if (val != this.showDifferences) {\n
-        this.showDifferences = val;\n
-        this.forceUpdate("full");\n
-      }\n
-    }\n
-  };\n
-\n
-  function registerUpdate(dv) {\n
-    var edit = {from: 0, to: 0, marked: []};\n
-    var orig = {from: 0, to: 0, marked: []};\n
-    var debounceChange;\n
-    function update(mode) {\n
-      if (mode == "full") {\n
-        if (dv.svg) clear(dv.svg);\n
-        clear(dv.copyButtons);\n
-        clearMarks(dv.edit, edit.marked, dv.classes);\n
-        clearMarks(dv.orig, orig.marked, dv.classes);\n
-        edit.from = edit.to = orig.from = orig.to = 0;\n
-      }\n
-      if (dv.diffOutOfDate) {\n
-        dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());\n
-        dv.diffOutOfDate = false;\n
-        CodeMirror.signal(dv.edit, "updateDiff", dv.diff);\n
-      }\n
-      if (dv.showDifferences) {\n
-        updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);\n
-        updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);\n
-      }\n
-      drawConnectors(dv);\n
-    }\n
-    function set(slow) {\n
-      clearTimeout(debounceChange);\n
-      debounceChange = setTimeout(update, slow == true ? 250 : 100);\n
-    }\n
-    function change() {\n
-      if (!dv.diffOutOfDate) {\n
-        dv.diffOutOfDate = true;\n
-        edit.from = edit.to = orig.from = orig.to = 0;\n
-      }\n
-      set(true);\n
-    }\n
-    dv.edit.on("change", change);\n
-    dv.orig.on("change", change);\n
-    dv.edit.on("viewportChange", set);\n
-    dv.orig.on("viewportChange", set);\n
-    update();\n
-    return update;\n
-  }\n
-\n
-  function registerScroll(dv) {\n
-    dv.edit.on("scroll", function() {\n
-      syncScroll(dv, DIFF_INSERT) && drawConnectors(dv);\n
-    });\n
-    dv.orig.on("scroll", function() {\n
-      syncScroll(dv, DIFF_DELETE) && drawConnectors(dv);\n
-    });\n
-  }\n
-\n
-  function syncScroll(dv, type) {\n
-    // Change handler will do a refresh after a timeout when diff is out of date\n
-    if (dv.diffOutOfDate) return false;\n
-    if (!dv.lockScroll) return true;\n
-    var editor, other, now = +new Date;\n
-    if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }\n
-    else { editor = dv.orig; other = dv.edit; }\n
-    // Don\'t take action if the position of this editor was recently set\n
-    // (to prevent feedback loops)\n
-    if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;\n
-\n
-    var sInfo = editor.getScrollInfo(), halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;\n
-    var mid = editor.lineAtHeight(midY, "local");\n
-    var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT);\n
-    var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);\n
-    var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);\n
-    var ratio = (midY - off.top) / (off.bot - off.top);\n
-    var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);\n
-\n
-    var botDist, mix;\n
-    // Some careful tweaking to make sure no space is left out of view\n
-    // when scrolling to top or bottom.\n
-    if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {\n
-      targetPos = targetPos * mix + sInfo.top * (1 - mix);\n
-    } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {\n
-      var otherInfo = other.getScrollInfo();\n
-      var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;\n
-      if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)\n
-        targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);\n
-    }\n
-\n
-    other.scrollTo(sInfo.left, targetPos);\n
-    other.state.scrollSetAt = now;\n
-    other.state.scrollSetBy = dv;\n
-    return true;\n
-  }\n
-\n
-  function getOffsets(editor, around) {\n
-    var bot = around.after;\n
-    if (bot == null) bot = editor.lastLine() + 1;\n
-    return {top: editor.heightAtLine(around.before || 0, "local"),\n
-            bot: editor.heightAtLine(bot, "local")};\n
-  }\n
-\n
-  function setScrollLock(dv, val, action) {\n
-    dv.lockScroll = val;\n
-    if (val && action != false) syncScroll(dv, DIFF_INSERT) && drawConnectors(dv);\n
-    dv.lockButton.innerHTML = val ? "\\u21db\\u21da" : "\\u21db&nbsp;&nbsp;\\u21da";\n
-  }\n
-\n
-  // Updating the marks for editor content\n
-\n
-  function clearMarks(editor, arr, classes) {\n
-    for (var i = 0; i < arr.length; ++i) {\n
-      var mark = arr[i];\n
-      if (mark instanceof CodeMirror.TextMarker) {\n
-        mark.clear();\n
-      } else {\n
-        editor.removeLineClass(mark, "background", classes.chunk);\n
-        editor.removeLineClass(mark, "background", classes.start);\n
-        editor.removeLineClass(mark, "background", classes.end);\n
-      }\n
-    }\n
-    arr.length = 0;\n
-  }\n
-\n
-  // FIXME maybe add a margin around viewport to prevent too many updates\n
-  function updateMarks(editor, diff, state, type, classes) {\n
-    var vp = editor.getViewport();\n
-    editor.operation(function() {\n
-      if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {\n
-        clearMarks(editor, state.marked, classes);\n
-        markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);\n
-        state.from = vp.from; state.to = vp.to;\n
-      } else {\n
-        if (vp.from < state.from) {\n
-          markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);\n
-          state.from = vp.from;\n
-        }\n
-        if (vp.to > state.to) {\n
-          markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);\n
-          state.to = vp.to;\n
-        }\n
-      }\n
-    });\n
-  }\n
-\n
-  function markChanges(editor, diff, type, marks, from, to, classes) {\n
-    var pos = Pos(0, 0);\n
-    var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));\n
-    var cls = type == DIFF_DELETE ? classes.del : classes.insert;\n
-    function markChunk(start, end) {\n
-      var bfrom = Math.max(from, start), bto = Math.min(to, end);\n
-      for (var i = bfrom; i < bto; ++i) {\n
-        var line = editor.addLineClass(i, "background", classes.chunk);\n
-        if (i == start) editor.addLineClass(line, "background", classes.start);\n
-        if (i == end - 1) editor.addLineClass(line, "background", classes.end);\n
-        marks.push(line);\n
-      }\n
-      // When the chunk is empty, make sure a horizontal line shows up\n
-      if (start == end && bfrom == end && bto == end) {\n
-        if (bfrom)\n
-          marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));\n
-        else\n
-          marks.push(editor.addLineClass(bfrom, "background", classes.start));\n
-      }\n
-    }\n
-\n
-    var chunkStart = 0;\n
-    for (var i = 0; i < diff.length; ++i) {\n
-      var part = diff[i], tp = part[0], str = part[1];\n
-      if (tp == DIFF_EQUAL) {\n
-        var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);\n
-        moveOver(pos, str);\n
-        var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);\n
-        if (cleanTo > cleanFrom) {\n
-          if (i) markChunk(chunkStart, cleanFrom);\n
-          chunkStart = cleanTo;\n
-        }\n
-      } else {\n
-        if (tp == type) {\n
-          var end = moveOver(pos, str, true);\n
-          var a = posMax(top, pos), b = posMin(bot, end);\n
-          if (!posEq(a, b))\n
-            marks.push(editor.markText(a, b, {className: cls}));\n
-          pos = end;\n
-        }\n
-      }\n
-    }\n
-    if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);\n
-  }\n
-\n
-  // Updating the gap between editor and original\n
-\n
-  function drawConnectors(dv) {\n
-    if (!dv.showDifferences) return;\n
-\n
-    if (dv.svg) {\n
-      clear(dv.svg);\n
-      var w = dv.gap.offsetWidth;\n
-      attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);\n
-    }\n
-    clear(dv.copyButtons);\n
-\n
-    var flip = dv.type == "left";\n
-    var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();\n
-    var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;\n
-    iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {\n
-      if (topEdit > vpEdit.to || botEdit < vpEdit.from ||\n
-          topOrig > vpOrig.to || botOrig < vpOrig.from)\n
-        return;\n
-      var topLpx = dv.orig.heightAtLine(topOrig, "local") - sTopOrig, top = topLpx;\n
-      if (dv.svg) {\n
-        var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit;\n
-        if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }\n
-        var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;\n
-        var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;\n
-        if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }\n
-        var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;\n
-        var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;\n
-        attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),\n
-              "d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",\n
-              "class", dv.classes.connect);\n
-      }\n
-      var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\\u21dd" : "\\u21dc",\n
-                                                "CodeMirror-merge-copy"));\n
-      copy.title = "Revert chunk";\n
-      copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};\n
-      copy.style.top = top + "px";\n
-    });\n
-  }\n
-\n
-  function copyChunk(dv, chunk) {\n
-    if (dv.diffOutOfDate) return;\n
-    dv.edit.replaceRange(dv.orig.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),\n
-                         Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0));\n
-  }\n
-\n
-  // Merge view, containing 0, 1, or 2 diff views.\n
-\n
-  var MergeView = CodeMirror.MergeView = function(node, options) {\n
-    if (!(this instanceof MergeView)) return new MergeView(node, options);\n
-\n
-    var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;\n
-    var hasLeft = origLeft != null, hasRight = origRight != null;\n
-    var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);\n
-    var wrap = [], left = this.left = null, right = this.right = null;\n
-\n
-    if (hasLeft) {\n
-      left = this.left = new DiffView(this, "left");\n
-      var leftPane = elt("div", null, "CodeMirror-merge-pane");\n
-      wrap.push(leftPane);\n
-      wrap.push(buildGap(left));\n
-    }\n
-\n
-    var editPane = elt("div", null, "CodeMirror-merge-pane");\n
-    wrap.push(editPane);\n
-\n
-    if (hasRight) {\n
-      right = this.right = new DiffView(this, "right");\n
-      wrap.push(buildGap(right));\n
-      var rightPane = elt("div", null, "CodeMirror-merge-pane");\n
-      wrap.push(rightPane);\n
-    }\n
-\n
-    (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";\n
-\n
-    wrap.push(elt("div", null, null, "height: 0; clear: both;"));\n
-    var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));\n
-    this.edit = CodeMirror(editPane, copyObj(options));\n
-\n
-    if (left) left.init(leftPane, origLeft, options);\n
-    if (right) right.init(rightPane, origRight, options);\n
-\n
-    var onResize = function() {\n
-      if (left) drawConnectors(left);\n
-      if (right) drawConnectors(right);\n
-    };\n
-    CodeMirror.on(window, "resize", onResize);\n
-    var resizeInterval = setInterval(function() {\n
-      for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}\n
-      if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }\n
-    }, 5000);\n
-  };\n
-\n
-  function buildGap(dv) {\n
-    var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");\n
-    lock.title = "Toggle locked scrolling";\n
-    var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");\n
-    CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });\n
-    dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);\n
-    CodeMirror.on(dv.copyButtons, "click", function(e) {\n
-      var node = e.target || e.srcElement;\n
-      if (node.chunk) copyChunk(dv, node.chunk);\n
-    });\n
-    var gapElts = [dv.copyButtons, lockWrap];\n
-    var svg = document.createElementNS && document.createElementNS(svgNS, "svg");\n
-    if (svg && !svg.createSVGRect) svg = null;\n
-    dv.svg = svg;\n
-    if (svg) gapElts.push(svg);\n
-\n
-    return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");\n
-  }\n
-\n
-  MergeView.prototype = {\n
-    constuctor: MergeView,\n
-    editor: function() { return this.edit; },\n
-    rightOriginal: function() { return this.right && this.right.orig; },\n
-    leftOriginal: function() { return this.left && this.left.orig; },\n
-    setShowDifferences: function(val) {\n
-      if (this.right) this.right.setShowDifferences(val);\n
-      if (this.left) this.left.setShowDifferences(val);\n
-    }\n
-  };\n
-\n
-  function asString(obj) {\n
-    if (typeof obj == "string") return obj;\n
-    else return obj.getValue();\n
-  }\n
-\n
-  // Operations on diffs\n
-\n
-  var dmp = new diff_match_patch();\n
-  function getDiff(a, b) {\n
-    var diff = dmp.diff_main(a, b);\n
-    dmp.diff_cleanupSemantic(diff);\n
-    // The library sometimes leaves in empty parts, which confuse the algorithm\n
-    for (var i = 0; i < diff.length; ++i) {\n
-      var part = diff[i];\n
-      if (!part[1]) {\n
-        diff.splice(i--, 1);\n
-      } else if (i && diff[i - 1][0] == part[0]) {\n
-        diff.splice(i--, 1);\n
-        diff[i][1] += part[1];\n
-      }\n
-    }\n
-    return diff;\n
-  }\n
-\n
-  function iterateChunks(diff, f) {\n
-    var startEdit = 0, startOrig = 0;\n
-    var edit = Pos(0, 0), orig = Pos(0, 0);\n
-    for (var i = 0; i < diff.length; ++i) {\n
-      var part = diff[i], tp = part[0];\n
-      if (tp == DIFF_EQUAL) {\n
-        var startOff = startOfLineClean(diff, i) ? 0 : 1;\n
-        var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;\n
-        moveOver(edit, part[1], null, orig);\n
-        var endOff = endOfLineClean(diff, i) ? 1 : 0;\n
-        var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;\n
-        if (cleanToEdit > cleanFromEdit) {\n
-          if (i) f(startOrig, cleanFromOrig, startEdit, cleanFromEdit);\n
-          startEdit = cleanToEdit; startOrig = cleanToOrig;\n
-        }\n
-      } else {\n
-        moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);\n
-      }\n
-    }\n
-    if (startEdit <= edit.line || startOrig <= orig.line)\n
-      f(startOrig, orig.line + 1, startEdit, edit.line + 1);\n
-  }\n
-\n
-  function endOfLineClean(diff, i) {\n
-    if (i == diff.length - 1) return true;\n
-    var next = diff[i + 1][1];\n
-    if (next.length == 1 || next.charCodeAt(0) != 10) return false;\n
-    if (i == diff.length - 2) return true;\n
-    next = diff[i + 2][1];\n
-    return next.length > 1 && next.charCodeAt(0) == 10;\n
-  }\n
-\n
-  function startOfLineClean(diff, i) {\n
-    if (i == 0) return true;\n
-    var last = diff[i - 1][1];\n
-    if (last.charCodeAt(last.length - 1) != 10) return false;\n
-    if (i == 1) return true;\n
-    last = diff[i - 2][1];\n
-    return last.charCodeAt(last.length - 1) == 10;\n
-  }\n
-\n
-  function chunkBoundariesAround(diff, n, nInEdit) {\n
-    var beforeE, afterE, beforeO, afterO;\n
-    iterateChunks(diff, function(fromOrig, toOrig, fromEdit, toEdit) {\n
-      var fromLocal = nInEdit ? fromEdit : fromOrig;\n
-      var toLocal = nInEdit ? toEdit : toOrig;\n
-      if (afterE == null) {\n
-        if (fromLocal > n) { afterE = fromEdit; afterO = fromOrig; }\n
-        else if (toLocal > n) { afterE = toEdit; afterO = toOrig; }\n
-      }\n
-      if (toLocal <= n) { beforeE = toEdit; beforeO = toOrig; }\n
-      else if (fromLocal <= n) { beforeE = fromEdit; beforeO = fromOrig; }\n
-    });\n
-    return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};\n
-  }\n
-\n
-  // General utilities\n
-\n
-  function elt(tag, content, className, style) {\n
-    var e = document.createElement(tag);\n
-    if (className) e.className = className;\n
-    if (style) e.style.cssText = style;\n
-    if (typeof content == "string") e.appendChild(document.createTextNode(content));\n
-    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);\n
-    return e;\n
-  }\n
-\n
-  function clear(node) {\n
-    for (var count = node.childNodes.length; count > 0; --count)\n
-      node.removeChild(node.firstChild);\n
-  }\n
-\n
-  function attrs(elt) {\n
-    for (var i = 1; i < arguments.length; i += 2)\n
-      elt.setAttribute(arguments[i], arguments[i+1]);\n
-  }\n
-\n
-  function copyObj(obj, target) {\n
-    if (!target) target = {};\n
-    for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];\n
-    return target;\n
-  }\n
-\n
-  function moveOver(pos, str, copy, other) {\n
-    var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;\n
-    for (;;) {\n
-      var nl = str.indexOf("\\n", at);\n
-      if (nl == -1) break;\n
-      ++out.line;\n
-      if (other) ++other.line;\n
-      at = nl + 1;\n
-    }\n
-    out.ch = (at ? 0 : out.ch) + (str.length - at);\n
-    if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);\n
-    return out;\n
-  }\n
-\n
-  function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }\n
-  function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }\n
-  function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }\n
-})();\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>18196</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/dep/diff_match_patch.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/dep/diff_match_patch.js.xml
deleted file mode 100644
index 27ddef728a8160c5461127d7dd008003a091a898..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/dep/diff_match_patch.js.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403073.27</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>diff_match_patch.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-// From https://code.google.com/p/google-diff-match-patch/ , licensed under the Apache License 2.0\n
-(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}\n
-diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,\n
-b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};\n
-diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,\n
-d):this.diff_bisect_(a,b,d)};\n
-diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,""]);for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};\n
-diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,q=0!=k%2,r=0,t=0,p=0,w=0,v=0;v<f&&!((new Date).getTime()>c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var s=m-n;m<d&&s<e&&a.charAt(m)==b.charAt(s);)m++,s++;j[l]=m;if(m>d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var u=d-i[l];if(m>=\n
-u)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=u-n;u<d&&m<e&&a.charAt(d-u-1)==b.charAt(e-m-1);)u++,m++;i[l]=u;if(u>d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l<h&&-1!=j[l])&&(m=j[l],s=g+m-l,u=d-u,m>=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]};\n
-diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};\n
-diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf("\\n",c);-1==f&&(f=a.length-1);var r=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(r):void 0!==e[r])?b+=String.fromCharCode(e[r]):(b+=String.fromCharCode(g),e[r]=g,d[g++]=r)}return b}var d=[],e={};d[0]="";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};\n
-diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\n
-diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\n
-diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};\n
-diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),s=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<s+m&&(g=b.substring(e-s,e)+b.substring(e,e+m),h=a.substring(0,c-s),j=a.substring(c+m),n=b.substring(0,e-s),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;\n
-var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};\n
-diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&(e.length<=Math.max(g,h)&&e.length<=Math.max(j,i))&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];\n
-d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};\n
-diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);\n
-return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=\n
-h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\\s/;diff_match_patch.linebreakRegex_=/[\\r\\n]/;diff_match_patch.blanklineEndRegex_=/\\n\\r?\\n$/;diff_match_patch.blanklineStartRegex_=/^\\r?\\n\\r?\\n/;\n
-diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};\n
-diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,""]);for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-\n
-g),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,\n
-a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};\n
-diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,"&amp;").replace(d,"&lt;").replace(e,"&gt;").replace(f,"&para;<br>");switch(h){case 1:b[g]=\'<ins style="background:#e6ffe6;">\'+j+"</ins>";break;case -1:b[g]=\'<del style="background:#ffe6e6;">\'+j+"</del>";break;case 0:b[g]="<span>"+j+"</span>"}}return b.join("")};\n
-diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};\n
-diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]="+"+encodeURI(a[c][1]);break;case -1:b[c]="-"+a[c][1].length;break;case 0:b[c]="="+a[c][1].length}return b.join("\\t").replace(/%20/g," ")};\n
-diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);"="==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+\n
-f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};\n
-diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,q=b.length+a.length,r,t=0;t<b.length;t++){i=0;for(k=q;i<k;)d(t,c+\n
-k)<=g?i=k:q=k,k=Math.floor((q-i)/2+i);q=k;i=Math.max(1,c-k+1);var p=Math.min(c+k,a.length)+b.length;k=Array(p+2);for(k[p+1]=(1<<t)-1;p>=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h};\n
-diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};\n
-diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=\n
-c.length+d.length;a.length2+=c.length+d.length}};\n
-diff_match_patch.prototype.patch_make=function(a,b,c){var d;if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");\n
-if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];!e&&0!==i&&(a.start1=f,a.start2=g);switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&\n
-e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};\n
-diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);\n
-if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var q=a[f].diffs[i];0!==q[0]&&(k=this.diff_xIndex(g,h));1===q[0]?b=b.substring(0,\n
-j+k)+q[1]+b.substring(j+k):-1===q[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+q[1].length)));-1!==q[0]&&(h+=q[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};\n
-diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,\n
-c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};\n
-diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push([0,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),\n
-j=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&&\n
-(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};\n
-diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\\n");for(var c=0,d=/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=\n
-parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push([-1,g]);else if("+"==e)f.diffs.push([1,g]);else if(" "==e)f.diffs.push([0,g]);else if("@"==e)break;else if(""!==e)throw Error(\'Invalid patch mode "\'+e+\'" in: \'+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};\n
-diff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1;b=0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2;a=["@@ -"+a+" +"+b+" @@\\n"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c="+";break;case -1:c="-";break;case 0:c=" "}a[b+1]=c+encodeURI(this.diffs[b][1])+"\\n"}return a.join("").replace(/%20/g," ")};\n
-this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})();\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>19292</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.css.xml
index 74fc5ee5c3c3c3dc796a18e9b3affc82a0dae8a2..52240ba7ff3e991c67be4e67eb295ea4a0eb96d4 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.css.xml
@@ -88,6 +88,12 @@
   color: #44c;\n
 }\n
 \n
+.CodeMirror-merge-copy-reverse {\n
+  position: absolute;\n
+  cursor: pointer;\n
+  color: #44c;\n
+}\n
+\n
 .CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }\n
 .CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }\n
 \n
@@ -116,6 +122,20 @@
 .CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }\n
 .CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }\n
 .CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }\n
+\n
+.CodeMirror-merge-collapsed-widget:before {\n
+  content: "(...)";\n
+}\n
+.CodeMirror-merge-collapsed-widget {\n
+  cursor: pointer;\n
+  color: #88b;\n
+  background: #eef;\n
+  border: 1px solid #ddf;\n
+  font-size: 90%;\n
+  padding: 0 3px;\n
+  border-radius: 4px;\n
+}\n
+.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.js.xml
index 5f1786c6d2fa801b8889eaf26f15997a196460a7..89c4de0b78da9f2a19a5cdaeea4b2b77d1606815 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/merge.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts94001297.26</string> </value>
+            <value> <string>ts21897120.12</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,20 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("diff_match_patch"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "diff_match_patch"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror, diff_match_patch);\n
+})(function(CodeMirror, diff_match_patch) {\n
   "use strict";\n
-  // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL\n
-\n
   var Pos = CodeMirror.Pos;\n
   var svgNS = "http://www.w3.org/2000/svg";\n
 \n
@@ -45,13 +55,15 @@
          insert: "CodeMirror-merge-r-inserted",\n
          del: "CodeMirror-merge-r-deleted",\n
          connect: "CodeMirror-merge-r-connect"};\n
+    if (mv.options.connect == "align")\n
+      this.aligners = [];\n
   }\n
 \n
   DiffView.prototype = {\n
     constructor: DiffView,\n
     init: function(pane, orig, options) {\n
       this.edit = this.mv.edit;\n
-      this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options)));\n
+      this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));\n
 \n
       this.diff = getDiff(asString(orig), asString(options.value));\n
       this.diffOutOfDate = false;\n
@@ -69,6 +81,14 @@
       }\n
     }\n
   };\n
+\n
+  function ensureDiff(dv) {\n
+    if (dv.diffOutOfDate) {\n
+      dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());\n
+      dv.diffOutOfDate = false;\n
+      CodeMirror.signal(dv.edit, "updateDiff", dv.diff);\n
+    }\n
+  }\n
 \n
   function registerUpdate(dv) {\n
     var edit = {from: 0, to: 0, marked: []};\n
@@ -77,21 +97,17 @@
     function update(mode) {\n
       if (mode == "full") {\n
         if (dv.svg) clear(dv.svg);\n
-        clear(dv.copyButtons);\n
+        if (dv.copyButtons) clear(dv.copyButtons);\n
         clearMarks(dv.edit, edit.marked, dv.classes);\n
         clearMarks(dv.orig, orig.marked, dv.classes);\n
         edit.from = edit.to = orig.from = orig.to = 0;\n
       }\n
-      if (dv.diffOutOfDate) {\n
-        dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());\n
-        dv.diffOutOfDate = false;\n
-        CodeMirror.signal(dv.edit, "updateDiff", dv.diff);\n
-      }\n
+      ensureDiff(dv);\n
       if (dv.showDifferences) {\n
         updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);\n
         updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);\n
       }\n
-      drawConnectors(dv);\n
+      makeConnections(dv);\n
     }\n
     function set(slow) {\n
       clearTimeout(debounceChange);\n
@@ -106,6 +122,10 @@
     }\n
     dv.edit.on("change", change);\n
     dv.orig.on("change", change);\n
+    dv.edit.on("markerAdded", set);\n
+    dv.edit.on("markerCleared", set);\n
+    dv.orig.on("markerAdded", set);\n
+    dv.orig.on("markerCleared", set);\n
     dv.edit.on("viewportChange", set);\n
     dv.orig.on("viewportChange", set);\n
     update();\n
@@ -114,10 +134,10 @@
 \n
   function registerScroll(dv) {\n
     dv.edit.on("scroll", function() {\n
-      syncScroll(dv, DIFF_INSERT) && drawConnectors(dv);\n
+      syncScroll(dv, DIFF_INSERT) && makeConnections(dv);\n
     });\n
     dv.orig.on("scroll", function() {\n
-      syncScroll(dv, DIFF_DELETE) && drawConnectors(dv);\n
+      syncScroll(dv, DIFF_DELETE) && makeConnections(dv);\n
     });\n
   }\n
 \n
@@ -132,24 +152,29 @@
     // (to prevent feedback loops)\n
     if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;\n
 \n
-    var sInfo = editor.getScrollInfo(), halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;\n
-    var mid = editor.lineAtHeight(midY, "local");\n
-    var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT);\n
-    var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);\n
-    var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);\n
-    var ratio = (midY - off.top) / (off.bot - off.top);\n
-    var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);\n
-\n
-    var botDist, mix;\n
-    // Some careful tweaking to make sure no space is left out of view\n
-    // when scrolling to top or bottom.\n
-    if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {\n
-      targetPos = targetPos * mix + sInfo.top * (1 - mix);\n
-    } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {\n
-      var otherInfo = other.getScrollInfo();\n
-      var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;\n
-      if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)\n
-        targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);\n
+    var sInfo = editor.getScrollInfo();\n
+    if (dv.mv.options.connect == "align") {\n
+      targetPos = sInfo.top;\n
+    } else {\n
+      var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;\n
+      var mid = editor.lineAtHeight(midY, "local");\n
+      var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT);\n
+      var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);\n
+      var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);\n
+      var ratio = (midY - off.top) / (off.bot - off.top);\n
+      var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);\n
+\n
+      var botDist, mix;\n
+      // Some careful tweaking to make sure no space is left out of view\n
+      // when scrolling to top or bottom.\n
+      if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {\n
+        targetPos = targetPos * mix + sInfo.top * (1 - mix);\n
+      } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {\n
+        var otherInfo = other.getScrollInfo();\n
+        var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;\n
+        if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)\n
+          targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);\n
+      }\n
     }\n
 \n
     other.scrollTo(sInfo.left, targetPos);\n
@@ -167,7 +192,7 @@
 \n
   function setScrollLock(dv, val, action) {\n
     dv.lockScroll = val;\n
-    if (val && action != false) syncScroll(dv, DIFF_INSERT) && drawConnectors(dv);\n
+    if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);\n
     dv.lockButton.innerHTML = val ? "\\u21db\\u21da" : "\\u21db&nbsp;&nbsp;\\u21da";\n
   }\n
 \n
@@ -178,7 +203,7 @@
       var mark = arr[i];\n
       if (mark instanceof CodeMirror.TextMarker) {\n
         mark.clear();\n
-      } else {\n
+      } else if (mark.parent) {\n
         editor.removeLineClass(mark, "background", classes.chunk);\n
         editor.removeLineClass(mark, "background", classes.start);\n
         editor.removeLineClass(mark, "background", classes.end);\n
@@ -255,47 +280,108 @@
 \n
   // Updating the gap between editor and original\n
 \n
-  function drawConnectors(dv) {\n
+  function makeConnections(dv) {\n
     if (!dv.showDifferences) return;\n
+\n
+    var align = dv.mv.options.connect == "align";\n
+    if (align) {\n
+      if (!dv.orig.curOp) return dv.orig.operation(function() {\n
+        makeConnections(dv);\n
+      });\n
+      for (var i = 0; i < dv.aligners.length; i++)\n
+        dv.aligners[i].clear();\n
+      dv.aligners.length = 0;\n
+      var extraSpaceAbove = {edit: 0, orig: 0};\n
+    }\n
 \n
     if (dv.svg) {\n
       clear(dv.svg);\n
       var w = dv.gap.offsetWidth;\n
       attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);\n
     }\n
-    clear(dv.copyButtons);\n
+    if (dv.copyButtons) clear(dv.copyButtons);\n
 \n
-    var flip = dv.type == "left";\n
     var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();\n
     var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;\n
     iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {\n
-      if (topEdit > vpEdit.to || botEdit < vpEdit.from ||\n
-          topOrig > vpOrig.to || botOrig < vpOrig.from)\n
-        return;\n
-      var topLpx = dv.orig.heightAtLine(topOrig, "local") - sTopOrig, top = topLpx;\n
-      if (dv.svg) {\n
-        var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit;\n
-        if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }\n
-        var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;\n
-        var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;\n
-        if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }\n
-        var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;\n
-        var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;\n
-        attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),\n
-              "d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",\n
-              "class", dv.classes.connect);\n
+      if (topEdit <= vpEdit.to && botEdit >= vpEdit.from &&\n
+          topOrig <= vpOrig.to && botOrig >= vpOrig.from)\n
+        drawConnectorsForChunk(dv, topOrig, botOrig, topEdit, botEdit, sTopOrig, sTopEdit, w);\n
+      if (align && (topEdit <= vpEdit.to || topOrig <= vpOrig.to)) {\n
+        var above = (botEdit < vpEdit.from && botOrig < vpOrig.from);\n
+        alignChunks(dv, topOrig, botOrig, topEdit, botEdit, above && extraSpaceAbove);\n
       }\n
+    });\n
+    if (align) {\n
+      if (extraSpaceAbove.edit)\n
+        dv.aligners.push(padBelow(dv.edit, 0, extraSpaceAbove.edit));\n
+      if (extraSpaceAbove.orig)\n
+        dv.aligners.push(padBelow(dv.orig, 0, extraSpaceAbove.orig));\n
+    }\n
+  }\n
+\n
+  function drawConnectorsForChunk(dv, topOrig, botOrig, topEdit, botEdit, sTopOrig, sTopEdit, w) {\n
+    var flip = dv.type == "left";\n
+    var top = dv.orig.heightAtLine(topOrig, "local") - sTopOrig;\n
+    if (dv.svg) {\n
+      var topLpx = top;\n
+      var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit;\n
+      if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }\n
+      var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;\n
+      var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;\n
+      if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }\n
+      var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;\n
+      var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;\n
+      attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),\n
+            "d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",\n
+            "class", dv.classes.connect);\n
+    }\n
+    if (dv.copyButtons) {\n
       var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\\u21dd" : "\\u21dc",\n
                                                 "CodeMirror-merge-copy"));\n
-      copy.title = "Revert chunk";\n
+      var editOriginals = dv.mv.options.allowEditingOriginals;\n
+      copy.title = editOriginals ? "Push to left" : "Revert chunk";\n
       copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};\n
       copy.style.top = top + "px";\n
-    });\n
+\n
+      if (editOriginals) {\n
+        var topReverse = dv.orig.heightAtLine(topEdit, "local") - sTopEdit;\n
+        var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\\u21dd" : "\\u21dc",\n
+                                                         "CodeMirror-merge-copy-reverse"));\n
+        copyReverse.title = "Push to right";\n
+        copyReverse.chunk = {topEdit: topOrig, botEdit: botOrig, topOrig: topEdit, botOrig: botEdit};\n
+        copyReverse.style.top = topReverse + "px";\n
+        dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";\n
+      }\n
+    }\n
+  }\n
+\n
+  function alignChunks(dv, topOrig, botOrig, topEdit, botEdit, aboveViewport) {\n
+    var topOrigPx = dv.orig.heightAtLine(topOrig, "local");\n
+    var botOrigPx = dv.orig.heightAtLine(botOrig, "local");\n
+    var topEditPx = dv.edit.heightAtLine(topEdit, "local");\n
+    var botEditPx = dv.edit.heightAtLine(botEdit, "local");\n
+    var origH = botOrigPx -topOrigPx, editH = botEditPx - topEditPx;\n
+    var diff = editH - origH;\n
+    if (diff > 1) {\n
+      if (aboveViewport) aboveViewport.orig += diff;\n
+      else dv.aligners.push(padBelow(dv.orig, botOrig - 1, diff));\n
+    } else if (diff < -1) {\n
+      if (aboveViewport) aboveViewport.edit -= diff;\n
+      else dv.aligners.push(padBelow(dv.edit, botEdit - 1, -diff));\n
+    }\n
+    return 0;\n
   }\n
 \n
-  function copyChunk(dv, chunk) {\n
+  function padBelow(cm, line, size) {\n
+    var elt = document.createElement("div");\n
+    elt.style.height = size + "px"; elt.style.minWidth = "1px";\n
+    return cm.addLineWidget(line, elt, {height: size});\n
+  }\n
+\n
+  function copyChunk(dv, to, from, chunk) {\n
     if (dv.diffOutOfDate) return;\n
-    dv.edit.replaceRange(dv.orig.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),\n
+    to.replaceRange(from.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),\n
                          Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0));\n
   }\n
 \n
@@ -304,7 +390,15 @@
   var MergeView = CodeMirror.MergeView = function(node, options) {\n
     if (!(this instanceof MergeView)) return new MergeView(node, options);\n
 \n
+    this.options = options;\n
     var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;\n
+    if (origLeft && origRight) {\n
+      if (options.connect == "align")\n
+        throw new Error("connect: \\"align\\" is not supported for three-way merge views");\n
+      if (options.collapseIdentical)\n
+        throw new Error("collapseIdentical option is not supported for three-way merge views");\n
+    }\n
+\n
     var hasLeft = origLeft != null, hasRight = origRight != null;\n
     var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);\n
     var wrap = [], left = this.left = null, right = this.right = null;\n
@@ -329,15 +423,19 @@
     (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";\n
 \n
     wrap.push(elt("div", null, null, "height: 0; clear: both;"));\n
+\n
     var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));\n
     this.edit = CodeMirror(editPane, copyObj(options));\n
 \n
     if (left) left.init(leftPane, origLeft, options);\n
     if (right) right.init(rightPane, origRight, options);\n
+\n
+    if (options.collapseIdentical)\n
+      collapseIdenticalStretches(left || right, options.collapseIdentical);\n
 \n
     var onResize = function() {\n
-      if (left) drawConnectors(left);\n
-      if (right) drawConnectors(right);\n
+      if (left) makeConnections(left);\n
+      if (right) makeConnections(right);\n
     };\n
     CodeMirror.on(window, "resize", onResize);\n
     var resizeInterval = setInterval(function() {\n
@@ -351,16 +449,26 @@
     lock.title = "Toggle locked scrolling";\n
     var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");\n
     CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });\n
-    dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);\n
-    CodeMirror.on(dv.copyButtons, "click", function(e) {\n
-      var node = e.target || e.srcElement;\n
-      if (node.chunk) copyChunk(dv, node.chunk);\n
-    });\n
-    var gapElts = [dv.copyButtons, lockWrap];\n
-    var svg = document.createElementNS && document.createElementNS(svgNS, "svg");\n
-    if (svg && !svg.createSVGRect) svg = null;\n
-    dv.svg = svg;\n
-    if (svg) gapElts.push(svg);\n
+    var gapElts = [lockWrap];\n
+    if (dv.mv.options.revertButtons !== false) {\n
+      dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);\n
+      CodeMirror.on(dv.copyButtons, "click", function(e) {\n
+        var node = e.target || e.srcElement;\n
+        if (!node.chunk) return;\n
+        if (node.className == "CodeMirror-merge-copy-reverse") {\n
+          copyChunk(dv, dv.orig, dv.edit, node.chunk);\n
+          return;\n
+        }\n
+        copyChunk(dv, dv.edit, dv.orig, node.chunk);\n
+      });\n
+      gapElts.unshift(dv.copyButtons);\n
+    }\n
+    if (dv.mv.options.connect != "align") {\n
+      var svg = document.createElementNS && document.createElementNS(svgNS, "svg");\n
+      if (svg && !svg.createSVGRect) svg = null;\n
+      dv.svg = svg;\n
+      if (svg) gapElts.push(svg);\n
+    }\n
 \n
     return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");\n
   }\n
@@ -373,6 +481,12 @@
     setShowDifferences: function(val) {\n
       if (this.right) this.right.setShowDifferences(val);\n
       if (this.left) this.left.setShowDifferences(val);\n
+    },\n
+    rightChunks: function() {\n
+      return this.right && getChunks(this.right);\n
+    },\n
+    leftChunks: function() {\n
+      return this.left && getChunks(this.left);\n
     }\n
   };\n
 \n
@@ -422,6 +536,16 @@
     if (startEdit <= edit.line || startOrig <= orig.line)\n
       f(startOrig, orig.line + 1, startEdit, edit.line + 1);\n
   }\n
+\n
+  function getChunks(dv) {\n
+    ensureDiff(dv);\n
+    var collect = [];\n
+    iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {\n
+      collect.push({origFrom: topOrig, origTo: botOrig,\n
+                    editFrom: topEdit, editTo: botEdit});\n
+    });\n
+    return collect;\n
+  }\n
 \n
   function endOfLineClean(diff, i) {\n
     if (i == diff.length - 1) return true;\n
@@ -455,6 +579,46 @@
     });\n
     return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};\n
   }\n
+\n
+  function collapseSingle(cm, from, to) {\n
+    cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");\n
+    var widget = document.createElement("span");\n
+    widget.className = "CodeMirror-merge-collapsed-widget";\n
+    widget.title = "Identical text collapsed. Click to expand.";\n
+    var mark = cm.markText(Pos(from, 0), Pos(to - 1), {\n
+      inclusiveLeft: true,\n
+      inclusiveRight: true,\n
+      replacedWith: widget,\n
+      clearOnEnter: true\n
+    });\n
+    function clear() {\n
+      mark.clear();\n
+      cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");\n
+    }\n
+    widget.addEventListener("click", clear);\n
+    return {mark: mark, clear: clear};\n
+  }\n
+\n
+  function collapseStretch(dv, origStart, editStart, size) {\n
+    var mOrig = collapseSingle(dv.orig, origStart, origStart + size);\n
+    var mEdit = collapseSingle(dv.edit, editStart, editStart + size);\n
+    mOrig.mark.on("clear", function() { mEdit.clear(); });\n
+    mEdit.mark.on("clear", function() { mOrig.clear(); });\n
+  }\n
+\n
+  function collapseIdenticalStretches(dv, margin) {\n
+    if (typeof margin != "number") margin = 2;\n
+    var lastOrig = dv.orig.firstLine(), lastEdit = dv.edit.firstLine();\n
+    iterateChunks(dv.diff, function(topOrig, botOrig, _topEdit, botEdit) {\n
+      var identicalSize = topOrig - margin - lastOrig;\n
+      if (identicalSize > margin)\n
+        collapseStretch(dv, lastOrig, lastEdit, identicalSize);\n
+      lastOrig = botOrig + margin; lastEdit = botEdit + margin;\n
+    });\n
+    var bottomSize = dv.orig.lastLine() + 1 - lastOrig;\n
+    if (bottomSize > margin)\n
+      collapseStretch(dv, lastOrig, lastEdit, bottomSize);\n
+  }\n
 \n
   // General utilities\n
 \n
@@ -500,7 +664,7 @@
   function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }\n
   function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }\n
   function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -511,7 +675,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>18196</int> </value>
+            <value> <int>24684</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/loadmode.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/loadmode.js.xml
index 120fa3cb3535d9cc81b0c7fb7d03f6c350f81ba4..d9d981dd749e6071522cc2f56b2f345c60946faa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/loadmode.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/loadmode.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.72</string> </value>
+            <value> <string>ts21897115.91</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), "cjs");\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });\n
+  else // Plain browser env\n
+    mod(CodeMirror, "plain");\n
+})(function(CodeMirror, env) {\n
   if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";\n
 \n
   var loading = {};\n
@@ -49,21 +59,24 @@
     if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);\n
     if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);\n
 \n
-    var script = document.createElement("script");\n
-    script.src = CodeMirror.modeURL.replace(/%N/g, mode);\n
-    var others = document.getElementsByTagName("script")[0];\n
-    others.parentNode.insertBefore(script, others);\n
-    var list = loading[mode] = [cont];\n
-    var count = 0, poll = setInterval(function() {\n
-      if (++count > 100) return clearInterval(poll);\n
-      if (CodeMirror.modes.hasOwnProperty(mode)) {\n
-        clearInterval(poll);\n
-        loading[mode] = null;\n
+    var file = CodeMirror.modeURL.replace(/%N/g, mode);\n
+    if (env == "plain") {\n
+      var script = document.createElement("script");\n
+      script.src = file;\n
+      var others = document.getElementsByTagName("script")[0];\n
+      var list = loading[mode] = [cont];\n
+      CodeMirror.on(script, "load", function() {\n
         ensureDeps(mode, function() {\n
           for (var i = 0; i < list.length; ++i) list[i]();\n
         });\n
-      }\n
-    }, 200);\n
+      });\n
+      others.parentNode.insertBefore(script, others);\n
+    } else if (env == "cjs") {\n
+      require(file);\n
+      cont();\n
+    } else if (env == "amd") {\n
+      requirejs([file], cont);\n
+    }\n
   };\n
 \n
   CodeMirror.autoLoadMode = function(instance, mode) {\n
@@ -72,7 +85,7 @@
         instance.setOption("mode", instance.getOption("mode"));\n
       });\n
   };\n
-}());\n
+});\n
 
 
 ]]></string> </value>
@@ -83,7 +96,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1787</int> </value>
+            <value> <int>2277</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex.js.xml
index e42c31fd5135f0db60c9db0e16a6274edccf55cc..0ce7342826146d803f06c125007704f943396c99 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.58</string> </value>
+            <value> <string>ts21897116.0</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.multiplexingMode = function(outer /*, others */) {\n
   // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects\n
   var others = Array.prototype.slice.call(arguments, 1);\n
@@ -125,6 +138,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {\n
     }\n
   };\n
 };\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -135,7 +150,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3736</int> </value>
+            <value> <int>4197</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex_test.js.xml
index bef94cad2c2a59729aa6d4b0c1f34a91a2e32846..578c61731d9d2e2c65f86b794efa16d9c378e7c5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/multiplex_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.85</string> </value>
+            <value> <string>ts21897115.81</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   CodeMirror.defineMode("markdown_with_stex", function(){\n
     var inner = CodeMirror.getMode({}, "stex");\n
@@ -62,7 +65,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>682</int> </value>
+            <value> <int>810</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/overlay.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/overlay.js.xml
index 620f76756d4c6ef6067359e6b8aa202ec7ede06b..18d58b4aacde60005ee44976e226099b1145f895 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/overlay.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/overlay.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403077.95</string> </value>
+            <value> <string>ts21897115.72</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,23 +22,37 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Utility function that allows modes to be combined. The mode given\n
 // as the base argument takes care of most of the normal mode\n
 // functionality, but a second (typically simple) mode is used, which\n
 // can override the style of text. Both modes get to parse all of the\n
 // text, but when both assign a non-null style to a piece of code, the\n
-// overlay wins, unless the combine argument was true, in which case\n
-// the styles are combined.\n
+// overlay wins, unless the combine argument was true and not overridden,\n
+// or state.overlay.combineTokens was true, in which case the styles are\n
+// combined.\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
 \n
-// overlayParser is the old, deprecated name\n
-CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) {\n
+CodeMirror.overlayMode = function(base, overlay, combine) {\n
   return {\n
     startState: function() {\n
       return {\n
         base: CodeMirror.startState(base),\n
         overlay: CodeMirror.startState(overlay),\n
         basePos: 0, baseCur: null,\n
-        overlayPos: 0, overlayCur: null\n
+        overlayPos: 0, overlayCur: null,\n
+        streamSeen: null\n
       };\n
     },\n
     copyState: function(state) {\n
@@ -51,6 +65,12 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
     },\n
 \n
     token: function(stream, state) {\n
+      if (stream != state.streamSeen ||\n
+          Math.min(state.basePos, state.overlayPos) < stream.start) {\n
+        state.streamSeen = stream;\n
+        state.basePos = state.overlayPos = stream.start;\n
+      }\n
+\n
       if (stream.start == state.basePos) {\n
         state.baseCur = base.token(stream, state.base);\n
         state.basePos = stream.pos;\n
@@ -61,10 +81,14 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
         state.overlayPos = stream.pos;\n
       }\n
       stream.pos = Math.min(state.basePos, state.overlayPos);\n
-      if (stream.eol()) state.basePos = state.overlayPos = 0;\n
 \n
+      // state.overlay.combineTokens always takes precedence over combine,\n
+      // unless set to null\n
       if (state.overlayCur == null) return state.baseCur;\n
-      if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;\n
+      else if (state.baseCur != null &&\n
+               state.overlay.combineTokens ||\n
+               combine && state.overlay.combineTokens == null)\n
+        return state.baseCur + " " + state.overlayCur;\n
       else return state.overlayCur;\n
     },\n
 \n
@@ -81,6 +105,8 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
     }\n
   };\n
 };\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -91,7 +117,7 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2178</int> </value>
+            <value> <int>3021</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/simple.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/simple.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..109df7aafb9623f7db4e26da49ca17b8ce3a8c62
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/mode/simple.js.xml
@@ -0,0 +1,257 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897115.63</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>simple.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineSimpleMode = function(name, states) {\n
+    CodeMirror.defineMode(name, function(config) {\n
+      return CodeMirror.simpleMode(config, states);\n
+    });\n
+  };\n
+\n
+  CodeMirror.simpleMode = function(config, states) {\n
+    ensureState(states, "start");\n
+    var states_ = {}, meta = states.meta || {}, hasIndentation = false;\n
+    for (var state in states) if (state != meta && states.hasOwnProperty(state)) {\n
+      var list = states_[state] = [], orig = states[state];\n
+      for (var i = 0; i < orig.length; i++) {\n
+        var data = orig[i];\n
+        list.push(new Rule(data, states));\n
+        if (data.indent || data.dedent) hasIndentation = true;\n
+      }\n
+    }\n
+    var mode = {\n
+      startState: function() {\n
+        return {state: "start", pending: null,\n
+                local: null, localState: null,\n
+                indent: hasIndentation ? [] : null};\n
+      },\n
+      copyState: function(state) {\n
+        var s = {state: state.state, pending: state.pending,\n
+                 local: state.local, localState: null,\n
+                 indent: state.indent && state.indent.slice(0)};\n
+        if (state.localState)\n
+          s.localState = CodeMirror.copyState(state.local.mode, state.localState);\n
+        if (state.stack)\n
+          s.stack = state.stack.slice(0);\n
+        for (var pers = state.persistentStates; pers; pers = pers.next)\n
+          s.persistentStates = {mode: pers.mode,\n
+                                spec: pers.spec,\n
+                                state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),\n
+                                next: s.persistentStates};\n
+        return s;\n
+      },\n
+      token: tokenFunction(states_, config),\n
+      innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },\n
+      indent: indentFunction(states_, meta)\n
+    };\n
+    if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))\n
+      mode[prop] = meta[prop];\n
+    return mode;\n
+  };\n
+\n
+  function ensureState(states, name) {\n
+    if (!states.hasOwnProperty(name))\n
+      throw new Error("Undefined state " + name + "in simple mode");\n
+  }\n
+\n
+  function toRegex(val, caret) {\n
+    if (!val) return /(?:)/;\n
+    var flags = "";\n
+    if (val instanceof RegExp) {\n
+      if (val.ignoreCase) flags = "i";\n
+      val = val.source;\n
+    } else {\n
+      val = String(val);\n
+    }\n
+    return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);\n
+  }\n
+\n
+  function asToken(val) {\n
+    if (!val) return null;\n
+    if (typeof val == "string") return val.replace(/\\./g, " ");\n
+    var result = [];\n
+    for (var i = 0; i < val.length; i++)\n
+      result.push(val[i] && val[i].replace(/\\./g, " "));\n
+    return result;\n
+  }\n
+\n
+  function Rule(data, states) {\n
+    if (data.next || data.push) ensureState(states, data.next || data.push);\n
+    this.regex = toRegex(data.regex);\n
+    this.token = asToken(data.token);\n
+    this.data = data;\n
+  }\n
+\n
+  function tokenFunction(states, config) {\n
+    return function(stream, state) {\n
+      if (state.pending) {\n
+        var pend = state.pending.shift();\n
+        if (state.pending.length == 0) state.pending = null;\n
+        stream.pos += pend.text.length;\n
+        return pend.token;\n
+      }\n
+\n
+      if (state.local) {\n
+        if (state.local.end && stream.match(state.local.end)) {\n
+          var tok = state.local.endToken || null;\n
+          state.local = state.localState = null;\n
+          return tok;\n
+        } else {\n
+          var tok = state.local.mode.token(stream, state.localState), m;\n
+          if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))\n
+            stream.pos = stream.start + m.index;\n
+          return tok;\n
+        }\n
+      }\n
+\n
+      var curState = states[state.state];\n
+      for (var i = 0; i < curState.length; i++) {\n
+        var rule = curState[i];\n
+        var matches = stream.match(rule.regex);\n
+        if (matches) {\n
+          if (rule.data.next) {\n
+            state.state = rule.data.next;\n
+          } else if (rule.data.push) {\n
+            (state.stack || (state.stack = [])).push(state.state);\n
+            state.state = rule.data.push;\n
+          } else if (rule.data.pop && state.stack && state.stack.length) {\n
+            state.state = state.stack.pop();\n
+          }\n
+\n
+          if (rule.data.mode)\n
+            enterLocalMode(config, state, rule.data.mode, rule.token);\n
+          if (rule.data.indent)\n
+            state.indent.push(stream.indentation() + config.indentUnit);\n
+          if (rule.data.dedent)\n
+            state.indent.pop();\n
+          if (matches.length > 2) {\n
+            state.pending = [];\n
+            for (var j = 2; j < matches.length; j++)\n
+              if (matches[j])\n
+                state.pending.push({text: matches[j], token: rule.token[j - 1]});\n
+            stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));\n
+            return rule.token[0];\n
+          } else if (rule.token && rule.token.join) {\n
+            return rule.token[0];\n
+          } else {\n
+            return rule.token;\n
+          }\n
+        }\n
+      }\n
+      stream.next();\n
+      return null;\n
+    };\n
+  }\n
+\n
+  function cmp(a, b) {\n
+    if (a === b) return true;\n
+    if (!a || typeof a != "object" || !b || typeof b != "object") return false;\n
+    var props = 0;\n
+    for (var prop in a) if (a.hasOwnProperty(prop)) {\n
+      if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;\n
+      props++;\n
+    }\n
+    for (var prop in b) if (b.hasOwnProperty(prop)) props--;\n
+    return props == 0;\n
+  }\n
+\n
+  function enterLocalMode(config, state, spec, token) {\n
+    var pers;\n
+    if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)\n
+      if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;\n
+    var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);\n
+    var lState = pers ? pers.state : CodeMirror.startState(mode);\n
+    if (spec.persistent && !pers)\n
+      state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};\n
+\n
+    state.localState = lState;\n
+    state.local = {mode: mode,\n
+                   end: spec.end && toRegex(spec.end),\n
+                   endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),\n
+                   endToken: token && token.join ? token[token.length - 1] : token};\n
+  }\n
+\n
+  function indexOf(val, arr) {\n
+    for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;\n
+  }\n
+\n
+  function indentFunction(states, meta) {\n
+    return function(state, textAfter, line) {\n
+      if (state.local && state.local.mode.indent)\n
+        return state.local.mode.indent(state.localState, textAfter, line);\n
+      if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)\n
+        return CodeMirror.Pass;\n
+\n
+      var pos = state.indent.length - 1, rules = states[state.state];\n
+      scan: for (;;) {\n
+        for (var i = 0; i < rules.length; i++) {\n
+          var rule = rules[i];\n
+          if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {\n
+            var m = rule.regex.exec(textAfter);\n
+            if (m && m[0]) {\n
+              pos--;\n
+              if (rule.next || rule.push) rules = states[rule.next || rule.push];\n
+              textAfter = textAfter.slice(m[0].length);\n
+              continue scan;\n
+            }\n
+          }\n
+        }\n
+        break;\n
+      }\n
+      return pos < 0 ? 0 : state.indent[pos];\n
+    };\n
+  }\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>7862</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/colorize.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/colorize.js.xml
index 78d367d35c461ac918b999bb6fbdbe129dd69293..d2f01c7efd0379e697280c0126d4ed34c8d0ad4e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/colorize.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/colorize.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403071.8</string> </value>
+            <value> <string>ts21897122.18</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,18 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.colorize = (function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("./runmode"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "./runmode"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
 \n
   var isBlock = /^(p|li|div|h\\\\d|pre|blockquote|td)$/;\n
 \n
@@ -34,7 +45,7 @@ CodeMirror.colorize = (function() {\n
     }\n
   }\n
 \n
-  return function(collection, defaultMode) {\n
+  CodeMirror.colorize = function(collection, defaultMode) {\n
     if (!collection) collection = document.body.getElementsByTagName("pre");\n
 \n
     for (var i = 0; i < collection.length; ++i) {\n
@@ -50,7 +61,7 @@ CodeMirror.colorize = (function() {\n
       node.className += " cm-s-default";\n
     }\n
   };\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -61,7 +72,7 @@ CodeMirror.colorize = (function() {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>834</int> </value>
+            <value> <int>1303</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode-standalone.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode-standalone.js.xml
index 9659a833a2df944e30c86c337bbcab23c6b8daae..73b4d522afb9b24a3a177b61e53a7fa89a7efb01 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode-standalone.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode-standalone.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403071.91</string> </value>
+            <value> <string>ts21897122.07</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,8 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-/* Just enough of CodeMirror to run runMode under node.js */\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
 \n
 window.CodeMirror = {};\n
 \n
@@ -97,7 +98,11 @@ CodeMirror.startState = function (mode, a1, a2) {\n
 };\n
 \n
 var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};\n
-CodeMirror.defineMode = function (name, mode) { modes[name] = mode; };\n
+CodeMirror.defineMode = function (name, mode) {\n
+  if (arguments.length > 2)\n
+    mode.dependencies = Array.prototype.slice.call(arguments, 2);\n
+  modes[name] = mode;\n
+};\n
 CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };\n
 CodeMirror.resolveMode = function(spec) {\n
   if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {\n
@@ -165,6 +170,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) {\n
   for (var i = 0, e = lines.length; i < e; ++i) {\n
     if (i) callback("\\n");\n
     var stream = new CodeMirror.StringStream(lines[i]);\n
+    if (!stream.string && mode.blankLine) mode.blankLine(state);\n
     while (!stream.eol()) {\n
       var style = mode.token(stream, state);\n
       callback(stream.current(), style, i, stream.start, state);\n
@@ -183,7 +189,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5075</int> </value>
+            <value> <int>5302</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.js.xml
index adf404177c2197eeaa3674f6a5d13ababe75b0cb..914f40442cf9598ca63c75ae0986571eae62239b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.03</string> </value>
+            <value> <string>ts21897121.98</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.runMode = function(string, modespec, callback, options) {\n
   var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);\n
   var ie = /MSIE \\d/.test(navigator.userAgent);\n
@@ -71,6 +84,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {\n
   for (var i = 0, e = lines.length; i < e; ++i) {\n
     if (i) callback("\\n");\n
     var stream = new CodeMirror.StringStream(lines[i]);\n
+    if (!stream.string && mode.blankLine) mode.blankLine(state);\n
     while (!stream.eol()) {\n
       var style = mode.token(stream, state);\n
       callback(stream.current(), style, i, stream.start, state);\n
@@ -78,6 +92,8 @@ CodeMirror.runMode = function(string, modespec, callback, options) {\n
     }\n
   }\n
 };\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -88,7 +104,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1975</int> </value>
+            <value> <int>2501</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.node.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.node.js.xml
index 21f1c0a7120182f9df59f5355ef5f6cf30f49d9f..c97684f30a869c497d1158479e7f241115e12210 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.node.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/runmode/runmode.node.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403071.7</string> </value>
+            <value> <string>ts21897122.25</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,8 +22,13 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /* Just enough of CodeMirror to run runMode under node.js */\n
 \n
+// declare global: StringStream\n
+\n
 function splitLines(string){ return string.split(/\\r?\\n|\\r/); };\n
 \n
 function StringStream(string) {\n
@@ -93,10 +98,8 @@ exports.startState = function(mode, a1, a2) {\n
 \n
 var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};\n
 exports.defineMode = function(name, mode) {\n
-  if (arguments.length > 2) {\n
-    mode.dependencies = [];\n
-    for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);\n
-  }\n
+  if (arguments.length > 2)\n
+    mode.dependencies = Array.prototype.slice.call(arguments, 2);\n
   modes[name] = mode;\n
 };\n
 exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };\n
@@ -129,6 +132,7 @@ exports.runMode = function(string, modespec, callback, options) {\n
   for (var i = 0, e = lines.length; i < e; ++i) {\n
     if (i) callback("\\n");\n
     var stream = new exports.StringStream(lines[i]);\n
+    if (!stream.string && mode.blankLine) mode.blankLine(state);\n
     while (!stream.eol()) {\n
       var style = mode.token(stream, state);\n
       callback(stream.current(), style, i, stream.start, state);\n
@@ -136,6 +140,8 @@ exports.runMode = function(string, modespec, callback, options) {\n
     }\n
   }\n
 };\n
+\n
+require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];\n
 
 
 ]]></string> </value>
@@ -146,7 +152,7 @@ exports.runMode = function(string, modespec, callback, options) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4008</int> </value>
+            <value> <int>4289</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/annotatescrollbar.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/annotatescrollbar.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e26790b65cdc4e56013ed7b479299271f8d81b5e
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/annotatescrollbar.js.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897118.59</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>annotatescrollbar.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineExtension("annotateScrollbar", function(className) {\n
+    return new Annotation(this, className);\n
+  });\n
+\n
+  function Annotation(cm, className) {\n
+    this.cm = cm;\n
+    this.className = className;\n
+    this.annotations = [];\n
+    this.div = cm.getWrapperElement().appendChild(document.createElement("div"));\n
+    this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";\n
+    this.computeScale();\n
+\n
+    var self = this;\n
+    cm.on("refresh", this.resizeHandler = function(){\n
+      if (self.computeScale()) self.redraw();\n
+    });\n
+  }\n
+\n
+  Annotation.prototype.computeScale = function() {\n
+    var cm = this.cm;\n
+    var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight) /\n
+      cm.heightAtLine(cm.lastLine() + 1, "local");\n
+    if (hScale != this.hScale) {\n
+      this.hScale = hScale;\n
+      return true;\n
+    }\n
+  };\n
+\n
+  Annotation.prototype.update = function(annotations) {\n
+    this.annotations = annotations;\n
+    this.redraw();\n
+  };\n
+\n
+  Annotation.prototype.redraw = function() {\n
+    var cm = this.cm, hScale = this.hScale;\n
+    if (!cm.display.barWidth) return;\n
+\n
+    var frag = document.createDocumentFragment(), anns = this.annotations;\n
+    for (var i = 0, nextTop; i < anns.length; i++) {\n
+      var ann = anns[i];\n
+      var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;\n
+      var bottom = cm.charCoords(ann.to, "local").bottom * hScale;\n
+      while (i < anns.length - 1) {\n
+        nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;\n
+        if (nextTop > bottom + .9) break;\n
+        ann = anns[++i];\n
+        bottom = cm.charCoords(ann.to, "local").bottom * hScale;\n
+      }\n
+      var height = Math.max(bottom - top, 3);\n
+\n
+      var elt = frag.appendChild(document.createElement("div"));\n
+      elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: " + top + "px; height: " + height + "px";\n
+      elt.className = this.className;\n
+    }\n
+    this.div.textContent = "";\n
+    this.div.appendChild(frag);\n
+  };\n
+\n
+  Annotation.prototype.clear = function() {\n
+    this.cm.off("refresh", this.resizeHandler);\n
+    this.div.parentNode.removeChild(this.div);\n
+  };\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2660</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/scrollpastend.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/scrollpastend.js.xml
index c811312537ff23d65de0897e5d0c9b01beb4890b..814b8499c8268b4e6cdfee0ca7ae168effbe8ce6 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/scrollpastend.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/scrollpastend.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.34</string> </value>
+            <value> <string>ts21897118.22</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {\n
@@ -57,7 +67,7 @@
       cm.setSize();\n
     }\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -68,7 +78,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1067</int> </value>
+            <value> <int>1492</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/simplescrollbars.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/simplescrollbars.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c15f3734ac0b9de690f23428e8397454348b5da2
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/simplescrollbars.css.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>simplescrollbars.css</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>.CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div {\n
+  position: absolute;\n
+  background: #ccc;\n
+  -moz-box-sizing: border-box;\n
+  box-sizing: border-box;\n
+  border: 1px solid #bbb;\n
+  border-radius: 2px;\n
+}\n
+\n
+.CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical {\n
+  position: absolute;\n
+  z-index: 6;\n
+  background: #eee;\n
+}\n
+\n
+.CodeMirror-simplescroll-horizontal {\n
+  bottom: 0; left: 0;\n
+  height: 8px;\n
+}\n
+.CodeMirror-simplescroll-horizontal div {\n
+  bottom: 0;\n
+  height: 100%;\n
+}\n
+\n
+.CodeMirror-simplescroll-vertical {\n
+  right: 0; top: 0;\n
+  width: 8px;\n
+}\n
+.CodeMirror-simplescroll-vertical div {\n
+  right: 0;\n
+  width: 100%;\n
+}\n
+\n
+\n
+.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler {\n
+  display: none;\n
+}\n
+\n
+.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {\n
+  position: absolute;\n
+  background: #bcd;\n
+  border-radius: 3px;\n
+}\n
+\n
+.CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical {\n
+  position: absolute;\n
+  z-index: 6;\n
+}\n
+\n
+.CodeMirror-overlayscroll-horizontal {\n
+  bottom: 0; left: 0;\n
+  height: 6px;\n
+}\n
+.CodeMirror-overlayscroll-horizontal div {\n
+  bottom: 0;\n
+  height: 100%;\n
+}\n
+\n
+.CodeMirror-overlayscroll-vertical {\n
+  right: 0; top: 0;\n
+  width: 6px;\n
+}\n
+.CodeMirror-overlayscroll-vertical div {\n
+  right: 0;\n
+  width: 100%;\n
+}\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/simplescrollbars.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/simplescrollbars.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4d7772c41e2407c9e3655eead9d35f4a20b00549
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/scroll/simplescrollbars.js.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897118.5</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>simplescrollbars.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  function Bar(cls, orientation, scroll) {\n
+    this.orientation = orientation;\n
+    this.scroll = scroll;\n
+    this.screen = this.total = this.size = 1;\n
+    this.pos = 0;\n
+\n
+    this.node = document.createElement("div");\n
+    this.node.className = cls + "-" + orientation;\n
+    this.inner = this.node.appendChild(document.createElement("div"));\n
+\n
+    var self = this;\n
+    CodeMirror.on(this.inner, "mousedown", function(e) {\n
+      if (e.which != 1) return;\n
+      CodeMirror.e_preventDefault(e);\n
+      var axis = self.orientation == "horizontal" ? "pageX" : "pageY";\n
+      var start = e[axis], startpos = self.pos;\n
+      function move(e) {\n
+        if (e.which != 1) {\n
+          CodeMirror.off(document, "mousemove", move);\n
+          return;\n
+        }\n
+        self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));\n
+      }\n
+      CodeMirror.on(document, "mousemove", move);\n
+    });\n
+\n
+    CodeMirror.on(this.node, "click", function(e) {\n
+      CodeMirror.e_preventDefault(e);\n
+      var innerBox = self.inner.getBoundingClientRect(), where;\n
+      if (self.orientation == "horizontal")\n
+        where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;\n
+      else\n
+        where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;\n
+      self.moveTo(self.pos + where * self.screen);\n
+    });\n
+\n
+    function onWheel(e) {\n
+      var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];\n
+      var oldPos = self.pos;\n
+      self.moveTo(self.pos + moved);\n
+      if (self.pos != oldPos) CodeMirror.e_preventDefault(e);\n
+    }\n
+    CodeMirror.on(this.node, "mousewheel", onWheel);\n
+    CodeMirror.on(this.node, "DOMMouseScroll", onWheel);\n
+  }\n
+\n
+  Bar.prototype.moveTo = function(pos, update) {\n
+    if (pos < 0) pos = 0;\n
+    if (pos > this.total - this.screen) pos = this.total - this.screen;\n
+    if (pos == this.pos) return;\n
+    this.pos = pos;\n
+    this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =\n
+      (pos * (this.size / this.total)) + "px";\n
+    if (update !== false) this.scroll(pos, this.orientation);\n
+  };\n
+\n
+  Bar.prototype.update = function(scrollSize, clientSize, barSize) {\n
+    this.screen = clientSize;\n
+    this.total = scrollSize;\n
+    this.size = barSize;\n
+\n
+    // FIXME clip to min size?\n
+    this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =\n
+      this.screen * (this.size / this.total) + "px";\n
+    this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =\n
+      this.pos * (this.size / this.total) + "px";\n
+  };\n
+\n
+  function SimpleScrollbars(cls, place, scroll) {\n
+    this.addClass = cls;\n
+    this.horiz = new Bar(cls, "horizontal", scroll);\n
+    place(this.horiz.node);\n
+    this.vert = new Bar(cls, "vertical", scroll);\n
+    place(this.vert.node);\n
+    this.width = null;\n
+  }\n
+\n
+  SimpleScrollbars.prototype.update = function(measure) {\n
+    if (this.width == null) {\n
+      var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;\n
+      if (style) this.width = parseInt(style.height);\n
+    }\n
+    var width = this.width || 0;\n
+\n
+    var needsH = measure.scrollWidth > measure.clientWidth + 1;\n
+    var needsV = measure.scrollHeight > measure.clientHeight + 1;\n
+    this.vert.node.style.display = needsV ? "block" : "none";\n
+    this.horiz.node.style.display = needsH ? "block" : "none";\n
+\n
+    if (needsV) {\n
+      this.vert.update(measure.scrollHeight, measure.clientHeight,\n
+                       measure.viewHeight - (needsH ? width : 0));\n
+      this.vert.node.style.display = "block";\n
+      this.vert.node.style.bottom = needsH ? width + "px" : "0";\n
+    }\n
+    if (needsH) {\n
+      this.horiz.update(measure.scrollWidth, measure.clientWidth,\n
+                        measure.viewWidth - (needsV ? width : 0) - measure.barLeft);\n
+      this.horiz.node.style.right = needsV ? width + "px" : "0";\n
+      this.horiz.node.style.left = measure.barLeft + "px";\n
+    }\n
+\n
+    return {right: needsV ? width : 0, bottom: needsH ? width : 0};\n
+  };\n
+\n
+  SimpleScrollbars.prototype.setScrollTop = function(pos) {\n
+    this.vert.moveTo(pos, false);\n
+  };\n
+\n
+  SimpleScrollbars.prototype.setScrollLeft = function(pos) {\n
+    this.horiz.moveTo(pos, false);\n
+  };\n
+\n
+  SimpleScrollbars.prototype.clear = function() {\n
+    var parent = this.horiz.node.parentNode;\n
+    parent.removeChild(this.horiz.node);\n
+    parent.removeChild(this.vert.node);\n
+  };\n
+\n
+  CodeMirror.scrollbarModel.simple = function(place, scroll) {\n
+    return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);\n
+  };\n
+  CodeMirror.scrollbarModel.overlay = function(place, scroll) {\n
+    return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);\n
+  };\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>5126</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/match-highlighter.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/match-highlighter.js.xml
index 38791a927b2d958c2b9c2870c977b255b893e08c..b858047f99394dd1a1f6801ddf9a4b44726647ac 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/match-highlighter.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/match-highlighter.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.44</string> </value>
+            <value> <string>ts21897121.25</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Highlighting text that matches the selection\n
 //\n
 // Defines an option highlightSelectionMatches, which, when enabled,\n
@@ -29,17 +32,30 @@
 // document.\n
 //\n
 // The option can be set to true to simply enable it, or to a\n
-// {minChars, style, showToken} object to explicitly configure it.\n
-// minChars is the minimum amount of characters that should be\n
+// {minChars, style, wordsOnly, showToken, delay} object to explicitly\n
+// configure it. minChars is the minimum amount of characters that should be\n
 // selected for the behavior to occur, and style is the token style to\n
 // apply to the matches. This will be prefixed by "cm-" to create an\n
-// actual CSS class name. showToken, when enabled, will cause the\n
-// current token to be highlighted when nothing is selected.\n
+// actual CSS class name. If wordsOnly is enabled, the matches will be\n
+// highlighted only if the selected text is a word. showToken, when enabled,\n
+// will cause the current token to be highlighted when nothing is selected.\n
+// delay is used to specify how much time to wait, in milliseconds, before\n
+// highlighting the matches.\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
 \n
-(function() {\n
   var DEFAULT_MIN_CHARS = 2;\n
   var DEFAULT_TOKEN_STYLE = "matchhighlight";\n
   var DEFAULT_DELAY = 100;\n
+  var DEFAULT_WORDS_ONLY = false;\n
 \n
   function State(options) {\n
     if (typeof options == "object") {\n
@@ -47,10 +63,12 @@
       this.style = options.style;\n
       this.showToken = options.showToken;\n
       this.delay = options.delay;\n
+      this.wordsOnly = options.wordsOnly;\n
     }\n
     if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;\n
     if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;\n
     if (this.delay == null) this.delay = DEFAULT_DELAY;\n
+    if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;\n
     this.overlay = this.timeout = null;\n
   }\n
 \n
@@ -91,12 +109,31 @@
           cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));\n
         return;\n
       }\n
-      if (cm.getCursor("head").line != cm.getCursor("anchor").line) return;\n
-      var selection = cm.getSelection().replace(/^\\s+|\\s+$/g, "");\n
+      var from = cm.getCursor("from"), to = cm.getCursor("to");\n
+      if (from.line != to.line) return;\n
+      if (state.wordsOnly && !isWord(cm, from, to)) return;\n
+      var selection = cm.getRange(from, to).replace(/^\\s+|\\s+$/g, "");\n
       if (selection.length >= state.minChars)\n
         cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));\n
     });\n
   }\n
+\n
+  function isWord(cm, from, to) {\n
+    var str = cm.getRange(from, to);\n
+    if (str.match(/^\\w+$/) !== null) {\n
+        if (from.ch > 0) {\n
+            var pos = {line: from.line, ch: from.ch - 1};\n
+            var chr = cm.getRange(pos, from);\n
+            if (chr.match(/\\W/) === null) return false;\n
+        }\n
+        if (to.ch < cm.getLine(from.line).length) {\n
+            var pos = {line: to.line, ch: to.ch + 1};\n
+            var chr = cm.getRange(to, pos);\n
+            if (chr.match(/\\W/) === null) return false;\n
+        }\n
+        return true;\n
+    } else return false;\n
+  }\n
 \n
   function boundariesAround(stream, re) {\n
     return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&\n
@@ -112,7 +149,7 @@
       stream.skipTo(query.charAt(0)) || stream.skipToEnd();\n
     }};\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -123,7 +160,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3471</int> </value>
+            <value> <int>4943</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/matchesonscrollbar.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/matchesonscrollbar.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..32afd1d0b0d9def6d6fb58981e3ab155c2bcf1e8
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/matchesonscrollbar.css.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>matchesonscrollbar.css</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>.CodeMirror-search-match {\n
+  background: gold;\n
+  border-top: 1px solid orange;\n
+  border-bottom: 1px solid orange;\n
+  -moz-box-sizing: border-box;\n
+  box-sizing: border-box;\n
+  opacity: .5;\n
+}\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/matchesonscrollbar.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/matchesonscrollbar.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b87f72075ce4ffb7839d6c01d73cc63650c07027
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/matchesonscrollbar.js.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897121.73</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>matchesonscrollbar.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, className) {\n
+    return new SearchAnnotation(this, query, caseFold, className);\n
+  });\n
+\n
+  function SearchAnnotation(cm, query, caseFold, className) {\n
+    this.cm = cm;\n
+    this.annotation = cm.annotateScrollbar(className || "CodeMirror-search-match");\n
+    this.query = query;\n
+    this.caseFold = caseFold;\n
+    this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};\n
+    this.matches = [];\n
+    this.update = null;\n
+\n
+    this.findMatches();\n
+    this.annotation.update(this.matches);\n
+\n
+    var self = this;\n
+    cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });\n
+  }\n
+\n
+  var MAX_MATCHES = 1000;\n
+\n
+  SearchAnnotation.prototype.findMatches = function() {\n
+    if (!this.gap) return;\n
+    for (var i = 0; i < this.matches.length; i++) {\n
+      var match = this.matches[i];\n
+      if (match.from.line >= this.gap.to) break;\n
+      if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);\n
+    }\n
+    var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);\n
+    while (cursor.findNext()) {\n
+      var match = {from: cursor.from(), to: cursor.to()};\n
+      if (match.from.line >= this.gap.to) break;\n
+      this.matches.splice(i++, 0, match);\n
+      if (this.matches.length > MAX_MATCHES) break;\n
+    }\n
+    this.gap = null;\n
+  };\n
+\n
+  function offsetLine(line, changeStart, sizeChange) {\n
+    if (line <= changeStart) return line;\n
+    return Math.max(changeStart, line + sizeChange);\n
+  }\n
+\n
+  SearchAnnotation.prototype.onChange = function(change) {\n
+    var startLine = change.from.line;\n
+    var endLine = CodeMirror.changeEnd(change).line;\n
+    var sizeChange = endLine - change.to.line;\n
+    if (this.gap) {\n
+      this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);\n
+      this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);\n
+    } else {\n
+      this.gap = {from: change.from.line, to: endLine + 1};\n
+    }\n
+\n
+    if (sizeChange) for (var i = 0; i < this.matches.length; i++) {\n
+      var match = this.matches[i];\n
+      var newFrom = offsetLine(match.from.line, startLine, sizeChange);\n
+      if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);\n
+      var newTo = offsetLine(match.to.line, startLine, sizeChange);\n
+      if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);\n
+    }\n
+    clearTimeout(this.update);\n
+    var self = this;\n
+    this.update = setTimeout(function() { self.updateAfterChange(); }, 250);\n
+  };\n
+\n
+  SearchAnnotation.prototype.updateAfterChange = function() {\n
+    this.findMatches();\n
+    this.annotation.update(this.matches);\n
+  };\n
+\n
+  SearchAnnotation.prototype.clear = function() {\n
+    this.cm.off("change", this.changeHandler);\n
+    this.annotation.clear();\n
+  };\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3420</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/search.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/search.js.xml
index 324e9c2039c08b84726952757f94db04ac22c8cc..2a42a84e24ffb16c3e6cb872f2f86e77fcb75d3f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/search.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/search.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.35</string> </value>
+            <value> <string>ts21897121.46</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Define search commands. Depends on dialog.js or another\n
 // implementation of the openDialog method.\n
 \n
@@ -30,28 +33,31 @@
 // replace by making sure the match is no longer selected when hitting\n
 // Ctrl-G.\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
   function searchOverlay(query, caseInsensitive) {\n
-    var startChar;\n
-    if (typeof query == "string") {\n
-      startChar = query.charAt(0);\n
-      query = new RegExp("^" + query.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, "\\\\$&"),\n
-                         caseInsensitive ? "i" : "");\n
-    } else {\n
-      query = new RegExp("^(?:" + query.source + ")", query.ignoreCase ? "i" : "");\n
-    }\n
-    if (typeof query == "string") return {token: function(stream) {\n
-      if (stream.match(query)) return "searching";\n
-      stream.next();\n
-      stream.skipTo(query.charAt(0)) || stream.skipToEnd();\n
-    }};\n
+    if (typeof query == "string")\n
+      query = new RegExp(query.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, "\\\\$&"), caseInsensitive ? "gi" : "g");\n
+    else if (!query.global)\n
+      query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");\n
+\n
     return {token: function(stream) {\n
-      if (stream.match(query)) return "searching";\n
-      while (!stream.eol()) {\n
-        stream.next();\n
-        if (startChar)\n
-          stream.skipTo(startChar) || stream.skipToEnd();\n
-        if (stream.match(query, false)) break;\n
+      query.lastIndex = stream.pos;\n
+      var match = query.exec(stream.string);\n
+      if (match && match.index == stream.pos) {\n
+        stream.pos += match[0].length;\n
+        return "searching";\n
+      } else if (match) {\n
+        stream.pos = match.index;\n
+      } else {\n
+        stream.skipToEnd();\n
       }\n
     }};\n
   }\n
@@ -81,15 +87,15 @@
   function parseQuery(query) {\n
     var isRE = query.match(/^\\/(.*)\\/([a-z]*)$/);\n
     if (isRE) {\n
-      query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i");\n
-      if (query.test("")) query = /x^/;\n
-    } else if (query == "") {\n
-      query = /x^/;\n
+      try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }\n
+      catch(e) {} // Not a regular expression after all, do a string search\n
     }\n
+    if (typeof query == "string" ? query == "" : query.test(""))\n
+      query = /x^/;\n
     return query;\n
   }\n
   var queryDialog =\n
-    \'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>\';\n
+    \'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>\';\n
   function doSearch(cm, rev) {\n
     var state = getSearchState(cm);\n
     if (state.query) return findNext(cm, rev);\n
@@ -98,8 +104,12 @@
         if (!query || state.query) return;\n
         state.query = parseQuery(query);\n
         cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));\n
-        state.overlay = searchOverlay(state.query);\n
+        state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));\n
         cm.addOverlay(state.overlay);\n
+        if (cm.showMatchesOnScrollbar) {\n
+          if (state.annotate) { state.annotate.clear(); state.annotate = null; }\n
+          state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));\n
+        }\n
         state.posFrom = state.posTo = cm.getCursor();\n
         findNext(cm, rev);\n
       });\n
@@ -121,13 +131,15 @@
     if (!state.query) return;\n
     state.query = null;\n
     cm.removeOverlay(state.overlay);\n
+    if (state.annotate) { state.annotate.clear(); state.annotate = null; }\n
   });}\n
 \n
   var replaceQueryDialog =\n
-    \'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>\';\n
-  var replacementQueryDialog = \'With: <input type="text" style="width: 10em"/>\';\n
+    \'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>\';\n
+  var replacementQueryDialog = \'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>\';\n
   var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";\n
   function replace(cm, all) {\n
+    if (cm.getOption("readOnly")) return;\n
     dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {\n
       if (!query) return;\n
       query = parseQuery(query);\n
@@ -173,7 +185,7 @@
   CodeMirror.commands.clearSearch = clearSearch;\n
   CodeMirror.commands.replace = replace;\n
   CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -184,7 +196,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6199</int> </value>
+            <value> <int>7128</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/searchcursor.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/searchcursor.js.xml
index c318bf879bf340ce501c0cfadad6f0ff4677e0c5..e5c47b409623c655e8721ee64781885217ea46cd 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/searchcursor.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/search/searchcursor.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.24</string> </value>
+            <value> <string>ts21897121.6</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,18 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function(){\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
   var Pos = CodeMirror.Pos;\n
 \n
   function SearchCursor(doc, query, pos, caseFold) {\n
@@ -120,7 +131,7 @@
             var from = Pos(pos.line, cut);\n
             for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)\n
               if (target[i] != fold(doc.getLine(ln))) return;\n
-            if (doc.getLine(ln).slice(0, origTarget[last].length) != target[last]) return;\n
+            if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;\n
             return {from: from, to: Pos(ln, origTarget[last].length)};\n
           }\n
         };\n
@@ -188,7 +199,18 @@
   CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {\n
     return new SearchCursor(this, query, pos, caseFold);\n
   });\n
-})();\n
+\n
+  CodeMirror.defineExtension("selectMatches", function(query, caseFold) {\n
+    var ranges = [], next;\n
+    var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);\n
+    while (next = cur.findNext()) {\n
+      if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;\n
+      ranges.push({anchor: cur.from(), head: cur.to()});\n
+    }\n
+    if (ranges.length)\n
+      this.setSelections(ranges, 0);\n
+  });\n
+});\n
 
 
 ]]></string> </value>
@@ -199,7 +221,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6856</int> </value>
+            <value> <int>7720</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/active-line.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/active-line.js.xml
index d3fd4b45f2445319b3972a072fd523427a790357..d4c7637c567709e44a60736d058ed0d2582ed5ef 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/active-line.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/active-line.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403073.85</string> </value>
+            <value> <string>ts21897119.76</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,13 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Because sometimes you need to style the cursor\'s line.\n
 //\n
 // Adds an option \'styleActiveLine\' which, when enabled, gives the\n
 // active line\'s wrapping <div> the CSS class "CodeMirror-activeline",\n
 // and gives its background <div> the class "CodeMirror-activeline-background".\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
   var WRAP_CLASS = "CodeMirror-activeline";\n
   var BACK_CLASS = "CodeMirror-activeline-background";\n
@@ -36,37 +46,53 @@
   CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {\n
     var prev = old && old != CodeMirror.Init;\n
     if (val && !prev) {\n
-      updateActiveLine(cm, cm.getCursor().line);\n
+      cm.state.activeLines = [];\n
+      updateActiveLines(cm, cm.listSelections());\n
       cm.on("beforeSelectionChange", selectionChange);\n
     } else if (!val && prev) {\n
       cm.off("beforeSelectionChange", selectionChange);\n
-      clearActiveLine(cm);\n
-      delete cm.state.activeLine;\n
+      clearActiveLines(cm);\n
+      delete cm.state.activeLines;\n
     }\n
   });\n
 \n
-  function clearActiveLine(cm) {\n
-    if ("activeLine" in cm.state) {\n
-      cm.removeLineClass(cm.state.activeLine, "wrap", WRAP_CLASS);\n
-      cm.removeLineClass(cm.state.activeLine, "background", BACK_CLASS);\n
+  function clearActiveLines(cm) {\n
+    for (var i = 0; i < cm.state.activeLines.length; i++) {\n
+      cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);\n
+      cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);\n
     }\n
   }\n
 \n
-  function updateActiveLine(cm, selectedLine) {\n
-    var line = cm.getLineHandleVisualStart(selectedLine);\n
-    if (cm.state.activeLine == line) return;\n
+  function sameArray(a, b) {\n
+    if (a.length != b.length) return false;\n
+    for (var i = 0; i < a.length; i++)\n
+      if (a[i] != b[i]) return false;\n
+    return true;\n
+  }\n
+\n
+  function updateActiveLines(cm, ranges) {\n
+    var active = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var range = ranges[i];\n
+      if (!range.empty()) continue;\n
+      var line = cm.getLineHandleVisualStart(range.head.line);\n
+      if (active[active.length - 1] != line) active.push(line);\n
+    }\n
+    if (sameArray(cm.state.activeLines, active)) return;\n
     cm.operation(function() {\n
-      clearActiveLine(cm);\n
-      cm.addLineClass(line, "wrap", WRAP_CLASS);\n
-      cm.addLineClass(line, "background", BACK_CLASS);\n
-      cm.state.activeLine = line;\n
+      clearActiveLines(cm);\n
+      for (var i = 0; i < active.length; i++) {\n
+        cm.addLineClass(active[i], "wrap", WRAP_CLASS);\n
+        cm.addLineClass(active[i], "background", BACK_CLASS);\n
+      }\n
+      cm.state.activeLines = active;\n
     });\n
   }\n
 \n
   function selectionChange(cm, sel) {\n
-    updateActiveLine(cm, sel.head.line);\n
+    updateActiveLines(cm, sel.ranges);\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -77,7 +103,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1490</int> </value>
+            <value> <int>2442</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/mark-selection.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/mark-selection.js.xml
index 38ba1c1c584ba8d6d9e5e5daff8c949a403f9eb3..62191e1a27cc2357b3586d1fe1d91bf56e11985c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/mark-selection.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/selection/mark-selection.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403074.08</string> </value>
+            <value> <string>ts21897119.62</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,13 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Because sometimes you need to mark the selected *text*.\n
 //\n
 // Adds an option \'styleSelectedText\' which, when enabled, gives\n
 // selected text the CSS class given as option value, or\n
 // "CodeMirror-selectedtext" when the value is not a string.\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {\n
@@ -58,10 +68,7 @@
 \n
   var CHUNK_SIZE = 8;\n
   var Pos = CodeMirror.Pos;\n
-\n
-  function cmp(pos1, pos2) {\n
-    return pos1.line - pos2.line || pos1.ch - pos2.ch;\n
-  }\n
+  var cmp = CodeMirror.cmpPos;\n
 \n
   function coverRange(cm, from, to, addAt) {\n
     if (cmp(from, to) == 0) return;\n
@@ -87,13 +94,16 @@
 \n
   function reset(cm) {\n
     clear(cm);\n
-    var from = cm.getCursor("start"), to = cm.getCursor("end");\n
-    coverRange(cm, from, to);\n
+    var ranges = cm.listSelections();\n
+    for (var i = 0; i < ranges.length; i++)\n
+      coverRange(cm, ranges[i].from(), ranges[i].to());\n
   }\n
 \n
   function update(cm) {\n
+    if (!cm.somethingSelected()) return clear(cm);\n
+    if (cm.listSelections().length > 1) return reset(cm);\n
+\n
     var from = cm.getCursor("start"), to = cm.getCursor("end");\n
-    if (cmp(from, to) == 0) return clear(cm);\n
 \n
     var array = cm.state.markedSelection;\n
     if (!array.length) return coverRange(cm, from, to);\n
@@ -129,7 +139,7 @@
       }\n
     }\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -140,7 +150,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3306</int> </value>
+            <value> <int>3781</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.css.xml
index 4fe1686a1f750d7c05fa98796c7e9ddd5e610d81..afeb71b9d437a5f2e23084f59d0d73d9bdfe38b1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.css.xml
@@ -102,6 +102,7 @@
 \n
 .CodeMirror-Tern-hint-doc {\n
   max-width: 25em;\n
+  margin-top: -3px;\n
 }\n
 \n
 .CodeMirror-Tern-fname { color: black; }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.js.xml
index 9379f97138916fda221ec41ba35b7b146c131627..6568a2c4a9d210d8a26c41dc46eae2819b425a50 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/tern.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.59</string> </value>
+            <value> <string>ts21897117.92</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Glue code between CodeMirror and Tern.\n
 //\n
 // Create a CodeMirror.TernServer to wrap an actual Tern server,\n
@@ -38,7 +41,7 @@
 //   indicate that a file is not available.\n
 // * fileFilter: A function(value, docName, doc) that will be applied\n
 //   to documents before passing them on to Tern.\n
-// * switchToDoc: A function(name) that should, when providing a\n
+// * switchToDoc: A function(name, doc) that should, when providing a\n
 //   multi-file view, switch the view or focus to the named file.\n
 // * showError: A function(editor, message) that can be used to\n
 //   override the way errors are displayed.\n
@@ -64,7 +67,14 @@
 //   load. Or, if you minified those into a single script and included\n
 //   them in the workerScript, simply leave this undefined.\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
   // declare global: tern\n
 \n
@@ -89,6 +99,9 @@
     this.cachedArgHints = null;\n
     this.activeArgHints = null;\n
     this.jumpStack = [];\n
+\n
+    this.getHint = function(cm, c) { return hint(self, cm, c); };\n
+    this.getHint.async = true;\n
   };\n
 \n
   CodeMirror.TernServer.prototype = {\n
@@ -99,28 +112,27 @@
       return this.docs[name] = data;\n
     },\n
 \n
-    delDoc: function(name) {\n
-      var found = this.docs[name];\n
+    delDoc: function(id) {\n
+      var found = resolveDoc(this, id);\n
       if (!found) return;\n
       CodeMirror.off(found.doc, "change", this.trackChange);\n
-      delete this.docs[name];\n
-      this.server.delFile(name);\n
+      delete this.docs[found.name];\n
+      this.server.delFile(found.name);\n
     },\n
 \n
-    hideDoc: function(name) {\n
+    hideDoc: function(id) {\n
       closeArgHints(this);\n
-      var found = this.docs[name];\n
+      var found = resolveDoc(this, id);\n
       if (found && found.changed) sendDoc(this, found);\n
     },\n
 \n
     complete: function(cm) {\n
-      var self = this;\n
-      CodeMirror.showHint(cm, function(cm, c) { return hint(self, cm, c); }, {async: true});\n
+      cm.showHint({hint: this.getHint});\n
     },\n
 \n
-    getHint: function(cm, c) { return hint(this, cm, c); },\n
+    showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },\n
 \n
-    showType: function(cm, pos) { showType(this, cm, pos); },\n
+    showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },\n
 \n
     updateArgHints: function(cm) { updateArgHints(this, cm); },\n
 \n
@@ -129,6 +141,8 @@
     jumpBack: function(cm) { jumpBack(this, cm); },\n
 \n
     rename: function(cm) { rename(this, cm); },\n
+\n
+    selectName: function(cm) { selectName(this, cm); },\n
 \n
     request: function (cm, query, c, pos) {\n
       var self = this;\n
@@ -168,6 +182,12 @@
     }\n
     return ts.addDoc(name, doc);\n
   }\n
+\n
+  function resolveDoc(ts, id) {\n
+    if (typeof id == "string") return ts.docs[id];\n
+    if (id instanceof CodeMirror) id = id.getDoc();\n
+    if (id instanceof CodeMirror.Doc) return findDoc(ts, id);\n
+  }\n
 \n
   function trackChange(ts, doc, change) {\n
     var data = findDoc(ts, doc);\n
@@ -191,7 +211,7 @@
 \n
   function sendDoc(ts, doc) {\n
     ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {\n
-      if (error) console.error(error);\n
+      if (error) window.console.error(error);\n
       else doc.changed = null;\n
     });\n
   }\n
@@ -245,8 +265,8 @@
 \n
   // Type queries\n
 \n
-  function showType(ts, cm, pos) {\n
-    ts.request(cm, "type", function(error, data) {\n
+  function showContextInfo(ts, cm, pos, queryName, c) {\n
+    ts.request(cm, queryName, function(error, data) {\n
       if (error) return showError(ts, cm, error);\n
       if (ts.options.typeTip) {\n
         var tip = ts.options.typeTip(data);\n
@@ -260,6 +280,7 @@
         }\n
       }\n
       tempTooltip(cm, tip);\n
+      if (c) c();\n
     }, pos);\n
   }\n
 \n
@@ -396,10 +417,10 @@
   }\n
 \n
   function moveTo(ts, curDoc, doc, start, end) {\n
-    doc.doc.setSelection(end, start);\n
+    doc.doc.setSelection(start, end);\n
     if (curDoc != doc && ts.options.switchToDoc) {\n
       closeArgHints(ts);\n
-      ts.options.switchToDoc(doc.name);\n
+      ts.options.switchToDoc(doc.name, doc.doc);\n
     }\n
   }\n
 \n
@@ -444,7 +465,7 @@
 \n
   function rename(ts, cm) {\n
     var token = cm.getTokenAt(cm.getCursor());\n
-    if (!/\\w/.test(token.string)) showError(ts, cm, "Not at a variable");\n
+    if (!/\\w/.test(token.string)) return showError(ts, cm, "Not at a variable");\n
     dialog(cm, "New name for " + token.string, function(newName) {\n
       ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {\n
         if (error) return showError(ts, cm, error);\n
@@ -452,6 +473,23 @@
       });\n
     });\n
   }\n
+\n
+  function selectName(ts, cm) {\n
+    var name = findDoc(ts, cm.doc).name;\n
+    ts.request(cm, {type: "refs"}, function(error, data) {\n
+      if (error) return showError(ts, cm, error);\n
+      var ranges = [], cur = 0;\n
+      for (var i = 0; i < data.refs.length; i++) {\n
+        var ref = data.refs[i];\n
+        if (ref.file == name) {\n
+          ranges.push({anchor: ref.start, head: ref.end});\n
+          if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)\n
+            cur = ranges.length - 1;\n
+        }\n
+      }\n
+      cm.setSelections(ranges, cur);\n
+    });\n
+  }\n
 \n
   var nextChangeOrig = 0;\n
   function applyChanges(ts, changes) {\n
@@ -545,7 +583,7 @@
 \n
   // Generic utilities\n
 \n
-  function cmpPos(a, b) { return a.line - b.line || a.ch - b.ch; }\n
+  var cmpPos = CodeMirror.cmpPos;\n
 \n
   function elt(tagname, cls /*, ... elts*/) {\n
     var e = document.createElement(tagname);\n
@@ -638,7 +676,7 @@
           send({type: "getFile", err: String(err), text: text, id: data.id});\n
         });\n
       } else if (data.type == "debug") {\n
-        console.log(data.message);\n
+        window.console.log(data.message);\n
       } else if (data.id && pending[data.id]) {\n
         pending[data.id](data.err, data.body);\n
         delete pending[data.id];\n
@@ -653,7 +691,7 @@
     this.delFile = function(name) { send({type: "del", name: name}); };\n
     this.request = function(body, c) { send({type: "req", body: body}, c); };\n
   }\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -664,7 +702,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>21996</int> </value>
+            <value> <int>23383</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/worker.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/worker.js.xml
index 938b5cda17b9eb6f365512e178531698c11bb2d1..f7c678fce68a153f0c44dd65416be578d1f0e0e2 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/worker.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/tern/worker.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403075.44</string> </value>
+            <value> <string>ts21897118.08</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // declare global: tern, server\n
 \n
 var server;\n
@@ -73,7 +76,7 @@ var console = {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1079</int> </value>
+            <value> <int>1207</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/wrap/hardwrap.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/wrap/hardwrap.js.xml
index 0e730294ac5275a56b17cadaea746100448115c4..112cd4a0cad3f578ae8144aa66b73ddf53313597 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/wrap/hardwrap.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/wrap/hardwrap.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403072.13</string> </value>
+            <value> <string>ts21897121.84</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var Pos = CodeMirror.Pos;\n
@@ -112,6 +122,24 @@
     var para = findParagraph(this, pos, options);\n
     return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);\n
   });\n
+\n
+  CodeMirror.commands.wrapLines = function(cm) {\n
+    cm.operation(function() {\n
+      var ranges = cm.listSelections(), at = cm.lastLine() + 1;\n
+      for (var i = ranges.length - 1; i >= 0; i--) {\n
+        var range = ranges[i], span;\n
+        if (range.empty()) {\n
+          var para = findParagraph(cm, range.head, {});\n
+          span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};\n
+        } else {\n
+          span = {from: range.from(), to: range.to()};\n
+        }\n
+        if (span.to.line >= at) continue;\n
+        at = span.from.line;\n
+        wrapRange(cm, span.from, span.to, {});\n
+      }\n
+    });\n
+  };\n
 \n
   CodeMirror.defineExtension("wrapRange", function(from, to, options) {\n
     return wrapRange(this, from, to, options || {});\n
@@ -132,7 +160,7 @@
     });\n
     return madeChange;\n
   });\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -143,7 +171,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4229</int> </value>
+            <value> <int>5260</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/dep.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin.xml
similarity index 92%
rename from bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/dep.xml
rename to bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin.xml
index c2a178d9512e4ddcbd9baa90f23661a797f93f78..0e5bcdb3e1d756a828a153faf4669f1f06141eb4 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/addon/merge/dep.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin.xml
@@ -14,7 +14,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>dep</string> </value>
+            <value> <string>bin</string> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/authors.sh.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/authors.sh.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe8926810990c1f2a7aa1243939991908d87af57
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/authors.sh.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>authors.sh</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+# Combine existing list of authors with everyone known in git, sort, add header.\n
+tail --lines=+3 AUTHORS > AUTHORS.tmp\n
+git log --format=\'%aN\' >> AUTHORS.tmp\n
+echo -e "List of CodeMirror contributors. Updated before every release.\\n" > AUTHORS\n
+sort -u AUTHORS.tmp >> AUTHORS\n
+rm -f AUTHORS.tmp\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/compress.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/compress.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a0b74b69424b6ed68ee60912a3d94c67fd954b0
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/compress.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>compress</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+#!/usr/bin/env node\n
+\n
+// Compression helper for CodeMirror\n
+//\n
+// Example:\n
+//\n
+//   bin/compress codemirror runmode javascript xml\n
+//\n
+// Will take lib/codemirror.js, addon/runmode/runmode.js,\n
+// mode/javascript/javascript.js, and mode/xml/xml.js, run them though\n
+// the online minifier at http://marijnhaverbeke.nl/uglifyjs, and spit\n
+// out the result.\n
+//\n
+//   bin/compress codemirror --local /path/to/bin/UglifyJS\n
+//\n
+// Will use a local minifier instead of the online default one.\n
+//\n
+// Script files are specified without .js ending. Prefixing them with\n
+// their full (local) path is optional. So you may say lib/codemirror\n
+// or mode/xml/xml to be more precise. In fact, even the .js suffix\n
+// may be speficied, if wanted.\n
+\n
+"use strict";\n
+\n
+var fs = require("fs");\n
+\n
+function help(ok) {\n
+  console.log("usage: " + process.argv[1] + " [--local /path/to/uglifyjs] files...");\n
+  process.exit(ok ? 0 : 1);\n
+}\n
+\n
+var local = null, args = [], extraArgs = null, files = [], blob = "";\n
+\n
+for (var i = 2; i < process.argv.length; ++i) {\n
+  var arg = process.argv[i];\n
+  if (arg == "--local" && i + 1 < process.argv.length) {\n
+    var parts = process.argv[++i].split(/\\s+/);\n
+    local = parts[0];\n
+    extraArgs = parts.slice(1);\n
+    if (!extraArgs.length) extraArgs = ["-c", "-m"];\n
+  } else if (arg == "--help") {\n
+    help(true);\n
+  } else if (arg[0] != "-") {\n
+    files.push({name: arg, re: new RegExp("(?:\\\\/|^)" + arg + (/\\.js$/.test(arg) ? "$" : "\\\\.js$"))});\n
+  } else help(false);\n
+}\n
+\n
+function walk(dir) {\n
+  fs.readdirSync(dir).forEach(function(fname) {\n
+    if (/^[_\\.]/.test(fname)) return;\n
+    var file = dir + fname;\n
+    if (fs.statSync(file).isDirectory()) return walk(file + "/");\n
+    if (files.some(function(spec, i) {\n
+      var match = spec.re.test(file);\n
+      if (match) files.splice(i, 1);\n
+      return match;\n
+    })) {\n
+      if (local) args.push(file);\n
+      else blob += fs.readFileSync(file, "utf8");\n
+    }\n
+  });\n
+}\n
+\n
+walk("lib/");\n
+walk("addon/");\n
+walk("mode/");\n
+\n
+if (!local && !blob) help(false);\n
+\n
+if (files.length) {\n
+  console.log("Some speficied files were not found: " +\n
+              files.map(function(a){return a.name;}).join(", "));\n
+  process.exit(1);\n
+}\n
+  \n
+if (local) {\n
+  require("child_process").spawn(local, args.concat(extraArgs), {stdio: ["ignore", process.stdout, process.stderr]});\n
+} else {\n
+  var data = new Buffer("js_code=" + require("querystring").escape(blob), "utf8");\n
+  var req = require("http").request({\n
+    host: "marijnhaverbeke.nl",\n
+    port: 80,\n
+    method: "POST",\n
+    path: "/uglifyjs",\n
+    headers: {"content-type": "application/x-www-form-urlencoded",\n
+              "content-length": data.length}\n
+  });\n
+  req.on("response", function(resp) {\n
+    resp.on("data", function (chunk) { process.stdout.write(chunk); });\n
+  });\n
+  req.end(data);\n
+}\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/lint.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/lint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d8b26b43638412e84d21766c98e2e2af2b6b8dc1
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/lint.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>lint</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+#!/usr/bin/env node\n
+\n
+var lint = require("../test/lint/lint"),\n
+    path = require("path");\n
+\n
+if (process.argv.length > 2) {\n
+  lint.checkDir(process.argv[2]);\n
+} else {\n
+  process.chdir(path.resolve(__dirname, ".."));\n
+  lint.checkDir("lib");\n
+  lint.checkDir("mode");\n
+  lint.checkDir("addon");\n
+  lint.checkDir("keymap");\n
+}\n
+\n
+process.exit(lint.success() ? 0 : 1);\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/release.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/release.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd3894587ee79c0b65f6d18738d5b9880ecb2312
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/release.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__propsets__</string> </key>
+            <value>
+              <tuple>
+                <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+#!/usr/bin/env node\n
+\n
+var fs = require("fs"), child = require("child_process");\n
+\n
+var number, bumpOnly;\n
+\n
+for (var i = 2; i < process.argv.length; i++) {\n
+  if (process.argv[i] == "-bump") bumpOnly = true;\n
+  else if (/^\\d+\\.\\d+\\.\\d+$/.test(process.argv[i])) number = process.argv[i];\n
+  else { console.log("Bogus command line arg: " + process.argv[i]); process.exit(1); }\n
+}\n
+\n
+if (!number) { console.log("Must give a version"); process.exit(1); }\n
+\n
+function rewrite(file, f) {\n
+  fs.writeFileSync(file, f(fs.readFileSync(file, "utf8")), "utf8");\n
+}\n
+\n
+rewrite("lib/codemirror.js", function(lib) {\n
+  return lib.replace(/CodeMirror\\.version = "\\d+\\.\\d+\\.\\d+"/,\n
+                     "CodeMirror.version = \\"" + number + "\\"");\n
+});\n
+function rewriteJSON(pack) {\n
+  return pack.replace(/"version":"\\d+\\.\\d+\\.\\d+"/, "\\"version\\":\\"" + number + "\\"");\n
+}\n
+rewrite("package.json", rewriteJSON);\n
+rewrite("bower.json", rewriteJSON);\n
+rewrite("doc/manual.html", function(manual) {\n
+  return manual.replace(/>version \\d+\\.\\d+\\.\\d+<\\/span>/, ">version " + number + "</span>");\n
+});\n
+\n
+if (bumpOnly) process.exit(0);\n
+\n
+child.exec("bash bin/authors.sh", function(){});\n
+\n
+var simple = number.slice(0, number.lastIndexOf("."));\n
+\n
+rewrite("doc/compress.html", function(cmp) {\n
+  return cmp.replace(/<option value="http:\\/\\/codemirror.net\\/">HEAD<\\/option>/,\n
+                     "<option value=\\"http://codemirror.net/\\">HEAD</option>\\n        <option value=\\"http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=" + number + ";f=\\">" + simple + "</option>");\n
+});\n
+\n
+rewrite("index.html", function(index) {\n
+  return index.replace(/<strong>version \\d+\\.\\d+<\\/strong>/,\n
+                       "<strong>version " + simple + "</strong>");\n
+});
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>release</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="PropertySheet" module="OFS.PropertySheets"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_md</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>xmlns</string> </key>
+                    <value> <unicode>http://apache.org/dav/props/</unicode> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>_properties</string> </key>
+            <value>
+              <tuple>
+                <dictionary>
+                  <item>
+                      <key> <string>id</string> </key>
+                      <value> <unicode>executable</unicode> </value>
+                  </item>
+                  <item>
+                      <key> <string>meta</string> </key>
+                      <value>
+                        <dictionary>
+                          <item>
+                              <key> <string>__xml_attrs__</string> </key>
+                              <value>
+                                <dictionary/>
+                              </value>
+                          </item>
+                        </dictionary>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>type</string> </key>
+                      <value> <string>string</string> </value>
+                  </item>
+                </dictionary>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>executable</string> </key>
+            <value> <string>T</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/source-highlight.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/source-highlight.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8552553d975475d26cc9fa456719acc0869f1e09
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bin/source-highlight.xml
@@ -0,0 +1,178 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__propsets__</string> </key>
+            <value>
+              <tuple>
+                <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+#!/usr/bin/env node\n
+\n
+// Simple command-line code highlighting tool. Reads code from stdin,\n
+// spits html to stdout. For example:\n
+//\n
+//   echo \'function foo(a) { return a; }\' | bin/source-highlight -s javascript\n
+//   bin/source-highlight -s \n
+\n
+var fs = require("fs");\n
+\n
+var CodeMirror = require("../addon/runmode/runmode.node.js");\n
+require("../mode/meta.js");\n
+\n
+var sPos = process.argv.indexOf("-s");\n
+if (sPos == -1 || sPos == process.argv.length - 1) {\n
+   console.error("Usage: source-highlight -s language");\n
+   process.exit(1);\n
+}\n
+var lang = process.argv[sPos + 1].toLowerCase(), modeName = lang;\n
+CodeMirror.modeInfo.forEach(function(info) {\n
+  if (info.mime == lang) {\n
+    modeName = info.mode;\n
+  } else if (info.name.toLowerCase() == lang) {\n
+    modeName = info.mode;\n
+    lang = info.mime;\n
+  }\n
+});\n
+\n
+if (!CodeMirror.modes[modeName])\n
+  require("../mode/" + modeName + "/" + modeName + ".js");\n
+\n
+function esc(str) {\n
+  return str.replace(/[<&]/g, function(ch) { return ch == "&" ? "&amp;" : "&lt;"; });\n
+}\n
+\n
+var code = fs.readFileSync("/dev/stdin", "utf8");\n
+var curStyle = null, accum = "";\n
+function flush() {\n
+  if (curStyle) process.stdout.write("<span class=\\"" + curStyle.replace(/(^|\\s+)/g, "$1cm-") + "\\">" + esc(accum) + "</span>");\n
+  else process.stdout.write(esc(accum));\n
+}\n
+\n
+CodeMirror.runMode(code, lang, function(text, style) {\n
+  if (style != curStyle) {\n
+    flush();\n
+    curStyle = style; accum = text;\n
+  } else {\n
+    accum += text;\n
+  }\n
+});\n
+flush();
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>source-highlight</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="PropertySheet" module="OFS.PropertySheets"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_md</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>xmlns</string> </key>
+                    <value> <unicode>http://apache.org/dav/props/</unicode> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>_properties</string> </key>
+            <value>
+              <tuple>
+                <dictionary>
+                  <item>
+                      <key> <string>id</string> </key>
+                      <value> <unicode>executable</unicode> </value>
+                  </item>
+                  <item>
+                      <key> <string>meta</string> </key>
+                      <value>
+                        <dictionary>
+                          <item>
+                              <key> <string>__xml_attrs__</string> </key>
+                              <value>
+                                <dictionary/>
+                              </value>
+                          </item>
+                        </dictionary>
+                      </value>
+                  </item>
+                  <item>
+                      <key> <string>type</string> </key>
+                      <value> <string>string</string> </value>
+                  </item>
+                </dictionary>
+              </tuple>
+            </value>
+        </item>
+        <item>
+            <key> <string>executable</string> </key>
+            <value> <string>T</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bower.json.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bower.json.xml
new file mode 100644
index 0000000000000000000000000000000000000000..10518b1019cc2b450331cf95e5bc67ab78183177
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/bower.json.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897123.11</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>bower.json</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/json</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>{\n
+  "name": "codemirror",\n
+  "version":"4.11.0",\n
+  "main": ["lib/codemirror.js", "lib/codemirror.css"],\n
+  "ignore": [\n
+    "**/.*",\n
+    "node_modules",\n
+    "components",\n
+    "bin",\n
+    "demo",\n
+    "doc",\n
+    "test",\n
+    "index.html",\n
+    "package.json"\n
+  ]\n
+}\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>257</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/activeline.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/activeline.html.xml
index b5217bc8220cf9274c10ccfd796bec176286916a..4b4e1d8ed00ca9c93f4072348ab4f734119b1223 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/activeline.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/activeline.html.xml
@@ -50,12 +50,12 @@
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Active Line</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/anywordhint.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/anywordhint.html.xml
index 21d1c566d292b08060fb45d1267a68213af73c08..288aab217393a9d6fe7b4a53c9d6629f017683e2 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/anywordhint.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/anywordhint.html.xml
@@ -49,12 +49,12 @@
 <script src="../addon/hint/anyword-hint.js"></script>\n
 <script src="../mode/javascript/javascript.js"></script>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Any Word Completion</a>\n
@@ -107,7 +107,7 @@ to those.</p>\n
 \n
     <script>\n
       CodeMirror.commands.autocomplete = function(cm) {\n
-        CodeMirror.showHint(cm, CodeMirror.hint.anyword);\n
+        cm.showHint({hint: CodeMirror.hint.anyword});\n
       }\n
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
         lineNumbers: true,\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/bidi.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/bidi.html.xml
index b61c08d771394ab7aa2e304deefd709dfc3dbd11..9b56797f41bcceb70b73d47c69b3b5d1600be5b0 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/bidi.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/bidi.html.xml
@@ -49,12 +49,12 @@
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Bi-directional Text</a>\n
@@ -84,7 +84,7 @@
   <dt id=option_theme><code>theme (string)</code></dt>\n
   <dd>脵聟脵聢脴露脵聢脴鹿 脵聞脵聠脵聟脴路 脴搂脵聞脵聟脴颅脴卤脴卤 脵聟脴鹿. 脵聤脴卢脴拧 脴鹿脵聞脵聤脵聝 脴搂脵聞脴陋脴拢脵聝脴炉 脵聟脵聠 脴搂脵聞脵聟脵聞脵聛 CSS 脴陋脴颅脴炉脵聤脴炉\n
   脴搂脵聞脵聟脵聜脴搂脴拧脵聞脴漏 <code>.cm-s-[name]</code> 脵聤脴陋脵聟 脴陋脴颅脵聟脵聤脵聞 脴拢脵聠脵聟脴搂脴路 (脴搂脵聠脴啪脴卤\n
-  <a href=../theme/><code>theme</code></a> 脴搂脵聞脴炉脵聞脵聤脵聞 脵聛脵聤 脴搂脵聞脴陋脵聢脴虏脵聤脴鹿).\n
+  <a href="../theme/"><code>theme</code></a> 脴搂脵聞脴炉脵聞脵聤脵聞 脵聛脵聤 脴搂脵聞脴陋脵聢脴虏脵聤脴鹿).\n
   脴搂脵聞脴搂脵聛脴陋脴卤脴搂脴露脵聤 脵聡脵聢 <code>"default"</code> 脴聦 脵聢脴搂脵聞脴陋脵聤 脴陋脵聟 脴陋脴露脵聟脵聤脵聠脵聡脴搂 脵聛脵聤\n
   脴搂脵聞脴拢脵聞脵聢脴搂脵聠 <code>codemirror.css</code>. 脵聛脵聟脵聠 脴搂脵聞脵聟脵聟脵聝脵聠 脴搂脴鲁脴陋脴庐脴炉脴搂脵聟 脵聛脴艩脴搂脴陋 脵聟脴陋脴鹿脴炉脴炉脴漏\n
   脵聛脵聤 脴陋脴路脴拧脵聤脵聜 脴搂脵聞脴鲁脵聟脴搂脴陋 脵聟脴卤脴漏 脵聢脴搂脴颅脴炉脴漏 脴鹿脵聞脵聣 脴鲁脴拧脵聤脵聞 脴搂脵聞脵聟脴芦脴搂脵聞 <code>"foo bar"</code>\n
@@ -105,7 +105,7 @@ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
   blog post</a> for more background.</p>\n
 \n
   <p><strong>Note:</strong> There is\n
-  a <a href="https://github.com/marijnh/CodeMirror/issues/1757">known\n
+  a <a href="https://github.com/codemirror/CodeMirror/issues/1757">known\n
   bug</a> with cursor motion and mouse clicks in bi-directional lines\n
   that are line wrapped.</p>\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/btree.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/btree.html.xml
index 64351322371637f58185792451c3bafbc0077f70..228ca6300c1a3fc552d40aab90b5ae744106d061 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/btree.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/btree.html.xml
@@ -49,12 +49,12 @@
       .CodeMirror {border: 1px solid #aaa; height: 400px}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">B-Tree visualization</a>\n
@@ -96,7 +96,6 @@ function updateVisual() {\n
         var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16);\n
         if (col.length == 1) col = "0" + col;\n
         lineElt.style.background = "#" + col + col + col;\n
-                          console.log(line.height, line);\n
         lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px";\n
       }\n
     } else {\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/buffers.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/buffers.html.xml
index 373469d72b78c4aa7d54499634cd6fe0efe3a9dd..6764014987281383530565915255e977d2772863 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/buffers.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/buffers.html.xml
@@ -50,12 +50,12 @@
       .CodeMirror {border: 1px solid black; height: 250px;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Multiple Buffer & Split View</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/changemode.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/changemode.html.xml
index da1e2f0a36cd15259e9b7cbda25bf3e5c5e91514..ce4fb22e676bdf61c9fe68519f8eb76b53b06c19 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/changemode.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/changemode.html.xml
@@ -50,12 +50,12 @@
       .CodeMirror {border: 1px solid black;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Mode-Changing</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closebrackets.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closebrackets.html.xml
index 15f4e952c504f3f19089b33c27e6042ce24ea4fc..11cd0142178decf2f6533e79edd4c217b13afe7a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closebrackets.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closebrackets.html.xml
@@ -50,12 +50,12 @@
       .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Closebrackets</a>\n
@@ -64,36 +64,25 @@
 \n
 <article>\n
 <h2>Closebrackets Demo</h2>\n
-<form><textarea id="code" name="code">(function() {\n
-  var DEFAULT_BRACKETS = "()[]{}\'\'\\"\\"";\n
-\n
-  CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {\n
-    var wasOn = old && old != CodeMirror.Init;\n
-    if (val && !wasOn)\n
-      cm.addKeyMap(buildKeymap(typeof val == "string" ? val : DEFAULT_BRACKETS));\n
-    else if (!val && wasOn)\n
-      cm.removeKeyMap("autoCloseBrackets");\n
-  });\n
-\n
-  function buildKeymap(pairs) {\n
-    var map = {name : "autoCloseBrackets"};\n
-    for (var i = 0; i < pairs.length; i += 2) (function(left, right) {\n
-      function maybeOverwrite(cm) {\n
-        var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));\n
-        if (ahead != right) return CodeMirror.Pass;\n
-        else cm.execCommand("goCharRight");\n
-      }\n
-      map["\'" + left + "\'"] = function(cm) {\n
-        if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;\n
-        var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);\n
-        cm.replaceSelection(left + right, {head: ahead, anchor: ahead});\n
-      };\n
-      if (left != right) map["\'" + right + "\'"] = maybeOverwrite;\n
-    })(pairs.charAt(i), pairs.charAt(i + 1));\n
-    return map;\n
-  }\n
-})();\n
-</textarea></form>\n
+<form><textarea id="code" name="code">function Grid(width, height) {\n
+  this.width = width;\n
+  this.height = height;\n
+  this.cells = new Array(width * height);\n
+}\n
+Grid.prototype.valueAt = function(point) {\n
+  return this.cells[point.y * this.width + point.x];\n
+};\n
+Grid.prototype.setValueAt = function(point, value) {\n
+  this.cells[point.y * this.width + point.x] = value;\n
+};\n
+Grid.prototype.isInside = function(point) {\n
+  return point.x >= 0 && point.y >= 0 &&\n
+         point.x < this.width && point.y < this.height;\n
+};\n
+Grid.prototype.moveValue = function(from, to) {\n
+  this.setValueAt(to, this.valueAt(from));\n
+  this.setValueAt(from, undefined);\n
+};</textarea></form>\n
 \n
     <script type="text/javascript">\n
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {autoCloseBrackets: true});\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closetag.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closetag.html.xml
index 89d8dfad40bc81ab3dc5553f95244a8aa997812b..fd25f862025da5a9f88935581b9ec6e38a03c81c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closetag.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/closetag.html.xml
@@ -54,12 +54,12 @@
       .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Close-Tag</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/complete.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/complete.html.xml
index 4333d372d0e76dc1f23821c2a0ad73dec82dd23c..8ef040e90a2da0b16dfb2c4052655f73283c9496 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/complete.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/complete.html.xml
@@ -50,12 +50,12 @@
 <script src="../mode/javascript/javascript.js"></script>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Autocomplete</a>\n
@@ -110,7 +110,8 @@ addons.</p>\n
     <script>\n
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
         lineNumbers: true,\n
-        extraKeys: {"Ctrl-Space": "autocomplete"}\n
+        extraKeys: {"Ctrl-Space": "autocomplete"},\n
+        mode: {name: "javascript", globalVars: true}\n
       });\n
     </script>\n
   </article>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/emacs.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/emacs.html.xml
index 3fb070ab0639e5596abb61ea79d4478a976def5a..06da49c7ac745884ee7157f7e9f5dffb0917ef69 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/emacs.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/emacs.html.xml
@@ -56,12 +56,12 @@
       .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Emacs bindings</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/folding.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/folding.html.xml
index 5cd0f37a4ef3cee920d0a63cfb698d3793cf89d6..1b0fec7b708a61be4c56179d54e2cc4f3ef4d767 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/folding.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/folding.html.xml
@@ -62,12 +62,12 @@
 \n
 <body>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Code Folding</a>\n
@@ -106,7 +106,7 @@ window.onload = function() {\n
     foldGutter: true,\n
     gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]\n
   });\n
-  editor.foldCode(CodeMirror.Pos(11, 0));\n
+  editor.foldCode(CodeMirror.Pos(13, 0));\n
 \n
   window.editor_html = CodeMirror.fromTextArea(te_html, {\n
     mode: "text/html",\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/fullscreen.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/fullscreen.html.xml
index 5ce3c68371e5c7ebc6ff7d3fff5848899c890ba3..c56809329437573bebedef2421787633d3a93fa5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/fullscreen.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/fullscreen.html.xml
@@ -50,12 +50,12 @@
 <script src="../addon/display/fullscreen.js"></script>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Full Screen Editing</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/hardwrap.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/hardwrap.html.xml
index a960c068cf5128f32a4606c520dd06202f54a27f..2bf8836d14b95cf793d7799e00560142572916fa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/hardwrap.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/hardwrap.html.xml
@@ -50,12 +50,12 @@
   .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
 </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Hard-wrapping</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/html5complete.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/html5complete.html.xml
index 35e0bb8e30c136ca5092d7cc9a065cc0d8f1ca03..da60dfe310d3eb11c0d99c0c5d8ef34919718e82 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/html5complete.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/html5complete.html.xml
@@ -60,12 +60,12 @@
 \n
 <body>\n
   <div id=nav>\n
-    <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+    <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
     <ul>\n
       <li><a href="../index.html">Home</a>\n
       <li><a href="../doc/manual.html">Manual</a>\n
-      <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+      <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
     </ul>\n
     <ul>\n
       <li><a class=active href="#">HTML completion</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/indentwrap.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/indentwrap.html.xml
index 656493d5baac10a637f1cc1319caa7b9c483be41..80161c41fd2a91c4c06dc55903238b9033132cf4 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/indentwrap.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/indentwrap.html.xml
@@ -50,12 +50,12 @@
       .CodeMirror pre > * { text-indent: 0px; }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Indented wrapped line</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/lint.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/lint.html.xml
index 2d76f6dd0836ce92eb0e19d14b3db4d77bcc8b03..6ef70e5519056bda29edb5e8968565df9b1764cd 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/lint.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/lint.html.xml
@@ -47,7 +47,7 @@
 <script src="../lib/codemirror.js"></script>\n
 <script src="../mode/javascript/javascript.js"></script>\n
 <script src="../mode/css/css.js"></script>\n
-<script src="http://ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>\n
+<script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>\n
 <script src="https://rawgithub.com/zaach/jsonlint/79b553fb65c192add9066da64043458981b3972b/lib/jsonlint.js"></script>\n
 <script src="https://rawgithub.com/stubbornella/csslint/master/release/csslint.js"></script>\n
 <script src="../addon/lint/lint.js"></script>\n
@@ -58,12 +58,12 @@
       .CodeMirror {border: 1px solid black;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Linter</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/loadmode.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/loadmode.html.xml
index 253a8380201a41e5e3a2260165761a6de881d13f..21ef27780a14d0840ad78488318b5d7b4fd6033d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/loadmode.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/loadmode.html.xml
@@ -45,16 +45,17 @@
 <link rel="stylesheet" href="../lib/codemirror.css">\n
 <script src="../lib/codemirror.js"></script>\n
 <script src="../addon/mode/loadmode.js"></script>\n
+<script src="../mode/meta.js"></script>\n
 <style type="text/css">\n
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Lazy Mode Loading</a>\n
@@ -63,12 +64,13 @@
 \n
 <article>\n
 <h2>Lazy Mode Loading Demo</h2>\n
+<p style="color: gray">Current mode: <span id="modeinfo">text/plain</span></p>\n
 <form><textarea id="code" name="code">This is the editor.\n
 // It starts out in plain text mode,\n
 #  use the control below to load and apply a mode\n
   "you\'ll see the highlighting of" this text /*change*/.\n
 </textarea></form>\n
-<p><input type=text value=javascript id=mode> <button type=button onclick="change()">change mode</button></p>\n
+<p>Filename, mime, or mode name: <input type=text value=foo.js id=mode> <button type=button onclick="change()">change mode</button></p>\n
 \n
     <script>\n
 CodeMirror.modeURL = "../mode/%N/%N.js";\n
@@ -80,8 +82,29 @@ CodeMirror.on(modeInput, "keypress", function(e) {\n
   if (e.keyCode == 13) change();\n
 });\n
 function change() {\n
-   editor.setOption("mode", modeInput.value);\n
-   CodeMirror.autoLoadMode(editor, modeInput.value);\n
+  var val = modeInput.value, m, mode, spec;\n
+  if (m = /.+\\.([^.]+)$/.exec(val)) {\n
+    var info = CodeMirror.findModeByExtension(m[1]);\n
+    if (info) {\n
+      mode = info.mode;\n
+      spec = info.mime;\n
+    }\n
+  } else if (/\\//.test(val)) {\n
+    var info = CodeMirror.findModeByMIME(val);\n
+    if (info) {\n
+      mode = info.mode;\n
+      spec = val;\n
+    }\n
+  } else {\n
+    mode = spec = val;\n
+  }\n
+  if (mode) {\n
+    editor.setOption("mode", spec);\n
+    CodeMirror.autoLoadMode(editor, mode);\n
+    document.getElementById("modeinfo").textContent = spec;\n
+  } else {\n
+    alert("Could not find a mode corresponding to " + val);\n
+  }\n
 }\n
 </script>\n
   </article>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/marker.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/marker.html.xml
index 9b6fa10d490466c39450817c4996ccd76ecbfcad..7915c756c5eec3740d8e55c735ffaa9135a2e3bd 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/marker.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/marker.html.xml
@@ -51,12 +51,12 @@
       .CodeMirror {border: 1px solid #aaa;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Breakpoint</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/markselection.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/markselection.html.xml
index 4f9ff366f41124eb6604a8b3a2c2cbf797008b9f..cf49fbf09ec5f7e8435f8ab91557207d1ddf481f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/markselection.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/markselection.html.xml
@@ -38,7 +38,7 @@
 
 <!doctype html>\n
 \n
-<title>CodeMirror: Match Selection Demo</title>\n
+<title>CodeMirror: Selection Marking Demo</title>\n
 <meta charset="utf-8"/>\n
 <link rel=stylesheet href="../doc/docs.css">\n
 \n
@@ -50,35 +50,42 @@
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
       .CodeMirror-selected  { background-color: blue !important; }\n
       .CodeMirror-selectedtext { color: white; }\n
+      .styled-background { background-color: #ff7; }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
-    <li><a class=active href="#">Match Selection</a>\n
+    <li><a class=active href="#">Selection Marking</a>\n
   </ul>\n
 </div>\n
 \n
 <article>\n
-<h2>Match Selection Demo</h2>\n
-<form><textarea id="code" name="code">Select something from here.\n
-You\'ll see that the selection\'s foreground color changes to white!\n
-Since, by default, CodeMirror only puts an independent "marker" layer\n
-behind the text, you\'ll need something like this to change its colour.</textarea></form>\n
+<h2>Selection Marking Demo</h2>\n
+<form><textarea id="code" name="code">\n
+Select something from here. You\'ll see that the selection\'s foreground\n
+color changes to white! Since, by default, CodeMirror only puts an\n
+independent "marker" layer behind the text, you\'ll need something like\n
+this to change its colour.\n
+\n
+Also notice that turning this addon on (with the default style) allows\n
+you to safely give text a background color without screwing up the\n
+visibility of the selection.</textarea></form>\n
 \n
     <script>\n
 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
   lineNumbers: true,\n
   styleSelectedText: true\n
 });\n
+editor.markText({line: 6, ch: 26}, {line: 6, ch: 42}, {className: "styled-background"});\n
 </script>\n
 \n
-    <p>Simple addon to easily mark (and style) selected text.</p>\n
+    <p>Simple addon to easily mark (and style) selected text. <a href="../doc/manual.html#addon_mark-selection">Docs</a>.</p>\n
 \n
   </article>
 
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchhighlighter.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchhighlighter.html.xml
index 6333d32e06d17138d5af79585c5399b6d7a2ddac..40c66adfe24561e385579260cccd1b612cbe40fe 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchhighlighter.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchhighlighter.html.xml
@@ -55,12 +55,12 @@
       }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Match Highlighter</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchtags.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchtags.html.xml
index c304014de1498b1d593e60f01d31e01e95942b6d..a97eb08e58381b72d013505e654d86395466dd9c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchtags.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/matchtags.html.xml
@@ -49,15 +49,14 @@
 <script src="../mode/xml/xml.js"></script>\n
 <style type="text/css">\n
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
-      .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Tag Matcher</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/merge.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/merge.html.xml
index bc98316d75f73afbad2e804902ae9e2b91d5e2aa..bde576ac82579f63ebe86fed2f656c585c29f335 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/merge.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/merge.html.xml
@@ -46,7 +46,7 @@
 <link rel=stylesheet href="../addon/merge/merge.css">\n
 <script src="../lib/codemirror.js"></script>\n
 <script src="../mode/xml/xml.js"></script>\n
-<script src="../addon/merge/dep/diff_match_patch.js"></script>\n
+<script src="//cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"></script>\n
 <script src="../addon/merge/merge.js"></script>\n
 <style>\n
     .CodeMirror { line-height: 1.2; }\n
@@ -59,12 +59,12 @@
     }\n
   </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">merge view</a>\n
@@ -79,33 +79,41 @@
 \n
 <p>The <a href="../doc/manual.html#addon_merge"><code>merge</code></a>\n
 addon provides an interface for displaying and merging diffs,\n
-either <span class=clicky onclick="initUI(2)">two-way</span>\n
-or <span class=clicky onclick="initUI(3)">three-way</span>. The left\n
-(or center) pane is editable, and the differences with the other\n
-pane(s) are <span class=clicky onclick="toggleDifferences()">optionally</span> shown live as you edit it.</p>\n
+either <span class=clicky onclick="panes = 2; initUI()">two-way</span>\n
+or <span class=clicky onclick="panes = 3; initUI()">three-way</span>.\n
+The left (or center) pane is editable, and the differences with the\n
+other pane(s) are <span class=clicky\n
+onclick="toggleDifferences()">optionally</span> shown live as you edit\n
+it. In the two-way configuration, there are also options to pad changed\n
+sections to <span class=clicky onclick="connect = connect ? null :\n
+\'align\'; initUI()">align</span> them, and to <span class=clicky\n
+onclick="collapse = !collapse; initUI()">collapse</span> unchanged\n
+stretches of text.</p>\n
 \n
 <p>This addon depends on\n
 the <a href="https://code.google.com/p/google-diff-match-patch/">google-diff-match-patch</a>\n
 library to compute the diffs.</p>\n
 \n
 <script>\n
-var value, orig1, orig2, dv, hilight= true;\n
-function initUI(panes) {\n
+var value, orig1, orig2, dv, panes = 2, highlight = true, connect = null, collapse = false;\n
+function initUI() {\n
   if (value == null) return;\n
   var target = document.getElementById("view");\n
   target.innerHTML = "";\n
   dv = CodeMirror.MergeView(target, {\n
     value: value,\n
-    origLeft: panes == 3 ? orig1 : null,\n
+    origLeft: panes == 3 && !collapse && !connect ? orig1 : null,\n
     orig: orig2,\n
     lineNumbers: true,\n
     mode: "text/html",\n
-    highlightDifferences: hilight\n
+    highlightDifferences: highlight,\n
+    connect: connect,\n
+    collapseIdentical: collapse\n
   });\n
 }\n
 \n
 function toggleDifferences() {\n
-  dv.setShowDifferences(hilight = !hilight);\n
+  dv.setShowDifferences(highlight = !highlight);\n
 }\n
 \n
 window.onload = function() {\n
@@ -113,8 +121,34 @@ window.onload = function() {\n
   orig1 = value.replace(/\\.\\.\\//g, "codemirror/").replace("yellow", "orange");\n
   orig2 = value.replace(/\\u003cscript/g, "\\u003cscript type=text/javascript ")\n
     .replace("white", "purple;\\n      font: comic sans;\\n      text-decoration: underline;\\n      height: 15em");\n
-  initUI(2);\n
+  initUI();\n
 };\n
+\n
+function mergeViewHeight(mergeView) {\n
+  function editorHeight(editor) {\n
+    if (!editor) return 0;\n
+    return editor.getScrollInfo().height;\n
+  }\n
+  return Math.max(editorHeight(mergeView.leftOriginal()),\n
+                  editorHeight(mergeView.editor()),\n
+                  editorHeight(mergeView.rightOriginal()));\n
+}\n
+\n
+function resize(mergeView) {\n
+  var height = mergeViewHeight(mergeView);\n
+  for(;;) {\n
+    if (mergeView.leftOriginal())\n
+      mergeView.leftOriginal().setSize(null, height);\n
+    mergeView.editor().setSize(null, height);\n
+    if (mergeView.rightOriginal())\n
+      mergeView.rightOriginal().setSize(null, height);\n
+\n
+    var newHeight = mergeViewHeight(mergeView);\n
+    if (newHeight >= height) break;\n
+    else height = newHeight;\n
+  }\n
+  mergeView.wrap.style.height = height + "px";\n
+}\n
 </script>\n
 </article>
 
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/multiplex.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/multiplex.html.xml
index fa94ce27c797bc88e6f87abc6a39ca03d1fd0acb..3851eb46fd5fd34845c25d541126355f577b2a28 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/multiplex.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/multiplex.html.xml
@@ -51,12 +51,12 @@
       .cm-delimit {color: #fa4;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Multiplexing Parser</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/mustache.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/mustache.html.xml
index 3047a3bcaff3299125c9883709cc27a29acc3df0..c55f7517cccc6eb91b8b788b3b492bb3c7192a7e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/mustache.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/mustache.html.xml
@@ -51,12 +51,12 @@
       .cm-mustache {color: #0ca;}\n
 </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Overlay Parser</a>\n
@@ -84,9 +84,10 @@ CodeMirror.defineMode("mustache", function(config, parserConfig) {\n
       var ch;\n
       if (stream.match("{{")) {\n
         while ((ch = stream.next()) != null)\n
-          if (ch == "}" && stream.next() == "}") break;\n
-        stream.eat("}");\n
-        return "mustache";\n
+          if (ch == "}" && stream.next() == "}") {\n
+            stream.eat("}");\n
+            return "mustache";\n
+          }\n
       }\n
       while (stream.next() != null && !stream.match("{{", false)) {}\n
       return null;\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/panel.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/panel.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35baff4fd25e0b9cad4d0e297b983614245780d6
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/panel.html.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+\n
+<title>CodeMirror: Panel Demo</title>\n
+<meta charset="utf-8"/>\n
+<link rel=stylesheet href="../doc/docs.css">\n
+\n
+<link rel="stylesheet" href="../lib/codemirror.css">\n
+<script src="../lib/codemirror.js"></script>\n
+<script src="../mode/javascript/javascript.js"></script>\n
+<script src="../addon/display/panel.js"></script>\n
+<style type="text/css">\n
+  .border {border: 1px solid black; border-bottom: 1px solid black;}\n
+  .add { background: orange; padding: 1px 3px; color: white !important; border-radius: 4px; }\n
+  .panel {\n
+    background-image: linear-gradient(to bottom, #ffffaa, #ffffdd);\n
+    padding: 3px 7px;\n
+  }\n
+  .panel.top { border-bottom: 1px solid #dd6; }\n
+  .panel.bottom { border-top: 1px solid #dd6; }\n
+  .panel span { cursor: pointer; }\n
+</style>\n
+\n
+<div id=nav>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
+\n
+  <ul>\n
+    <li><a href="../index.html">Home</a>\n
+    <li><a href="../doc/manual.html">Manual</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
+  </ul>\n
+  <ul>\n
+    <li><a class=active href="#">Panel</a>\n
+  </ul>\n
+</div>\n
+\n
+<article>\n
+<h2>Panel Demo</h2>\n
+<form><div class="border"><textarea id="code" name="code"></textarea></div></form>\n
+\n
+<script id="localscript">var textarea = document.getElementById("code");\n
+var script = document.getElementById("localscript");\n
+textarea.value = (script.textContent ||\n
+                  script.innerText ||\n
+                  script.innerHTML);\n
+editor = CodeMirror.fromTextArea(textarea, {\n
+  lineNumbers: true\n
+});\n
+\n
+function addPanel(where) {\n
+  var node = document.createElement("div");\n
+  node.className = "panel " + where;\n
+  var close = node.appendChild(document.createElement("span"));\n
+  close.textContent = "芒聹聳 Remove this panel";\n
+  var widget = editor.addPanel(node, {position: where});\n
+  CodeMirror.on(close, "click", function() { widget.clear(); });\n
+}</script>\n
+\n
+<p>The <a href="../doc/manual.html#addon_panel"><code>panel</code></a>\n
+addon allows you to display panels <a class=add\n
+href="javascript:addPanel(\'top\')">above</a> or <a class=add\n
+href="javascript:addPanel(\'bottom\')">below</a> an editor. Click the\n
+links in the previous paragraph to add panels to the editor.</p>\n
+\n
+</article>
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>panel.html</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/placeholder.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/placeholder.html.xml
index ebd38d361da561cfb0811359feca4d9ae3b05578..d74a2def7f89405e02835e58b74ca77f6dac5c88 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/placeholder.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/placeholder.html.xml
@@ -52,12 +52,12 @@
       .CodeMirror pre.CodeMirror-placeholder { color: #999; }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Placeholder</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/preview.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/preview.html.xml
index 6767f43270e881d1430abe91a06fec8665a3669b..5a6d14edfdc3b03ff410e134242d64bbd08d22e3 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/preview.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/preview.html.xml
@@ -63,12 +63,12 @@
       }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">HTML5 preview</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/requirejs.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/requirejs.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..823c33b3202c62c857e570cb455eb644f8b8d01b
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/requirejs.html.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+\n
+<head>\n
+  <title>CodeMirror: HTML completion demo</title>\n
+  <meta charset="utf-8"/>\n
+  <link rel=stylesheet href="../doc/docs.css">\n
+\n
+  <link rel="stylesheet" href="../lib/codemirror.css">\n
+  <link rel="stylesheet" href="../addon/hint/show-hint.css">\n
+  <script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.min.js"></script>\n
+  <style type="text/css">\n
+    .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}\n
+  </style>\n
+</head>\n
+\n
+<body>\n
+  <div id=nav>\n
+    <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
+    <ul>\n
+      <li><a href="../index.html">Home</a>\n
+      <li><a href="../doc/manual.html">Manual</a>\n
+      <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
+    </ul>\n
+    <ul>\n
+      <li><a class=active href="#">HTML completion</a>\n
+    </ul>\n
+  </div>\n
+\n
+  <article>\n
+    <h2>RequireJS module loading demo</h2>\n
+\n
+    <p>This demo does the same thing as\n
+    the <a href="html5complete.html">HTML5 completion demo</a>, but\n
+    loads its dependencies\n
+    with <a href="http://requirejs.org/">Require.js</a>, rather than\n
+    explicitly. Press <strong>ctrl-space</strong> to activate\n
+    completion.</p>\n
+\n
+    <div id="code"></div>\n
+\n
+    <script type="text/javascript">\n
+      require(["../lib/codemirror", "../mode/htmlmixed/htmlmixed",\n
+               "../addon/hint/show-hint", "../addon/hint/html-hint"], function(CodeMirror) {\n
+        editor = CodeMirror(document.getElementById("code"), {\n
+          mode: "text/html",\n
+          extraKeys: {"Ctrl-Space": "autocomplete"},\n
+          value: document.documentElement.innerHTML\n
+        });\n
+      });\n
+    </script>\n
+  </article>\n
+</body>
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>requirejs.html</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/resize.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/resize.html.xml
index c9fd40276f2d160c51a23e2edb20619fe9e4aca8..81d4edb2e7d63c7cda4cdf04ad91f12eb590f403 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/resize.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/resize.html.xml
@@ -50,18 +50,14 @@
         border: 1px solid #eee;\n
         height: auto;\n
       }\n
-      .CodeMirror-scroll {\n
-        overflow-y: hidden;\n
-        overflow-x: auto;\n
-      }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Autoresize</a>\n
@@ -75,13 +71,10 @@
   border: 1px solid #eee;\n
   height: auto;\n
 }\n
-.CodeMirror-scroll {\n
-  overflow-y: hidden;\n
-  overflow-x: auto;\n
-}\n
 </textarea></form>\n
 \n
-<p>By setting a few CSS properties, and giving\n
+<p>By setting an editor\'s <code>height</code> style\n
+to <code>auto</code> and giving\n
 the <a href="../doc/manual.html#option_viewportMargin"><code>viewportMargin</code></a>\n
 a value of <code>Infinity</code>, CodeMirror can be made to\n
 automatically resize to fit its content.</p>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/rulers.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/rulers.html.xml
index 0f527d5db3acc607812e7f8918e42d93a2aeb889..4e18475d361e04398abf94e0d506fe5e76a5606d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/rulers.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/rulers.html.xml
@@ -47,20 +47,14 @@
 <script src="../addon/display/rulers.js"></script>\n
 <style type="text/css">\n
   .CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}\n
-  .ruler1 { border-left: 1px solid #fcc; }\n
-  .ruler2 { border-left: 1px solid #f5f577; }\n
-  .ruler3 { border-left: 1px solid #cfc; }\n
-  .ruler4 { border-left: 1px solid #aff; }\n
-  .ruler5 { border-left: 1px solid #ccf; }\n
-  .ruler6 { border-left: 1px solid #fcf; }\n
 </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Ruler demo</a>\n
@@ -72,9 +66,10 @@
 \n
 <script type="text/javascript">\n
   var nums = "0123456789", space = "          ";\n
+  var colors = ["#fcc", "#f5f577", "#cfc", "#aff", "#ccf", "#fcf"];\n
   var rulers = [], value = "";\n
   for (var i = 1; i <= 6; i++) {\n
-    rulers.push({className: "ruler" + i, column: i * 10});\n
+    rulers.push({color: colors[i], column: i * 10, lineStyle: "dashed"});\n
     for (var j = 1; j < i; j++) value += space;\n
     value += nums + "\\n";\n
   }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/runmode.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/runmode.html.xml
index 1987707b67a156bb972c86fc8463d86286ee10a1..a143952bf9e3985e0671b541ce95a6a88faf9114 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/runmode.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/runmode.html.xml
@@ -47,12 +47,12 @@
 <script src="../addon/runmode/runmode.js"></script>\n
 <script src="../mode/xml/xml.js"></script>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Mode Runner</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/search.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/search.html.xml
index c7ca0300b540dbed311e1e9d581c1b1ee4cd5d93..8f88e5c0cf38cde4c3236720c4879ea35418c46b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/search.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/search.html.xml
@@ -44,22 +44,25 @@
 \n
 <link rel="stylesheet" href="../lib/codemirror.css">\n
 <link rel="stylesheet" href="../addon/dialog/dialog.css">\n
+<link rel="stylesheet" href="../addon/search/matchesonscrollbar.css">\n
 <script src="../lib/codemirror.js"></script>\n
 <script src="../mode/xml/xml.js"></script>\n
 <script src="../addon/dialog/dialog.js"></script>\n
 <script src="../addon/search/searchcursor.js"></script>\n
 <script src="../addon/search/search.js"></script>\n
+<script src="../addon/scroll/annotatescrollbar.js"></script>\n
+<script src="../addon/search/matchesonscrollbar.js"></script>\n
 <style type="text/css">\n
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n
       dt {font-family: monospace; color: #666;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Search/Replace</a>\n
@@ -104,7 +107,10 @@
 </textarea></form>\n
 \n
     <script>\n
-var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "text/html", lineNumbers: true});\n
+var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
+  mode: "text/html",\n
+  lineNumbers: true\n
+});\n
 </script>\n
 \n
     <p>Demonstration of primitive search/replace functionality. The\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/simplemode.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/simplemode.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..25ebd7d7f5791319a4bf32259cbe348591d4cfc2
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/simplemode.html.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+\n
+<title>CodeMirror: Simple Mode Demo</title>\n
+<meta charset="utf-8"/>\n
+<link rel=stylesheet href="../doc/docs.css">\n
+\n
+<link rel="stylesheet" href="../lib/codemirror.css">\n
+<script src="../lib/codemirror.js"></script>\n
+<script src="../addon/mode/simple.js"></script>\n
+<script src="../mode/xml/xml.js"></script>\n
+<style type="text/css">\n
+  .CodeMirror {border: 1px solid silver; margin-bottom: 1em; }\n
+  dt { text-indent: -2em; padding-left: 2em; margin-top: 1em; }\n
+  dd { margin-left: 1.5em; margin-bottom: 1em; }\n
+  dt {margin-top: 1em;}\n
+</style>\n
+\n
+<div id=nav>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
+\n
+  <ul>\n
+    <li><a href="../index.html">Home</a>\n
+    <li><a href="../doc/manual.html">Manual</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
+  </ul>\n
+  <ul>\n
+    <li><a class=active href="#">Simple Mode</a>\n
+  </ul>\n
+</div>\n
+\n
+<article>\n
+<h2>Simple Mode Demo</h2>\n
+\n
+<p>The <a href="../addon/mode/simple.js"><code>mode/simple</code></a>\n
+addon allows CodeMirror modes to be specified using a relatively simple\n
+declarative format. This format is not as powerful as writing code\n
+directly against the <a href="../doc/manual.html#modeapi">mode\n
+interface</a>, but is a lot easier to get started with, and\n
+sufficiently expressive for many simple language modes.</p>\n
+\n
+<p>This interface is still in flux. It is unlikely to be scrapped or\n
+overhauled completely, so do start writing code against it, but\n
+details might change as it stabilizes, and you might have to tweak\n
+your code when upgrading.</p>\n
+\n
+<p>Simple modes (loosely based on\n
+the <a href="https://github.com/mozilla/skywriter/wiki/Common-JavaScript-Syntax-Highlighting-Specification">Common\n
+JavaScript Syntax Highlighting Specification</a>, which never took\n
+off), are state machines, where each state has a number of rules that\n
+match tokens. A rule describes a type of token that may occur in the\n
+current state, and possibly a transition to another state caused by\n
+that token.</p>\n
+\n
+<p>The <code>CodeMirror.defineSimpleMode(name, states)</code> method\n
+takes a mode name and an object that describes the mode\'s states. The\n
+editor below shows an example of such a mode (and is itself\n
+highlighted by the mode shown in it).</p>\n
+\n
+<div id="code"></div>\n
+\n
+<p>Each state is an array of rules. A rule may have the following properties:</p>\n
+\n
+<dl>\n
+  <dt><code><strong>regex</strong>: string | RegExp</code></dt>\n
+  <dd>The regular expression that matches the token. May be a string\n
+  or a regex object. When a regex, the <code>ignoreCase</code> flag\n
+  will be taken into account when matching the token. This regex\n
+  should only capture groups when the <code>token</code> property is\n
+  an array.</dd>\n
+  <dt><code><strong>token</strong></code>: string | null</dt>\n
+  <dd>An optional token style. Multiple styles can be specified by\n
+  separating them with dots or spaces. When the <code>regex</code> for\n
+  this rule captures groups, it must capture <em>all</em> of the\n
+  string (since JS provides no way to find out where a group matched),\n
+  and this property must hold an array of token styles that has one\n
+  style for each matched group.</dd>\n
+  <dt><code><strong>next</strong>: string</code></dt>\n
+  <dd>When a <code>next</code> property is present, the mode will\n
+  transfer to the state named by the property when the token is\n
+  encountered.</dd>\n
+  <dt><code><strong>push</strong>: string</code></dt>\n
+  <dd>Like <code>next</code>, but instead replacing the current state\n
+  by the new state, the current state is kept on a stack, and can be\n
+  returned to with the <code>pop</code> directive.</dd>\n
+  <dt><code><strong>pop</strong>: bool</code></dt>\n
+  <dd>When true, and there is another state on the state stack, will\n
+  cause the mode to pop that state off the stack and transition to\n
+  it.</dd>\n
+  <dt><code><strong>mode</strong>: {spec, end, persistent}</code></dt>\n
+  <dd>Can be used to embed another mode inside a mode. When present,\n
+  must hold an object with a <code>spec</code> property that describes\n
+  the embedded mode, and an optional <code>end</code> end property\n
+  that specifies the regexp that will end the extent of the mode. When\n
+  a <code>persistent</code> property is set (and true), the nested\n
+  mode\'s state will be preserved between occurrences of the mode.</dd>\n
+  <dt><code><strong>indent</strong>: bool</code></dt>\n
+  <dd>When true, this token changes the indentation to be one unit\n
+  more than the current line\'s indentation.</dd>\n
+  <dt><code><strong>dedent</strong>: bool</code></dt>\n
+  <dd>When true, this token will pop one scope off the indentation\n
+  stack.</dd>\n
+  <dt><code><strong>dedentIfLineStart</strong>: bool</code></dt>\n
+  <dd>If a token has its <code>dedent</code> property set, it will, by\n
+  default, cause lines where it appears at the start to be dedented.\n
+  Set this property to false to prevent that behavior.</dd>\n
+</dl>\n
+\n
+<p>The <code>meta</code> property of the states object is special, and\n
+will not be interpreted as a state. Instead, properties set on it will\n
+be set on the mode, which is useful for properties\n
+like <a href="../doc/manual.html#addon_comment"><code>lineComment</code></a>,\n
+which sets the comment style for a mode. The simple mode addon also\n
+recognizes a few such properties:</p>\n
+\n
+<dl>\n
+  <dt><code><strong>dontIndentStates</strong>: array&lt;string&gt;</code></dt>\n
+  <dd>An array of states in which the mode\'s auto-indentation should\n
+  not take effect. Usually used for multi-line comment and string\n
+  states.</dd>\n
+</dl>\n
+\n
+<script id="modecode">/* Example definition of a simple mode that understands a subset of\n
+ * JavaScript:\n
+ */\n
+\n
+CodeMirror.defineSimpleMode("simplemode", {\n
+  // The start state contains the rules that are intially used\n
+  start: [\n
+    // The regex matches the token, the token property contains the type\n
+    {regex: /"(?:[^\\\\]|\\\\.)*?"/, token: "string"},\n
+    // You can match multiple tokens at once. Note that the captured\n
+    // groups must span the whole string in this case\n
+    {regex: /(function)(\\s+)([a-z$][\\w$]*)/,\n
+     token: ["keyword", null, "variable-2"]},\n
+    // Rules are matched in the order in which they appear, so there is\n
+    // no ambiguity between this one and the one above\n
+    {regex: /(?:function|var|return|if|for|while|else|do|this)\\b/,\n
+     token: "keyword"},\n
+    {regex: /true|false|null|undefined/, token: "atom"},\n
+    {regex: /0x[a-f\\d]+|[-+]?(?:\\.\\d+|\\d+\\.?\\d*)(?:e[-+]?\\d+)?/i,\n
+     token: "number"},\n
+    {regex: /\\/\\/.*/, token: "comment"},\n
+    {regex: /\\/(?:[^\\\\]|\\\\.)*?\\//, token: "variable-3"},\n
+    // A next property will cause the mode to move to a different state\n
+    {regex: /\\/\\*/, token: "comment", next: "comment"},\n
+    {regex: /[-+\\/*=<>!]+/, token: "operator"},\n
+    // indent and dedent properties guide autoindentation\n
+    {regex: /[\\{\\[\\(]/, indent: true},\n
+    {regex: /[\\}\\]\\)]/, dedent: true},\n
+    {regex: /[a-z$][\\w$]*/, token: "variable"},\n
+    // You can embed other modes with the mode property. This rule\n
+    // causes all code between << and >> to be highlighted with the XML\n
+    // mode.\n
+    {regex: /<</, token: "meta", mode: {spec: "xml", end: />>/}}\n
+  ],\n
+  // The multi-line comment state.\n
+  comment: [\n
+    {regex: /.*?\\*\\//, token: "comment", next: "start"},\n
+    {regex: /.*/, token: "comment"}\n
+  ],\n
+  // The meta property contains global information about the mode. It\n
+  // can contain properties like lineComment, which are supported by\n
+  // all modes, and also directives like dontIndentStates, which are\n
+  // specific to simple modes.\n
+  meta: {\n
+    dontIndentStates: ["comment"],\n
+    lineComment: "//"\n
+  }\n
+});\n
+</script>\n
+\n
+<script>\n
+var sc = document.getElementById("modecode");\n
+var code = document.getElementById("code");\n
+var editor = CodeMirror(code, {\n
+  value: (sc.textContent || sc.innerText || sc.innerHTML),\n
+  mode: "simplemode"\n
+});\n
+</script>\n
+\n
+</article>
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>simplemode.html</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/simplescrollbars.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/simplescrollbars.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ff5f9d4abdbefe86f81f7150a06f226e7a4b2495
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/simplescrollbars.html.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+\n
+<title>CodeMirror: Simple Scrollbar Demo</title>\n
+<meta charset="utf-8"/>\n
+<link rel=stylesheet href="../doc/docs.css">\n
+\n
+<link rel="stylesheet" href="../lib/codemirror.css">\n
+<link rel="stylesheet" href="../addon/scroll/simplescrollbars.css">\n
+<script src="../lib/codemirror.js"></script>\n
+<script src="../mode/markdown/markdown.js"></script>\n
+<script src="../mode/xml/xml.js"></script>\n
+<script src="../addon/scroll/simplescrollbars.js"></script>\n
+\n
+<div id=nav>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
+\n
+  <ul>\n
+    <li><a href="../index.html">Home</a>\n
+    <li><a href="../doc/manual.html">Manual</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
+  </ul>\n
+  <ul>\n
+    <li><a class=active href="#">Simple Scrollbar</a>\n
+  </ul>\n
+</div>\n
+\n
+<article>\n
+<h2>Simple Scrollbar Demo</h2>\n
+<form><textarea id="code" name="code"># Custom Scrollbars\n
+\n
+This is a piece of text that creates scrollbars\n
+\n
+Lorem ipsum dolor sit amet, turpis nec facilisis neque vestibulum adipiscing, magna nunc est luctus orci a,\n
+aliquam duis ad volutpat nostra. Vestibulum ultricies suspendisse commodo volutpat pede sed. Bibendum odio\n
+dignissim, ad vitae mollis ac sed nibh quis, suspendisse diam, risus quas blandit phasellus luctus nec,\n
+integer nunc vitae posuere scelerisque. Lobortis quam porta conubia nulla. Et nisl ac, imperdiet vitae ac.\n
+Parturient sit. Et vestibulum euismod, rutrum nunc libero mauris purus convallis. Cum id adipiscing et eget\n
+pretium rutrum, ultrices sapien magnis fringilla sit lorem, eu vitae scelerisque ipsum aliquet, magna sed\n
+fusce vel.\n
+\n
+Lectus ultricies libero dolor convallis, sed etiam vel hendrerit egestas viverra, at urna mauris, eget\n
+vulputate dolor voluptatem, nulla eget sollicitudin. Sed tincidunt, elit sociis. Mattis mi tortor dui id\n
+sodales mi, maecenas nam fringilla risus turpis mauris praesent, imperdiet maecenas ultrices nonummy tellus\n
+quis est. Scelerisque nec pharetra quis varius fringilla. Varius vestibulum non dictum pharetra, tincidunt in\n
+vestibulum iaculis molestie, id condimentum blandit elit urna magna pulvinar, quam suspendisse pellentesque\n
+donec. Vel amet ad ac. Nec aut viverra, morbi mi neque massa, turpis enim proin. Tellus eu, fermentum velit\n
+est convallis aliquam velit, rutrum in diam lacus, praesent tempor pellentesque dictum semper augue. Felis\n
+explicabo massa amet lectus phasellus dolor. Ut lorem quis arcu neque felis ultricies, senectus vitae\n
+curabitur sed pellentesque et, id sed risus in sed ac accumsan, blandit arcu quam duis nunc.\n
+\n
+Sed leo sollicitudin odio vitae, purus sit egestas, justo eros inceptos auctor fermentum lectus. Ligula luctus\n
+turpis, quod massa vitae elementum orci, nullam fringilla elit tortor. Justo ante tempor amet quam posuere\n
+volutpat. Facilisis pede erat ut hac ultrices ipsum, wisi duis sit metus. Dolor vitae est sed sed vitae. Sed\n
+eu ligula, morbi vestibulum nunc nibh velit ut taciti, ligula elit semper sagittis in, auctor arcu vel eget.\n
+Mauris at vitae nec suspendisse et, aenean proin blandit suscipit. Morbi quam, dolor ultricies. Viverra\n
+tempus. Suspendisse sit dapibus, ac fuga aenean, magna nisl nonummy augue posuere, dictum ut fuga velit\n
+parturient augue interdum, mattis sit tellus.\n
+\n
+Vehicula commodo tempus curabitur eros, lacinia erat vulputate lorem vel fermentum donec, lectus sed conubia\n
+id pellentesque. Vel senectus donec pede aliquet dolor sit, nec vivamus justo placerat interdum maecenas,\n
+sodales euismod. Quis netus sapien amet, vestibulum quam nec amet lacinia, quis aliquet, tempor vivamus tellus\n
+enim, suscipit quis eleifend. Amet class phasellus orci pretium, risus in nulla. Neque sit ullamcorper,\n
+ultricies platea id nec suspendisse ac. Et elementum. Dictum nam, ut dui fermentum egestas facilisis elit\n
+augue, adipiscing donec ipsum erat nam pellentesque convallis, vestibulum vestibulum risus id nulla ut mauris,\n
+curabitur aute aptent. Ultrices orci wisi dui ipsum praesent, pharetra felis eu quis. Est fringilla etiam,\n
+maxime sem dapibus et eget, mi enim dignissim nec pretium, augue vehicula, volutpat proin. Et occaecati\n
+lobortis viverra, cum in sed, vivamus tellus. Libero at malesuada est vivamus leo tortor.\n
+</textarea></form>\n
+\n
+<p>The <a href="../doc/manual.html#addon_simplescrollbars"><code>simplescrollbars</code></a> addon defines two\n
+styles of non-native scrollbars: <a href="javascript:editor.setOption(\'scrollbarStyle\', \'simple\')"><code>"simple"</code></a> and <a href="javascript:editor.setOption(\'scrollbarStyle\', \'overlay\')"><code>"overlay"</code></a> (click to try), which can be passed to\n
+the <a href="../doc/manual.html#option_scrollbarStyle"><code>scrollbarStyle</code></a> option. These implement\n
+the scrollbar using DOM elements, allowing more control over\n
+its <a href="../addon/scroll/simplescrollbars.css">appearance</a>.</p>\n
+\n
+  <script>\n
+    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
+      lineNumbers: true,\n
+      scrollbarStyle: "simple"\n
+    });\n
+  </script>\n
+</article>
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>simplescrollbars.html</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/spanaffectswrapping_shim.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/spanaffectswrapping_shim.html.xml
index be569cd42b5d6a6dd78729e72c271b89897230f8..ffdca558aca5ce639d9ec6765568b5d2abb831c2 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/spanaffectswrapping_shim.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/spanaffectswrapping_shim.html.xml
@@ -43,12 +43,12 @@
 <link rel=stylesheet href="../doc/docs.css">\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Automatically derive odd wrapping behavior for your browser</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/sublime.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/sublime.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..be9986dc83dad7d40a6d7be540b9e461c6677433
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/sublime.html.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+\n
+<title>CodeMirror: Sublime Text bindings demo</title>\n
+<meta charset="utf-8"/>\n
+<link rel=stylesheet href="../doc/docs.css">\n
+\n
+<link rel="stylesheet" href="../lib/codemirror.css">\n
+<link rel="stylesheet" href="../addon/fold/foldgutter.css">\n
+<link rel="stylesheet" href="../addon/dialog/dialog.css">\n
+<link rel="stylesheet" href="../theme/monokai.css">\n
+<script src="../lib/codemirror.js"></script>\n
+<script src="../addon/search/searchcursor.js"></script>\n
+<script src="../addon/search/search.js"></script>\n
+<script src="../addon/dialog/dialog.js"></script>\n
+<script src="../addon/edit/matchbrackets.js"></script>\n
+<script src="../addon/edit/closebrackets.js"></script>\n
+<script src="../addon/comment/comment.js"></script>\n
+<script src="../addon/wrap/hardwrap.js"></script>\n
+<script src="../addon/fold/foldcode.js"></script>\n
+<script src="../addon/fold/brace-fold.js"></script>\n
+<script src="../mode/javascript/javascript.js"></script>\n
+<script src="../keymap/sublime.js"></script>\n
+<style type="text/css">\n
+  .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee; line-height: 1.3; height: 500px}\n
+  .CodeMirror-linenumbers { padding: 0 8px; }\n
+</style>\n
+<div id=nav>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
+\n
+  <ul>\n
+    <li><a href="../index.html">Home</a>\n
+    <li><a href="../doc/manual.html">Manual</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
+  </ul>\n
+  <ul>\n
+    <li><a class=active href="#">Sublime bindings</a>\n
+  </ul>\n
+</div>\n
+\n
+<article>\n
+<h2>Sublime Text bindings demo</h2>\n
+\n
+<p>The <code>sublime</code> keymap defines many Sublime Text-specific\n
+bindings for CodeMirror. See the code below for an overview.</p>\n
+\n
+<p>Enable the keymap by\n
+loading <a href="../keymap/sublime.js"><code>keymap/sublime.js</code></a>\n
+and setting\n
+the <a href="../doc/manual.html#option_keyMap"><code>keyMap</code></a>\n
+option to <code>"sublime"</code>.</p>\n
+\n
+<p>(A lot of the search functionality is still missing.)\n
+\n
+<script>\n
+  var value = "// The bindings defined specifically in the Sublime Text mode\\nvar bindings = {\\n";\n
+  var map = CodeMirror.keyMap.sublime;\n
+  for (var key in map) {\n
+    var val = map[key];\n
+    if (key != "fallthrough" && val != "..." && (!/find/.test(val) || /findUnder/.test(val)))\n
+      value += "  \\"" + key + "\\": \\"" + val + "\\",\\n";\n
+  }\n
+  value += "}\\n\\n// The implementation of joinLines\\n";\n
+  value += CodeMirror.commands.joinLines.toString().replace(/^function\\s*\\(/, "function joinLines(").replace(/\\n  /g, "\\n") + "\\n";\n
+  var editor = CodeMirror(document.body.getElementsByTagName("article")[0], {\n
+    value: value,\n
+    lineNumbers: true,\n
+    mode: "javascript",\n
+    keyMap: "sublime",\n
+    autoCloseBrackets: true,\n
+    matchBrackets: true,\n
+    showCursorWhenSelecting: true,\n
+    theme: "monokai"\n
+  });\n
+</script>\n
+\n
+</article>
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>sublime.html</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/tern.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/tern.html.xml
index a4408f9e37d11e04611632e6bdbc263fc8910902..765aed21ed53e74c5cd1c445002e06b11d3f739d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/tern.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/tern.html.xml
@@ -65,12 +65,12 @@
       .CodeMirror {border: 1px solid #ddd;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Tern</a>\n
@@ -80,7 +80,7 @@
 <article>\n
 <h2>Tern Demo</h2>\n
 <form><textarea id="code" name="code">// Use ctrl-space to complete something\n
-// Put the cursor in or after an expression, press ctrl-i to\n
+// Put the cursor in or after an expression, press ctrl-o to\n
 // find its type\n
 \n
 var foo = ["array", "of", "strings"];\n
@@ -121,9 +121,11 @@ and CodeMirror. The following keys are bound:</p>\n
 \n
 <dl>\n
   <dt>Ctrl-Space</dt><dd>Autocomplete</dd>\n
+  <dt>Ctrl-O</dt><dd>Find docs for the expression at the cursor</dd>\n
   <dt>Ctrl-I</dt><dd>Find type at cursor</dd>\n
   <dt>Alt-.</dt><dd>Jump to definition (Alt-, to jump back)</dd>\n
   <dt>Ctrl-Q</dt><dd>Rename variable</dd>\n
+  <dt>Ctrl-.</dt><dd>Select all occurrences of a variable</dd>\n
 </dl>\n
 \n
 <p>Documentation is sparse for now. See the top of\n
@@ -151,9 +153,11 @@ overview.</p>\n
     editor.setOption("extraKeys", {\n
       "Ctrl-Space": function(cm) { server.complete(cm); },\n
       "Ctrl-I": function(cm) { server.showType(cm); },\n
+      "Ctrl-O": function(cm) { server.showDocs(cm); },\n
       "Alt-.": function(cm) { server.jumpToDef(cm); },\n
       "Alt-,": function(cm) { server.jumpBack(cm); },\n
       "Ctrl-Q": function(cm) { server.rename(cm); },\n
+      "Ctrl-.": function(cm) { server.selectName(cm); }\n
     })\n
     editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); });\n
   });\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/theme.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/theme.html.xml
index 9542a3f3e839ad7c7bced6a27941bb7adbb15fb1..c9ed25fe5baee7418742a74f360016cab8200370 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/theme.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/theme.html.xml
@@ -59,6 +59,7 @@
 <link rel="stylesheet" href="../theme/midnight.css">\n
 <link rel="stylesheet" href="../theme/monokai.css">\n
 <link rel="stylesheet" href="../theme/neat.css">\n
+<link rel="stylesheet" href="../theme/neo.css">\n
 <link rel="stylesheet" href="../theme/night.css">\n
 <link rel="stylesheet" href="../theme/paraiso-dark.css">\n
 <link rel="stylesheet" href="../theme/paraiso-light.css">\n
@@ -66,26 +67,27 @@
 <link rel="stylesheet" href="../theme/rubyblue.css">\n
 <link rel="stylesheet" href="../theme/solarized.css">\n
 <link rel="stylesheet" href="../theme/the-matrix.css">\n
+<link rel="stylesheet" href="../theme/tomorrow-night-bright.css">\n
 <link rel="stylesheet" href="../theme/tomorrow-night-eighties.css">\n
 <link rel="stylesheet" href="../theme/twilight.css">\n
 <link rel="stylesheet" href="../theme/vibrant-ink.css">\n
 <link rel="stylesheet" href="../theme/xq-dark.css">\n
 <link rel="stylesheet" href="../theme/xq-light.css">\n
+<link rel="stylesheet" href="../theme/zenburn.css">\n
 <script src="../lib/codemirror.js"></script>\n
 <script src="../mode/javascript/javascript.js"></script>\n
-<script src="../keymap/extra.js"></script>\n
 <script src="../addon/selection/active-line.js"></script>\n
 <script src="../addon/edit/matchbrackets.js"></script>\n
 <style type="text/css">\n
       .CodeMirror {border: 1px solid black; font-size:13px}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Theme</a>\n
@@ -126,6 +128,7 @@ function findSequence(goal) {\n
     <option>midnight</option>\n
     <option>monokai</option>\n
     <option>neat</option>\n
+    <option>neo</option>\n
     <option>night</option>\n
     <option>paraiso-dark</option>\n
     <option>paraiso-light</option>\n
@@ -134,11 +137,13 @@ function findSequence(goal) {\n
     <option>solarized dark</option>\n
     <option>solarized light</option>\n
     <option>the-matrix</option>\n
+    <option>tomorrow-night-bright</option>\n
     <option>tomorrow-night-eighties</option>\n
     <option>twilight</option>\n
     <option>vibrant-ink</option>\n
     <option>xq-dark</option>\n
     <option>xq-light</option>\n
+    <option>zenburn</option>\n
 </select>\n
 </p>\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/trailingspace.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/trailingspace.html.xml
index d928ded949ee313d706ae6e1ec49c137fc8f4542..a70cb0b75191156c2ab94ff73f2b6d9f76659495 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/trailingspace.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/trailingspace.html.xml
@@ -54,12 +54,12 @@
       }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Trailing Whitespace</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/variableheight.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/variableheight.html.xml
index 547e809fbc435da97608ea13fd6ba4621e09e0fe..64ede38122d9e91d333aaaa3a489ffb1028e1bbc 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/variableheight.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/variableheight.html.xml
@@ -58,12 +58,12 @@
       .cm-strong { font-size: 140%; }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Variable Height</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/vim.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/vim.html.xml
index 6700e8b91876af480484ed598e44218299ea0c77..c0f22ff6cd678ddbba99fd116de9d4a66c1a8f04 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/vim.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/vim.html.xml
@@ -48,17 +48,18 @@
 <script src="../addon/dialog/dialog.js"></script>\n
 <script src="../addon/search/searchcursor.js"></script>\n
 <script src="../mode/clike/clike.js"></script>\n
+<script src="../addon/edit/matchbrackets.js"></script>\n
 <script src="../keymap/vim.js"></script>\n
 <style type="text/css">\n
       .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Vim bindings</a>\n
@@ -82,30 +83,54 @@ int getchar(void)\n
   return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n
 }\n
 </textarea></form>\n
-\n
-    <form><textarea id="code2" name="code2">\n
-        I am another file! You can yank from my neighbor and paste here.\n
-</textarea></form>\n
+<div style="font-size: 13px; width: 300px; height: 30px;">Key buffer: <span id="command-display"></span></div>\n
 \n
 <p>The vim keybindings are enabled by\n
 including <a href="../keymap/vim.js">keymap/vim.js</a> and setting\n
-the <code>keyMap</code> option to <code>"vim"</code>. Because\n
-CodeMirror\'s internal API is quite different from Vim, they are only\n
-a loose approximation of actual vim bindings, though.</p>\n
+the <code>vimMode</code> option to <code>true</code>. This will also\n
+automatically change the <code>keyMap</code> option to <code>"vim"</code>.</p>\n
+\n
+<p><strong>Features</strong></p>\n
+\n
+<ul>\n
+  <li>All common motions and operators, including text objects</li>\n
+  <li>Operator motion orthogonality</li>\n
+  <li>Visual mode - characterwise, linewise, partial support for blockwise</li>\n
+  <li>Full macro support (q, @)</li>\n
+  <li>Incremental highlighted search (/, ?, #, *, g#, g*)</li>\n
+  <li>Search/replace with confirm (:substitute, :%s)</li>\n
+  <li>Search history</li>\n
+  <li>Jump lists (Ctrl-o, Ctrl-i)</li>\n
+  <li>Key/command mapping with API (:map, :nmap, :vmap)</li>\n
+  <li>Sort (:sort)</li>\n
+  <li>Marks (`, \')</li>\n
+  <li>:global</li>\n
+  <li>Insert mode behaves identical to base CodeMirror</li>\n
+  <li>Cross-buffer yank/paste</li>\n
+</ul>\n
+\n
+<p>Note that while the vim mode tries to emulate the most useful features of\n
+vim as faithfully as possible, it does not strive to become a complete vim\n
+implementation</p>\n
 \n
     <script>\n
       CodeMirror.commands.save = function(){ alert("Saving"); };\n
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {\n
         lineNumbers: true,\n
         mode: "text/x-csrc",\n
-        vimMode: true,\n
+        keyMap: "vim",\n
+        matchBrackets: true,\n
         showCursorWhenSelecting: true\n
       });\n
-      var editor2 = CodeMirror.fromTextArea(document.getElementById("code2"), {\n
-        lineNumbers: true,\n
-        mode: "text/x-csrc",\n
-        vimMode: true,\n
-        showCursorWhenSelecting: true\n
+      var commandDisplay = document.getElementById(\'command-display\');\n
+      var keys = \'\';\n
+      CodeMirror.on(editor, \'vim-keypress\', function(key) {\n
+        keys = keys + key;\n
+        commandDisplay.innerHTML = keys;\n
+      });\n
+      CodeMirror.on(editor, \'vim-command-done\', function(e) {\n
+        keys = \'\';\n
+        commandDisplay.innerHTML = keys;\n
       });\n
     </script>\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/visibletabs.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/visibletabs.html.xml
index 495f4122dd590979a2708d50cce34d5037b926f7..a26ec49a70cef5fe2f895647349a8a1f0257e150 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/visibletabs.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/visibletabs.html.xml
@@ -54,12 +54,12 @@
       }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Visible tabs</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/widget.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/widget.html.xml
index 1ee7977553bbff1252f5ec1673fdc30162c2c234..1d9f19452fb70557ad74469d591624e22cab5912 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/widget.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/widget.html.xml
@@ -45,19 +45,19 @@
 <link rel="stylesheet" href="../lib/codemirror.css">\n
 <script src="../lib/codemirror.js"></script>\n
 <script src="../mode/javascript/javascript.js"></script>\n
-<script src="http://ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>\n
+<script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>\n
 <style type="text/css">\n
       .CodeMirror {border: 1px solid black;}\n
       .lint-error {font-family: arial; font-size: 70%; background: #ffa; color: #a00; padding: 2px 5px 3px; }\n
       .lint-error-icon {color: white; background-color: red; font-weight: bold; border-radius: 50%; padding: 0 3px; margin-right: 7px;}\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Inline Widget</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/xmlcomplete.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/xmlcomplete.html.xml
index 379d8350e889b43e7f9eb0b9e10ff2cfe9a4fba4..4ff7d4d1f5dede522169ec8f891ce83f2f97d859 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/xmlcomplete.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/demo/xmlcomplete.html.xml
@@ -52,12 +52,12 @@
       .CodeMirror { border: 1px solid #eee; }\n
     </style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">XML Autocomplete</a>\n
@@ -90,6 +90,10 @@
 \n
       var tags = {\n
         "!top": ["top"],\n
+        "!attrs": {\n
+          id: null,\n
+          class: ["A", "B", "C"]\n
+        },\n
         top: {\n
           attrs: {\n
             lang: ["en", "de", "fr", "nl"],\n
@@ -116,7 +120,7 @@
         var cur = cm.getCursor();\n
         if (!pred || pred()) setTimeout(function() {\n
           if (!cm.state.completionActive)\n
-            CodeMirror.showHint(cm, CodeMirror.hint.xml, {schemaInfo: tags, completeSingle: false});\n
+            cm.showHint({completeSingle: false});\n
         }, 100);\n
         return CodeMirror.Pass;\n
       }\n
@@ -145,10 +149,9 @@
           "\'/\'": completeIfAfterLt,\n
           "\' \'": completeIfInTag,\n
           "\'=\'": completeIfInTag,\n
-          "Ctrl-Space": function(cm) {\n
-            CodeMirror.showHint(cm, CodeMirror.hint.xml, {schemaInfo: tags});\n
-          }\n
-        }\n
+          "Ctrl-Space": "autocomplete"\n
+        },\n
+        hintOptions: {schemaInfo: tags}\n
       });\n
     </script>\n
   </article>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/activebookmark.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/activebookmark.js.xml
index 01331ef4ff9f331f8c4be898792e94fe262ca3c7..0a229ef12c2a88aa733da05eaf5bf2c8505731c5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/activebookmark.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/activebookmark.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403084.07</string> </value>
+            <value> <string>ts21897129.72</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -27,6 +27,7 @@ document.createElement("section");\n
 document.createElement("article");\n
 \n
 (function() {\n
+  if (!window.addEventListener) return;\n
   var pending = false, prevVal = null;\n
 \n
   function updateSoon() {\n
@@ -65,10 +66,18 @@ document.createElement("article");\n
     }\n
   }\n
 \n
-  if (window.addEventListener) {\n
-    window.addEventListener("scroll", updateSoon);\n
-    window.addEventListener("load", updateSoon);\n
-  }\n
+  window.addEventListener("scroll", updateSoon);\n
+  window.addEventListener("load", updateSoon);\n
+  window.addEventListener("hashchange", function() {\n
+    setTimeout(function() {\n
+      var hash = document.location.hash, found = null, m;\n
+      var marks = document.getElementById("nav").getElementsByTagName("a");\n
+      for (var i = 0; i < marks.length; i++)\n
+        if ((m = marks[i].href.match(/(#.*)/)) && m[1] == hash) { found = i; break; }\n
+      if (found != null) for (var i = 0; i < marks.length; i++)\n
+        marks[i].className = i == found ? "active" : "";\n
+    }, 300);\n
+  });\n
 })();\n
 
 
@@ -80,7 +89,7 @@ document.createElement("article");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1412</int> </value>
+            <value> <int>1897</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/compress.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/compress.html.xml
index 254f333447acc4b20eeffb90e8e349ba24baa9bf..b0edbd88b8ea42644e3458ad9ae21ed4922b5e80 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/compress.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/compress.html.xml
@@ -41,14 +41,17 @@
 <title>CodeMirror: Compression Helper</title>\n
 <meta charset="utf-8"/>\n
 <link rel=stylesheet href="docs.css">\n
+<script src="../lib/codemirror.js"></script>\n
+<script src="../mode/javascript/javascript.js"></script>\n
+<link rel=stylesheet href="../lib/codemirror.css">\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Compression helper</a>\n
@@ -67,10 +70,24 @@
     click <strong>Compress</strong> to download the minified script\n
     file.</p>\n
 \n
-    <form id="form" action="http://marijnhaverbeke.nl/uglifyjs" method="post">\n
+    <form id="form" action="http://marijnhaverbeke.nl/uglifyjs" method="post" onsubmit="generateHeader();">\n
       <input type="hidden" id="download" name="download" value="codemirror-compressed.js"/>\n
       <p>Version: <select id="version" onchange="setVersion(this);" style="padding: 1px;">\n
         <option value="http://codemirror.net/">HEAD</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.11.0;f=">4.11</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.10.0;f=">4.10</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.9.0;f=">4.9</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.8.0;f=">4.8</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.7.0;f=">4.7</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.6.0;f=">4.6</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.5.0;f=">4.5</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.4.0;f=">4.4</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.3.0;f=">4.3</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.1;f=">4.2</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.0;f=">4.2</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.1.0;f=">4.1</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.0.3;f=">4.0</option>\n
+        <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.23.0;f=">3.23</option>\n
         <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.22.0;f=">3.22</option>\n
         <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.21.0;f=">3.21</option>\n
         <option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.20.0;f=">3.20</option>\n
@@ -127,9 +144,15 @@
           <option value="http://codemirror.net/mode/coffeescript/coffeescript.js">coffeescript.js</option>\n
           <option value="http://codemirror.net/mode/commonlisp/commonlisp.js">commonlisp.js</option>\n
           <option value="http://codemirror.net/mode/css/css.js">css.js</option>\n
+          <option value="http://codemirror.net/mode/cypher/cypher.js">cypher.js</option>\n
           <option value="http://codemirror.net/mode/d/d.js">d.js</option>\n
+          <option value="http://codemirror.net/mode/dart/dart.js">dart.js</option>\n
           <option value="http://codemirror.net/mode/diff/diff.js">diff.js</option>\n
+          <option value="http://codemirror.net/mode/django/django.js">django.js</option>\n
+          <option value="http://codemirror.net/mode/dockerfile/dockerfile.js">dockerfile.js</option>\n
           <option value="http://codemirror.net/mode/dtd/dtd.js">dtd.js</option>\n
+          <option value="http://codemirror.net/mode/dylan/dylan.js">dylan.js</option>\n
+          <option value="http://codemirror.net/mode/ebnf/ebnf.js">ebnf.js</option>\n
           <option value="http://codemirror.net/mode/ecl/ecl.js">ecl.js</option>\n
           <option value="http://codemirror.net/mode/eiffel/eiffel.js">eiffel.js</option>\n
           <option value="http://codemirror.net/mode/erlang/erlang.js">erlang.js</option>\n
@@ -145,16 +168,18 @@
           <option value="http://codemirror.net/mode/htmlembedded/htmlembedded.js">htmlembedded.js</option>\n
           <option value="http://codemirror.net/mode/htmlmixed/htmlmixed.js">htmlmixed.js</option>\n
           <option value="http://codemirror.net/mode/http/http.js">http.js</option>\n
+          <option value="http://codemirror.net/mode/idl/idl.js">idl.js</option>\n
           <option value="http://codemirror.net/mode/jade/jade.js">jade.js</option>\n
           <option value="http://codemirror.net/mode/javascript/javascript.js">javascript.js</option>\n
           <option value="http://codemirror.net/mode/jinja2/jinja2.js">jinja2.js</option>\n
-          <option value="http://codemirror.net/mode/julia/julia.js">jinja2.js</option>\n
-          <option value="http://codemirror.net/mode/less/less.js">less.js</option>\n
+          <option value="http://codemirror.net/mode/julia/julia.js">julia.js</option>\n
+          <option value="http://codemirror.net/mode/kotlin/kotlin.js">kotlin.js</option>\n
           <option value="http://codemirror.net/mode/livescript/livescript.js">livescript.js</option>\n
           <option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>\n
           <option value="http://codemirror.net/mode/markdown/markdown.js">markdown.js</option>\n
           <option value="http://codemirror.net/mode/mirc/mirc.js">mirc.js</option>\n
           <option value="http://codemirror.net/mode/mllike/mllike.js">mllike.js</option>\n
+          <option value="http://codemirror.net/mode/modelica/modelica.js">modelica.js</option>\n
           <option value="http://codemirror.net/mode/nginx/nginx.js">nginx.js</option>\n
           <option value="http://codemirror.net/mode/ntriples/ntriples.js">ntriples.js</option>\n
           <option value="http://codemirror.net/mode/octave/octave.js">octave.js</option>\n
@@ -168,8 +193,7 @@
           <option value="http://codemirror.net/mode/puppet/puppet.js">puppet.js</option>\n
           <option value="http://codemirror.net/mode/q/q.js">q.js</option>\n
           <option value="http://codemirror.net/mode/r/r.js">r.js</option>\n
-          <option value="http://codemirror.net/mode/rpm/changes/changes.js">rpm/changes.js</option>\n
-          <option value="http://codemirror.net/mode/rpm/spec/spec.js">rpm/spec.js</option>\n
+          <option value="http://codemirror.net/mode/rpm/rpm.js">rpm.js</option>\n
           <option value="http://codemirror.net/mode/rst/rst.js">rst.js</option>\n
           <option value="http://codemirror.net/mode/ruby/ruby.js">ruby.js</option>\n
           <option value="http://codemirror.net/mode/rust/rust.js">rust.js</option>\n
@@ -178,16 +202,22 @@
           <option value="http://codemirror.net/mode/scheme/scheme.js">scheme.js</option>\n
           <option value="http://codemirror.net/mode/shell/shell.js">shell.js</option>\n
           <option value="http://codemirror.net/mode/sieve/sieve.js">sieve.js</option>\n
+          <option value="http://codemirror.net/mode/slim/slim.js">slim.js</option>\n
           <option value="http://codemirror.net/mode/smalltalk/smalltalk.js">smalltalk.js</option>\n
           <option value="http://codemirror.net/mode/smarty/smarty.js">smarty.js</option>\n
           <option value="http://codemirror.net/mode/smartymixed/smartymixed.js">smartymixed.js</option>\n
-          <option value="http://codemirror.net/mode/sql/sql.js">sql.js</option>\n
+          <option value="http://codemirror.net/mode/solr/solr.js">solr.js</option>\n
+          <option value="http://codemirror.net/mode/soy/soy.js">soy.js</option>\n
           <option value="http://codemirror.net/mode/sparql/sparql.js">sparql.js</option>\n
+          <option value="http://codemirror.net/mode/spreadsheet/spreadsheet.js">spreadsheet.js</option>\n
+          <option value="http://codemirror.net/mode/sql/sql.js">sql.js</option>\n
           <option value="http://codemirror.net/mode/stex/stex.js">stex.js</option>\n
           <option value="http://codemirror.net/mode/tcl/tcl.js">tcl.js</option>\n
+          <option value="http://codemirror.net/mode/textile/textile.js">textile.js</option>\n
           <option value="http://codemirror.net/mode/tiddlywiki/tiddlywiki.js">tiddlywiki.js</option>\n
           <option value="http://codemirror.net/mode/tiki/tiki.js">tiki.js</option>\n
           <option value="http://codemirror.net/mode/toml/toml.js">toml.js</option>\n
+          <option value="http://codemirror.net/mode/tornado/tornado.js">tornado.js</option>\n
           <option value="http://codemirror.net/mode/turtle/turtle.js">turtle.js</option>\n
           <option value="http://codemirror.net/mode/vb/vb.js">vb.js</option>\n
           <option value="http://codemirror.net/mode/vbscript/vbscript.js">vbscript.js</option>\n
@@ -230,9 +260,7 @@
           <option value="http://codemirror.net/addon/merge/merge.js">merge.js</option>\n
           <option value="http://codemirror.net/addon/mode/multiplex.js">multiplex.js</option>\n
           <option value="http://codemirror.net/addon/mode/overlay.js">overlay.js</option>\n
-          <option value="http://codemirror.net/addon/hint/pig-hint.js">pig-hint.js</option>\n
           <option value="http://codemirror.net/addon/display/placeholder.js">placeholder.js</option>\n
-          <option value="http://codemirror.net/addon/hint/python-hint.js">python-hint.js</option>\n
           <option value="http://codemirror.net/addon/display/rulers.js">rulers.js</option>\n
           <option value="http://codemirror.net/addon/runmode/runmode.js">runmode.js</option>\n
           <option value="http://codemirror.net/addon/runmode/runmode.node.js">runmode.node.js</option>\n
@@ -240,6 +268,8 @@
           <option value="http://codemirror.net/addon/search/search.js">search.js</option>\n
           <option value="http://codemirror.net/addon/search/searchcursor.js">searchcursor.js</option>\n
           <option value="http://codemirror.net/addon/hint/show-hint.js">show-hint.js</option>\n
+          <option value="http://codemirror.net/addon/mode/simple.js">simple.js</option>\n
+          <option value="http://codemirror.net/addon/scroll/simplescrollbars.js">simplescrollbars.js</option>\n
           <option value="http://codemirror.net/addon/hint/sql-hint.js">sql-hint.js</option>\n
           <option value="http://codemirror.net/addon/edit/trailingspace.js">trailingspace.js</option>\n
           <option value="http://codemirror.net/addon/tern/tern.js">tern.js</option>\n
@@ -249,6 +279,7 @@
         </optgroup>\n
         <optgroup label="Keymaps">\n
           <option value="http://codemirror.net/keymap/emacs.js">emacs.js</option>\n
+          <option value="http://codemirror.net/keymap/sublime.js">sublime.js</option>\n
           <option value="http://codemirror.net/keymap/vim.js">vim.js</option>\n
         </optgroup>\n
       </select>\n
@@ -256,11 +287,13 @@
       <p>\n
         <button type="submit">Compress</button> with <a href="http://github.com/mishoo/UglifyJS/">UglifyJS</a>\n
       </p>\n
-\n
-      <p>Custom code to add to the compressed file:<textarea name="js_code" style="width: 100%; height: 15em;" class="field"></textarea></p>\n
+      <input type="hidden" id="header" name="header">\n
+      <p>Custom code to add to the compressed file:<textarea name="js_code" style="width: 100%; height: 15em;" class="field" id="js_code"></textarea></p>\n
     </form>\n
 \n
     <script type="text/javascript">\n
+      CodeMirror.fromTextArea(document.getElementById("js_code")).getWrapperElement().className += " field";\n
+\n
       function setVersion(ver) {\n
         var urlprefix = ver.options[ver.selectedIndex].value;\n
         var select = document.getElementById("files"), m;\n
@@ -274,6 +307,36 @@
               opt.value = urlprefix + m[1];\n
           }\n
        }\n
+       \n
+       function generateHeader() {\n
+         var versionNode = document.getElementById("version");\n
+         var version = versionNode.options[versionNode.selectedIndex].label\n
+         var filesNode = document.getElementById("files");\n
+         var optGroupHeaderIncluded;\n
+\n
+         // Generate the comment\n
+         var str = "/* CodeMirror - Minified & Bundled\\n";\n
+         str += "   Generated on " + new Date().toLocaleDateString() + " with http://codemirror.net/doc/compress.html\\n";\n
+         str += "   Version: " + version + "\\n\\n";\n
+\n
+         for (var group = filesNode.firstChild; group; group = group.nextSibling) {\n
+           optGroupHeaderIncluded = false;\n
+           for (var option = group.firstChild; option; option = option.nextSibling) {\n
+             if (option.nodeName !== "OPTION") {\n
+               continue;\n
+             } else if (option.selected) {\n
+               if (!optGroupHeaderIncluded) {\n
+                 str += "   " + group.label + ":\\n";\n
+                 optGroupHeaderIncluded = true;\n
+               }\n
+               str += "   - " + option.label + "\\n";\n
+             }\n
+           }\n
+         }\n
+         str += " */\\n\\n";\n
+\n
+         document.getElementById("header").value = str;\n
+       }\n
     </script>\n
 \n
 </article>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/docs.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/docs.css.xml
index 9d863942adc7cf8b3009448063221e32a9b10dc1..a8640cb01ab895ad4536efe4960af6f131632cb2 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/docs.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/docs.css.xml
@@ -30,7 +30,7 @@
   font-family: \'Source Sans Pro\';\n
   font-style: normal;\n
   font-weight: 400;\n
-  src: local(\'Source Sans Pro\'), local(\'SourceSansPro-Regular\'), url(http://themes.googleusercontent.com/static/fonts/sourcesanspro/v5/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format(\'woff\');\n
+  src: local(\'Source Sans Pro\'), local(\'SourceSansPro-Regular\'), url(//themes.googleusercontent.com/static/fonts/sourcesanspro/v5/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format(\'woff\');\n
 }\n
 \n
 body, html { margin: 0; padding: 0; height: 100%; }\n
@@ -44,14 +44,23 @@ body {\n
 \n
 p { margin-top: 0; }\n
 \n
-h2, h3 {\n
+h2, h3, h1 {\n
   font-weight: normal;\n
   margin-bottom: .7em;\n
 }\n
+h1 { font-size: 140%; }\n
 h2 { font-size: 120%; }\n
 h3 { font-size: 110%; }\n
 article > h2:first-child, section:first-child > h2 { margin-top: 0; }\n
 \n
+#nav h1 {\n
+  margin-right: 12px;\n
+  margin-top: 0;\n
+  margin-bottom: 2px;\n
+  color: #d30707;\n
+  letter-spacing: .5px;\n
+}\n
+\n
 a, a:visited, a:link, .quasilink {\n
   color: #A21313;\n
   text-decoration: none;\n
@@ -83,10 +92,11 @@ article {\n
   position: fixed;\n
   padding-top: 30px;\n
   max-height: 100%;\n
-  overflow-y:scroll;\n
+  box-sizing: -moz-border-box;\n
+  box-sizing: border-box;\n
+  overflow-y: auto;\n
   left: 0; right: none;\n
   width: 160px;\n
-  padding-right: 350px;\n
   text-align: right;\n
   z-index: 1;\n
 }\n
@@ -98,6 +108,7 @@ article {\n
   #nav {\n
     right: 50%;\n
     width: auto;\n
+    border-right: 349px solid transparent;\n
   }\n
 }\n
 \n
@@ -124,6 +135,7 @@ article {\n
 \n
 #nav li li a {\n
   padding-right: 20px;\n
+  display: inline-block;\n
 }\n
 \n
 #nav ul a {\n
@@ -133,12 +145,13 @@ article {\n
 \n
 #nav ul a.active, #nav ul a:hover {\n
   border-bottom: 1px solid #E30808;\n
+  margin-bottom: -1px;\n
   color: #E30808;\n
 }\n
 \n
 #logo {\n
   border: 0;\n
-  margin-right: 7px;\n
+  margin-right: 12px;\n
   margin-bottom: 25px;\n
 }\n
 \n
@@ -163,7 +176,7 @@ section.first {\n
   z-index: 25;\n
 }\n
 \n
-#bankinfo {\n
+.bankinfo {\n
   text-align: left;\n
   display: none;\n
   padding: 0 .5em;\n
@@ -175,7 +188,7 @@ section.first {\n
   left: 30px;\n
 }\n
 \n
-#bankinfo_close {\n
+.bankinfo_close {\n
   position: absolute;\n
   top: 0; right: 6px;\n
   font-weight: bold;\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/internals.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/internals.html.xml
index 753b8a9b6b491c8df4bcabddb26d43a0b033e2df..ec1f67429764772e9a1bbf40fbc818796314b03f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/internals.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/internals.html.xml
@@ -45,12 +45,12 @@
 <script src="activebookmark.js"></script>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="#top">Introduction</a></li>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.png.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.png.xml
index 40592cbb09fb2bd0db225c0abeb76a6ebd58446a..a23c75501cbf90a514c1f750827ba17d98b0c61e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.png.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.png.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403083.15</string> </value>
+            <value> <string>ts21897130.77</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,221 +20,174 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAJMAAACQCAYAAAAMcVm7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz
-AAAEOQAABDkBNNJBtAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURB
-VHic7X15eBRV1v57q3rJvnV1p4EkQFYSZBMcYNiRUUBUFFEEGpkZt2HEbZRPPhXlY9Dx+xzGgXEZ
-10AHEHFB/DEgoKDsKIKyhYQlIYRs1UlIIEt3V53fH9UdOt2dDZJ0J/F9nvNU113PvXX63nPP3RgR
-oSuDMcanpaX902AwjK6pqVGLorjx9OnTrxFRqa9562hgXUmYevXqNScsLGyOTqfT19TUXLl06dJ5
-Iop75513bhwzZowWAA4fPkzz5s3LKioq2qDVatOCgoJ0NptNysvLW1pWVva1r8vg1yCiLkFpaWlr
-3nrrrfLa2lpyory8nIqLi8kd5eXldOTIEbp8+TIREVVVVdFbb71VnpqausXX5fBn8jkDbV5AgPXo
-0ePRDz/8sIKuE1988cWVxMTEJb4uk79Sp+zmtFptQp8+fdYLghCi0Wg0aWlpQX//+9/1rZH2a6+9
-Ztm9e/clq9VaU1paasvLy3ussLBwd2uk3dHR6YTJYDAMGjhw4Beffvppz7CwsCbDV1RU4MyZM8jK
-yqotKiqqSklJiUhISGA9e/aEWq1uNK7NZsMf//jHgv379z+dlZX1cWuVoaOi0wnToEGDvtq9e/eU
-4OBgr/5EhM2bN1vfeOON86WlpYU1NTX5gZcv5/EXL2Yft9kODw4Lm3rJYDBoVaqb5OBg6j9wYPTz
-zz/frXfv3g3mOXTo0KMHDhzo31Zl6ihQ+ZqB1gRjTDNlypRkb4JUXV2N9957r3xNRsaFyPz8g1Or
-qz+fV1q6yTXMKkGYrbLbX5cqK61kt9/FiWLQnqys8rk7dz4empzc/b8WLowZNWqUR3M1fPhwPWMs
-mYiy2rB4fo9O0TL16tVrVnh4+INGo7Hn4sWLewwbNkzj6r9t27bqZ/7yl6Pa8+ffmB8Q8I1kt0dp
-eb7s/qKiItdwawyGJEmSRkuM7VERxQLgZcaiwZihwG4/+GF4+KheKSlzV69enSAIQl28c+fO4Ykn
-nsjOzc3NKyoq+rSoqOjfRCS3T+n9CL4eAVwv9erVa/bzzz9fXl1dTe6QZZkWLlxYnJyc/AYcf5zr
-JQDd+/Xr98OePXus7vlZrVZ69913qxMSEv7p63rxBfmcgev8sNyIESPOuH9UIiJRFGnChAk5MTEx
-d7ZBvqrk5OSVf/vb3yze8n7ggQeKAPTxdf20+/fwNQPX+VGFRx555Lz7xywtLaWBAwdmAoh7GeBW
-RUaO9BY/Xa8fTUT4d/fuQR8IQmhz8zVHRU3MiIqKiYuLe2j+/PlF7vmvWbPGBuA2X9dPe1OHVcAZ
-Y1q9Xv9wz549g1zdbTYb7r7rrpwjR45MJKLzqwThThtj35qjokYCOE8cZ2RE/Xie/57J8gAA3wfV
-1EySgZ7vMrbiYSKb2WgMZnb770BULDMWxAEhsy2WL50SLBNdlLTa2r9euWJ5d+PGjW+lpEyf9+c/
-hzt5iI6OVun1+pmMsd1EdKl9a8Z34HzNwLUgLS3t/yZOnPjzypUrX3ruued0rn5zH3jg4i9Hj84k
-ohwA4IhUfygpqQTPp5JKpWNEPcHYMVmWhwMoW88YT0SnOI7b+TCRDQBsksQRECEBIQwIIyDCNY85
-paW//L6goIQA466cnIcyli07snXr1mqn//jx4/Hpp5/eN3ny5MMpKSlrGWPatq8V36PDjeaMRuPk
-v/zlL6ufffbZCHe/RYsWlXy7cuWru3Nz/+F0W6nT9eWBcJKkAlKpRhPRj4yxcpnj9GpJEmWOGxQQ
-ELC9urr6Xjk0dN3cc+dqmsvLSp3uFg5gVsbK3oyKejtjw4YBaWlpvGuY7777zjZ37tz/O3fu3PPX
-V/IOAF/3sy2lQYMG7bdaPQZStHfvXltycvIyb3Faog9dKwEIGjx48Am73e7B2+jRo7N8XW/tQR2u
-m+N53u4+zSHLMp555pnTWVlZz3mL84eSksq25ouIqvLz859btmxZmbtfQEBAx2r+rxEdSpgYY4aC
-ggK9JEn13N95550KW07OCiKymgXh8dU6XZrTb01ERGSGTjfRW3qr9PpxAGA2Gg0Zen235vJhFoS5
-GXp9irt7QUHBxvT09KMlJSX13MvLy3nGWExz0++o6DCjucTExBfvueeeh1588cUYnr+qlpSXl+O9
-t9/OfspqPblap4sBY4k8x33q9Jd5/nezS0vXr9Lp7uGBE8RxvUmWk0H0A8fz4wDsYDbbKNfR3HqD
-IaSGaAoDCgEEExBqEsV1zv7MrlZvYpLEZ+h008BxGiJSMSCW47j1U2prdzz15JNJGatX1wnnxx9/
-nPDKK68cSE1N3Z6Zmfl76qTW8Q7RMqlUqjGzZs16av369bH9+/dnrn4LFiwounz69DyOKPZ0aelF
-AD/NKCm56BJEAhFxQITMmJFkOQiM7QXHJcqyfHxtdHQ0MXaCZ+znAqB+k9cAfl9QUDK3uLiQGLuZ
-iEYAiJSBfFmS9P1Uqq0/Hzy44/Dhw3UC07t3b7z33nvdlyxZMiMxMdFrV9wZ0CFGcykpKeadO3fO
-7tatfk9UWVmJkSNHfvPzzz9PMEdFjQwoKzt4Ra+PmltcXOgM81G3bnrOah1UGxCwO8BqHSqpVMfI
-bq/hGAsO1movVVdVDZxTWrrfrNONC7BYdk8nsjaXL7PRaFARMVt1tZ3TantqAwJOWquq1LNLS9n9
-M2YcXbN2baxreCLCsGHD9h04cOC3110p/ghfjwCaQ2lpadtcl9s68dZbb1VGRET8ztf8eaMBAwZs
-rqys9OB59OjRR33NW1tRh+jmysrKvty9e7fd3X3NmjUXysvLtzcnjdU6XVi6wWBckZTUagbEDL1+
-FgBkGAyjPtLp6rVC586de3316tUVrm5lZWUoKys701r5+xs6hAKuUqmqN2/eXDF+/Pgop1tmZiaq
-ior2rxKE0QC+A4D1sbGB1VVVd9js9m1qnh+qUqlOW202m1ajqSaVyshJ0v3h5eUfromIKLFptVG8
-LPeVJSlHJqpQcVzSbItlGwAsZozrGRERxmu1NlNh4RVAMX4yojibJB0IZIxkjUYnE6kAgDjuFG+3
-DwaQ5+Tv0qVL34wZMybvkUce6et027Fjh62kpKSgfWqt/eH3wtSnT5//M5lMv1+6dGmUq/uKFSsu
-3lJUdNh06dJ3TjebzdaNA4xMo7FBloNlojt5ng+wS5JeCg39L76yMjMgICCvVpZn8HZ7BXGcnnFc
-LE+kI8Zq0iMjf5hbVlbeMyIijOf5RyFJOQA+BgCO40ZxsnyEaTQj7IxdcMzrNapwFhYWbj158mTf
-1NRUAMDdd9+trqysnJmcnGzMzs6+lxzTN50Fft3NMcYSb7nllgeWLl2qc/f7cf/+kr4qVb2VjZwk
-1YDjqjUcF8+AGJmokDF2DsDhuefO1TCiwul5edXEcb0YsI2I+oKxMnDcYUaUM7esrBwArOXlVyRg
-g12W99TxAlxkPG9hHHeek+URxJjIMXbUrNffHltUVArGUtN79w4wC8KfnXGysrL++e933qlndHrg
-gQfCFi9ePMlgMMxu9QrzNXyttDVGffr0eTs7O9tDic3NzaW0tLQPriXNtYLQ3azXjyIirBKEIa3N
-c0ZUVJrr+81jx3qst7LZbDRo0KBdvq7f1iZ/7+bCo6KiPBz37t1rO3/+/JfXkqDDBnURAEwlJT9e
-H3uemGWxnHB9F8vKLsiyHM9xVzsBlUoFrVar8YjcweHX3VxxcfHypUuXFru7b9++veTy5cte96qt
-jIoasZ4x3pufO9INhoEZgjB1tU4XszI6OsFbmLVhYUJT6b3bo0fQh3p9qDe/mpqaPceOHavn9vXX
-X9daLJZN3sJ3ZPh1y1RaWnpw48aN5X/7298MrpO7OWfOVJoFoZdZrx8BoMJUUqIo4YwxXhB6VYeG
-ZmZER8eQLEdIjF1SEaXKwCHI8qBAoi3TS0svAQAvSbOJaANUqt48UPFBeHiUVq2ewoi+JWAiA/bK
-Gs0dUlRUNoDPAMVQyez234Lnz80uKvoZAAJqaiYzIDbdYFirkuVbyG7fBbVaB0kK6FNTU7Rr164r
-/fv3r9sy8/LLL4vZ2dkr2q8m2wd+3TIlJSW99a9//SvOVZCsVivKysouEvAbEOnqBAnAer0+WJLl
-kjkVFRZZkkaQLBtVRKky0QBIUgJTq3c4BQkAwNgxU2npbrmm5oQsy7FarTZKkuUzsyyWC8RxVRLH
-RRNwyspxW51RyG5XExDB7PZApxtPdIp4fqcGCAXR6erg4CIAyeC4xNsCAnrt2rGj3mrL9PT07n36
-9PmCMVZvaqijw2+FSavVjpkxY8b0W2+9NcDVPTs7G+FVVQWMse0Sxx1x9ZteXHyZA2LBGGOMHQ8M
-CtoIWRYZcJxTqbIBXHEN74w/p6LCwogEEF2RGTsP5SsTT3SZY2y/GrjNGWeOKOabRDF9lsWy3+l2
-JTDwDGS5v0x02QbkPZyfXwVZtjHGcgJ4fkOpxVLPeJmSksJeffXVocnJyf/dilXme/h6BNAQJSUl
-vZGVleU+EKLvvvuOevTo8UhD8VZFRwe/DHC+5t+Vhg8fvs+9HJIk0aBBg3b6mrfWJL/VmXie7+dt
-S7bFYqGCgoILDcVzWqz9CTU1NbXubhzHISwsLNIX/LQV/Labq6ys/Hzjxo0e67GLioquyLJsAYAM
-vX4soIy4MnS6J9aGhdVtszXr9UPWGAxJALBKp7tnfWxs4Gqdblhz88/Q6+9YqdPVTYWYo6JuyNDp
-7l0fGxu4ShDmm43GenvQMwyGUQ2lZbVaq+32+lOLeXl5EEUxp7n8dAT4bcuUn5//9oIFC+5OSkoa
-369fvzr3wsLCGgDOpbHjwdh3dp1uNBHx2srKuiWzJMsJMy2WdRk63YMcx6Vaq6pOyBzXC8D+VTrd
-izJj6+eKYiYArNLrkxlwY7VGs/Hh/PyqNRERkaRS9eM5LhjAcQAAxyUTYLRWVenA2CCy2yPgooOR
-JCVn6HQGMJZCQCYD+sjAeY4xitLpAkpLS2EwGAAoE75Tp07NPn78+B/atBLbGX7bMgGINBqNPd27
-usLCQisA5bxJWT6WrtdHc7KczXHczulErovblN8cFyEDWbMslhNEFPUuY2owdt4pSADAAd1d87Do
-9VUA8skxkQsAYMxAQJLM2DjG2HHG2Bin107GVOC4n4nj1DJjnxJglIHzDIgiQAqw2WosFktdUqGh
-oYiLiwsMDAzscf3V5D/w25YpLS3NvGbNmoSQkJB67sXFxRKAcgDQBgV9JVdVDZQ1ml8CZNl9mJ2/
-xmiMl4nWMlnuDQDE2IHIyMggO89vcQ04u6Rkp+v7/Ozs2jUGwx61VntVN+P5z8lm2yXzvIWT5TgN
-Y/X1NkkqhkZzfk5hYbHZaCyXJSkWtbU5NaGh1eet1sSysrK6degqlQoZGRkxI0aMWMUYG0z1/wQd
-F74eATREEyZM8BzKEdGsWbPyALT51qXWpISEhEWHDh3yKMvTTz+dD6CHr/lrLfLLbo4xxhqauzIa
-jSoAbToK2smYao3RGA8oa5uaCu86leItvEajMep0HgsfEBMTEwTAc/Kxg8Ivuzkiov79+1fabDaP
-owC7desWACBqMWMX4qOjAwNkmcFu562Mhc6yWC58rNd3t/H8JaeJ4F3G1FqDIS6IqAglJdYygNRG
-Y4S2uto+s7zcY48bAGQBLMhunw7gtXi9fuLasLCDslptldXqAFNhYXGGXt9tdklJgVmne4px3BUN
-kSZDr/9MK4rFCTrdrJ2MrRlLZAcAs15/e6DBEO9NmPbs2VMOx6RzZ4BftkwAYLFYnpozZ85FWa6/
-Kyg6OjoIQNRLRDIkaWatJM2oYiyGGPurWRBS7bJ8q1RbWyeBgYLwuMpmC6qR5Xuq9fq+AZGRqWqr
-dZ4UEFAXZqXBMNqs189YrdOFAcDDRDYCigCAJCmUAgIiZcZMzG6fuEoQJhDRwgyd7gnGcYUEEAFB
-BNxZKwgGYiyoUBAMzrQZUQzHcRHuut/y5cvLjh49+hERWdBJ4LfClJ+fv/3bb799/7333qtn8NPr
-9ZqIiAgDABBRNTiugAcmEJHIybJKIspyLnIDACbLdpnnezGiKhBNYIAsM5ZjKiz0WI3gCgLsqwXh
-Jo7jjthleSIYk2SOOwogmBjLkzluMxHF1x1qQSRoJamKyfIZAFgVFTVpRVKSloBTgVptPZvU4cOH
-8frrr/906tSp/2md2vIT+Fppa4gABA4fPvy0JEn1lNYffviBEhISnq0XHmCfxMQENpTW8sRELRHh
-5RZOs+wAVESEfwNqV3fn+ycATwAjgO0AVB/p9caVUVFPfwJoyOWkutGjRv1IbpgxY8YFAL19Xc+t
-+s18zUBDJAjCH7788kuPUyAKCwupX79+6b7mryU0ceLETPdyFBQUUEpKitnXvLUm+W03V1FRUalW
-qz34i46ORnBwcGp78ZGh13dz3R6V3rt3gOvTHTsZU62JjOy53mAIWa3Thc0KCRnTt29fj9GnSqUC
-Y8z/d8C2AH45mgMAq9WauW3btpJJkyYZ3P30er1+CGPqxwVBMUZynMTLch9tQMC31dXVt/BEh2ZZ
-LBcAwCwICxjRGZnjjjKezydJ6sGAG1W1tdtltToRRFdmlZYeBYD1jGmuREQEVQpC9fzsbEVXI/pd
-yOXLm9eGhZGk1f6Ol2X7esY+56Oibjfr9cXEWIXKZiuVeH5wgCx/U63TTeWIqmuJ4uw8v52Cgp6Z
-MGGCx+0IBw8etFZXVx9zd+/I8NuWiYiObt68+Quz2XzZ3W/EiBGRh4A0yPJIJsujOFmOJFkeV1VV
-FU+yLDoFyYHTVo7bCqI4SNJMDuguS1KepNFMlxibRYyNdwasEoR+PM8/GlVWdvWAeKLTWkmKkNTq
-ZCLSMqCyRqd7hQCOEaUxWf6txPPjTKL4eTXHTVVbrZsAhEGWf55bXHwkX6czDh06tJ51/sSJE9KC
-BQsO5+bmLmuDqvMZ/FaYAODkyZOPLly48P1ly5bVW1YyZsyYiPj4+EkckCdz3BEQxTHGSjlJquKA
-+mdIynKWiujOORbLNwzoY2esnDE2nhg7wQEnAPzgDKq22c5KwAZmt592utl5/qwsyxNkjhOJKEri
-uBLG2GYAEin1V8GICgGAyfIhSaOZLhGdlDkufmVU1AiEh4dGRl7t5Xbt2iVPnjz5u+PHj48nhy2q
-08DXSltTlJaWtiEvL6+e8lpTU0P9+vXb1pJ00gVhcLrBkPCRXm9cqdO1yxQGAO1dd92V68p7VVUV
-DRgw4LCv67UtyG91JgBgjKknTpzYPyam/jlZWq0Wer2+J2NMRc38dz9QUnKoTZhsBDqd7vZp06YJ
-rm6BgYG4++67Yxlj/Ynol/bmqS3h190cEdlsNpvXI24efPDBGIPBcE9TaZiNxuB0g8F4rTysMhgG
-rRKE3zQWZrUg3JxuMAxcYzTGZwjCVKd7TEzM/HvuuSfIPXxlZaUVQKexfDvh1y0TABQXF587ceJE
-UlpaWj3Bv/vuuwNfe+21x+A4C8CJDEGYOlsUNzjfeSCaZDk+Q6/vDqKhMrCRMTZZItrFAzcxoJJk
-WeQ4rlYGODDWH5L0tam09DwAzCkpOZKh0z0K4CAArNbpYmTgVp7nv5fs9mgAgEZzlLNaB88sLT1i
-Vg7SAGMseu7cufFabf1DVyoqKvDNN99cIqL81q8t38KvWyYAOHr06N333nvvtq+++qra1V2r1WLg
-wIG9GWP1Wh0rY9+4vpPNJqokKVsGbgJjByDLOiKyzrVYThFjQcSYETyfKhP1Yowl2lWqDcTYBGf8
-DEEwgrE64bTxvFB3jjjPp4LjElVVVTLH8xwAkOMwi6SkpKeefPLJev3z6dOnafz48ccOHz48qfVq
-yH/g98JERNXHjh2b+OSTT245dKi+2jN//vzuycnJf3F1U8tyvVPZeI4LkXg+iJflXZDlh3nGSjme
-P+LQGgtBlCUx9gMYC5Zl2a6y26epVaq63bYyECoTudZTIQEX7Bz3CxjLZ4yV3F9RIYJIl967dwAj
-KkyPjOyl1+tvGzBgQF2kyspKTJ48OfPQoUO/JceB950Ovh4BNJfS0tK+9nZz07Bhw07Bbe7MG2VE
-RcWsjIzs31iYD41GvXM+7npIr9ff+sYbb5S78zp8+PBDvq7HtiSfM9BcGjJkyEH3j0NEtH37dmty
-cvJffc1fXYUC/KBBg455Ozbxtttuy/Q1f21Jft/NOVFTU1NQVua5lu3mm29Wp6amzmaMNXihs1mv
-n7kqKmpSemSkxxUZZr1+put7usEw0FsaOxlTObc+rdTpblkVFua52g1AQkLCgsWLFydoNJ4LRS0W
-i8f+uc4Evx/NOZGZmfnX5cuXj3zppZc8lrkuX76859mzZ/8N4O4MnW7abIvlM6ffTsZUTKdTQaP5
-nrPZJq3W6bYSxz1DkvS+pFJZecbq1j59pNPFqhj7Q4bBsFyWpDvA2DkGdCfgFGcwlDC7fXZ6ZORS
-juMi51RUWDIE4TEGnJSIIjmOq95ttRamDB36+O233+4xCbx//365qKjoU3f3zoQO0zLZbLYf1q5d
-u+n999+vdHQndYiLi8OUKVNGRkRE3GTn+XoHkJ7X6cbaJel7U2HhFcZYiKa0tIaIzjKe78fL8u/K
-w8O/eZcx9Uqdru/vLZY8Yuw4Z7PZGGOJHMeJjOd3c4yN1hYXn2RAprW8/AqunhceXMvYQcZYNGTZ
-cNBo/Os/33rLw6a1b98++x//+MdD586de6PNKsgP0GGECQAyMzPnLFmy5OkhQ4Yc3blzZz1j5qJF
-i/RJSUnpP125Um+dL8dY/NyyshzHa8VlozGcA/KswPeMscD52dm1kYDMESn3qzB2UFaprIzn/w2g
-AACIaO10IqtMlBkcFRXIeL5qTUREJCdJH2tkuZ/VZlu7WqPpdetdd92YmJhYl3deXh7Gjx9/bvbs
-2f8+ceLEGHLm0Vnha6XtGpXcW9esWeNxtdPZs2cpNTV1L5oxumtNCgkJGXLHHXdckGW5Hj+nT5+m
-tLS0N3xdX+1FHaplcoHMvGwp6t27Nz788MMhSUlJnzjd0nv3DnBfyLbeYAjZyZhXfXE9Y7xzY8EH
-4eFNbkNijMXecMMN69atW9fD/bglxhiIqFOdwdQYOqowHXrzzTcvOFqpehg2bJh6yZIlN8fHx/8D
-AFQVFWO5y5cnrDcYQj7W67sDQDXRrLzIyD7rGdO473OrjYoaDyBsfWxsoEajucXp7oy/njHNu4yp
-1xsMIfNDQtL69u37n6+++io+IMBz4eWbb75ZIoriJx4enRQdZjTnCiIqjY2NfWHmzJmvL1q0KNp5
-zrYT9913X+jFixfnJCQk6ANKS/9wHLCZdbp5YKwsQ6/PPCeK770EUIbB0D9FlkvgsneNgLjZFss2
-s15/u12lqpuaqZHlB8BYmU0Q5CCOO7m3unrivri4xz///HOjINRbGABRFPH+++9Xbtq06evi4uI9
-6CLokMIEAHl5eRmMsT2HDh16ShCEm5cuXZo4bty4OuPOU089FTV48OB7H3300TR28uQdK5VWOFSW
-5dqXHFd0SXq9iuP5uiZlPWM8RUU5mzvj7wsKXM/w5gkIBZC1heMWlg0bNm7bunUG14VvOTk5eOyx
-x87m5uYeO3PmzN+rq6t3tWkl+Bt8rbS1BoWHh9+/adMmG3lBYWEhjRkzJucuo3GJ+1TJSp3uN65X
-rn6k0/VZrdcnERFWCsIU17BmQbjjNiAoKSnpw5dfftnirmwTEV28eJH69u37vq/rw1fkcwZag9Rq
-9a0ffPDBZY+v64DdbqdXXnnFMnDgwJ+MRuNctHD+DYAxOTn5zXHjxmXv2rXL84JgB7Kzsyk5Oflf
-vq4PX5HPGWiVQgDq6Ojo7NOnT3v5xFdht9tp3bp11SNHjjyVlJj4jxnBwS8uioiY5SU9HkC8Wq2e
-3Ldv3y0zZ87MO3bsWKNp19TUUGpq6kUARl/Xh6+oQ1xe2BgYY8YBAwZsfvHFF5OnTZvmsaqxIfzy
-yy/Yu2fPlSNHjlScz8mxXq6svGyrrZVCgoNDgyMjVWmpqUH9Bw4Mu+WWW9Tebknwhu3bt9teeOGF
-c6dPn54jiuKBay5UR4Wvpfl6CADr06fPj4WFhd4aC5+gtraWhg0blgUgkvygjtqTOqqdyYnwIUOG
-REdHR/uajzpoNBrMmzcvBkD/JgN3MnR0YQoKCAho1j0p7YmQkJAAtVod5ms+2hsdWpiI6OLu3btP
-njp1ytes1MFqteLVV1/NstlsO33NS3ujMyjgQlJS0kdBQUH66Ojo6I0bN/Zy3xHSHnj22WcLf/zx
-x/OXLl2qyM3NfdHich1Gl4GvlbbWpNDQ0BGPP/54gYdW3Mb47LPPqhMTExe3Vjk6KvmcgdamxMTE
-d/bt29egYbG1UVRURH379j0El8O9uir5nIFWLxCgSUlJ2ZCenn6J2hiHDh2yDxgw4BcAsb4utz+Q
-zxloK0pISHh2zpw5F8+fP0+tjYqKCnr99dfLUlJSPgGg9XVZ/YU6vALeGBhjyWlpaf+l0+mGTpgw
-ofvs2bMj4+Pjrymty5cvY8OGDVUZGRkFeXl5ZwoKClaUlpb+v1ZmuWPD19LcXgSgf2Ji4sb//Oc/
-njs5m0Bubi4lJyf/EhERMRWAxtdl8VfyOQPtWlggduzYsS2ee3nmmWdKQ0NDJ/uaf38nnzPQnpSS
-kmI+e/YstRRWq5UGDRq019f8+zt1aAt4S8FxXLjR2PKjmtRqNYKCggKbDtm10aWEyWKxbNqyZYvX
-w8Maw8WLF1FWVna66ZBdHL5uGtuTAPApKSkbd+/eXUPNRFFREQ0cOPAYAL2v+fd38jkD7V5ggE9N
-Tf1q3759nseUuKG4uJgGDRqUiS68erIl1KW6OQAgIunkyZNPpqene70ezBVbt26tzc3NfZ0cRzP/
-isbRIbY6mQVBBcB5UPw8kyh+fp1JxgwcODC4qUD9+vXTCoLQ6zrzahRmQhNbJgAADlRJREFUQeAA
-DAeQaRLFDn1oqldhMgtCBIDbAaRBuamxFMARAJtMouhxY0A7gAFwLqf0emdJC7H37bffzps2bVqq
-Xu/9WCciwssvv5yblZX1gdPNLAiJAJwnUxw3iWJeUxmZlR2aQxyvF0yi6H7FxQcA5gKoMgtCb5Mo
-Nnp1mT+jnjCZBSESwEsA/gTA27WmJWZB+LNJFNe3B3NtBSKyMcZumTp16r49e/bEeAvzxBNPFB88
-ePAxIjrn4jwHwIuO3+sAzGhGdk8CeN7x+0MAf3Tz7+d4BgFIAtBhhalOZzIrl9ocAPAEFEG6AmAH
-gH8A2ASlddID+MQsCA+1P6utDlVycnKD3Xz//v0DbTZbY6vs7nS04A3CLAgMgKkJPuYD+BTAf5tE
-sUNvJVcBgFkQQgFsxdUm/DUAL5hEse70f7MgaAG8CuBOAGvbmc+2QE1xcbEsSRJ43nMZ+aVLl1hN
-TU1Dtx9UQWlJ7gfwdiN5jAMQB6ASytZyD5hEcR+A6S1h3F/hbJn+F1cFaZZJFJ9zFSQAMIlirUkU
-nwYwwAd6U6svbSCiwgMHDjwzb968cne/Tz75xLps2bJ1ly5d+rKB6Fscz7lNZPOA47n5GtnsUFCZ
-BaE7gD843jeZRHFNYxGaEiSzINwEYBiAQQDKABwC8K1JFJscXpsFIRDABAAjAQgAfgawxSSKWWZB
-sKOJ0adZEDRQWoOhAPoAEKF8+C0mUZTdw6tUqh6TJk3yaDGGDRumCQsL69ZIVgUAjgL4jVkQ0kyi
-eMILL8EApkE5YSWzEZ77ABgIoMbkcrOCwy8OwG8B5JhEcb/DbRAUXa07gGUmUTxsFgQjgLEA8k2i
-uMsR7gYA9wGIB/CmSRT3uqWdAmAUgBsdTocAfGcSxQYt/WZB+B0AHYCvTaJY5ijj7QAmA7ioAjAL
-io5EuKpcthhmQQgHsALedYQKsyDMN4niqkbipwH4BEBfNy+rWRBeAVCLRoTJ8VHWQvkwrpgP4Auz
-IMw0iWKNq0dRUdG/li5d+uDUqVNTXN0XLlxYkJmZOa+hvKBc8vwxFOV5LoAFXsLcAyAYymitMd3q
-TgB/g3Jb+QY3v+GOMn1pFoS7oCj9rl3ie47nAEe47wCMNQvCewAedAlXd0aUWRDUABYBWAhlG7wr
-7GZBWAzgVZMoSvDEXwH8BsAYsyCUAdgFINzh9xMHwHl53xmTKB5upNANwiGhP0ARJDuA9QCegaJj
-HQYQBmClWRCWNBB/sCN+Xyj3xX0A4HEoyv95AC9D+TAN5X8jlH/WQAC/OPK+D8pHKgZwFwCPhWxE
-VKNWq6vc3aurq61ElNtIkUNw9c4Wk1kQvO3dm+N4rkMD+lILoIPyIacDyAFgBvA5lDLXC2cWhGeg
-CFI+gNVQvoXrTpmvALwARZC2On6/COBbKH/WJVAGBI0h1ZFOGIBvoIxSM1QAbnAEONNAxOZgEZRh
-bSWAu02iuN3pYRaEFwEsBzAPwHNmQVjnamtxjHjehKLQngMw2SSKmS7+C6EU+AVvGTviv+WI/zGA
-OSZRtDm8PzELwkcA9gK42SwIt5hEcatrfFmWPbo/WZab0tGCTaJ41iwIu6B0FROhjHidPMVB6W5P
-A9gHZYR8PRgCpet/F8DjJlFs6DzxZCiDp7UAHjSJYr0/ilkQTABuBSADeNQkiu+5eP/VLAjzoXyr
-qWZBmGYSxc/gHf8AYAMwxtmtAooC7jyV4ZqEyWFSeMrx+ndXQQIAR3P5OBRBUQFwv0r0fig6DgA8
-5ipIjvi1AP6nERZmOuKXO+LbXD1NopgF5SMAiv2sHsgxYecKSZI8BMwNzuUo7zuec938TVAMre+b
-RJFcwl8rAqCYaf7UiCABirryE5Q/lLsgaQG87nj93E2QFKZFcQWA/zhe32igxQWU8phcBQlQhMlp
-nLzWY4WHA1BDkfYV3gI4BOpfjteRjtbEiTGO5wmTKP4HLccox3N7I9MRztaon7tHAy1TU8Lk5H89
-lG75DrMguB6VMgfKPze9iXRagkXeBhFesNh9JO5AMgDn5dn/bCS+0y8GQO8GwvxgEsWN7o4qKCMu
-PYCezWDUG5wHSl40iWJpI+GOOp6Bjrxy3OL/fI35O5VnjVkQHm0gjHMqxsPa3UDL1CxThEkUq82C
-sBpKF34fgLcdo9lkAJ+ZRLGoOek0Ez9eZzjXgz+PNhAGUHRO1zjeRnde81BBGbrqAfRqJIPGkOR4
-Nqawuvsn46owOYXh7DXm77SP3eGgxuAhJNfYMrnifSjCNAuKAdN5F4tHN+JjJDuel0yieKmRcEUA
-rFB6rKRGwnmAg6IgAkCKWRCuZRLV2bU0OrXg5u/aHTntVtc64nG2hmYoSm9jNN498vW0TADgGAH/
-BGCEWRASoLRQuQC2tagUbQ9nnYc4VmE0hCBcVX1atIpBBUWfeBRAJICH0IDe0whOOp69mgjn3LBG
-qG/Ey3X4xbYwXyeyoJyFFGQSxZ0tjaxSqbwZM1vSMgFKK/Q2lFaqG5qv37QnnN+JhzLF01BP0MtL
-nGaBg2IvcK4Ves5hhW4JnBkGmwVhSiPh7nU880yieMXFPcfxHGsWhGYfI+iCLMdzlFkQQloaOSQk
-xKO8ISEhgd5uQGgEa6DM142FcknPhy3lox3gKhj3NhhKaVkBzz99k+Acmv9/Od67A9jpmGLxgFkQ
-QsyCsNIsCCNcnHdCMUwCwMvehNEsCMMBOG/VdjcNOK3ikVB0D29oSLEGlNagGspIZXFDgRyL0DwQ
-GBjoYQyNjY3V4KrS3iRMolgBZWQHAJtNouh3lzk7BgPOqbKnHFMw9WAWhBgoMwYA8IGjXM2GypHR
-GrMgjIRih/kNgENmQfgnFKv0L1CavsFQ7EnJAG4yC0JfkyiSSRQlsyA8AsXKOhjAd2ZBeBqKgEVA
-MegthzKc/glXTQTOQu40C8IOKDrN/5oFIQyK/nMBiv3ocSgWbK8wieI5h2X9FQBPOyppEa424wlQ
-JlynmQXhRtcpFcYYP336dI/WMCEhIRjKyK+gGXXoxFtQ6qmxYbev8TSUeTQDgANmQZiHqzrzSChd
-dQSAElxtYJqNOkXMJIrzzIJQAMW0boQyFeINPwOY4TDGOeP+YBaEOVAs2TdBmbMhXLXHAIqwzWpg
-zudhKPNSfR35v+gWfwUUe9YQL3EBxRjXDcBjUEZTM6GsxwKuTsNchiLsrmuGjHFxcR5rluLj48M1
-Gk0clD9Ts2ASxYNQujm/hUkUi8yCcCeUP2scvEwxQfkTzmrCzOMV9Zp+kygugWLYe9ORqFOJlAEc
-h/KPH+pupXbEXe2I+yGAE444l6EI1l8AjDSJolelzzFTPRTKv/oolPm9SgBfA5hqEsXHoSzj+A7K
-0NU9vs0RZjwUHTAHyqgEUBb8/S+ABC+Lz2KSkpI89Kzu3buzHj16pHlhNcfBw0/eytEIjjniedNB
-zjv89nrxK3b4fYer38IbSl3CNbov0CSK30P5Tn+HMrdnhTKJ/iOUqZj+zhUKXnDIkUe2V19fb4/x
-JUVFRc3YsmULuaOoqIhSU1NX+Zq/jkZdbquTKwwGQ1qPHj083PV6PRhjXteG/4qG0aWFSa1Wp8TE
-eMoMYwzBwcFNboX6FfXRpYUpODg4PiLCu+G+e/fukcz9astf0Si6rDAxxoLi4uIMDfmPHTvWAGUF
-469oJrqsMAUFBY2eMmVKg8I0ceLE8NTU1Psa8v8VnuiywtSzZ8/7J0yY0ODEdp8+fRAaGjqyPXnq
-6OiywhQaGnpDt26NbUABunXr1o0x5nd3s/gruqQwMcbC4+PjhabCTZgwwaBSqRqyuv8KN3RJYQoM
-DBx35513NqgvOXHrrbeGJicn/6o3NRNdUpji4uLuu/nmm5tcCJiUlITg4ODh7cFTZ0CXFKbQ0NAG
-j9JxR48ePYyMMXUbs9Qp0OWEKSQk5Dc33nhj8yQJwO23367v3r3779uSp04DX08OtifpdLrRkydP
-zq2tbfI4y3r405/+VNi7d+8/+Zp/fyefM9BuBQXUw4YNO2Oz2ehaYDKZCgEk+Loc/kxdppsLDg4e
-99BDDxlUqms7xvPZZ5+Njo+P7wyHnLUZuowwxcbGThkzZkyLNxw40a9fP2i12tGtyVNnQ5cRptzc
-3A07duy45kPKjh49CqvVuq/pkF0XXUaYqqurv//iiy+u+TzvdevWWc6cObOyNXnqbOgywtS7d+8H
-S0pKrmVfHgDg1KlTUnx8/LRf5+oaga9HAG1NUO5L2Zmenl5B14lvvvmmZsCAAYfw6z0q3uva1wy0
-NRkMhhlr1669Qq2EY8eOUVJS0nJfl8sfqdN3czqd7qE777zzmrs3d/Tt2xcRERHjWiu9zoROL0w1
-NTVf79y5s6HzvFuM4uJiVFVV5bRWep0Kvm4a25oAqG+44YYfCgoK6Hpht9tp7NixZwD08HW5/JE6
-fctERLZjx469sHXr1hbfgOmOs2fP4sKFC18Qkd8dTOEP6PTCBACCIMT26NHD28VCLUL37t2hUqmu
-9RypTo8uIUyiKH67bNmyIlEUrzkNm82G5cuXV5WWln7Tiqx1Lvi6n20vUqlUAyZNmnSBrhFLliwp
-j4iI+DMAztdl8VfqEi0TANjt9kye521Nh2wQcnl5+QEi8rfjBf0GXUaYiKg2Jycnfdq0aedb0t0R
-ERYsWFC8evXq74mouccnd034umlsb1Kr1RNXrVrV7KWWOTk5FB8f/7av+e4I1GVaJidsNtvBFStW
-XDh27BiKiho+891msyE/Px+LFi0qLCkpyWhHFjssGFGr3wvo92CM9UpMTHyY47j45OTkkRkZGT3C
-w5Wbrux2O5577rniL7/88oRKpTpbUVGxPj8/f0sTSf4KdFFhcoVGo+mTmpr6jtFo7AaAFRUVleXn
-5y8sKSn51te8dTT8f55fKsbmgm+wAAAAAElFTkSuQmCC</string> </value>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAHEAAABpCAYAAAAN+8wmAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
+WXMAAAKOAAACjgH/xBOOAAAAB3RJTUUH3goUFDELO4vaAAAAIABJREFUeNrtnXd8VEXXx79zdze9
+kAABKVIUabsLIUEEBKSFEhBrQAhFQfTlUVBBUUCf18IDNlCkC4iF3osQpImFRyEQsrsEFGmhSktP
+NtnsnfePbMImJCFlA4HX8/nsJ9mZ2Tv3zu/OzDlnThFSSu4WEkKIls2btbYj+oDSTAjpKSSeUuAp
+JZ4gPUFYQcRIKQ+gsMdsNpvu+Oe+00Fs1KiRn7e7e5iK0kdRRLiqqtVKeYlYkF+jKItNJlPCPyDe
+YtLr9YEaqekghN3LLoQ2wDfAe9ToUbOsVqty9uxZzp07x7kzZ7lw4QKZmZk3u9wlIZWXYg/HrvoH
+xNtIRr3Be+PmTb/Xr1+/uXO5lJLTp0/zyy+/8Ouen9l/IJqsrKwilmTW2+z2UXFxcRf+AfH2gPjo
+V18vnhoSEtK0uHZWq5Xf9v6X5UuXsfe3/xbWJFEKxprN5kV3wnMr3F3UNyUlxfdmjTw8PHikS2fm
+LpjPqjWrCe/bB41G49ykipAsNOoNPxiNxoB/QLx1s7An8CyqvKc0v2vcuDFTpkxh4+ZNBIe0Kljd
+HVVuCw0N9f9nOa14APXAr0II359+2iP8A8o2eVRVZfHixcz6YiY2m8256r8qMsxisaT+MxMrBsCa
+wGbAr1mzZtayAgigKArPPfccS5cvo0aNGs5vd1sF8c0/y2nFADhQq9XGAfUAHn/yCU9XXLdx48Z8
+9fViUQDIxw0Gw/B/llPXAKd4eXn19vX1nfL333/rc8sHRg7izTffdGlf586d47lhz6oXLlzIfdlT
+UUQLk8l04h8QywZeg/r1649JSEgYlpSU5H9drhM8M2gg48ePRwjh8n7PnDnD008+paanpzuAlEtN
+Fsugf0AsOXCtfLy8++vc3QYmJCTUKVjfpVtX/vWvf9GoUaMKvY9tUVt5fdwbefyPFOjNZvORyjJO
+2koGmg7oJITo5+bmFgEEpaanQXpaXpvadWrRrXsY4eHhNGnS5JbcV4+evfjl171sWLceQNFI/g0M
++GcmXgdOAB2BIYqiPKWqql/BNnXr1qV7jzC6d+9O8+bNb8t9ZmRk8Fi/R+0Xzl/UAFJRNcZDcYcs
+/69BNOoN9wNDgMFA/YL19RvUo1v3MMLCwm7ZjHOWFxXlRsZ906ZNTHxrgmMvZlWs2Rzx/w5Eo95Q
+BejvAK9dwfqgoCB69wmnT58+PPDAA7dlQFRVJTYmluCQ4ELrnnz8SXn8+F8CyFaRdS0Wy8X/F3ui
+UW94EBgL9APcnet8vLzp2qM7ffr0oXXr1oXOgFtJNpuNPT/vKRRERVEYPXq0GDNmNIBWQRkKfHhX
+g2jUG9oDbwM9Ctbdf38jBg8dTO/evXF3d680zFViYiIHow8UWd+5a2cCAgJISEgA5KC7FkSj3vAQ
+MBnoUrCuTduHGDp0KO3bt68Qua7cICZc4/Tp00XWZ2VlOZ943HfXiRhGvSEAmAo8D+QhpNVq6dGr
+J0OHDr3lTEpp6eq1BBISEkhJScHXN/+p1vnz5/n000+5cuVKbtHfQgghXchYtGzZsna9unVH6HTu
+PseOH1sQGxv7xy0D0ag3DASmA0HO5e07PMyECROoW7fuHaEZSryWCEB8fDzNmzcn+coVDu/ew/Zt
+UWz4/XdsDrw0QsQj7QNcCeCgAf3DqwYEruzbr5/XmlWrURCjWzRv0Tv2cOzOCgXRqDdUA74ruO8F
+BQXx5lvj6dY9jDuJ/r78NwCLp37M2VMniUtMIBcnBfAVmkup2P9jk+pCi+Wwy46menbr2cdmz1r3
+7ZLvtLVq1SItLY2FXy5wUwSfAMEVBqJRbwgB1gL35pZpNBoGDY5k1KhReHl5caeR6WAMAEl/HONo
+RgrOE00FUqTdZrKYP3dlnwaDIdxNq1s3Y+YX2lq1agE51geOPluGhob6R0dHJ7kcRKPeMAyYA3jk
+lumNBv73f//3tsl4rqD9v+9TAaVPlaqMq1mX3SkJXLXbEHZYmXwFu5S1mzVrdo+rDKkMBkNdnUa7
+esTI57Xt2rVDZtsQWh3nzp3La2O324VLZ6JRb1CAGcC/nMvD+/bh3Xffxc3N7Y4F8MiRIySnpykA
+PlotNXRuDAiskVfv56Zj3uXzuClKKLDJFX36evt+Vb16NbeRzw0nc9ka3MI6I6pV5Xz82RJfQykl
+gAL40hlAIQSjXvoXU6ZMuaMBBFi9cmUu08IDbjeeL/evWoNArS5ZRXnQJcxgM+NjqakpXV8f/4aS
+HbWd7PgzSJ0OgBOnTuK0RUmXgQh8DjyX+8Xd3Z2PPv6QF198kTud0tLS2Lx+gwoQ7OmNb37rNwB0
+El6sdo+3FvlCcHBwlfL0p9frfbRumrnt27ajbe17sR35M29SWCwWZzEmuWHDhqkuAdGoN0wBXs79
+HhgYyIJFC+nRs9dtGfTTp0+TlJTksutNmzbNlmGzKQCP+BSNTwf/QA2IQDU7e2p5+lNQPrDb7UGv
+jn2NrB0/5gCo0SB8fdixY4dz059XrlxpLzeIRr1hIvCm8wycNWc2LVq0uG0z595772XGjBnMmDGD
+y5cvl+taWzZvYdWKlTqAhm4e9KxStci2Pgja+fgqUjKyRfMWXcvSX3DT4PogX3rsiccJupaE/epV
+SE1DCaqKEIIdP2zPaysFP5Z7TzTqDWHA+85l7733/m0713PeiydOnEhWVhY9w3owadIkjh49Wqpr
+qKrKihUr7BMnTsjK5fIm1aqPuyh+WHr4VxOAkELdWBYg7Rr7OCGE5rmBkSLxYAzSlo166TKapo35
+888/iY+Pd37O3eXS2Bj1hkDgK2cV2vDnR9ArvBeVgRRFYdy4cRj0zXl70jtsXL+BoKAaBIcEExoa
+SkhICPfdd98NOtrExERMJhOzvphpP3LkiAbQKMDooNo0cr+5wVwH3yoYPbwxWdO8pFA3G43GniaT
+aU9J7rlFixZBIId36NRJrXXxb+VYehrVzl1AKBq0Rj07FuXzHEg0m80x5VW7zQNq5X7p+EgnXn75
+5UrHlPTo2YsGDe/jldFjOHv2LNu2RrFtaxQA/v7+1KpTG51Oh1ar5eL5C5w/fz6P8QPwF5rsd+o0
+0D7o5VuyVUBKXqlZl+dPHsEuhAeqXGMwGNqYzebjN5392eoYIfCI6NOH7LijpFozsdtsaBo1RPHw
+YMcPzvuh2CmlVMsMolFvGAI85bwHffjhh7f9vK8oeuCBB1i9dg3Lli3j66+/JvFajqthUlJSsQxQ
+Ky8f69u1G3pUUzSl6q+Ruyejg+rw+eVzqFBVSDEdeLTY3zRq5Ofl4fmvJk2aqH6nzihSKqQnJ6Hx
+9kb4+nL69Gn++uuY034oF5dZTjTqDXWBL5zLxo0bh7e3d6UWE7y8vBg+fDhRUVFMeudtuoV1p0pg
+0Rbhk++pz+d1G5UawFx6IjCId++pj04IO8ieN2vv6e7+opTSf1jkICXeZEZkWEm2WiGoGrpgI9u3
+b3dufqFp06ZbS3IfRc3ECUCewVLrkFAe6dL5jpH5vLy8iIiIICIiAikl58+fJyoqis+nf5avXapq
+L9V1U+x2liVcIjYtmQwpaeTpRVZ2NgpS4ymUv4v7bUREhAaUMb6+PpnNqgW5R6elIoVAq2hAq0HT
+qCE7PvvU6Rfy65uJFkXORKPecA/wrDMX+Nob4+5YIV4IQe3atenc+caXcN7Vi1n7M1JRS3Cdg9Y0
+hp06yrdXL2KypnMsM4MtiVfZnZZsD9S6HbJj73YTlV5XkLV6hffWxJ84STWrHeHtRYCvL5qAAC5l
+ZREXF3ddS2PXfVXSZyxsJr6Gkx1Mr/Det12ccAU1aNAAX28fUtKuKz9SbDb7a/HHqKbV0dW3CmF+
+gTzgkf/kJT4rk3UJl1iXdBW704mGEPwkpFyUarWuizlmSr45MyQGgSQ8PFx7dPNWDDodokZ1qly8
+gPbBELZui3KehT/HHIn5s0wgOkSKPB2aVqtl9OjR3A0khKBaUHVSTl4H0SYwuQsl6Eq2rcGKhMus
+SLjMvW4e3KPRYROSFLudY5kZBS9lFVIZEGuJ3VDSvkNDQ71APhEQEJBmvP9+792X/6ZrrVooXl4E
+VK8OTRqxdOwrzsvjwtJpf/LTaMAn90v7Dg+Te751N5C/f0FfUXnxSmpyM62Q05Sc40Lis6z8npHC
+wfTUQgCUp6Sga+zhkgMIkG21Pgr4hPfto7EfiMVmV/EKDEBmZhL4WDibtm7h0qVLuc0vpmVmLi/N
+9bVOs1ADjHKuDO/di7uJ/AOqFHiDRfLJkyetwFi9Xr9cqxKBIrqp0BDwdSg5zoA8KITYn27N/OLY
+sWPJZVgHBgH07d7Dw37IQl3/HI5Z+PqirVmDxYuctz/x+bFjxzLLBCLQHqie+8XDw4NOj3S+q0DM
+zs7OL3gj8gCxWCz7gf1Oy69o27atx969ezPK06fD57+Hv79/yn0aja/q7k49X18UBJpgA7t27eLU
+qVN527RGp5lb2j6cQXzcuaJT50fw9PS8q0A8ffJUwaIixQKHAVRG+d8cQlDQPfhQG5vdfATFx5u6
+nt5oGtRH4+/HIic1mxDMj4mJSSy1+tHp/8fyLaW9et9VANpsNmd1W87Dy+wfKl7BqxoA2gS38rKf
+yTmtr6Zo0LQJYc+ePVhM5ut8lkYzvUxdOPbDFjg5tWg0Gtq2b3dXgXj27FlUNZ9E+Hds3JF9t6Br
+I0Bw9RxLTmmzITw9sQdUYep/pjjP/SWHDh06V2YQCy6lDRo0rFSm9a6gn3/+uYDIwRZ5S7yJhMHD
+wyOjri7HdEWmpKILacn8+fOdjaGsGrvu3TJPdsfffBxMo8aNuNto/dr1BZgaNt8C2VQBmjVs2DBZ
+Sb++vZ7z9y7AkcqPYo7EnCoviAbnwjvZ5LAwOmw25zsdALKklBW+HzZv3lwLeNZrUN9d2rLRuHug
+Cw/j/SlTnOPkxPv4+ZXP1MOoN9QG8qn6GzdufFeBuHrt2gK8hlx0KwILWSyWLCC1Xr16fmpiErpe
+3Vi8cQP7fvvdSR2njCuvGKMtOAsr80yUUpbakyo+Pp6N6/MpWFKlTvPv8txH586dtdcuXWsrheyg
+KLjlbq0qXFMUZW1sbOxZpyU1oWbNmj5u3btz4MgRZs5wPuGTO10RmlML6J0LNBoNQUFBlRLEq5cv
+U62U9/bxxx8XDPHlI+32pQaD4UutVrutpHKZ0Whs6Ovr29ffz3dgWkpqsBSqDsCZ4RWAtKvTjXrD
+T1LwutlsjgZ5+eLFi7XPXL2qvDHudWcO+QCK8rRrWKfm+q/Jcb8GwNfbh19//2+lAzA1NZWTx09i
+aGEo8W/27t3LiyNfKK6JHeReUL5HYYubm9txQJeWlqbVaDQBnu7uHQMCAh5LS0lrl5KWWhVyziof
+fKgN7dq1o327tgRWrUZGRgaHYg6yfcdOtm2NygUqC+SbUgjvAN8qb2Vn27xSr0cB2a/RacPKItgX
+BeJPQIfcgmrVqrHrx92VDsSFCxfSr18/qlUrWXTozMxMIp56mpMnT+Yua5RHorjvvvsYMmwo4eHh
+xVq6//HHH3w85UP2Redo8KTgqJA0yVltUUFscPNwG16cg0xZuNN8NheVUdWWmZnJlu83lxhAKSVv
+v/12HoBeXl68Nm4s999fOtFJURTatH2ImbNnsXb9Oh5//PGbuio0btyYBYsXMe2z6dSuXVt1AlAR
+UulvspieciWAuXtiPhBzXaoqFXe5ejVBVUu+F86ePZuoLVvzBvWTaZ9Sr149Bg8ezPebN7Hth+0c
+3BeN0/JWUDSgV3hvevbsWWb+oFu3bnTs2FH55ptvmDnjC6GqUpXCXiHMhjA018cDeW68hhZGlixZ
+UmkAPH78OIOeGcjY18fx9NM35wM2b97MhDffAuDp/hG88cYbhWqf7HY7cZY4/jrxF15eXnh7e+Pt
+7U2NGjVcfoa6b98+XnvlVTU5OVlRVPnJoTjL6y7twNBcf8XQXC9zP0MiB8vKQikpKbJP7z6yTesH
+ZWpq6k3bb1i3QYYEt5JtW7eRUVu3VMg9ZWdny6SkpFL/Lj4+Xvbu2Us1NNdLQ1NDNyklrvrcsJwm
+JydXihkopWT8+PGcPn2KJ556slhzyczMTCZPnsyPu3YzZNhQBgwY4FIxKTs7my2bt7Bpwwb2H4hG
+VVXqN6hHr945gZNKEo+gbt26fDp9mogcOAgQC3HEaHXVcpoF6HILqlevzs7du247iLNmzWLenJzz
+0WUrlhdprHXh3HkWLf6Kpk2bEh4e7lLFvd1uZ+PGjcyfN5dzZ88X2kaj0TAwchCjRo0qkV3uggUL
+mD1zVvrBQzEuM+LVApeA2pVpJq5cuZL5c+flMRnFWdvVrHUPEydOdGn/qqoStSWKOXPmcPq0s15a
+HAbpD9RxBvrbr79h29ZtRA6JpFevXtSoUaM4jldVVfVvVzM20UCIc+H+A9G35SjKbrczdepUVizL
+sRNyd3dnybKlt0wNKKVkxw87mDVrJidOXA8uLATrUZQ3Y2Nj/+jcubM24fLlx1SU/wF5Q7AlIQTB
+Ia1o06YNTz75ZL5l/cqlS/Tp0zc7LS39I/Nhc5nfPKPeEAHMBMxAuBa4IcBcSlIS7rdY9RYfH8+7
+b/+b/Qei88rGvj7ulgH4467dzJo1iz/++MMZvIOoyiuxlti8w8jdu3dnA6uB1Xq9/l4hRHchZUvA
+R1E0fVVVrXow+gAHow+wbWsU6zde19suWLSI9PR0rRRyZTkADAW+BdzIidj1bKEgJiQllVpHWR51
+2rx581j63ZJ8Os7OXbswYEDFx4X95ZdfmPXFTA4fPpzvPZaCSU2aNp1VnCm9xWKJBxY2bdq0qlbR
+DlRVNZ+Jy6WL+VfNixcvSkVREs1mU3kyxX3kADCXHisUxD+OHqnwkMyZmZmsWrWKL+fNdwS7c1I4
+eHny3nvvVWj/+/btY+aMLzh06FDBBXGNolXGlMZUQqfRTQU5omB5YLX8HscnTxxPVVX1x7JaFBj1
+hlpApwLF92uBUwUbxxyKpU/fRytk8KxWKytWrGDxoq+4evVqoW2yrJlcvHC+EGPf8jMsu3ft5Jtv
+vyPmwMGC+sdzdsELZrPp+1LvpUL+JCQ3gPjCiyPz/o/aukWeOnnasyTu28VQf240+A7QAr8WbHko
+5qDLwcvIyMgD79q1azcd7P9MnsL8BV+6hMFKSkhg1Zo1rFy+gosXC48xqyriA7Op9AACmM3mb1sY
+WgyTUu3ixIWeaxUSWnvdunWsXbvWHhtzSAMiEcG6cjzKM4WU+QgpJUa94TJQzZnD+mXvrzdEGSwr
+x7ds2TLmzp2b5/hZGOn1euLi4vJZpAUHBzNj5hdlnpF/HD3CkqXL2Pr9lkLzJ9apU5uzZ8/lMjFL
+Ys3myHIwHAtxCg8DZBXYuxKkICznjLFM178fOFZI1cVc4+GfcbJ4k1ISGxvLww8/XC4Az5w5wzvv
+vMOB/UXfd0BAAONeH0vfR/uxaNEiPpt23fQyJiaGIZGDefXVV2nbvt1NZ+WVK1eIjo7O+ezbn09M
+cCb/gCq8MvoVWoW2op9j25CSsNDQUK/o6Oj00j5nixYtGuN0Jgv8BdgBf5BRUog1Vqt1e2nN8wvQ
+U0WU/10oiLkDWFYQpZQsX76cz6ZNJyOjcPMRT09P+j8zgBEjRuDnl+PP+txzz5GUlMRXC69bRZ88
+eZLRo0fj6elJ+w4P07Jlyxtczk+cOEH0vv3O5vBFalfsdjsZaekE1QyiQYMG1KtXP1egr55lzXqL
+nEjJpXteu/1DENo8LZ1q71gBSTQfL6L8XO5yGoqTHwLkBNtbunRpmbjOl19+md/2Fm4d4OvtQ/9B
+zzBkyBCqVCk86M/8+fOZP3dekdlGS0O+vr706BFGl27d2LJlC5s35oRk0+l0zJozm4y0DBwxvQGs
+QqM0i42NPVnKpc7m0H6hwIpDFrNLZSOj3lAHiMcpiokTTcp9ew46GuWFvLSYzBw2m2luMJSqww8+
++KBQAP38/Bg0OJLIyMib7rUjR44kLCyMefPmsXvnLtLTS77C3XPPPeiNBgyGnI9er89bhh9++GHq
+1KnD3NlzsNlsfDT1I9asW0OHTh35ec9PAB7Sbp9OAZeGm5GC/B8V8b4QXJGKUhFu1QOLABBgd15K
+BaPe8BbwH+faXuG9+fDDkscpX7FiBZPf/yBfmZeXF0OfHcbgwYPx8fEpk0jy6y8/8+exvzhz5gzn
+zpzFZs/Gy80Dd29PPD09qVevHkaDnuZ6w01P/5MSEujSpWueYuHTT6fRtHlTHu/3WB7zIwSTYs3m
+yVQCMuoNnsAJoGZhuhIg0BnEIOCMM0el0WiI+mFbsQpd5z10+LPP5bmP6XQ6Igb0Z+TIkQQEVK6M
+ruPHj2fr91sAeDC0NQsWL+K7777jo6kfOqvcRsWazXMqAYijyQmMWBh9brKYX8njEEwW8yVgVUGF
+9PLlJXNanTp1KtnZ2SiKwqOP9WPT95sZP358hQCYlpbG0aNHOXDgAHv27GHPj7s5fvx4iffQdg9d
+dxY6fSYnBFdkZCTPDneWEMSsNiEhz95mAN2BN4qotgGfwo2BF2YB+dLKrV65ihdeeKFY25szZ85w
+5HAcQUFBTJ/+WanMCkuqaYmLi2Pv3r3s3buX2JhD2O32vNUitFUIHbs8gsFgwGg03jRgkrMBcqbt
+OvCvvvoqKSkprF65CimlyMjMWtSpU6fXkpOTx8TExNyOQ9bncDomLEDfmizmMzeAaLKY/2vUG34l
+x2s4Zw9JSmLjxo1ERBSdFmn79u20Cg1h2rRpBAYGuuwJpJREbYlixhef3XAo2+7h9oT37kXHTo+U
+WhmQG6w9R+DPn9Fv0qRJpKens2VzjvIm4eo1PbCzU4eOl61W6xmrNeOaYy+KFnbNzgf0D+wvabyZ
+Us7CKsWIOypOSVUKC4HyEhCNI+4ZwPy58+jZs2eePFeQjh8/zuzZs10auN1ms/HKK6/kco15VL9+
+fd6c8Bbt2pXdf/KnH6/H0qtaNb+SWlEUpk6dyiOPPMKX8+dx6uRp7HY7UsrqWkVT3Ul1/ZhU7B8c
+jTt6rEXzFq+XNhhDCWg6UFSm8rUmizkvREqhCb+MesMMnALUFsepJicnk5SU5PK8F2+99Rbfb9qc
+j8t9cdT/EBkZiVZb9iQCFpOJyMjBqKqKEAJvTy9WrVtD7dq1i1wNcpdfVVVZunRpPgbIqeV7Jovl
+3y6ahT2B4kKChZgs5oPXRZzC6W0KHFFt/X4LUVFRhcp/rgbwxIkTecsZQJUqVVi5ehXDhg0rF4CZ
+mZlMmDghTz8rpSQ1PY3XXnutSLMU5/1z3759rFu7pqid9p2yBrEtAKAvML+YJmudASwSRJPFnATc
+YBs5+f0PuHI93kqF0ZIlS/JM7rVaLZ9/PoN77723/OvT9OmcOnnaibsTewGOHI4jctBAzsQXniMq
+5kAMEU9FyJEjnufYn385A3wJxCYgFpBS3HimWAb6GCc74AJ0Gm488iqSjTNZzN8B2/IJyklJTHrn
+nQoFMDk5mU0bNuZ979Kta6Fp8EpL+/btY9mSpc5y4CcqamdFlTMAeerkaZ4ZMFDu3nmjH8qn0z/l
+6NEjwum3WxRV0zbWbKphspgeNVnMLVVkB6BbOWdhN2BkMSJFf5PFnFBiEJ3UPfm0ynt/+ZUVK1aU
++Uazjx7DunYT1rWbyNocRebOPdiPXY/1umP7D1it1rzvffuEuwTAV18e43SgLubEms0TLBZL1qE4
+yxgp6ALyVHJyshgzZjQjRozIZ67hFOv8shR0jjWbww/FHfot315rsfyqwR5eDgCbACuLUa+9YbKY
+fy90Ib+ZpYBRb2gJ7AXyPG08PDz4+ttvaNq0ack4zf0HyP7tANkHTahF7D2a2rXQde/EhB3b2L5z
+Z54M+Nu+38t1MLxl8xYmTZoos7OzRc4Ds8gUZxlR0ESiSZMmvm5atw8dZhY6gHr16tMqtBVxlsMO
+Ayo5X4WXHR7ArhQnagL/pZC0vA5aZ7KYnyhS7i2JuYdRb4gkx8IqH0Pz5cIFxQJpv3CRjDmLsB8u
+WYB1Fehz4jApDgG8UaNGrFm3tsyDs2jRIvn59M+cnlF8Yz5sfra4kMyhjR+oZXNzf0lKIovYmxJA
+LBUa8V5sbOwlFwDoA+wBWhXF5wGtHHxK2UF0dPY5OQH8SgSk/dx50iZ+gEwpuWt8bEYqL8VfP7zu
+2+9RJk8uvR76+PHjTJ48OSN6337P64pi+ZrJYvmyNNcJbhr8QLY2u4uQIghUT0CgKr9p3DU/usJB
+1Kg3aMlJV1RU1OIsoJ3JYj5Q3HVKw6+PBZo5b97Jyck8P3xEoUCmfzKzVAACrEm4ku97SZfrXEpM
+TGTGjBnWNatWu0kpcwHcKwVDzGbL8dIOsiPm6J9UHM0tBsBMByNz4GYXKXFUdpPFnE1OoPIdBbnJ
+54eP4MiRI/mYF7UUCasAzBmp7E7Jz3gFlzB5Snp6OnPnzrV169I1c/XKVR5SSgVIFII3mjRr2rEk
+UfJvsWJbGPWGD4HhRTRJBXqbLOYSaYFKnaLdqDd4AOspkPTSeWlNn70Q2849pbrui/F/cDjj+uFv
+rVq1iPph202F9+XLl8s5c+ZkpqemeVwfAPG5Rqf5xFU+8S4G0Bv4BiiKUbkG9DJZzCUOWVbq/Agm
+i9lKTqr1rYXNyB937UaWMofTxsRr+QAE6N4jrFi96ooVKwgLC7N9+vEnwgGgFeQ0rZuuoclimlRJ
+AawL/FIMgBeAjqUBsEwz0emG3IE1wA2yUfh9jRiteOJ1k1QFKvDl5bN8dy1/ridFUVi1ZnWhVuiH
+Dh5k/Pg35YULF3LlKZuiyoW4aT8oa4C7WwRgW2AdUKMYLrS7yWI+Udpri/JElDDqDW6OpaF/wbqa
+Wjcm1KpHsGfhJhmpqsq7507yW/qNcuPT/SN4++0bT2F+3LWbsWPHqjZHdjXgrIp8whFwlkoM4BCH
+PrQogfewA8AyWcgJVwQaNOoNLwGfFLxJBXgIg8YpAAAD30lEQVQ6oDojg2rj5lBEnMiy8n3CZbYl
+XSOpEHEtMDCQDZs23nBGuGfPHka/9LKUUjpmoIiRQvYym81F+vo1aNDAw8fHx99ut3sAxMXFnb7F
+4GmAKRSih3YW5IERJov5Wln7Ea6KFulIEr0CuK9gnb/Q0MDTi8TsLE5lFW0/6+fnx4JFC2nSpEm+
+ciklPcN6JF+4cMHv+gsi+x2yWDbeIKyHhuqyrdYnVUQE0AunnMfAJRA/oTDVZDIdqGAAw8nxYGpW
+lEQEvOzQUZeLXJb4ySHPhJDju5ePkqSdQ+mpxQJYp04d5n05/wYAAXbt2oUzgADZkHLDwBmNnbKs
+mbEqYhk5xrYFbUqCQD6FKn8zGAzjKgi8YKPesJOcUJxFARgF6F0BYGmF/ZIAmQQ8XfjyWviM9/X1
+pf8zA3jhhReK1JGeP3++oF8DCmJ9i+YtRkiNNCv2bH9VaCeALIkr1yUQ04Skn16vX2+xWP5yIec5
+GYikaCV2CjDWZDF/6cpx11bE22iymGca9YZd5JyNFRlMvG7durzwwov07tO72MPexo0bF7Zi+Emh
+rkQFVWiKeklSHFxfLa5nGgiSUvqZD5s76PV6NxeA5we8BbxSyMzPx5cBz5os5lOuHm9R0RGUjXpD
+FweYRSl4CQoK4plBA3nqqacKNXrKzMyke9duMYmJiSU4WBS/K6izpUbzu8lk+lNKKSMiIjRH446O
+Afk+4AUkVK1eLcjhul3W56oNDHWAV72YpknAO8AXJou5QgZb3Iow2I7U7gMdy02R8Vs8PDx4uGMH
+WrduTevWrfNlIc3IyFjbpnXrZBCDcTLicqIjqGK0Kc60o6jrN2vW7B6d0HWRwt7KZLGMLcNzeDgU
+Hc8C3W/CU1wEPgPmmCzmCg1JcktALKAgGE1Oar+bpjivEhhASEgIoaGhuaB2b9mypVmBAagYhcBb
+RSRLIaPc3d03RUdH2yrgnhsCXR2fHiW4778c/MBik8WceSvG9ZaC6DQw/uR4vQ4D2pT0d35+fhLY
+lZycvAn4nZzkJFdd9aY7XBmaOD5tHMCVNPJTDDAVWG2ymNVbOZ63BcQCA9fYAeZgirZ2vhnZgKvA
+Fae/VwqUpZMTAs2bnKRmuZ9AoLHjUxafg93AVJPF/MPtGsPbDqITmAo5Z5VDHTJeZc1xZAV+csh6
+W00W89HbfUOVBsRC2PauwEOOZS2UAoEEbzEddYC2DdhjspgzKtN4VUoQCwFVAzR3AJoLbFNXapwK
+EQt25QJnsphPV+bxuSNALAJYX4fsWdOxlxX3CXTM5DSHAiDV8TfFwRwdd3CVxx2fCxUl01UE/R+4
+oNmVz83aAgAAAABJRU5ErkJggg==</string> </value>
         </item>
         <item>
             <key> <string>height</string> </key>
-            <value> <int>144</int> </value>
+            <value> <int>105</int> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -242,7 +195,7 @@ w5Wbrux2O5577rniL7/88oRKpTpbUVGxPj8/f0sTSf4KdFFhcoVGo+mTmpr6jtFo7AaAFRUVleXn
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>12003</int> </value>
+            <value> <int>9310</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
@@ -250,7 +203,7 @@ w5Wbrux2O5577rniL7/88oRKpTpbUVGxPj8/f0sTSf4KdFFhcoVGo+mTmpr6jtFo7AaAFRUVleXn
         </item>
         <item>
             <key> <string>width</string> </key>
-            <value> <int>147</int> </value>
+            <value> <int>113</int> </value>
         </item>
       </dictionary>
     </pickle>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.svg.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.svg.xml
index c4a2085ee36f7b5f11f53685f4af58c51be7fe73..2e1607ba841a042001ad6e1e8811ad4641609cb9 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.svg.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/logo.svg.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403084.87</string> </value>
+            <value> <string>ts21897129.17</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -33,143 +33,176 @@
    xmlns="http://www.w3.org/2000/svg"\n
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\n
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n
-   width="744.09448819"\n
-   height="1052.3622047"\n
    id="svg2"\n
    version="1.1"\n
    inkscape:version="0.48.4 r9939"\n
+   width="640"\n
+   height="640"\n
+   xml:space="preserve"\n
+   sodipodi:docname="logo.svg"\n
    inkscape:export-filename="/home/marijn/src/js/codemirror/doc/logo.png"\n
-   inkscape:export-xdpi="27.450405"\n
-   inkscape:export-ydpi="27.450405"\n
-   sodipodi:docname="logo.svg">\n
-  <defs\n
-     id="defs4">\n
-    <clipPath\n
+   inkscape:export-xdpi="16.601332"\n
+   inkscape:export-ydpi="16.601332"><metadata\n
+     id="metadata8"><rdf:RDF><cc:Work\n
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type\n
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs\n
+     id="defs6"><clipPath\n
        clipPathUnits="userSpaceOnUse"\n
-       id="clipPath4138">\n
-      <path\n
-         transform="matrix(1.05,0,0,1,-290.76164,27.927128)"\n
-         d="m 705.08647,231.61324 a 70.710678,104.55079 0 1 1 -141.42135,0 70.710678,104.55079 0 1 1 141.42135,0 z"\n
-         sodipodi:ry="104.55079"\n
-         sodipodi:rx="70.710678"\n
-         sodipodi:cy="231.61324"\n
-         sodipodi:cx="634.37579"\n
-         id="path4140"\n
-         style="fill:#ffffff;fill-opacity:1;stroke:none"\n
-         sodipodi:type="arc" />\n
-    </clipPath>\n
-  </defs>\n
-  <sodipodi:namedview\n
-     id="base"\n
+       id="clipPath16"><path\n
+         d="M 0,512 512,512 512,0 0,0 0,512 z"\n
+         id="path18" /></clipPath><clipPath\n
+       clipPathUnits="userSpaceOnUse"\n
+       id="clipPath40"><path\n
+         d="m 435.607,369.899 31.242,0 0,-64.782 -31.242,0 0,64.782 z"\n
+         id="path42" /></clipPath><clipPath\n
+       clipPathUnits="userSpaceOnUse"\n
+       id="clipPath56"><path\n
+         d="m 421.796,349.477 39.074,0 0,-88.423 -39.074,0 0,88.423 z"\n
+         id="path58" /></clipPath></defs><sodipodi:namedview\n
      pagecolor="#ffffff"\n
      bordercolor="#666666"\n
-     borderopacity="1.0"\n
-     inkscape:pageopacity="0.0"\n
+     borderopacity="1"\n
+     objecttolerance="10"\n
+     gridtolerance="10"\n
+     guidetolerance="10"\n
+     inkscape:pageopacity="0"\n
      inkscape:pageshadow="2"\n
-     inkscape:zoom="1.4"\n
-     inkscape:cx="291.72812"\n
-     inkscape:cy="789.2497"\n
-     inkscape:document-units="px"\n
-     inkscape:current-layer="layer1"\n
-     showgrid="false"\n
      inkscape:window-width="1600"\n
      inkscape:window-height="875"\n
+     id="namedview4"\n
+     showgrid="false"\n
+     showguides="true"\n
+     inkscape:guide-bbox="true"\n
+     inkscape:zoom="0.52149125"\n
+     inkscape:cx="303.572"\n
+     inkscape:cy="574.48012"\n
      inkscape:window-x="0"\n
      inkscape:window-y="25"\n
-     inkscape:window-maximized="0" />\n
-  <metadata\n
-     id="metadata7">\n
-    <rdf:RDF>\n
-      <cc:Work\n
-         rdf:about="">\n
-        <dc:format>image/svg+xml</dc:format>\n
-        <dc:type\n
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\n
-        <dc:title></dc:title>\n
-      </cc:Work>\n
-    </rdf:RDF>\n
-  </metadata>\n
-  <g\n
-     inkscape:label="Layer 1"\n
+     inkscape:window-maximized="0"\n
+     inkscape:current-layer="g10" /><g\n
+     id="g10"\n
      inkscape:groupmode="layer"\n
-     id="layer1">\n
-    <text\n
-       xml:space="preserve"\n
-       style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#a21313;fill-opacity:1;stroke:none;font-family:Ubuntu Mono;-inkscape-font-specification:Ubuntu Mono"\n
-       x="247.48738"\n
-       y="163.42795"\n
-       id="text4006"\n
-       sodipodi:linespacing="125%"\n
-       clip-path="url(#clipPath4138)"\n
-       transform="translate(0.50507287,0.50507595)"><tspan\n
-         sodipodi:role="line"\n
-         id="tspan4008"\n
-         x="247.48738"\n
-         y="163.42795">    if (unit == &quot;char&quot;) moveOnce();</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="182.17795"\n
-         id="tspan4010">    else if (unit == &quot;column&quot;) moveOnce(true);</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="200.92795"\n
-         id="tspan4012">    else if (unit == &quot;word&quot; || unit == &quot;group&quot;) {</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="219.67795"\n
-         id="tspan4014">      var sawType = null, group = unit == &quot;group&quot;;</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="238.42795"\n
-         id="tspan4016">      for (var first = true;; first = false) {</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="257.17795"\n
-         id="tspan4018">        if (dir &lt; 0 &amp;&amp; !moveOnce(!first)) break;</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="275.92795"\n
-         id="tspan4020">        var cur = lineObj.text.charAt(ch) || &quot;\\n&quot;;</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="294.67795"\n
-         id="tspan4022">        var type = isWordChar(cur) ? &quot;w&quot;</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="313.42795"\n
-         id="tspan4024">          : !group ? null</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="332.17795"\n
-         id="tspan4026">          : /\\s/.test(cur) ? null</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="350.92795"\n
-         id="tspan4028">          : &quot;p&quot;; // punctuation</tspan><tspan\n
-         sodipodi:role="line"\n
-         x="247.48738"\n
-         y="369.67795"\n
-         id="tspan4046">        if (sawType &amp;&amp; sawType</tspan></text>\n
-    <path\n
-       style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"\n
-       d="M 374.84375 136.8125 C 371.96854 136.71001 368.64305 137.97919 365.15625 142.03125 C 361.97051 140.84608 359.22347 140.35622 356.84375 140.375 C 346.53162 140.4564 343.3125 149.71875 343.3125 149.71875 C 326.2234 146.67934 325.625 162.59375 325.625 162.59375 C 309.43195 163.37101 312.4375 177.375 312.4375 177.375 C 295.67899 180.15651 301.1875 194 301.1875 194 C 284.10838 199.04575 293.4375 212.46875 293.4375 212.46875 C 293.4375 212.46875 277.68174 220.31271 288.1875 232.25 C 288.1875 232.25 273.81776 243.63282 285.90625 253.34375 C 285.90625 253.34375 271.57897 263.97487 286.40625 275.03125 C 286.40625 275.03125 273.84147 285.48036 289.96875 295.3125 C 289.96875 295.3125 278.92374 306.07108 295.59375 314.65625 C 295.59375 314.65625 287.70844 329.01862 305.96875 335.125 C 305.96875 335.125 300.47495 348.88874 319.09375 351.46875 C 319.09375 351.46875 315.90162 357.19564 321.59375 361.15625 C 321.59375 361.15625 310.04416 364.78661 312.5625 374.40625 C 313.83361 379.26171 316.82684 380.49158 323.53125 380.1875 C 323.53125 380.1875 329.096 395.54812 350.46875 398.96875 L 353.125 402.59375 C 353.125 402.59375 342.80592 409.64088 359.125 421.5 C 359.125 421.5 354.16126 425.74314 363.28125 433.34375 C 363.28125 433.34375 357.54117 438.3362 365.75 442.625 C 365.75 442.625 361.35822 445.96166 366.09375 448.125 C 366.09375 448.125 370.88293 490.18262 355.40625 534.4375 C 355.40625 534.4375 341.28721 542.04782 350.1875 556.96875 C 350.1875 556.96875 331.59675 562.24093 345.09375 575.53125 C 345.09375 575.53125 342.0547 585.56155 349.375 585.78125 C 349.375 585.78125 346.16048 592.54552 354.4375 594.5625 C 354.4375 594.5625 353.17883 603.88113 364.09375 602.1875 C 369.44813 608.40994 378.92733 608.70518 385.21875 602.34375 C 396.13361 604.03738 394.875 594.71875 394.875 594.71875 C 403.15197 592.70177 399.9375 585.9375 399.9375 585.9375 C 407.25781 585.7178 404.21875 575.6875 404.21875 575.6875 C 417.71573 562.39718 399.125 557.09375 399.125 557.09375 C 408.0253 542.17282 393.90625 534.5625 393.90625 534.5625 C 378.42953 490.30762 383.21875 448.28125 383.21875 448.28125 C 387.95421 446.11791 383.5625 442.78125 383.5625 442.78125 C 391.77129 438.49245 386.03125 433.5 386.03125 433.5 C 395.15125 425.89939 390.1875 421.65625 390.1875 421.65625 C 406.5066 409.79713 396.1875 402.75 396.1875 402.75 L 398.84375 399.125 C 420.21649 395.70437 425.78125 380.34375 425.78125 380.34375 C 432.48566 380.64783 435.47889 379.41796 436.75 374.5625 C 439.26834 364.94286 427.75 361.3125 427.75 361.3125 C 433.44213 357.35188 430.21875 351.59375 430.21875 351.59375 C 448.83755 349.01373 443.34375 335.28125 443.34375 335.28125 C 461.60406 329.17487 453.71875 314.78125 453.71875 314.78125 C 470.38876 306.19608 459.34375 295.46875 459.34375 295.46875 C 475.47103 285.63661 462.90625 275.1875 462.90625 275.1875 C 477.73353 264.13112 463.40625 253.5 463.40625 253.5 C 475.49474 243.78907 461.15625 232.375 461.15625 232.375 C 471.66201 220.43771 455.875 212.625 455.875 212.625 C 455.875 212.625 465.20411 199.202 448.125 194.15625 C 448.125 194.15625 453.66476 180.31276 436.90625 177.53125 C 436.90625 177.53125 439.88054 163.52726 423.6875 162.75 C 423.6875 162.75 423.0891 146.8356 406 149.875 C 406 149.875 401.14687 135.83532 384.15625 142.15625 C 384.15625 142.15625 380.33279 137.00815 374.84375 136.8125 z M 375.34375 155 C 416.3488 155 449.59375 201.78944 449.59375 259.53125 C 449.59375 317.27306 416.3488 364.09375 375.34375 364.09375 C 334.3387 364.09375 301.09375 317.27306 301.09375 259.53125 C 301.09375 201.78944 334.3387 155 375.34375 155 z "\n
-       id="rect3058" />\n
-    <text\n
-       sodipodi:linespacing="125%"\n
-       id="text4207"\n
-       y="491.91403"\n
-       x="149.69542"\n
-       style="font-size:95px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#a21313;fill-opacity:1;stroke:none;font-family:Source Sans;-inkscape-font-specification:Source Sans"\n
-       xml:space="preserve"\n
-       inkscape:export-xdpi="90"\n
-       inkscape:export-ydpi="90"><tspan\n
-         y="491.91403"\n
-         x="149.69542"\n
-         id="tspan4209"\n
-         sodipodi:role="line">Code  Mirror</tspan></text>\n
-  </g>\n
-</svg>\n
-
+     inkscape:label="2014-10_codeMirror_logo_vectors"\n
+     transform="matrix(1.25,0,0,-1.25,0,640)"><path\n
+       inkscape:connector-curvature="0"\n
+       id="path22"\n
+       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 233.97976,469.37438 c 0,0 7.01353,-14.94848 -2.94916,-31.42373 -4.97925,-8.23417 -130.50847,-34.94915 -179.50847,-102.94915 -30,-47 -76,-183 71,-273 66,-34 94,-33 94,-33 0,0 -44,31 -16,52 28,21 69,31 80,60 13,-10 34,-31 54,-29 -2,13 -7,18 9,20 16,2 24,2 24,2 0,0 -15,12 -32,13 -17,1 -49,34 -48,48 21,12 48,32 64,26 16,-6 32,-16 35,-25 0,-6 -3,-16 10,-8 13,8 10,13 15,24 5,11 6,13 -5,22 -11,9 -37,30 -58,24 -21,-6 -65,-23 -87,-2 9,20 23,52 16,74 13,10 28,21 30,39 15,2 47,11 41,27 -6,16 -48.59322,87.16949 -113.59322,73.16949"\n
+       sodipodi:nodetypes="cscccsccscscscsssscccsc" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path26"\n
+       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 441.52213,306.0015 c 11,29 29,78 12,80 -17,2 -36,-44 -41,-56 -5,-12 -25,-72 -14,-80 11,-8 43,56 43,56" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path30"\n
+       style="fill:#da687d;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 348.52213,384.0015 c 3.13,4.919 5.82086,0.64508 -7.67914,-0.35492 -13.5,-1 -29.62196,-5.18461 -32.38899,-11.04836 -5.19174,-11.00208 -6.93187,-38.09672 -26.43187,-44.09672 -1,-7 0,-23 27.5,-26 27.5,-3 28.5,15 44.5,14.5 16,-0.5 14.5,5.5 9,10 -5.5,4.5 -24.5,35 -24.5,45 0,10 6.5,6.5 10,12"\n
+       sodipodi:nodetypes="csscssssc" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path34"\n
+       style="fill:#da687d;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 103.02213,82.502 c 0,0 -8.5,22.5 16.5,34.5 25,12 47.5,2.5 52,-6 4.5,-8.5 -7.5,-42.5 -50.5,-43 -10.5,8.5 -18,14.5 -18,14.5" /><g\n
+       id="g38"\n
+       transform="translate(-21.47687,0)" /><g\n
+       id="g44"\n
+       transform="translate(-21.47687,0)"><g\n
+         style="opacity:0.69999701"\n
+         id="g46"\n
+         clip-path="url(#clipPath40)"><g\n
+           id="g48"\n
+           transform="translate(466.2583,369.8384)"><path\n
+             inkscape:connector-curvature="0"\n
+             id="path50"\n
+             style="fill:#da687d;fill-opacity:1;fill-rule:evenodd;stroke:none"\n
+             d="M 0,0 C 0.423,-1.569 0.298,-3.199 0.255,-4.838 0.213,-6.452 0.062,-8.15 -0.349,-9.801 c 0.106,-0.377 -0.082,-0.814 -0.018,-1.201 -0.41,-0.515 -0.194,-0.903 -0.284,-1.354 0.661,-0.674 1.522,-1.313 1.152,-2.162 -0.259,-0.596 -0.874,-0.706 -1.464,-0.995 -0.389,-1.403 -0.709,-3.099 -1.028,-4.649 -0.097,-0.476 -0.044,-1.051 -0.187,-1.485 -0.334,-1.01 -0.691,-1.978 -0.971,-3.09 -0.237,-0.945 0.034,-2.689 -1.063,-2.811 -0.423,-1.049 -0.663,-1.841 -1.165,-2.83 -0.286,-0.163 -0.452,0.106 -0.692,0.009 -0.305,-0.348 -0.294,-0.823 -0.577,-1.114 -0.222,-0.229 -0.503,-0.163 -0.665,-0.385 -0.363,-0.5 -0.266,-1.24 -0.523,-1.902 -0.468,-0.4 -0.862,-0.905 -1.147,-1.478 -0.588,-1.179 -0.698,-2.681 -1.591,-3.593 -0.28,-0.286 -0.761,-0.365 -1.011,-0.647 -0.238,-0.269 -0.455,-0.665 -0.689,-0.98 -0.338,-0.452 -0.669,-1.045 -0.972,-1.583 -1.004,-1.787 -2.383,-3.71 -3.301,-5.664 -0.173,-0.369 -0.199,-0.805 -0.364,-1.165 -0.381,-0.827 -0.943,-1.579 -1.257,-2.333 -0.516,-1.239 -1.31,-3.339 -2.538,-4.42 -0.149,-0.131 -0.473,-0.254 -0.606,-0.414 -0.179,-0.215 -0.136,-0.568 -0.32,-0.808 -0.086,-0.113 -0.4,-0.164 -0.537,-0.302 -0.208,-0.211 -0.306,-0.481 -0.479,-0.639 -0.426,-0.388 -1.015,-0.555 -1.381,-0.959 -0.277,-0.306 -0.397,-0.743 -0.692,-1.127 -0.318,-0.413 -0.761,-0.784 -1.09,-1.202 -0.994,-1.264 -1.38,-2.8 -2.702,-3.396 -0.393,-0.178 -0.88,-0.12 -1.291,-0.241 -0.374,0.344 -0.078,0.818 -0.163,1.164 -0.055,0.222 -0.285,0.382 -0.346,0.583 -0.143,0.474 -0.347,1.336 -0.34,1.878 0.007,0.538 0.305,0.971 0.375,1.612 0.061,0.549 -0.137,1.246 -0.177,1.856 -0.021,0.306 0.064,0.624 0.059,0.956 -0.008,0.533 -0.066,0.801 0.008,1.442 0.086,0.743 -0.074,1.462 -0.171,2.152 0.342,1.705 0.531,3.008 1.09,4.919 0.258,0.881 0.721,2.367 1.18,3.346 0.886,1.895 1.64,3.964 2.6,5.945 0.319,0.656 0.825,1.196 1.139,1.852 0.182,0.381 0.211,0.828 0.395,1.215 1.617,3.398 3.877,6.233 5.565,9.731 1.399,2.859 2.88,5.418 4.745,8.545 0.842,1.415 1.568,2.917 2.434,4.086 0.66,0.891 1.632,2.413 2.334,3.916 0.278,0.596 0.269,1.073 1.005,1.102 0.758,0.948 1.326,2.018 2.119,2.824 0.2,0.202 0.51,0.303 0.733,0.498 0.26,0.228 0.383,0.57 0.638,0.778 0.541,0.441 1.432,0.832 2.035,1.659 0.16,0.22 0.229,0.451 0.406,0.682 0.414,0.539 1.191,1.866 1.81,2.013 C -0.241,0.085 -0.126,0.061 0,0" /></g></g></g><g\n
+       id="g54"\n
+       transform="translate(-21.47687,0)" /><g\n
+       id="g60"\n
+       transform="translate(-21.47687,0)"><g\n
+         style="opacity:0.69999701"\n
+         id="g62"\n
+         clip-path="url(#clipPath56)"><g\n
+           id="g64"\n
+           transform="translate(459.8965,349.4487)"><path\n
+             inkscape:connector-curvature="0"\n
+             id="path66"\n
+             style="fill:#da687d;fill-opacity:1;fill-rule:evenodd;stroke:none"\n
+             d="m 0,0 c 0.688,-1.936 0.765,-4.106 0.935,-6.266 -0.019,-2.14 -0.168,-4.579 -0.715,-6.943 0.098,-0.492 -0.155,-1.108 -0.109,-1.623 -0.519,-0.752 -0.295,-1.25 -0.438,-1.876 0.718,-0.835 1.666,-1.609 1.155,-2.836 -0.37,-0.846 -1.118,-1.037 -1.845,-1.479 -0.64,-1.905 -1.226,-4.263 -1.846,-6.305 -0.187,-0.635 -0.212,-1.395 -0.447,-1.977 -0.547,-1.362 -1.111,-2.656 -1.597,-4.101 -0.416,-1.238 -0.356,-3.498 -1.652,-3.689 -0.61,-1.355 -0.978,-2.373 -1.674,-3.651 -0.35,-0.217 -0.512,0.119 -0.801,-0.013 -0.392,-0.456 -0.442,-1.063 -0.795,-1.445 -0.269,-0.298 -0.585,-0.226 -0.785,-0.514 -0.449,-0.651 -0.386,-1.58 -0.723,-2.425 -0.282,-0.266 -0.546,-0.564 -0.784,-0.888 -0.119,-0.162 -0.233,-0.33 -0.337,-0.505 l -0.153,-0.266 -0.072,-0.136 -0.034,-0.069 -0.003,-0.004 0,-10e-4 c 0.099,0.238 0.028,0.066 0.05,0.119 l -10e-4,-0.002 -0.001,-10e-4 -0.004,-0.01 -0.008,-0.019 -0.016,-0.037 c -0.697,-1.635 -0.851,-3.63 -1.895,-4.955 -0.335,-0.421 -0.872,-0.577 -1.142,-0.971 -0.259,-0.375 -0.491,-0.912 -0.746,-1.347 -0.366,-0.625 -0.722,-1.432 -1.046,-2.164 -1.085,-2.456 -2.571,-5.274 -3.572,-8.03 -0.188,-0.523 -0.205,-1.106 -0.385,-1.617 -0.422,-1.173 -1.022,-2.273 -1.394,-3.342 -0.626,-1.753 -1.474,-4.727 -3.01,-6.377 -0.182,-0.2 -0.567,-0.415 -0.732,-0.65 -0.22,-0.315 -0.191,-0.786 -0.42,-1.137 -0.106,-0.164 -0.475,-0.275 -0.642,-0.48 -0.254,-0.313 -0.383,-0.69 -0.594,-0.926 -0.503,-0.581 -1.23,-0.865 -1.714,-1.438 -0.365,-0.435 -0.562,-1.029 -0.958,-1.568 -0.426,-0.578 -0.991,-1.104 -1.428,-1.683 -0.65,-0.928 -1.251,-1.786 -1.828,-2.608 -0.592,-0.813 -1.215,-1.514 -2.047,-1.884 -0.495,-0.219 -1.042,-0.12 -1.539,-0.256 -0.353,0.473 0.086,1.071 0.061,1.524 -0.018,0.288 -0.25,0.504 -0.28,0.766 -0.07,0.615 -0.141,1.712 -0.035,2.387 0.099,0.676 0.548,1.191 0.712,2.005 0.125,0.708 -0.034,1.591 -0.025,2.359 0.004,0.387 0.13,0.791 0.153,1.206 0.038,0.668 -0.008,0.999 0.13,1.795 0.163,0.922 -0.034,1.854 -0.121,2.709 0.426,2.191 0.686,3.806 1.265,6.362 0.273,1.176 0.786,3.104 1.265,4.488 0.472,1.315 0.904,2.681 1.347,4.063 0.445,1.4 0.906,2.841 1.424,4.249 0.347,0.939 0.896,1.734 1.274,2.728 0.213,0.565 0.249,1.192 0.465,1.767 0.475,1.25 0.99,2.514 1.541,3.656 0.553,1.123 1.13,2.228 1.711,3.336 l 0.938,1.807 c 0.326,0.58 0.653,1.161 0.981,1.745 0.649,1.172 1.283,2.367 1.886,3.609 1.027,1.966 2.073,3.828 3.188,5.725 1.116,1.844 2.324,3.757 3.629,5.817 1.158,1.853 2.248,3.825 3.357,5.355 0.827,1.167 2.173,3.163 3.042,5.126 0.342,0.78 0.349,1.38 1.197,1.482 0.907,1.274 1.649,2.697 2.452,3.773 0.214,0.276 0.563,0.445 0.808,0.722 0.286,0.323 0.408,0.762 0.693,1.065 0.582,0.653 1.672,1.277 2.21,2.569 0.151,0.332 0.198,0.653 0.368,1.006 0.397,0.822 1.098,2.779 1.78,3.145 C -0.284,0.044 -0.151,0.044 0,0" /></g></g></g><path\n
+       inkscape:connector-curvature="0"\n
+       id="path70"\n
+       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 416.68863,327.0015 c 0,0 -8,-30.667 -4.667,-56 0.667,8 4.667,56 4.667,56" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path74"\n
+       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 426.18913,347.7256 c -0.61,2.147 -4.597,-59.478 -3.432,-61.636 1.166,-2.159 7.147,48.575 3.432,61.636" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path78"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 235.24913,465.60369 c 0,0 4.667,-26.6198 -38.667,-40.6198 -43.333,-14 -103.0605,-25.98239 -147.0605,-78.64939 -44.0000004,-52.666 -52.0000004,-139.999 -22,-197.333 30,-57.333 103.333,-128.667 235.333,-128.667 132,0 236.85312,101.50582 236.85312,171.50582 0,36.667 -20.1469,28.4918 -27.11433,-5.90828 C 466.30468,154.88286 408.18863,39.0015 262.18863,39.0015 c -146,0 -220.667,88.667 -230,164.667 -9.334,76 11.898969,141.46925 88.56597,180.80225 76.667,39.334 125.32039,23.66435 114.65339,80.99735"\n
+       sodipodi:nodetypes="cssssssscsc" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path82"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 198.85713,260.335 c 0,0 -8.667,-40.001 -50.667,-59.333 -42,-19.334 -60,-30 -66,-63.334 16,26.666 62.667,32 88.667,58 26,26 28,64.667 28,64.667" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path86"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 210.19013,353.0015 c 0,0 36,-46.667 78.667,-24 42.666,22.667 20.667,75.333 20,78.667 -0.667,3.333 4.666,-58.667 -27.334,-69.334 -32,-10.666 -71.333,14.667 -71.333,14.667" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path90"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 116.18913,74.3359 c 0,0 22.666,-1.334 39.333,17.332 16.667,18.668 7.334,48 34.667,58.668 27.333,10.666 46,4 46,4 0,0 -48.667,-6.668 -52.667,-34.668 -4,-28 -10.666,-40.666 -21.333,-49.332 -10.667,-8.668 -24.667,-10 -24.667,-10 l -21.333,14 z" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path94"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 219.02213,219.502 c 0,0 40.523,6.783 59,48 15.167,33.833 5,63 5,63 l -20.5,-3 c 0,0 8.5,-24.5 2,-46.5 -6.5,-22 -21.5,-47.5 -45.5,-61.5" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path98"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 437.13303,313.1621 c -14.461,-36.13 -35.773,-62.068 -38.265,-60.674 -4.494,2.513 -0.358,34.036 14.104,70.166 14.46,36.13 32.432,63.635 39.104,61.014 6.672,-2.621 -0.483,-34.376 -14.943,-70.506 m 20.999,72.506 c -16.442,8.934 -36.644,-24.449 -53.276,-63.334 -16.633,-38.885 -18.542,-70.229 -5.759,-75.836 17.092,-7.496 33.127,22.285 49.759,61.17 16.632,38.885 24,70 9.276,78" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path102"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 159.52163,189.668 c 0,0 10.331,-31.037 62,-24.666 48.667,6 69.59,24.744 99.333,43.334 21.334,13.332 20,7.332 22.667,6.666 2.667,-0.666 14.667,-8 27.333,-6.666 0.667,-6.668 -5.999,-1.334 -8.666,-7.334 -1.333,-4 10.12,-22.824 26.666,-20 27.334,4.666 19.667,16 25.001,28.666 5.333,12.666 9,19.334 -17.667,37.334 -20.667,18.666 -32,13.999 -42,13.999 -10,0 -36,-13.999 -54,-10.666 -18,3.333 -29.334,10 -29.334,10 l -11.999,-13.333 c 0,0 21.999,-16.666 47.333,-10.666 25.333,6 44.001,25.332 66.001,15.332 22,-10 26.282,-16.701 32.999,-21.666 7.667,-5.668 8.333,-11.666 3,-17 -5.334,-5.334 0.001,-9.334 -3.332,-15.334 -3.334,-6 -20,-8.666 -20,-8.666 0,0 18.273,23.477 -4,25.332 -16,1.334 -26,22.668 -48.667,11.334 -32.55,-16.277 -78.668,-44 -110.668,-47.332 -31.193,-3.248 -42.667,6.666 -50.667,25.332 -9.333,-8 -11.333,-14 -11.333,-14" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path106"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 274.18863,183.002 c 0,0 22.667,-12 16,-38 -6.667,-26 -36.667,-44 -56,-52.668 -19.333,-8.666 -33.743,-20.127 -19.333,-27.332 12,-6 18.667,9.334 36,12 17.333,2.666 32.667,-4 34,-14 -7.334,4 -12.667,4 -12.667,4 0,0 6,-4 6.667,-10.668 0.666,-6.666 -0.667,-3.332 -4.667,-3.332 -10,0 -11.333,8.666 -20,7.332 -22,-2 -23.333,-11.334 -35.333,-12.666 -12,-1.334 -32,5.334 -29.334,20.666 2.667,15.334 23.334,26 42.667,34 19.333,8 48.667,33.334 44.667,56 -4,22.668 -21.334,18 -21.334,18 l 18.667,6.668 z" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path110"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 331.02213,371.7515 c 0,0 9.5,-4.75 15.5,-28.75 4,-8.667 9.333,-15.667 14,-17.667 4.667,-2 -2,-4 -5.333,-3.333 -3.334,0.667 -10.334,3.667 -15,-0.333 -4.667,-4 -16,-14.667 -32,-12 -16,2.666 -29.667,12.833 -29.667,12.833 0,0 6,-26.5 41.667,-24.833 24.721,1.155 19.333,14 36,16.666 16.666,2.667 14.893,11.089 11.333,18 -5.667,11 -23.333,13.667 -25.333,45.834 -2,3.333 -14.5,-0.417 -11.167,-6.417" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path114"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 388.01383,204.4707 c 1.506,-1.477 -11.825,-31.469 -11.825,-31.469 0,0 -2.667,-7.334 -9.814,-4.75 -7.311,2.645 -5.413,7.948 -5.413,7.948 l 17.026,30.837 c 0,0 9.353,-1.906 10.026,-2.566" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path118"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 406.74623,247.168 c -0.667,-2 -3.333,-10 -3.333,-10 l -10.891,8.334 2.891,6.332 11.333,-4.666 z" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path122"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 284.85563,189.002 c -2,-7.334 23.333,-50.002 40.667,-47.334 17.333,2.666 19.999,-2.668 14.666,-6 -5.333,-3.334 -14.666,-4.668 -13.333,-9.334 1.333,-4.666 5,-9.334 -3.667,-8 -8.666,1.334 -26.333,10.668 -37,28.668 -3.333,-10.668 -4.666,-14 -4.666,-14 0,0 34,-35.334 68.666,-20.668 -6,4.668 -22.666,3.334 -8.666,11.334 14,8 24.666,10.666 31.333,-2 3.333,0.666 3.333,30 -40.667,28 -15.333,2 -36,32 -36,47.334 -4,-4 -9.333,-0.666 -11.333,-8" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path126"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 420.44553,336.5015 c 0,0 -8.75,-26.286 -5.104,-48 0.729,6.857 5.104,48 5.104,48" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path130"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 429.40543,352.0503 c -0.444,1.66 -4.07,-45.761 -3.203,-47.435 0.868,-1.673 5.909,37.339 3.203,47.435" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path134"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 312.85513,378.335 c 0,0 37.667,3.333 31,18.333 -20.105,45.239 -58.333,71.667 -129,69 40,16 74.00021,14.00025 106.667,-14 16.33311,-13.99988 23.89324,-31.04069 29.74979,-44.08296 9.34044,-20.80074 6.58914,-22.74696 -3.74979,-28.58304 -12.56847,-7.0946 -34.191,-2.57 -34.667,-0.667"\n
+       sodipodi:nodetypes="cccsssc" /><path\n
+       inkscape:connector-curvature="0"\n
+       id="path138"\n
+       style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"\n
+       d="m 316.7084,372.58242 c 0,0 10.36415,-7.13802 18.50215,-1.32602 3.74086,3.84884 6.23323,5.95026 -4.37137,5.51213 l -12.90479,0.52875 c -8.94116,1.82452 -8.7647,-0.93753 -1.22599,-4.71486 z"\n
+       sodipodi:nodetypes="ccccc" /></g></svg>
 
 ]]></string> </value>
         </item>
@@ -179,7 +212,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9055</int> </value>
+            <value> <int>17692</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/manual.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/manual.html.xml
index 2140ced6e3153fa691df663bec159ba1024e4214..39d4d554d38029cec7ce0dd09406a78fcfe8effa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/manual.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/manual.html.xml
@@ -56,20 +56,24 @@
   dd { margin-left: 1.5em; margin-bottom: 1em; }\n
   dt {margin-top: 1em;}\n
   dd dl, dd dt, dd dd, dd ul { margin-top: 0; margin-bottom: 0; }\n
+  dt + dt { margin-top: 0; }\n
+  dt.command { position: relative; }\n
+  span.keybinding { position: absolute; right: 0; font-size: 80%; color: #555; text-indent: 0; }\n
 </style>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
   <ul>\n
     <li><a href="../index.html">Home</a></li>\n
     <li><a href="#overview" class=active data-default="true">Manual</a></li>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a></li>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a></li>\n
   </ul>\n
   <ul>\n
     <li><a href="#usage">Basic Usage</a></li>\n
     <li><a href="#config">Configuration</a></li>\n
     <li><a href="#events">Events</a></li>\n
-    <li><a href="#keymaps">Keymaps</a></li>\n
+    <li><a href="#keymaps">Key maps</a></li>\n
+    <li><a href="#commands">Commands</a></li>\n
     <li><a href="#styling">Customized Styling</a></li>\n
     <li><a href="#api">Programming API</a>\n
       <ul>\n
@@ -95,7 +99,10 @@
 <article>\n
 \n
 <section class=first id=overview>\n
-    <h2>User manual and reference guide</h2>\n
+    <h2 style="position: relative">\n
+      User manual and reference guide\n
+      <span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 4.11.0</span>\n
+    </h2>\n
 \n
     <p>CodeMirror is a code-editor component that can be embedded in\n
     Web pages. The core library provides <em>only</em> the editor\n
@@ -103,7 +110,7 @@
     functionality. It does provide a rich API on top of which such\n
     functionality can be straightforwardly implemented. See\n
     the <a href="#addons">addons</a> included in the distribution,\n
-    and the <a href="https://github.com/marijnh/CodeMirror/wiki/CodeMirror-addons">list\n
+    and the <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">list\n
     of externally hosted addons</a>, for reusable\n
     implementations of extra features.</p>\n
 \n
@@ -127,6 +134,9 @@
     <pre data-lang="text/html">&lt;script src="lib/codemirror.js">&lt;/script>\n
 &lt;link rel="stylesheet" href="../lib/codemirror.css">\n
 &lt;script src="mode/javascript/javascript.js">&lt;/script></pre>\n
+\n
+    <p>(Alternatively, use a module loader. <a href="#modloader">More\n
+    about that later.</a>)</p>\n
 \n
     <p>Having done this, an editor instance can be created like\n
     this:</p>\n
@@ -171,8 +181,42 @@
     is updated with the editor\'s contents when the form (if it is part\n
     of a form) is submitted. See the <a href="#fromTextArea">API\n
     reference</a> for a full description of this method.</p>\n
+\n
+    <h3 id=modloader>Module loaders</h3>\n
+\n
+    <p>The files in the CodeMirror distribution contain shims for\n
+    loading them (and their dependencies) in AMD or CommonJS\n
+    environments. If the variables <code>exports</code>\n
+    and <code>module</code> exist and have type object, CommonJS-style\n
+    require will be used. If not, but there is a\n
+    function <code>define</code> with an <code>amd</code> property\n
+    present, AMD-style (RequireJS) will be used.</p>\n
+\n
+    <p>It is possible to\n
+    use <a href="http://browserify.org/">Browserify</a> or similar\n
+    tools to statically build modules using CodeMirror. Alternatively,\n
+    use <a href="http://requirejs.org/">RequireJS</a> to dynamically\n
+    load dependencies at runtime. Both of these approaches have the\n
+    advantage that they don\'t use the global namespace and can, thus,\n
+    do things like load multiple versions of CodeMirror alongside each\n
+    other.</p>\n
+\n
+    <p>Here\'s a simple example of using RequireJS to load CodeMirror:</p>\n
+\n
+    <pre data-lang="javascript">require([\n
+  "cm/lib/codemirror", "cm/mode/htmlmixed/htmlmixed"\n
+], function(CodeMirror) {\n
+  CodeMirror.fromTextArea(document.getElementById("code"), {\n
+    lineNumbers: true,\n
+    mode: "htmlmixed"\n
+  });\n
+});</pre>\n
+\n
+    <p>It will automatically load the modes that the mixed HTML mode\n
+    depends on (XML, JavaScript, and CSS).</p>\n
 \n
 </section>\n
+\n
 <section id=config>\n
     <h2>Configuration</h2>\n
 \n
@@ -267,18 +311,18 @@
       on Windows, and <code>true</code> on other platforms.</dd>\n
 \n
       <dt id="option_keyMap"><code><strong>keyMap</strong>: string</code></dt>\n
-      <dd>Configures the keymap to use. The default\n
-      is <code>"default"</code>, which is the only keymap defined\n
-      in <code>codemirror.js</code> itself. Extra keymaps are found in\n
-      the <a href="../keymap/"><code>keymap</code></a> directory. See\n
-      the <a href="#keymaps">section on keymaps</a> for more\n
+      <dd>Configures the key map to use. The default\n
+      is <code>"default"</code>, which is the only key map defined\n
+      in <code>codemirror.js</code> itself. Extra key maps are found in\n
+      the <a href="../keymap/"><code>key map</code></a> directory. See\n
+      the <a href="#keymaps">section on key maps</a> for more\n
       information.</dd>\n
 \n
       <dt id="option_extraKeys"><code><strong>extraKeys</strong>: object</code></dt>\n
-      <dd>Can be used to specify extra keybindings for the editor,\n
+      <dd>Can be used to specify extra key bindings for the editor,\n
       alongside the ones defined\n
       by <a href="#option_keyMap"><code>keyMap</code></a>. Should be\n
-      either null, or a valid <a href="#keymaps">keymap</a> value.</dd>\n
+      either null, or a valid <a href="#keymaps">key map</a> value.</dd>\n
 \n
       <dt id="option_lineWrapping"><code><strong>lineWrapping</strong>: boolean</code></dt>\n
       <dd>Whether CodeMirror should scroll or wrap for long lines.\n
@@ -311,6 +355,14 @@
       <dd>Determines whether the gutter scrolls along with the content\n
       horizontally (false) or whether it stays fixed during horizontal\n
       scrolling (true, the default).</dd>\n
+\n
+      <dt id="option_scrollbarStyle"><code><strong>scrollbarStyle</strong>: string</code></dt>\n
+      <dd>Chooses a scrollbar implementation. The default\n
+      is <code>"native"</code>, showing native scrollbars. The core\n
+      library also provides the <code>"null"</code> style, which\n
+      completely hides the\n
+      scrollbars. <a href="#addon_simplescrollbars">Addons</a> can\n
+      implement additional scrollbar models.</dd>\n
 \n
       <dt id="option_coverGutterNextToScrollbar"><code><strong>coverGutterNextToScrollbar</strong>: boolean</code></dt>\n
       <dd>When <a href="#option_fixedGutter"><code>fixedGutter</code></a>\n
@@ -331,12 +383,13 @@
 \n
       <dt id="option_undoDepth"><code><strong>undoDepth</strong>: integer</code></dt>\n
       <dd>The maximum number of undo levels that the editor stores.\n
-      Defaults to 40.</dd>\n
+      Note that this includes selection change events. Defaults to\n
+      200.</dd>\n
 \n
       <dt id="option_historyEventDelay"><code><strong>historyEventDelay</strong>: integer</code></dt>\n
       <dd>The period of inactivity (in milliseconds) that will cause a\n
       new history event to be started when typing or deleting.\n
-      Defaults to 500.</dd>\n
+      Defaults to 1250.</dd>\n
 \n
       <dt id="option_tabindex"><code><strong>tabindex</strong>: integer</code></dt>\n
       <dd>The <a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex">tab\n
@@ -360,42 +413,11 @@
     <dl>\n
       <dt id="option_dragDrop"><code><strong>dragDrop</strong>: boolean</code></dt>\n
       <dd>Controls whether drag-and-drop is enabled. On by default.</dd>\n
-\n
-      <dt id="option_onDragEvent"><code><strong>onDragEvent</strong>: function(instance: CodeMirror, event: Event) 芒聠聮 boolean</code></dt>\n
-      <dd><em>Deprecated! See <a href="#event_dom">these</a> event\n
-      handlers for the current recommended approach.</em><br>When given,\n
-      this will be called when the editor is handling\n
-      a <code>dragenter</code>, <code>dragover</code>,\n
-      or <code>drop</code> event. It will be passed the editor\n
-      instance and the event object as arguments. The callback can\n
-      choose to handle the event itself, in which case it should\n
-      return <code>true</code> to indicate that CodeMirror should not\n
-      do anything further.</dd>\n
-\n
-      <dt id="option_onKeyEvent"><code><strong>onKeyEvent</strong>: function(instance: CodeMirror, event: Event) 芒聠聮 boolean</code></dt>\n
-      <dd><em>Deprecated! See <a href="#event_dom">these</a> event\n
-      handlers for the current recommended approach.</em><br>This\n
-      provides a rather low-level hook into CodeMirror\'s key handling.\n
-      If provided, this function will be called on\n
-      every <code>keydown</code>, <code>keyup</code>,\n
-      and <code>keypress</code> event that CodeMirror captures. It\n
-      will be passed two arguments, the editor instance and the key\n
-      event. This key event is pretty much the raw key event, except\n
-      that a <code>stop()</code> method is always added to it. You\n
-      could feed it to, for example, <code>jQuery.Event</code> to\n
-      further normalize it.<br>This function can inspect the key\n
-      event, and handle it if it wants to. It may return true to tell\n
-      CodeMirror to ignore the event. Be wary that, on some browsers,\n
-      stopping a <code>keydown</code> does not stop\n
-      the <code>keypress</code> from firing, whereas on others it\n
-      does. If you respond to an event, you should probably inspect\n
-      its <code>type</code> property and only do something when it\n
-      is <code>keydown</code> (or <code>keypress</code> for actions\n
-      that need character data).</dd>\n
 \n
       <dt id="option_cursorBlinkRate"><code><strong>cursorBlinkRate</strong>: number</code></dt>\n
       <dd>Half-period in milliseconds used for cursor blinking. The default blink\n
-      rate is 530ms. By setting this to zero, blinking can be disabled.</dd>\n
+      rate is 530ms. By setting this to zero, blinking can be disabled. A\n
+      negative value hides the cursor entirely.</dd>\n
 \n
       <dt id="option_cursorScrollMargin"><code><strong>cursorScrollMargin</strong>: number</code></dt>\n
       <dd>How much extra space to always keep above and below the\n
@@ -414,15 +436,12 @@
       click outside of the current selection, the cursor is moved to\n
       the point of the click. Defaults to <code>true</code>.</dd>\n
 \n
-      <dt id="option_workTime"><code><strong>workTime</strong>, <strong>workDelay</strong>: number</code></dt>\n
+      <dt id="option_workTime"><code id="option_wordkDelay"><strong>workTime</strong>, <strong>workDelay</strong>: number</code></dt>\n
       <dd>Highlighting is done by a pseudo background-thread that will\n
       work for <code>workTime</code> milliseconds, and then use\n
       timeout to sleep for <code>workDelay</code> milliseconds. The\n
       defaults are 200 and 300, you can change these options to make\n
       the highlighting more or less aggressive.</dd>\n
-\n
-      <dt id="option_workDelay"><code><strong>workDelay</strong>: number</code></dt>\n
-      <dd>See <a href="#option_workTime"><code>workTime</code></a>.</dd>\n
 \n
       <dt id="option_pollInterval"><code><strong>pollInterval</strong>: number</code></dt>\n
       <dd>Indicates how quickly CodeMirror should poll its input\n
@@ -497,7 +516,7 @@
       <dt id="event_change"><code><strong>"change"</strong> (instance: CodeMirror, changeObj: object)</code></dt>\n
       <dd>Fires every time the content of the editor is changed.\n
       The <code>changeObj</code> is a <code>{from, to, text, removed,\n
-      next}</code> object containing information about the changes\n
+      origin}</code> object containing information about the changes\n
       that occurred as second argument. <code>from</code>\n
       and <code>to</code> are the positions (in the pre-change\n
       coordinate system) where the change started and ended (for\n
@@ -506,10 +525,13 @@
       an array of strings representing the text that replaced the\n
       changed range (split by line). <code>removed</code> is the text\n
       that used to be between <code>from</code> and <code>to</code>,\n
-      which is overwritten by this change. If multiple changes\n
-      happened during a single operation, the object will have\n
-      a <code>next</code> property pointing to another change object\n
-      (which may point to another, etc).</dd>\n
+      which is overwritten by this change.</dd>\n
+\n
+      <dt id="event_changes"><code><strong>"changes"</strong> (instance: CodeMirror, changes: array&lt;object&gt;)</code></dt>\n
+      <dd>Like the <a href="#event_change"><code>"change"</code></a>\n
+      event, but batched per <a href="#operation">operation</a>,\n
+      passing an array containing all the changes that happened in the\n
+      operation.</dd>\n
 \n
       <dt id="event_beforeChange"><code><strong>"beforeChange"</strong> (instance: CodeMirror, changeObj: object)</code></dt>\n
       <dd>This event is fired before a change is applied, and its\n
@@ -517,12 +539,10 @@
       The <code>changeObj</code> object\n
       has <code>from</code>, <code>to</code>, and <code>text</code>\n
       properties, as with\n
-      the <a href="#event_change"><code>"change"</code></a> event, but\n
-      never a <code>next</code> property, since this is fired for each\n
-      individual change, and not batched per operation. It also has\n
-      a <code>cancel()</code> method, which can be called to cancel\n
-      the change, and, <strong>if</strong> the change isn\'t coming\n
-      from an undo or redo event, an <code>update(from, to,\n
+      the <a href="#event_change"><code>"change"</code></a> event. It\n
+      also has a <code>cancel()</code> method, which can be called to\n
+      cancel the change, and, <strong>if</strong> the change isn\'t\n
+      coming from an undo or redo event, an <code>update(from, to,\n
       text)</code> method, which may be used to modify the change.\n
       Undo or redo changes can\'t be modified, because they hold some\n
       metainformation for restoring old marked ranges that is only\n
@@ -542,7 +562,7 @@
 \n
       <dt id="event_keyHandled"><code><strong>"keyHandled"</strong> (instance: CodeMirror, name: string, event: Event)</code></dt>\n
       <dd>Fired after a key is handled through a\n
-      keymap. <code>name</code> is the name of the handled key (for\n
+      key map. <code>name</code> is the name of the handled key (for\n
       example <code>"Ctrl-X"</code> or <code>"\'q\'"</code>),\n
       and <code>event</code> is the DOM <code>keydown</code>\n
       or <code>keypress</code> event.</dd>\n
@@ -551,14 +571,15 @@
       <dd>Fired whenever new input is read from the hidden textarea\n
       (typed or pasted by the user).</dd>\n
 \n
-      <dt id="event_beforeSelectionChange"><code><strong>"beforeSelectionChange"</strong> (instance: CodeMirror, selection: {head, anchor})</code></dt>\n
+      <dt id="event_beforeSelectionChange"><code><strong>"beforeSelectionChange"</strong> (instance: CodeMirror, obj: {ranges, update})</code></dt>\n
       <dd>This event is fired before the selection is moved. Its\n
-      handler may modify the resulting selection head and anchor.\n
-      The <code>selection</code> parameter is an object\n
-      with <code>head</code> and <code>anchor</code> properties\n
-      holding <code>{line, ch}</code> objects, which the handler can\n
-      read and update. Handlers for this event have the same\n
-      restriction\n
+      handler may inspect the set of selection ranges, present as an\n
+      array of <code>{anchor, head}</code> objects in\n
+      the <code>ranges</code> property of the <code>obj</code>\n
+      argument, and optionally change them by calling\n
+      the <code>update</code> method on this object, passing an array\n
+      of ranges in the same format. Handlers for this event have the\n
+      same restriction\n
       as <a href="#event_beforeChange"><code>"beforeChange"</code></a>\n
       handlers 芒聙聰 they should not do anything to directly update the\n
       state of the editor.</dd>\n
@@ -600,6 +621,13 @@
 \n
       <dt id="event_scroll"><code><strong>"scroll"</strong> (instance: CodeMirror)</code></dt>\n
       <dd>Fires when the editor is scrolled.</dd>\n
+\n
+      <dt id="event_scrollCursorIntoView"><code><strong>"scrollCursorIntoView"</strong> (instance: CodeMirror, event: Event)</code></dt>\n
+      <dd>Fires when the editor tries to scroll its cursor into view.\n
+      Can be hooked into to take care of additional scrollable\n
+      containers around the editor. When the event object has\n
+      its <code>preventDefault</code> method called, CodeMirror will\n
+      not itself try to scroll the window.</dd>\n
 \n
       <dt id="event_update"><code><strong>"update"</strong> (instance: CodeMirror)</code></dt>\n
       <dd>Will be fired whenever CodeMirror updates its DOM display.</dd>\n
@@ -632,9 +660,7 @@
       document. <code>changeObj</code> has a similar type as the\n
       object passed to the\n
       editor\'s <a href="#event_change"><code>"change"</code></a>\n
-      event, but it never has a <code>next</code> property, because\n
-      document change events are not batched (whereas editor change\n
-      events are).</dd>\n
+      event.</dd>\n
 \n
       <dt id="event_doc_beforeChange"><code><strong>"beforeChange"</strong> (doc: CodeMirror.Doc, change: object)</code></dt>\n
       <dd>See the <a href="#event_beforeChange">description of the\n
@@ -713,11 +739,15 @@
 </section>\n
 \n
 <section id=keymaps>\n
-    <h2>Keymaps</h2>\n
+    <h2>Key Maps</h2>\n
 \n
-    <p>Keymaps are ways to associate keys with functionality. A keymap\n
+    <p>Key maps are ways to associate keys with functionality. A key map\n
     is an object mapping strings that identify the keys to functions\n
     that implement their functionality.</p>\n
+\n
+    <p>The CodeMirror distributions comes\n
+    with <a href="../demo/emacs.html">Emacs</a>, <a href="../demo/vim.html">Vim</a>,\n
+    and <a href="../demo/sublime.html">Sublime Text</a>-style keymaps.</p>\n
 \n
     <p>Keys are identified either by name or by character.\n
     The <code>CodeMirror.keyNames</code> object defines names for\n
@@ -725,65 +755,272 @@
     names defined here are <code>Enter</code>, <code>F5</code>,\n
     and <code>Q</code>. These can be prefixed\n
     with <code>Shift-</code>, <code>Cmd-</code>, <code>Ctrl-</code>,\n
-    and <code>Alt-</code> (in that order!) to specify a modifier. So\n
-    for example, <code>Shift-Ctrl-Space</code> would be a valid key\n
+    and <code>Alt-</code> to specify a modifier. So for\n
+    example, <code>Shift-Ctrl-Space</code> would be a valid key\n
     identifier.</p>\n
 \n
     <p>Common example: map the Tab key to insert spaces instead of a tab\n
     character.</p>\n
 \n
     <pre data-lang="javascript">\n
-{\n
+editor.setOption("extraKeys", {\n
   Tab: function(cm) {\n
     var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");\n
-    cm.replaceSelection(spaces, "end", "+input");\n
+    cm.replaceSelection(spaces);\n
   }\n
-}</pre>\n
+});</pre>\n
 \n
     <p>Alternatively, a character can be specified directly by\n
     surrounding it in single quotes, for example <code>\'$\'</code>\n
     or <code>\'q\'</code>. Due to limitations in the way browsers fire\n
     key events, these may not be prefixed with modifiers.</p>\n
 \n
-    <p>The <code>CodeMirror.keyMap</code> object associates keymaps\n
-    with names. User code and keymap definitions can assign extra\n
-    properties to this object. Anywhere where a keymap is expected, a\n
+    <p id="normalizeKeyMap">Multi-stroke key bindings can be specified\n
+    by separating the key names by spaces in the property name, for\n
+    example <code>Ctrl-X Ctrl-V</code>. When a map contains\n
+    multi-stoke bindings or keys with modifiers that are not specified\n
+    in the default order (<code>Shift-Cmd-Ctrl-Alt</code>), you must\n
+    call <code>CodeMirror.normalizeKeyMap</code> on it before it can\n
+    be used. This function takes a keymap and modifies it to normalize\n
+    modifier order and properly recognize multi-stroke bindings. It\n
+    will return the keymap itself.</p>\n
+\n
+    <p>The <code>CodeMirror.keyMap</code> object associates key maps\n
+    with names. User code and key map definitions can assign extra\n
+    properties to this object. Anywhere where a key map is expected, a\n
     string can be given, which will be looked up in this object. It\n
-    also contains the <code>"default"</code> keymap holding the\n
+    also contains the <code>"default"</code> key map holding the\n
     default bindings.</p>\n
 \n
-    <p id="commands">The values of properties in keymaps can be either functions of\n
+    <p>The values of properties in key maps can be either functions of\n
     a single argument (the CodeMirror instance), strings, or\n
-    <code>false</code>. Such strings refer to properties of the\n
-    <code>CodeMirror.commands</code> object, which defines a number of\n
-    common commands that are used by the default keybindings, and maps\n
-    them to functions. If the property is set to <code>false</code>,\n
-    CodeMirror leaves handling of the key up to the browser. A key\n
-    handler function may return <code>CodeMirror.Pass</code> to indicate\n
-    that it has decided not to handle the key, and other handlers (or\n
-    the default behavior) should be given a turn.</p>\n
+    <code>false</code>. Strings refer\n
+    to <a href="#commands">commands</a>, which are described below. If\n
+    the property is set to <code>false</code>, CodeMirror leaves\n
+    handling of the key up to the browser. A key handler function may\n
+    return <code>CodeMirror.Pass</code> to indicate that it has\n
+    decided not to handle the key, and other handlers (or the default\n
+    behavior) should be given a turn.</p>\n
 \n
     <p>Keys mapped to command names that start with the\n
-    characters <code>"go"</code> (which should be used for\n
+    characters <code>"go"</code> or to functions that have a\n
+    truthy <code>motion</code> property (which should be used for\n
     cursor-movement actions) will be fired even when an\n
     extra <code>Shift</code> modifier is present (i.e. <code>"Up":\n
     "goLineUp"</code> matches both up and shift-up). This is used to\n
     easily implement shift-selection.</p>\n
 \n
-    <p>Keymaps can defer to each other by defining\n
+    <p>Key maps can defer to each other by defining\n
     a <code>fallthrough</code> property. This indicates that when a\n
     key is not found in the map itself, one or more other maps should\n
-    be searched. It can hold either a single keymap or an array of\n
-    keymaps.</p>\n
-\n
-    <p>When a keymap contains a <code>nofallthrough</code> property\n
-    set to <code>true</code>, keys matched against that map will be\n
-    ignored if they don\'t match any of the bindings in the map (no\n
-    further child maps will be tried). When\n
-    the <code>disableInput</code> property is set\n
-    to <code>true</code>, the default effect of inserting a character\n
-    will be suppressed when the keymap is active as the top-level\n
-    map.</p>\n
+    be searched. It can hold either a single key map or an array of\n
+    key maps.</p>\n
+\n
+    <p>When a key map needs to set something up when it becomes\n
+    active, or tear something down when deactivated, it can\n
+    contain <code>attach</code> and/or <code>detach</code> properties,\n
+    which should hold functions that take the editor instance and the\n
+    next or previous keymap. Note that this only works for the\n
+    <a href="#option_keyMap">top-level keymap</a>, not for fallthrough\n
+    maps or maps added\n
+    with <a href="#option_extraKeys"><code>extraKeys</code></a>\n
+    or <a href="#addKeyMap"><code>addKeyMap</code></a>.</p>\n
+</section>\n
+\n
+<section id=commands>\n
+    <h2>Commands</h2>\n
+\n
+    <p>Commands are parameter-less actions that can be performed on an\n
+    editor. Their main use is for key bindings. Commands are defined by\n
+    adding properties to the <code>CodeMirror.commands</code> object.\n
+    A number of common commands are defined by the library itself,\n
+    most of them used by the default key bindings. The value of a\n
+    command property must be a function of one argument (an editor\n
+    instance).</p>\n
+\n
+    <p>Some of the commands below are referenced in the default\n
+    key map, but not defined by the core library. These are intended to\n
+    be defined by user code or addons.</p>\n
+\n
+    <p>Commands can also be run with\n
+    the <a href="#execCommand"><code>execCommand</code></a>\n
+    method.</p>\n
+\n
+    <dl>\n
+      <dt class=command id=command_selectAll><code><strong>selectAll</strong></code><span class=keybinding>Ctrl-A (PC), Cmd-A (Mac)</span></dt>\n
+      <dd>Select the whole content of the editor.</dd>\n
+\n
+      <dt class=command id=command_singleSelection><code><strong>singleSelection</strong></code><span class=keybinding>Esc</span></dt>\n
+      <dd>When multiple selections are present, this deselects all but\n
+      the primary selection.</dd>\n
+\n
+      <dt class=command id=command_killLine><code><strong>killLine</strong></code><span class=keybinding>Ctrl-K (Mac)</span></dt>\n
+      <dd>Emacs-style line killing. Deletes the part of the line after\n
+      the cursor. If that consists only of whitespace, the newline at\n
+      the end of the line is also deleted.</dd>\n
+\n
+      <dt class=command id=command_deleteLine><code><strong>deleteLine</strong></code><span class=keybinding>Ctrl-D (PC), Cmd-D (Mac)</span></dt>\n
+      <dd>Deletes the whole line under the cursor, including newline at the end.</dd>\n
+\n
+      <dt class=command id=command_delLineLeft><code><strong>delLineLeft</strong></code></dt>\n
+      <dd>Delete the part of the line before the cursor.</dd>\n
+\n
+      <dt class=command id=command_delWrappedLineLeft><code><strong>delWrappedLineLeft</strong></code><span class=keybinding>Cmd-Backspace (Mac)</span></dt>\n
+      <dd>Delete the part of the line from the left side of the visual line the cursor is on to the cursor.</dd>\n
+\n
+      <dt class=command id=command_delWrappedLineRight><code><strong>delWrappedLineRight</strong></code><span class=keybinding>Cmd-Delete (Mac)</span></dt>\n
+      <dd>Delete the part of the line from the cursor to the right side of the visual line the cursor is on.</dd>\n
+\n
+      <dt class=command id=command_undo><code><strong>undo</strong></code><span class=keybinding>Ctrl-Z (PC), Cmd-Z (Mac)</span></dt>\n
+      <dd>Undo the last change.</dd>\n
+\n
+      <dt class=command id=command_redo><code><strong>redo</strong></code><span class=keybinding>Ctrl-Y (PC), Shift-Cmd-Z (Mac), Cmd-Y (Mac)</span></dt>\n
+      <dd>Redo the last undone change.</dd>\n
+\n
+      <dt class=command id=command_undoSelection><code><strong>undoSelection</strong></code><span class=keybinding>Ctrl-U (PC), Cmd-U (Mac)</span></dt>\n
+      <dd>Undo the last change to the selection, or if there are no\n
+      selection-only changes at the top of the history, undo the last\n
+      change.</dd>\n
+\n
+      <dt class=command id=command_redoSelection><code><strong>redoSelection</strong></code><span class=keybinding>Alt-U (PC), Shift-Cmd-U (Mac)</span></dt>\n
+      <dd>Redo the last change to the selection, or the last text change if\n
+      no selection changes remain.</dd>\n
+\n
+      <dt class=command id=command_goDocStart><code><strong>goDocStart</strong></code><span class=keybinding>Ctrl-Up (PC), Cmd-Up (Mac), Cmd-Home (Mac)</span></dt>\n
+      <dd>Move the cursor to the start of the document.</dd>\n
+\n
+      <dt class=command id=command_goDocEnd><code><strong>goDocEnd</strong></code><span class=keybinding>Ctrl-Down (PC), Cmd-End (Mac), Cmd-Down (Mac)</span></dt>\n
+      <dd>Move the cursor to the end of the document.</dd>\n
+\n
+      <dt class=command id=command_goLineStart><code><strong>goLineStart</strong></code><span class=keybinding>Alt-Left (PC), Ctrl-A (Mac)</span></dt>\n
+      <dd>Move the cursor to the start of the line.</dd>\n
+\n
+      <dt class=command id=command_goLineStartSmart><code><strong>goLineStartSmart</strong></code><span class=keybinding>Home</span></dt>\n
+      <dd>Move to the start of the text on the line, or if we are\n
+      already there, to the actual start of the line (including\n
+      whitespace).</dd>\n
+\n
+      <dt class=command id=command_goLineEnd><code><strong>goLineEnd</strong></code><span class=keybinding>Alt-Right (PC), Ctrl-E (Mac)</span></dt>\n
+      <dd>Move the cursor to the end of the line.</dd>\n
+\n
+      <dt class=command id=command_goLineRight><code><strong>goLineRight</strong></code><span class=keybinding>Cmd-Right (Mac)</span></dt>\n
+      <dd>Move the cursor to the right side of the visual line it is on.</dd>\n
+\n
+      <dt class=command id=command_goLineLeft><code><strong>goLineLeft</strong></code><span class=keybinding>Cmd-Left (Mac)</span></dt>\n
+      <dd>Move the cursor to the left side of the visual line it is on. If\n
+      this line is wrapped, that may not be the start of the line.</dd>\n
+\n
+      <dt class=command id=command_goLineLeftSmart><code><strong>goLineLeftSmart</strong></code></dt>\n
+      <dd>Move the cursor to the left side of the visual line it is\n
+      on. If that takes it to the start of the line, behave\n
+      like <a href="#command_goLineStartSmart"><code>goLineStartSmart</code></a>.</dd>\n
+\n
+      <dt class=command id=command_goLineUp><code><strong>goLineUp</strong></code><span class=keybinding>Up, Ctrl-P (Mac)</span></dt>\n
+      <dd>Move the cursor up one line.</dd>\n
+\n
+      <dt class=command id=command_goLineDown><code><strong>goLineDown</strong></code><span class=keybinding>Down, Ctrl-N (Mac)</span></dt>\n
+      <dd>Move down one line.</dd>\n
+\n
+      <dt class=command id=command_goPageUp><code><strong>goPageUp</strong></code><span class=keybinding>PageUp, Shift-Ctrl-V (Mac)</span></dt>\n
+      <dd>Move the cursor up one screen, and scroll up by the same distance.</dd>\n
+\n
+      <dt class=command id=command_goPageDown><code><strong>goPageDown</strong></code><span class=keybinding>PageDown, Ctrl-V (Mac)</span></dt>\n
+      <dd>Move the cursor down one screen, and scroll down by the same distance.</dd>\n
+\n
+      <dt class=command id=command_goCharLeft><code><strong>goCharLeft</strong></code><span class=keybinding>Left, Ctrl-B (Mac)</span></dt>\n
+      <dd>Move the cursor one character left, going to the previous line\n
+      when hitting the start of line.</dd>\n
+\n
+      <dt class=command id=command_goCharRight><code><strong>goCharRight</strong></code><span class=keybinding>Right, Ctrl-F (Mac)</span></dt>\n
+      <dd>Move the cursor one character right, going to the next line\n
+      when hitting the end of line.</dd>\n
+\n
+      <dt class=command id=command_goColumnLeft><code><strong>goColumnLeft</strong></code></dt>\n
+      <dd>Move the cursor one character left, but don\'t cross line boundaries.</dd>\n
+\n
+      <dt class=command id=command_goColumnRight><code><strong>goColumnRight</strong></code></dt>\n
+      <dd>Move the cursor one character right, don\'t cross line boundaries.</dd>\n
+\n
+      <dt class=command id=command_goWordLeft><code><strong>goWordLeft</strong></code><span class=keybinding>Alt-B (Mac)</span></dt>\n
+      <dd>Move the cursor to the start of the previous word.</dd>\n
+\n
+      <dt class=command id=command_goWordRight><code><strong>goWordRight</strong></code><span class=keybinding>Alt-F (Mac)</span></dt>\n
+      <dd>Move the cursor to the end of the next word.</dd>\n
+\n
+      <dt class=command id=command_goGroupLeft><code><strong>goGroupLeft</strong></code><span class=keybinding>Ctrl-Left (PC), Alt-Left (Mac)</span></dt>\n
+      <dd>Move to the left of the group before the cursor. A group is\n
+      a stretch of word characters, a stretch of punctuation\n
+      characters, a newline, or a stretch of <em>more than one</em>\n
+      whitespace character.</dd>\n
+\n
+      <dt class=command id=command_goGroupRight><code><strong>goGroupRight</strong></code><span class=keybinding>Ctrl-Right (PC), Alt-Right (Mac)</span></dt>\n
+      <dd>Move to the right of the group after the cursor\n
+      (see <a href="#command_goGroupLeft">above</a>).</dd>\n
+\n
+      <dt class=command id=command_delCharBefore><code><strong>delCharBefore</strong></code><span class=keybinding>Shift-Backspace, Ctrl-H (Mac)</span></dt>\n
+      <dd>Delete the character before the cursor.</dd>\n
+\n
+      <dt class=command id=command_delCharAfter><code><strong>delCharAfter</strong></code><span class=keybinding>Delete, Ctrl-D (Mac)</span></dt>\n
+      <dd>Delete the character after the cursor.</dd>\n
+\n
+      <dt class=command id=command_delWordBefore><code><strong>delWordBefore</strong></code><span class=keybinding>Alt-Backspace (Mac)</span></dt>\n
+      <dd>Delete up to the start of the word before the cursor.</dd>\n
+\n
+      <dt class=command id=command_delWordAfter><code><strong>delWordAfter</strong></code><span class=keybinding>Alt-D (Mac)</span></dt>\n
+      <dd>Delete up to the end of the word after the cursor.</dd>\n
+\n
+      <dt class=command id=command_delGroupBefore><code><strong>delGroupBefore</strong></code><span class=keybinding>Ctrl-Backspace (PC), Alt-Backspace (Mac)</span></dt>\n
+      <dd>Delete to the left of the <a href="#command_goGroupLeft">group</a> before the cursor.</dd>\n
+\n
+      <dt class=command id=command_delGroupAfter><code><strong>delGroupAfter</strong></code><span class=keybinding>Ctrl-Delete (PC), Ctrl-Alt-Backspace (Mac), Alt-Delete (Mac)</span></dt>\n
+      <dd>Delete to the start of the <a href="#command_goGroupLeft">group</a> after the cursor.</dd>\n
+\n
+      <dt class=command id=command_indentAuto><code><strong>indentAuto</strong></code><span class=keybinding>Shift-Tab</span></dt>\n
+      <dd>Auto-indent the current line or selection.</dd>\n
+\n
+      <dt class=command id=command_indentMore><code><strong>indentMore</strong></code><span class=keybinding>Ctrl-] (PC), Cmd-] (Mac)</span></dt>\n
+      <dd>Indent the current line or selection by one <a href="#option_indentUnit">indent unit</a>.</dd>\n
+\n
+      <dt class=command id=command_indentLess><code><strong>indentLess</strong></code><span class=keybinding>Ctrl-[ (PC), Cmd-[ (Mac)</span></dt>\n
+      <dd>Dedent the current line or selection by one <a href="#option_indentUnit">indent unit</a>.</dd>\n
+\n
+      <dt class=command id=command_insertTab><code><strong>insertTab</strong></code></dt>\n
+      <dd>Insert a tab character at the cursor.</dd>\n
+\n
+      <dt class=command id=command_insertSoftTab><code><strong>insertSoftTab</strong></code></dt>\n
+      <dd>Insert the amount of spaces that match the width a tab at\n
+      the cursor position would have.</dd>\n
+\n
+      <dt class=command id=command_defaultTab><code><strong>defaultTab</strong></code><span class=keybinding>Tab</span></dt>\n
+      <dd>If something is selected, indent it by\n
+      one <a href="#option_indentUnit">indent unit</a>. If nothing is\n
+      selected, insert a tab character.</dd>\n
+\n
+      <dt class=command id=command_transposeChars><code><strong>transposeChars</strong></code><span class=keybinding>Ctrl-T (Mac)</span></dt>\n
+      <dd>Swap the characters before and after the cursor.</dd>\n
+\n
+      <dt class=command id=command_newlineAndIndent><code><strong>newlineAndIndent</strong></code><span class=keybinding>Enter</span></dt>\n
+      <dd>Insert a newline and auto-indent the new line.</dd>\n
+\n
+      <dt class=command id=command_toggleOverwrite><code><strong>toggleOverwrite</strong></code><span class=keybinding>Insert</span></dt>\n
+      <dd>Flip the <a href="#toggleOverwrite">overwrite</a> flag.</dd>\n
+\n
+      <dt class=command id=command_save><code><strong>save</strong></code><span class=keybinding>Ctrl-S (PC), Cmd-S (Mac)</span></dt>\n
+      <dd>Not defined by the core library, only referred to in\n
+      key maps. Intended to provide an easy way for user code to define\n
+      a save command.</dd>\n
+\n
+      <dt class=command id=command_find><code><strong>find</strong></code><span class=keybinding>Ctrl-F (PC), Cmd-F (Mac)</span></dt>\n
+      <dt class=command id=command_findNext><code><strong>findNext</strong></code><span class=keybinding>Ctrl-G (PC), Cmd-G (Mac)</span></dt>\n
+      <dt class=command id=command_findPrev><code><strong>findPrev</strong></code><span class=keybinding>Shift-Ctrl-G (PC), Shift-Cmd-G (Mac)</span></dt>\n
+      <dt class=command id=command_replace><code><strong>replace</strong></code><span class=keybinding>Shift-Ctrl-F (PC), Cmd-Alt-F (Mac)</span></dt>\n
+      <dt class=command id=command_replaceAll><code><strong>replaceAll</strong></code><span class=keybinding>Shift-Ctrl-R (PC), Shift-Cmd-Alt-F (Mac)</span></dt>\n
+      <dd>Not defined by the core library, but defined in\n
+      the <a href="#addon_search">search addon</a> (or custom client\n
+      addons).</dd>\n
+\n
+    </dl>\n
+\n
 </section>\n
 \n
 <section id=styling>\n
@@ -807,16 +1044,12 @@
       <dd>The outer element of the editor. This should be used for the\n
       editor width, height, borders and positioning. Can also be used\n
       to set styles that should hold for everything inside the editor\n
-      (such as font and font size), or to set a background.</dd>\n
-\n
-      <dt id="class_CodeMirror_scroll"><code><strong>CodeMirror-scroll</strong></code></dt>\n
-      <dd>Whether the editor scrolls (<code>overflow: auto</code> +\n
-      fixed height). By default, it does. Setting\n
-      the <code>CodeMirror</code> class to have <code>height:\n
-      auto</code> and giving this class <code>overflow-x: auto;\n
-      overflow-y: hidden;</code> will cause the editor\n
-      to <a href="../demo/resize.html">resize to fit its\n
-      content</a>.</dd>\n
+      (such as font and font size), or to set a background. Setting\n
+      this class\' <code>height</code> style to <code>auto</code> will\n
+      make the editor <a href="../demo/resize.html">resize to fit its\n
+      content</a> (it is recommended to also set\n
+      the <a href="#option_viewportMargin"><code>viewportMargin</code>\n
+      option</a> to <code>Infinity</code> when doing this.</dd>\n
 \n
       <dt id="class_CodeMirror_focused"><code><strong>CodeMirror-focused</strong></code></dt>\n
       <dd>Whenever the editor is focused, the top element gets this\n
@@ -926,19 +1159,20 @@
       should be <code>{line, ch}</code> objects. An optional third\n
       argument can be given to indicate the line separator string to\n
       use (defaults to <code>"\\n"</code>).</dd>\n
-      <dt id="replaceRange"><code><strong>doc.replaceRange</strong>(replacement: string, from: {line, ch}, to: {line, ch})</code></dt>\n
+      <dt id="replaceRange"><code><strong>doc.replaceRange</strong>(replacement: string, from: {line, ch}, to:脗聽{line,脗聽ch}, ?origin:脗聽string)</code></dt>\n
       <dd>Replace the part of the document between <code>from</code>\n
       and <code>to</code> with the given string. <code>from</code>\n
       and <code>to</code> must be <code>{line, ch}</code>\n
       objects. <code>to</code> can be left off to simply insert the\n
-      string at position <code>from</code>.</dd>\n
+      string at position <code>from</code>. When <code>origin</code>\n
+      is given, it will be passed on\n
+      to <a href="#event_change"><code>"change"</code> events</a>, and\n
+      its first letter will be used to determine whether this change\n
+      can be merged with previous history events, in the way described\n
+      for <a href="#selection_origin">selection origins</a>.</dd>\n
 \n
       <dt id="getLine"><code><strong>doc.getLine</strong>(n: integer) 芒聠聮 string</code></dt>\n
       <dd>Get the content of line <code>n</code>.</dd>\n
-      <dt id="setLine"><code><strong>doc.setLine</strong>(n: integer, text: string)</code></dt>\n
-      <dd>Set the content of line <code>n</code>.</dd>\n
-      <dt id="removeLine"><code><strong>doc.removeLine</strong>(n: integer)</code></dt>\n
-      <dd>Remove the given line from the document.</dd>\n
 \n
       <dt id="lineCount"><code><strong>doc.lineCount</strong>() 芒聠聮 integer</code></dt>\n
       <dd>Get the number of lines in the editor.</dd>\n
@@ -999,56 +1233,128 @@
     <h3 id="api_selection">Cursor and selection methods</h3>\n
 \n
     <dl>\n
-      <dt id="getSelection"><code><strong>doc.getSelection</strong>() 芒聠聮 string</code></dt>\n
-      <dd>Get the currently selected code.</dd>\n
-      <dt id="replaceSelection"><code><strong>doc.replaceSelection</strong>(replacement: string, ?collapse: string)</code></dt>\n
-      <dd>Replace the selection with the given string. By default, the\n
-      new selection will span the inserted text. The\n
-      optional <code>collapse</code> argument can be used to change\n
-      this芒聙聰passing <code>"start"</code> or <code>"end"</code> will\n
-      collapse the selection to the start or end of the inserted\n
-      text.</dd>\n
+      <dt id="getSelection"><code><strong>doc.getSelection</strong>(?lineSep: string) 芒聠聮 string</code></dt>\n
+      <dd>Get the currently selected code. Optionally pass a line\n
+      separator to put between the lines in the output. When multiple\n
+      selections are present, they are concatenated with instances\n
+      of <code>lineSep</code> in between.</dd>\n
+      <dt id="getSelections"><code><strong>doc.getSelections</strong>(?lineSep: string) 芒聠聮 string</code></dt>\n
+      <dd>Returns an array containing a string for each selection,\n
+      representing the content of the selections.</dd>\n
+\n
+      <dt id="replaceSelection"><code><strong>doc.replaceSelection</strong>(replacement: string, ?select: string)</code></dt>\n
+      <dd>Replace the selection(s) with the given string. By default,\n
+      the new selection ends up after the inserted text. The\n
+      optional <code>select</code> argument can be used to change\n
+      this芒聙聰passing <code>"around"</code> will cause the new text to be\n
+      selected, passing <code>"start"</code> will collapse the\n
+      selection to the start of the inserted text.</dd>\n
+      <dt id="replaceSelections"><code><strong>doc.replaceSelections</strong>(replacements: array&lt;string&gt;, ?select: string)</code></dt>\n
+      <dd>The length of the given array should be the same as the\n
+      number of active selections. Replaces the content of the\n
+      selections with the strings in the array.\n
+      The <code>select</code> argument works the same as\n
+      in <a href="#replaceSelection"><code>replaceSelection</code></a>.</dd>\n
 \n
       <dt id="getCursor"><code><strong>doc.getCursor</strong>(?start: string) 芒聠聮 {line, ch}</code></dt>\n
-      <dd><code>start</code> is a an optional string indicating which\n
-      end of the selection to return. It may\n
-      be <code>"start"</code>, <code>"end"</code>, <code>"head"</code>\n
+      <dd>Retrieve one end of the <em>primary</em>\n
+      selection. <code>start</code> is a an optional string indicating\n
+      which end of the selection to return. It may\n
+      be <code>"from"</code>, <code>"to"</code>, <code>"head"</code>\n
       (the side of the selection that moves when you press\n
       shift+arrow), or <code>"anchor"</code> (the fixed side of the\n
       selection). Omitting the argument is the same as\n
       passing <code>"head"</code>. A <code>{line, ch}</code> object\n
       will be returned.</dd>\n
+      <dt id="listSelections"><code><strong>doc.listSelections</strong>() 芒聠聮 array&lt;{anchor, head}&gt;</code></dt>\n
+      <dd>Retrieves a list of all current selections. These will\n
+      always be sorted, and never overlap (overlapping selections are\n
+      merged). Each object in the array contains <code>anchor</code>\n
+      and <code>head</code> properties referring to <code>{line,\n
+      ch}</code> objects.</dd>\n
+\n
       <dt id="somethingSelected"><code><strong>doc.somethingSelected</strong>() 芒聠聮 boolean</code></dt>\n
       <dd>Return true if any text is selected.</dd>\n
-      <dt id="setCursor"><code><strong>doc.setCursor</strong>(pos: {line, ch})</code></dt>\n
+      <dt id="setCursor"><code><strong>doc.setCursor</strong>(pos: {line, ch}|number, ?ch: number, ?options: object)</code></dt>\n
       <dd>Set the cursor position. You can either pass a\n
       single <code>{line, ch}</code> object, or the line and the\n
-      character as two separate parameters.</dd>\n
-      <dt id="setSelection"><code><strong>doc.setSelection</strong>(anchor: {line, ch}, ?head: {line, ch})</code></dt>\n
-      <dd>Set the selection range. <code>anchor</code>\n
+      character as two separate parameters. Will replace all\n
+      selections with a single, empty selection at the given position.\n
+      The supported options are the same as for <a href="#setSelection"><code>setSelection</code></a>.</dd>\n
+\n
+      <dt id="setSelection"><code><strong>doc.setSelection</strong>(anchor: {line, ch}, ?head: {line, ch}, ?options: object)</code></dt>\n
+      <dd>Set a single selection range. <code>anchor</code>\n
       and <code>head</code> should be <code>{line, ch}</code>\n
       objects. <code>head</code> defaults to <code>anchor</code> when\n
-      not given.</dd>\n
-      <dt id="extendSelection"><code><strong>doc.extendSelection</strong>(from: {line, ch}, ?to: {line, ch})</code></dt>\n
+      not given. These options are supported:\n
+      <dl>\n
+        <dt id="selection_scroll"><code><strong>scroll</strong>: boolean</code></dt>\n
+        <dd>Determines whether the selection head should be scrolled\n
+        into view. Defaults to true.</dd>\n
+        <dt id="selection_origin"><code><strong>origin</strong>: string</code></dt>\n
+        <dd>Detemines whether the selection history event may be\n
+        merged with the previous one. When an origin starts with the\n
+        character <code>+</code>, and the last recorded selection had\n
+        the same origin and was similar (close\n
+        in <a href="#option_historyEventDelay">time</a>, both\n
+        collapsed or both non-collapsed), the new one will replace the\n
+        old one. When it starts with <code>*</code>, it will always\n
+        replace the previous event (if that had the same origin).\n
+        Built-in motion uses the <code>"+move"</code> origin.</dd>\n
+        <dt id="selection_bias"><code><strong>bias</strong>: number</code></dt>\n
+        <dd>Determine the direction into which the selection endpoints\n
+        should be adjusted when they fall inside\n
+        an <a href="#mark_atomic">atomic</a> range. Can be either -1\n
+        (backward) or 1 (forward). When not given, the bias will be\n
+        based on the relative position of the old selection芒聙聰the editor\n
+        will try to move further away from that, to prevent getting\n
+        stuck.</dd>\n
+      </dl></dd>\n
+\n
+      <dt id="setSelections"><code><strong>doc.setSelections</strong>(ranges: array&lt;{anchor, head}&gt;, ?primary: integer, ?options: object)</code></dt>\n
+      <dd>Sets a new set of selections. There must be at least one\n
+      selection in the given array. When <code>primary</code> is a\n
+      number, it determines which selection is the primary one. When\n
+      it is not given, the primary index is taken from the previous\n
+      selection, or set to the last range if the previous selection\n
+      had less ranges than the new one. Supports the same options\n
+      as <a href="#setSelection"><code>setSelection</code></a>.</dd>\n
+      <dt id="addSelection"><code><strong>doc.addSelection</strong>(anchor: {line, ch}, ?head: {line, ch})</code></dt>\n
+      <dd>Adds a new selection to the existing set of selections, and\n
+      makes it the primary selection.</dd>\n
+\n
+      <dt id="extendSelection"><code><strong>doc.extendSelection</strong>(from: {line, ch}, ?to: {line, ch}, ?options: object)</code></dt>\n
       <dd>Similar\n
       to <a href="#setSelection"><code>setSelection</code></a>, but\n
       will, if shift is held or\n
       the <a href="#setExtending">extending</a> flag is set, move the\n
       head of the selection while leaving the anchor at its current\n
-      place. <code>to</code> is optional, and can be passed to\n
-      ensure a region (for example a word or paragraph) will end up\n
-      selected (in addition to whatever lies between that region and\n
-      the current anchor).</dd>\n
+      place. <code>to</code> is optional, and can be passed to ensure\n
+      a region (for example a word or paragraph) will end up selected\n
+      (in addition to whatever lies between that region and the\n
+      current anchor). When multiple selections are present, all but\n
+      the primary selection will be dropped by this method.\n
+      Supports the same options as <a href="#setSelection"><code>setSelection</code></a>.</dd>\n
+      <dt id="extendSelections"><code><strong>doc.extendSelections</strong>(heads: array&lt;{line, ch}&gt;, ?options: object)</code></dt>\n
+      <dd>An equivalent\n
+      of <a href="#extendSelection"><code>extendSelection</code></a>\n
+      that acts on all selections at once.</dd>\n
+      <dt id="extendSelectionsBy"><code><strong>doc.extendSelectionsBy</strong>(f: function(range: {anchor, head}) 芒聠聮脗聽{anchor,脗聽head}), ?options: object)</code></dt>\n
+      <dd>Applies the given function to all existing selections, and\n
+      calls <a href="#extendSelections"><code>extendSelections</code></a>\n
+      on the result.</dd>\n
       <dt id="setExtending"><code><strong>doc.setExtending</strong>(value: boolean)</code></dt>\n
       <dd>Sets or clears the \'extending\' flag, which acts similar to\n
       the shift key, in that it will cause cursor movement and calls\n
       to <a href="#extendSelection"><code>extendSelection</code></a>\n
       to leave the selection anchor in place.</dd>\n
+      <dt id="getExtending"><code><strong>doc.getExtending</strong>() 芒聠聮 boolean</code></dt>\n
+      <dd>Get the value of the \'extending\' flag.</dd>\n
 \n
       <dt id="hasFocus"><code><strong>cm.hasFocus</strong>() 芒聠聮 boolean</code></dt>\n
       <dd>Tells you whether the editor currently has focus.</dd>\n
 \n
-      <dt id="findPosH"><code><strong>cm.findPosH</strong>(start: {line, ch}, amount: integer, unit: string, visually: boolean) 芒聠聮 {line, ch, ?hitSide: boolean}</code></dt>\n
+      <dt id="findPosH"><code><strong>cm.findPosH</strong>(start: {line, ch}, amount: integer, unit: string, visually:脗聽boolean) 芒聠聮脗聽{line, ch, ?hitSide: boolean}</code></dt>\n
       <dd>Used to find the target position for horizontal cursor\n
       motion. <code>start</code> is a <code>{line, ch}</code>\n
       object, <code>amount</code> an integer (may be negative),\n
@@ -1067,6 +1373,10 @@
       be <code>"line"</code> or <code>"page"</code>. The other\n
       arguments and the returned value have the same interpretation as\n
       they have in <code>findPosH</code>.</dd>\n
+\n
+      <dt id="findWordAt"><code><strong>cm.findWordAt</strong>(pos: {line, ch}) 芒聠聮 {anchor: {line, ch}, head: {line, ch}}</code></dt>\n
+      <dd>Returns the start and end of the \'word\' (the stretch of\n
+      letters, whitespace, or punctuation) at the given position.</dd>\n
     </dl>\n
 \n
     <h3 id="api_configuration">Configuration methods</h3>\n
@@ -1082,7 +1392,7 @@
       editor instance.</dd>\n
 \n
       <dt id="addKeyMap"><code><strong>cm.addKeyMap</strong>(map: object, bottom: boolean)</code></dt>\n
-      <dd>Attach an additional <a href="#keymaps">keymap</a> to the\n
+      <dd>Attach an additional <a href="#keymaps">key map</a> to the\n
       editor. This is mostly useful for addons that need to register\n
       some key handlers without trampling on\n
       the <a href="#option_extraKeys"><code>extraKeys</code></a>\n
@@ -1091,14 +1401,14 @@
       and <a href="#option_keyMap"><code>keyMap</code></a> options,\n
       and between them, the maps added earlier have a lower precedence\n
       than those added later, unless the <code>bottom</code> argument\n
-      was passed, in which case they end up below other keymaps added\n
+      was passed, in which case they end up below other key maps added\n
       with this method.</dd>\n
       <dt id="removeKeyMap"><code><strong>cm.removeKeyMap</strong>(map: object)</code></dt>\n
       <dd>Disable a keymap added\n
       with <a href="#addKeyMap"><code>addKeyMap</code></a>. Either\n
-      pass in the keymap object itself, or a string, which will be\n
+      pass in the key map object itself, or a string, which will be\n
       compared against the <code>name</code> property of the active\n
-      keymaps.</dd>\n
+      key maps.</dd>\n
 \n
       <dt id="addOverlay"><code><strong>cm.addOverlay</strong>(mode: string|object, ?options: object)</code></dt>\n
       <dd>Enable a highlighting overlay. This is a stateless mini-mode\n
@@ -1202,6 +1512,11 @@
       <dd>Undo one edit (if any undo events are stored).</dd>\n
       <dt id="redo"><code><strong>doc.redo</strong>()</code></dt>\n
       <dd>Redo one undone edit.</dd>\n
+\n
+      <dt id="undoSelection"><code><strong>doc.undoSelection</strong>()</code></dt>\n
+      <dd>Undo one edit or selection change.</dd>\n
+      <dt id="redoSelection"><code><strong>doc.redoSelection</strong>()</code></dt>\n
+      <dd>Redo one undone edit or selection change.</dd>\n
 \n
       <dt id="historySize"><code><strong>doc.historySize</strong>() 芒聠聮 {undo: integer, redo: integer}</code></dt>\n
       <dd>Returns an object with <code>{undo, redo}</code> properties,\n
@@ -1288,6 +1603,8 @@
         is part of the marker.</dd>\n
         <dt id="mark_endStyle"><code><strong>endStyle</strong>: string</code></dt><dd>Equivalent\n
         to <code>startStyle</code>, but for the rightmost span.</dd>\n
+        <dt id="mark_css"><code><strong>css</strong>: string</code></dt>\n
+        <dd>A string of CSS to be applied to the covered text. For example <code>"color: #fe3"</code>.</dd>\n
         <dt id="mark_title"><code><strong>title</strong>:\n
         string</code></dt><dd>When given, will give the nodes created\n
         for this span a HTML <code>title</code> attribute with the\n
@@ -1329,6 +1646,9 @@
         when the cursor is on top of the bookmark will end up to the\n
         right of the bookmark. Set this option to true to make it go\n
         to the left instead.</dd>\n
+        <dt><code><strong>shared</strong>: boolean</code></dt><dd>See\n
+        the corresponding <a href="#mark_shared">option</a>\n
+        to <code>markText</code>.</dd>\n
       </dl></dd>\n
 \n
       <dt id="findMarks"><code><strong>doc.findMarks</strong>(from: {line, ch}, to: {line, ch}) 芒聠聮 array&lt;TextMarker&gt;</code></dt>\n
@@ -1357,18 +1677,19 @@
       <dd>Remove all gutter markers in\n
       the <a href="#option_gutters">gutter</a> with the given ID.</dd>\n
 \n
-      <dt id="addLineClass"><code><strong>cm.addLineClass</strong>(line: integer|LineHandle, where: string, class: string) 芒聠聮 LineHandle</code></dt>\n
+      <dt id="addLineClass"><code><strong>doc.addLineClass</strong>(line: integer|LineHandle, where: string, class: string) 芒聠聮 LineHandle</code></dt>\n
       <dd>Set a CSS class name for the given line. <code>line</code>\n
       can be a number or a line handle. <code>where</code> determines\n
       to which element this class should be applied, can can be one\n
       of <code>"text"</code> (the text element, which lies in front of\n
       the selection), <code>"background"</code> (a background element\n
-      that will be behind the selection), or <code>"wrap"</code> (the\n
-      wrapper node that wraps all of the line\'s elements, including\n
-      gutter elements). <code>class</code> should be the name of the\n
-      class to apply.</dd>\n
+      that will be behind the selection), <code>"gutter"</code> (the\n
+      line\'s gutter space), or <code>"wrap"</code> (the wrapper node\n
+      that wraps all of the line\'s elements, including gutter\n
+      elements). <code>class</code> should be the name of the class to\n
+      apply.</dd>\n
 \n
-      <dt id="removeLineClass"><code><strong>cm.removeLineClass</strong>(line: integer|LineHandle, where: string, class: string) 芒聠聮 LineHandle</code></dt>\n
+      <dt id="removeLineClass"><code><strong>doc.removeLineClass</strong>(line: integer|LineHandle, where: string, class: string) 芒聠聮 LineHandle</code></dt>\n
       <dd>Remove a CSS class from a line. <code>line</code> can be a\n
       line handle or number. <code>where</code> should be one\n
       of <code>"text"</code>, <code>"background"</code>,\n
@@ -1415,9 +1736,6 @@
           <dt><code><strong>above</strong>: boolean</code></dt>\n
           <dd>Causes the widget to be placed above instead of below\n
           the text of the line.</dd>\n
-          <dt><code><strong>showIfHidden</strong>: boolean</code></dt>\n
-          <dd>When true, will cause the widget to be rendered even if\n
-          the line it is associated with is hidden.</dd>\n
           <dt><code><strong>handleMouseEvents</strong>: boolean</code></dt>\n
           <dd>Determines whether the editor will capture mouse and\n
           drag events occurring in this widget. Default is false芒聙聰the\n
@@ -1575,6 +1893,13 @@
       not specified, the token will use cached state information, which will be faster but might not be accurate if\n
       edits were recently made and highlighting has not yet completed.\n
       </dd>\n
+\n
+      <dt id="getLineTokens"><code><strong>cm.getLineTokens</strong>(line: integer, ?precise: boolean) 芒聠聮 array&lt;{start, end, string, type, state}&gt;</code></dt>\n
+      <dd>This is similar\n
+      to <a href="#getTokenAt"><code>getTokenAt</code></a>, but\n
+      collects all tokens for a given line into an array. It is much\n
+      cheaper than repeatedly calling <code>getTokenAt</code>, which\n
+      re-parses the part of the line before the token for every call.</dd>\n
 \n
       <dt id="getTokenTypeAt"><code><strong>cm.getTokenTypeAt</strong>(pos: {line, ch}) 芒聠聮 string</code></dt>\n
       <dd>This is a (much) cheaper version\n
@@ -1791,7 +2116,7 @@
 </section>\n
 \n
 <section id=addons>\n
-    <h2>Addons</h2>\n
+    <h2 id="addons">Addons</h2>\n
 \n
     <p>The <code>addon</code> directory in the distribution contains a\n
     number of reusable components that implement extra editor\n
@@ -1803,14 +2128,43 @@
     <dl>\n
       <dt id="addon_dialog"><a href="../addon/dialog/dialog.js"><code>dialog/dialog.js</code></a></dt>\n
       <dd>Provides a very simple way to query users for text input.\n
-      Adds an <strong><code>openDialog</code></strong> method to\n
-      CodeMirror instances, which can be called with an HTML fragment\n
-      or a detached DOM node that provides the prompt (should include\n
-      an <code>input</code> tag), and a callback function that is called\n
-      when text has been entered. Also adds\n
-      an <strong><code>openNotification</code></strong> function that\n
-      simply shows an HTML fragment as a notification. Depends\n
-      on <code>addon/dialog/dialog.css</code>.</dd>\n
+      Adds the <strong><code>openDialog(template, callback, options) 芒聠聮\n
+      closeFunction</code></strong> method to CodeMirror instances,\n
+      which can be called with an HTML fragment or a detached DOM\n
+      node that provides the prompt (should include an <code>input</code>\n
+      or <code>button</code> tag), and a callback function that is called\n
+      when the user presses enter. It returns a function <code>closeFunction</code>\n
+      which, if called, will close the dialog immediately.\n
+      <strong><code>openDialog</code></strong> takes the following options:\n
+        <dl>\n
+          <dt><code><strong>closeOnEnter</strong></code>:</dt>\n
+          <dd>If true, the dialog will be closed when the user presses\n
+          enter in the input. Defaults to <code>true</code>.</dd>\n
+          <dt><code><strong>onKeyDown</strong></code>:</dt>\n
+          <dd>An event handler of the signature <code>(event, value, closeFunction)</code>\n
+          that will be called whenever <code>keydown</code> fires in the\n
+          dialog\'s input. If your callback returns <code>true</code>,\n
+          the dialog will not do any further processing of the event.</dd>\n
+          <dt><code><strong>onKeyUp</strong></code>:</dt>\n
+          <dd>Same as <code>onKeyDown</code> but for the\n
+          <code>keyup</code> event.</dd>\n
+          <dt><code><strong>onInput</strong></code>:</dt>\n
+          <dd>Same as <code>onKeyDown</code> but for the\n
+          <code>input</code> event.</dd>\n
+          <dt><code><strong>onClose</strong></code>:</dt>\n
+          <dd>A callback of the signature <code>(dialogInstance)</code>\n
+          that will be called after the dialog has been closed and\n
+          removed from the DOM. No return value.</dd>\n
+        </dl>\n
+\n
+      <p>Also adds an <strong><code>openNotification(template, options) 芒聠聮\n
+      closeFunction</code></strong> function that simply shows an HTML\n
+      fragment as a notification at the top of the editor. It takes a\n
+      single option: <code>duration</code>, the amount of time after\n
+      which the notification will be automatically closed. If <code>\n
+      duration</code> is zero, the dialog will not be closed automatically.</p>\n
+\n
+      <p>Depends on <code>addon/dialog/dialog.css</code>.</p></dd>\n
 \n
       <dt id="addon_searchcursor"><a href="../addon/search/searchcursor.js"><code>search/searchcursor.js</code></a></dt>\n
       <dd>Adds the <code>getSearchCursor(query, start, caseFold) 芒聠聮\n
@@ -1850,6 +2204,28 @@
       on <code>searchcursor.js</code>, and will make use\n
       of <a href="#addon_dialog"><code>openDialog</code></a> when\n
       available to make prompting for search queries less ugly.</dd>\n
+\n
+      <dt id="addon_matchesonscrollbar"><a href="../addon/search/matchesonscrollbar.js"><code>search/matchesonscrollbar.js</code></a></dt>\n
+      <dd>Adds a <code>showMatchesOnScrollbar</code> method to editor\n
+      instances, which should be given a query (string or regular\n
+      expression), optionally a case-fold flag (only applicable for\n
+      strings), and optionally a class name (defaults\n
+      to <code>CodeMirror-search-match</code>) as arguments. When\n
+      called, matches of the given query will be displayed on the\n
+      editor\'s vertical scrollbar. The method returns an object with\n
+      a <code>clear</code> method that can be called to remove the\n
+      matches. Depends on\n
+      the <a href="#addon_annotatescrollbar"><code>annotatescrollbar</code></a>\n
+      addon, and\n
+      the <a href="../addon/search/matchesonscrollbar.css"><code>matchesonscrollbar.css</code></a>\n
+      file provides a default (transparent yellowish) definition of\n
+      the CSS class applied to the matches. Note that the matches are\n
+      only perfectly aligned if your scrollbar does not have buttons\n
+      at the top and bottom. You can use\n
+      the <a href="#addon_simplescrollbars"><code>simplescrollbar</code></a>\n
+      addon to make sure of this. If this addon is loaded,\n
+      the <a href="#addon_search"><code>search</code></a> addon will\n
+      automatically use it.</dd>\n
 \n
       <dt id="addon_matchbrackets"><a href="../addon/edit/matchbrackets.js"><code>edit/matchbrackets.js</code></a></dt>\n
       <dd>Defines an option <code>matchBrackets</code> which, when set\n
@@ -1927,8 +2303,9 @@
         <dd>Override the <a href="#mode_comment">comment string\n
         properties</a> of the mode with custom comment strings.</dd>\n
         <dt><code><strong>padding</strong>: string</code></dt>\n
-        <dd>A string that will be inserted after opening and before\n
-        closing comment markers. Defaults to a single space.</dd>\n
+        <dd>A string that will be inserted after opening and leading\n
+        markers, and before closing comment markers. Defaults to a\n
+        single space.</dd>\n
         <dt><code><strong>commentBlankLines</strong>: boolean</code></dt>\n
         <dd>Whether, when adding line comments, to also comment lines\n
         that contain only whitespace.</dd>\n
@@ -2024,6 +2401,8 @@
         given, <a href="#helper_fold_auto"><code>CodeMirror.fold.auto</code></a>\n
         will be used as default.</dd>\n
       </dl>\n
+      The <code>foldOptions</code> editor option can be set to an\n
+      object to provide an editor-wide default configuration.\n
       Demo <a href="../demo/folding.html">here</a>.</dd>\n
 \n
       <dt id="addon_runmode"><a href="../addon/runmode/runmode.js"><code>runmode/runmode.js</code></a></dt>\n
@@ -2085,18 +2464,18 @@
 \n
       <dt id="addon_show-hint"><a href="../addon/hint/show-hint.js"><code>hint/show-hint.js</code></a></dt>\n
       <dd>Provides a framework for showing autocompletion hints.\n
-      Defines <code>CodeMirror.showHint</code>, which takes a\n
-      CodeMirror instance, a hinting function, and optionally an\n
+      Defines <code>editor.showHint</code>, which takes an optional\n
       options object, and pops up a widget that allows the user to\n
-      select a completion. Hinting functions are function that take an\n
-      editor instance and an optional options object, and return\n
+      select a completion. Finding hints is done with a hinting\n
+      functions (the <code>hint</code> option), which is a function\n
+      that take an editor instance and options object, and return\n
       a <code>{list, from, to}</code> object, where <code>list</code>\n
       is an array of strings or objects (the completions),\n
       and <code>from</code> and <code>to</code> give the start and end\n
       of the token that is being completed as <code>{line, ch}</code>\n
       objects.</dd>\n
       <dd>If no hinting function is given, the addon will\n
-      use <code>CodeMirror.hint.auto</code>, with\n
+      use <code>CodeMirror.hint.auto</code>, which\n
       calls <a href="#getHelpers"><code>getHelpers</code></a> with\n
       the <code>"hint"</code> type to find applicable hinting\n
       functions, and tries them one by one. If that fails, it looks\n
@@ -2104,9 +2483,8 @@
       completable words for the mode, and\n
       uses <code>CodeMirror.hint.fromList</code> to complete from\n
       those.</dd>\n
-      <dd>When completions\n
-      aren\'t simple strings, they should be objects with the following\n
-      properties:\n
+      <dd>When completions aren\'t simple strings, they should be\n
+      objects with the following properties:\n
       <dl>\n
         <dt><code><strong>text</strong>: string</code></dt>\n
         <dd>The completion text. This is the only required\n
@@ -2133,11 +2511,13 @@
       will also be passed along to the hinting function, which may\n
       understand additional options):\n
       <dl>\n
-        <dt><code><strong>async</strong>: boolean</code></dt>\n
-        <dd>When set to true, the hinting function\'s signature should\n
-        be <code>(cm, callback, ?options)</code>, and the completion\n
-        interface will only be popped up when the hinting function\n
-        calls the callback, passing it the object holding the\n
+        <dt><code><strong>hint</strong>: function</code></dt>\n
+        <dd>A hinting function, as specified above. It is possible to\n
+        set the <code>async</code> property on a hinting function to\n
+        true, in which case it will be called with\n
+        arguments <code>(cm, callback, ?options)</code>, and the\n
+        completion interface will only be popped up when the hinting\n
+        function calls the callback, passing it the object holding the\n
         completions.</dd>\n
         <dt><code><strong>completeSingle</strong>: boolean</code></dt>\n
         <dd>Determines whether, when only a single completion is\n
@@ -2150,7 +2530,7 @@
         <dd>When enabled (which is the default), the pop-up will close\n
         when the editor is unfocused.</dd>\n
         <dt><code><strong>customKeys</strong>: keymap</code></dt>\n
-        <dd>Allows you to provide a custom keymap of keys to be active\n
+        <dd>Allows you to provide a custom key map of keys to be active\n
         when the pop-up is active. The handlers will be called with an\n
         extra argument, a handle to the completion menu, which\n
         has <code>moveFocus(n)</code>, <code>setFocus(n)</code>, <code>pick()</code>,\n
@@ -2175,10 +2555,13 @@
         <dd>Fired when a completion is selected. Passed the completion\n
         value (string or object) and the DOM node that represents it\n
         in the menu.</dd>\n
+        <dt><code><strong>"pick"</strong> (completion)</code></dt>\n
+        <dd>Fired when a completion is picked. Passed the completion value\n
+        (string or object).</dd>\n
         <dt><code><strong>"close"</strong> ()</code></dt>\n
         <dd>Fired when the completion is finished.</dd>\n
       </dl>\n
-      This addon depends styles\n
+      This addon depends on styles\n
       from <code>addon/hint/show-hint.css</code>. Check\n
       out <a href="../demo/complete.html">the demo</a> for an\n
       example.</dd>\n
@@ -2222,10 +2605,6 @@
       <dt id="addon_css-hint"><a href="../addon/hint/css-hint.js"><code>hint/css-hint.js</code></a></dt>\n
       <dd>A hinting function for CSS, SCSS, or LESS code.\n
       Defines <code>CodeMirror.hint.css</code>.</dd>\n
-\n
-      <dt id="addon_python-hint"><a href="../addon/hint/python-hint.js"><code>hint/python-hint.js</code></a></dt>\n
-      <dd>A very simple hinting function for Python code.\n
-      Defines <code>CodeMirror.hint.python</code>.</dd>\n
 \n
       <dt id="addon_anyword-hint"><a href="../addon/hint/anyword-hint.js"><code>hint/anyword-hint.js</code></a></dt>\n
       <dd>A very simple hinting function\n
@@ -2237,10 +2616,11 @@
       should scan when completing (defaults to 500).</dd>\n
 \n
       <dt id="addon_sql-hint"><a href="../addon/hint/sql-hint.js"><code>hint/sql-hint.js</code></a></dt>\n
-      <dd>A simple SQL hinter. Defines <code>CodeMirror.hint.sql</code>.</dd>\n
-\n
-      <dt id="addon_pig-hint"><a href="../addon/hint/pig-hint.js"><code>hint/pig-hint.js</code></a></dt>\n
-      <dd>A simple hinter for <a href="../mode/pig/index.html">Pig Latin</a>. Defines <code>CodeMirror.hint.pig</code>.</dd>\n
+      <dd>A simple SQL hinter. Defines <code>CodeMirror.hint.sql</code>.\n
+      Takes two optional options, <code>tables</code>, a object with\n
+      table names as keys and array of respective column names as values,\n
+      and <code>defaultTable</code>, a string corresponding to a\n
+      table name in <code>tables</code> for autocompletion.</dd>\n
 \n
       <dt id="addon_match-highlighter"><a href="../addon/search/match-highlighter.js"><code>search/match-highlighter.js</code></a></dt>\n
       <dd>Adds a <code>highlightSelectionMatches</code> option that\n
@@ -2297,6 +2677,26 @@
       which will ensure the given mode is loaded and cause the given\n
       editor instance to refresh its mode when the loading\n
       succeeded. See the <a href="../demo/loadmode.html">demo</a>.</dd>\n
+\n
+      <dt id="addon_meta"><a href="../mode/meta.js"><code>mode/meta.js</code></a></dt>\n
+      <dd>Provides meta-information about all the modes in the\n
+      distribution in a single file.\n
+      Defines <code>CodeMirror.modeInfo</code>, an array of objects\n
+      with <code>{name, mime, mode}</code> properties,\n
+      where <code>name</code> is the human-readable\n
+      name, <code>mime</code> the MIME type, and <code>mode</code> the\n
+      name of the mode file that defines this MIME. There are optional\n
+      properties <code>mimes</code>, which holds an array of MIME\n
+      types for modes with multiple MIMEs associated,\n
+      and <code>ext</code>, which holds an array of file extensions\n
+      associated with this mode. Three convenience\n
+      functions, <code>CodeMirror.findModeByMIME</code>,\n
+      and <code>CodeMirror.findModeByExtension</code>,\n
+      and <code>CodeMirror.findModeByName</code> are provided, which\n
+      return such an object given a MIME or extension string. Note\n
+      that, for historical reasons, this file resides in the\n
+      top-level <code>mode</code> directory, not\n
+      under <code>addon</code>. <a href="../demo/loadmode.html">Demo</a>.</dd>\n
 \n
       <dt id="addon_continuecomment"><a href="../addon/comment/continuecomment.js"><code>comment/continuecomment.js</code></a></dt>\n
       <dd>Adds a <code>continueComments</code> option, which sets whether the\n
@@ -2321,16 +2721,52 @@
       taking up the whole browser window). Depends\n
       on <a href="../addon/display/fullscreen.css"><code>fullscreen.css</code></a>. <a href="../demo/fullscreen.html">Demo\n
       here</a>.</dd>\n
+\n
+      <dt id="addon_simplescrollbars"><a href="../addon/scroll/simplescrollbars.js"><code>scroll/simplescrollbars.js</code></a></dt>\n
+      <dd>Defines two additional scrollbar\n
+      models, <code>"simple"</code> and <code>"overlay"</code>\n
+      (see <a href="../demo/simplescrollbars.html">demo</a>) that can\n
+      be selected with\n
+      the <a href="#option_scrollbarStyle"><code>scrollbarStyle</code></a>\n
+      option. Depends\n
+      on <a href="../addon/scroll/simplescrollbars.css"><code>simplescrollbars.css</code></a>,\n
+      which can be further overridden to style your own\n
+      scrollbars.</dd>\n
+\n
+      <dt id="addon_annotatescrollbar"><a href="../addon/scroll/annotatescrollbar.js"><code>scroll/annotatescrollbar.js</code></a></dt>\n
+      <dd>Provides functionality for showing markers on the scrollbar\n
+      to call out certain parts of the document. Adds a\n
+      method <code>annotateScrollbar</code> to editor instances that\n
+      can be called, with a CSS class name as argument, to create a\n
+      set of annotations. The method returns an object\n
+      whose <code>update</code> method can be called with an array\n
+      of <code>{from: Pos, to: Pos}</code> objects marking the ranges\n
+      to be higlighed. To detach the annotations, call the\n
+      object\'s <code>clear</code> method.</dd>\n
 \n
       <dt id="addon_rulers"><a href="../addon/display/rulers.js"><code>display/rulers.js</code></a></dt>\n
       <dd>Adds a <code>rulers</code> option, which can be used to show\n
       one or more vertical rulers in the editor. The option, if\n
-      defined, should be given an array of <code>{column,\n
-      className}</code> objects or numbers. The ruler will be\n
-      displayed at the column indicated by the number or\n
-      the <code>column</code> property. The <code>className</code>\n
-      property can be used to assign a custom style to a\n
-      ruler. <a href="../demo/rulers.html">Demo here</a>.</dd>\n
+      defined, should be given an array of <code>{column [, className,\n
+      color, lineStyle, width]}</code> objects or numbers (wich\n
+      indicate a column). The ruler will be displayed at the column\n
+      indicated by the number or the <code>column</code> property.\n
+      The <code>className</code> property can be used to assign a\n
+      custom style to a ruler. <a href="../demo/rulers.html">Demo\n
+      here</a>.</dd>\n
+\n
+      <dt id="addon_panel"><a href="../addon/display/panel.js"><code>display/panel.js</code></a></dt>\n
+      <dd>Defines an <code>addPanel</code> method for CodeMirror\n
+      instances, which places a DOM node above or below an editor, and\n
+      shrinks the editor to make room for the node. The method takes\n
+      as first argument as DOM node, and as second an optional options\n
+      object. By default, the panel ends up above the editor. This can\n
+      be changed by passing a <code>position</code> option with the\n
+      value <code>"bottom"</code>. The object returned by this method\n
+      has a <code>clear</code> method that is used to remove the\n
+      panel, and a <code>changed</code> method that can be used to\n
+      notify the addon when the size of the panel\'s DOM node has\n
+      changed.</dd>\n
 \n
       <dt id="addon_hardwrap"><a href="../addon/wrap/hardwrap.js"><code>wrap/hardwrap.js</code></a></dt>\n
       <dd>Addon to perform hard line wrapping/breaking for paragraphs\n
@@ -2371,13 +2807,37 @@
       constructor takes arguments similar to\n
       the <a href="#CodeMirror"><code>CodeMirror</code></a>\n
       constructor, first a node to append the interface to, and then\n
-      an options object. Two extra optional options are\n
-      recognized, <code>origLeft</code> and <code>origRight</code>,\n
-      which may be strings that provide original versions of the\n
-      document, which will be shown to the left and right of the\n
-      editor in non-editable CodeMirror instances. The merge interface\n
-      will highlight changes between the editable document and the\n
-      original(s) (<a href="../demo/merge.html">demo</a>).</dd>\n
+      an options object. Options are passed through to the editors\n
+      inside the view. These extra options are recognized:\n
+        <dl>\n
+          <dt><code><strong>origLeft</strong></code> and <code><strong>origRight</strong>: string</code></dt>\n
+          <dd>If given these provide original versions of the\n
+          document, which will be shown to the left and right of the\n
+          editor in non-editable CodeMirror instances. The merge\n
+          interface will highlight changes between the editable\n
+          document and the original(s). To create a 2-way (as opposed\n
+          to 3-way) merge view, provide only one of them.</dd>\n
+          <dt><code><strong>revertButtons</strong>: boolean</code></dt>\n
+          <dd>Determines whether buttons that allow the user to revert\n
+          changes are shown. Defaults to true.</dd>\n
+          <dt><code><strong>connect</strong>: string</code></dt>\n
+          <dd>Sets the style used to connect changed chunks of code.\n
+          By default, connectors are drawn. When this is set\n
+          to <code>"align"</code>, the smaller chunk is padded to\n
+          align with the bigger chunk instead.</dd>\n
+          <dt><code><strong>collapseIdentical</strong>: boolean|number</code></dt>\n
+          <dd>When true (default is false), stretches of unchanged\n
+          text will be collapsed. When a number is given, this\n
+          indicates the amount of lines to leave visible around such\n
+          stretches (which defaults to 2).</dd>\n
+          <dt><code><strong>allowEditingOriginals</strong>: boolean</code></dt>\n
+          <dd>Determines whether the original editor allows editing.\n
+          Defaults to false.</dd>\n
+          <dt><code><strong>showDifferences</strong>: boolean</code></dt>\n
+          <dd>When true (the default), changed pieces of text are\n
+          highlighted.</dd>\n
+        </dl>\n
+        <a href="../demo/merge.html">Demo here</a>.</dd>\n
 \n
       <dt id="addon_tern"><a href="../addon/tern/tern.js"><code>tern/tern.js</code></a></dt>\n
       <dd>Provides integration with\n
@@ -2401,6 +2861,11 @@
     language芒聙聰a function that takes a character stream as input,\n
     advances it past a token, and returns a style for that token. More\n
     advanced modes can also handle indentation for the language.</p>\n
+\n
+    <p>This section describes the low-level mode interface. Many modes\n
+    are written directly against this, since it offers a lot of\n
+    control, but for a quick mode definition, you might want to use\n
+    the <a href="../demo/simplemode.html">simple mode addon</a>.</p>\n
 \n
     <p id="defineMode">The mode script should\n
     call <code><strong>CodeMirror.defineMode</strong></code> to\n
@@ -2574,12 +3039,20 @@
     continued lines in a block comment). All of these are\n
     optional.</p>\n
 \n
-    <p id="electricChars">Finally, a mode may define\n
-    an <code>electricChars</code> property, which should hold a string\n
-    containing all the characters that should trigger the behaviour\n
-    described for\n
+    <p id="electricChars">Finally, a mode may define either\n
+    an <code>electricChars</code> or an <code>electricInput</code>\n
+    property, which are used to automatically reindent the line when\n
+    certain patterns are typed and\n
     the <a href="#option_electricChars"><code>electricChars</code></a>\n
-    option.</p>\n
+    option is enabled. <code>electricChars</code> may be a string, and\n
+    will trigger a reindent whenever one of the characters in that\n
+    string are typed. Often, it is more appropriate to\n
+    use <code>electricInput</code>, which should hold a regular\n
+    expression, and will trigger indentation when the part of the\n
+    line <em>before</em> the cursor matches the expression. It should\n
+    usually end with a <code>$</code> character, so that it only\n
+    matches when the indentation-changing pattern was just typed, not when something was\n
+    typed after the pattern.</p>\n
 \n
     <p>So, to summarize, a mode <em>must</em> provide\n
     a <code>token</code> method, and it <em>may</em>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/realworld.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/realworld.html.xml
index 2545dc05794392d3f256efa438c0ef0b9e60692e..3bcf10d55f8ccd46c5011a162975e2747802ca24 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/realworld.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/realworld.html.xml
@@ -43,12 +43,12 @@
 <link rel=stylesheet href="docs.css">\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Real-world uses</a>\n
@@ -59,20 +59,25 @@
 \n
 <h2>CodeMirror real-world uses</h2>\n
 \n
-    <p><a href="mailto:marijnh@gmail.com">Contact me</a> if you\'d like\n
-    your project to be added to this list.</p>\n
+    <p>Create a <a href="https://github.com/codemirror/codemirror">pull\n
+    request</a> or <a href="mailto:marijnh@gmail.com">email me</a> if\n
+    you\'d like your project to be added to this list.</p>\n
 \n
     <ul>\n
       <li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>\n
       <li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li>\n
+      <li><a href="http://apachegui.ca/">Apache GUI</a></li>\n
       <li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li>\n
+      <li><a href="https://chrome.google.com/webstore/detail/better-text-viewer/lcaidopdffhfemoefoaadecppnjdknkc">Better Text Viewer</a> (plain text reader app for Chrome)</li>\n
       <li><a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a> (code hosting)</li>\n
       <li><a href="http://buzz.blogger.com/2013/04/improvements-to-blogger-template-html.html">Blogger\'s template editor</a></li>\n
       <li><a href="http://bluegriffon.org/">BlueGriffon</a> (HTML editor)</li>\n
       <li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li>\n
       <li><a href="https://developers.google.com/chrome-developer-tools/">Chrome DevTools</a></li>\n
       <li><a href="http://clickhelp.co/">ClickHelp</a> (technical writing tool)</li>\n
+      <li><a href="http://codeworld.info/">CodeWorld</a> (Haskell playground)</li>\n
       <li><a href="http://complete-ly.appspot.com/playground/code.playground.html">Complete.ly playground</a></li>\n
+      <li><a href="https://codeanywhere.com/">Codeanywhere</a> (multi-platform cloud editor)</li>\n
       <li><a href="http://drupal.org/project/cpn">Code per Node</a> (Drupal module)</li>\n
       <li><a href="http://www.codebugapp.com/">Codebug</a> (PHP Xdebug front-end)</li>\n
       <li><a href="https://github.com/angelozerr/CodeMirror-Eclipse">CodeMirror Eclipse</a> (embed CM in Eclipse)</li>\n
@@ -80,6 +85,7 @@
       <li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li>\n
       <li><a href="http://www.crunchzilla.com/code-monster">Code Monster</a> & <a href="http://www.crunchzilla.com/code-maven">Code Maven</a> (learning environment)</li>\n
       <li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li>\n
+      <li><a href="https://coderpad.io/">Coderpad</a> (interviewing tool)</li>\n
       <li><a href="http://sasstwo.codeschool.com/levels/1/challenges/1">Code School</a> (online tech learning environment)</li>\n
       <li><a href="http://code-snippets.bungeshea.com/">Code Snippets</a> (WordPress snippet management plugin)</li>\n
       <li><a href="http://antonmi.github.io/code_together/">Code together</a> (collaborative editing)</li>\n
@@ -90,35 +96,46 @@
       <li><a href="http://www.communitycodecamp.com/">Community Code Camp</a> (code snippet sharing)</li>\n
       <li><a href="http://www.compilejava.net/">compilejava.net</a> (online Java sandbox)</li>\n
       <li><a href="http://www.ckwnc.com/">CKWNC</a> (UML editor)</li>\n
+      <li><a href="http://www.crossui.com/">CrossUI</a> (cross-platform UI builder)</li>\n
+      <li><a href="http://rsnous.com/cruncher/">Cruncher</a> (notepad with calculation features)</li>\n
       <li><a href="http://www.crudzilla.com/">Crudzilla</a> (self-hosted web IDE)</li>\n
       <li><a href="http://cssdeck.com/">CSSDeck</a> (CSS showcase)</li>\n
       <li><a href="http://ireneros.com/deck/deck.js-codemirror/introduction/#textarea-code">Deck.js integration</a> (slides with editors)</li>\n
       <li><a href="http://www.dbninja.com">DbNinja</a> (MySQL access interface)</li>\n
       <li><a href="https://chat.echoplex.us/">Echoplexus</a> (chat and collaborative coding)</li>\n
+      <li><a href="http://www.ecsspert.com/">eCSSpert</a> (CSS demos and experiments)</li>\n
       <li><a href="http://elm-lang.org/Examples.elm">Elm language examples</a></li>\n
       <li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</li>\n
       <li><a href="http://emmet.io">Emmet</a> (fast XML editing)</li>\n
+      <li><a href="https://github.com/espruino/EspruinoWebIDE">Espruino Web IDE</a> (Chrome App for writing code on Espruino devices)</li>\n
       <li><a href="http://www.fastfig.com/">Fastfig</a> (online computation/math tool)</li>\n
       <li><a href="https://metacpan.org/module/Farabi">Farabi</a> (modern Perl IDE)</li>\n
       <li><a href="http://blog.pamelafox.org/2012/02/interactive-html5-slides-with-fathomjs.html">FathomJS integration</a> (slides with editors, again)</li>\n
+      <li><a href="https://phantomus.com/">Phantomus</a> (blogging platform)</li>\n
       <li><a href="http://fiddlesalad.com/">Fiddle Salad</a> (web development environment)</li>\n
+      <li><a href="https://github.com/simogeo/Filemanager">Filemanager</a></li>\n
       <li><a href="https://hacks.mozilla.org/2013/11/firefox-developer-tools-episode-27-edit-as-html-codemirror-more/">Firefox Developer Tools</a></li>\n
       <li><a href="http://www.firepad.io">Firepad</a> (collaborative text editor)</li>\n
-      <li><a href="https://code.google.com/p/gerrit/">Gerrit</a>\'s diff view</a></li>\n
+      <li><a href="https://code.google.com/p/gerrit/">Gerrit</a>\'s diff view</li>\n
+      <li><a href="https://github.com/maks/git-crx">Git Crx</a> (Chrome App for browsing local git repos)</li>\n
       <li><a href="http://tour.golang.org">Go language tour</a></li>\n
       <li><a href="https://github.com/github/android">GitHub\'s Android app</a></li>\n
       <li><a href="https://script.google.com/">Google Apps Script</a></li>\n
       <li><a href="http://web.uvic.ca/~siefkenj/graphit/graphit.html">Graphit</a> (function graphing)</li>\n
       <li><a href="http://www.handcraft.com/">Handcraft</a> (HTML prototyping)</li>\n
+      <li><a href="http://hawkee.com/">Hawkee</a></li>\n
       <li><a href="http://try.haxe.org">Haxe</a> (Haxe Playground) </li>\n
       <li><a href="http://haxpad.com/">HaxPad</a> (editor for Win RT)</li>\n
       <li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li>\n
       <li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>\n
+      <li><a href="http://ipython.org/">IPython</a> (interactive computing shell)</li>\n
       <li><a href="http://i-mos.org/imos/">i-MOS</a> (modeling and simulation platform)</li>\n
       <li><a href="http://www.janvas.com/">Janvas</a> (vector graphics editor)</li>\n
       <li><a href="http://extensions.joomla.org/extensions/edition/editors/8723">Joomla plugin</a></li>\n
       <li><a href="http://jqfundamentals.com/">jQuery fundamentals</a> (interactive tutorial)</li>\n
       <li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>\n
+      <li><a href="http://tool.jser.com/preprocessor">JSER preprocessor</a></li>\n
+      <li><a href="https://github.com/kucherenko/jscpd">jscpd</a> (code duplication detector)</li>\n
       <li><a href="http://jsfiddle.com">jsfiddle.com</a> (another JS playground)</li>\n
       <li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>\n
       <li><a href="http://jumpseller.com/">Jumpseller</a> (online store builder)</li>\n
@@ -131,6 +148,7 @@
       <li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>\n
       <li><a href="http://www.iunbug.com/mihtool">MIHTool</a> (iOS web-app debugging tool)</li>\n
       <li><a href="http://mongo-mapreduce-webbrowser.opensagres.cloudbees.net/">Mongo MapReduce WebBrowser</a></li>\n
+      <li><a href="http://montagestudio.com/">Montage Studio</a> (web app creator suite)</li>\n
       <li><a href="http://mvcplayground.apphb.com/">MVC Playground</a></li>\n
       <li><a href="https://www.my2ndgeneration.com/">My2ndGeneration</a> (social coding)</li>\n
       <li><a href="http://www.navigatecms.com">Navigate CMS</a></li>\n
@@ -142,6 +160,7 @@
       <li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>\n
       <li><a href="http://prinbit.com/">PrinBit</a> (collaborative coding tool)</li>\n
       <li><a href="http://prose.io/">Prose.io</a> (github content editor)</li>\n
+      <li><a href="https://pypi.python.org/pypi/PubliForge/">PubliForge</a> (online publishing system)</li>\n
       <li><a href="http://www.puzzlescript.net/">Puzzlescript</a> (puzzle game engine)</li>\n
       <li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>\n
       <li><a href="http://qyapp.com">QiYun web app platform</a></li>\n
@@ -149,14 +168,22 @@
       <li><a href="http://www.quivive-file-manager.com">Quivive File Manager</a></li>\n
       <li><a href="http://rascalmicro.com/docs/basic-tutorial-getting-started.html">Rascal</a> (tiny computer)</li>\n
       <li><a href="https://www.realtime.io/">RealTime.io</a> (Internet-of-Things infrastructure)</li>\n
+      <li><a href="https://cloud.sagemath.com/">SageMathCloud</a> (interactive mathematical software environment)</li>\n
+      <li><a href="https://chrome.google.com/webstore/detail/servephp/mnpikomdchjhkhbhmbboehfdjkobbfpo">ServePHP</a> (PHP code testing in Chrome dev tools)</li>\n
       <li><a href="https://www.shadertoy.com/">Shadertoy</a> (shader sharing)</li>\n
       <li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>\n
       <li><a href="http://www.skulpt.org/">Skulpt</a> (in-browser Python environment)</li>\n
+      <li><a href="http://snaptomato.appspot.com/editor.html">Snap Tomato</a> (HTML editing/testing page)</li>\n
       <li><a href="http://snippets.pro/">Snippets.pro</a> (code snippet sharing)</li>\n
       <li><a href="http://www.solidshops.com/">SolidShops</a> (hosted e-commerce platform)</li>\n
       <li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>\n
+      <li><a href="http://www.subte.org/page/programar-ta-te-ti-online/">SubTe</a> (AI bot programming environment)</li>\n
+      <li><a href="http://xuanji.appspot.com/isicp/">Structure and Interpretation of Computer Programs</a>, Interactive Version</li>\n
+      <li><a href="http://syframework.alwaysdata.net">SyBox</a> (PHP playground)</li>\n
+      <li><a href="http://www.tagspaces.org/">TagSpaces</a> (personal data manager)</li>\n
       <li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>\n
       <li><a href="http://www.mapbox.com/tilemill/">TileMill</a> (map design tool)</li>\n
+      <li><a href="http://doc.tiki.org/Syntax+Highlighter">Tiki</a> (wiki CMS groupware)</li>\n
       <li><a href="http://www.toolsverse.com/products/data-explorer/">Toolsverse Data Explorer</a> (database management)</li>\n
       <li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a> (augmented editing)</li>\n
       <li><a href="http://blog.englard.net/post/39608000629/codeintumblr">Tumblr code highlighting shim</a></li>\n
@@ -164,11 +191,14 @@
       <li><a href="http://uicod.com/">uiCod</a> (animation demo gallery and sharing)</li>\n
       <li><a href="http://cruise.eecs.uottawa.ca/umpleonline/">UmpleOnline</a> (model-oriented programming tool)</li>\n
       <li><a href="https://upsource.jetbrains.com/#idea/view/923f30395f2603cd9f42a32bcafd13b6c28de0ff/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java">Upsource</a> (code viewer)</li>\n
+      <li><a href="https://github.com/mgaitan/waliki">Waliki</a> (wiki engine)</li>\n
+      <li><a href="http://wamer.net/">Wamer</a> (web application builder)</li>\n
       <li><a href="https://github.com/brettz9/webappfind">webappfind</a> (windows file bindings for webapps)</li>\n
       <li><a href="http://www.webglacademy.com/">WebGL academy</a> (learning WebGL)</li>\n
       <li><a href="http://webglplayground.net/">WebGL playground</a></li>\n
       <li><a href="https://www.webkit.org/blog/2518/state-of-web-inspector/#source-code">WebKit Web inspector</a></li>\n
       <li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>\n
+      <li><a href="https://github.com/b3log/wide">Wide</a> (golang web IDE)</li>\n
       <li><a href="http://wordpress.org/extend/plugins/codemirror-for-codeeditor/">WordPress plugin</a></li>\n
       <li><a href="https://www.writelatex.com">writeLaTeX</a> (Collaborative LaTeX Editor)</li>\n
       <li><a href="http://www.xosystem.org/home/applications_websites/xosystem_website/xoside_EN.php">XOSide</a> (online editor)</li>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/releases.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/releases.html.xml
index 38512c87e3cfd6f98700912cca8c37d89c092cc3..189489565fbf1269c5b4aae7dca2f3bf7e41c16a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/releases.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/releases.html.xml
@@ -44,15 +44,16 @@
 <script src="activebookmark.js"></script>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
-    <li><a class=active data-default="true" href="#v3">Version 3.x</a>\n
+    <li><a class=active data-default="true" href="#v4">Version 4.x</a>\n
+    <li><a href="#v3">Version 3.x</a>\n
     <li><a href="#v2">Version 2.x</a>\n
     <li><a href="#v1">Version 0.x</a>\n
   </ul>\n
@@ -62,18 +63,212 @@
 \n
 <h2>Release notes and version history</h2>\n
 \n
-<section id=v3 class=first>\n
+<section id=v4 class=first>\n
+\n
+  <h2>Version 4.x</h2>\n
+\n
+  <p class="rel">9-01-2015: <a href="http://codemirror.net/codemirror-4.11.zip">Version 4.11</a>:</p>\n
+\n
+  <p class="rel-note">Unfortunately, 4.10 did not take care of the\n
+  Firefox scrolling issue entirely. This release adds two more patches\n
+  to address that.</p>\n
+\n
+  <p class="rel">29-12-2014: <a href="http://codemirror.net/codemirror-4.10.zip">Version 4.10</a>:</p>\n
+\n
+  <p class="rel-note">Emergency single-patch update to 4.9. Fixes\n
+  Firefox-specific problem where the cursor could end up behind the\n
+  horizontal scrollbar.</p>\n
+\n
+  <p class="rel">23-12-2014: <a href="http://codemirror.net/codemirror-4.9.zip">Version 4.9</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>Overhauled scroll bar handling.\n
+    Add pluggable <a href="../demo/simplescrollbars.html">scrollbar\n
+    implementations</a>.</li>\n
+    <li>Tweaked behavior for\n
+    the <a href="manual.html#addon_show-hint">completion addons</a> to\n
+    not take text after cursor into account.</li>\n
+    <li>Two new optional features in\n
+    the <a href="manual.html#addon_merge">merge addon</a>: aligning\n
+    editors, and folding unchanged text.</li>\n
+    <li>New\n
+    modes: <a href="../mode/dart/index.html">Dart</a>, <a href="../mode/ebnf/index.html">EBNF</a>, <a href="../mode/spreadsheet/index.html">spreadsheet</a>,\n
+    and <a href="../mode/soy/index.html">Soy</a>.</li>\n
+    <li>New <a href="../demo/panel.html">addon</a> to show persistent panels below/above an editor.</li>\n
+    <li>New themes: <a href="../demo/theme.html?zenburn">zenburn</a>\n
+    and <a href="../demo/theme.html?tomorrow-night-bright">tomorrow night\n
+    bright</a>.</li>\n
+    <li>Allow ctrl-click to clear existing cursors.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.8.0...4.9.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">22-11-2014: <a href="http://codemirror.net/codemirror-4.8.zip">Version 4.8</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>Built-in support for <a href="manual.html#normalizeKeyMap">multi-stroke key bindings</a>.</li>\n
+    <li>New method: <a href="manual.html#getLineTokens"><code>getLineTokens</code></a>.</li>\n
+    <li>New modes: <a href="../mode/dockerfile/index.html">dockerfile</a>, <a href="../mode/idl/index.html">IDL</a>, <a href="../mode/clike/index.html">Objective C</a> (crude).</li>\n
+    <li>Support styling of gutter backgrounds, allow <code>"gutter"</code> styles in <a href="manual.html#addLineClass"><code>addLineClass</code></a>.</li>\n
+    <li>Many improvements to the <a href="../demo/vim.html">Vim mode</a>, rewritten visual mode.</li>\n
+    <li>Improvements to modes: <a href="../mode/gfm/index.html">gfm</a> (strikethrough), <a href="../mode/sparql/index.html">SPARQL</a> (version 1.1 support), and <a href="../mode/stex/index.html">sTeX</a> (no more runaway math mode).\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.7.0...4.8.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">20-10-2014: <a href="http://codemirror.net/codemirror-4.7.zip">Version 4.7</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li><strong>Incompatible</strong>:\n
+    The <a href="../demo/lint.html">lint addon</a> now passes the\n
+    editor\'s value as first argument to asynchronous lint functions,\n
+    for consistency. The editor is still passed, as fourth\n
+    argument.</li>\n
+    <li>Improved handling of unicode identifiers in modes for\n
+    languages that support them.</li>\n
+    <li>More mode\n
+    improvements: <a href="../mode/coffeescript/index.html">CoffeeScript</a>\n
+    (indentation), <a href="../mode/verilog/index.html">Verilog</a>\n
+    (indentation), <a href="../mode/clike/index.html">Scala</a>\n
+    (indentation, triple-quoted strings),\n
+    and <a href="../mode/php/index.html">PHP</a> (interpolated\n
+    variables in heredoc strings).</li>\n
+    <li>New modes: <a href="../mode/textile/index.html">Textile</a> and <a href="../mode/tornado/index.html">Tornado templates</a>.</li>\n
+    <li>Experimental new <a href="../demo/simplemode.html">way to define modes</a>.</li>\n
+    <li>Improvements to the <a href="../demo/vim.html">Vim\n
+    bindings</a>: Arbitrary insert mode key mappings are now possible,\n
+    and text objects are supported in visual mode.</li>\n
+    <li>The mode <a href="../mode/meta.js">meta-information file</a>\n
+    now includes information about file extensions,\n
+    and <a href="manual.html#addon_meta">helper\n
+    functions</a> <code>findModeByMIME</code>\n
+    and <code>findModeByExtension</code>.</li>\n
+    <li>New logo!</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.6.0...4.7.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">19-09-2014: <a href="http://codemirror.net/codemirror-4.6.zip">Version 4.6</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>New mode: <a href="../mode/modelica/index.html">Modelica</a></li>\n
+    <li>New method: <a href="manual.html#findWordAt"><code>findWordAt</code></a></li>\n
+    <li>Make it easier to <a href="../demo/markselection.html">use text background styling</a></li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.5.0...4.6.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">21-08-2014: <a href="http://codemirror.net/codemirror-4.5.zip">Version 4.5</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>Fix several serious bugs with horizontal scrolling</li>\n
+    <li>New mode: <a href="../mode/slim/index.html">Slim</a></li>\n
+    <li>New command: <a href="manual.html#command_goLineLeftSmart"><code>goLineLeftSmart</code></a></li>\n
+    <li>More fixes and extensions for the <a href="../demo/vim.html">Vim</a> visual block mode</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.4.0...4.5.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">21-07-2014: <a href="http://codemirror.net/codemirror-4.4.zip">Version 4.4</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li><strong>Note:</strong> Some events might now fire in slightly\n
+    different order (<code>"change"</code> is still guaranteed to fire\n
+    before <code>"cursorActivity"</code>)</li>\n
+    <li>Nested operations in multiple editors are now synced (complete\n
+    at same time, reducing DOM reflows)</li>\n
+    <li>Visual block mode for <a href="../demo/vim.html">vim</a> (&lt;C-v>) is nearly complete</li>\n
+    <li>New mode: <a href="../mode/kotlin/index.html">Kotlin</a></li>\n
+    <li>Better multi-selection paste for text copied from multiple CodeMirror selections</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.3.0...4.4.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">23-06-2014: <a href="http://codemirror.net/codemirror-4.3.zip">Version 4.3</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>Several <a href="../demo/vim.html">vim bindings</a>\n
+    improvements: search and exCommand history, global flag\n
+    for <code>:substitute</code>, <code>:global</code> command.\n
+    <li>Allow hiding the cursor by\n
+    setting <a href="manual.html#option_cursorBlinkRate"><code>cursorBlinkRate</code></a>\n
+    to a negative value.</li>\n
+    <li>Make gutter markers themeable, use this in foldgutter.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.2.0...4.3.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">19-05-2014: <a href="http://codemirror.net/codemirror-4.2.zip">Version 4.2</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>Fix problem where some modes were broken by the fact that empty tokens were forbidden.</li>\n
+    <li>Several fixes to context menu handling.</li>\n
+    <li>On undo, scroll <em>change</em>, not cursor, into view.</li>\n
+    <li>Rewritten <a href="../mode/jade/index.html">Jade</a> mode.</li>\n
+    <li>Various improvements to <a href="../mode/shell/index.html">Shell</a> (support for more syntax) and <a href="../mode/python/index.html">Python</a> (better indentation) modes.</li>\n
+    <li>New mode: <a href="../mode/cypher/index.html">Cypher</a>.</li>\n
+    <li>New theme: <a href="../demo/theme.html?neo">Neo</a>.</li>\n
+    <li>Support direct styling options (color, line style, width) in the <a href="manual.html#addon_rulers">rulers</a> addon.</li>\n
+    <li>Recognize per-editor configuration for the <a href="manual.html#addon_show-hint">show-hint</a> and <a href="manual.html#addon_foldcode">foldcode</a> addons.</li>\n
+    <li>More intelligent scanning for existing close tags in <a href="manual.html#addon_closetag">closetag</a> addon.</li>\n
+    <li>In the <a href="../demo/vim.html">Vim bindings</a>: Fix bracket matching, support case conversion in visual mode, visual paste, append action.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.1.0...4.2.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">22-04-2014: <a href="http://codemirror.net/codemirror-4.1.zip">Version 4.1</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li><em>Slightly incompatible</em>:\n
+    The <a href="manual.html#event_cursorActivity"><code>"cursorActivity"</code></a>\n
+    event now fires after all other events for the operation (and only\n
+    for handlers that were actually registered at the time the\n
+    activity happened).</li>\n
+    <li>New command: <a href="manual.html#command_insertSoftTab"><code>insertSoftTab</code></a>.</li>\n
+    <li>New mode: <a href="../mode/django/index.html">Django</a>.</li>\n
+    <li>Improved modes: <a href="../mode/verilog/index.html">Verilog</a> (rewritten), <a href="../mode/jinja2/index.html">Jinja2</a>, <a href="../mode/haxe/index.html">Haxe</a>, <a href="../mode/php/index.html">PHP</a> (string interpolation highlighted), <a href="../mode/javascript/index.html">JavaScript</a> (indentation of trailing else, template strings), <a href="../mode/livescript/index.html">LiveScript</a> (multi-line strings).</li>\n
+    <li>Many small issues from the 3.x芒聠聮4.x transition were found and fixed.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/4.0.3...4.1.0">list of patches</a>.</li>\n
+  </ul>\n
+\n
+  <p class="rel">20-03-2014: <a href="http://codemirror.net/codemirror-4.0.zip">Version 4.0</a>:</p>\n
+\n
+  <p class="rel-note">This is a new major version of CodeMirror. There\n
+  are a few <strong>incompatible</strong> changes in the API. Upgrade\n
+  with care, and read the <a href="upgrade_v4.html">upgrading\n
+  guide</a>.</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>Multiple selections (ctrl-click, alt-drag, <a href="manual.html#setSelections">API</a>).</li>\n
+    <li>Sublime Text <a href="../demo/sublime.html">bindings</a>.</li>\n
+    <li><a href="manual.html#modloader">Module loader shims</a> wrapped around all modules.</li>\n
+    <li>Selection <a href="manual.html#command_undoSelection">undo</a>/<a href="manual.html#command_redoSelection">redo</a>.</li>\n
+    <li>Improved character measuring (faster, handles wrapped lines more robustly).</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.23.0...4.0.3">list of patches</a>.</li>\n
+  </ul>\n
+\n
+</section>\n
+\n
+<section id=v3>\n
 \n
   <h2>Version 3.x</h2>\n
+\n
+  <p class="rel">22-04-2014: <a href="http://codemirror.net/codemirror-3.24.zip">Version 3.24</a>:</p>\n
+\n
+  <p class="rel-note">Merges the improvements from 4.1 that could\n
+  easily be applied to the 3.x code. Also improves the way the editor\n
+  size is updated when line widgets change.</p>\n
+\n
+  <p class="rel">20-03-2014: <a href="http://codemirror.net/codemirror-3.23.zip">Version 3.23</a>:</p>\n
+\n
+  <ul class="rel-note">\n
+    <li>In the <a href="../mode/xml/index.html">XML mode</a>,\n
+    add <code>brackets</code> style to angle brackets, fix\n
+    case-sensitivity of tags for HTML.</li>\n
+    <li>New mode: <a href="../mode/dylan/index.html">Dylan</a>.</li>\n
+    <li>Many improvements to the <a href="../demo/vim.html">Vim bindings</a>.</li>\n
+  </ul>\n
 \n
   <p class="rel">21-02-2014: <a href="http://codemirror.net/codemirror-3.22.zip">Version 3.22</a>:</p>\n
 \n
   <ul class="rel-note">\n
-    <li>Adds the <a href="doc/manual.html#findMarks"><code>findMarks</code></a> method.</li>\n
-    <li>New addons: <a href="doc/manual.html#addon_rulers">rulers</a>, markdown-fold, yaml-lint.</li>\n
-    <li>New theme: <a href="demo/theme.html?mdn-like">mdn-like</a>.</li>\n
-    <li>New mode: <a href="mode/sold/index.html">Sold</a>.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.21.0...3.22.0">list of patches</a>.</li>\n
+    <li>Adds the <a href="manual.html#findMarks"><code>findMarks</code></a> method.</li>\n
+    <li>New addons: <a href="manual.html#addon_rulers">rulers</a>, markdown-fold, yaml-lint.</li>\n
+    <li>New theme: <a href="../demo/theme.html?mdn-like">mdn-like</a>.</li>\n
+    <li>New mode: <a href="../mode/solr/index.html">Solr</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.21.0...3.22.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">16-01-2014: <a href="http://codemirror.net/codemirror-3.21.zip">Version 3.21</a>:</p>\n
@@ -87,7 +282,7 @@
     <li>Make it possible to fetch multiple applicable helper values with <a href="manual.html#getHelpers"><code>getHelpers</code></a>, and to register helpers matched on predicates with <a href="manual.html#registerGlobalHelper"><code>registerGlobalHelper</code></a>.</li>\n
     <li>New theme <a href="../demo/theme.html?pastel-on-dark">pastel-on-dark</a>.</li>\n
     <li>Better ECMAScript 6 support in <a href="../mode/javascript/index.html">JavaScript</a> mode.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.20.0...3.21.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.20.0...3.21.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">21-11-2013: <a href="http://codemirror.net/codemirror-3.20.zip">Version 3.20</a>:</p>\n
@@ -98,7 +293,7 @@
     <li>Improved indentation for the <a href="../mode/coffeescript/index.html">CoffeeScript mode</a>.</li>\n
     <li>Make non-printable-character representation <a href="manual.html#option_specialChars">configurable</a>.</li>\n
     <li>Add 芒聙聵notification芒聙聶 functionality to <a href="manual.html#addon_dialog">dialog</a> addon.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.19.0...3.20.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.19.0...3.20.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">21-10-2013: <a href="http://codemirror.net/codemirror-3.19.zip">Version 3.19</a>:</p>\n
@@ -108,7 +303,7 @@
     <li>New addons: <a href="manual.html#addon_hardwrap">hardwrap</a>, <a href="manual.html#addon_sql-hint">sql-hint</a>.</li>\n
     <li>New theme: <a href="../demo/theme.html?mbo">MBO</a>.</li>\n
     <li>Add <a href="manual.html#token_style_line">support</a> for line-level styling from mode tokenizers.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.18.0...3.19.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.18.0...3.19.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">23-09-2013: <a href="http://codemirror.net/codemirror-3.18.zip">Version 3.18</a>:</p>\n
@@ -123,7 +318,7 @@
     <li>New modes: <a href="../mode/fortran/index.html">Fortran</a>, <a href="../mode/octave/index.html">Octave</a> (Matlab), <a href="../mode/toml/index.html">TOML</a>, and <a href="../mode/dtd/index.html">DTD</a>.</li>\n
     <li>New addons: <a href="../addon/lint/css-lint.js"><code>css-lint</code></a>, <a href="manual.html#addon_css-hint"><code>css-hint</code></a>.</li>\n
     <li>Improve resilience to CSS \'frameworks\' that globally mess up <code>box-sizing</code>.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.16.0...3.17.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.16.0...3.17.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">21-08-2013: <a href="http://codemirror.net/codemirror-3.16.zip">Version 3.16</a>:</p>\n
@@ -135,7 +330,7 @@
     <li>Improved interaction between themes and <a href="manual.html#addon_active-line">active-line</a>/<a href="manual.html#addon_matchbrackets">matchbrackets</a> addons.</li>\n
     <li>New <a href="manual.html#addon_foldcode">folding</a> function <code>CodeMirror.fold.comment</code>.</li>\n
     <li>Added <a href="manual.html#addon_fullscreen">fullscreen</a> addon.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.15.0...3.16.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.15.0...3.16.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">29-07-2013: <a href="http://codemirror.net/codemirror-3.15.zip">Version 3.15</a>:</p>\n
@@ -146,7 +341,7 @@
     <li>Introduced <a href="manual.html#getHelper"><em>helper</em></a> concept (<a href="https://groups.google.com/forum/#!msg/codemirror/cOc0xvUUEUU/nLrX1-qnidgJ">context</a>).</li>\n
     <li>New method: <a href="manual.html#getModeAt"><code>getModeAt</code></a>.</li>\n
     <li>New themes: base16 <a href="../demo/theme.html?base16-dark">dark</a>/<a href="../demo/theme.html?base16-light">light</a>, 3024 <a href="../demo/theme.html?3024-night">dark</a>/<a href="../demo/theme.html?3024-day">light</a>, <a href="../demo/theme.html?tomorrow-night-eighties">tomorrow-night</a>.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.14.0...3.15.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.14.0...3.15.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">20-06-2013: <a href="http://codemirror.net/codemirror-3.14.zip">Version 3.14</a>:</p>\n
@@ -173,7 +368,7 @@
     <li>Various improvements to <a href="../mode/ruby/index.html">Ruby</a>,\n
     <a href="../mode/smarty/index.html">Smarty</a>, <a href="../mode/sql/index.html">SQL</a>,\n
     and <a href="../demo/vim.html">Vim</a> modes.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/3.13.0...3.14.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/3.13.0...3.14.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">20-05-2013: <a href="http://codemirror.net/codemirror-3.13.zip">Version 3.13</a>:</p>\n
@@ -183,7 +378,7 @@
     <li>New options: <a href="manual.html#option_cursorScrollMargin"><code>cursorScrollMargin</code></a> and <a href="manual.html#option_coverGutterNextToScrollbar"><code>coverGutterNextToScrollbar</code></a>.</li>\n
     <li>New addon: <a href="manual.html#addon_comment">commenting</a>.</li>\n
     <li>More features added to the <a href="../demo/vim.html">Vim keymap</a>.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.12...3.13.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.12...3.13.0">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">19-04-2013: <a href="http://codemirror.net/codemirror-3.12.zip">Version 3.12</a>:</p>\n
@@ -197,7 +392,7 @@
     option for <code>markText</code>.</li>\n
     <li>Various fixes to JavaScript tokenization and indentation corner cases.</li>\n
     <li>Further improvements to the vim mode.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.11...v3.12">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.11...v3.12">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">20-03-2013: <a href="http://codemirror.net/codemirror-3.11.zip">Version 3.11</a>:</p>\n
@@ -222,7 +417,7 @@
     dialog addon.</li>\n
     <li>Tweak behavior of by-word cursor motion.</li>\n
     <li>Further improvements to the <a href="../demo/vim.html">vim mode</a>.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.1...v3.11">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.1...v3.11">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">21-02-2013: <a href="http://codemirror.net/codemirror-3.1.zip">Version 3.1</a>:</p>\n
@@ -258,7 +453,7 @@
     <li>New modes: <a href="../mode/turtle/index.html">Turtle</a>\n
     and <a href="../mode/q/index.html">Q</a>.</li>\n
     <li>Further improvements to the <a href="../demo/vim.html">vim mode</a>.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.01...v3.1">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.01...v3.1">list of patches</a>.</li>\n
   </ul>\n
   \n
 \n
@@ -284,7 +479,7 @@
     <li>Support <code>showIfHidden</code> option for <a href="manual.html#addLineWidget">line widgets</a>.</li>\n
     <li>Add simple <a href="manual.html#addon_python-hint">Python hinter</a>.</li>\n
     <li>Bring back the <a href="manual.html#option_fixedGutter"><code>fixedGutter</code></a> option.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0...v3.01">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0...v3.01">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">10-12-2012: <a href="http://codemirror.net/codemirror-3.0.zip">Version 3.0</a>:</p>\n
@@ -298,7 +493,7 @@
     <li>Rewritten VIM mode.</li>\n
     <li>Fix a few minor scrolling and sizing issues.</li>\n
     <li>Work around Safari segfault when dragging.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0rc2...v3.0">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0rc2...v3.0">list of patches</a>.</li>\n
   </ul>\n
   \n
   <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc2.zip">Version 3.0, release candidate 2</a>:</p>\n
@@ -310,7 +505,7 @@
     <li>Reduce gutter glitches during horiz. scrolling.</li>\n
     <li>Add <a href="manual.html#addKeyMap"><code>addKeyMap</code></a> and <a href="manual.html#removeKeyMap"><code>removeKeyMap</code></a> methods.</li>\n
     <li>Rewrite <code>formatting</code> and <code>closetag</code> add-ons.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0rc1...v3.0rc2">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0rc1...v3.0rc2">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc1.zip">Version 3.0, release candidate 1</a>:</p>\n
@@ -327,7 +522,7 @@
     <li>Add <a href="manual.html#isClean"><code>isClean</code></a>/<a href="manual.html#markClean"><code>markClean</code></a> methods.</li>\n
     <li>Remove <code>compoundChange</code> method, use better undo-event-combining heuristic.</li>\n
     <li>Improve scrolling performance smoothness.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-3.0beta2.zip">Version 3.0, beta 2</a>:</p>\n
@@ -343,7 +538,7 @@
     <li>Add <a href="manual.html#option_flattenSpans"><code>flattenSpans</code></a> option.</li>\n
     <li>Many optimizations. Poor responsiveness should be fixed.</li>\n
     <li>Initialization in hidden state works again.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0beta1...v3.0beta2">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v3.0beta1...v3.0beta2">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-3.0beta1.zip">Version 3.0, beta 1</a>:</p>\n
@@ -375,7 +570,7 @@
     <li>New mode: <a href="../mode/sql/index.html">SQL</a> (will replace <a href="../mode/plsql/index.html">plsql</a> and <a href="../mode/mysql/index.html">mysql</a> modes).</li>\n
     <li>Further work on the new VIM mode.</li>\n
     <li>Fix Cmd/Ctrl keys on recent Operas on OS X.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v2.36...v2.37">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v2.36...v2.37">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-2.36.zip">Version 2.36</a>:</p>\n
@@ -389,7 +584,7 @@
     <li>Various extensions to the vim keymap.</li>\n
     <li>Make <a href="../mode/php/index.html">PHP mode</a> build on <a href="../mode/htmlmixed/index.html">mixed HTML mode</a>.</li>\n
     <li>Add <a href="manual.html#addon_continuecomment">comment-continuing</a> add-on.</li>\n
-    <li>Full <a href="../https://github.com/marijnh/CodeMirror/compare/v2.35...v2.36">list of patches</a>.</li>\n
+    <li>Full <a href="../https://github.com/codemirror/CodeMirror/compare/v2.35...v2.36">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-2.35.zip">Version 2.35</a>:</p>\n
@@ -400,7 +595,7 @@
     <li>Fix several bugs in <a href="manual.html#markText"><code>markText</code></a>/undo interaction.</li>\n
     <li>Better indentation of JavaScript code without semicolons.</li>\n
     <li>Add <a href="manual.html#defineInitHook"><code>defineInitHook</code></a> function.</li>\n
-    <li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v2.34...v2.35">list of patches</a>.</li>\n
+    <li>Full <a href="https://github.com/codemirror/CodeMirror/compare/v2.34...v2.35">list of patches</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">19-09-2012: <a href="http://codemirror.net/codemirror-2.34.zip">Version 2.34</a>:</p>\n
@@ -413,7 +608,7 @@
     <li>Add a <a href="manual.html#version"><code>CodeMirror.version</code></a> property.</li>\n
     <li>More robust handling of nested modes in <a href="../demo/formatting.html">formatting</a> and <a href="../demo/closetag.html">closetag</a> plug-ins.</li>\n
     <li>Un/redo now preserves <a href="manual.html#markText">marked text</a> and bookmarks.</li>\n
-    <li><a href="https://github.com/marijnh/CodeMirror/compare/v2.33...v2.34">Full list</a> of patches.</li>\n
+    <li><a href="https://github.com/codemirror/CodeMirror/compare/v2.33...v2.34">Full list</a> of patches.</li>\n
   </ul>\n
 \n
   <p class="rel">23-08-2012: <a href="http://codemirror.net/codemirror-2.33.zip">Version 2.33</a>:</p>\n
@@ -427,7 +622,7 @@
     <li>More tweaks to the scrolling model.</li>\n
     <li>Expanded testsuite. Basic linter added.</li>\n
     <li>Remove most uses of <code>innerHTML</code>. Remove <code>CodeMirror.htmlEscape</code>.</li>\n
-    <li><a href="https://github.com/marijnh/CodeMirror/compare/v2.32...v2.33">Full list</a> of patches.</li>\n
+    <li><a href="https://github.com/codemirror/CodeMirror/compare/v2.32...v2.33">Full list</a> of patches.</li>\n
   </ul>\n
 \n
   <p class="rel">23-07-2012: <a href="http://codemirror.net/codemirror-2.32.zip">Version 2.32</a>:</p>\n
@@ -445,7 +640,7 @@
     <li>Add <a href="manual.html#getHistory"><code>getHistory</code></a> and <a href="manual.html#setHistory"><code>setHistory</code></a> methods.</li>\n
     <li>Allow custom line separator string in <a href="manual.html#getValue"><code>getValue</code></a> and <a href="manual.html#getRange"><code>getRange</code></a>.</li>\n
     <li>Support double- and triple-click drag, double-clicking whitespace.</li>\n
-    <li>And more... <a href="https://github.com/marijnh/CodeMirror/compare/v2.3...v2.31">(all patches)</a></li>\n
+    <li>And more... <a href="https://github.com/codemirror/CodeMirror/compare/v2.3...v2.31">(all patches)</a></li>\n
   </ul>\n
 \n
   <p class="rel">22-06-2012: <a href="http://codemirror.net/codemirror-2.3.zip">Version 2.3</a>:</p>\n
@@ -457,7 +652,7 @@
     <li>Add <a href="../demo/multiplex.html">mode-multiplexing</a> utility script.</li>\n
     <li>Fix bug where right-click paste works in read-only mode.</li>\n
     <li>Add a <a href="manual.html#getScrollInfo"><code>getScrollInfo</code></a> method.</li>\n
-    <li>Lots of other <a href="https://github.com/marijnh/CodeMirror/compare/v2.25...v2.3">fixes</a>.</li>\n
+    <li>Lots of other <a href="https://github.com/codemirror/CodeMirror/compare/v2.25...v2.3">fixes</a>.</li>\n
   </ul>\n
 \n
   <p class="rel">23-05-2012: <a href="http://codemirror.net/codemirror-2.25.zip">Version 2.25</a>:</p>\n
@@ -695,7 +890,7 @@
   and <a href="http://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580">this</a>\n
   for more information.</p>\n
 \n
-  <p class="rel">22-02-2011: <a href="https://github.com/marijnh/codemirror/tree/beta2">Version 2.0 beta 2</a>:</p>\n
+  <p class="rel">22-02-2011: <a href="https://github.com/codemirror/codemirror/tree/beta2">Version 2.0 beta 2</a>:</p>\n
   <p class="rel-note">Somewhat more mature API, lots of bugs shaken out.</p>\n
 \n
   <p class="rel">17-02-2011: <a href="http://codemirror.net/codemirror-0.94.zip">Version 0.94</a>:</p>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/reporting.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/reporting.html.xml
index 1a95c6e96acb3baaa97322f9488bda99491ddeca..241df7687e82093adc61d7025a9a2cf947d8943d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/reporting.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/reporting.html.xml
@@ -43,12 +43,12 @@
 <link rel=stylesheet href="docs.css">\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">Reporting bugs</a>\n
@@ -89,7 +89,7 @@ CodeMirror. But first, please read over these points:</p>\n
   <li>If the problem can not be reproduced in any of the demos\n
   included in the CodeMirror distribution, please provide an HTML\n
   document that demonstrates the problem. The best way to do this is\n
-  to go to <a href="http://jsbin.com/ihunin/edit">jsbin.com</a>, enter\n
+  to go to <a href="http://jsbin.com/ihunin/1/edit">jsbin.com</a>, enter\n
   it there, press save, and include the resulting link in your bug\n
   report.</li>\n
 </ol>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v2.2.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v2.2.html.xml
index 5216155e55ce034a41ea0dede7bc7316269a6c78..4e610d25368f509ffd0f3a047875d3c909cfcdb1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v2.2.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v2.2.html.xml
@@ -43,12 +43,12 @@
 <link rel=stylesheet href="docs.css">\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#">2.2 upgrade guide</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v3.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v3.html.xml
index 7460a07ba8796c19688c5c4ba8d73c6f063a268d..8aff51f1fbc70a4719c5bb0e260f48d9ab934b66 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v3.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v3.html.xml
@@ -52,12 +52,12 @@
 <script src="activebookmark.js"></script>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../index.html">Home</a>\n
     <li><a href="manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a class=active href="#upgrade">Upgrade guide</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v4.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v4.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..697b0cf4ddadf98b2ab037039b1d03cfac67c388
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/doc/upgrade_v4.html.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <unicode encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+\n
+<title>CodeMirror: Version 4 upgrade guide</title>\n
+<meta charset="utf-8"/>\n
+<link rel=stylesheet href="docs.css">\n
+<script src="activebookmark.js"></script>\n
+\n
+<div id=nav>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>\n
+\n
+  <ul>\n
+    <li><a href="../index.html">Home</a>\n
+    <li><a href="manual.html">Manual</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
+  </ul>\n
+  <ul>\n
+    <li><a class=active href="#upgrade">Upgrade guide</a>\n
+    <li><a href="#multisel">Multiple selections</a>\n
+    <li><a href="#beforeSelectionChange">The beforeSelectionChange event</a>\n
+    <li><a href="#replaceSelection">replaceSelection and collapsing</a>\n
+    <li><a href="#changeEvent">change event data</a>\n
+    <li><a href="#showIfHidden">showIfHidden option to line widgets</a>\n
+    <li><a href="#module">Module loaders</a>\n
+    <li><a href="#shareddata">Mutating shared data structures</a></li>\n
+    <li><a href="#deprecated">Deprecated interfaces dropped</a>\n
+  </ul>\n
+</div>\n
+\n
+<article>\n
+\n
+<h2 id=upgrade>Upgrading to version 4</h2>\n
+\n
+<p>CodeMirror 4\'s interface is <em>very</em> close version 3, but it\n
+does fix a few awkward details in a backwards-incompatible ways. At\n
+least skim the text below before upgrading.</p>\n
+\n
+<section id=multisel><h2>Multiple selections</h2>\n
+\n
+<p>The main new feature in version 4 is multiple selections. The\n
+single-selection variants of methods are still there, but now\n
+typically act only on the <em>primary</em> selection (usually the last\n
+one added).</p>\n
+\n
+<p>The exception to this\n
+is <a href="manual.html#getSelection"><strong><code>getSelection</code></strong></a>,\n
+which will now return the content of <em>all</em> selections\n
+(separated by newlines, or whatever <code>lineSep</code> parameter you passed\n
+it).</p>\n
+\n
+</section>\n
+\n
+<section id=beforeSelectionChange><h2>The beforeSelectionChange event</h2>\n
+\n
+<p>This event still exists, but the object it is passed has\n
+a <a href="manual.html#event_beforeSelectionChange">completely new\n
+interface</a>, because such changes now concern multiple\n
+selections.</p>\n
+\n
+</section>\n
+\n
+<section id=replaceSelection><h2>replaceSelection\'s collapsing behavior</h2>\n
+\n
+<p>By\n
+default, <a href="manual.html#replaceSelection"><code>replaceSelection</code></a>\n
+would leave the newly inserted text selected. This is only rarely what\n
+you want, and also (slightly) more expensive in the new model, so the\n
+default was changed to <code>"end"</code>, meaning the old behavior\n
+must be explicitly specified by passing a second argument\n
+of <code>"around"</code>.</p>\n
+\n
+</section>\n
+\n
+<section id=changeEvent><h2>change event data</h2>\n
+\n
+<p>Rather than forcing client code to follow <code>next</code>\n
+pointers from one change object to the next, the library will now\n
+simply fire\n
+multiple <a href="manual.html#event_change"><code>"change"</code></a>\n
+events. Existing code will probably continue to work unmodified.</p>\n
+\n
+</section>\n
+\n
+<section id=showIfHidden><h2>showIfHidden option to line widgets</h2>\n
+\n
+<p>This option, which conceptually caused line widgets to be visible\n
+even if their line was hidden, was never really well-defined, and was\n
+buggy from the start. It would be a rather expensive feature, both in\n
+code complexity and run-time performance, to implement properly. It\n
+has been dropped entirely in 4.0.</p>\n
+\n
+</section>\n
+\n
+<section id=module><h2>Module loaders</h2>\n
+\n
+<p>All modules in the CodeMirror distribution are now wrapped in a\n
+shim function to make them compatible with both AMD\n
+(<a href="http://requirejs.org">requirejs</a>) and CommonJS (as used\n
+by <a href="http://nodejs.org/">node</a>\n
+and <a href="http://browserify.org/">browserify</a>) module loaders.\n
+When neither of these is present, they fall back to simply using the\n
+global <code>CodeMirror</code> variable.</p>\n
+\n
+<p>If you have a module loader present in your environment, CodeMirror\n
+will attempt to use it, and you might need to change the way you load\n
+CodeMirror modules.</p>\n
+\n
+</section>\n
+\n
+<section id=shareddata><h2>Mutating shared data structures</h2>\n
+\n
+<p>Data structures produced by the library should not be mutated\n
+unless explicitly allowed, in general. This is slightly more strict in\n
+4.0 than it was in earlier versions, which copied the position objects\n
+returned by <a href="manual.html#getCursor"><code>getCursor</code></a>\n
+for nebulous, historic reasons. In 4.0, mutating these\n
+objects <em>will</em> corrupt your editor\'s selection.</p>\n
+\n
+</section>\n
+\n
+<section id=deprecated><h2>Deprecated interfaces dropped</h2>\n
+\n
+<p>A few properties and methods that have been deprecated for a while\n
+are now gone. Most notably, the <code>onKeyEvent</code>\n
+and <code>onDragEvent</code> options (use the\n
+corresponding <a href="manual.html#event_dom">events</a> instead).</p>\n
+\n
+<p>Two silly methods, which were mostly there to stay close to the 0.x\n
+API, <code>setLine</code> and <code>removeLine</code> are now gone.\n
+Use the more\n
+flexible <a href="manual.html#replaceRange"><code>replaceRange</code></a>\n
+method instead.</p>\n
+\n
+<p>The long names for folding and completing functions\n
+(<code>CodeMirror.braceRangeFinder</code>, <code>CodeMirror.javascriptHint</code>,\n
+etc) are also gone\n
+(use <code>CodeMirror.fold.brace</code>, <code>CodeMirror.hint.javascript</code>).</p>\n
+\n
+<p>The <code>className</code> property in the return value\n
+of <a href="manual.html#getTokenAt"><code>getTokenAt</code></a>, which\n
+has been superseded by the <code>type</code> property, is also no\n
+longer present.</p>\n
+\n
+</section>\n
+</article>
+
+]]></unicode> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>expand</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>upgrade_v4.html</string> </value>
+        </item>
+        <item>
+            <key> <string>output_encoding</string> </key>
+            <value> <string>iso-8859-15</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/index.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/index.html.xml
index cf53e801c05488524f256ff537640dbc7e61c231..1298a1fdd2a70df6e5ca60242f88b65c88a6c6bf 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/index.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/index.html.xml
@@ -59,12 +59,12 @@
 </style>\n
 \n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a class=active data-default="true" href="#description">Home</a>\n
     <li><a href="doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="#features">Features</a>\n
@@ -78,7 +78,7 @@
 <section id=description class=first>\n
   <p><strong>CodeMirror</strong> is a versatile text editor\n
   implemented in JavaScript for the browser. It is specialized for\n
-  editing code, and comes with a number of language modes and addons\n
+  editing code, and comes with a number of <a href="mode/index.html">language modes</a> and <a href="doc/manual.html#addons">addons</a>\n
   that implement more advanced editing functionality.</p>\n
 \n
   <p>A rich <a href="doc/manual.html#api">programming API</a> and a\n
@@ -95,7 +95,7 @@
 <script src="lib/codemirror.js"></script>\n
 <script>\n
   var editor = CodeMirror.fromTextArea(myTextarea, {\n
-    mode: "text/html"\n
+    lineNumbers: true\n
   });\n
 </script></textarea>\n
   <select id="demolist" onchange="document.location = this.options[this.selectedIndex].value;">\n
@@ -109,9 +109,11 @@
     <option value="demo/search.html">Search interface</option>\n
     <option value="demo/vim.html">Vim bindings</option>\n
     <option value="demo/emacs.html">Emacs bindings</option>\n
+    <option value="demo/sublime.html">Sublime Text bindings</option>\n
     <option value="demo/tern.html">Tern integration</option>\n
     <option value="demo/merge.html">Merge/diff interface</option>\n
     <option value="demo/fullscreen.html">Full-screen editor</option>\n
+    <option value="demo/simplescrollbars.html">Custom scrollbars</option>\n
   </select></form>\n
   <script>\n
     var editor = CodeMirror.fromTextArea(document.getElementById("demotext"), {\n
@@ -122,16 +124,17 @@
   </script>\n
   <div style="position: relative; margin: 1em 0;">\n
     <a class="bigbutton left" href="http://codemirror.net/codemirror.zip">DOWNLOAD LATEST RELEASE</a>\n
-    <div><strong>version 3.22</strong> (<a href="doc/releases.html">Release notes</a>)</div>\n
+    <div><strong>version 4.11</strong> (<a href="doc/releases.html">Release notes</a>)</div>\n
     <div>or use the <a href="doc/compress.html">minification helper</a></div>\n
     <div style="position: absolute; top: 0; right: 0; text-align: right">\n
       <span class="bigbutton right" onclick="document.getElementById(\'paypal\').submit();">DONATE WITH PAYPAL</span>\n
       <div style="position: relative">\n
         or <span onclick="document.getElementById(\'bankinfo\').style.display = \'block\';" class=quasilink>Bank</span>,\n
-        <a href="https://www.gittip.com/marijnh">Gittip</a>,\n
-        <a href="https://flattr.com/profile/marijnh">Flattr</a><br>\n
-        <div id=bankinfo>\n
-          <span id=bankinfo_close onclick="document.getElementById(\'bankinfo\').style.display = \'\';">脙聴</span>\n
+        <span onclick="document.getElementById(\'bcinfo\').style.display = \'block\';" class=quasilink>Bitcoin</span>,\n
+        <a href="http://www.patreon.com/marijn">Patreon</a><br>\n
+        <a href="https://gratipay.com/marijnh/">Gratipay</a><br>\n
+        <div id=bankinfo class=bankinfo>\n
+          <span class=bankinfo_close onclick="document.getElementById(\'bankinfo\').style.display = \'\';">脙聴</span>\n
           Bank: <i>Rabobank</i><br/>\n
           Country: <i>Netherlands</i><br/>\n
           SWIFT: <i>RABONL2U</i><br/>\n
@@ -139,6 +142,10 @@
           Name: <i>Marijn Haverbeke</i><br/>\n
           IBAN: <i>NL26 RABO 0147 8507 70</i>\n
         </div>\n
+        <div id=bcinfo class=bankinfo>\n
+          <span class=bankinfo_close onclick="document.getElementById(\'bcinfo\').style.display = \'\';">脙聴</span>\n
+          Bitcoin address: 1HVnnU8E9yLPeFyNgNtUPB5deXBvUmZ6Nx\n
+        </div>\n
         <form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">\n
           <input type="hidden" name="cmd" value="_s-xclick"/>\n
           <input type="hidden" name="hosted_button_id" value="3FVHS5FGUY7CC"/>\n
@@ -159,7 +166,7 @@
     <li><a href="doc/manual.html#addon_show-hint">Autocompletion</a> (<a href="demo/xmlcomplete.html">XML</a>)\n
     <li><a href="doc/manual.html#addon_foldcode">Code folding</a>\n
     <li><a href="doc/manual.html#option_extraKeys">Configurable</a> keybindings\n
-    <li><a href="demo/vim.html">Vim</a> and <a href="demo/emacs.html">Emacs</a> bindings\n
+    <li><a href="demo/vim.html">Vim</a>, <a href="demo/emacs.html">Emacs</a>, and <a href="demo/sublime.html">Sublime Text</a> bindings\n
     <li><a href="doc/manual.html#addon_search">Search and replace</a> interface\n
     <li><a href="doc/manual.html#addon_matchbrackets">Bracket</a> and <a href="doc/manual.html#addon_matchtags">tag</a> matching\n
     <li>Support for <a href="demo/buffers.html">split views</a>\n
@@ -188,7 +195,7 @@
   and <a href="doc/realworld.html">many other projects</a>.</p>\n
 \n
   <p>Development and bug tracking happens\n
-  on <a href="https://github.com/marijnh/CodeMirror/">github</a>\n
+  on <a href="https://github.com/codemirror/CodeMirror/">github</a>\n
   (<a href="http://marijnhaverbeke.nl/git/codemirror">alternate git\n
   repository</a>).\n
   Please <a href="http://codemirror.net/doc/reporting.html">read these\n
@@ -197,7 +204,7 @@
   license that CodeMirror uses.</p>\n
 \n
   <p>Discussion around the project is done on\n
-  a <a href="http://groups.google.com/group/codemirror">mailing list</a>.\n
+  a <a href="http://discuss.codemirror.net">discussion forum</a>.\n
   There is also\n
   the <a href="http://groups.google.com/group/codemirror-announce">codemirror-announce</a>\n
   list, which is only used for major announcements (such as new\n
@@ -207,17 +214,17 @@
 \n
   <p>A list of CodeMirror-related software that is not part of the\n
   main distribution is maintained\n
-  on <a href="https://github.com/marijnh/CodeMirror/wiki/CodeMirror-addons">our\n
+  on <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">our\n
   wiki</a>. Feel free to add your project.</p>\n
 </section>\n
 \n
 <section id=browsersupport>\n
   <h2>Browser support</h2>\n
   <p>The <em>desktop</em> versions of the following browsers,\n
-  in <em>standards mode</em> (HTML5 <code>&lt;!doctype html></code>\n
+  in <em>standards mode</em> (HTML5 <code>&lt;!doctype脗聽html></code>\n
   recommended) are supported:</p>\n
   <table style="margin-bottom: 1em">\n
-    <tr><th>Firefox</th><td>version 3 and up</td></tr>\n
+    <tr><th>Firefox</th><td>version 4 and up</td></tr>\n
     <tr><th>Chrome</th><td>any version</td></tr>\n
     <tr><th>Safari</th><td>version 5.2 and up</td></tr>\n
     <tr><th style="padding-right: 1em;">Internet Explorer</th><td>version 8 and up</td></tr>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/emacs.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/emacs.js.xml
index b932f444ea1a6db08a9108f192284110e3a4134c..a4a250da3eed8909d0903528c04554b43244ef52 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/emacs.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/emacs.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403085.31</string> </value>
+            <value> <string>ts21897131.51</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,17 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   "use strict";\n
 \n
   var Pos = CodeMirror.Pos;\n
@@ -146,8 +156,8 @@
     };\n
   }\n
 \n
-  function findEnd(cm, by, dir) {\n
-    var pos = cm.getCursor(), prefix = getPrefix(cm);\n
+  function findEnd(cm, pos, by, dir) {\n
+    var prefix = getPrefix(cm);\n
     if (prefix < 0) { dir = -dir; prefix = -prefix; }\n
     for (var i = 0; i < prefix; ++i) {\n
       var newPos = by(cm, pos, dir);\n
@@ -159,14 +169,31 @@
 \n
   function move(by, dir) {\n
     var f = function(cm) {\n
-      cm.extendSelection(findEnd(cm, by, dir));\n
+      cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir));\n
     };\n
     f.motion = true;\n
     return f;\n
   }\n
 \n
   function killTo(cm, by, dir) {\n
-    kill(cm, cm.getCursor(), findEnd(cm, by, dir), true);\n
+    var selections = cm.listSelections(), cursor;\n
+    var i = selections.length;\n
+    while (i--) {\n
+      cursor = selections[i].head;\n
+      kill(cm, cursor, findEnd(cm, cursor, by, dir), true);\n
+    }\n
+  }\n
+\n
+  function killRegion(cm) {\n
+    if (cm.somethingSelected()) {\n
+      var selections = cm.listSelections(), selection;\n
+      var i = selections.length;\n
+      while (i--) {\n
+        selection = selections[i];\n
+        kill(cm, selection.anchor, selection.head);\n
+      }\n
+      return true;\n
+    }\n
   }\n
 \n
   function addPrefix(cm, digit) {\n
@@ -198,7 +225,7 @@
     if (dup > 1 && event.origin == "+input") {\n
       var one = event.text.join("\\n"), txt = "";\n
       for (var i = 1; i < dup; ++i) txt += one;\n
-      cm.replaceSelection(txt, "end", "+input");\n
+      cm.replaceSelection(txt);\n
     }\n
   }\n
 \n
@@ -221,7 +248,7 @@
 \n
   function setMark(cm) {\n
     cm.setCursor(cm.getCursor());\n
-    cm.setExtending(true);\n
+    cm.setExtending(!cm.getExtending());\n
     cm.on("change", function() { cm.setExtending(false); });\n
   }\n
 \n
@@ -270,7 +297,7 @@
 \n
   // Actual keymap\n
 \n
-  var keyMap = CodeMirror.keyMap.emacs = {\n
+  var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({\n
     "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},\n
     "Ctrl-K": repeated(function(cm) {\n
       var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));\n
@@ -290,16 +317,16 @@
       cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste");\n
       cm.setSelection(start, cm.getCursor());\n
     },\n
-    "Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},\n
+    "Alt-Y": function(cm) {cm.replaceSelection(popFromRing(), "around", "paste");},\n
 \n
     "Ctrl-Space": setMark, "Ctrl-Shift-2": setMark,\n
 \n
     "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),\n
     "Right": move(byChar, 1), "Left": move(byChar, -1),\n
     "Ctrl-D": function(cm) { killTo(cm, byChar, 1); },\n
-    "Delete": function(cm) { killTo(cm, byChar, 1); },\n
+    "Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); },\n
     "Ctrl-H": function(cm) { killTo(cm, byChar, -1); },\n
-    "Backspace": function(cm) { killTo(cm, byChar, -1); },\n
+    "Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); },\n
 \n
     "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),\n
     "Alt-D": function(cm) { killTo(cm, byWord, 1); },\n
@@ -323,7 +350,8 @@
     "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),\n
 \n
     "Shift-Ctrl-Alt-2": function(cm) {\n
-      cm.setSelection(findEnd(cm, byExpr, 1), cm.getCursor());\n
+      var cursor = cm.getCursor();\n
+      cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor);\n
     },\n
     "Ctrl-Alt-T": function(cm) {\n
       var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);\n
@@ -341,13 +369,7 @@
     },\n
     "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\\n", "start"); }),\n
     "Ctrl-T": repeated(function(cm) {\n
-      var pos = cm.getCursor();\n
-      if (pos.ch < cm.getLine(pos.line).length) pos = Pos(pos.line, pos.ch + 1);\n
-      var from = cm.findPosH(pos, -2, "char");\n
-      var range = cm.getRange(from, pos);\n
-      if (range.length != 2) return;\n
-      cm.setSelection(from, pos);\n
-      cm.replaceSelection(range.charAt(1) + range.charAt(0), "end");\n
+      cm.execCommand("transposeChars");\n
     }),\n
 \n
     "Alt-C": repeated(function(cm) {\n
@@ -373,27 +395,7 @@
     "Alt-/": "autocomplete",\n
     "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",\n
 \n
-    "Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");},\n
-    "Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},\n
-    "Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");},\n
-    "Ctrl-U": addPrefixMap\n
-  };\n
-\n
-  CodeMirror.keyMap["emacs-Ctrl-X"] = {\n
-    "Tab": function(cm) {\n
-      cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));\n
-    },\n
-    "Ctrl-X": function(cm) {\n
-      cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));\n
-    },\n
-\n
-    "Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",\n
-    "Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },\n
-    auto: "emacs", nofallthrough: true, disableInput: true\n
-  };\n
-\n
-  CodeMirror.keyMap["emacs-Alt-G"] = {\n
-    "G": function(cm) {\n
+    "Alt-G G": function(cm) {\n
       var prefix = getPrefix(cm, true);\n
       if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);\n
 \n
@@ -403,13 +405,24 @@
           cm.setCursor(num - 1);\n
       });\n
     },\n
-    auto: "emacs", nofallthrough: true, disableInput: true\n
-  };\n
 \n
-  CodeMirror.keyMap["emacs-Ctrl-Q"] = {\n
-    "Tab": repeated("insertTab"),\n
-    auto: "emacs", nofallthrough: true\n
-  };\n
+    "Ctrl-X Tab": function(cm) {\n
+      cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));\n
+    },\n
+    "Ctrl-X Ctrl-X": function(cm) {\n
+      cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));\n
+    },\n
+    "Ctrl-X Ctrl-S": "save",\n
+    "Ctrl-X Ctrl-W": "save",\n
+    "Ctrl-X S": "saveAll",\n
+    "Ctrl-X F": "open",\n
+    "Ctrl-X U": repeated("undo"),\n
+    "Ctrl-X K": "close",\n
+    "Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },\n
+\n
+    "Ctrl-Q Tab": repeated("insertTab"),\n
+    "Ctrl-U": addPrefixMap\n
+  });\n
 \n
   var prefixMap = {"Ctrl-G": clearPrefix};\n
   function regPrefix(d) {\n
@@ -419,7 +432,7 @@
   }\n
   for (var i = 0; i < 10; ++i) regPrefix(String(i));\n
   regPrefix("-");\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -430,7 +443,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>13044</int> </value>
+            <value> <int>13307</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/extra.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/extra.js.xml
deleted file mode 100644
index 6bcc8eb72762ba7c967251ab381ba344d7b1d535..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/extra.js.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403085.58</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>extra.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-// A number of additional default bindings that are too obscure to\n
-// include in the core codemirror.js file.\n
-\n
-(function() {\n
-  "use strict";\n
-\n
-  var Pos = CodeMirror.Pos;\n
-\n
-  function moveLines(cm, start, end, dist) {\n
-    if (!dist || start > end) return 0;\n
-\n
-    var from = cm.clipPos(Pos(start, 0)), to = cm.clipPos(Pos(end));\n
-    var text = cm.getRange(from, to);\n
-\n
-    if (start <= cm.firstLine())\n
-      cm.replaceRange("", from, Pos(to.line + 1, 0));\n
-    else\n
-      cm.replaceRange("", Pos(from.line - 1), to);\n
-    var target = from.line + dist;\n
-    if (target <= cm.firstLine()) {\n
-      cm.replaceRange(text + "\\n", Pos(target, 0));\n
-      return cm.firstLine() - from.line;\n
-    } else {\n
-      var targetPos = cm.clipPos(Pos(target - 1));\n
-      cm.replaceRange("\\n" + text, targetPos);\n
-      return targetPos.line + 1 - from.line;\n
-    }\n
-  }\n
-\n
-  function moveSelectedLines(cm, dist) {\n
-    var head = cm.getCursor("head"), anchor = cm.getCursor("anchor");\n
-    cm.operation(function() {\n
-      var moved = moveLines(cm, Math.min(head.line, anchor.line), Math.max(head.line, anchor.line), dist);\n
-      cm.setSelection(Pos(anchor.line + moved, anchor.ch), Pos(head.line + moved, head.ch));\n
-    });\n
-  }\n
-\n
-  CodeMirror.commands.moveLinesUp = function(cm) { moveSelectedLines(cm, -1); };\n
-  CodeMirror.commands.moveLinesDown = function(cm) { moveSelectedLines(cm, 1); };\n
-\n
-  CodeMirror.keyMap["default"]["Alt-Up"] = "moveLinesUp";\n
-  CodeMirror.keyMap["default"]["Alt-Down"] = "moveLinesDown";\n
-})();\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>1487</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/sublime.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/sublime.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..140cf14d1e82dd68fe9340196e329e30eef990dc
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/sublime.js.xml
@@ -0,0 +1,584 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897131.32</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>sublime.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// A rough approximation of Sublime Text\'s keybindings\n
+// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  var map = CodeMirror.keyMap.sublime = {fallthrough: "default"};\n
+  var cmds = CodeMirror.commands;\n
+  var Pos = CodeMirror.Pos;\n
+  var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;\n
+  var ctrl = mac ? "Cmd-" : "Ctrl-";\n
+\n
+  // This is not exactly Sublime\'s algorithm. I couldn\'t make heads or tails of that.\n
+  function findPosSubword(doc, start, dir) {\n
+    if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));\n
+    var line = doc.getLine(start.line);\n
+    if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));\n
+    var state = "start", type;\n
+    for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) {\n
+      var next = line.charAt(dir < 0 ? pos - 1 : pos);\n
+      var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";\n
+      if (cat == "w" && next.toUpperCase() == next) cat = "W";\n
+      if (state == "start") {\n
+        if (cat != "o") { state = "in"; type = cat; }\n
+      } else if (state == "in") {\n
+        if (type != cat) {\n
+          if (type == "w" && cat == "W" && dir < 0) pos--;\n
+          if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; }\n
+          break;\n
+        }\n
+      }\n
+    }\n
+    return Pos(start.line, pos);\n
+  }\n
+\n
+  function moveSubword(cm, dir) {\n
+    cm.extendSelectionsBy(function(range) {\n
+      if (cm.display.shift || cm.doc.extend || range.empty())\n
+        return findPosSubword(cm.doc, range.head, dir);\n
+      else\n
+        return dir < 0 ? range.from() : range.to();\n
+    });\n
+  }\n
+\n
+  cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };\n
+  cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };\n
+\n
+  cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) {\n
+    var info = cm.getScrollInfo();\n
+    if (!cm.somethingSelected()) {\n
+      var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");\n
+      if (cm.getCursor().line >= visibleBottomLine)\n
+        cm.execCommand("goLineUp");\n
+    }\n
+    cm.scrollTo(null, info.top - cm.defaultTextHeight());\n
+  };\n
+  cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) {\n
+    var info = cm.getScrollInfo();\n
+    if (!cm.somethingSelected()) {\n
+      var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;\n
+      if (cm.getCursor().line <= visibleTopLine)\n
+        cm.execCommand("goLineDown");\n
+    }\n
+    cm.scrollTo(null, info.top + cm.defaultTextHeight());\n
+  };\n
+\n
+  cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) {\n
+    var ranges = cm.listSelections(), lineRanges = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var from = ranges[i].from(), to = ranges[i].to();\n
+      for (var line = from.line; line <= to.line; ++line)\n
+        if (!(to.line > from.line && line == to.line && to.ch == 0))\n
+          lineRanges.push({anchor: line == from.line ? from : Pos(line, 0),\n
+                           head: line == to.line ? to : Pos(line)});\n
+    }\n
+    cm.setSelections(lineRanges, 0);\n
+  };\n
+\n
+  map["Shift-Tab"] = "indentLess";\n
+\n
+  cmds[map["Esc"] = "singleSelectionTop"] = function(cm) {\n
+    var range = cm.listSelections()[0];\n
+    cm.setSelection(range.anchor, range.head, {scroll: false});\n
+  };\n
+\n
+  cmds[map[ctrl + "L"] = "selectLine"] = function(cm) {\n
+    var ranges = cm.listSelections(), extended = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var range = ranges[i];\n
+      extended.push({anchor: Pos(range.from().line, 0),\n
+                     head: Pos(range.to().line + 1, 0)});\n
+    }\n
+    cm.setSelections(extended);\n
+  };\n
+\n
+  map["Shift-" + ctrl + "K"] = "deleteLine";\n
+\n
+  function insertLine(cm, above) {\n
+    cm.operation(function() {\n
+      var len = cm.listSelections().length, newSelection = [], last = -1;\n
+      for (var i = 0; i < len; i++) {\n
+        var head = cm.listSelections()[i].head;\n
+        if (head.line <= last) continue;\n
+        var at = Pos(head.line + (above ? 0 : 1), 0);\n
+        cm.replaceRange("\\n", at, null, "+insertLine");\n
+        cm.indentLine(at.line, null, true);\n
+        newSelection.push({head: at, anchor: at});\n
+        last = head.line + 1;\n
+      }\n
+      cm.setSelections(newSelection);\n
+    });\n
+  }\n
+\n
+  cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { insertLine(cm, false); };\n
+\n
+  cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { insertLine(cm, true); };\n
+\n
+  function wordAt(cm, pos) {\n
+    var start = pos.ch, end = start, line = cm.getLine(pos.line);\n
+    while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start;\n
+    while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end;\n
+    return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)};\n
+  }\n
+\n
+  cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) {\n
+    var from = cm.getCursor("from"), to = cm.getCursor("to");\n
+    var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel;\n
+    if (CodeMirror.cmpPos(from, to) == 0) {\n
+      var word = wordAt(cm, from);\n
+      if (!word.word) return;\n
+      cm.setSelection(word.from, word.to);\n
+      fullWord = true;\n
+    } else {\n
+      var text = cm.getRange(from, to);\n
+      var query = fullWord ? new RegExp("\\\\b" + text + "\\\\b") : text;\n
+      var cur = cm.getSearchCursor(query, to);\n
+      if (cur.findNext()) {\n
+        cm.addSelection(cur.from(), cur.to());\n
+      } else {\n
+        cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));\n
+        if (cur.findNext())\n
+          cm.addSelection(cur.from(), cur.to());\n
+      }\n
+    }\n
+    if (fullWord)\n
+      cm.state.sublimeFindFullWord = cm.doc.sel;\n
+  };\n
+\n
+  var mirror = "(){}[]";\n
+  function selectBetweenBrackets(cm) {\n
+    var pos = cm.getCursor(), opening = cm.scanForBracket(pos, -1);\n
+    if (!opening) return;\n
+    for (;;) {\n
+      var closing = cm.scanForBracket(pos, 1);\n
+      if (!closing) return;\n
+      if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) {\n
+        cm.setSelection(Pos(opening.pos.line, opening.pos.ch + 1), closing.pos, false);\n
+        return true;\n
+      }\n
+      pos = Pos(closing.pos.line, closing.pos.ch + 1);\n
+    }\n
+  }\n
+\n
+  cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) {\n
+    selectBetweenBrackets(cm) || cm.execCommand("selectAll");\n
+  };\n
+  cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) {\n
+    if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;\n
+  };\n
+\n
+  cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) {\n
+    cm.extendSelectionsBy(function(range) {\n
+      var next = cm.scanForBracket(range.head, 1);\n
+      if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos;\n
+      var prev = cm.scanForBracket(range.head, -1);\n
+      return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;\n
+    });\n
+  };\n
+\n
+  var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-";\n
+\n
+  cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) {\n
+    var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var range = ranges[i], from = range.from().line - 1, to = range.to().line;\n
+      newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch),\n
+                    head: Pos(range.head.line - 1, range.head.ch)});\n
+      if (range.to().ch == 0 && !range.empty()) --to;\n
+      if (from > at) linesToMove.push(from, to);\n
+      else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;\n
+      at = to;\n
+    }\n
+    cm.operation(function() {\n
+      for (var i = 0; i < linesToMove.length; i += 2) {\n
+        var from = linesToMove[i], to = linesToMove[i + 1];\n
+        var line = cm.getLine(from);\n
+        cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");\n
+        if (to > cm.lastLine())\n
+          cm.replaceRange("\\n" + line, Pos(cm.lastLine()), null, "+swapLine");\n
+        else\n
+          cm.replaceRange(line + "\\n", Pos(to, 0), null, "+swapLine");\n
+      }\n
+      cm.setSelections(newSels);\n
+      cm.scrollIntoView();\n
+    });\n
+  };\n
+\n
+  cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) {\n
+    var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;\n
+    for (var i = ranges.length - 1; i >= 0; i--) {\n
+      var range = ranges[i], from = range.to().line + 1, to = range.from().line;\n
+      if (range.to().ch == 0 && !range.empty()) from--;\n
+      if (from < at) linesToMove.push(from, to);\n
+      else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;\n
+      at = to;\n
+    }\n
+    cm.operation(function() {\n
+      for (var i = linesToMove.length - 2; i >= 0; i -= 2) {\n
+        var from = linesToMove[i], to = linesToMove[i + 1];\n
+        var line = cm.getLine(from);\n
+        if (from == cm.lastLine())\n
+          cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine");\n
+        else\n
+          cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");\n
+        cm.replaceRange(line + "\\n", Pos(to, 0), null, "+swapLine");\n
+      }\n
+      cm.scrollIntoView();\n
+    });\n
+  };\n
+\n
+  map[ctrl + "/"] = "toggleComment";\n
+\n
+  cmds[map[ctrl + "J"] = "joinLines"] = function(cm) {\n
+    var ranges = cm.listSelections(), joined = [];\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var range = ranges[i], from = range.from();\n
+      var start = from.line, end = range.to().line;\n
+      while (i < ranges.length - 1 && ranges[i + 1].from().line == end)\n
+        end = ranges[++i].to().line;\n
+      joined.push({start: start, end: end, anchor: !range.empty() && from});\n
+    }\n
+    cm.operation(function() {\n
+      var offset = 0, ranges = [];\n
+      for (var i = 0; i < joined.length; i++) {\n
+        var obj = joined[i];\n
+        var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head;\n
+        for (var line = obj.start; line <= obj.end; line++) {\n
+          var actual = line - offset;\n
+          if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1);\n
+          if (actual < cm.lastLine()) {\n
+            cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\\s*/.exec(cm.getLine(actual + 1))[0].length));\n
+            ++offset;\n
+          }\n
+        }\n
+        ranges.push({anchor: anchor || head, head: head});\n
+      }\n
+      cm.setSelections(ranges, 0);\n
+    });\n
+  };\n
+\n
+  cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) {\n
+    cm.operation(function() {\n
+      var rangeCount = cm.listSelections().length;\n
+      for (var i = 0; i < rangeCount; i++) {\n
+        var range = cm.listSelections()[i];\n
+        if (range.empty())\n
+          cm.replaceRange(cm.getLine(range.head.line) + "\\n", Pos(range.head.line, 0));\n
+        else\n
+          cm.replaceRange(cm.getRange(range.from(), range.to()), range.from());\n
+      }\n
+      cm.scrollIntoView();\n
+    });\n
+  };\n
+\n
+  map[ctrl + "T"] = "transposeChars";\n
+\n
+  function sortLines(cm, caseSensitive) {\n
+    var ranges = cm.listSelections(), toSort = [], selected;\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var range = ranges[i];\n
+      if (range.empty()) continue;\n
+      var from = range.from().line, to = range.to().line;\n
+      while (i < ranges.length - 1 && ranges[i + 1].from().line == to)\n
+        to = range[++i].to().line;\n
+      toSort.push(from, to);\n
+    }\n
+    if (toSort.length) selected = true;\n
+    else toSort.push(cm.firstLine(), cm.lastLine());\n
+\n
+    cm.operation(function() {\n
+      var ranges = [];\n
+      for (var i = 0; i < toSort.length; i += 2) {\n
+        var from = toSort[i], to = toSort[i + 1];\n
+        var start = Pos(from, 0), end = Pos(to);\n
+        var lines = cm.getRange(start, end, false);\n
+        if (caseSensitive)\n
+          lines.sort();\n
+        else\n
+          lines.sort(function(a, b) {\n
+            var au = a.toUpperCase(), bu = b.toUpperCase();\n
+            if (au != bu) { a = au; b = bu; }\n
+            return a < b ? -1 : a == b ? 0 : 1;\n
+          });\n
+        cm.replaceRange(lines, start, end);\n
+        if (selected) ranges.push({anchor: start, head: end});\n
+      }\n
+      if (selected) cm.setSelections(ranges, 0);\n
+    });\n
+  }\n
+\n
+  cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); };\n
+  cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); };\n
+\n
+  cmds[map["F2"] = "nextBookmark"] = function(cm) {\n
+    var marks = cm.state.sublimeBookmarks;\n
+    if (marks) while (marks.length) {\n
+      var current = marks.shift();\n
+      var found = current.find();\n
+      if (found) {\n
+        marks.push(current);\n
+        return cm.setSelection(found.from, found.to);\n
+      }\n
+    }\n
+  };\n
+\n
+  cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) {\n
+    var marks = cm.state.sublimeBookmarks;\n
+    if (marks) while (marks.length) {\n
+      marks.unshift(marks.pop());\n
+      var found = marks[marks.length - 1].find();\n
+      if (!found)\n
+        marks.pop();\n
+      else\n
+        return cm.setSelection(found.from, found.to);\n
+    }\n
+  };\n
+\n
+  cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) {\n
+    var ranges = cm.listSelections();\n
+    var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []);\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var from = ranges[i].from(), to = ranges[i].to();\n
+      var found = cm.findMarks(from, to);\n
+      for (var j = 0; j < found.length; j++) {\n
+        if (found[j].sublimeBookmark) {\n
+          found[j].clear();\n
+          for (var k = 0; k < marks.length; k++)\n
+            if (marks[k] == found[j])\n
+              marks.splice(k--, 1);\n
+          break;\n
+        }\n
+      }\n
+      if (j == found.length)\n
+        marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false}));\n
+    }\n
+  };\n
+\n
+  cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) {\n
+    var marks = cm.state.sublimeBookmarks;\n
+    if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear();\n
+    marks.length = 0;\n
+  };\n
+\n
+  cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) {\n
+    var marks = cm.state.sublimeBookmarks, ranges = [];\n
+    if (marks) for (var i = 0; i < marks.length; i++) {\n
+      var found = marks[i].find();\n
+      if (!found)\n
+        marks.splice(i--, 0);\n
+      else\n
+        ranges.push({anchor: found.from, head: found.to});\n
+    }\n
+    if (ranges.length)\n
+      cm.setSelections(ranges, 0);\n
+  };\n
+\n
+  map["Alt-Q"] = "wrapLines";\n
+\n
+  var cK = ctrl + "K ";\n
+\n
+  function modifyWordOrSelection(cm, mod) {\n
+    cm.operation(function() {\n
+      var ranges = cm.listSelections(), indices = [], replacements = [];\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var range = ranges[i];\n
+        if (range.empty()) { indices.push(i); replacements.push(""); }\n
+        else replacements.push(mod(cm.getRange(range.from(), range.to())));\n
+      }\n
+      cm.replaceSelections(replacements, "around", "case");\n
+      for (var i = indices.length - 1, at; i >= 0; i--) {\n
+        var range = ranges[indices[i]];\n
+        if (at && CodeMirror.cmpPos(range.head, at) > 0) continue;\n
+        var word = wordAt(cm, range.head);\n
+        at = word.from;\n
+        cm.replaceRange(mod(word.word), word.from, word.to);\n
+      }\n
+    });\n
+  }\n
+\n
+  map[cK + ctrl + "Backspace"] = "delLineLeft";\n
+\n
+  cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {\n
+    cm.operation(function() {\n
+      var ranges = cm.listSelections();\n
+      for (var i = ranges.length - 1; i >= 0; i--)\n
+        cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete");\n
+      cm.scrollIntoView();\n
+    });\n
+  };\n
+\n
+  cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) {\n
+    modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });\n
+  };\n
+  cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) {\n
+    modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });\n
+  };\n
+\n
+  cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) {\n
+    if (cm.state.sublimeMark) cm.state.sublimeMark.clear();\n
+    cm.state.sublimeMark = cm.setBookmark(cm.getCursor());\n
+  };\n
+  cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) {\n
+    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();\n
+    if (found) cm.setSelection(cm.getCursor(), found);\n
+  };\n
+  cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {\n
+    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();\n
+    if (found) {\n
+      var from = cm.getCursor(), to = found;\n
+      if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; }\n
+      cm.state.sublimeKilled = cm.getRange(from, to);\n
+      cm.replaceRange("", from, to);\n
+    }\n
+  };\n
+  cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {\n
+    var found = cm.state.sublimeMark && cm.state.sublimeMark.find();\n
+    if (found) {\n
+      cm.state.sublimeMark.clear();\n
+      cm.state.sublimeMark = cm.setBookmark(cm.getCursor());\n
+      cm.setCursor(found);\n
+    }\n
+  };\n
+  cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) {\n
+    if (cm.state.sublimeKilled != null)\n
+      cm.replaceSelection(cm.state.sublimeKilled, null, "paste");\n
+  };\n
+\n
+  map[cK + ctrl + "G"] = "clearBookmarks";\n
+  cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) {\n
+    var pos = cm.cursorCoords(null, "local");\n
+    cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);\n
+  };\n
+\n
+  cmds[map["Shift-Alt-Up"] = "selectLinesUpward"] = function(cm) {\n
+    cm.operation(function() {\n
+      var ranges = cm.listSelections();\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var range = ranges[i];\n
+        if (range.head.line > cm.firstLine())\n
+          cm.addSelection(Pos(range.head.line - 1, range.head.ch));\n
+      }\n
+    });\n
+  };\n
+  cmds[map["Shift-Alt-Down"] = "selectLinesDownward"] = function(cm) {\n
+    cm.operation(function() {\n
+      var ranges = cm.listSelections();\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var range = ranges[i];\n
+        if (range.head.line < cm.lastLine())\n
+          cm.addSelection(Pos(range.head.line + 1, range.head.ch));\n
+      }\n
+    });\n
+  };\n
+\n
+  function getTarget(cm) {\n
+    var from = cm.getCursor("from"), to = cm.getCursor("to");\n
+    if (CodeMirror.cmpPos(from, to) == 0) {\n
+      var word = wordAt(cm, from);\n
+      if (!word.word) return;\n
+      from = word.from;\n
+      to = word.to;\n
+    }\n
+    return {from: from, to: to, query: cm.getRange(from, to), word: word};\n
+  }\n
+\n
+  function findAndGoTo(cm, forward) {\n
+    var target = getTarget(cm);\n
+    if (!target) return;\n
+    var query = target.query;\n
+    var cur = cm.getSearchCursor(query, forward ? target.to : target.from);\n
+\n
+    if (forward ? cur.findNext() : cur.findPrevious()) {\n
+      cm.setSelection(cur.from(), cur.to());\n
+    } else {\n
+      cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0)\n
+                                              : cm.clipPos(Pos(cm.lastLine())));\n
+      if (forward ? cur.findNext() : cur.findPrevious())\n
+        cm.setSelection(cur.from(), cur.to());\n
+      else if (target.word)\n
+        cm.setSelection(target.from, target.to);\n
+    }\n
+  };\n
+  cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); };\n
+  cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); };\n
+  cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) {\n
+    var target = getTarget(cm);\n
+    if (!target) return;\n
+    var cur = cm.getSearchCursor(target.query);\n
+    var matches = [];\n
+    var primaryIndex = -1;\n
+    while (cur.findNext()) {\n
+      matches.push({anchor: cur.from(), head: cur.to()});\n
+      if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)\n
+        primaryIndex++;\n
+    }\n
+    cm.setSelections(matches, primaryIndex);\n
+  };\n
+\n
+  map["Shift-" + ctrl + "["] = "fold";\n
+  map["Shift-" + ctrl + "]"] = "unfold";\n
+  map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll";\n
+\n
+  map[ctrl + "I"] = "findIncremental";\n
+  map["Shift-" + ctrl + "I"] = "findIncrementalReverse";\n
+  map[ctrl + "H"] = "replace";\n
+  map["F3"] = "findNext";\n
+  map["Shift-F3"] = "findPrev";\n
+\n
+  CodeMirror.normalizeKeyMap(map);\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>20403</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/vim.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/vim.js.xml
index 1ec2b76e31894bb409fbab13f3aa7215d949842c..48207154e8e081f68f18494a2e1bb189f76b621c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/vim.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/keymap/vim.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403085.43</string> </value>
+            <value> <string>ts21897131.38</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -30,7 +30,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>145020</int> </value>
+            <value> <int>191805</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
@@ -49,6 +49,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Supported keybindings:\n
  *\n
@@ -83,7 +86,7 @@
  *   ESC - leave insert mode, visual mode, and clear input state.\n
  *   Ctrl-[, Ctrl-c - same as ESC.\n
  *\n
- * Registers: unamed, -, a-z, A-Z, 0-9\n
+ * Registers: unnamed, -, a-z, A-Z, 0-9\n
  *   (Does not respect the special case for number registers when delete\n
  *    operator is made with these commands: %, (, ),  , /, ?, n, N, {, } )\n
  *   TODO: Implement the remaining registers.\n
@@ -107,303 +110,269 @@
  *  8. Set up Vim to work as a keymap for CodeMirror.\n
  */\n
 \n
-(function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/dialog/dialog"), require("../addon/edit/matchbrackets.js"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
   \'use strict\';\n
 \n
   var defaultKeymap = [\n
     // Key to key mapping. This goes first to make it possible to override\n
     // existing mappings.\n
-    { keys: [\'<Left>\'], type: \'keyToKey\', toKeys: [\'h\'] },\n
-    { keys: [\'<Right>\'], type: \'keyToKey\', toKeys: [\'l\'] },\n
-    { keys: [\'<Up>\'], type: \'keyToKey\', toKeys: [\'k\'] },\n
-    { keys: [\'<Down>\'], type: \'keyToKey\', toKeys: [\'j\'] },\n
-    { keys: [\'<Space>\'], type: \'keyToKey\', toKeys: [\'l\'] },\n
-    { keys: [\'<BS>\'], type: \'keyToKey\', toKeys: [\'h\'] },\n
-    { keys: [\'<C-Space>\'], type: \'keyToKey\', toKeys: [\'W\'] },\n
-    { keys: [\'<C-BS>\'], type: \'keyToKey\', toKeys: [\'B\'] },\n
-    { keys: [\'<S-Space>\'], type: \'keyToKey\', toKeys: [\'w\'] },\n
-    { keys: [\'<S-BS>\'], type: \'keyToKey\', toKeys: [\'b\'] },\n
-    { keys: [\'<C-n>\'], type: \'keyToKey\', toKeys: [\'j\'] },\n
-    { keys: [\'<C-p>\'], type: \'keyToKey\', toKeys: [\'k\'] },\n
-    { keys: [\'<C-[>\'], type: \'keyToKey\', toKeys: [\'<Esc>\'] },\n
-    { keys: [\'<C-c>\'], type: \'keyToKey\', toKeys: [\'<Esc>\'] },\n
-    { keys: [\'s\'], type: \'keyToKey\', toKeys: [\'c\', \'l\'], context: \'normal\' },\n
-    { keys: [\'s\'], type: \'keyToKey\', toKeys: [\'x\', \'i\'], context: \'visual\'},\n
-    { keys: [\'S\'], type: \'keyToKey\', toKeys: [\'c\', \'c\'], context: \'normal\' },\n
-    { keys: [\'S\'], type: \'keyToKey\', toKeys: [\'d\', \'c\', \'c\'], context: \'visual\' },\n
-    { keys: [\'<Home>\'], type: \'keyToKey\', toKeys: [\'0\'] },\n
-    { keys: [\'<End>\'], type: \'keyToKey\', toKeys: [\'$\'] },\n
-    { keys: [\'<PageUp>\'], type: \'keyToKey\', toKeys: [\'<C-b>\'] },\n
-    { keys: [\'<PageDown>\'], type: \'keyToKey\', toKeys: [\'<C-f>\'] },\n
-    { keys: [\'<CR>\'], type: \'keyToKey\', toKeys: [\'j\', \'^\'], context: \'normal\' },\n
+    { keys: \'<Left>\', type: \'keyToKey\', toKeys: \'h\' },\n
+    { keys: \'<Right>\', type: \'keyToKey\', toKeys: \'l\' },\n
+    { keys: \'<Up>\', type: \'keyToKey\', toKeys: \'k\' },\n
+    { keys: \'<Down>\', type: \'keyToKey\', toKeys: \'j\' },\n
+    { keys: \'<Space>\', type: \'keyToKey\', toKeys: \'l\' },\n
+    { keys: \'<BS>\', type: \'keyToKey\', toKeys: \'h\', context: \'normal\'},\n
+    { keys: \'<C-Space>\', type: \'keyToKey\', toKeys: \'W\' },\n
+    { keys: \'<C-BS>\', type: \'keyToKey\', toKeys: \'B\', context: \'normal\' },\n
+    { keys: \'<S-Space>\', type: \'keyToKey\', toKeys: \'w\' },\n
+    { keys: \'<S-BS>\', type: \'keyToKey\', toKeys: \'b\', context: \'normal\' },\n
+    { keys: \'<C-n>\', type: \'keyToKey\', toKeys: \'j\' },\n
+    { keys: \'<C-p>\', type: \'keyToKey\', toKeys: \'k\' },\n
+    { keys: \'<C-[>\', type: \'keyToKey\', toKeys: \'<Esc>\' },\n
+    { keys: \'<C-c>\', type: \'keyToKey\', toKeys: \'<Esc>\' },\n
+    { keys: \'<C-[>\', type: \'keyToKey\', toKeys: \'<Esc>\', context: \'insert\' },\n
+    { keys: \'<C-c>\', type: \'keyToKey\', toKeys: \'<Esc>\', context: \'insert\' },\n
+    { keys: \'s\', type: \'keyToKey\', toKeys: \'cl\', context: \'normal\' },\n
+    { keys: \'s\', type: \'keyToKey\', toKeys: \'xi\', context: \'visual\'},\n
+    { keys: \'S\', type: \'keyToKey\', toKeys: \'cc\', context: \'normal\' },\n
+    { keys: \'S\', type: \'keyToKey\', toKeys: \'dcc\', context: \'visual\' },\n
+    { keys: \'<Home>\', type: \'keyToKey\', toKeys: \'0\' },\n
+    { keys: \'<End>\', type: \'keyToKey\', toKeys: \'$\' },\n
+    { keys: \'<PageUp>\', type: \'keyToKey\', toKeys: \'<C-b>\' },\n
+    { keys: \'<PageDown>\', type: \'keyToKey\', toKeys: \'<C-f>\' },\n
+    { keys: \'<CR>\', type: \'keyToKey\', toKeys: \'j^\', context: \'normal\' },\n
     // Motions\n
-    { keys: [\'H\'], type: \'motion\',\n
-        motion: \'moveToTopLine\',\n
-        motionArgs: { linewise: true, toJumplist: true }},\n
-    { keys: [\'M\'], type: \'motion\',\n
-        motion: \'moveToMiddleLine\',\n
-        motionArgs: { linewise: true, toJumplist: true }},\n
-    { keys: [\'L\'], type: \'motion\',\n
-        motion: \'moveToBottomLine\',\n
-        motionArgs: { linewise: true, toJumplist: true }},\n
-    { keys: [\'h\'], type: \'motion\',\n
-        motion: \'moveByCharacters\',\n
-        motionArgs: { forward: false }},\n
-    { keys: [\'l\'], type: \'motion\',\n
-        motion: \'moveByCharacters\',\n
-        motionArgs: { forward: true }},\n
-    { keys: [\'j\'], type: \'motion\',\n
-        motion: \'moveByLines\',\n
-        motionArgs: { forward: true, linewise: true }},\n
-    { keys: [\'k\'], type: \'motion\',\n
-        motion: \'moveByLines\',\n
-        motionArgs: { forward: false, linewise: true }},\n
-    { keys: [\'g\',\'j\'], type: \'motion\',\n
-        motion: \'moveByDisplayLines\',\n
-        motionArgs: { forward: true }},\n
-    { keys: [\'g\',\'k\'], type: \'motion\',\n
-        motion: \'moveByDisplayLines\',\n
-        motionArgs: { forward: false }},\n
-    { keys: [\'w\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: true, wordEnd: false }},\n
-    { keys: [\'W\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: true, wordEnd: false, bigWord: true }},\n
-    { keys: [\'e\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: true, wordEnd: true, inclusive: true }},\n
-    { keys: [\'E\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: true, wordEnd: true, bigWord: true,\n
-            inclusive: true }},\n
-    { keys: [\'b\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: false, wordEnd: false }},\n
-    { keys: [\'B\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: false, wordEnd: false, bigWord: true }},\n
-    { keys: [\'g\', \'e\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: false, wordEnd: true, inclusive: true }},\n
-    { keys: [\'g\', \'E\'], type: \'motion\',\n
-        motion: \'moveByWords\',\n
-        motionArgs: { forward: false, wordEnd: true, bigWord: true,\n
-            inclusive: true }},\n
-    { keys: [\'{\'], type: \'motion\', motion: \'moveByParagraph\',\n
-        motionArgs: { forward: false, toJumplist: true }},\n
-    { keys: [\'}\'], type: \'motion\', motion: \'moveByParagraph\',\n
-        motionArgs: { forward: true, toJumplist: true }},\n
-    { keys: [\'<C-f>\'], type: \'motion\',\n
-        motion: \'moveByPage\', motionArgs: { forward: true }},\n
-    { keys: [\'<C-b>\'], type: \'motion\',\n
-        motion: \'moveByPage\', motionArgs: { forward: false }},\n
-    { keys: [\'<C-d>\'], type: \'motion\',\n
-        motion: \'moveByScroll\',\n
-        motionArgs: { forward: true, explicitRepeat: true }},\n
-    { keys: [\'<C-u>\'], type: \'motion\',\n
-        motion: \'moveByScroll\',\n
-        motionArgs: { forward: false, explicitRepeat: true }},\n
-    { keys: [\'g\', \'g\'], type: \'motion\',\n
-        motion: \'moveToLineOrEdgeOfDocument\',\n
-        motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }},\n
-    { keys: [\'G\'], type: \'motion\',\n
-        motion: \'moveToLineOrEdgeOfDocument\',\n
-        motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }},\n
-    { keys: [\'0\'], type: \'motion\', motion: \'moveToStartOfLine\' },\n
-    { keys: [\'^\'], type: \'motion\',\n
-        motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
-    { keys: [\'+\'], type: \'motion\',\n
-        motion: \'moveByLines\',\n
-        motionArgs: { forward: true, toFirstChar:true }},\n
-    { keys: [\'-\'], type: \'motion\',\n
-        motion: \'moveByLines\',\n
-        motionArgs: { forward: false, toFirstChar:true }},\n
-    { keys: [\'_\'], type: \'motion\',\n
-        motion: \'moveByLines\',\n
-        motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }},\n
-    { keys: [\'$\'], type: \'motion\',\n
-        motion: \'moveToEol\',\n
-        motionArgs: { inclusive: true }},\n
-    { keys: [\'%\'], type: \'motion\',\n
-        motion: \'moveToMatchedSymbol\',\n
-        motionArgs: { inclusive: true, toJumplist: true }},\n
-    { keys: [\'f\', \'character\'], type: \'motion\',\n
-        motion: \'moveToCharacter\',\n
-        motionArgs: { forward: true , inclusive: true }},\n
-    { keys: [\'F\', \'character\'], type: \'motion\',\n
-        motion: \'moveToCharacter\',\n
-        motionArgs: { forward: false }},\n
-    { keys: [\'t\', \'character\'], type: \'motion\',\n
-        motion: \'moveTillCharacter\',\n
-        motionArgs: { forward: true, inclusive: true }},\n
-    { keys: [\'T\', \'character\'], type: \'motion\',\n
-        motion: \'moveTillCharacter\',\n
-        motionArgs: { forward: false }},\n
-    { keys: [\';\'], type: \'motion\', motion: \'repeatLastCharacterSearch\',\n
-        motionArgs: { forward: true }},\n
-    { keys: [\',\'], type: \'motion\', motion: \'repeatLastCharacterSearch\',\n
-        motionArgs: { forward: false }},\n
-    { keys: [\'\\\'\', \'character\'], type: \'motion\', motion: \'goToMark\',\n
-        motionArgs: {toJumplist: true}},\n
-    { keys: [\'`\', \'character\'], type: \'motion\', motion: \'goToMark\',\n
-        motionArgs: {toJumplist: true}},\n
-    { keys: [\']\', \'`\'], type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: true } },\n
-    { keys: [\'[\', \'`\'], type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: false } },\n
-    { keys: [\']\', \'\\\'\'], type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: true, linewise: true } },\n
-    { keys: [\'[\', \'\\\'\'], type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: false, linewise: true } },\n
-    { keys: [\']\', \'character\'], type: \'motion\',\n
-        motion: \'moveToSymbol\',\n
-        motionArgs: { forward: true, toJumplist: true}},\n
-    { keys: [\'[\', \'character\'], type: \'motion\',\n
-        motion: \'moveToSymbol\',\n
-        motionArgs: { forward: false, toJumplist: true}},\n
-    { keys: [\'|\'], type: \'motion\',\n
-        motion: \'moveToColumn\',\n
-        motionArgs: { }},\n
+    { keys: \'H\', type: \'motion\', motion: \'moveToTopLine\', motionArgs: { linewise: true, toJumplist: true }},\n
+    { keys: \'M\', type: \'motion\', motion: \'moveToMiddleLine\', motionArgs: { linewise: true, toJumplist: true }},\n
+    { keys: \'L\', type: \'motion\', motion: \'moveToBottomLine\', motionArgs: { linewise: true, toJumplist: true }},\n
+    { keys: \'h\', type: \'motion\', motion: \'moveByCharacters\', motionArgs: { forward: false }},\n
+    { keys: \'l\', type: \'motion\', motion: \'moveByCharacters\', motionArgs: { forward: true }},\n
+    { keys: \'j\', type: \'motion\', motion: \'moveByLines\', motionArgs: { forward: true, linewise: true }},\n
+    { keys: \'k\', type: \'motion\', motion: \'moveByLines\', motionArgs: { forward: false, linewise: true }},\n
+    { keys: \'gj\', type: \'motion\', motion: \'moveByDisplayLines\', motionArgs: { forward: true }},\n
+    { keys: \'gk\', type: \'motion\', motion: \'moveByDisplayLines\', motionArgs: { forward: false }},\n
+    { keys: \'w\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: true, wordEnd: false }},\n
+    { keys: \'W\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: true, wordEnd: false, bigWord: true }},\n
+    { keys: \'e\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: true, wordEnd: true, inclusive: true }},\n
+    { keys: \'E\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }},\n
+    { keys: \'b\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: false, wordEnd: false }},\n
+    { keys: \'B\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: false, wordEnd: false, bigWord: true }},\n
+    { keys: \'ge\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: false, wordEnd: true, inclusive: true }},\n
+    { keys: \'gE\', type: \'motion\', motion: \'moveByWords\', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }},\n
+    { keys: \'{\', type: \'motion\', motion: \'moveByParagraph\', motionArgs: { forward: false, toJumplist: true }},\n
+    { keys: \'}\', type: \'motion\', motion: \'moveByParagraph\', motionArgs: { forward: true, toJumplist: true }},\n
+    { keys: \'<C-f>\', type: \'motion\', motion: \'moveByPage\', motionArgs: { forward: true }},\n
+    { keys: \'<C-b>\', type: \'motion\', motion: \'moveByPage\', motionArgs: { forward: false }},\n
+    { keys: \'<C-d>\', type: \'motion\', motion: \'moveByScroll\', motionArgs: { forward: true, explicitRepeat: true }},\n
+    { keys: \'<C-u>\', type: \'motion\', motion: \'moveByScroll\', motionArgs: { forward: false, explicitRepeat: true }},\n
+    { keys: \'gg\', type: \'motion\', motion: \'moveToLineOrEdgeOfDocument\', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }},\n
+    { keys: \'G\', type: \'motion\', motion: \'moveToLineOrEdgeOfDocument\', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }},\n
+    { keys: \'0\', type: \'motion\', motion: \'moveToStartOfLine\' },\n
+    { keys: \'^\', type: \'motion\', motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
+    { keys: \'+\', type: \'motion\', motion: \'moveByLines\', motionArgs: { forward: true, toFirstChar:true }},\n
+    { keys: \'-\', type: \'motion\', motion: \'moveByLines\', motionArgs: { forward: false, toFirstChar:true }},\n
+    { keys: \'_\', type: \'motion\', motion: \'moveByLines\', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }},\n
+    { keys: \'$\', type: \'motion\', motion: \'moveToEol\', motionArgs: { inclusive: true }},\n
+    { keys: \'%\', type: \'motion\', motion: \'moveToMatchedSymbol\', motionArgs: { inclusive: true, toJumplist: true }},\n
+    { keys: \'f<character>\', type: \'motion\', motion: \'moveToCharacter\', motionArgs: { forward: true , inclusive: true }},\n
+    { keys: \'F<character>\', type: \'motion\', motion: \'moveToCharacter\', motionArgs: { forward: false }},\n
+    { keys: \'t<character>\', type: \'motion\', motion: \'moveTillCharacter\', motionArgs: { forward: true, inclusive: true }},\n
+    { keys: \'T<character>\', type: \'motion\', motion: \'moveTillCharacter\', motionArgs: { forward: false }},\n
+    { keys: \';\', type: \'motion\', motion: \'repeatLastCharacterSearch\', motionArgs: { forward: true }},\n
+    { keys: \',\', type: \'motion\', motion: \'repeatLastCharacterSearch\', motionArgs: { forward: false }},\n
+    { keys: \'\\\'<character>\', type: \'motion\', motion: \'goToMark\', motionArgs: {toJumplist: true, linewise: true}},\n
+    { keys: \'`<character>\', type: \'motion\', motion: \'goToMark\', motionArgs: {toJumplist: true}},\n
+    { keys: \']`\', type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: true } },\n
+    { keys: \'[`\', type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: false } },\n
+    { keys: \']\\\'\', type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: true, linewise: true } },\n
+    { keys: \'[\\\'\', type: \'motion\', motion: \'jumpToMark\', motionArgs: { forward: false, linewise: true } },\n
+    // the next two aren\'t motions but must come before more general motion declarations\n
+    { keys: \']p\', type: \'action\', action: \'paste\', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}},\n
+    { keys: \'[p\', type: \'action\', action: \'paste\', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}},\n
+    { keys: \']<character>\', type: \'motion\', motion: \'moveToSymbol\', motionArgs: { forward: true, toJumplist: true}},\n
+    { keys: \'[<character>\', type: \'motion\', motion: \'moveToSymbol\', motionArgs: { forward: false, toJumplist: true}},\n
+    { keys: \'|\', type: \'motion\', motion: \'moveToColumn\'},\n
+    { keys: \'o\', type: \'motion\', motion: \'moveToOtherHighlightedEnd\', context:\'visual\'},\n
+    { keys: \'O\', type: \'motion\', motion: \'moveToOtherHighlightedEnd\', motionArgs: {sameLine: true}, context:\'visual\'},\n
     // Operators\n
-    { keys: [\'d\'], type: \'operator\', operator: \'delete\' },\n
-    { keys: [\'y\'], type: \'operator\', operator: \'yank\' },\n
-    { keys: [\'c\'], type: \'operator\', operator: \'change\' },\n
-    { keys: [\'>\'], type: \'operator\', operator: \'indent\',\n
-        operatorArgs: { indentRight: true }},\n
-    { keys: [\'<\'], type: \'operator\', operator: \'indent\',\n
-        operatorArgs: { indentRight: false }},\n
-    { keys: [\'g\', \'~\'], type: \'operator\', operator: \'swapcase\' },\n
-    { keys: [\'n\'], type: \'motion\', motion: \'findNext\',\n
-        motionArgs: { forward: true, toJumplist: true }},\n
-    { keys: [\'N\'], type: \'motion\', motion: \'findNext\',\n
-        motionArgs: { forward: false, toJumplist: true }},\n
+    { keys: \'d\', type: \'operator\', operator: \'delete\' },\n
+    { keys: \'y\', type: \'operator\', operator: \'yank\' },\n
+    { keys: \'c\', type: \'operator\', operator: \'change\' },\n
+    { keys: \'>\', type: \'operator\', operator: \'indent\', operatorArgs: { indentRight: true }},\n
+    { keys: \'<\', type: \'operator\', operator: \'indent\', operatorArgs: { indentRight: false }},\n
+    { keys: \'g~\', type: \'operator\', operator: \'changeCase\' },\n
+    { keys: \'gu\', type: \'operator\', operator: \'changeCase\', operatorArgs: {toLower: true}, isEdit: true },\n
+    { keys: \'gU\', type: \'operator\', operator: \'changeCase\', operatorArgs: {toLower: false}, isEdit: true },\n
+    { keys: \'n\', type: \'motion\', motion: \'findNext\', motionArgs: { forward: true, toJumplist: true }},\n
+    { keys: \'N\', type: \'motion\', motion: \'findNext\', motionArgs: { forward: false, toJumplist: true }},\n
     // Operator-Motion dual commands\n
-    { keys: [\'x\'], type: \'operatorMotion\', operator: \'delete\',\n
-        motion: \'moveByCharacters\', motionArgs: { forward: true },\n
-        operatorMotionArgs: { visualLine: false }},\n
-    { keys: [\'X\'], type: \'operatorMotion\', operator: \'delete\',\n
-        motion: \'moveByCharacters\', motionArgs: { forward: false },\n
-        operatorMotionArgs: { visualLine: true }},\n
-    { keys: [\'D\'], type: \'operatorMotion\', operator: \'delete\',\n
-      motion: \'moveToEol\', motionArgs: { inclusive: true },\n
-        operatorMotionArgs: { visualLine: true }},\n
-    { keys: [\'Y\'], type: \'operatorMotion\', operator: \'yank\',\n
-        motion: \'moveToEol\', motionArgs: { inclusive: true },\n
-        operatorMotionArgs: { visualLine: true }},\n
-    { keys: [\'C\'], type: \'operatorMotion\',\n
-        operator: \'change\',\n
-        motion: \'moveToEol\', motionArgs: { inclusive: true },\n
-        operatorMotionArgs: { visualLine: true }},\n
-    { keys: [\'~\'], type: \'operatorMotion\',\n
-        operator: \'swapcase\', operatorArgs: { shouldMoveCursor: true },\n
-        motion: \'moveByCharacters\', motionArgs: { forward: true }},\n
+    { keys: \'x\', type: \'operatorMotion\', operator: \'delete\', motion: \'moveByCharacters\', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }},\n
+    { keys: \'X\', type: \'operatorMotion\', operator: \'delete\', motion: \'moveByCharacters\', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},\n
+    { keys: \'D\', type: \'operatorMotion\', operator: \'delete\', motion: \'moveToEol\', motionArgs: { inclusive: true }, context: \'normal\'},\n
+    { keys: \'D\', type: \'operator\', operator: \'delete\', operatorArgs: { linewise: true }, context: \'visual\'},\n
+    { keys: \'Y\', type: \'operatorMotion\', operator: \'yank\', motion: \'moveToEol\', motionArgs: { inclusive: true }, context: \'normal\'},\n
+    { keys: \'Y\', type: \'operator\', operator: \'yank\', operatorArgs: { linewise: true }, context: \'visual\'},\n
+    { keys: \'C\', type: \'operatorMotion\', operator: \'change\', motion: \'moveToEol\', motionArgs: { inclusive: true }, context: \'normal\'},\n
+    { keys: \'C\', type: \'operator\', operator: \'change\', operatorArgs: { linewise: true }, context: \'visual\'},\n
+    { keys: \'~\', type: \'operatorMotion\', operator: \'changeCase\', motion: \'moveByCharacters\', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: \'normal\'},\n
+    { keys: \'~\', type: \'operator\', operator: \'changeCase\', context: \'visual\'},\n
+    { keys: \'<C-w>\', type: \'operatorMotion\', operator: \'delete\', motion: \'moveByWords\', motionArgs: { forward: false, wordEnd: false }, context: \'insert\' },\n
     // Actions\n
-    { keys: [\'<C-i>\'], type: \'action\', action: \'jumpListWalk\',\n
-        actionArgs: { forward: true }},\n
-    { keys: [\'<C-o>\'], type: \'action\', action: \'jumpListWalk\',\n
-        actionArgs: { forward: false }},\n
-    { keys: [\'<C-e>\'], type: \'action\',\n
-        action: \'scroll\',\n
-        actionArgs: { forward: true, linewise: true }},\n
-    { keys: [\'<C-y>\'], type: \'action\',\n
-        action: \'scroll\',\n
-        actionArgs: { forward: false, linewise: true }},\n
-    { keys: [\'a\'], type: \'action\', action: \'enterInsertMode\', isEdit: true,\n
-        actionArgs: { insertAt: \'charAfter\' }},\n
-    { keys: [\'A\'], type: \'action\', action: \'enterInsertMode\', isEdit: true,\n
-        actionArgs: { insertAt: \'eol\' }},\n
-    { keys: [\'i\'], type: \'action\', action: \'enterInsertMode\', isEdit: true,\n
-        actionArgs: { insertAt: \'inplace\' }},\n
-    { keys: [\'I\'], type: \'action\', action: \'enterInsertMode\', isEdit: true,\n
-        actionArgs: { insertAt: \'firstNonBlank\' }},\n
-    { keys: [\'o\'], type: \'action\', action: \'newLineAndEnterInsertMode\',\n
-        isEdit: true, interlaceInsertRepeat: true,\n
-        actionArgs: { after: true }},\n
-    { keys: [\'O\'], type: \'action\', action: \'newLineAndEnterInsertMode\',\n
-        isEdit: true, interlaceInsertRepeat: true,\n
-        actionArgs: { after: false }},\n
-    { keys: [\'v\'], type: \'action\', action: \'toggleVisualMode\' },\n
-    { keys: [\'V\'], type: \'action\', action: \'toggleVisualMode\',\n
-        actionArgs: { linewise: true }},\n
-    { keys: [\'J\'], type: \'action\', action: \'joinLines\', isEdit: true },\n
-    { keys: [\'p\'], type: \'action\', action: \'paste\', isEdit: true,\n
-        actionArgs: { after: true, isEdit: true }},\n
-    { keys: [\'P\'], type: \'action\', action: \'paste\', isEdit: true,\n
-        actionArgs: { after: false, isEdit: true }},\n
-    { keys: [\'r\', \'character\'], type: \'action\', action: \'replace\', isEdit: true },\n
-    { keys: [\'@\', \'character\'], type: \'action\', action: \'replayMacro\' },\n
-    { keys: [\'q\', \'character\'], type: \'action\', action: \'enterMacroRecordMode\' },\n
+    { keys: \'<C-i>\', type: \'action\', action: \'jumpListWalk\', actionArgs: { forward: true }},\n
+    { keys: \'<C-o>\', type: \'action\', action: \'jumpListWalk\', actionArgs: { forward: false }},\n
+    { keys: \'<C-e>\', type: \'action\', action: \'scroll\', actionArgs: { forward: true, linewise: true }},\n
+    { keys: \'<C-y>\', type: \'action\', action: \'scroll\', actionArgs: { forward: false, linewise: true }},\n
+    { keys: \'a\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { insertAt: \'charAfter\' }, context: \'normal\' },\n
+    { keys: \'A\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { insertAt: \'eol\' }, context: \'normal\' },\n
+    { keys: \'A\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { insertAt: \'endOfSelectedArea\' }, context: \'visual\' },\n
+    { keys: \'i\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { insertAt: \'inplace\' }, context: \'normal\' },\n
+    { keys: \'I\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { insertAt: \'firstNonBlank\'}, context: \'normal\' },\n
+    { keys: \'I\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { insertAt: \'startOfSelectedArea\' }, context: \'visual\' },\n
+    { keys: \'o\', type: \'action\', action: \'newLineAndEnterInsertMode\', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: \'normal\' },\n
+    { keys: \'O\', type: \'action\', action: \'newLineAndEnterInsertMode\', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: \'normal\' },\n
+    { keys: \'v\', type: \'action\', action: \'toggleVisualMode\' },\n
+    { keys: \'V\', type: \'action\', action: \'toggleVisualMode\', actionArgs: { linewise: true }},\n
+    { keys: \'<C-v>\', type: \'action\', action: \'toggleVisualMode\', actionArgs: { blockwise: true }},\n
+    { keys: \'gv\', type: \'action\', action: \'reselectLastSelection\' },\n
+    { keys: \'J\', type: \'action\', action: \'joinLines\', isEdit: true },\n
+    { keys: \'p\', type: \'action\', action: \'paste\', isEdit: true, actionArgs: { after: true, isEdit: true }},\n
+    { keys: \'P\', type: \'action\', action: \'paste\', isEdit: true, actionArgs: { after: false, isEdit: true }},\n
+    { keys: \'r<character>\', type: \'action\', action: \'replace\', isEdit: true },\n
+    { keys: \'@<character>\', type: \'action\', action: \'replayMacro\' },\n
+    { keys: \'q<character>\', type: \'action\', action: \'enterMacroRecordMode\' },\n
     // Handle Replace-mode as a special case of insert mode.\n
-    { keys: [\'R\'], type: \'action\', action: \'enterInsertMode\', isEdit: true,\n
-        actionArgs: { replace: true }},\n
-    { keys: [\'u\'], type: \'action\', action: \'undo\' },\n
-    { keys: [\'<C-r>\'], type: \'action\', action: \'redo\' },\n
-    { keys: [\'m\', \'character\'], type: \'action\', action: \'setMark\' },\n
-    { keys: [\'"\', \'character\'], type: \'action\', action: \'setRegister\' },\n
-    { keys: [\'z\', \'z\'], type: \'action\', action: \'scrollToCursor\',\n
-        actionArgs: { position: \'center\' }},\n
-    { keys: [\'z\', \'.\'], type: \'action\', action: \'scrollToCursor\',\n
-        actionArgs: { position: \'center\' },\n
-        motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
-    { keys: [\'z\', \'t\'], type: \'action\', action: \'scrollToCursor\',\n
-        actionArgs: { position: \'top\' }},\n
-    { keys: [\'z\', \'<CR>\'], type: \'action\', action: \'scrollToCursor\',\n
-        actionArgs: { position: \'top\' },\n
-        motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
-    { keys: [\'z\', \'-\'], type: \'action\', action: \'scrollToCursor\',\n
-        actionArgs: { position: \'bottom\' }},\n
-    { keys: [\'z\', \'b\'], type: \'action\', action: \'scrollToCursor\',\n
-        actionArgs: { position: \'bottom\' },\n
-        motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
-    { keys: [\'.\'], type: \'action\', action: \'repeatLastEdit\' },\n
-    { keys: [\'<C-a>\'], type: \'action\', action: \'incrementNumberToken\',\n
-        isEdit: true,\n
-        actionArgs: {increase: true, backtrack: false}},\n
-    { keys: [\'<C-x>\'], type: \'action\', action: \'incrementNumberToken\',\n
-        isEdit: true,\n
-        actionArgs: {increase: false, backtrack: false}},\n
+    { keys: \'R\', type: \'action\', action: \'enterInsertMode\', isEdit: true, actionArgs: { replace: true }},\n
+    { keys: \'u\', type: \'action\', action: \'undo\', context: \'normal\' },\n
+    { keys: \'u\', type: \'operator\', operator: \'changeCase\', operatorArgs: {toLower: true}, context: \'visual\', isEdit: true },\n
+    { keys: \'U\', type: \'operator\', operator: \'changeCase\', operatorArgs: {toLower: false}, context: \'visual\', isEdit: true },\n
+    { keys: \'<C-r>\', type: \'action\', action: \'redo\' },\n
+    { keys: \'m<character>\', type: \'action\', action: \'setMark\' },\n
+    { keys: \'"<character>\', type: \'action\', action: \'setRegister\' },\n
+    { keys: \'zz\', type: \'action\', action: \'scrollToCursor\', actionArgs: { position: \'center\' }},\n
+    { keys: \'z.\', type: \'action\', action: \'scrollToCursor\', actionArgs: { position: \'center\' }, motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
+    { keys: \'zt\', type: \'action\', action: \'scrollToCursor\', actionArgs: { position: \'top\' }},\n
+    { keys: \'z<CR>\', type: \'action\', action: \'scrollToCursor\', actionArgs: { position: \'top\' }, motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
+    { keys: \'z-\', type: \'action\', action: \'scrollToCursor\', actionArgs: { position: \'bottom\' }},\n
+    { keys: \'zb\', type: \'action\', action: \'scrollToCursor\', actionArgs: { position: \'bottom\' }, motion: \'moveToFirstNonWhiteSpaceCharacter\' },\n
+    { keys: \'.\', type: \'action\', action: \'repeatLastEdit\' },\n
+    { keys: \'<C-a>\', type: \'action\', action: \'incrementNumberToken\', isEdit: true, actionArgs: {increase: true, backtrack: false}},\n
+    { keys: \'<C-x>\', type: \'action\', action: \'incrementNumberToken\', isEdit: true, actionArgs: {increase: false, backtrack: false}},\n
     // Text object motions\n
-    { keys: [\'a\', \'character\'], type: \'motion\',\n
-        motion: \'textObjectManipulation\' },\n
-    { keys: [\'i\', \'character\'], type: \'motion\',\n
-        motion: \'textObjectManipulation\',\n
-        motionArgs: { textObjectInner: true }},\n
+    { keys: \'a<character>\', type: \'motion\', motion: \'textObjectManipulation\' },\n
+    { keys: \'i<character>\', type: \'motion\', motion: \'textObjectManipulation\', motionArgs: { textObjectInner: true }},\n
     // Search\n
-    { keys: [\'/\'], type: \'search\',\n
-        searchArgs: { forward: true, querySrc: \'prompt\', toJumplist: true }},\n
-    { keys: [\'?\'], type: \'search\',\n
-        searchArgs: { forward: false, querySrc: \'prompt\', toJumplist: true }},\n
-    { keys: [\'*\'], type: \'search\',\n
-        searchArgs: { forward: true, querySrc: \'wordUnderCursor\', toJumplist: true }},\n
-    { keys: [\'#\'], type: \'search\',\n
-        searchArgs: { forward: false, querySrc: \'wordUnderCursor\', toJumplist: true }},\n
+    { keys: \'/\', type: \'search\', searchArgs: { forward: true, querySrc: \'prompt\', toJumplist: true }},\n
+    { keys: \'?\', type: \'search\', searchArgs: { forward: false, querySrc: \'prompt\', toJumplist: true }},\n
+    { keys: \'*\', type: \'search\', searchArgs: { forward: true, querySrc: \'wordUnderCursor\', wholeWordOnly: true, toJumplist: true }},\n
+    { keys: \'#\', type: \'search\', searchArgs: { forward: false, querySrc: \'wordUnderCursor\', wholeWordOnly: true, toJumplist: true }},\n
+    { keys: \'g*\', type: \'search\', searchArgs: { forward: true, querySrc: \'wordUnderCursor\', toJumplist: true }},\n
+    { keys: \'g#\', type: \'search\', searchArgs: { forward: false, querySrc: \'wordUnderCursor\', toJumplist: true }},\n
     // Ex command\n
-    { keys: [\':\'], type: \'ex\' }\n
+    { keys: \':\', type: \'ex\' }\n
   ];\n
+\n
+  var Pos = CodeMirror.Pos;\n
 \n
   var Vim = function() {\n
-    CodeMirror.defineOption(\'vimMode\', false, function(cm, val) {\n
-      if (val) {\n
-        cm.setOption(\'keyMap\', \'vim\');\n
-        cm.setOption(\'disableInput\', true);\n
-        CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});\n
-        cm.on(\'beforeSelectionChange\', beforeSelectionChange);\n
-        maybeInitVimState(cm);\n
-        CodeMirror.on(cm.getInputField(), \'paste\', getOnPasteFn(cm));\n
-      } else if (cm.state.vim) {\n
-        cm.setOption(\'keyMap\', \'default\');\n
-        cm.setOption(\'disableInput\', false);\n
-        cm.off(\'beforeSelectionChange\', beforeSelectionChange);\n
-        CodeMirror.off(cm.getInputField(), \'paste\', getOnPasteFn(cm));\n
-        cm.state.vim = null;\n
-      }\n
+    function enterVimMode(cm) {\n
+      cm.setOption(\'disableInput\', true);\n
+      cm.setOption(\'showCursorWhenSelecting\', false);\n
+      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});\n
+      cm.on(\'cursorActivity\', onCursorActivity);\n
+      maybeInitVimState(cm);\n
+      CodeMirror.on(cm.getInputField(), \'paste\', getOnPasteFn(cm));\n
+    }\n
+\n
+    function leaveVimMode(cm) {\n
+      cm.setOption(\'disableInput\', false);\n
+      cm.off(\'cursorActivity\', onCursorActivity);\n
+      CodeMirror.off(cm.getInputField(), \'paste\', getOnPasteFn(cm));\n
+      cm.state.vim = null;\n
+    }\n
+\n
+    function detachVimMap(cm, next) {\n
+      if (this == CodeMirror.keyMap.vim)\n
+        CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor");\n
+\n
+      if (!next || next.attach != attachVimMap)\n
+        leaveVimMode(cm, false);\n
+    }\n
+    function attachVimMap(cm, prev) {\n
+      if (this == CodeMirror.keyMap.vim)\n
+        CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor");\n
+\n
+      if (!prev || prev.attach != attachVimMap)\n
+        enterVimMode(cm);\n
+    }\n
+\n
+    // Deprecated, simply setting the keymap works again.\n
+    CodeMirror.defineOption(\'vimMode\', false, function(cm, val, prev) {\n
+      if (val && cm.getOption("keyMap") != "vim")\n
+        cm.setOption("keyMap", "vim");\n
+      else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap")))\n
+        cm.setOption("keyMap", "default");\n
     });\n
-    function beforeSelectionChange(cm, cur) {\n
-      var vim = cm.state.vim;\n
-      if (vim.insertMode || vim.exMode) return;\n
 \n
-      var head = cur.head;\n
-      if (head.ch && head.ch == cm.doc.getLine(head.line).length) {\n
-        head.ch--;\n
+    function cmKey(key, cm) {\n
+      if (!cm) { return undefined; }\n
+      var vimKey = cmKeyToVimKey(key);\n
+      if (!vimKey) {\n
+        return false;\n
+      }\n
+      var cmd = CodeMirror.Vim.findKey(cm, vimKey);\n
+      if (typeof cmd == \'function\') {\n
+        CodeMirror.signal(cm, \'vim-keypress\', vimKey);\n
+      }\n
+      return cmd;\n
+    }\n
+\n
+    var modifiers = {\'Shift\': \'S\', \'Ctrl\': \'C\', \'Alt\': \'A\', \'Cmd\': \'D\', \'Mod\': \'A\'};\n
+    var specialKeys = {Enter:\'CR\',Backspace:\'BS\',Delete:\'Del\'};\n
+    function cmKeyToVimKey(key) {\n
+      if (key.charAt(0) == \'\\\'\') {\n
+        // Keypress character binding of format "\'a\'"\n
+        return key.charAt(1);\n
+      }\n
+      var pieces = key.split(\'-\');\n
+      if (/-$/.test(key)) {\n
+        // If the - key was typed, split will result in 2 extra empty strings\n
+        // in the array. Replace them with 1 \'-\'.\n
+        pieces.splice(-2, 2, \'-\');\n
+      }\n
+      var lastPiece = pieces[pieces.length - 1];\n
+      if (pieces.length == 1 && pieces[0].length == 1) {\n
+        // No-modifier bindings use literal character bindings above. Skip.\n
+        return false;\n
+      } else if (pieces.length == 2 && pieces[0] == \'Shift\' && lastPiece.length == 1) {\n
+        // Ignore Shift+char bindings as they should be handled by literal character.\n
+        return false;\n
       }\n
+      var hasCharacter = false;\n
+      for (var i = 0; i < pieces.length; i++) {\n
+        var piece = pieces[i];\n
+        if (piece in modifiers) { pieces[i] = modifiers[piece]; }\n
+        else { hasCharacter = true; }\n
+        if (piece in specialKeys) { pieces[i] = specialKeys[piece]; }\n
+      }\n
+      if (!hasCharacter) {\n
+        // Vim does not support modifier only keys.\n
+        return false;\n
+      }\n
+      // TODO: Current bindings expect the character to be lower case, but\n
+      // it looks like vim key notation uses upper case.\n
+      if (isUpperCase(lastPiece)) {\n
+        pieces[pieces.length - 1] = lastPiece.toLowerCase();\n
+      }\n
+      return \'<\' + pieces.join(\'-\') + \'>\';\n
     }\n
+\n
     function getOnPasteFn(cm) {\n
       var vim = cm.state.vim;\n
       if (!vim.onPasteFn) {\n
@@ -429,11 +398,8 @@
     var upperCaseAlphabet = makeKeyRange(65, 26);\n
     var lowerCaseAlphabet = makeKeyRange(97, 26);\n
     var numbers = makeKeyRange(48, 10);\n
-    var specialSymbols = \'~`!@#$%^&*()_-+=[{}]\\\\|/?.,<>:;"\\\'\'.split(\'\');\n
-    var specialKeys = [\'Left\', \'Right\', \'Up\', \'Down\', \'Space\', \'Backspace\',\n
-        \'Esc\', \'Home\', \'End\', \'PageUp\', \'PageDown\', \'Enter\'];\n
     var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, [\'<\', \'>\']);\n
-    var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, [\'-\', \'"\']);\n
+    var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, [\'-\', \'"\', \'.\', \':\', \'/\']);\n
 \n
     function isLine(cm, line) {\n
       return line >= cm.firstLine() && line <= cm.lastLine();\n
@@ -461,6 +427,41 @@
       }\n
       return false;\n
     }\n
+\n
+    var options = {};\n
+    function defineOption(name, defaultValue, type) {\n
+      if (defaultValue === undefined) { throw Error(\'defaultValue is required\'); }\n
+      if (!type) { type = \'string\'; }\n
+      options[name] = {\n
+        type: type,\n
+        defaultValue: defaultValue\n
+      };\n
+      setOption(name, defaultValue);\n
+    }\n
+\n
+    function setOption(name, value) {\n
+      var option = options[name];\n
+      if (!option) {\n
+        throw Error(\'Unknown option: \' + name);\n
+      }\n
+      if (option.type == \'boolean\') {\n
+        if (value && value !== true) {\n
+          throw Error(\'Invalid argument: \' + name + \'=\' + value);\n
+        } else if (value !== false) {\n
+          // Boolean options are set to true if value is not defined.\n
+          value = true;\n
+        }\n
+      }\n
+      option.value = option.type == \'boolean\' ? !!value : value;\n
+    }\n
+\n
+    function getOption(name) {\n
+      var option = options[name];\n
+      if (!option) {\n
+        throw Error(\'Unknown option: \' + name);\n
+      }\n
+      return option.value;\n
+    }\n
 \n
     var createCircularJumpList = function() {\n
       var size = 100;\n
@@ -528,30 +529,56 @@
       };\n
     };\n
 \n
-    var createMacroState = function() {\n
+    // Returns an object to track the changes associated insert mode.  It\n
+    // clones the object that is passed in, or creates an empty object one if\n
+    // none is provided.\n
+    var createInsertModeChanges = function(c) {\n
+      if (c) {\n
+        // Copy construction\n
+        return {\n
+          changes: c.changes,\n
+          expectCursorActivityForChange: c.expectCursorActivityForChange\n
+        };\n
+      }\n
       return {\n
-        macroKeyBuffer: [],\n
-        latestRegister: undefined,\n
-        inReplay: false,\n
-        lastInsertModeChanges: {\n
-          changes: [], // Change list\n
-          expectCursorActivityForChange: false // Set to true on change, false on cursorActivity.\n
-        },\n
-        enteredMacroMode: undefined,\n
-        isMacroPlaying: false,\n
-        toggle: function(cm, registerName) {\n
-          if (this.enteredMacroMode) { //onExit\n
-            this.enteredMacroMode(); // close dialog\n
-            this.enteredMacroMode = undefined;\n
-          } else { //onEnter\n
-            this.latestRegister = registerName;\n
-            this.enteredMacroMode = cm.openDialog(\n
-              \'(recording)[\'+registerName+\']\', null, {bottom:true});\n
-          }\n
-        }\n
+        // Change list\n
+        changes: [],\n
+        // Set to true on change, false on cursorActivity.\n
+        expectCursorActivityForChange: false\n
       };\n
     };\n
 \n
+    function MacroModeState() {\n
+      this.latestRegister = undefined;\n
+      this.isPlaying = false;\n
+      this.isRecording = false;\n
+      this.replaySearchQueries = [];\n
+      this.onRecordingDone = undefined;\n
+      this.lastInsertModeChanges = createInsertModeChanges();\n
+    }\n
+    MacroModeState.prototype = {\n
+      exitMacroRecordMode: function() {\n
+        var macroModeState = vimGlobalState.macroModeState;\n
+        if (macroModeState.onRecordingDone) {\n
+          macroModeState.onRecordingDone(); // close dialog\n
+        }\n
+        macroModeState.onRecordingDone = undefined;\n
+        macroModeState.isRecording = false;\n
+      },\n
+      enterMacroRecordMode: function(cm, registerName) {\n
+        var register =\n
+            vimGlobalState.registerController.getRegister(registerName);\n
+        if (register) {\n
+          register.clear();\n
+          this.latestRegister = registerName;\n
+          if (cm.openDialog) {\n
+            this.onRecordingDone = cm.openDialog(\n
+                \'(recording)[\'+registerName+\']\', null, {bottom:true});\n
+          }\n
+          this.isRecording = true;\n
+        }\n
+      }\n
+    };\n
 \n
     function maybeInitVimState(cm) {\n
       if (!cm.state.vim) {\n
@@ -576,13 +603,20 @@
           // executed in between.\n
           lastMotion: null,\n
           marks: {},\n
+          // Mark for rendering fake cursor for visual mode.\n
+          fakeCursor: null,\n
           insertMode: false,\n
           // Repeat count for changes made in insert mode, triggered by key\n
           // sequences like 3,i. Only exists when insertMode is true.\n
           insertModeRepeat: undefined,\n
           visualMode: false,\n
           // If we are in visual line mode. No effect if visualMode is false.\n
-          visualLine: false\n
+          visualLine: false,\n
+          visualBlock: false,\n
+          lastSelection: null,\n
+          lastPastedText: null,\n
+          sel: {\n
+          }\n
         };\n
       }\n
       return cm.state.vim;\n
@@ -594,14 +628,25 @@
         searchQuery: null,\n
         // Whether we are searching backwards.\n
         searchIsReversed: false,\n
+        // Replace part of the last substituted pattern\n
+        lastSubstituteReplacePart: undefined,\n
         jumpList: createCircularJumpList(),\n
-        macroModeState: createMacroState(),\n
+        macroModeState: new MacroModeState,\n
         // Recording latest f, t, F or T motion command.\n
         lastChararacterSearch: {increment:0, forward:true, selectedCharacter:\'\'},\n
-        registerController: new RegisterController({})\n
+        registerController: new RegisterController({}),\n
+        // search history buffer\n
+        searchHistoryController: new HistoryController({}),\n
+        // ex Command history buffer\n
+        exCommandHistoryController : new HistoryController({})\n
       };\n
+      for (var optionName in options) {\n
+        var option = options[optionName];\n
+        option.value = option.defaultValue;\n
+      }\n
     }\n
 \n
+    var lastInsertModeKeyTimer;\n
     var vimApi= {\n
       buildKeyMap: function() {\n
         // TODO: Convert keymap into dictionary format for fast lookup.\n
@@ -621,12 +666,17 @@
 \n
       // Testing hook.\n
       maybeInitVimState_: maybeInitVimState,\n
+\n
+      suppressErrorLogging: false,\n
 \n
       InsertModeKey: InsertModeKey,\n
       map: function(lhs, rhs, ctx) {\n
         // Add user defined key bindings.\n
         exCommandDispatcher.map(lhs, rhs, ctx);\n
       },\n
+      setOption: setOption,\n
+      getOption: getOption,\n
+      defineOption: defineOption,\n
       defineEx: function(name, prefix, func){\n
         if (name.indexOf(prefix) !== 0) {\n
           throw new Error(\'(Vim.defineEx) "\'+prefix+\'" is not a prefix of "\'+name+\'", command not registered\');\n
@@ -634,56 +684,145 @@
         exCommands[name]=func;\n
         exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:\'api\'};\n
       },\n
-      // This is the outermost function called by CodeMirror, after keys have\n
-      // been mapped to their Vim equivalents.\n
-      handleKey: function(cm, key) {\n
-        var command;\n
+      handleKey: function (cm, key, origin) {\n
+        var command = this.findKey(cm, key, origin);\n
+        if (typeof command === \'function\') {\n
+          return command();\n
+        }\n
+      },\n
+      /**\n
+       * This is the outermost function called by CodeMirror, after keys have\n
+       * been mapped to their Vim equivalents.\n
+       *\n
+       * Finds a command based on the key (and cached keys if there is a\n
+       * multi-key sequence). Returns `undefined` if no key is matched, a noop\n
+       * function if a partial match is found (multi-key), and a function to\n
+       * execute the bound command if a a key is matched. The function always\n
+       * returns true.\n
+       */\n
+      findKey: function(cm, key, origin) {\n
         var vim = maybeInitVimState(cm);\n
-        var macroModeState = vimGlobalState.macroModeState;\n
-        if (macroModeState.enteredMacroMode) {\n
-          if (key == \'q\') {\n
-            actions.exitMacroRecordMode();\n
-            vim.inputState = new InputState();\n
-            return;\n
+        function handleMacroRecording() {\n
+          var macroModeState = vimGlobalState.macroModeState;\n
+          if (macroModeState.isRecording) {\n
+            if (key == \'q\') {\n
+              macroModeState.exitMacroRecordMode();\n
+              clearInputState(cm);\n
+              return true;\n
+            }\n
+            if (origin != \'mapping\') {\n
+              logKey(macroModeState, key);\n
+            }\n
           }\n
         }\n
-        if (key == \'<Esc>\') {\n
-          // Clear input state and get back to normal mode.\n
-          vim.inputState = new InputState();\n
-          if (vim.visualMode) {\n
-            exitVisualMode(cm);\n
+        function handleEsc() {\n
+          if (key == \'<Esc>\') {\n
+            // Clear input state and get back to normal mode.\n
+            clearInputState(cm);\n
+            if (vim.visualMode) {\n
+              exitVisualMode(cm);\n
+            } else if (vim.insertMode) {\n
+              exitInsertMode(cm);\n
+            }\n
+            return true;\n
           }\n
-          return;\n
         }\n
-        // Enter visual mode when the mouse selects text.\n
-        if (!vim.visualMode &&\n
-            !cursorEqual(cm.getCursor(\'head\'), cm.getCursor(\'anchor\'))) {\n
-          vim.visualMode = true;\n
-          vim.visualLine = false;\n
-          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});\n
-          cm.on(\'mousedown\', exitVisualMode);\n
-        }\n
-        if (key != \'0\' || (key == \'0\' && vim.inputState.getRepeat() === 0)) {\n
-          // Have to special case 0 since it\'s both a motion and a number.\n
-          command = commandDispatcher.matchCommand(key, defaultKeymap, vim);\n
+        function doKeyToKey(keys) {\n
+          // TODO: prevent infinite recursion.\n
+          var match;\n
+          while (keys) {\n
+            // Pull off one command key, which is either a single character\n
+            // or a special sequence wrapped in \'<\' and \'>\', e.g. \'<Space>\'.\n
+            match = (/<\\w+-.+?>|<\\w+>|./).exec(keys);\n
+            key = match[0];\n
+            keys = keys.substring(match.index + key.length);\n
+            CodeMirror.Vim.handleKey(cm, key, \'mapping\');\n
+          }\n
         }\n
-        if (!command) {\n
-          if (isNumber(key)) {\n
-            // Increment count unless count is 0 and key is 0.\n
-            vim.inputState.pushRepeatDigit(key);\n
+\n
+        function handleKeyInsertMode() {\n
+          if (handleEsc()) { return true; }\n
+          var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;\n
+          var keysAreChars = key.length == 1;\n
+          var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, \'insert\');\n
+          // Need to check all key substrings in insert mode.\n
+          while (keys.length > 1 && match.type != \'full\') {\n
+            var keys = vim.inputState.keyBuffer = keys.slice(1);\n
+            var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, \'insert\');\n
+            if (thisMatch.type != \'none\') { match = thisMatch; }\n
           }\n
-          return;\n
+          if (match.type == \'none\') { clearInputState(cm); return false; }\n
+          else if (match.type == \'partial\') {\n
+            if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }\n
+            lastInsertModeKeyTimer = window.setTimeout(\n
+              function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } },\n
+              getOption(\'insertModeEscKeysTimeout\'));\n
+            return !keysAreChars;\n
+          }\n
+\n
+          if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); }\n
+          if (keysAreChars) {\n
+            var here = cm.getCursor();\n
+            cm.replaceRange(\'\', offsetCursor(here, 0, -(keys.length - 1)), here, \'+input\');\n
+          }\n
+          clearInputState(cm);\n
+          return match.command;\n
         }\n
-        if (command.type == \'keyToKey\') {\n
-          // TODO: prevent infinite recursion.\n
-          for (var i = 0; i < command.toKeys.length; i++) {\n
-            this.handleKey(cm, command.toKeys[i]);\n
+\n
+        function handleKeyNonInsertMode() {\n
+          if (handleMacroRecording() || handleEsc()) { return true; };\n
+\n
+          var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key;\n
+          if (/^[1-9]\\d*$/.test(keys)) { return true; }\n
+\n
+          var keysMatcher = /^(\\d*)(.*)$/.exec(keys);\n
+          if (!keysMatcher) { clearInputState(cm); return false; }\n
+          var context = vim.visualMode ? \'visual\' :\n
+                                         \'normal\';\n
+          var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context);\n
+          if (match.type == \'none\') { clearInputState(cm); return false; }\n
+          else if (match.type == \'partial\') { return true; }\n
+\n
+          vim.inputState.keyBuffer = \'\';\n
+          var keysMatcher = /^(\\d*)(.*)$/.exec(keys);\n
+          if (keysMatcher[1] && keysMatcher[1] != \'0\') {\n
+            vim.inputState.pushRepeatDigit(keysMatcher[1]);\n
           }\n
+          return match.command;\n
+        }\n
+\n
+        var command;\n
+        if (vim.insertMode) { command = handleKeyInsertMode(); }\n
+        else { command = handleKeyNonInsertMode(); }\n
+        if (command === false) {\n
+          return undefined;\n
+        } else if (command === true) {\n
+          // TODO: Look into using CodeMirror\'s multi-key handling.\n
+          // Return no-op since we are caching the key. Counts as handled, but\n
+          // don\'t want act on it just yet.\n
+          return function() {};\n
         } else {\n
-          if (macroModeState.enteredMacroMode) {\n
-            logKey(macroModeState, key);\n
-          }\n
-          commandDispatcher.processCommand(cm, vim, command);\n
+          return function() {\n
+            return cm.operation(function() {\n
+              cm.curOp.isVimOp = true;\n
+              try {\n
+                if (command.type == \'keyToKey\') {\n
+                  doKeyToKey(command.toKeys);\n
+                } else {\n
+                  commandDispatcher.processCommand(cm, vim, command);\n
+                }\n
+              } catch (e) {\n
+                // clear VIM state in case it\'s in a bad state.\n
+                cm.state.vim = undefined;\n
+                maybeInitVimState(cm);\n
+                if (!CodeMirror.Vim.suppressErrorLogging) {\n
+                  console[\'log\'](e);\n
+                }\n
+                throw e;\n
+              }\n
+              return true;\n
+            });\n
+          };\n
         }\n
       },\n
       handleEx: function(cm, input) {\n
@@ -701,7 +840,7 @@
       this.motion = null;\n
       this.motionArgs = null;\n
       this.keyBuffer = []; // For matching multi-key commands.\n
-      this.registerName = null; // Defaults to the unamed register.\n
+      this.registerName = null; // Defaults to the unnamed register.\n
     }\n
     InputState.prototype.pushRepeatDigit = function(n) {\n
       if (!this.operator) {\n
@@ -723,6 +862,11 @@
       }\n
       return repeat;\n
     };\n
+\n
+    function clearInputState(cm, reason) {\n
+      cm.state.vim.inputState = new InputState();\n
+      CodeMirror.signal(cm, \'vim-command-done\', reason);\n
+    }\n
 \n
     /*\n
      * Register stores information about copy and paste registers.  Besides\n
@@ -730,31 +874,45 @@
      * pasted, should it insert itself into a new line, or should the text be\n
      * inserted at the cursor position.)\n
      */\n
-    function Register(text, linewise) {\n
+    function Register(text, linewise, blockwise) {\n
       this.clear();\n
-      if (text) {\n
-        this.set(text, linewise);\n
-      }\n
+      this.keyBuffer = [text || \'\'];\n
+      this.insertModeChanges = [];\n
+      this.searchQueries = [];\n
+      this.linewise = !!linewise;\n
+      this.blockwise = !!blockwise;\n
     }\n
     Register.prototype = {\n
-      set: function(text, linewise) {\n
-        this.text = text;\n
+      setText: function(text, linewise, blockwise) {\n
+        this.keyBuffer = [text || \'\'];\n
         this.linewise = !!linewise;\n
+        this.blockwise = !!blockwise;\n
       },\n
-      append: function(text, linewise) {\n
+      pushText: function(text, linewise) {\n
         // if this register has ever been set to linewise, use linewise.\n
-        if (linewise || this.linewise) {\n
-          this.text += \'\\n\' + text;\n
+        if (linewise) {\n
+          if (!this.linewise) {\n
+            this.keyBuffer.push(\'\\n\');\n
+          }\n
           this.linewise = true;\n
-        } else {\n
-          this.text += text;\n
         }\n
+        this.keyBuffer.push(text);\n
+      },\n
+      pushInsertModeChanges: function(changes) {\n
+        this.insertModeChanges.push(createInsertModeChanges(changes));\n
+      },\n
+      pushSearchQuery: function(query) {\n
+        this.searchQueries.push(query);\n
       },\n
       clear: function() {\n
-        this.text = \'\';\n
+        this.keyBuffer = [];\n
+        this.insertModeChanges = [];\n
+        this.searchQueries = [];\n
         this.linewise = false;\n
       },\n
-      toString: function() { return this.text; }\n
+      toString: function() {\n
+        return this.keyBuffer.join(\'\');\n
+      }\n
     };\n
 \n
     /*\n
@@ -767,14 +925,17 @@
      */\n
     function RegisterController(registers) {\n
       this.registers = registers;\n
-      this.unamedRegister = registers[\'"\'] = new Register();\n
+      this.unnamedRegister = registers[\'"\'] = new Register();\n
+      registers[\'.\'] = new Register();\n
+      registers[\':\'] = new Register();\n
+      registers[\'/\'] = new Register();\n
     }\n
     RegisterController.prototype = {\n
-      pushText: function(registerName, operator, text, linewise) {\n
+      pushText: function(registerName, operator, text, linewise, blockwise) {\n
         if (linewise && text.charAt(0) == \'\\n\') {\n
           text = text.slice(1) + \'\\n\';\n
         }\n
-        if(linewise && text.charAt(text.length - 1) !== \'\\n\'){\n
+        if (linewise && text.charAt(text.length - 1) !== \'\\n\'){\n
           text += \'\\n\';\n
         }\n
         // Lowercase and uppercase registers refer to the same register.\n
@@ -787,7 +948,7 @@
           switch (operator) {\n
             case \'yank\':\n
               // The 0 register contains the text from the most recent yank.\n
-              this.registers[\'0\'] = new Register(text, linewise);\n
+              this.registers[\'0\'] = new Register(text, linewise, blockwise);\n
               break;\n
             case \'delete\':\n
             case \'change\':\n
@@ -803,30 +964,26 @@
               break;\n
           }\n
           // Make sure the unnamed register is set to what just happened\n
-          this.unamedRegister.set(text, linewise);\n
+          this.unnamedRegister.setText(text, linewise, blockwise);\n
           return;\n
         }\n
 \n
         // If we\'ve gotten to this point, we\'ve actually specified a register\n
         var append = isUpperCase(registerName);\n
         if (append) {\n
-          register.append(text, linewise);\n
-          // The unamed register always has the same value as the last used\n
-          // register.\n
-          this.unamedRegister.append(text, linewise);\n
+          register.pushText(text, linewise);\n
         } else {\n
-          register.set(text, linewise);\n
-          this.unamedRegister.set(text, linewise);\n
+          register.setText(text, linewise, blockwise);\n
         }\n
-      },\n
-      setRegisterText: function(name, text, linewise) {\n
-        this.getRegister(name).set(text, linewise);\n
+        // The unnamed register always has the same value as the last used\n
+        // register.\n
+        this.unnamedRegister.setText(register.toString(), linewise);\n
       },\n
       // Gets the register named @name.  If one of @name doesn\'t already exist,\n
-      // create it.  If @name is invalid, return the unamedRegister.\n
+      // create it.  If @name is invalid, return the unnamedRegister.\n
       getRegister: function(name) {\n
         if (!this.isValidRegister(name)) {\n
-          return this.unamedRegister;\n
+          return this.unnamedRegister;\n
         }\n
         name = name.toLowerCase();\n
         if (!this.registers[name]) {\n
@@ -843,85 +1000,65 @@
         }\n
       }\n
     };\n
-\n
-    var commandDispatcher = {\n
-      matchCommand: function(key, keyMap, vim) {\n
-        var inputState = vim.inputState;\n
-        var keys = inputState.keyBuffer.concat(key);\n
-        var matchedCommands = [];\n
-        var selectedCharacter;\n
-        for (var i = 0; i < keyMap.length; i++) {\n
-          var command = keyMap[i];\n
-          if (matchKeysPartial(keys, command.keys)) {\n
-            if (inputState.operator && command.type == \'action\') {\n
-              // Ignore matched action commands after an operator. Operators\n
-              // only operate on motions. This check is really for text\n
-              // objects since aW, a[ etcs conflicts with a.\n
-              continue;\n
-            }\n
-            // Match commands that take <character> as an argument.\n
-            if (command.keys[keys.length - 1] == \'character\') {\n
-              selectedCharacter = keys[keys.length - 1];\n
-              if(selectedCharacter.length>1){\n
-                switch(selectedCharacter){\n
-                  case \'<CR>\':\n
-                    selectedCharacter=\'\\n\';\n
-                    break;\n
-                  case \'<Space>\':\n
-                    selectedCharacter=\' \';\n
-                    break;\n
-                  default:\n
-                    continue;\n
-                }\n
-              }\n
+    function HistoryController() {\n
+        this.historyBuffer = [];\n
+        this.iterator;\n
+        this.initialPrefix = null;\n
+    }\n
+    HistoryController.prototype = {\n
+      // the input argument here acts a user entered prefix for a small time\n
+      // until we start autocompletion in which case it is the autocompleted.\n
+      nextMatch: function (input, up) {\n
+        var historyBuffer = this.historyBuffer;\n
+        var dir = up ? -1 : 1;\n
+        if (this.initialPrefix === null) this.initialPrefix = input;\n
+        for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) {\n
+          var element = historyBuffer[i];\n
+          for (var j = 0; j <= element.length; j++) {\n
+            if (this.initialPrefix == element.substring(0, j)) {\n
+              this.iterator = i;\n
+              return element;\n
             }\n
-            // Add the command to the list of matched commands. Choose the best\n
-            // command later.\n
-            matchedCommands.push(command);\n
           }\n
         }\n
-\n
-        // Returns the command if it is a full match, or null if not.\n
-        function getFullyMatchedCommandOrNull(command) {\n
-          if (keys.length < command.keys.length) {\n
-            // Matches part of a multi-key command. Buffer and wait for next\n
-            // stroke.\n
-            inputState.keyBuffer.push(key);\n
-            return null;\n
-          } else {\n
-            if (command.keys[keys.length - 1] == \'character\') {\n
-              inputState.selectedCharacter = selectedCharacter;\n
-            }\n
-            // Clear the buffer since a full match was found.\n
-            inputState.keyBuffer = [];\n
-            return command;\n
-          }\n
+        // should return the user input in case we reach the end of buffer.\n
+        if (i >= historyBuffer.length) {\n
+          this.iterator = historyBuffer.length;\n
+          return this.initialPrefix;\n
+        }\n
+        // return the last autocompleted query or exCommand as it is.\n
+        if (i < 0 ) return input;\n
+      },\n
+      pushInput: function(input) {\n
+        var index = this.historyBuffer.indexOf(input);\n
+        if (index > -1) this.historyBuffer.splice(index, 1);\n
+        if (input.length) this.historyBuffer.push(input);\n
+      },\n
+      reset: function() {\n
+        this.initialPrefix = null;\n
+        this.iterator = this.historyBuffer.length;\n
+      }\n
+    };\n
+    var commandDispatcher = {\n
+      matchCommand: function(keys, keyMap, inputState, context) {\n
+        var matches = commandMatches(keys, keyMap, context, inputState);\n
+        if (!matches.full && !matches.partial) {\n
+          return {type: \'none\'};\n
+        } else if (!matches.full && matches.partial) {\n
+          return {type: \'partial\'};\n
         }\n
 \n
-        if (!matchedCommands.length) {\n
-          // Clear the buffer since there were no matches.\n
-          inputState.keyBuffer = [];\n
-          return null;\n
-        } else if (matchedCommands.length == 1) {\n
-          return getFullyMatchedCommandOrNull(matchedCommands[0]);\n
-        } else {\n
-          // Find the best match in the list of matchedCommands.\n
-          var context = vim.visualMode ? \'visual\' : \'normal\';\n
-          var bestMatch; // Default to first in the list.\n
-          for (var i = 0; i < matchedCommands.length; i++) {\n
-            var current = matchedCommands[i];\n
-            if (current.context == context) {\n
-              bestMatch = current;\n
-              break;\n
-            } else if (!bestMatch && !current.context) {\n
-              // Only set an imperfect match to best match if no best match is\n
-              // set and the imperfect match is not restricted to another\n
-              // context.\n
-              bestMatch = current;\n
-            }\n
+        var bestMatch;\n
+        for (var i = 0; i < matches.full.length; i++) {\n
+          var match = matches.full[i];\n
+          if (!bestMatch) {\n
+            bestMatch = match;\n
           }\n
-          return getFullyMatchedCommandOrNull(bestMatch);\n
         }\n
+        if (bestMatch.keys.slice(-11) == \'<character>\') {\n
+          inputState.selectedCharacter = lastChar(keys);\n
+        }\n
+        return {type: \'full\', command: bestMatch};\n
       },\n
       processCommand: function(cm, vim, command) {\n
         vim.inputState.repeatOverride = command.repeatOverride;\n
@@ -940,10 +1077,12 @@
             break;\n
           case \'search\':\n
             this.processSearch(cm, vim, command);\n
+            clearInputState(cm);\n
             break;\n
           case \'ex\':\n
           case \'keyToEx\':\n
             this.processEx(cm, vim, command);\n
+            clearInputState(cm);\n
             break;\n
           default:\n
             break;\n
@@ -966,7 +1105,7 @@
             return;\n
           } else {\n
             // 2 different operators in a row doesn\'t make sense.\n
-            vim.inputState = new InputState();\n
+            clearInputState(cm);\n
           }\n
         }\n
         inputState.operator = command.operator;\n
@@ -1011,7 +1150,7 @@
         actionArgs.repeat = repeat || 1;\n
         actionArgs.repeatIsExplicit = repeatIsExplicit;\n
         actionArgs.registerName = inputState.registerName;\n
-        vim.inputState = new InputState();\n
+        clearInputState(cm);\n
         vim.lastMotion = null;\n
         if (command.isEdit) {\n
           this.recordLastEdit(vim, inputState, command);\n
@@ -1024,11 +1163,14 @@
           return;\n
         }\n
         var forward = command.searchArgs.forward;\n
+        var wholeWordOnly = command.searchArgs.wholeWordOnly;\n
         getSearchState(cm).setReversed(!forward);\n
         var promptPrefix = (forward) ? \'/\' : \'?\';\n
         var originalQuery = getSearchState(cm).getQuery();\n
         var originalScrollPos = cm.getScrollInfo();\n
         function handleQuery(query, ignoreCase, smartCase) {\n
+          vimGlobalState.searchHistoryController.pushInput(query);\n
+          vimGlobalState.searchHistoryController.reset();\n
           try {\n
             updateSearchQuery(cm, query, ignoreCase, smartCase);\n
           } catch (e) {\n
@@ -1044,8 +1186,21 @@
         function onPromptClose(query) {\n
           cm.scrollTo(originalScrollPos.left, originalScrollPos.top);\n
           handleQuery(query, true /** ignoreCase */, true /** smartCase */);\n
+          var macroModeState = vimGlobalState.macroModeState;\n
+          if (macroModeState.isRecording) {\n
+            logSearchQuery(macroModeState, query);\n
+          }\n
         }\n
-        function onPromptKeyUp(_e, query) {\n
+        function onPromptKeyUp(e, query, close) {\n
+          var keyName = CodeMirror.keyName(e), up;\n
+          if (keyName == \'Up\' || keyName == \'Down\') {\n
+            up = keyName == \'Up\' ? true : false;\n
+            query = vimGlobalState.searchHistoryController.nextMatch(query, up) || \'\';\n
+            close(query);\n
+          } else {\n
+            if ( keyName != \'Left\' && keyName != \'Right\' && keyName != \'Ctrl\' && keyName != \'Alt\' && keyName != \'Shift\')\n
+              vimGlobalState.searchHistoryController.reset();\n
+          }\n
           var parsedQuery;\n
           try {\n
             parsedQuery = updateSearchQuery(cm, query,\n
@@ -1060,13 +1215,14 @@
             cm.scrollTo(originalScrollPos.left, originalScrollPos.top);\n
           }\n
         }\n
-        function onPromptKeyDown(e, _query, close) {\n
+        function onPromptKeyDown(e, query, close) {\n
           var keyName = CodeMirror.keyName(e);\n
           if (keyName == \'Esc\' || keyName == \'Ctrl-C\' || keyName == \'Ctrl-[\') {\n
+            vimGlobalState.searchHistoryController.pushInput(query);\n
+            vimGlobalState.searchHistoryController.reset();\n
             updateSearchQuery(cm, originalQuery);\n
             clearSearchHighlight(cm);\n
             cm.scrollTo(originalScrollPos.left, originalScrollPos.top);\n
-\n
             CodeMirror.e_stop(e);\n
             close();\n
             cm.focus();\n
@@ -1074,13 +1230,19 @@
         }\n
         switch (command.searchArgs.querySrc) {\n
           case \'prompt\':\n
-            showPrompt(cm, {\n
-                onClose: onPromptClose,\n
-                prefix: promptPrefix,\n
-                desc: searchPromptDesc,\n
-                onKeyUp: onPromptKeyUp,\n
-                onKeyDown: onPromptKeyDown\n
-            });\n
+            var macroModeState = vimGlobalState.macroModeState;\n
+            if (macroModeState.isPlaying) {\n
+              var query = macroModeState.replaySearchQueries.shift();\n
+              handleQuery(query, true /** ignoreCase */, false /** smartCase */);\n
+            } else {\n
+              showPrompt(cm, {\n
+                  onClose: onPromptClose,\n
+                  prefix: promptPrefix,\n
+                  desc: searchPromptDesc,\n
+                  onKeyUp: onPromptKeyUp,\n
+                  onKeyDown: onPromptKeyDown\n
+              });\n
+            }\n
             break;\n
           case \'wordUnderCursor\':\n
             var word = expandWordUnderCursor(cm, false /** inclusive */,\n
@@ -1098,8 +1260,8 @@
             }\n
             var query = cm.getLine(word.start.line).substring(word.start.ch,\n
                 word.end.ch);\n
-            if (isKeyword) {\n
-              query = \'\\\\b\' + query + \'\\\\b\';\n
+            if (isKeyword && wholeWordOnly) {\n
+                query = \'\\\\b\' + query + \'\\\\b\';\n
             } else {\n
               query = escapeRegex(query);\n
             }\n
@@ -1118,15 +1280,27 @@
         function onPromptClose(input) {\n
           // Give the prompt some time to close so that if processCommand shows\n
           // an error, the elements don\'t overlap.\n
+          vimGlobalState.exCommandHistoryController.pushInput(input);\n
+          vimGlobalState.exCommandHistoryController.reset();\n
           exCommandDispatcher.processCommand(cm, input);\n
         }\n
-        function onPromptKeyDown(e, _input, close) {\n
-          var keyName = CodeMirror.keyName(e);\n
+        function onPromptKeyDown(e, input, close) {\n
+          var keyName = CodeMirror.keyName(e), up;\n
           if (keyName == \'Esc\' || keyName == \'Ctrl-C\' || keyName == \'Ctrl-[\') {\n
+            vimGlobalState.exCommandHistoryController.pushInput(input);\n
+            vimGlobalState.exCommandHistoryController.reset();\n
             CodeMirror.e_stop(e);\n
             close();\n
             cm.focus();\n
           }\n
+          if (keyName == \'Up\' || keyName == \'Down\') {\n
+            up = keyName == \'Up\' ? true : false;\n
+            input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || \'\';\n
+            close(input);\n
+          } else {\n
+            if ( keyName != \'Left\' && keyName != \'Right\' && keyName != \'Ctrl\' && keyName != \'Alt\' && keyName != \'Shift\')\n
+              vimGlobalState.exCommandHistoryController.reset();\n
+          }\n
         }\n
         if (command.type == \'keyToEx\') {\n
           // Handle user defined Ex to Ex mappings\n
@@ -1150,13 +1324,13 @@
         var operator = inputState.operator;\n
         var operatorArgs = inputState.operatorArgs || {};\n
         var registerName = inputState.registerName;\n
-        var selectionEnd = cm.getCursor(\'head\');\n
-        var selectionStart = cm.getCursor(\'anchor\');\n
-        // The difference between cur and selection cursors are that cur is\n
-        // being operated on and ignores that there is a selection.\n
-        var curStart = copyCursor(selectionEnd);\n
-        var curOriginal = copyCursor(curStart);\n
-        var curEnd;\n
+        var sel = vim.sel;\n
+        // TODO: Make sure cm and vim selections are identical outside visual mode.\n
+        var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor(\'head\'));\n
+        var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor(\'anchor\'));\n
+        var oldHead = copyCursor(origHead);\n
+        var oldAnchor = copyCursor(origAnchor);\n
+        var newHead, newAnchor;\n
         var repeat;\n
         if (operator) {\n
           this.recordLastEdit(vim, inputState);\n
@@ -1181,9 +1355,9 @@
               inputState.selectedCharacter;\n
         }\n
         motionArgs.repeat = repeat;\n
-        vim.inputState = new InputState();\n
+        clearInputState(cm);\n
         if (motion) {\n
-          var motionResult = motions[motion](cm, motionArgs, vim);\n
+          var motionResult = motions[motion](cm, origHead, motionArgs, vim);\n
           vim.lastMotion = motions[motion];\n
           if (!motionResult) {\n
             return;\n
@@ -1196,105 +1370,146 @@
               recordJumpPosition(cm, cachedCursor, motionResult);\n
               delete jumpList.cachedCursor;\n
             } else {\n
-              recordJumpPosition(cm, curOriginal, motionResult);\n
+              recordJumpPosition(cm, origHead, motionResult);\n
             }\n
           }\n
           if (motionResult instanceof Array) {\n
-            curStart = motionResult[0];\n
-            curEnd = motionResult[1];\n
+            newAnchor = motionResult[0];\n
+            newHead = motionResult[1];\n
           } else {\n
-            curEnd = motionResult;\n
+            newHead = motionResult;\n
           }\n
           // TODO: Handle null returns from motion commands better.\n
-          if (!curEnd) {\n
-            curEnd = { ch: curStart.ch, line: curStart.line };\n
+          if (!newHead) {\n
+            newHead = copyCursor(origHead);\n
           }\n
           if (vim.visualMode) {\n
-            // Check if the selection crossed over itself. Will need to shift\n
-            // the start point if that happened.\n
-            if (cursorIsBefore(selectionStart, selectionEnd) &&\n
-                (cursorEqual(selectionStart, curEnd) ||\n
-                    cursorIsBefore(curEnd, selectionStart))) {\n
-              // The end of the selection has moved from after the start to\n
-              // before the start. We will shift the start right by 1.\n
-              selectionStart.ch += 1;\n
-            } else if (cursorIsBefore(selectionEnd, selectionStart) &&\n
-                (cursorEqual(selectionStart, curEnd) ||\n
-                    cursorIsBefore(selectionStart, curEnd))) {\n
-              // The opposite happened. We will shift the start left by 1.\n
-              selectionStart.ch -= 1;\n
+            if (!(vim.visualBlock && newHead.ch === Infinity)) {\n
+              newHead = clipCursorToContent(cm, newHead, vim.visualBlock);\n
             }\n
-            selectionEnd = curEnd;\n
-            if (vim.visualLine) {\n
-              if (cursorIsBefore(selectionStart, selectionEnd)) {\n
-                selectionStart.ch = 0;\n
-\n
-                var lastLine = cm.lastLine();\n
-                if (selectionEnd.line > lastLine) {\n
-                  selectionEnd.line = lastLine;\n
-                }\n
-                selectionEnd.ch = lineLength(cm, selectionEnd.line);\n
-              } else {\n
-                selectionEnd.ch = 0;\n
-                selectionStart.ch = lineLength(cm, selectionStart.line);\n
-              }\n
+            if (newAnchor) {\n
+              newAnchor = clipCursorToContent(cm, newAnchor, true);\n
             }\n
-            cm.setSelection(selectionStart, selectionEnd);\n
+            newAnchor = newAnchor || oldAnchor;\n
+            sel.anchor = newAnchor;\n
+            sel.head = newHead;\n
+            updateCmSelection(cm);\n
             updateMark(cm, vim, \'<\',\n
-                cursorIsBefore(selectionStart, selectionEnd) ? selectionStart\n
-                    : selectionEnd);\n
+                cursorIsBefore(newAnchor, newHead) ? newAnchor\n
+                    : newHead);\n
             updateMark(cm, vim, \'>\',\n
-                cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd\n
-                    : selectionStart);\n
+                cursorIsBefore(newAnchor, newHead) ? newHead\n
+                    : newAnchor);\n
           } else if (!operator) {\n
-            curEnd = clipCursorToContent(cm, curEnd);\n
-            cm.setCursor(curEnd.line, curEnd.ch);\n
+            newHead = clipCursorToContent(cm, newHead);\n
+            cm.setCursor(newHead.line, newHead.ch);\n
           }\n
         }\n
-\n
         if (operator) {\n
-          var inverted = false;\n
-          vim.lastMotion = null;\n
-          operatorArgs.repeat = repeat; // Indent in visual mode needs this.\n
+          if (operatorArgs.lastSel) {\n
+            // Replaying a visual mode operation\n
+            newAnchor = oldAnchor;\n
+            var lastSel = operatorArgs.lastSel;\n
+            var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line);\n
+            var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch);\n
+            if (lastSel.visualLine) {\n
+              // Linewise Visual mode: The same number of lines.\n
+              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);\n
+            } else if (lastSel.visualBlock) {\n
+              // Blockwise Visual mode: The same number of lines and columns.\n
+              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset);\n
+            } else if (lastSel.head.line == lastSel.anchor.line) {\n
+              // Normal Visual mode within one line: The same number of characters.\n
+              newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset);\n
+            } else {\n
+              // Normal Visual mode with several lines: The same number of lines, in the\n
+              // last line the same number of characters as in the last line the last time.\n
+              newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch);\n
+            }\n
+            vim.visualMode = true;\n
+            vim.visualLine = lastSel.visualLine;\n
+            vim.visualBlock = lastSel.visualBlock;\n
+            sel = vim.sel = {\n
+              anchor: newAnchor,\n
+              head: newHead\n
+            };\n
+            updateCmSelection(cm);\n
+          } else if (vim.visualMode) {\n
+            operatorArgs.lastSel = {\n
+              anchor: copyCursor(sel.anchor),\n
+              head: copyCursor(sel.head),\n
+              visualBlock: vim.visualBlock,\n
+              visualLine: vim.visualLine\n
+            };\n
+          }\n
+          var curStart, curEnd, linewise, mode;\n
+          var cmSel;\n
           if (vim.visualMode) {\n
-            curStart = selectionStart;\n
-            curEnd = selectionEnd;\n
-            motionArgs.inclusive = true;\n
-          }\n
-          // Swap start and end if motion was backward.\n
-          if (cursorIsBefore(curEnd, curStart)) {\n
-            var tmp = curStart;\n
-            curStart = curEnd;\n
-            curEnd = tmp;\n
-            inverted = true;\n
-          }\n
-          if (motionArgs.inclusive && !(vim.visualMode && inverted)) {\n
-            // Move the selection end one to the right to include the last\n
-            // character.\n
-            curEnd.ch++;\n
-          }\n
-          var linewise = motionArgs.linewise ||\n
-              (vim.visualMode && vim.visualLine);\n
-          if (linewise) {\n
-            // Expand selection to entire line.\n
-            expandSelectionToLine(cm, curStart, curEnd);\n
-          } else if (motionArgs.forward) {\n
-            // Clip to trailing newlines only if the motion goes forward.\n
-            clipToLine(cm, curStart, curEnd);\n
+            // Init visual op\n
+            curStart = cursorMin(sel.head, sel.anchor);\n
+            curEnd = cursorMax(sel.head, sel.anchor);\n
+            linewise = vim.visualLine || operatorArgs.linewise;\n
+            mode = vim.visualBlock ? \'block\' :\n
+                   linewise ? \'line\' :\n
+                   \'char\';\n
+            cmSel = makeCmSelection(cm, {\n
+              anchor: curStart,\n
+              head: curEnd\n
+            }, mode);\n
+            if (linewise) {\n
+              var ranges = cmSel.ranges;\n
+              if (mode == \'block\') {\n
+                // Linewise operators in visual block mode extend to end of line\n
+                for (var i = 0; i < ranges.length; i++) {\n
+                  ranges[i].head.ch = lineLength(cm, ranges[i].head.line);\n
+                }\n
+              } else if (mode == \'line\') {\n
+                ranges[0].head = Pos(ranges[0].head.line + 1, 0);\n
+              }\n
+            }\n
+          } else {\n
+            // Init motion op\n
+            curStart = copyCursor(newAnchor || oldAnchor);\n
+            curEnd = copyCursor(newHead || oldHead);\n
+            if (cursorIsBefore(curEnd, curStart)) {\n
+              var tmp = curStart;\n
+              curStart = curEnd;\n
+              curEnd = tmp;\n
+            }\n
+            linewise = motionArgs.linewise || operatorArgs.linewise;\n
+            if (linewise) {\n
+              // Expand selection to entire line.\n
+              expandSelectionToLine(cm, curStart, curEnd);\n
+            } else if (motionArgs.forward) {\n
+              // Clip to trailing newlines only if the motion goes forward.\n
+              clipToLine(cm, curStart, curEnd);\n
+            }\n
+            mode = \'char\';\n
+            var exclusive = !motionArgs.inclusive || linewise;\n
+            cmSel = makeCmSelection(cm, {\n
+              anchor: curStart,\n
+              head: curEnd\n
+            }, mode, exclusive);\n
           }\n
+          cm.setSelections(cmSel.ranges, cmSel.primary);\n
+          vim.lastMotion = null;\n
+          operatorArgs.repeat = repeat; // For indent in visual mode.\n
           operatorArgs.registerName = registerName;\n
           // Keep track of linewise as it affects how paste and change behave.\n
           operatorArgs.linewise = linewise;\n
-          operators[operator](cm, operatorArgs, vim, curStart,\n
-              curEnd, curOriginal);\n
+          var operatorMoveTo = operators[operator](\n
+            cm, operatorArgs, cmSel.ranges, oldAnchor, newHead);\n
           if (vim.visualMode) {\n
             exitVisualMode(cm);\n
           }\n
+          if (operatorMoveTo) {\n
+            cm.setCursor(operatorMoveTo);\n
+          }\n
         }\n
       },\n
       recordLastEdit: function(vim, inputState, actionCommand) {\n
         var macroModeState = vimGlobalState.macroModeState;\n
-        if (macroModeState.inReplay) { return; }\n
+        if (macroModeState.isPlaying) { return; }\n
         vim.lastEditInputState = inputState;\n
         vim.lastEditActionCommand = actionCommand;\n
         macroModeState.lastInsertModeChanges.changes = [];\n
@@ -1308,26 +1523,26 @@
      */\n
     // All of the functions below return Cursor objects.\n
     var motions = {\n
-      moveToTopLine: function(cm, motionArgs) {\n
+      moveToTopLine: function(cm, _head, motionArgs) {\n
         var line = getUserVisibleLines(cm).top + motionArgs.repeat -1;\n
-        return { line: line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(line)) };\n
+        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));\n
       },\n
       moveToMiddleLine: function(cm) {\n
         var range = getUserVisibleLines(cm);\n
         var line = Math.floor((range.top + range.bottom) * 0.5);\n
-        return { line: line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(line)) };\n
+        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));\n
       },\n
-      moveToBottomLine: function(cm, motionArgs) {\n
+      moveToBottomLine: function(cm, _head, motionArgs) {\n
         var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1;\n
-        return { line: line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(line)) };\n
+        return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line)));\n
       },\n
-      expandToLine: function(cm, motionArgs) {\n
+      expandToLine: function(_cm, head, motionArgs) {\n
         // Expands forward to end of line, and then to next line if repeat is\n
         // >1. Does not handle backward motion!\n
-        var cur = cm.getCursor();\n
-        return { line: cur.line + motionArgs.repeat - 1, ch: Infinity };\n
+        var cur = head;\n
+        return Pos(cur.line + motionArgs.repeat - 1, Infinity);\n
       },\n
-      findNext: function(cm, motionArgs) {\n
+      findNext: function(cm, _head, motionArgs) {\n
         var state = getSearchState(cm);\n
         var query = state.getQuery();\n
         if (!query) {\n
@@ -1339,15 +1554,27 @@
         highlightSearchMatches(cm, query);\n
         return findNext(cm, prev/** prev */, query, motionArgs.repeat);\n
       },\n
-      goToMark: function(_cm, motionArgs, vim) {\n
+      goToMark: function(cm, _head, motionArgs, vim) {\n
         var mark = vim.marks[motionArgs.selectedCharacter];\n
         if (mark) {\n
-          return mark.find();\n
+          var pos = mark.find();\n
+          return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos;\n
         }\n
         return null;\n
       },\n
-      jumpToMark: function(cm, motionArgs, vim) {\n
-        var best = cm.getCursor();\n
+      moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) {\n
+        if (vim.visualBlock && motionArgs.sameLine) {\n
+          var sel = vim.sel;\n
+          return [\n
+            clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)),\n
+            clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch))\n
+          ];\n
+        } else {\n
+          return ([vim.sel.head, vim.sel.anchor]);\n
+        }\n
+      },\n
+      jumpToMark: function(cm, head, motionArgs, vim) {\n
+        var best = head;\n
         for (var i = 0; i < motionArgs.repeat; i++) {\n
           var cursor = best;\n
           for (var key in vim.marks) {\n
@@ -1367,8 +1594,8 @@
 \n
             var equal = cursorEqual(cursor, best);\n
             var between = (motionArgs.forward) ?\n
-              cusrorIsBetween(cursor, mark, best) :\n
-              cusrorIsBetween(best, mark, cursor);\n
+              cursorIsBetween(cursor, mark, best) :\n
+              cursorIsBetween(best, mark, cursor);\n
 \n
             if (equal || between) {\n
               best = mark;\n
@@ -1380,18 +1607,18 @@
           // Vim places the cursor on the first non-whitespace character of\n
           // the line if there is one, else it places the cursor at the end\n
           // of the line, regardless of whether a mark was found.\n
-          best.ch = findFirstNonWhiteSpaceCharacter(cm.getLine(best.line));\n
+          best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line)));\n
         }\n
         return best;\n
       },\n
-      moveByCharacters: function(cm, motionArgs) {\n
-        var cur = cm.getCursor();\n
+      moveByCharacters: function(_cm, head, motionArgs) {\n
+        var cur = head;\n
         var repeat = motionArgs.repeat;\n
         var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat;\n
-        return { line: cur.line, ch: ch };\n
+        return Pos(cur.line, ch);\n
       },\n
-      moveByLines: function(cm, motionArgs, vim) {\n
-        var cur = cm.getCursor();\n
+      moveByLines: function(cm, head, motionArgs, vim) {\n
+        var cur = head;\n
         var endCh = cur.ch;\n
         // Depending what our last motion was, we may want to do different\n
         // things. If our last motion was moving vertically, we want to\n
@@ -1419,15 +1646,15 @@
             (line > last && cur.line == last)) {\n
           return;\n
         }\n
-        if(motionArgs.toFirstChar){\n
+        if (motionArgs.toFirstChar){\n
           endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));\n
           vim.lastHPos = endCh;\n
         }\n
-        vim.lastHSPos = cm.charCoords({line:line, ch:endCh},\'div\').left;\n
-        return { line: line, ch: endCh };\n
+        vim.lastHSPos = cm.charCoords(Pos(line, endCh),\'div\').left;\n
+        return Pos(line, endCh);\n
       },\n
-      moveByDisplayLines: function(cm, motionArgs, vim) {\n
-        var cur = cm.getCursor();\n
+      moveByDisplayLines: function(cm, head, motionArgs, vim) {\n
+        var cur = head;\n
         switch (vim.lastMotion) {\n
           case this.moveByDisplayLines:\n
           case this.moveByScroll:\n
@@ -1446,7 +1673,7 @@
             var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos };\n
             var res = cm.coordsChar(goalCoords, \'div\');\n
           } else {\n
-            var resCoords = cm.charCoords({ line: cm.firstLine(), ch: 0}, \'div\');\n
+            var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), \'div\');\n
             resCoords.left = vim.lastHSPos;\n
             res = cm.coordsChar(resCoords, \'div\');\n
           }\n
@@ -1454,43 +1681,28 @@
         vim.lastHPos = res.ch;\n
         return res;\n
       },\n
-      moveByPage: function(cm, motionArgs) {\n
+      moveByPage: function(cm, head, motionArgs) {\n
         // CodeMirror only exposes functions that move the cursor page down, so\n
         // doing this bad hack to move the cursor and move it back. evalInput\n
         // will move the cursor to where it should be in the end.\n
-        var curStart = cm.getCursor();\n
+        var curStart = head;\n
         var repeat = motionArgs.repeat;\n
-        cm.moveV((motionArgs.forward ? repeat : -repeat), \'page\');\n
-        var curEnd = cm.getCursor();\n
-        cm.setCursor(curStart);\n
-        return curEnd;\n
+        return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), \'page\');\n
       },\n
-      moveByParagraph: function(cm, motionArgs) {\n
-        var line = cm.getCursor().line;\n
-        var repeat = motionArgs.repeat;\n
-        var inc = motionArgs.forward ? 1 : -1;\n
-        for (var i = 0; i < repeat; i++) {\n
-          if ((!motionArgs.forward && line === cm.firstLine() ) ||\n
-              (motionArgs.forward && line == cm.lastLine())) {\n
-            break;\n
-          }\n
-          line += inc;\n
-          while (line !== cm.firstLine() && line != cm.lastLine() && cm.getLine(line)) {\n
-            line += inc;\n
-          }\n
-        }\n
-        return { line: line, ch: 0 };\n
+      moveByParagraph: function(cm, head, motionArgs) {\n
+        var dir = motionArgs.forward ? 1 : -1;\n
+        return findParagraph(cm, head, motionArgs.repeat, dir);\n
       },\n
-      moveByScroll: function(cm, motionArgs, vim) {\n
+      moveByScroll: function(cm, head, motionArgs, vim) {\n
         var scrollbox = cm.getScrollInfo();\n
         var curEnd = null;\n
         var repeat = motionArgs.repeat;\n
         if (!repeat) {\n
           repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight());\n
         }\n
-        var orig = cm.charCoords(cm.getCursor(), \'local\');\n
+        var orig = cm.charCoords(head, \'local\');\n
         motionArgs.repeat = repeat;\n
-        var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim);\n
+        var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim);\n
         if (!curEnd) {\n
           return null;\n
         }\n
@@ -1498,11 +1710,11 @@
         cm.scrollTo(null, scrollbox.top + dest.top - orig.top);\n
         return curEnd;\n
       },\n
-      moveByWords: function(cm, motionArgs) {\n
-        return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward,\n
+      moveByWords: function(cm, head, motionArgs) {\n
+        return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward,\n
             !!motionArgs.wordEnd, !!motionArgs.bigWord);\n
       },\n
-      moveTillCharacter: function(cm, motionArgs) {\n
+      moveTillCharacter: function(cm, _head, motionArgs) {\n
         var repeat = motionArgs.repeat;\n
         var curEnd = moveToCharacter(cm, repeat, motionArgs.forward,\n
             motionArgs.selectedCharacter);\n
@@ -1512,77 +1724,74 @@
         curEnd.ch += increment;\n
         return curEnd;\n
       },\n
-      moveToCharacter: function(cm, motionArgs) {\n
+      moveToCharacter: function(cm, head, motionArgs) {\n
         var repeat = motionArgs.repeat;\n
         recordLastCharacterSearch(0, motionArgs);\n
         return moveToCharacter(cm, repeat, motionArgs.forward,\n
-            motionArgs.selectedCharacter) || cm.getCursor();\n
+            motionArgs.selectedCharacter) || head;\n
       },\n
-      moveToSymbol: function(cm, motionArgs) {\n
+      moveToSymbol: function(cm, head, motionArgs) {\n
         var repeat = motionArgs.repeat;\n
         return findSymbol(cm, repeat, motionArgs.forward,\n
-            motionArgs.selectedCharacter) || cm.getCursor();\n
+            motionArgs.selectedCharacter) || head;\n
       },\n
-      moveToColumn: function(cm, motionArgs, vim) {\n
+      moveToColumn: function(cm, head, motionArgs, vim) {\n
         var repeat = motionArgs.repeat;\n
         // repeat is equivalent to which column we want to move to!\n
         vim.lastHPos = repeat - 1;\n
-        vim.lastHSPos = cm.charCoords(cm.getCursor(),\'div\').left;\n
+        vim.lastHSPos = cm.charCoords(head,\'div\').left;\n
         return moveToColumn(cm, repeat);\n
       },\n
-      moveToEol: function(cm, motionArgs, vim) {\n
-        var cur = cm.getCursor();\n
+      moveToEol: function(cm, head, motionArgs, vim) {\n
+        var cur = head;\n
         vim.lastHPos = Infinity;\n
-        var retval={ line: cur.line + motionArgs.repeat - 1, ch: Infinity };\n
+        var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity);\n
         var end=cm.clipPos(retval);\n
         end.ch--;\n
         vim.lastHSPos = cm.charCoords(end,\'div\').left;\n
         return retval;\n
       },\n
-      moveToFirstNonWhiteSpaceCharacter: function(cm) {\n
+      moveToFirstNonWhiteSpaceCharacter: function(cm, head) {\n
         // Go to the start of the line where the text begins, or the end for\n
         // whitespace-only lines\n
-        var cursor = cm.getCursor();\n
-        return { line: cursor.line,\n
-            ch: findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line)) };\n
+        var cursor = head;\n
+        return Pos(cursor.line,\n
+                   findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line)));\n
       },\n
-      moveToMatchedSymbol: function(cm) {\n
-        var cursor = cm.getCursor();\n
+      moveToMatchedSymbol: function(cm, head) {\n
+        var cursor = head;\n
         var line = cursor.line;\n
         var ch = cursor.ch;\n
         var lineText = cm.getLine(line);\n
         var symbol;\n
-        var startContext = cm.getTokenAt(cursor).type;\n
-        var startCtxLevel = getContextLevel(startContext);\n
         do {\n
           symbol = lineText.charAt(ch++);\n
           if (symbol && isMatchableSymbol(symbol)) {\n
-            var endContext = cm.getTokenAt({line:line, ch:ch}).type;\n
-            var endCtxLevel = getContextLevel(endContext);\n
-            if (startCtxLevel >= endCtxLevel) {\n
+            var style = cm.getTokenTypeAt(Pos(line, ch));\n
+            if (style !== "string" && style !== "comment") {\n
               break;\n
             }\n
           }\n
         } while (symbol);\n
         if (symbol) {\n
-          return findMatchedSymbol(cm, {line:line, ch:ch-1}, symbol);\n
+          var matched = cm.findMatchingBracket(Pos(line, ch));\n
+          return matched.to;\n
         } else {\n
           return cursor;\n
         }\n
       },\n
-      moveToStartOfLine: function(cm) {\n
-        var cursor = cm.getCursor();\n
-        return { line: cursor.line, ch: 0 };\n
+      moveToStartOfLine: function(_cm, head) {\n
+        return Pos(head.line, 0);\n
       },\n
-      moveToLineOrEdgeOfDocument: function(cm, motionArgs) {\n
+      moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) {\n
         var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine();\n
         if (motionArgs.repeatIsExplicit) {\n
           lineNum = motionArgs.repeat - cm.getOption(\'firstLineNumber\');\n
         }\n
-        return { line: lineNum,\n
-            ch: findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)) };\n
+        return Pos(lineNum,\n
+                   findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum)));\n
       },\n
-      textObjectManipulation: function(cm, motionArgs) {\n
+      textObjectManipulation: function(cm, head, motionArgs, vim) {\n
         // TODO: lots of possible exceptions that can be thrown here. Try da(\n
         //     outside of a () block.\n
 \n
@@ -1594,6 +1803,13 @@
         var selfPaired = {\'\\\'\': true, \'"\': true};\n
 \n
         var character = motionArgs.selectedCharacter;\n
+        // \'b\' refers to  \'()\' block.\n
+        // \'B\' refers to  \'{}\' block.\n
+        if (character == \'b\') {\n
+          character = \'(\';\n
+        } else if (character == \'B\') {\n
+          character = \'{\';\n
+        }\n
 \n
         // Inclusive is the difference between a and i\n
         // TODO: Instead of using the additional text object map to perform text\n
@@ -1604,24 +1820,38 @@
 \n
         var tmp;\n
         if (mirroredPairs[character]) {\n
-          tmp = selectCompanionObject(cm, mirroredPairs[character], inclusive);\n
+          tmp = selectCompanionObject(cm, head, character, inclusive);\n
         } else if (selfPaired[character]) {\n
-          tmp = findBeginningAndEnd(cm, character, inclusive);\n
+          tmp = findBeginningAndEnd(cm, head, character, inclusive);\n
         } else if (character === \'W\') {\n
           tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,\n
                                                      true /** bigWord */);\n
         } else if (character === \'w\') {\n
           tmp = expandWordUnderCursor(cm, inclusive, true /** forward */,\n
                                                      false /** bigWord */);\n
+        } else if (character === \'p\') {\n
+          tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive);\n
+          motionArgs.linewise = true;\n
+          if (vim.visualMode) {\n
+            if (!vim.visualLine) { vim.visualLine = true; }\n
+          } else {\n
+            var operatorArgs = vim.inputState.operatorArgs;\n
+            if (operatorArgs) { operatorArgs.linewise = true; }\n
+            tmp.end.line--;\n
+          }\n
         } else {\n
           // No text object defined for this, don\'t move.\n
           return null;\n
         }\n
 \n
-        return [tmp.start, tmp.end];\n
+        if (!cm.state.vim.visualMode) {\n
+          return [tmp.start, tmp.end];\n
+        } else {\n
+          return expandSelection(cm, tmp.start, tmp.end);\n
+        }\n
       },\n
 \n
-      repeatLastCharacterSearch: function(cm, motionArgs) {\n
+      repeatLastCharacterSearch: function(cm, head, motionArgs) {\n
         var lastSearch = vimGlobalState.lastChararacterSearch;\n
         var repeat = motionArgs.repeat;\n
         var forward = motionArgs.forward === lastSearch.forward;\n
@@ -1631,65 +1861,107 @@
         var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter);\n
         if (!curEnd) {\n
           cm.moveH(increment, \'char\');\n
-          return cm.getCursor();\n
+          return head;\n
         }\n
         curEnd.ch += increment;\n
         return curEnd;\n
       }\n
     };\n
 \n
+    function fillArray(val, times) {\n
+      var arr = [];\n
+      for (var i = 0; i < times; i++) {\n
+        arr.push(val);\n
+      }\n
+      return arr;\n
+    }\n
+    /**\n
+     * An operator acts on a text selection. It receives the list of selections\n
+     * as input. The corresponding CodeMirror selection is guaranteed to\n
+    * match the input selection.\n
+     */\n
     var operators = {\n
-      change: function(cm, operatorArgs, _vim, curStart, curEnd) {\n
-        vimGlobalState.registerController.pushText(\n
-            operatorArgs.registerName, \'change\', cm.getRange(curStart, curEnd),\n
-            operatorArgs.linewise);\n
-        if (operatorArgs.linewise) {\n
-          // Push the next line back down, if there is a next line.\n
-          var replacement = curEnd.line > cm.lastLine() ? \'\' : \'\\n\';\n
-          cm.replaceRange(replacement, curStart, curEnd);\n
-          cm.indentLine(curStart.line, \'smart\');\n
-          // null ch so setCursor moves to end of line.\n
-          curStart.ch = null;\n
-        } else {\n
-          // Exclude trailing whitespace if the range is not all whitespace.\n
-          var text = cm.getRange(curStart, curEnd);\n
+      change: function(cm, args, ranges) {\n
+        var finalHead, text;\n
+        var vim = cm.state.vim;\n
+        vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock;\n
+        if (!vim.visualMode) {\n
+          var anchor = ranges[0].anchor,\n
+              head = ranges[0].head;\n
+          text = cm.getRange(anchor, head);\n
           if (!isWhiteSpaceString(text)) {\n
+            // Exclude trailing whitespace if the range is not all whitespace.\n
             var match = (/\\s+$/).exec(text);\n
             if (match) {\n
-              curEnd = offsetCursor(curEnd, 0, - match[0].length);\n
+              head = offsetCursor(head, 0, - match[0].length);\n
+              text = text.slice(0, - match[0].length);\n
             }\n
           }\n
-          cm.replaceRange(\'\', curStart, curEnd);\n
+          var wasLastLine = head.line - 1 == cm.lastLine();\n
+          cm.replaceRange(\'\', anchor, head);\n
+          if (args.linewise && !wasLastLine) {\n
+            // Push the next line back down, if there is a next line.\n
+            CodeMirror.commands.newlineAndIndent(cm);\n
+            // null ch so setCursor moves to end of line.\n
+            anchor.ch = null;\n
+          }\n
+          finalHead = anchor;\n
+        } else {\n
+          text = cm.getSelection();\n
+          var replacement = fillArray(\'\', ranges.length);\n
+          cm.replaceSelections(replacement);\n
+          finalHead = cursorMin(ranges[0].head, ranges[0].anchor);\n
         }\n
-        actions.enterInsertMode(cm, {}, cm.state.vim);\n
-        cm.setCursor(curStart);\n
+        vimGlobalState.registerController.pushText(\n
+            args.registerName, \'change\', text,\n
+            args.linewise, ranges.length > 1);\n
+        actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim);\n
       },\n
       // delete is a javascript keyword.\n
-      \'delete\': function(cm, operatorArgs, _vim, curStart, curEnd) {\n
-        // If the ending line is past the last line, inclusive, instead of\n
-        // including the trailing \\n, include the \\n before the starting line\n
-        if (operatorArgs.linewise &&\n
-            curEnd.line > cm.lastLine() && curStart.line > cm.firstLine()) {\n
-          curStart.line--;\n
-          curStart.ch = lineLength(cm, curStart.line);\n
-        }\n
-        vimGlobalState.registerController.pushText(\n
-            operatorArgs.registerName, \'delete\', cm.getRange(curStart, curEnd),\n
-            operatorArgs.linewise);\n
-        cm.replaceRange(\'\', curStart, curEnd);\n
-        if (operatorArgs.linewise) {\n
-          cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));\n
+      \'delete\': function(cm, args, ranges) {\n
+        var finalHead, text;\n
+        var vim = cm.state.vim;\n
+        if (!vim.visualBlock) {\n
+          var anchor = ranges[0].anchor,\n
+              head = ranges[0].head;\n
+          if (args.linewise &&\n
+              head.line != cm.firstLine() &&\n
+              anchor.line == cm.lastLine() &&\n
+              anchor.line == head.line - 1) {\n
+            // Special case for dd on last line (and first line).\n
+            if (anchor.line == cm.firstLine()) {\n
+              anchor.ch = 0;\n
+            } else {\n
+              anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1));\n
+            }\n
+          }\n
+          text = cm.getRange(anchor, head);\n
+          cm.replaceRange(\'\', anchor, head);\n
+          finalHead = anchor;\n
+          if (args.linewise) {\n
+            finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor);\n
+          }\n
         } else {\n
-          cm.setCursor(curStart);\n
+          text = cm.getSelection();\n
+          var replacement = fillArray(\'\', ranges.length);\n
+          cm.replaceSelections(replacement);\n
+          finalHead = ranges[0].anchor;\n
         }\n
+        vimGlobalState.registerController.pushText(\n
+            args.registerName, \'delete\', text,\n
+            args.linewise, vim.visualBlock);\n
+        return finalHead;\n
       },\n
-      indent: function(cm, operatorArgs, vim, curStart, curEnd) {\n
-        var startLine = curStart.line;\n
-        var endLine = curEnd.line;\n
+      indent: function(cm, args, ranges) {\n
+        var vim = cm.state.vim;\n
+        var startLine = ranges[0].anchor.line;\n
+        var endLine = vim.visualBlock ?\n
+          ranges[ranges.length - 1].anchor.line :\n
+          ranges[0].head.line;\n
         // In visual mode, n> shifts the selection right n times, instead of\n
         // shifting n lines right once.\n
-        var repeat = (vim.visualMode) ? operatorArgs.repeat : 1;\n
-        if (operatorArgs.linewise) {\n
+        var repeat = (vim.visualMode) ? args.repeat : 1;\n
+        if (args.linewise) {\n
           // The only way to delete a newline is to delete until the start of\n
           // the next line, so in linewise mode evalInput will include the next\n
           // line. We don\'t want this in indent, so we go back a line.\n
@@ -1697,30 +1969,52 @@
         }\n
         for (var i = startLine; i <= endLine; i++) {\n
           for (var j = 0; j < repeat; j++) {\n
-            cm.indentLine(i, operatorArgs.indentRight);\n
+            cm.indentLine(i, args.indentRight);\n
           }\n
         }\n
-        cm.setCursor(curStart);\n
-        cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));\n
+        return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor);\n
       },\n
-      swapcase: function(cm, operatorArgs, _vim, curStart, curEnd, curOriginal) {\n
-        var toSwap = cm.getRange(curStart, curEnd);\n
-        var swapped = \'\';\n
-        for (var i = 0; i < toSwap.length; i++) {\n
-          var character = toSwap.charAt(i);\n
-          swapped += isUpperCase(character) ? character.toLowerCase() :\n
-              character.toUpperCase();\n
-        }\n
-        cm.replaceRange(swapped, curStart, curEnd);\n
-        if (!operatorArgs.shouldMoveCursor) {\n
-          cm.setCursor(curOriginal);\n
+      changeCase: function(cm, args, ranges, oldAnchor, newHead) {\n
+        var selections = cm.getSelections();\n
+        var swapped = [];\n
+        var toLower = args.toLower;\n
+        for (var j = 0; j < selections.length; j++) {\n
+          var toSwap = selections[j];\n
+          var text = \'\';\n
+          if (toLower === true) {\n
+            text = toSwap.toLowerCase();\n
+          } else if (toLower === false) {\n
+            text = toSwap.toUpperCase();\n
+          } else {\n
+            for (var i = 0; i < toSwap.length; i++) {\n
+              var character = toSwap.charAt(i);\n
+              text += isUpperCase(character) ? character.toLowerCase() :\n
+                  character.toUpperCase();\n
+            }\n
+          }\n
+          swapped.push(text);\n
+        }\n
+        cm.replaceSelections(swapped);\n
+        if (args.shouldMoveCursor){\n
+          return newHead;\n
+        } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) {\n
+          return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor);\n
+        } else if (args.linewise){\n
+          return oldAnchor;\n
+        } else {\n
+          return cursorMin(ranges[0].anchor, ranges[0].head);\n
         }\n
       },\n
-      yank: function(cm, operatorArgs, _vim, curStart, curEnd, curOriginal) {\n
+      yank: function(cm, args, ranges, oldAnchor) {\n
+        var vim = cm.state.vim;\n
+        var text = cm.getSelection();\n
+        var endPos = vim.visualMode\n
+          ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor)\n
+          : oldAnchor;\n
         vimGlobalState.registerController.pushText(\n
-            operatorArgs.registerName, \'yank\',\n
-            cm.getRange(curStart, curEnd), operatorArgs.linewise);\n
-        cm.setCursor(curOriginal);\n
+            args.registerName, \'yank\',\n
+            text, args.linewise, vim.visualBlock);\n
+        return endPos;\n
       }\n
     };\n
 \n
@@ -1747,7 +2041,7 @@
         var top = cm.getScrollInfo().top;\n
         var delta = lineHeight * repeat;\n
         var newPos = actionArgs.forward ? top + delta : top - delta;\n
-        var cursor = cm.getCursor();\n
+        var cursor = copyCursor(cm.getCursor());\n
         var cursorCoords = cm.charCoords(cursor, \'local\');\n
         if (actionArgs.forward) {\n
           if (newPos > cursorCoords.top) {\n
@@ -1777,7 +2071,7 @@
       },\n
       scrollToCursor: function(cm, actionArgs) {\n
         var lineNum = cm.getCursor().line;\n
-        var charCoords = cm.charCoords({line: lineNum, ch: 0}, \'local\');\n
+        var charCoords = cm.charCoords(Pos(lineNum, 0), \'local\');\n
         var height = cm.getScrollInfo().clientHeight;\n
         var y = charCoords.top;\n
         var lineHeight = charCoords.bottom - y;\n
@@ -1791,43 +2085,66 @@
         }\n
         cm.scrollTo(null, y);\n
       },\n
-      replayMacro: function(cm, actionArgs) {\n
+      replayMacro: function(cm, actionArgs, vim) {\n
         var registerName = actionArgs.selectedCharacter;\n
         var repeat = actionArgs.repeat;\n
         var macroModeState = vimGlobalState.macroModeState;\n
         if (registerName == \'@\') {\n
           registerName = macroModeState.latestRegister;\n
         }\n
-        var keyBuffer = parseRegisterToKeyBuffer(macroModeState, registerName);\n
         while(repeat--){\n
-          executeMacroKeyBuffer(cm, macroModeState, keyBuffer);\n
+          executeMacroRegister(cm, vim, macroModeState, registerName);\n
         }\n
       },\n
-      exitMacroRecordMode: function() {\n
-        var macroModeState = vimGlobalState.macroModeState;\n
-        macroModeState.toggle();\n
-        parseKeyBufferToRegister(macroModeState.latestRegister,\n
-                                 macroModeState.macroKeyBuffer);\n
-      },\n
       enterMacroRecordMode: function(cm, actionArgs) {\n
         var macroModeState = vimGlobalState.macroModeState;\n
         var registerName = actionArgs.selectedCharacter;\n
-        macroModeState.toggle(cm, registerName);\n
-        emptyMacroKeyBuffer(macroModeState);\n
+        macroModeState.enterMacroRecordMode(cm, registerName);\n
       },\n
       enterInsertMode: function(cm, actionArgs, vim) {\n
         if (cm.getOption(\'readOnly\')) { return; }\n
         vim.insertMode = true;\n
         vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1;\n
         var insertAt = (actionArgs) ? actionArgs.insertAt : null;\n
+        var sel = vim.sel;\n
+        var head = actionArgs.head || cm.getCursor(\'head\');\n
+        var height = cm.listSelections().length;\n
         if (insertAt == \'eol\') {\n
-          var cursor = cm.getCursor();\n
-          cursor = { line: cursor.line, ch: lineLength(cm, cursor.line) };\n
-          cm.setCursor(cursor);\n
+          head = Pos(head.line, lineLength(cm, head.line));\n
         } else if (insertAt == \'charAfter\') {\n
-          cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));\n
+          head = offsetCursor(head, 0, 1);\n
         } else if (insertAt == \'firstNonBlank\') {\n
-          cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));\n
+          head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head);\n
+        } else if (insertAt == \'startOfSelectedArea\') {\n
+          if (!vim.visualBlock) {\n
+            if (sel.head.line < sel.anchor.line) {\n
+              head = sel.head;\n
+            } else {\n
+              head = Pos(sel.anchor.line, 0);\n
+            }\n
+          } else {\n
+            head = Pos(\n
+                Math.min(sel.head.line, sel.anchor.line),\n
+                Math.min(sel.head.ch, sel.anchor.ch));\n
+            height = Math.abs(sel.head.line - sel.anchor.line) + 1;\n
+          }\n
+        } else if (insertAt == \'endOfSelectedArea\') {\n
+          if (!vim.visualBlock) {\n
+            if (sel.head.line >= sel.anchor.line) {\n
+              head = offsetCursor(sel.head, 0, 1);\n
+            } else {\n
+              head = Pos(sel.anchor.line, 0);\n
+            }\n
+          } else {\n
+            head = Pos(\n
+                Math.min(sel.head.line, sel.anchor.line),\n
+                Math.max(sel.head.ch + 1, sel.anchor.ch));\n
+            height = Math.abs(sel.head.line - sel.anchor.line) + 1;\n
+          }\n
+        } else if (insertAt == \'inplace\') {\n
+          if (vim.visualMode){\n
+            return;\n
+          }\n
         }\n
         cm.setOption(\'keyMap\', \'vim-insert\');\n
         cm.setOption(\'disableInput\', false);\n
@@ -1840,73 +2157,77 @@
           cm.setOption(\'keyMap\', \'vim-insert\');\n
           CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});\n
         }\n
-        if (!vimGlobalState.macroModeState.inReplay) {\n
+        if (!vimGlobalState.macroModeState.isPlaying) {\n
           // Only record if not replaying.\n
           cm.on(\'change\', onChange);\n
-          cm.on(\'cursorActivity\', onCursorActivity);\n
           CodeMirror.on(cm.getInputField(), \'keydown\', onKeyEventTargetKeyDown);\n
         }\n
+        if (vim.visualMode) {\n
+          exitVisualMode(cm);\n
+        }\n
+        selectForInsert(cm, head, height);\n
       },\n
       toggleVisualMode: function(cm, actionArgs, vim) {\n
         var repeat = actionArgs.repeat;\n
-        var curStart = cm.getCursor();\n
-        var curEnd;\n
+        var anchor = cm.getCursor();\n
+        var head;\n
         // TODO: The repeat should actually select number of characters/lines\n
         //     equal to the repeat times the size of the previous visual\n
         //     operation.\n
         if (!vim.visualMode) {\n
-          cm.on(\'mousedown\', exitVisualMode);\n
+          // Entering visual mode\n
           vim.visualMode = true;\n
           vim.visualLine = !!actionArgs.linewise;\n
-          if (vim.visualLine) {\n
-            curStart.ch = 0;\n
-            curEnd = clipCursorToContent(cm, {\n
-              line: curStart.line + repeat - 1,\n
-              ch: lineLength(cm, curStart.line)\n
-            }, true /** includeLineBreak */);\n
-          } else {\n
-            curEnd = clipCursorToContent(cm, {\n
-              line: curStart.line,\n
-              ch: curStart.ch + repeat\n
-            }, true /** includeLineBreak */);\n
-          }\n
-          // Make the initial selection.\n
-          if (!actionArgs.repeatIsExplicit && !vim.visualLine) {\n
-            // This is a strange case. Here the implicit repeat is 1. The\n
-            // following commands lets the cursor hover over the 1 character\n
-            // selection.\n
-            cm.setCursor(curEnd);\n
-            cm.setSelection(curEnd, curStart);\n
-          } else {\n
-            cm.setSelection(curStart, curEnd);\n
-          }\n
-          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""});\n
+          vim.visualBlock = !!actionArgs.blockwise;\n
+          head = clipCursorToContent(\n
+              cm, Pos(anchor.line, anchor.ch + repeat - 1),\n
+              true /** includeLineBreak */);\n
+          vim.sel = {\n
+            anchor: anchor,\n
+            head: head\n
+          };\n
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});\n
+          updateCmSelection(cm);\n
+          updateMark(cm, vim, \'<\', cursorMin(anchor, head));\n
+          updateMark(cm, vim, \'>\', cursorMax(anchor, head));\n
+        } else if (vim.visualLine ^ actionArgs.linewise ||\n
+            vim.visualBlock ^ actionArgs.blockwise) {\n
+          // Toggling between modes\n
+          vim.visualLine = !!actionArgs.linewise;\n
+          vim.visualBlock = !!actionArgs.blockwise;\n
+          CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""});\n
+          updateCmSelection(cm);\n
         } else {\n
-          curStart = cm.getCursor(\'anchor\');\n
-          curEnd = cm.getCursor(\'head\');\n
-          if (!vim.visualLine && actionArgs.linewise) {\n
-            // Shift-V pressed in characterwise visual mode. Switch to linewise\n
-            // visual mode instead of exiting visual mode.\n
-            vim.visualLine = true;\n
-            curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 :\n
-                lineLength(cm, curStart.line);\n
-            curEnd.ch = cursorIsBefore(curStart, curEnd) ?\n
-                lineLength(cm, curEnd.line) : 0;\n
-            cm.setSelection(curStart, curEnd);\n
-            CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"});\n
-          } else if (vim.visualLine && !actionArgs.linewise) {\n
-            // v pressed in linewise visual mode. Switch to characterwise visual\n
-            // mode instead of exiting visual mode.\n
-            vim.visualLine = false;\n
-            CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});\n
-          } else {\n
-            exitVisualMode(cm);\n
+          exitVisualMode(cm);\n
+        }\n
+      },\n
+      reselectLastSelection: function(cm, _actionArgs, vim) {\n
+        var lastSelection = vim.lastSelection;\n
+        if (vim.visualMode) {\n
+          updateLastSelection(cm, vim);\n
+        }\n
+        if (lastSelection) {\n
+          var anchor = lastSelection.anchorMark.find();\n
+          var head = lastSelection.headMark.find();\n
+          if (!anchor || !head) {\n
+            // If the marks have been destroyed due to edits, do nothing.\n
+            return;\n
           }\n
+          vim.sel = {\n
+            anchor: anchor,\n
+            head: head\n
+          };\n
+          vim.visualMode = true;\n
+          vim.visualLine = lastSelection.visualLine;\n
+          vim.visualBlock = lastSelection.visualBlock;\n
+          updateCmSelection(cm);\n
+          updateMark(cm, vim, \'<\', cursorMin(anchor, head));\n
+          updateMark(cm, vim, \'>\', cursorMax(anchor, head));\n
+          CodeMirror.signal(cm, \'vim-mode-change\', {\n
+            mode: \'visual\',\n
+            subMode: vim.visualLine ? \'linewise\' :\n
+                     vim.visualBlock ? \'blockwise\' : \'\'});\n
         }\n
-        updateMark(cm, vim, \'<\', cursorIsBefore(curStart, curEnd) ? curStart\n
-            : curEnd);\n
-        updateMark(cm, vim, \'>\', cursorIsBefore(curStart, curEnd) ? curEnd\n
-            : curStart);\n
       },\n
       joinLines: function(cm, actionArgs, vim) {\n
         var curStart, curEnd;\n
@@ -1918,29 +2239,30 @@
           // Repeat is the number of lines to join. Minimum 2 lines.\n
           var repeat = Math.max(actionArgs.repeat, 2);\n
           curStart = cm.getCursor();\n
-          curEnd = clipCursorToContent(cm, { line: curStart.line + repeat - 1,\n
-              ch: Infinity });\n
+          curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1,\n
+                                               Infinity));\n
         }\n
         var finalCh = 0;\n
-        cm.operation(function() {\n
-          for (var i = curStart.line; i < curEnd.line; i++) {\n
-            finalCh = lineLength(cm, curStart.line);\n
-            var tmp = { line: curStart.line + 1,\n
-                ch: lineLength(cm, curStart.line + 1) };\n
-            var text = cm.getRange(curStart, tmp);\n
-            text = text.replace(/\\n\\s*/g, \' \');\n
-            cm.replaceRange(text, curStart, tmp);\n
-          }\n
-          var curFinalPos = { line: curStart.line, ch: finalCh };\n
-          cm.setCursor(curFinalPos);\n
-        });\n
+        for (var i = curStart.line; i < curEnd.line; i++) {\n
+          finalCh = lineLength(cm, curStart.line);\n
+          var tmp = Pos(curStart.line + 1,\n
+                        lineLength(cm, curStart.line + 1));\n
+          var text = cm.getRange(curStart, tmp);\n
+          text = text.replace(/\\n\\s*/g, \' \');\n
+          cm.replaceRange(text, curStart, tmp);\n
+        }\n
+        var curFinalPos = Pos(curStart.line, finalCh);\n
+        cm.setCursor(curFinalPos);\n
+        if (vim.visualMode) {\n
+          exitVisualMode(cm);\n
+        }\n
       },\n
       newLineAndEnterInsertMode: function(cm, actionArgs, vim) {\n
         vim.insertMode = true;\n
-        var insertAt = cm.getCursor();\n
+        var insertAt = copyCursor(cm.getCursor());\n
         if (insertAt.line === cm.firstLine() && !actionArgs.after) {\n
           // Special case for inserting newline before start of document.\n
-          cm.replaceRange(\'\\n\', { line: cm.firstLine(), ch: 0 });\n
+          cm.replaceRange(\'\\n\', Pos(cm.firstLine(), 0));\n
           cm.setCursor(cm.firstLine(), 0);\n
         } else {\n
           insertAt.line = (actionArgs.after) ? insertAt.line :\n
@@ -1953,19 +2275,52 @@
         }\n
         this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim);\n
       },\n
-      paste: function(cm, actionArgs) {\n
-        var cur = cm.getCursor();\n
+      paste: function(cm, actionArgs, vim) {\n
+        var cur = copyCursor(cm.getCursor());\n
         var register = vimGlobalState.registerController.getRegister(\n
             actionArgs.registerName);\n
-        if (!register.text) {\n
+        var text = register.toString();\n
+        if (!text) {\n
           return;\n
         }\n
-        for (var text = \'\', i = 0; i < actionArgs.repeat; i++) {\n
-          text += register.text;\n
+        if (actionArgs.matchIndent) {\n
+          var tabSize = cm.getOption("tabSize");\n
+          // length that considers tabs and tabSize\n
+          var whitespaceLength = function(str) {\n
+            var tabs = (str.split("\\t").length - 1);\n
+            var spaces = (str.split(" ").length - 1);\n
+            return tabs * tabSize + spaces * 1;\n
+          };\n
+          var currentLine = cm.getLine(cm.getCursor().line);\n
+          var indent = whitespaceLength(currentLine.match(/^\\s*/)[0]);\n
+          // chomp last newline b/c don\'t want it to match /^\\s*/gm\n
+          var chompedText = text.replace(/\\n$/, \'\');\n
+          var wasChomped = text !== chompedText;\n
+          var firstIndent = whitespaceLength(text.match(/^\\s*/)[0]);\n
+          var text = chompedText.replace(/^\\s*/gm, function(wspace) {\n
+            var newIndent = indent + (whitespaceLength(wspace) - firstIndent);\n
+            if (newIndent < 0) {\n
+              return "";\n
+            }\n
+            else if (cm.getOption("indentWithTabs")) {\n
+              var quotient = Math.floor(newIndent / tabSize);\n
+              return Array(quotient + 1).join(\'\\t\');\n
+            }\n
+            else {\n
+              return Array(newIndent + 1).join(\' \');\n
+            }\n
+          });\n
+          text += wasChomped ? "\\n" : "";\n
+        }\n
+        if (actionArgs.repeat > 1) {\n
+          var text = Array(actionArgs.repeat + 1).join(text);\n
         }\n
         var linewise = register.linewise;\n
+        var blockwise = register.blockwise;\n
         if (linewise) {\n
-          if (actionArgs.after) {\n
+          if(vim.visualMode) {\n
+            text = vim.visualLine ? text.slice(0, -1) : \'\\n\' + text.slice(0, text.length - 1) + \'\\n\';\n
+          } else if (actionArgs.after) {\n
             // Move the newline at the end to the start instead, and paste just\n
             // before the newline character of the line we are on right now.\n
             text = \'\\n\' + text.slice(0, text.length - 1);\n
@@ -1973,25 +2328,97 @@
           } else {\n
             cur.ch = 0;\n
           }\n
-        } else {\n
-          cur.ch += actionArgs.after ? 1 : 0;\n
+        } else {\n
+          if (blockwise) {\n
+            text = text.split(\'\\n\');\n
+            for (var i = 0; i < text.length; i++) {\n
+              text[i] = (text[i] == \'\') ? \' \' : text[i];\n
+            }\n
+          }\n
+          cur.ch += actionArgs.after ? 1 : 0;\n
+        }\n
+        var curPosFinal;\n
+        var idx;\n
+        if (vim.visualMode) {\n
+          //  save the pasted text for reselection if the need arises\n
+          vim.lastPastedText = text;\n
+          var lastSelectionCurEnd;\n
+          var selectedArea = getSelectedAreaRange(cm, vim);\n
+          var selectionStart = selectedArea[0];\n
+          var selectionEnd = selectedArea[1];\n
+          var selectedText = cm.getSelection();\n
+          var selections = cm.listSelections();\n
+          var emptyStrings = new Array(selections.length).join(\'1\').split(\'1\');\n
+          // save the curEnd marker before it get cleared due to cm.replaceRange.\n
+          if (vim.lastSelection) {\n
+            lastSelectionCurEnd = vim.lastSelection.headMark.find();\n
+          }\n
+          // push the previously selected text to unnamed register\n
+          vimGlobalState.registerController.unnamedRegister.setText(selectedText);\n
+          if (blockwise) {\n
+            // first delete the selected text\n
+            cm.replaceSelections(emptyStrings);\n
+            // Set new selections as per the block length of the yanked text\n
+            selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch);\n
+            cm.setCursor(selectionStart);\n
+            selectBlock(cm, selectionEnd);\n
+            cm.replaceSelections(text);\n
+            curPosFinal = selectionStart;\n
+          } else if (vim.visualBlock) {\n
+            cm.replaceSelections(emptyStrings);\n
+            cm.setCursor(selectionStart);\n
+            cm.replaceRange(text, selectionStart, selectionStart);\n
+            curPosFinal = selectionStart;\n
+          } else {\n
+            cm.replaceRange(text, selectionStart, selectionEnd);\n
+            curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1);\n
+          }\n
+          // restore the the curEnd marker\n
+          if(lastSelectionCurEnd) {\n
+            vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd);\n
+          }\n
+          if (linewise) {\n
+            curPosFinal.ch=0;\n
+          }\n
+        } else {\n
+          if (blockwise) {\n
+            cm.setCursor(cur);\n
+            for (var i = 0; i < text.length; i++) {\n
+              var line = cur.line+i;\n
+              if (line > cm.lastLine()) {\n
+                cm.replaceRange(\'\\n\',  Pos(line, 0));\n
+              }\n
+              var lastCh = lineLength(cm, line);\n
+              if (lastCh < cur.ch) {\n
+                extendLineToColumn(cm, line, cur.ch);\n
+              }\n
+            }\n
+            cm.setCursor(cur);\n
+            selectBlock(cm, Pos(cur.line + text.length-1, cur.ch));\n
+            cm.replaceSelections(text);\n
+            curPosFinal = cur;\n
+          } else {\n
+            cm.replaceRange(text, cur);\n
+            // Now fine tune the cursor to where we want it.\n
+            if (linewise && actionArgs.after) {\n
+              curPosFinal = Pos(\n
+              cur.line + 1,\n
+              findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)));\n
+            } else if (linewise && !actionArgs.after) {\n
+              curPosFinal = Pos(\n
+                cur.line,\n
+                findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)));\n
+            } else if (!linewise && actionArgs.after) {\n
+              idx = cm.indexFromPos(cur);\n
+              curPosFinal = cm.posFromIndex(idx + text.length - 1);\n
+            } else {\n
+              idx = cm.indexFromPos(cur);\n
+              curPosFinal = cm.posFromIndex(idx + text.length);\n
+            }\n
+          }\n
         }\n
-        cm.replaceRange(text, cur);\n
-        // Now fine tune the cursor to where we want it.\n
-        var curPosFinal;\n
-        var idx;\n
-        if (linewise && actionArgs.after) {\n
-          curPosFinal = { line: cur.line + 1,\n
-              ch: findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1)) };\n
-        } else if (linewise && !actionArgs.after) {\n
-          curPosFinal = { line: cur.line,\n
-              ch: findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line)) };\n
-        } else if (!linewise && actionArgs.after) {\n
-          idx = cm.indexFromPos(cur);\n
-          curPosFinal = cm.posFromIndex(idx + text.length - 1);\n
-        } else {\n
-          idx = cm.indexFromPos(cur);\n
-          curPosFinal = cm.posFromIndex(idx + text.length);\n
+        if (vim.visualMode) {\n
+          exitVisualMode(cm);\n
         }\n
         cm.setCursor(curPosFinal);\n
       },\n
@@ -2016,33 +2443,41 @@
         var curStart = cm.getCursor();\n
         var replaceTo;\n
         var curEnd;\n
-        if(vim.visualMode){\n
-          curStart=cm.getCursor(\'start\');\n
-          curEnd=cm.getCursor(\'end\');\n
-          // workaround to catch the character under the cursor\n
-          //  existing workaround doesn\'t cover actions\n
-          curEnd=cm.clipPos({line: curEnd.line, ch: curEnd.ch+1});\n
-        }else{\n
+        var selections = cm.listSelections();\n
+        if (vim.visualMode) {\n
+          curStart = cm.getCursor(\'start\');\n
+          curEnd = cm.getCursor(\'end\');\n
+        } else {\n
           var line = cm.getLine(curStart.line);\n
           replaceTo = curStart.ch + actionArgs.repeat;\n
           if (replaceTo > line.length) {\n
             replaceTo=line.length;\n
           }\n
-          curEnd = { line: curStart.line, ch: replaceTo };\n
+          curEnd = Pos(curStart.line, replaceTo);\n
         }\n
-        if(replaceWith==\'\\n\'){\n
-          if(!vim.visualMode) cm.replaceRange(\'\', curStart, curEnd);\n
+        if (replaceWith==\'\\n\') {\n
+          if (!vim.visualMode) cm.replaceRange(\'\', curStart, curEnd);\n
           // special case, where vim help says to replace by just one line-break\n
           (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm);\n
-        }else {\n
-          var replaceWithStr=cm.getRange(curStart, curEnd);\n
+        } else {\n
+          var replaceWithStr = cm.getRange(curStart, curEnd);\n
           //replace all characters in range by selected, but keep linebreaks\n
-          replaceWithStr=replaceWithStr.replace(/[^\\n]/g,replaceWith);\n
-          cm.replaceRange(replaceWithStr, curStart, curEnd);\n
-          if(vim.visualMode){\n
+          replaceWithStr = replaceWithStr.replace(/[^\\n]/g, replaceWith);\n
+          if (vim.visualBlock) {\n
+            // Tabs are split in visua block before replacing\n
+            var spaces = new Array(cm.getOption("tabSize")+1).join(\' \');\n
+            replaceWithStr = cm.getSelection();\n
+            replaceWithStr = replaceWithStr.replace(/\\t/g, spaces).replace(/[^\\n]/g, replaceWith).split(\'\\n\');\n
+            cm.replaceSelections(replaceWithStr);\n
+          } else {\n
+            cm.replaceRange(replaceWithStr, curStart, curEnd);\n
+          }\n
+          if (vim.visualMode) {\n
+            curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ?\n
+                         selections[0].anchor : selections[0].head;\n
             cm.setCursor(curStart);\n
             exitVisualMode(cm);\n
-          }else{\n
+          } else {\n
             cm.setCursor(offsetCursor(curEnd, 0, -1));\n
           }\n
         }\n
@@ -2060,20 +2495,20 @@
           token = match[0];\n
           start = match.index;\n
           end = start + token.length;\n
-          if(cur.ch < end)break;\n
+          if (cur.ch < end)break;\n
         }\n
-        if(!actionArgs.backtrack && (end <= cur.ch))return;\n
+        if (!actionArgs.backtrack && (end <= cur.ch))return;\n
         if (token) {\n
           var increment = actionArgs.increase ? 1 : -1;\n
           var number = parseInt(token) + (increment * actionArgs.repeat);\n
-          var from = {ch:start, line:cur.line};\n
-          var to = {ch:end, line:cur.line};\n
+          var from = Pos(cur.line, start);\n
+          var to = Pos(cur.line, end);\n
           numberStr = number.toString();\n
           cm.replaceRange(numberStr, from, to);\n
         } else {\n
           return;\n
         }\n
-        cm.setCursor({line: cur.line, ch: start + numberStr.length - 1});\n
+        cm.setCursor(Pos(cur.line, start + numberStr.length - 1));\n
       },\n
       repeatLastEdit: function(cm, actionArgs, vim) {\n
         var lastEditInputState = vim.lastEditInputState;\n
@@ -2085,7 +2520,8 @@
           repeat = vim.lastEditInputState.repeatOverride || repeat;\n
         }\n
         repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */);\n
-      }\n
+      },\n
+      exitInsertMode: exitInsertMode\n
     };\n
 \n
     /*\n
@@ -2101,7 +2537,7 @@
       var maxCh = lineLength(cm, line) - 1;\n
       maxCh = (includeLineBreak) ? maxCh + 1 : maxCh;\n
       var ch = Math.min(Math.max(0, cur.ch), maxCh);\n
-      return { line: line, ch: ch };\n
+      return Pos(line, ch);\n
     }\n
     function copyArgs(args) {\n
       var ret = {};\n
@@ -2113,16 +2549,66 @@
       return ret;\n
     }\n
     function offsetCursor(cur, offsetLine, offsetCh) {\n
-      return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };\n
+      if (typeof offsetLine === \'object\') {\n
+        offsetCh = offsetLine.ch;\n
+        offsetLine = offsetLine.line;\n
+      }\n
+      return Pos(cur.line + offsetLine, cur.ch + offsetCh);\n
     }\n
-    function matchKeysPartial(pressed, mapped) {\n
-      for (var i = 0; i < pressed.length; i++) {\n
-        // \'character\' means any character. For mark, register commads, etc.\n
-        if (pressed[i] != mapped[i] && mapped[i] != \'character\') {\n
-          return false;\n
+    function getOffset(anchor, head) {\n
+      return {\n
+        line: head.line - anchor.line,\n
+        ch: head.line - anchor.line\n
+      };\n
+    }\n
+    function commandMatches(keys, keyMap, context, inputState) {\n
+      // Partial matches are not applied. They inform the key handler\n
+      // that the current key sequence is a subsequence of a valid key\n
+      // sequence, so that the key buffer is not cleared.\n
+      var match, partial = [], full = [];\n
+      for (var i = 0; i < keyMap.length; i++) {\n
+        var command = keyMap[i];\n
+        if (context == \'insert\' && command.context != \'insert\' ||\n
+            command.context && command.context != context ||\n
+            inputState.operator && command.type == \'action\' ||\n
+            !(match = commandMatch(keys, command.keys))) { continue; }\n
+        if (match == \'partial\') { partial.push(command); }\n
+        if (match == \'full\') { full.push(command); }\n
+      }\n
+      return {\n
+        partial: partial.length && partial,\n
+        full: full.length && full\n
+      };\n
+    }\n
+    function commandMatch(pressed, mapped) {\n
+      if (mapped.slice(-11) == \'<character>\') {\n
+        // Last character matches anything.\n
+        var prefixLen = mapped.length - 11;\n
+        var pressedPrefix = pressed.slice(0, prefixLen);\n
+        var mappedPrefix = mapped.slice(0, prefixLen);\n
+        return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? \'full\' :\n
+               mappedPrefix.indexOf(pressedPrefix) == 0 ? \'partial\' : false;\n
+      } else {\n
+        return pressed == mapped ? \'full\' :\n
+               mapped.indexOf(pressed) == 0 ? \'partial\' : false;\n
+      }\n
+    }\n
+    function lastChar(keys) {\n
+      var match = /^.*(<[\\w\\-]+>)$/.exec(keys);\n
+      var selectedCharacter = match ? match[1] : keys.slice(-1);\n
+      if (selectedCharacter.length > 1){\n
+        switch(selectedCharacter){\n
+          case \'<CR>\':\n
+            selectedCharacter=\'\\n\';\n
+            break;\n
+          case \'<Space>\':\n
+            selectedCharacter=\' \';\n
+            break;\n
+          default:\n
+            break;\n
         }\n
       }\n
-      return true;\n
+      return selectedCharacter;\n
     }\n
     function repeatFn(cm, fn, repeat) {\n
       return function() {\n
@@ -2132,7 +2618,7 @@
       };\n
     }\n
     function copyCursor(cur) {\n
-      return { line: cur.line, ch: cur.ch };\n
+      return Pos(cur.line, cur.ch);\n
     }\n
     function cursorEqual(cur1, cur2) {\n
       return cur1.ch == cur2.ch && cur1.line == cur2.line;\n
@@ -2146,7 +2632,19 @@
       }\n
       return false;\n
     }\n
-    function cusrorIsBetween(cur1, cur2, cur3) {\n
+    function cursorMin(cur1, cur2) {\n
+      if (arguments.length > 2) {\n
+        cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1));\n
+      }\n
+      return cursorIsBefore(cur1, cur2) ? cur1 : cur2;\n
+    }\n
+    function cursorMax(cur1, cur2) {\n
+      if (arguments.length > 2) {\n
+        cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1));\n
+      }\n
+      return cursorIsBefore(cur1, cur2) ? cur2 : cur1;\n
+    }\n
+    function cursorIsBetween(cur1, cur2, cur3) {\n
       // returns true if cur2 is between cur1 and cur3.\n
       var cur1before2 = cursorIsBefore(cur1, cur2);\n
       var cur2before3 = cursorIsBefore(cur2, cur3);\n
@@ -2167,21 +2665,254 @@
     function escapeRegex(s) {\n
       return s.replace(/([.?*+$\\[\\]\\/\\\\(){}|\\-])/g, \'\\\\$1\');\n
     }\n
+    function extendLineToColumn(cm, lineNum, column) {\n
+      var endCh = lineLength(cm, lineNum);\n
+      var spaces = new Array(column-endCh+1).join(\' \');\n
+      cm.setCursor(Pos(lineNum, endCh));\n
+      cm.replaceRange(spaces, cm.getCursor());\n
+    }\n
+    // This functions selects a rectangular block\n
+    // of text with selectionEnd as any of its corner\n
+    // Height of block:\n
+    // Difference in selectionEnd.line and first/last selection.line\n
+    // Width of the block:\n
+    // Distance between selectionEnd.ch and any(first considered here) selection.ch\n
+    function selectBlock(cm, selectionEnd) {\n
+      var selections = [], ranges = cm.listSelections();\n
+      var head = copyCursor(cm.clipPos(selectionEnd));\n
+      var isClipped = !cursorEqual(selectionEnd, head);\n
+      var curHead = cm.getCursor(\'head\');\n
+      var primIndex = getIndex(ranges, curHead);\n
+      var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor);\n
+      var max = ranges.length - 1;\n
+      var index = max - primIndex > primIndex ? max : 0;\n
+      var base = ranges[index].anchor;\n
+\n
+      var firstLine = Math.min(base.line, head.line);\n
+      var lastLine = Math.max(base.line, head.line);\n
+      var baseCh = base.ch, headCh = head.ch;\n
+\n
+      var dir = ranges[index].head.ch - baseCh;\n
+      var newDir = headCh - baseCh;\n
+      if (dir > 0 && newDir <= 0) {\n
+        baseCh++;\n
+        if (!isClipped) { headCh--; }\n
+      } else if (dir < 0 && newDir >= 0) {\n
+        baseCh--;\n
+        if (!wasClipped) { headCh++; }\n
+      } else if (dir < 0 && newDir == -1) {\n
+        baseCh--;\n
+        headCh++;\n
+      }\n
+      for (var line = firstLine; line <= lastLine; line++) {\n
+        var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)};\n
+        selections.push(range);\n
+      }\n
+      primIndex = head.line == lastLine ? selections.length - 1 : 0;\n
+      cm.setSelections(selections);\n
+      selectionEnd.ch = headCh;\n
+      base.ch = baseCh;\n
+      return base;\n
+    }\n
+    function selectForInsert(cm, head, height) {\n
+      var sel = [];\n
+      for (var i = 0; i < height; i++) {\n
+        var lineHead = offsetCursor(head, i, 0);\n
+        sel.push({anchor: lineHead, head: lineHead});\n
+      }\n
+      cm.setSelections(sel, 0);\n
+    }\n
+    // getIndex returns the index of the cursor in the selections.\n
+    function getIndex(ranges, cursor, end) {\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var atAnchor = end != \'head\' && cursorEqual(ranges[i].anchor, cursor);\n
+        var atHead = end != \'anchor\' && cursorEqual(ranges[i].head, cursor);\n
+        if (atAnchor || atHead) {\n
+          return i;\n
+        }\n
+      }\n
+      return -1;\n
+    }\n
+    function getSelectedAreaRange(cm, vim) {\n
+      var lastSelection = vim.lastSelection;\n
+      var getCurrentSelectedAreaRange = function() {\n
+        var selections = cm.listSelections();\n
+        var start =  selections[0];\n
+        var end = selections[selections.length-1];\n
+        var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head;\n
+        var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor;\n
+        return [selectionStart, selectionEnd];\n
+      };\n
+      var getLastSelectedAreaRange = function() {\n
+        var selectionStart = cm.getCursor();\n
+        var selectionEnd = cm.getCursor();\n
+        var block = lastSelection.visualBlock;\n
+        if (block) {\n
+          var width = block.width;\n
+          var height = block.height;\n
+          selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width);\n
+          var selections = [];\n
+          // selectBlock creates a \'proper\' rectangular block.\n
+          // We do not want that in all cases, so we manually set selections.\n
+          for (var i = selectionStart.line; i < selectionEnd.line; i++) {\n
+            var anchor = Pos(i, selectionStart.ch);\n
+            var head = Pos(i, selectionEnd.ch);\n
+            var range = {anchor: anchor, head: head};\n
+            selections.push(range);\n
+          }\n
+          cm.setSelections(selections);\n
+        } else {\n
+          var start = lastSelection.anchorMark.find();\n
+          var end = lastSelection.headMark.find();\n
+          var line = end.line - start.line;\n
+          var ch = end.ch - start.ch;\n
+          selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch};\n
+          if (lastSelection.visualLine) {\n
+            selectionStart = Pos(selectionStart.line, 0);\n
+            selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line));\n
+          }\n
+          cm.setSelection(selectionStart, selectionEnd);\n
+        }\n
+        return [selectionStart, selectionEnd];\n
+      };\n
+      if (!vim.visualMode) {\n
+      // In case of replaying the action.\n
+        return getLastSelectedAreaRange();\n
+      } else {\n
+        return getCurrentSelectedAreaRange();\n
+      }\n
+    }\n
+    // Updates the previous selection with the current selection\'s values. This\n
+    // should only be called in visual mode.\n
+    function updateLastSelection(cm, vim) {\n
+      var anchor = vim.sel.anchor;\n
+      var head = vim.sel.head;\n
+      // To accommodate the effect of lastPastedText in the last selection\n
+      if (vim.lastPastedText) {\n
+        head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length);\n
+        vim.lastPastedText = null;\n
+      }\n
+      vim.lastSelection = {\'anchorMark\': cm.setBookmark(anchor),\n
+                           \'headMark\': cm.setBookmark(head),\n
+                           \'anchor\': copyCursor(anchor),\n
+                           \'head\': copyCursor(head),\n
+                           \'visualMode\': vim.visualMode,\n
+                           \'visualLine\': vim.visualLine,\n
+                           \'visualBlock\': vim.visualBlock};\n
+    }\n
+    function expandSelection(cm, start, end) {\n
+      var sel = cm.state.vim.sel;\n
+      var head = sel.head;\n
+      var anchor = sel.anchor;\n
+      var tmp;\n
+      if (cursorIsBefore(end, start)) {\n
+        tmp = end;\n
+        end = start;\n
+        start = tmp;\n
+      }\n
+      if (cursorIsBefore(head, anchor)) {\n
+        head = cursorMin(start, head);\n
+        anchor = cursorMax(anchor, end);\n
+      } else {\n
+        anchor = cursorMin(start, anchor);\n
+        head = cursorMax(head, end);\n
+        head = offsetCursor(head, 0, -1);\n
+        if (head.ch == -1 && head.line != cm.firstLine()) {\n
+          head = Pos(head.line - 1, lineLength(cm, head.line - 1));\n
+        }\n
+      }\n
+      return [anchor, head];\n
+    }\n
+    /**\n
+     * Updates the CodeMirror selection to match the provided vim selection.\n
+     * If no arguments are given, it uses the current vim selection state.\n
+     */\n
+    function updateCmSelection(cm, sel, mode) {\n
+      var vim = cm.state.vim;\n
+      sel = sel || vim.sel;\n
+      var mode = mode ||\n
+        vim.visualLine ? \'line\' : vim.visualBlock ? \'block\' : \'char\';\n
+      var cmSel = makeCmSelection(cm, sel, mode);\n
+      cm.setSelections(cmSel.ranges, cmSel.primary);\n
+      updateFakeCursor(cm);\n
+    }\n
+    function makeCmSelection(cm, sel, mode, exclusive) {\n
+      var head = copyCursor(sel.head);\n
+      var anchor = copyCursor(sel.anchor);\n
+      if (mode == \'char\') {\n
+        var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;\n
+        var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0;\n
+        head = offsetCursor(sel.head, 0, headOffset);\n
+        anchor = offsetCursor(sel.anchor, 0, anchorOffset);\n
+        return {\n
+          ranges: [{anchor: anchor, head: head}],\n
+          primary: 0\n
+        };\n
+      } else if (mode == \'line\') {\n
+        if (!cursorIsBefore(sel.head, sel.anchor)) {\n
+          anchor.ch = 0;\n
+\n
+          var lastLine = cm.lastLine();\n
+          if (head.line > lastLine) {\n
+            head.line = lastLine;\n
+          }\n
+          head.ch = lineLength(cm, head.line);\n
+        } else {\n
+          head.ch = 0;\n
+          anchor.ch = lineLength(cm, anchor.line);\n
+        }\n
+        return {\n
+          ranges: [{anchor: anchor, head: head}],\n
+          primary: 0\n
+        };\n
+      } else if (mode == \'block\') {\n
+        var top = Math.min(anchor.line, head.line),\n
+            left = Math.min(anchor.ch, head.ch),\n
+            bottom = Math.max(anchor.line, head.line),\n
+            right = Math.max(anchor.ch, head.ch) + 1;\n
+        var height = bottom - top + 1;\n
+        var primary = head.line == top ? 0 : height - 1;\n
+        var ranges = [];\n
+        for (var i = 0; i < height; i++) {\n
+          ranges.push({\n
+            anchor: Pos(top + i, left),\n
+            head: Pos(top + i, right)\n
+          });\n
+        }\n
+        return {\n
+          ranges: ranges,\n
+          primary: primary\n
+        };\n
+      }\n
+    }\n
+    function getHead(cm) {\n
+      var cur = cm.getCursor(\'head\');\n
+      if (cm.getSelection().length == 1) {\n
+        // Small corner case when only 1 character is selected. The "real"\n
+        // head is the left of head and anchor.\n
+        cur = cursorMin(cur, cm.getCursor(\'anchor\'));\n
+      }\n
+      return cur;\n
+    }\n
 \n
-    function exitVisualMode(cm) {\n
-      cm.off(\'mousedown\', exitVisualMode);\n
+    /**\n
+     * If moveHead is set to false, the CodeMirror selection will not be\n
+     * touched. The caller assumes the responsibility of putting the cursor\n
+    * in the right place.\n
+     */\n
+    function exitVisualMode(cm, moveHead) {\n
       var vim = cm.state.vim;\n
+      if (moveHead !== false) {\n
+        cm.setCursor(clipCursorToContent(cm, vim.sel.head));\n
+      }\n
+      updateLastSelection(cm, vim);\n
       vim.visualMode = false;\n
       vim.visualLine = false;\n
-      var selectionStart = cm.getCursor(\'anchor\');\n
-      var selectionEnd = cm.getCursor(\'head\');\n
-      if (!cursorEqual(selectionStart, selectionEnd)) {\n
-        // Clear the selection and set the cursor only if the selection has not\n
-        // already been cleared. Otherwise we risk moving the cursor somewhere\n
-        // it\'s not supposed to be.\n
-        cm.setCursor(clipCursorToContent(cm, selectionEnd));\n
-      }\n
+      vim.visualBlock = false;\n
       CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});\n
+      if (vim.fakeCursor) {\n
+        vim.fakeCursor.clear();\n
+      }\n
     }\n
 \n
     // Remove any trailing newlines from the selection. For\n
@@ -2232,7 +2963,7 @@
     }\n
 \n
     function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) {\n
-      var cur = cm.getCursor();\n
+      var cur = getHead(cm);\n
       var line = cm.getLine(cur.line);\n
       var idx = cur.ch;\n
 \n
@@ -2289,12 +3020,12 @@
         }\n
       }\n
 \n
-      return { start: { line: cur.line, ch: wordStart },\n
-        end: { line: cur.line, ch: wordEnd }};\n
+      return { start: Pos(cur.line, wordStart),\n
+               end: Pos(cur.line, wordEnd) };\n
     }\n
 \n
     function recordJumpPosition(cm, oldCur, newCur) {\n
-      if(!cursorEqual(oldCur, newCur)) {\n
+      if (!cursorEqual(oldCur, newCur)) {\n
         vimGlobalState.jumpList.add(cm, oldCur, newCur);\n
       }\n
     }\n
@@ -2317,7 +3048,7 @@
         isComplete: function(state) {\n
           if (state.nextCh === state.symb) {\n
             state.depth++;\n
-            if(state.depth >= 1)return true;\n
+            if (state.depth >= 1)return true;\n
           } else if (state.nextCh === state.reverseSymb) {\n
             state.depth--;\n
           }\n
@@ -2349,7 +3080,7 @@
           state.reverseSymb = state.symb === \'{\' ? \'}\' : \'{\';\n
         },\n
         isComplete: function(state) {\n
-          if(state.nextCh === state.symb)return true;\n
+          if (state.nextCh === state.symb)return true;\n
           return false;\n
         }\n
       },\n
@@ -2371,14 +3102,14 @@
               }\n
               state.depth--;\n
             }\n
-            if(token === \'else\' && state.depth === 0)return true;\n
+            if (token === \'else\' && state.depth === 0)return true;\n
           }\n
           return false;\n
         }\n
       }\n
     };\n
     function findSymbol(cm, repeat, forward, symb) {\n
-      var cur = cm.getCursor();\n
+      var cur = copyCursor(cm.getCursor());\n
       var increment = forward ? 1 : -1;\n
       var endLine = forward ? cm.lineCount() : -1;\n
       var curCh = cur.ch;\n
@@ -2396,10 +3127,10 @@
         curMoveThrough: false\n
       };\n
       var mode = symbolToMode[symb];\n
-      if(!mode)return cur;\n
+      if (!mode)return cur;\n
       var init = findSymbolModes[mode].init;\n
       var isComplete = findSymbolModes[mode].isComplete;\n
-      if(init)init(state);\n
+      if (init) { init(state); }\n
       while (line !== endLine && repeat) {\n
         state.index += increment;\n
         state.nextCh = state.lineText.charAt(state.index);\n
@@ -2421,7 +3152,7 @@
         }\n
       }\n
       if (state.nextCh || state.curMoveThrough) {\n
-        return { line: line, ch: state.index };\n
+        return Pos(line, state.index);\n
       }\n
       return cur;\n
     }\n
@@ -2507,6 +3238,7 @@
 \n
     /**\n
      * @param {CodeMirror} cm CodeMirror object.\n
+     * @param {Pos} cur The position to start from.\n
      * @param {int} repeat Number of words to move past.\n
      * @param {boolean} forward True to search forward. False to search\n
      *     backward.\n
@@ -2516,8 +3248,7 @@
      *     False if only alphabet characters count as part of the word.\n
      * @return {Cursor} The position the cursor should move to.\n
      */\n
-    function moveToWord(cm, repeat, forward, wordEnd, bigWord) {\n
-      var cur = cm.getCursor();\n
+    function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) {\n
       var curStart = copyCursor(cur);\n
       var words = [];\n
       if (forward && !wordEnd || !forward && wordEnd) {\n
@@ -2535,7 +3266,7 @@
           break;\n
         }\n
         words.push(word);\n
-        cur = {line: word.line, ch: forward ? (word.to - 1) : word.from};\n
+        cur = Pos(word.line, forward ? (word.to - 1) : word.from);\n
       }\n
       var shortCircuit = words.length != repeat;\n
       var firstWord = words[0];\n
@@ -2546,19 +3277,19 @@
           // We did not start in the middle of a word. Discard the extra word at the end.\n
           lastWord = words.pop();\n
         }\n
-        return {line: lastWord.line, ch: lastWord.from};\n
+        return Pos(lastWord.line, lastWord.from);\n
       } else if (forward && wordEnd) {\n
-        return {line: lastWord.line, ch: lastWord.to - 1};\n
+        return Pos(lastWord.line, lastWord.to - 1);\n
       } else if (!forward && wordEnd) {\n
         // ge\n
         if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) {\n
           // We did not start in the middle of a word. Discard the extra word at the end.\n
           lastWord = words.pop();\n
         }\n
-        return {line: lastWord.line, ch: lastWord.to};\n
+        return Pos(lastWord.line, lastWord.to);\n
       } else {\n
         // b\n
-        return {line: lastWord.line, ch: lastWord.from};\n
+        return Pos(lastWord.line, lastWord.from);\n
       }\n
     }\n
 \n
@@ -2574,14 +3305,14 @@
         }\n
         start = idx;\n
       }\n
-      return { line: cm.getCursor().line, ch: idx };\n
+      return Pos(cm.getCursor().line, idx);\n
     }\n
 \n
     function moveToColumn(cm, repeat) {\n
       // repeat is always >= 1, so repeat - 1 always corresponds\n
       // to the column we want to go to.\n
       var line = cm.getCursor().line;\n
-      return clipCursorToContent(cm, { line: line, ch: repeat - 1 });\n
+      return clipCursorToContent(cm, Pos(line, repeat - 1));\n
     }\n
 \n
     function updateMark(cm, vim, markName, pos) {\n
@@ -2615,83 +3346,90 @@
       return idx;\n
     }\n
 \n
-    function getContextLevel(ctx) {\n
-      return (ctx === \'string\' || ctx === \'comment\') ? 1 : 0;\n
-    }\n
+    function findParagraph(cm, head, repeat, dir, inclusive) {\n
+      var line = head.line;\n
+      var min = cm.firstLine();\n
+      var max = cm.lastLine();\n
+      var start, end, i = line;\n
+      function isEmpty(i) { return !cm.getLine(i); }\n
+      function isBoundary(i, dir, any) {\n
+        if (any) { return isEmpty(i) != isEmpty(i + dir); }\n
+        return !isEmpty(i) && isEmpty(i + dir);\n
+      }\n
+      if (dir) {\n
+        while (min <= i && i <= max && repeat > 0) {\n
+          if (isBoundary(i, dir)) { repeat--; }\n
+          i += dir;\n
+        }\n
+        return new Pos(i, 0);\n
+      }\n
 \n
-    function findMatchedSymbol(cm, cur, symb) {\n
-      var line = cur.line;\n
-      var ch = cur.ch;\n
-      symb = symb ? symb : cm.getLine(line).charAt(ch);\n
-\n
-      var symbContext = cm.getTokenAt({line:line, ch:ch+1}).type;\n
-      var symbCtxLevel = getContextLevel(symbContext);\n
-\n
-      var reverseSymb = ({\n
-        \'(\': \')\', \')\': \'(\',\n
-        \'[\': \']\', \']\': \'[\',\n
-        \'{\': \'}\', \'}\': \'{\'})[symb];\n
-\n
-      // Couldn\'t find a matching symbol, abort\n
-      if (!reverseSymb) {\n
-        return cur;\n
-      }\n
-\n
-      // set our increment to move forward (+1) or backwards (-1)\n
-      // depending on which bracket we\'re matching\n
-      var increment = ({\'(\': 1, \'{\': 1, \'[\': 1})[symb] || -1;\n
-      var endLine = increment === 1 ? cm.lineCount() : -1;\n
-      var depth = 1, nextCh = symb, index = ch, lineText = cm.getLine(line);\n
-      // Simple search for closing paren--just count openings and closings till\n
-      // we find our match\n
-      // TODO: use info from CodeMirror to ignore closing brackets in comments\n
-      // and quotes, etc.\n
-      while (line !== endLine && depth > 0) {\n
-        index += increment;\n
-        nextCh = lineText.charAt(index);\n
-        if (!nextCh) {\n
-          line += increment;\n
-          lineText = cm.getLine(line) || \'\';\n
-          if (increment > 0) {\n
-            index = 0;\n
-          } else {\n
-            var lineLen = lineText.length;\n
-            index = (lineLen > 0) ? (lineLen-1) : 0;\n
+      var vim = cm.state.vim;\n
+      if (vim.visualLine && isBoundary(line, 1, true)) {\n
+        var anchor = vim.sel.anchor;\n
+        if (isBoundary(anchor.line, -1, true)) {\n
+          if (!inclusive || anchor.line != line) {\n
+            line += 1;\n
           }\n
-          nextCh = lineText.charAt(index);\n
         }\n
-        var revSymbContext = cm.getTokenAt({line:line, ch:index+1}).type;\n
-        var revSymbCtxLevel = getContextLevel(revSymbContext);\n
-        if (symbCtxLevel >= revSymbCtxLevel) {\n
-          if (nextCh === symb) {\n
-            depth++;\n
-          } else if (nextCh === reverseSymb) {\n
-            depth--;\n
+      }\n
+      var startState = isEmpty(line);\n
+      for (i = line; i <= max && repeat; i++) {\n
+        if (isBoundary(i, 1, true)) {\n
+          if (!inclusive || isEmpty(i) != startState) {\n
+            repeat--;\n
           }\n
         }\n
       }\n
-\n
-      if (nextCh) {\n
-        return { line: line, ch: index };\n
+      end = new Pos(i, 0);\n
+      // select boundary before paragraph for the last one\n
+      if (i > max && !startState) { startState = true; }\n
+      else { inclusive = false; }\n
+      for (i = line; i > min; i--) {\n
+        if (!inclusive || isEmpty(i) == startState || i == line) {\n
+          if (isBoundary(i, -1, true)) { break; }\n
+        }\n
       }\n
-      return cur;\n
+      start = new Pos(i, 0);\n
+      return { start: start, end: end };\n
     }\n
 \n
     // TODO: perhaps this finagling of start and end positions belonds\n
     // in codmirror/replaceRange?\n
-    function selectCompanionObject(cm, revSymb, inclusive) {\n
-      var cur = cm.getCursor();\n
-      var end = findMatchedSymbol(cm, cur, revSymb);\n
-      var start = findMatchedSymbol(cm, end);\n
+    function selectCompanionObject(cm, head, symb, inclusive) {\n
+      var cur = head, start, end;\n
 \n
-      if((start.line == end.line && start.ch > end.ch)\n
+      var bracketRegexp = ({\n
+        \'(\': /[()]/, \')\': /[()]/,\n
+        \'[\': /[[\\]]/, \']\': /[[\\]]/,\n
+        \'{\': /[{}]/, \'}\': /[{}]/})[symb];\n
+      var openSym = ({\n
+        \'(\': \'(\', \')\': \'(\',\n
+        \'[\': \'[\', \']\': \'[\',\n
+        \'{\': \'{\', \'}\': \'{\'})[symb];\n
+      var curChar = cm.getLine(cur.line).charAt(cur.ch);\n
+      // Due to the behavior of scanForBracket, we need to add an offset if the\n
+      // cursor is on a matching open bracket.\n
+      var offset = curChar === openSym ? 1 : 0;\n
+\n
+      start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {\'bracketRegex\': bracketRegexp});\n
+      end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {\'bracketRegex\': bracketRegexp});\n
+\n
+      if (!start || !end) {\n
+        return { start: cur, end: cur };\n
+      }\n
+\n
+      start = start.pos;\n
+      end = end.pos;\n
+\n
+      if ((start.line == end.line && start.ch > end.ch)\n
           || (start.line > end.line)) {\n
         var tmp = start;\n
         start = end;\n
         end = tmp;\n
       }\n
 \n
-      if(inclusive) {\n
+      if (inclusive) {\n
         end.ch += 1;\n
       } else {\n
         start.ch += 1;\n
@@ -2703,8 +3441,8 @@
     // Takes in a symbol and a cursor and tries to simulate text objects that\n
     // have identical opening and closing symbols\n
     // TODO support across multiple lines\n
-    function findBeginningAndEnd(cm, symb, inclusive) {\n
-      var cur = cm.getCursor();\n
+    function findBeginningAndEnd(cm, head, symb, inclusive) {\n
+      var cur = copyCursor(head);\n
       var line = cm.getLine(cur.line);\n
       var chars = line.split(\'\');\n
       var start, end, i, len;\n
@@ -2756,12 +3494,13 @@
       }\n
 \n
       return {\n
-        start: { line: cur.line, ch: start },\n
-        end: { line: cur.line, ch: end }\n
+        start: Pos(cur.line, start),\n
+        end: Pos(cur.line, end)\n
       };\n
     }\n
 \n
     // Search functions\n
+    defineOption(\'pcre\', true, \'boolean\');\n
     function SearchState() {}\n
     SearchState.prototype = {\n
       getQuery: function() {\n
@@ -2796,6 +3535,18 @@
         onClose(prompt(shortText, \'\'));\n
       }\n
     }\n
+    function splitBySlash(argString) {\n
+      var slashes = findUnescapedSlashes(argString) || [];\n
+      if (!slashes.length) return [];\n
+      var tokens = [];\n
+      // in case of strings like foo/bar\n
+      if (slashes[0] !== 0) return;\n
+      for (var i = 0; i < slashes.length; i++) {\n
+        if (typeof slashes[i] == \'number\')\n
+          tokens.push(argString.substring(slashes[i] + 1, slashes[i+1]));\n
+      }\n
+      return tokens;\n
+    }\n
 \n
     function findUnescapedSlashes(str) {\n
       var escapeNextChar = false;\n
@@ -2811,17 +3562,17 @@
     }\n
 \n
     // Translates a search string from ex (vim) syntax into javascript form.\n
-    function fixRegex(str) {\n
+    function translateRegex(str) {\n
       // When these match, add a \'\\\' if unescaped or remove one if escaped.\n
-      var specials = [\'|\', \'(\', \')\', \'{\'];\n
+      var specials = \'|(){\';\n
       // Remove, but never add, a \'\\\' for these.\n
-      var unescape = [\'}\'];\n
+      var unescape = \'}\';\n
       var escapeNextChar = false;\n
       var out = [];\n
       for (var i = -1; i < str.length; i++) {\n
         var c = str.charAt(i) || \'\';\n
         var n = str.charAt(i+1) || \'\';\n
-        var specialComesNext = (specials.indexOf(n) != -1);\n
+        var specialComesNext = (n && specials.indexOf(n) != -1);\n
         if (escapeNextChar) {\n
           if (c !== \'\\\\\' || !specialComesNext) {\n
             out.push(c);\n
@@ -2831,7 +3582,7 @@
           if (c === \'\\\\\') {\n
             escapeNextChar = true;\n
             // Treat the unescape list as special for removing, but not adding \'\\\'.\n
-            if (unescape.indexOf(n) != -1) {\n
+            if (n && unescape.indexOf(n) != -1) {\n
               specialComesNext = true;\n
             }\n
             // Not passing this test means removing a \'\\\'.\n
@@ -2850,15 +3601,17 @@
     }\n
 \n
     // Translates the replace part of a search and replace from ex (vim) syntax into\n
-    // javascript form.  Similar to fixRegex, but additionally fixes back references\n
+    // javascript form.  Similar to translateRegex, but additionally fixes back references\n
     // (translates \'\\[0..9]\' to \'$[0..9]\') and follows different rules for escaping \'$\'.\n
-    function fixRegexReplace(str) {\n
+    function translateRegexReplace(str) {\n
       var escapeNextChar = false;\n
       var out = [];\n
       for (var i = -1; i < str.length; i++) {\n
         var c = str.charAt(i) || \'\';\n
         var n = str.charAt(i+1) || \'\';\n
         if (escapeNextChar) {\n
+          // At any point in the loop, escapeNextChar is true if the previous\n
+          // character was a \'\\\' and was not escaped.\n
           out.push(c);\n
           escapeNextChar = false;\n
         } else {\n
@@ -2882,6 +3635,29 @@
       }\n
       return out.join(\'\');\n
     }\n
+\n
+    // Unescape \\ and / in the replace part, for PCRE mode.\n
+    function unescapeRegexReplace(str) {\n
+      var stream = new CodeMirror.StringStream(str);\n
+      var output = [];\n
+      while (!stream.eol()) {\n
+        // Search for \\.\n
+        while (stream.peek() && stream.peek() != \'\\\\\') {\n
+          output.push(stream.next());\n
+        }\n
+        if (stream.match(\'\\\\/\', true)) {\n
+          // \\/ => /\n
+          output.push(\'/\');\n
+        } else if (stream.match(\'\\\\\\\\\', true)) {\n
+          // \\\\ => \\\n
+          output.push(\'\\\\\');\n
+        } else {\n
+          // Don\'t change anything\n
+          output.push(stream.next());\n
+        }\n
+      }\n
+      return output.join(\'\');\n
+    }\n
 \n
     /**\n
      * Extract the regular expression from the query and return a Regexp object.\n
@@ -2894,6 +3670,9 @@
      *   through to the Regex object.\n
      */\n
     function parseQuery(query, ignoreCase, smartCase) {\n
+      // First update the last search register\n
+      var lastSearchRegister = vimGlobalState.registerController.getRegister(\'/\');\n
+      lastSearchRegister.setText(query);\n
       // Check if the query is already a regex.\n
       if (query instanceof RegExp) { return query; }\n
       // First try to extract regex + flags from the input. If no flags found,\n
@@ -2914,7 +3693,9 @@
       if (!regexPart) {\n
         return null;\n
       }\n
-      regexPart = fixRegex(regexPart);\n
+      if (!getOption(\'pcre\')) {\n
+        regexPart = translateRegex(regexPart);\n
+      }\n
       if (smartCase) {\n
         ignoreCase = (/^[^A-Z]*$/).test(regexPart);\n
       }\n
@@ -3039,7 +3820,7 @@
             // SearchCursor may have returned null because it hit EOF, wrap\n
             // around and try again.\n
             cursor = cm.getSearchCursor(query,\n
-                (prev) ? { line: cm.lastLine() } : {line: cm.firstLine(), ch: 0} );\n
+                (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) );\n
             if (!cursor.find(prev)) {\n
               return;\n
             }\n
@@ -3094,34 +3875,44 @@
     // shortNames must not match the prefix of the other command.\n
     var defaultExCommandMap = [\n
       { name: \'map\' },\n
+      { name: \'imap\', shortName: \'im\' },\n
       { name: \'nmap\', shortName: \'nm\' },\n
       { name: \'vmap\', shortName: \'vm\' },\n
+      { name: \'unmap\' },\n
       { name: \'write\', shortName: \'w\' },\n
       { name: \'undo\', shortName: \'u\' },\n
       { name: \'redo\', shortName: \'red\' },\n
+      { name: \'set\', shortName: \'set\' },\n
       { name: \'sort\', shortName: \'sor\' },\n
-      { name: \'substitute\', shortName: \'s\' },\n
+      { name: \'substitute\', shortName: \'s\', possiblyAsync: true },\n
       { name: \'nohlsearch\', shortName: \'noh\' },\n
-      { name: \'delmarks\', shortName: \'delm\' }\n
+      { name: \'delmarks\', shortName: \'delm\' },\n
+      { name: \'registers\', shortName: \'reg\', excludeFromCommandHistory: true },\n
+      { name: \'global\', shortName: \'g\' }\n
     ];\n
-    Vim.ExCommandDispatcher = function() {\n
+    var ExCommandDispatcher = function() {\n
       this.buildCommandMap_();\n
     };\n
-    Vim.ExCommandDispatcher.prototype = {\n
-      processCommand: function(cm, input) {\n
+    ExCommandDispatcher.prototype = {\n
+      processCommand: function(cm, input, opt_params) {\n
         var vim = cm.state.vim;\n
+        var commandHistoryRegister = vimGlobalState.registerController.getRegister(\':\');\n
+        var previousCommand = commandHistoryRegister.toString();\n
         if (vim.visualMode) {\n
           exitVisualMode(cm);\n
         }\n
         var inputStream = new CodeMirror.StringStream(input);\n
-        var params = {};\n
+        // update ": with the latest command whether valid or invalid\n
+        commandHistoryRegister.setText(input);\n
+        var params = opt_params || {};\n
         params.input = input;\n
         try {\n
           this.parseInput_(cm, inputStream, params);\n
         } catch(e) {\n
           showConfirm(cm, e);\n
-          return;\n
+          throw e;\n
         }\n
+        var command;\n
         var commandName;\n
         if (!params.commandName) {\n
           // If only a line range is defined, move to the line.\n
@@ -3129,14 +3920,17 @@
             commandName = \'move\';\n
           }\n
         } else {\n
-          var command = this.matchCommand_(params.commandName);\n
+          command = this.matchCommand_(params.commandName);\n
           if (command) {\n
             commandName = command.name;\n
+            if (command.excludeFromCommandHistory) {\n
+              commandHistoryRegister.setText(previousCommand);\n
+            }\n
             this.parseCommandArgs_(inputStream, params, command);\n
             if (command.type == \'exToKey\') {\n
               // Handle Ex to Key mapping.\n
               for (var i = 0; i < command.toKeys.length; i++) {\n
-                CodeMirror.Vim.handleKey(cm, command.toKeys[i]);\n
+                CodeMirror.Vim.handleKey(cm, command.toKeys[i], \'mapping\');\n
               }\n
               return;\n
             } else if (command.type == \'exToEx\') {\n
@@ -3152,6 +3946,12 @@
         }\n
         try {\n
           exCommands[commandName](cm, params);\n
+          // Possibly asynchronous commands (e.g. substitute, which might have a\n
+          // user confirmation), are responsible for calling the callback when\n
+          // done. All others have it taken care of for them here.\n
+          if ((!command || !command.possiblyAsync) && params.callback) {\n
+            params.callback();\n
+          }\n
         } catch(e) {\n
           showConfirm(cm, e);\n
           throw e;\n
@@ -3246,53 +4046,65 @@
             this.commandMap_[commandName] = {\n
               name: commandName,\n
               type: \'exToEx\',\n
-              toInput: rhs.substring(1)\n
+              toInput: rhs.substring(1),\n
+              user: true\n
             };\n
           } else {\n
             // Ex to key mapping\n
             this.commandMap_[commandName] = {\n
               name: commandName,\n
               type: \'exToKey\',\n
-              toKeys: parseKeyString(rhs)\n
+              toKeys: rhs,\n
+              user: true\n
             };\n
           }\n
         } else {\n
           if (rhs != \':\' && rhs.charAt(0) == \':\') {\n
             // Key to Ex mapping.\n
             var mapping = {\n
-              keys: parseKeyString(lhs),\n
+              keys: lhs,\n
               type: \'keyToEx\',\n
-              exArgs: { input: rhs.substring(1) }};\n
+              exArgs: { input: rhs.substring(1) },\n
+              user: true};\n
             if (ctx) { mapping.context = ctx; }\n
             defaultKeymap.unshift(mapping);\n
           } else {\n
             // Key to key mapping\n
             var mapping = {\n
-              keys: parseKeyString(lhs),\n
+              keys: lhs,\n
               type: \'keyToKey\',\n
-              toKeys: parseKeyString(rhs)\n
+              toKeys: rhs,\n
+              user: true\n
             };\n
             if (ctx) { mapping.context = ctx; }\n
             defaultKeymap.unshift(mapping);\n
           }\n
         }\n
+      },\n
+      unmap: function(lhs, ctx) {\n
+        if (lhs != \':\' && lhs.charAt(0) == \':\') {\n
+          // Ex to Ex or Ex to key mapping\n
+          if (ctx) { throw Error(\'Mode not supported for ex mappings\'); }\n
+          var commandName = lhs.substring(1);\n
+          if (this.commandMap_[commandName] && this.commandMap_[commandName].user) {\n
+            delete this.commandMap_[commandName];\n
+            return;\n
+          }\n
+        } else {\n
+          // Key to Ex or key to key mapping\n
+          var keys = lhs;\n
+          for (var i = 0; i < defaultKeymap.length; i++) {\n
+            if (keys == defaultKeymap[i].keys\n
+                && defaultKeymap[i].context === ctx\n
+                && defaultKeymap[i].user) {\n
+              defaultKeymap.splice(i, 1);\n
+              return;\n
+            }\n
+          }\n
+        }\n
+        throw Error(\'No such mapping.\');\n
       }\n
     };\n
-\n
-    // Converts a key string sequence of the form a<C-w>bd<Left> into Vim\'s\n
-    // keymap representation.\n
-    function parseKeyString(str) {\n
-      var key, match;\n
-      var keys = [];\n
-      while (str) {\n
-        match = (/<\\w+-.+?>|<\\w+>|./).exec(str);\n
-        if(match === null)break;\n
-        key = match[0];\n
-        str = str.substring(match.index + key.length);\n
-        keys.push(key);\n
-      }\n
-      return keys;\n
-    }\n
 \n
     var exCommands = {\n
       map: function(cm, params, ctx) {\n
@@ -3305,8 +4117,19 @@
         }\n
         exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx);\n
       },\n
+      imap: function(cm, params) { this.map(cm, params, \'insert\'); },\n
       nmap: function(cm, params) { this.map(cm, params, \'normal\'); },\n
       vmap: function(cm, params) { this.map(cm, params, \'visual\'); },\n
+      unmap: function(cm, params, ctx) {\n
+        var mapArgs = params.args;\n
+        if (!mapArgs || mapArgs.length < 1) {\n
+          if (cm) {\n
+            showConfirm(cm, \'No such mapping: \' + params.input);\n
+          }\n
+          return;\n
+        }\n
+        exCommandDispatcher.unmap(mapArgs[0], ctx);\n
+      },\n
       move: function(cm, params) {\n
         commandDispatcher.processCommand(cm, cm.state.vim, {\n
             type: \'motion\',\n
@@ -3315,6 +4138,73 @@
               linewise: true },\n
             repeatOverride: params.line+1});\n
       },\n
+      set: function(cm, params) {\n
+        var setArgs = params.args;\n
+        if (!setArgs || setArgs.length < 1) {\n
+          if (cm) {\n
+            showConfirm(cm, \'Invalid mapping: \' + params.input);\n
+          }\n
+          return;\n
+        }\n
+        var expr = setArgs[0].split(\'=\');\n
+        var optionName = expr[0];\n
+        var value = expr[1];\n
+        var forceGet = false;\n
+\n
+        if (optionName.charAt(optionName.length - 1) == \'?\') {\n
+          // If post-fixed with ?, then the set is actually a get.\n
+          if (value) { throw Error(\'Trailing characters: \' + params.argString); }\n
+          optionName = optionName.substring(0, optionName.length - 1);\n
+          forceGet = true;\n
+        }\n
+        if (value === undefined && optionName.substring(0, 2) == \'no\') {\n
+          // To set boolean options to false, the option name is prefixed with\n
+          // \'no\'.\n
+          optionName = optionName.substring(2);\n
+          value = false;\n
+        }\n
+        var optionIsBoolean = options[optionName] && options[optionName].type == \'boolean\';\n
+        if (optionIsBoolean && value == undefined) {\n
+          // Calling set with a boolean option sets it to true.\n
+          value = true;\n
+        }\n
+        if (!optionIsBoolean && !value || forceGet) {\n
+          var oldValue = getOption(optionName);\n
+          // If no value is provided, then we assume this is a get.\n
+          if (oldValue === true || oldValue === false) {\n
+            showConfirm(cm, \' \' + (oldValue ? \'\' : \'no\') + optionName);\n
+          } else {\n
+            showConfirm(cm, \'  \' + optionName + \'=\' + oldValue);\n
+          }\n
+        } else {\n
+          setOption(optionName, value);\n
+        }\n
+      },\n
+      registers: function(cm,params) {\n
+        var regArgs = params.args;\n
+        var registers = vimGlobalState.registerController.registers;\n
+        var regInfo = \'----------Registers----------<br><br>\';\n
+        if (!regArgs) {\n
+          for (var registerName in registers) {\n
+            var text = registers[registerName].toString();\n
+            if (text.length) {\n
+              regInfo += \'"\' + registerName + \'    \' + text + \'<br>\';\n
+            }\n
+          }\n
+        } else {\n
+          var registerName;\n
+          regArgs = regArgs.join(\'\');\n
+          for (var i = 0; i < regArgs.length; i++) {\n
+            registerName = regArgs.charAt(i);\n
+            if (!vimGlobalState.registerController.isValidRegister(registerName)) {\n
+              continue;\n
+            }\n
+            var register = registers[registerName] || new Register();\n
+            regInfo += \'"\' + registerName + \'    \' + register.toString() + \'<br>\';\n
+          }\n
+        }\n
+        showConfirm(cm, regInfo);\n
+      },\n
       sort: function(cm, params) {\n
         var reverse, ignoreCase, unique, number;\n
         function parseArgs() {\n
@@ -3345,8 +4235,8 @@
         var lineStart = params.line || cm.firstLine();\n
         var lineEnd = params.lineEnd || params.line || cm.lastLine();\n
         if (lineStart == lineEnd) { return; }\n
-        var curStart = { line: lineStart, ch: 0 };\n
-        var curEnd = { line: lineEnd, ch: lineLength(cm, lineEnd) };\n
+        var curStart = Pos(lineStart, 0);\n
+        var curEnd = Pos(lineEnd, lineLength(cm, lineEnd));\n
         var text = cm.getRange(curStart, curEnd).split(\'\\n\');\n
         var numberRegex = (number == \'decimal\') ? /(-?)([\\d]+)/ :\n
            (number == \'hex\') ? /(-?)(?:0x)?([0-9a-f]+)/i :\n
@@ -3390,40 +4280,112 @@
         }\n
         cm.replaceRange(text.join(\'\\n\'), curStart, curEnd);\n
       },\n
+      global: function(cm, params) {\n
+        // a global command is of the form\n
+        // :[range]g/pattern/[cmd]\n
+        // argString holds the string /pattern/[cmd]\n
+        var argString = params.argString;\n
+        if (!argString) {\n
+          showConfirm(cm, \'Regular Expression missing from global\');\n
+          return;\n
+        }\n
+        // range is specified here\n
+        var lineStart = (params.line !== undefined) ? params.line : cm.firstLine();\n
+        var lineEnd = params.lineEnd || params.line || cm.lastLine();\n
+        // get the tokens from argString\n
+        var tokens = splitBySlash(argString);\n
+        var regexPart = argString, cmd;\n
+        if (tokens.length) {\n
+          regexPart = tokens[0];\n
+          cmd = tokens.slice(1, tokens.length).join(\'/\');\n
+        }\n
+        if (regexPart) {\n
+          // If regex part is empty, then use the previous query. Otherwise\n
+          // use the regex part as the new query.\n
+          try {\n
+           updateSearchQuery(cm, regexPart, true /** ignoreCase */,\n
+             true /** smartCase */);\n
+          } catch (e) {\n
+           showConfirm(cm, \'Invalid regex: \' + regexPart);\n
+           return;\n
+          }\n
+        }\n
+        // now that we have the regexPart, search for regex matches in the\n
+        // specified range of lines\n
+        var query = getSearchState(cm).getQuery();\n
+        var matchedLines = [], content = \'\';\n
+        for (var i = lineStart; i <= lineEnd; i++) {\n
+          var matched = query.test(cm.getLine(i));\n
+          if (matched) {\n
+            matchedLines.push(i+1);\n
+            content+= cm.getLine(i) + \'<br>\';\n
+          }\n
+        }\n
+        // if there is no [cmd], just display the list of matched lines\n
+        if (!cmd) {\n
+          showConfirm(cm, content);\n
+          return;\n
+        }\n
+        var index = 0;\n
+        var nextCommand = function() {\n
+          if (index < matchedLines.length) {\n
+            var command = matchedLines[index] + cmd;\n
+            exCommandDispatcher.processCommand(cm, command, {\n
+              callback: nextCommand\n
+            });\n
+          }\n
+          index++;\n
+        };\n
+        nextCommand();\n
+      },\n
       substitute: function(cm, params) {\n
         if (!cm.getSearchCursor) {\n
           throw new Error(\'Search feature not available. Requires searchcursor.js or \' +\n
               \'any other getSearchCursor implementation.\');\n
         }\n
         var argString = params.argString;\n
-        var slashes = findUnescapedSlashes(argString);\n
-        if (slashes[0] !== 0) {\n
-          showConfirm(cm, \'Substitutions should be of the form \' +\n
-              \':s/pattern/replace/\');\n
-          return;\n
-        }\n
-        var regexPart = argString.substring(slashes[0] + 1, slashes[1]);\n
-        var replacePart = \'\';\n
-        var flagsPart;\n
-        var count;\n
+        var tokens = argString ? splitBySlash(argString) : [];\n
+        var regexPart, replacePart = \'\', trailing, flagsPart, count;\n
         var confirm = false; // Whether to confirm each replace.\n
-        if (slashes[1]) {\n
-          replacePart = argString.substring(slashes[1] + 1, slashes[2]);\n
-          replacePart = fixRegexReplace(replacePart);\n
-        }\n
-        if (slashes[2]) {\n
-          // After the 3rd slash, we can have flags followed by a space followed\n
-          // by count.\n
-          var trailing = argString.substring(slashes[2] + 1).split(\' \');\n
+        var global = false; // True to replace all instances on a line, false to replace only 1.\n
+        if (tokens.length) {\n
+          regexPart = tokens[0];\n
+          replacePart = tokens[1];\n
+          if (replacePart !== undefined) {\n
+            if (getOption(\'pcre\')) {\n
+              replacePart = unescapeRegexReplace(replacePart);\n
+            } else {\n
+              replacePart = translateRegexReplace(replacePart);\n
+            }\n
+            vimGlobalState.lastSubstituteReplacePart = replacePart;\n
+          }\n
+          trailing = tokens[2] ? tokens[2].split(\' \') : [];\n
+        } else {\n
+          // either the argString is empty or its of the form \' hello/world\'\n
+          // actually splitBySlash returns a list of tokens\n
+          // only if the string starts with a \'/\'\n
+          if (argString && argString.length) {\n
+            showConfirm(cm, \'Substitutions should be of the form \' +\n
+                \':s/pattern/replace/\');\n
+            return;\n
+          }\n
+        }\n
+        // After the 3rd slash, we can have flags followed by a space followed\n
+        // by count.\n
+        if (trailing) {\n
           flagsPart = trailing[0];\n
           count = parseInt(trailing[1]);\n
-        }\n
-        if (flagsPart) {\n
-          if (flagsPart.indexOf(\'c\') != -1) {\n
-            confirm = true;\n
-            flagsPart.replace(\'c\', \'\');\n
+          if (flagsPart) {\n
+            if (flagsPart.indexOf(\'c\') != -1) {\n
+              confirm = true;\n
+              flagsPart.replace(\'c\', \'\');\n
+            }\n
+            if (flagsPart.indexOf(\'g\') != -1) {\n
+              global = true;\n
+              flagsPart.replace(\'g\', \'\');\n
+            }\n
+            regexPart = regexPart + \'/\' + flagsPart;\n
           }\n
-          regexPart = regexPart + \'/\' + flagsPart;\n
         }\n
         if (regexPart) {\n
           // If regex part is empty, then use the previous query. Otherwise use\n
@@ -3436,6 +4398,11 @@
             return;\n
           }\n
         }\n
+        replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart;\n
+        if (replacePart === undefined) {\n
+          showConfirm(cm, \'No previous substitute regular expression\');\n
+          return;\n
+        }\n
         var state = getSearchState(cm);\n
         var query = state.getQuery();\n
         var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line;\n
@@ -3444,9 +4411,9 @@
           lineStart = lineEnd;\n
           lineEnd = lineStart + count - 1;\n
         }\n
-        var startPos = clipCursorToContent(cm, { line: lineStart, ch: 0 });\n
+        var startPos = clipCursorToContent(cm, Pos(lineStart, 0));\n
         var cursor = cm.getSearchCursor(query, startPos);\n
-        doReplace(cm, confirm, lineStart, lineEnd, cursor, query, replacePart);\n
+        doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback);\n
       },\n
       redo: CodeMirror.commands.redo,\n
       undo: CodeMirror.commands.undo,\n
@@ -3525,7 +4492,7 @@
       }\n
     };\n
 \n
-    var exCommandDispatcher = new Vim.ExCommandDispatcher();\n
+    var exCommandDispatcher = new ExCommandDispatcher();\n
 \n
     /**\n
     * @param {CodeMirror} cm CodeMirror instance we are in.\n
@@ -3535,9 +4502,10 @@
     * @param {RegExp} query Query for performing matches with.\n
     * @param {string} replaceWith Text to replace matches with. May contain $1,\n
     *     $2, etc for replacing captured groups using Javascript replace.\n
+    * @param {function()} callback A callback for when the replace is done.\n
     */\n
-    function doReplace(cm, confirm, lineStart, lineEnd, searchCursor, query,\n
-        replaceWith) {\n
+    function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query,\n
+        replaceWith, callback) {\n
       // Set up all the functions.\n
       cm.state.vim.exMode = true;\n
       var done = false;\n
@@ -3557,17 +4525,21 @@
         searchCursor.replace(newText);\n
       }\n
       function next() {\n
-        var found = searchCursor.findNext();\n
-        if (!found) {\n
-          done = true;\n
-        } else if (isInRange(searchCursor.from(), lineStart, lineEnd)) {\n
+        var found;\n
+        // The below only loops to skip over multiple occurrences on the same\n
+        // line when \'global\' is not true.\n
+        while(found = searchCursor.findNext() &&\n
+              isInRange(searchCursor.from(), lineStart, lineEnd)) {\n
+          if (!global && lastPos && searchCursor.from().line == lastPos.line) {\n
+            continue;\n
+          }\n
           cm.scrollIntoView(searchCursor.from(), 30);\n
           cm.setSelection(searchCursor.from(), searchCursor.to());\n
           lastPos = searchCursor.from();\n
           done = false;\n
-        } else {\n
-          done = true;\n
+          return;\n
         }\n
+        done = true;\n
       }\n
       function stop(close) {\n
         if (close) { close(); }\n
@@ -3578,6 +4550,7 @@
           vim.exMode = false;\n
           vim.lastHPos = vim.lastHSPos = lastPos.ch;\n
         }\n
+        if (callback) { callback(); }\n
       }\n
       function onPromptKeyDown(e, _value, close) {\n
         // Swallow all keys.\n
@@ -3589,7 +4562,13 @@
           case \'N\':\n
             next(); break;\n
           case \'A\':\n
-            cm.operation(replaceAll); break;\n
+            // replaceAll contains a call to close of its own. We don\'t want it\n
+            // to fire too early or multiple times.\n
+            var savedCallback = callback;\n
+            callback = undefined;\n
+            cm.operation(replaceAll);\n
+            callback = savedCallback;\n
+            break;\n
           case \'L\':\n
             replace();\n
             // fall through and exit.\n
@@ -3601,6 +4580,7 @@
             break;\n
         }\n
         if (done) { stop(close); }\n
+        return true;\n
       }\n
 \n
       // Actually do replace.\n
@@ -3611,6 +4591,7 @@
       }\n
       if (!confirm) {\n
         replaceAll();\n
+        if (callback) { callback(); };\n
         return;\n
       }\n
       showPrompt(cm, {\n
@@ -3619,94 +4600,73 @@
       });\n
     }\n
 \n
-    // Register Vim with CodeMirror\n
-    function buildVimKeyMap() {\n
-      /**\n
-       * Handle the raw key event from CodeMirror. Translate the\n
-       * Shift + key modifier to the resulting letter, while preserving other\n
-       * modifers.\n
-       */\n
-      function cmKeyToVimKey(key, modifier) {\n
-        var vimKey = key;\n
-        if (isUpperCase(vimKey) && modifier == \'Ctrl\') {\n
-            vimKey = vimKey.toLowerCase();\n
-        }\n
-        if (modifier) {\n
-          // Vim will parse modifier+key combination as a single key.\n
-          vimKey = modifier.charAt(0) + \'-\' + vimKey;\n
-        }\n
-        var specialKey = ({Enter:\'CR\',Backspace:\'BS\',Delete:\'Del\'})[vimKey];\n
-        vimKey = specialKey ? specialKey : vimKey;\n
-        vimKey = vimKey.length > 1 ? \'<\'+ vimKey + \'>\' : vimKey;\n
-        return vimKey;\n
-      }\n
-\n
-      // Closure to bind CodeMirror, key, modifier.\n
-      function keyMapper(vimKey) {\n
-        return function(cm) {\n
-          CodeMirror.Vim.handleKey(cm, vimKey);\n
-        };\n
-      }\n
-\n
-      var cmToVimKeymap = {\n
-        \'nofallthrough\': true,\n
-        \'style\': \'fat-cursor\'\n
-      };\n
-      function bindKeys(keys, modifier) {\n
-        for (var i = 0; i < keys.length; i++) {\n
-          var key = keys[i];\n
-          if (!modifier && key.length == 1) {\n
-            // Wrap all keys without modifiers with \'\' to identify them by their\n
-            // key characters instead of key identifiers.\n
-            key = "\'" + key + "\'";\n
-          }\n
-          var vimKey = cmKeyToVimKey(keys[i], modifier);\n
-          var cmKey = modifier ? modifier + \'-\' + key : key;\n
-          cmToVimKeymap[cmKey] = keyMapper(vimKey);\n
-        }\n
-      }\n
-      bindKeys(upperCaseAlphabet);\n
-      bindKeys(lowerCaseAlphabet);\n
-      bindKeys(upperCaseAlphabet, \'Ctrl\');\n
-      bindKeys(specialSymbols);\n
-      bindKeys(specialSymbols, \'Ctrl\');\n
-      bindKeys(numbers);\n
-      bindKeys(numbers, \'Ctrl\');\n
-      bindKeys(specialKeys);\n
-      bindKeys(specialKeys, \'Ctrl\');\n
-      return cmToVimKeymap;\n
-    }\n
-    CodeMirror.keyMap.vim = buildVimKeyMap();\n
+    CodeMirror.keyMap.vim = {\n
+      attach: attachVimMap,\n
+      detach: detachVimMap,\n
+      call: cmKey\n
+    };\n
 \n
     function exitInsertMode(cm) {\n
       var vim = cm.state.vim;\n
-      var inReplay = vimGlobalState.macroModeState.inReplay;\n
-      if (!inReplay) {\n
+      var macroModeState = vimGlobalState.macroModeState;\n
+      var insertModeChangeRegister = vimGlobalState.registerController.getRegister(\'.\');\n
+      var isPlaying = macroModeState.isPlaying;\n
+      var lastChange = macroModeState.lastInsertModeChanges;\n
+      // In case of visual block, the insertModeChanges are not saved as a\n
+      // single word, so we convert them to a single word\n
+      // so as to update the ". register as expected in real vim.\n
+      var text = [];\n
+      if (!isPlaying) {\n
+        var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1;\n
+        var changes = lastChange.changes;\n
+        var text = [];\n
+        var i = 0;\n
+        // In case of multiple selections in blockwise visual,\n
+        // the inserted text, for example: \'f<Backspace>oo\', is stored as\n
+        // \'f\', \'f\', InsertModeKey \'o\', \'o\', \'o\', \'o\'. (if you have a block with 2 lines).\n
+        // We push the contents of the changes array as per the following:\n
+        // 1. In case of InsertModeKey, just increment by 1.\n
+        // 2. In case of a character, jump by selLength (2 in the example).\n
+        while (i < changes.length) {\n
+          // This loop will convert \'ff<bs>oooo\' to \'f<bs>oo\'.\n
+          text.push(changes[i]);\n
+          if (changes[i] instanceof InsertModeKey) {\n
+             i++;\n
+          } else {\n
+             i+= selLength;\n
+          }\n
+        }\n
+        lastChange.changes = text;\n
         cm.off(\'change\', onChange);\n
-        cm.off(\'cursorActivity\', onCursorActivity);\n
         CodeMirror.off(cm.getInputField(), \'keydown\', onKeyEventTargetKeyDown);\n
       }\n
-      if (!inReplay && vim.insertModeRepeat > 1) {\n
+      if (!isPlaying && vim.insertModeRepeat > 1) {\n
         // Perform insert mode repeat for commands like 3,a and 3,o.\n
         repeatLastEdit(cm, vim, vim.insertModeRepeat - 1,\n
             true /** repeatForInsert */);\n
         vim.lastEditInputState.repeatOverride = vim.insertModeRepeat;\n
       }\n
       delete vim.insertModeRepeat;\n
-      cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);\n
       vim.insertMode = false;\n
+      cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1);\n
       cm.setOption(\'keyMap\', \'vim\');\n
       cm.setOption(\'disableInput\', true);\n
       cm.toggleOverwrite(false); // exit replace mode if we were in it.\n
+      // update the ". register before exiting insert mode\n
+      insertModeChangeRegister.setText(lastChange.changes.join(\'\'));\n
       CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});\n
+      if (macroModeState.isRecording) {\n
+        logInsertModeChange(macroModeState);\n
+      }\n
     }\n
+\n
+    // The timeout in milliseconds for the two-character ESC keymap should be\n
+    // adjusted according to your typing speed to prevent false positives.\n
+    defineOption(\'insertModeEscKeysTimeout\', 200, \'number\');\n
 \n
     CodeMirror.keyMap[\'vim-insert\'] = {\n
       // TODO: override navigation keys so that Esc will cancel automatic\n
       // indentation from o, O, i_<CR>\n
-      \'Esc\': exitInsertMode,\n
-      \'Ctrl-[\': exitInsertMode,\n
-      \'Ctrl-C\': exitInsertMode,\n
       \'Ctrl-N\': \'autocomplete\',\n
       \'Ctrl-P\': \'autocomplete\',\n
       \'Enter\': function(cm) {\n
@@ -3714,53 +4674,73 @@
             CodeMirror.commands.newlineAndIndent;\n
         fn(cm);\n
       },\n
-      fallthrough: [\'default\']\n
+      fallthrough: [\'default\'],\n
+      attach: attachVimMap,\n
+      detach: detachVimMap,\n
+      call: cmKey\n
     };\n
 \n
     CodeMirror.keyMap[\'vim-replace\'] = {\n
       \'Backspace\': \'goCharLeft\',\n
-      fallthrough: [\'vim-insert\']\n
+      fallthrough: [\'vim-insert\'],\n
+      attach: attachVimMap,\n
+      detach: detachVimMap,\n
+      call: cmKey\n
     };\n
 \n
-    function parseRegisterToKeyBuffer(macroModeState, registerName) {\n
-      var match, key;\n
+    function executeMacroRegister(cm, vim, macroModeState, registerName) {\n
       var register = vimGlobalState.registerController.getRegister(registerName);\n
-      var text = register.toString();\n
-      var macroKeyBuffer = macroModeState.macroKeyBuffer;\n
-      emptyMacroKeyBuffer(macroModeState);\n
-      do {\n
-        match = (/<\\w+-.+?>|<\\w+>|./).exec(text);\n
-        if(match === null)break;\n
-        key = match[0];\n
-        text = text.substring(match.index + key.length);\n
-        macroKeyBuffer.push(key);\n
-      } while (text);\n
-      return macroKeyBuffer;\n
-    }\n
-\n
-    function parseKeyBufferToRegister(registerName, keyBuffer) {\n
-      var text = keyBuffer.join(\'\');\n
-      vimGlobalState.registerController.setRegisterText(registerName, text);\n
-    }\n
-\n
-    function emptyMacroKeyBuffer(macroModeState) {\n
-      if(macroModeState.isMacroPlaying)return;\n
-      var macroKeyBuffer = macroModeState.macroKeyBuffer;\n
-      macroKeyBuffer.length = 0;\n
-    }\n
-\n
-    function executeMacroKeyBuffer(cm, macroModeState, keyBuffer) {\n
-      macroModeState.isMacroPlaying = true;\n
-      for (var i = 0, len = keyBuffer.length; i < len; i++) {\n
-        CodeMirror.Vim.handleKey(cm, keyBuffer[i]);\n
+      var keyBuffer = register.keyBuffer;\n
+      var imc = 0;\n
+      macroModeState.isPlaying = true;\n
+      macroModeState.replaySearchQueries = register.searchQueries.slice(0);\n
+      for (var i = 0; i < keyBuffer.length; i++) {\n
+        var text = keyBuffer[i];\n
+        var match, key;\n
+        while (text) {\n
+          // Pull off one command key, which is either a single character\n
+          // or a special sequence wrapped in \'<\' and \'>\', e.g. \'<Space>\'.\n
+          match = (/<\\w+-.+?>|<\\w+>|./).exec(text);\n
+          key = match[0];\n
+          text = text.substring(match.index + key.length);\n
+          CodeMirror.Vim.handleKey(cm, key, \'macro\');\n
+          if (vim.insertMode) {\n
+            var changes = register.insertModeChanges[imc++].changes;\n
+            vimGlobalState.macroModeState.lastInsertModeChanges.changes =\n
+                changes;\n
+            repeatInsertModeChanges(cm, changes, 1);\n
+            exitInsertMode(cm);\n
+          }\n
+        }\n
       };\n
-      macroModeState.isMacroPlaying = false;\n
+      macroModeState.isPlaying = false;\n
     }\n
 \n
     function logKey(macroModeState, key) {\n
-      if(macroModeState.isMacroPlaying)return;\n
-      var macroKeyBuffer = macroModeState.macroKeyBuffer;\n
-      macroKeyBuffer.push(key);\n
+      if (macroModeState.isPlaying) { return; }\n
+      var registerName = macroModeState.latestRegister;\n
+      var register = vimGlobalState.registerController.getRegister(registerName);\n
+      if (register) {\n
+        register.pushText(key);\n
+      }\n
+    }\n
+\n
+    function logInsertModeChange(macroModeState) {\n
+      if (macroModeState.isPlaying) { return; }\n
+      var registerName = macroModeState.latestRegister;\n
+      var register = vimGlobalState.registerController.getRegister(registerName);\n
+      if (register) {\n
+        register.pushInsertModeChanges(macroModeState.lastInsertModeChanges);\n
+      }\n
+    }\n
+\n
+    function logSearchQuery(macroModeState, query) {\n
+      if (macroModeState.isPlaying) { return; }\n
+      var registerName = macroModeState.latestRegister;\n
+      var register = vimGlobalState.registerController.getRegister(registerName);\n
+      if (register) {\n
+        register.pushSearchQuery(query);\n
+      }\n
     }\n
 \n
     /**\n
@@ -3770,31 +4750,79 @@
     function onChange(_cm, changeObj) {\n
       var macroModeState = vimGlobalState.macroModeState;\n
       var lastChange = macroModeState.lastInsertModeChanges;\n
-      while (changeObj) {\n
-        lastChange.expectCursorActivityForChange = true;\n
-        if (changeObj.origin == \'+input\' || changeObj.origin == \'paste\'\n
-            || changeObj.origin === undefined /* only in testing */) {\n
-          var text = changeObj.text.join(\'\\n\');\n
-          lastChange.changes.push(text);\n
+      if (!macroModeState.isPlaying) {\n
+        while(changeObj) {\n
+          lastChange.expectCursorActivityForChange = true;\n
+          if (changeObj.origin == \'+input\' || changeObj.origin == \'paste\'\n
+              || changeObj.origin === undefined /* only in testing */) {\n
+            var text = changeObj.text.join(\'\\n\');\n
+            lastChange.changes.push(text);\n
+          }\n
+          // Change objects may be chained with next.\n
+          changeObj = changeObj.next;\n
         }\n
-        // Change objects may be chained with next.\n
-        changeObj = changeObj.next;\n
       }\n
     }\n
 \n
     /**\n
     * Listens for any kind of cursor activity on CodeMirror.\n
-    * - For tracking cursor activity in insert mode.\n
-    * - Should only be active in insert mode.\n
     */\n
-    function onCursorActivity() {\n
-      var macroModeState = vimGlobalState.macroModeState;\n
-      var lastChange = macroModeState.lastInsertModeChanges;\n
-      if (lastChange.expectCursorActivityForChange) {\n
-        lastChange.expectCursorActivityForChange = false;\n
-      } else {\n
-        // Cursor moved outside the context of an edit. Reset the change.\n
-        lastChange.changes = [];\n
+    function onCursorActivity(cm) {\n
+      var vim = cm.state.vim;\n
+      if (vim.insertMode) {\n
+        // Tracking cursor activity in insert mode (for macro support).\n
+        var macroModeState = vimGlobalState.macroModeState;\n
+        if (macroModeState.isPlaying) { return; }\n
+        var lastChange = macroModeState.lastInsertModeChanges;\n
+        if (lastChange.expectCursorActivityForChange) {\n
+          lastChange.expectCursorActivityForChange = false;\n
+        } else {\n
+          // Cursor moved outside the context of an edit. Reset the change.\n
+          lastChange.changes = [];\n
+        }\n
+      } else if (!cm.curOp.isVimOp) {\n
+        handleExternalSelection(cm, vim);\n
+      }\n
+      if (vim.visualMode) {\n
+        updateFakeCursor(cm);\n
+      }\n
+    }\n
+    function updateFakeCursor(cm) {\n
+      var vim = cm.state.vim;\n
+      var from = copyCursor(vim.sel.head);\n
+      var to = offsetCursor(from, 0, 1);\n
+      if (vim.fakeCursor) {\n
+        vim.fakeCursor.clear();\n
+      }\n
+      vim.fakeCursor = cm.markText(from, to, {className: \'cm-animate-fat-cursor\'});\n
+    }\n
+    function handleExternalSelection(cm, vim) {\n
+      var anchor = cm.getCursor(\'anchor\');\n
+      var head = cm.getCursor(\'head\');\n
+      // Enter or exit visual mode to match mouse selection.\n
+      if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) {\n
+        exitVisualMode(cm, false);\n
+      } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {\n
+        vim.visualMode = true;\n
+        vim.visualLine = false;\n
+        CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});\n
+      }\n
+      if (vim.visualMode) {\n
+        // Bind CodeMirror selection model to vim selection model.\n
+        // Mouse selections are considered visual characterwise.\n
+        var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0;\n
+        var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0;\n
+        head = offsetCursor(head, 0, headOffset);\n
+        anchor = offsetCursor(anchor, 0, anchorOffset);\n
+        vim.sel = {\n
+          anchor: anchor,\n
+          head: head\n
+        };\n
+        updateMark(cm, vim, \'<\', cursorMin(head, anchor));\n
+        updateMark(cm, vim, \'>\', cursorMax(head, anchor));\n
+      } else if (!vim.insertMode) {\n
+        // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse.\n
+        vim.lastHPos = cm.getCursor().ch;\n
       }\n
     }\n
 \n
@@ -3817,7 +4845,7 @@
         return true;\n
       }\n
       if (keyName.indexOf(\'Delete\') != -1 || keyName.indexOf(\'Backspace\') != -1) {\n
-        CodeMirror.lookupKey(keyName, [\'vim-insert\'], onKeyFound);\n
+        CodeMirror.lookupKey(keyName, \'vim-insert\', onKeyFound);\n
       }\n
     }\n
 \n
@@ -3832,7 +4860,7 @@
      */\n
     function repeatLastEdit(cm, vim, repeat, repeatForInsert) {\n
       var macroModeState = vimGlobalState.macroModeState;\n
-      macroModeState.inReplay = true;\n
+      macroModeState.isPlaying = true;\n
       var isAction = !!vim.lastEditActionCommand;\n
       var cachedInputState = vim.inputState;\n
       function repeatCommand() {\n
@@ -3844,10 +4872,11 @@
       }\n
       function repeatInsert(repeat) {\n
         if (macroModeState.lastInsertModeChanges.changes.length > 0) {\n
-          // For some reason, repeat cw in desktop VIM will does not repeat\n
+          // For some reason, repeat cw in desktop VIM does not repeat\n
           // insert mode changes. Will conform to that behavior.\n
           repeat = !vim.lastEditActionCommand ? 1 : repeat;\n
-          repeatLastInsertModeChanges(cm, repeat, macroModeState);\n
+          var changeObject = macroModeState.lastInsertModeChanges;\n
+          repeatInsertModeChanges(cm, changeObject.changes, repeat);\n
         }\n
       }\n
       vim.inputState = vim.lastEditInputState;\n
@@ -3873,11 +4902,10 @@
         // were called by an exitInsertMode call lower on the stack.\n
         exitInsertMode(cm);\n
       }\n
-      macroModeState.inReplay = false;\n
+      macroModeState.isPlaying = false;\n
     };\n
 \n
-    function repeatLastInsertModeChanges(cm, repeat, macroModeState) {\n
-      var lastChange = macroModeState.lastInsertModeChanges;\n
+    function repeatInsertModeChanges(cm, changes, repeat) {\n
       function keyHandler(binding) {\n
         if (typeof binding == \'string\') {\n
           CodeMirror.commands[binding](cm);\n
@@ -3886,17 +4914,34 @@
         }\n
         return true;\n
       }\n
+      var head = cm.getCursor(\'head\');\n
+      var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock;\n
+      if (inVisualBlock) {\n
+        // Set up block selection again for repeating the changes.\n
+        var vim = cm.state.vim;\n
+        var lastSel = vim.lastSelection;\n
+        var offset = getOffset(lastSel.anchor, lastSel.head);\n
+        selectForInsert(cm, head, offset.line + 1);\n
+        repeat = cm.listSelections().length;\n
+        cm.setCursor(head);\n
+      }\n
       for (var i = 0; i < repeat; i++) {\n
-        for (var j = 0; j < lastChange.changes.length; j++) {\n
-          var change = lastChange.changes[j];\n
+        if (inVisualBlock) {\n
+          cm.setCursor(offsetCursor(head, i, 0));\n
+        }\n
+        for (var j = 0; j < changes.length; j++) {\n
+          var change = changes[j];\n
           if (change instanceof InsertModeKey) {\n
-            CodeMirror.lookupKey(change.keyName, [\'vim-insert\'], keyHandler);\n
+            CodeMirror.lookupKey(change.keyName, \'vim-insert\', keyHandler);\n
           } else {\n
             var cur = cm.getCursor();\n
             cm.replaceRange(change, cur, cur);\n
           }\n
         }\n
       }\n
+      if (inVisualBlock) {\n
+        cm.setCursor(offsetCursor(head, 0, 1));\n
+      }\n
     }\n
 \n
     resetVimGlobalState();\n
@@ -3904,8 +4949,7 @@
   };\n
   // Initialize Vim and make it available as an API.\n
   CodeMirror.Vim = Vim();\n
-}\n
-)();\n
+});\n
 
 
 ]]></string> </value>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.css.xml
index ad9b9765eb5fbdd8f448778ff59fd0b2c71c61a5..85621ec3d2e197dd2026f0b9110fe32fbf236ce9 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.css.xml
@@ -31,10 +31,6 @@
   font-family: monospace;\n
   height: 300px;\n
 }\n
-.CodeMirror-scroll {\n
-  /* Set scrolling behaviour here */\n
-  overflow: auto;\n
-}\n
 \n
 /* PADDING */\n
 \n
@@ -66,26 +62,54 @@
   box-sizing: content-box;\n
 }\n
 \n
+.CodeMirror-guttermarker { color: black; }\n
+.CodeMirror-guttermarker-subtle { color: #999; }\n
+\n
 /* CURSOR */\n
 \n
 .CodeMirror div.CodeMirror-cursor {\n
   border-left: 1px solid black;\n
-  z-index: 3;\n
 }\n
 /* Shown when moving in bi-directional text */\n
 .CodeMirror div.CodeMirror-secondarycursor {\n
   border-left: 1px solid silver;\n
 }\n
-.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {\n
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {\n
   width: auto;\n
   border: 0;\n
   background: #7e7;\n
+}\n
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {\n
   z-index: 1;\n
 }\n
+\n
+.cm-animate-fat-cursor {\n
+  width: auto;\n
+  border: 0;\n
+  -webkit-animation: blink 1.06s steps(1) infinite;\n
+  -moz-animation: blink 1.06s steps(1) infinite;\n
+  animation: blink 1.06s steps(1) infinite;\n
+}\n
+@-moz-keyframes blink {\n
+  0% { background: #7e7; }\n
+  50% { background: none; }\n
+  100% { background: #7e7; }\n
+}\n
+@-webkit-keyframes blink {\n
+  0% { background: #7e7; }\n
+  50% { background: none; }\n
+  100% { background: #7e7; }\n
+}\n
+@keyframes blink {\n
+  0% { background: #7e7; }\n
+  50% { background: none; }\n
+  100% { background: #7e7; }\n
+}\n
+\n
 /* Can style cursor different in overwrite (non-insert) mode */\n
-.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}\n
+div.CodeMirror-overwrite div.CodeMirror-cursor {}\n
 \n
-.cm-tab { display: inline-block; }\n
+.cm-tab { display: inline-block; text-decoration: inherit; }\n
 \n
 .CodeMirror-ruler {\n
   border-left: 1px solid #ccc;\n
@@ -98,11 +122,12 @@
 .cm-s-default .cm-atom {color: #219;}\n
 .cm-s-default .cm-number {color: #164;}\n
 .cm-s-default .cm-def {color: #00f;}\n
-.cm-s-default .cm-variable {color: black;}\n
+.cm-s-default .cm-variable,\n
+.cm-s-default .cm-punctuation,\n
+.cm-s-default .cm-property,\n
+.cm-s-default .cm-operator {}\n
 .cm-s-default .cm-variable-2 {color: #05a;}\n
 .cm-s-default .cm-variable-3 {color: #085;}\n
-.cm-s-default .cm-property {color: black;}\n
-.cm-s-default .cm-operator {color: black;}\n
 .cm-s-default .cm-comment {color: #a50;}\n
 .cm-s-default .cm-string {color: #a11;}\n
 .cm-s-default .cm-string-2 {color: #f50;}\n
@@ -122,12 +147,16 @@
 .cm-header, .cm-strong {font-weight: bold;}\n
 .cm-em {font-style: italic;}\n
 .cm-link {text-decoration: underline;}\n
+.cm-strikethrough {text-decoration: line-through;}\n
 \n
 .cm-s-default .cm-error {color: #f00;}\n
 .cm-invalidchar {color: #f00;}\n
 \n
+/* Default styles for common addons */\n
+\n
 div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\n
 div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
+.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n
 .CodeMirror-activeline-background {background: #e8f2ff;}\n
 \n
 /* STOP */\n
@@ -144,6 +173,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
 }\n
 \n
 .CodeMirror-scroll {\n
+  overflow: scroll !important; /* Things will break if this is overridden */\n
   /* 30px is the magic margin used to hide the element\'s real scrollbars */\n
   /* See overflow: hidden in .CodeMirror */\n
   margin-bottom: -30px; margin-right: -30px;\n
@@ -188,7 +218,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
 \n
 .CodeMirror-gutters {\n
   position: absolute; left: 0; top: 0;\n
-  padding-bottom: 30px;\n
   z-index: 3;\n
 }\n
 .CodeMirror-gutter {\n
@@ -196,13 +225,17 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
   height: 100%;\n
   -moz-box-sizing: content-box;\n
   box-sizing: content-box;\n
-  padding-bottom: 30px;\n
-  margin-bottom: -32px;\n
   display: inline-block;\n
+  margin-bottom: -30px;\n
   /* Hack to make IE7 behave */\n
   *zoom:1;\n
   *display:inline;\n
 }\n
+.CodeMirror-gutter-wrapper {\n
+  position: absolute;\n
+  z-index: 4;\n
+  height: 100%;\n
+}\n
 .CodeMirror-gutter-elt {\n
   position: absolute;\n
   cursor: default;\n
@@ -211,6 +244,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
 \n
 .CodeMirror-lines {\n
   cursor: text;\n
+  min-height: 1px; /* prevents collapsing before first draw */\n
 }\n
 .CodeMirror pre {\n
   /* Reset some styles that the rest of the page might have set */\n
@@ -248,10 +282,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
 \n
 .CodeMirror-widget {}\n
 \n
-.CodeMirror-wrap .CodeMirror-scroll {\n
-  overflow-x: hidden;\n
-}\n
-\n
 .CodeMirror-measure {\n
   position: absolute;\n
   width: 100%;\n
@@ -263,16 +293,22 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
 \n
 .CodeMirror div.CodeMirror-cursor {\n
   position: absolute;\n
-  visibility: hidden;\n
   border-right: none;\n
   width: 0;\n
 }\n
-.CodeMirror-focused div.CodeMirror-cursor {\n
+\n
+div.CodeMirror-cursors {\n
+  visibility: hidden;\n
+  position: relative;\n
+  z-index: 3;\n
+}\n
+.CodeMirror-focused div.CodeMirror-cursors {\n
   visibility: visible;\n
 }\n
 \n
 .CodeMirror-selected { background: #d9d9d9; }\n
 .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n
+.CodeMirror-crosshair { cursor: crosshair; }\n
 \n
 .cm-searching {\n
   background: #ffa;\n
@@ -282,12 +318,21 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n
 /* IE7 hack to prevent it from returning funny offsetTops on the spans */\n
 .CodeMirror span { *vertical-align: text-bottom; }\n
 \n
+/* Used to force a border model for a node */\n
+.cm-force-border { padding-right: .1px; }\n
+\n
 @media print {\n
   /* Hide the cursor when printing */\n
-  .CodeMirror div.CodeMirror-cursor {\n
+  .CodeMirror div.CodeMirror-cursors {\n
     visibility: hidden;\n
   }\n
 }\n
+\n
+/* See issue #2901 */\n
+.cm-tab-wrap-hack:after { content: \'\'; }\n
+\n
+/* Help users use markselection to safely style text background */\n
+span.CodeMirror-selectedtext { background: none; }\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.js.xml
index 1b9b654e640d4b290d1572121c39f072d63fd4d2..156ad963460f0b43f3a33eaa11a3de3c6a9d6d72 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/lib/codemirror.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403085.78</string> </value>
+            <value> <string>ts21897131.66</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -30,7 +30,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>241716</int> </value>
+            <value> <int>320620</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
@@ -49,33 +49,42 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-// CodeMirror version 3.22\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// This is CodeMirror (http://codemirror.net), a code editor\n
+// implemented in JavaScript on top of the browser\'s DOM.\n
 //\n
-// CodeMirror is the only global var we claim\n
-window.CodeMirror = (function() {\n
+// You can find some technical background for some of the code below\n
+// at http://marijnhaverbeke.nl/blog/#cm-internals .\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    module.exports = mod();\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    return define([], mod);\n
+  else // Plain browser env\n
+    this.CodeMirror = mod();\n
+})(function() {\n
   "use strict";\n
 \n
   // BROWSER SNIFFING\n
 \n
-  // Crude, but necessary to handle a number of hard-to-feature-detect\n
-  // bugs and behavior differences.\n
+  // Kludges for bugs and behavior differences that can\'t be feature\n
+  // detected are enabled based on userAgent etc sniffing.\n
+\n
   var gecko = /gecko\\/\\d/i.test(navigator.userAgent);\n
-  // IE11 currently doesn\'t count as \'ie\', since it has almost none of\n
-  // the same bugs as earlier versions. Use ie_gt10 to handle\n
-  // incompatibilities in that version.\n
-  var old_ie = /MSIE \\d/.test(navigator.userAgent);\n
-  var ie_lt8 = old_ie && (document.documentMode == null || document.documentMode < 8);\n
-  var ie_lt9 = old_ie && (document.documentMode == null || document.documentMode < 9);\n
-  var ie_lt10 = old_ie && (document.documentMode == null || document.documentMode < 10);\n
-  var ie_gt10 = /Trident\\/([7-9]|\\d{2,})\\./.test(navigator.userAgent);\n
-  var ie = old_ie || ie_gt10;\n
+  // ie_uptoN means Internet Explorer version N or lower\n
+  var ie_upto10 = /MSIE \\d/.test(navigator.userAgent);\n
+  var ie_11up = /Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(navigator.userAgent);\n
+  var ie = ie_upto10 || ie_11up;\n
+  var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);\n
   var webkit = /WebKit\\//.test(navigator.userAgent);\n
   var qtwebkit = webkit && /Qt\\/\\d+\\.\\d+/.test(navigator.userAgent);\n
   var chrome = /Chrome\\//.test(navigator.userAgent);\n
-  var opera = /Opera\\//.test(navigator.userAgent);\n
+  var presto = /Opera\\//.test(navigator.userAgent);\n
   var safari = /Apple Computer/.test(navigator.vendor);\n
   var khtml = /KHTML\\//.test(navigator.userAgent);\n
-  var mac_geLion = /Mac OS X 1\\d\\D([7-9]|\\d\\d)\\D/.test(navigator.userAgent);\n
   var mac_geMountainLion = /Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(navigator.userAgent);\n
   var phantom = /PhantomJS/.test(navigator.userAgent);\n
 \n
@@ -85,152 +94,188 @@ window.CodeMirror = (function() {\n
   var mac = ios || /Mac/.test(navigator.platform);\n
   var windows = /win/i.test(navigator.platform);\n
 \n
-  var opera_version = opera && navigator.userAgent.match(/Version\\/(\\d*\\.\\d*)/);\n
-  if (opera_version) opera_version = Number(opera_version[1]);\n
-  if (opera_version && opera_version >= 15) { opera = false; webkit = true; }\n
+  var presto_version = presto && navigator.userAgent.match(/Version\\/(\\d*\\.\\d*)/);\n
+  if (presto_version) presto_version = Number(presto_version[1]);\n
+  if (presto_version && presto_version >= 15) { presto = false; webkit = true; }\n
   // Some browsers use the wrong event properties to signal cmd/ctrl on OS X\n
-  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));\n
-  var captureMiddleClick = gecko || (ie && !ie_lt9);\n
+  var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));\n
+  var captureRightClick = gecko || (ie && ie_version >= 9);\n
 \n
-  // Optimize some code when these features are not used\n
+  // Optimize some code when these features are not used.\n
   var sawReadOnlySpans = false, sawCollapsedSpans = false;\n
 \n
-  // CONSTRUCTOR\n
+  // EDITOR CONSTRUCTOR\n
+\n
+  // A CodeMirror instance represents an editor. This is the object\n
+  // that user code is usually dealing with.\n
 \n
   function CodeMirror(place, options) {\n
     if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);\n
 \n
-    this.options = options = options || {};\n
+    this.options = options = options ? copyObj(options) : {};\n
     // Determine effective options based on given values and defaults.\n
-    for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))\n
-      options[opt] = defaults[opt];\n
+    copyObj(defaults, options, false);\n
     setGuttersForLineNumbers(options);\n
 \n
-    var docStart = typeof options.value == "string" ? 0 : options.value.first;\n
-    var display = this.display = makeDisplay(place, docStart);\n
+    var doc = options.value;\n
+    if (typeof doc == "string") doc = new Doc(doc, options.mode);\n
+    this.doc = doc;\n
+\n
+    var display = this.display = new Display(place, doc);\n
     display.wrapper.CodeMirror = this;\n
     updateGutters(this);\n
-    if (options.autofocus && !mobile) focusInput(this);\n
-\n
-    this.state = {keyMaps: [],\n
-                  overlays: [],\n
-                  modeGen: 0,\n
-                  overwrite: false, focused: false,\n
-                  suppressEdits: false,\n
-                  pasteIncoming: false, cutIncoming: false,\n
-                  draggingText: false,\n
-                  highlight: new Delayed()};\n
-\n
     themeChanged(this);\n
     if (options.lineWrapping)\n
       this.display.wrapper.className += " CodeMirror-wrap";\n
-\n
-    var doc = options.value;\n
-    if (typeof doc == "string") doc = new Doc(options.value, options.mode);\n
-    operation(this, attachDoc)(this, doc);\n
+    if (options.autofocus && !mobile) focusInput(this);\n
+    initScrollbars(this);\n
+\n
+    this.state = {\n
+      keyMaps: [],  // stores maps added by addKeyMap\n
+      overlays: [], // highlighting overlays, as added by addOverlay\n
+      modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info\n
+      overwrite: false, focused: false,\n
+      suppressEdits: false, // used to disable editing during key handlers when in readOnly mode\n
+      pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in readInput\n
+      draggingText: false,\n
+      highlight: new Delayed(), // stores highlight worker timeout\n
+      keySeq: null  // Unfinished key sequence\n
+    };\n
 \n
     // Override magic textarea content restore that IE sometimes does\n
     // on our hidden textarea on reload\n
-    if (old_ie) setTimeout(bind(resetInput, this, true), 20);\n
+    if (ie && ie_version < 11) setTimeout(bind(resetInput, this, true), 20);\n
 \n
     registerEventHandlers(this);\n
-    // IE throws unspecified error in certain cases, when\n
-    // trying to access activeElement before onload\n
-    var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }\n
-    if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);\n
-    else onBlur(this);\n
+    ensureGlobalHandlers();\n
+\n
+    startOperation(this);\n
+    this.curOp.forceUpdate = true;\n
+    attachDoc(this, doc);\n
 \n
-    operation(this, function() {\n
-      for (var opt in optionHandlers)\n
-        if (optionHandlers.propertyIsEnumerable(opt))\n
-          optionHandlers[opt](this, options[opt], Init);\n
-      for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);\n
-    })();\n
+    if ((options.autofocus && !mobile) || activeElt() == display.input)\n
+      setTimeout(bind(onFocus, this), 20);\n
+    else\n
+      onBlur(this);\n
+\n
+    for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))\n
+      optionHandlers[opt](this, options[opt], Init);\n
+    maybeUpdateLineNumberWidth(this);\n
+    for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);\n
+    endOperation(this);\n
   }\n
 \n
   // DISPLAY CONSTRUCTOR\n
 \n
-  function makeDisplay(place, docStart) {\n
-    var d = {};\n
+  // The display handles the DOM integration, both for input reading\n
+  // and content drawing. It holds references to DOM nodes and\n
+  // display-related state.\n
 \n
+  function Display(place, doc) {\n
+    var d = this;\n
+\n
+    // The semihidden textarea that is focused when the editor is\n
+    // focused, and receives input.\n
     var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");\n
+    // The textarea is kept positioned near the cursor to prevent the\n
+    // fact that it\'ll be scrolled into view on input from scrolling\n
+    // our fake cursor out of view. On webkit, when wrap=off, paste is\n
+    // very slow. So make the area wide instead.\n
     if (webkit) input.style.width = "1000px";\n
     else input.setAttribute("wrap", "off");\n
-    // if border: 0; -- iOS fails to open keyboard (issue #1287)\n
+    // If border: 0; -- iOS fails to open keyboard (issue #1287)\n
     if (ios) input.style.border = "1px solid black";\n
     input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");\n
 \n
     // Wraps and hides input textarea\n
     d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");\n
-    // The actual fake scrollbars.\n
-    d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");\n
-    d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");\n
+    // Covers bottom-right square when both scrollbars are present.\n
     d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");\n
+    d.scrollbarFiller.setAttribute("not-content", "true");\n
+    // Covers bottom of gutter when coverGutterNextToScrollbar is on\n
+    // and h scrollbar is present.\n
     d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");\n
-    // DIVs containing the selection and the actual code\n
+    d.gutterFiller.setAttribute("not-content", "true");\n
+    // Will contain the actual code, positioned to cover the viewport.\n
     d.lineDiv = elt("div", null, "CodeMirror-code");\n
+    // Elements are added to these to represent selection and cursors.\n
     d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");\n
-    // Blinky cursor, and element used to ensure cursor fits at the end of a line\n
-    d.cursor = elt("div", "\\u00a0", "CodeMirror-cursor");\n
-    // Secondary cursor, shown when on a \'jump\' in bi-directional text\n
-    d.otherCursor = elt("div", "\\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");\n
-    // Used to measure text size\n
+    d.cursorDiv = elt("div", null, "CodeMirror-cursors");\n
+    // A visibility: hidden element used to find the size of things.\n
     d.measure = elt("div", null, "CodeMirror-measure");\n
+    // When lines outside of the viewport are measured, they are drawn in this.\n
+    d.lineMeasure = elt("div", null, "CodeMirror-measure");\n
     // Wraps everything that needs to exist inside the vertically-padded coordinate system\n
-    d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],\n
-                         null, "position: relative; outline: none");\n
-    // Moved around its parent to cover visible view\n
+    d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],\n
+                      null, "position: relative; outline: none");\n
+    // Moved around its parent to cover visible view.\n
     d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");\n
-    // Set to the height of the text, causes scrolling\n
+    // Set to the height of the document, allowing scrolling.\n
     d.sizer = elt("div", [d.mover], "CodeMirror-sizer");\n
-    // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers\n
-    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");\n
-    // Will contain the gutters, if any\n
+    d.sizerWidth = null;\n
+    // Behavior of elts with overflow: auto and padding is\n
+    // inconsistent across browsers. This is used to ensure the\n
+    // scrollable area is big enough.\n
+    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");\n
+    // Will contain the gutters, if any.\n
     d.gutters = elt("div", null, "CodeMirror-gutters");\n
     d.lineGutter = null;\n
-    // Provides scrolling\n
+    // Actual scrollable element.\n
     d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");\n
     d.scroller.setAttribute("tabIndex", "-1");\n
     // The element in which the editor lives.\n
-    d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,\n
-                            d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");\n
-    // Work around IE7 z-index bug\n
-    if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }\n
-    if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);\n
+    d.wrapper = elt("div", [d.inputDiv, d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");\n
 \n
+    // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)\n
+    if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }\n
     // Needed to hide big blue blinking cursor on Mobile Safari\n
     if (ios) input.style.width = "0px";\n
     if (!webkit) d.scroller.draggable = true;\n
     // Needed to handle Tab key in KHTML\n
     if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }\n
-    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).\n
-    else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";\n
 \n
-    // Current visible range (may be bigger than the view window).\n
-    d.viewOffset = d.lastSizeC = 0;\n
-    d.showingFrom = d.showingTo = docStart;\n
+    if (place) {\n
+      if (place.appendChild) place.appendChild(d.wrapper);\n
+      else place(d.wrapper);\n
+    }\n
+\n
+    // Current rendered range (may be bigger than the view window).\n
+    d.viewFrom = d.viewTo = doc.first;\n
+    d.reportedViewFrom = d.reportedViewTo = doc.first;\n
+    // Information about the rendered lines.\n
+    d.view = [];\n
+    d.renderedView = null;\n
+    // Holds info about a single rendered line when it was rendered\n
+    // for measurement, while not in view.\n
+    d.externalMeasured = null;\n
+    // Empty space (in pixels) above the view\n
+    d.viewOffset = 0;\n
+    d.lastWrapHeight = d.lastWrapWidth = 0;\n
+    d.updateLineNumbers = null;\n
+\n
+    d.nativeBarWidth = d.barHeight = d.barWidth = 0;\n
+    d.scrollbarsClipped = false;\n
 \n
     // Used to only resize the line number gutter when necessary (when\n
     // the amount of lines crosses a boundary that makes its width change)\n
     d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;\n
     // See readInput and resetInput\n
     d.prevInput = "";\n
-    // Set to true when a non-horizontal-scrolling widget is added. As\n
-    // an optimization, widget aligning is skipped when d is false.\n
+    // Set to true when a non-horizontal-scrolling line widget is\n
+    // added. As an optimization, line widget aligning is skipped when\n
+    // this is false.\n
     d.alignWidgets = false;\n
-    // Flag that indicates whether we currently expect input to appear\n
-    // (after some event like \'keypress\' or \'input\') and are polling\n
-    // intensively.\n
+    // Flag that indicates whether we expect input to appear real soon\n
+    // now (after some event like \'keypress\' or \'input\') and are\n
+    // polling intensively.\n
     d.pollingFast = false;\n
     // Self-resetting timeout for the poller\n
     d.poll = new Delayed();\n
 \n
     d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n
-    d.measureLineCache = [];\n
-    d.measureLineCachePos = 0;\n
 \n
     // Tracks when resetInput has punted to just putting a short\n
-    // string instead of the (large) selection.\n
+    // string into the textarea instead of the full selection.\n
     d.inaccurateSelection = false;\n
 \n
     // Tracks the maximum line length so that the horizontal scrollbar\n
@@ -242,7 +287,12 @@ window.CodeMirror = (function() {\n
     // Used for measuring wheel scrolling granularity\n
     d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;\n
 \n
-    return d;\n
+    // True when shift is held down.\n
+    d.shift = false;\n
+\n
+    // Used to track whether anything happened since the context menu\n
+    // was opened.\n
+    d.selForContextMenu = null;\n
   }\n
 \n
   // STATE UPDATES\n
@@ -267,11 +317,12 @@ window.CodeMirror = (function() {\n
 \n
   function wrappingChanged(cm) {\n
     if (cm.options.lineWrapping) {\n
-      cm.display.wrapper.className += " CodeMirror-wrap";\n
+      addClass(cm.display.wrapper, "CodeMirror-wrap");\n
       cm.display.sizer.style.minWidth = "";\n
+      cm.display.sizerWidth = null;\n
     } else {\n
-      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");\n
-      computeMaxLength(cm);\n
+      rmClass(cm.display.wrapper, "CodeMirror-wrap");\n
+      findMaxLine(cm);\n
     }\n
     estimateLineHeights(cm);\n
     regChange(cm);\n
@@ -279,16 +330,24 @@ window.CodeMirror = (function() {\n
     setTimeout(function(){updateScrollbars(cm);}, 100);\n
   }\n
 \n
+  // Returns a function that estimates the height of a line, to use as\n
+  // first approximation until the line becomes visible (and is thus\n
+  // properly measurable).\n
   function estimateHeight(cm) {\n
     var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;\n
     var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);\n
     return function(line) {\n
-      if (lineIsHidden(cm.doc, line))\n
-        return 0;\n
-      else if (wrapping)\n
-        return (Math.ceil(line.text.length / perLine) || 1) * th;\n
+      if (lineIsHidden(cm.doc, line)) return 0;\n
+\n
+      var widgetsHeight = 0;\n
+      if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {\n
+        if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;\n
+      }\n
+\n
+      if (wrapping)\n
+        return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;\n
       else\n
-        return th;\n
+        return widgetsHeight + th;\n
     };\n
   }\n
 \n
@@ -299,12 +358,6 @@ window.CodeMirror = (function() {\n
       if (estHeight != line.height) updateLineHeight(line, estHeight);\n
     });\n
   }\n
-\n
-  function keyMapChanged(cm) {\n
-    var map = keyMap[cm.options.keyMap], style = map.style;\n
-    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-keymap-\\S+/g, "") +\n
-      (style ? " cm-keymap-" + style : "");\n
-  }\n
 \n
   function themeChanged(cm) {\n
     cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-s-\\S+/g, "") +\n
@@ -318,6 +371,8 @@ window.CodeMirror = (function() {\n
     setTimeout(function(){alignHorizontally(cm);}, 20);\n
   }\n
 \n
+  // Rebuild the gutter elements, ensure the margin to the left of the\n
+  // code matches their width.\n
   function updateGutters(cm) {\n
     var gutters = cm.display.gutters, specs = cm.options.gutters;\n
     removeChildren(gutters);\n
@@ -330,33 +385,43 @@ window.CodeMirror = (function() {\n
       }\n
     }\n
     gutters.style.display = i ? "" : "none";\n
+    updateGutterSpace(cm);\n
   }\n
 \n
-  function lineLength(doc, line) {\n
+  function updateGutterSpace(cm) {\n
+    var width = cm.display.gutters.offsetWidth;\n
+    cm.display.sizer.style.marginLeft = width + "px";\n
+  }\n
+\n
+  // Compute the character length of a line, taking into account\n
+  // collapsed ranges (see markText) that might hide parts, and join\n
+  // other lines onto it.\n
+  function lineLength(line) {\n
     if (line.height == 0) return 0;\n
     var len = line.text.length, merged, cur = line;\n
     while (merged = collapsedSpanAtStart(cur)) {\n
-      var found = merged.find();\n
-      cur = getLine(doc, found.from.line);\n
+      var found = merged.find(0, true);\n
+      cur = found.from.line;\n
       len += found.from.ch - found.to.ch;\n
     }\n
     cur = line;\n
     while (merged = collapsedSpanAtEnd(cur)) {\n
-      var found = merged.find();\n
+      var found = merged.find(0, true);\n
       len -= cur.text.length - found.from.ch;\n
-      cur = getLine(doc, found.to.line);\n
+      cur = found.to.line;\n
       len += cur.text.length - found.to.ch;\n
     }\n
     return len;\n
   }\n
 \n
-  function computeMaxLength(cm) {\n
+  // Find the longest line in the document.\n
+  function findMaxLine(cm) {\n
     var d = cm.display, doc = cm.doc;\n
     d.maxLine = getLine(doc, doc.first);\n
-    d.maxLineLength = lineLength(doc, d.maxLine);\n
+    d.maxLineLength = lineLength(d.maxLine);\n
     d.maxLineChanged = true;\n
     doc.iter(function(line) {\n
-      var len = lineLength(doc, line);\n
+      var len = lineLength(line);\n
       if (len > d.maxLineLength) {\n
         d.maxLineLength = len;\n
         d.maxLine = line;\n
@@ -378,74 +443,215 @@ window.CodeMirror = (function() {\n
 \n
   // SCROLLBARS\n
 \n
-  // Re-synchronize the fake scrollbars with the actual size of the\n
-  // content. Optionally force a scrollTop.\n
-  function updateScrollbars(cm) {\n
-    var d = cm.display, docHeight = cm.doc.height;\n
-    var totalHeight = docHeight + paddingVert(d);\n
-    d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";\n
-    d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";\n
-    var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);\n
-    var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);\n
-    var needsV = scrollHeight > (d.scroller.clientHeight + 1);\n
-    if (needsV) {\n
-      d.scrollbarV.style.display = "block";\n
-      d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";\n
-      // A bug in IE8 can cause this value to be negative, so guard it.\n
-      d.scrollbarV.firstChild.style.height =\n
-        Math.max(0, scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";\n
-    } else {\n
-      d.scrollbarV.style.display = "";\n
-      d.scrollbarV.firstChild.style.height = "0";\n
-    }\n
-    if (needsH) {\n
-      d.scrollbarH.style.display = "block";\n
-      d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";\n
-      d.scrollbarH.firstChild.style.width =\n
-        (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";\n
-    } else {\n
-      d.scrollbarH.style.display = "";\n
-      d.scrollbarH.firstChild.style.width = "0";\n
+  // Prepare DOM reads needed to update the scrollbars. Done in one\n
+  // shot to minimize update/measure roundtrips.\n
+  function measureForScrollbars(cm) {\n
+    var d = cm.display, gutterW = d.gutters.offsetWidth;\n
+    var docH = Math.round(cm.doc.height + paddingVert(cm.display));\n
+    return {\n
+      clientHeight: d.scroller.clientHeight,\n
+      viewHeight: d.wrapper.clientHeight,\n
+      scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,\n
+      viewWidth: d.wrapper.clientWidth,\n
+      barLeft: cm.options.fixedGutter ? gutterW : 0,\n
+      docHeight: docH,\n
+      scrollHeight: docH + scrollGap(cm) + d.barHeight,\n
+      nativeBarWidth: d.nativeBarWidth,\n
+      gutterWidth: gutterW\n
+    };\n
+  }\n
+\n
+  function NativeScrollbars(place, scroll, cm) {\n
+    this.cm = cm;\n
+    var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");\n
+    var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");\n
+    place(vert); place(horiz);\n
+\n
+    on(vert, "scroll", function() {\n
+      if (vert.clientHeight) scroll(vert.scrollTop, "vertical");\n
+    });\n
+    on(horiz, "scroll", function() {\n
+      if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");\n
+    });\n
+\n
+    this.checkedOverlay = false;\n
+    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).\n
+    if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";\n
+  }\n
+\n
+  NativeScrollbars.prototype = copyObj({\n
+    update: function(measure) {\n
+      var needsH = measure.scrollWidth > measure.clientWidth + 1;\n
+      var needsV = measure.scrollHeight > measure.clientHeight + 1;\n
+      var sWidth = measure.nativeBarWidth;\n
+\n
+      if (needsV) {\n
+        this.vert.style.display = "block";\n
+        this.vert.style.bottom = needsH ? sWidth + "px" : "0";\n
+        var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);\n
+        // A bug in IE8 can cause this value to be negative, so guard it.\n
+        this.vert.firstChild.style.height =\n
+          Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";\n
+      } else {\n
+        this.vert.style.display = "";\n
+        this.vert.firstChild.style.height = "0";\n
+      }\n
+\n
+      if (needsH) {\n
+        this.horiz.style.display = "block";\n
+        this.horiz.style.right = needsV ? sWidth + "px" : "0";\n
+        this.horiz.style.left = measure.barLeft + "px";\n
+        var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);\n
+        this.horiz.firstChild.style.width =\n
+          (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";\n
+      } else {\n
+        this.horiz.style.display = "";\n
+        this.horiz.firstChild.style.width = "0";\n
+      }\n
+\n
+      if (!this.checkedOverlay && measure.clientHeight > 0) {\n
+        if (sWidth == 0) this.overlayHack();\n
+        this.checkedOverlay = true;\n
+      }\n
+\n
+      return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};\n
+    },\n
+    setScrollLeft: function(pos) {\n
+      if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;\n
+    },\n
+    setScrollTop: function(pos) {\n
+      if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;\n
+    },\n
+    overlayHack: function() {\n
+      var w = mac && !mac_geMountainLion ? "12px" : "18px";\n
+      this.horiz.style.minHeight = this.vert.style.minWidth = w;\n
+      var self = this;\n
+      var barMouseDown = function(e) {\n
+        if (e_target(e) != self.vert && e_target(e) != self.horiz)\n
+          operation(self.cm, onMouseDown)(e);\n
+      };\n
+      on(this.vert, "mousedown", barMouseDown);\n
+      on(this.horiz, "mousedown", barMouseDown);\n
+    },\n
+    clear: function() {\n
+      var parent = this.horiz.parentNode;\n
+      parent.removeChild(this.horiz);\n
+      parent.removeChild(this.vert);\n
     }\n
-    if (needsH && needsV) {\n
+  }, NativeScrollbars.prototype);\n
+\n
+  function NullScrollbars() {}\n
+\n
+  NullScrollbars.prototype = copyObj({\n
+    update: function() { return {bottom: 0, right: 0}; },\n
+    setScrollLeft: function() {},\n
+    setScrollTop: function() {},\n
+    clear: function() {}\n
+  }, NullScrollbars.prototype);\n
+\n
+  CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};\n
+\n
+  function initScrollbars(cm) {\n
+    if (cm.display.scrollbars) {\n
+      cm.display.scrollbars.clear();\n
+      if (cm.display.scrollbars.addClass)\n
+        rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);\n
+    }\n
+\n
+    cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {\n
+      cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);\n
+      on(node, "mousedown", function() {\n
+        if (cm.state.focused) setTimeout(bind(focusInput, cm), 0);\n
+      });\n
+      node.setAttribute("not-content", "true");\n
+    }, function(pos, axis) {\n
+      if (axis == "horizontal") setScrollLeft(cm, pos);\n
+      else setScrollTop(cm, pos);\n
+    }, cm);\n
+    if (cm.display.scrollbars.addClass)\n
+      addClass(cm.display.wrapper, cm.display.scrollbars.addClass);\n
+  }\n
+\n
+  function updateScrollbars(cm, measure) {\n
+    if (!measure) measure = measureForScrollbars(cm);\n
+    var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;\n
+    updateScrollbarsInner(cm, measure);\n
+    for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {\n
+      if (startWidth != cm.display.barWidth && cm.options.lineWrapping)\n
+        updateHeightsInViewport(cm);\n
+      updateScrollbarsInner(cm, measureForScrollbars(cm));\n
+      startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;\n
+    }\n
+  }\n
+\n
+  // Re-synchronize the fake scrollbars with the actual size of the\n
+  // content.\n
+  function updateScrollbarsInner(cm, measure) {\n
+    var d = cm.display;\n
+    var sizes = d.scrollbars.update(measure);\n
+\n
+    d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";\n
+    d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";\n
+\n
+    if (sizes.right && sizes.bottom) {\n
       d.scrollbarFiller.style.display = "block";\n
-      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";\n
+      d.scrollbarFiller.style.height = sizes.bottom + "px";\n
+      d.scrollbarFiller.style.width = sizes.right + "px";\n
     } else d.scrollbarFiller.style.display = "";\n
-    if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {\n
+    if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {\n
       d.gutterFiller.style.display = "block";\n
-      d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";\n
-      d.gutterFiller.style.width = d.gutters.offsetWidth + "px";\n
+      d.gutterFiller.style.height = sizes.bottom + "px";\n
+      d.gutterFiller.style.width = measure.gutterWidth + "px";\n
     } else d.gutterFiller.style.display = "";\n
-\n
-    if (mac_geLion && scrollbarWidth(d.measure) === 0) {\n
-      d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";\n
-      d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = "none";\n
-    }\n
   }\n
 \n
-  function visibleLines(display, doc, viewPort) {\n
-    var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;\n
-    if (typeof viewPort == "number") top = viewPort;\n
-    else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}\n
+  // Compute the lines that are visible in a given viewport (defaults\n
+  // the the current scroll position). viewport may contain top,\n
+  // height, and ensure (see op.scrollToPos) properties.\n
+  function visibleLines(display, doc, viewport) {\n
+    var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;\n
     top = Math.floor(top - paddingTop(display));\n
-    var bottom = Math.ceil(top + height);\n
-    return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};\n
+    var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;\n
+\n
+    var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);\n
+    // Ensure is a {from: {line, ch}, to: {line, ch}} object, and\n
+    // forces those lines into the viewport (if possible).\n
+    if (viewport && viewport.ensure) {\n
+      var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;\n
+      if (ensureFrom < from) {\n
+        from = ensureFrom;\n
+        to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);\n
+      } else if (Math.min(ensureTo, doc.lastLine()) >= to) {\n
+        from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);\n
+        to = ensureTo;\n
+      }\n
+    }\n
+    return {from: from, to: Math.max(to, from + 1)};\n
   }\n
 \n
   // LINE NUMBERS\n
 \n
+  // Re-align line numbers and gutter marks to compensate for\n
+  // horizontal scrolling.\n
   function alignHorizontally(cm) {\n
-    var display = cm.display;\n
+    var display = cm.display, view = display.view;\n
     if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;\n
     var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;\n
-    var gutterW = display.gutters.offsetWidth, l = comp + "px";\n
-    for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {\n
-      for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;\n
+    var gutterW = display.gutters.offsetWidth, left = comp + "px";\n
+    for (var i = 0; i < view.length; i++) if (!view[i].hidden) {\n
+      if (cm.options.fixedGutter && view[i].gutter)\n
+        view[i].gutter.style.left = left;\n
+      var align = view[i].alignable;\n
+      if (align) for (var j = 0; j < align.length; j++)\n
+        align[j].style.left = left;\n
     }\n
     if (cm.options.fixedGutter)\n
       display.gutters.style.left = (comp + gutterW) + "px";\n
   }\n
 \n
+  // Used to ensure that the line number gutter is still the right\n
+  // size for the current document size. Returns true when an update\n
+  // is needed.\n
   function maybeUpdateLineNumberWidth(cm) {\n
     if (!cm.options.lineNumbers) return false;\n
     var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;\n
@@ -458,6 +664,7 @@ window.CodeMirror = (function() {\n
       display.lineNumWidth = display.lineNumInnerWidth + padding;\n
       display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;\n
       display.lineGutter.style.width = display.lineNumWidth + "px";\n
+      updateGutterSpace(cm);\n
       return true;\n
     }\n
     return false;\n
@@ -466,197 +673,208 @@ window.CodeMirror = (function() {\n
   function lineNumberFor(options, i) {\n
     return String(options.lineNumberFormatter(i + options.firstLineNumber));\n
   }\n
+\n
+  // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,\n
+  // but using getBoundingClientRect to get a sub-pixel-accurate\n
+  // result.\n
   function compensateForHScroll(display) {\n
-    return getRect(display.scroller).left - getRect(display.sizer).left;\n
+    return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;\n
   }\n
 \n
   // DISPLAY DRAWING\n
 \n
-  function updateDisplay(cm, changes, viewPort, forced) {\n
-    var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;\n
-    var visible = visibleLines(cm.display, cm.doc, viewPort);\n
-    for (var first = true;; first = false) {\n
-      var oldWidth = cm.display.scroller.clientWidth;\n
-      if (!updateDisplayInner(cm, changes, visible, forced)) break;\n
-      updated = true;\n
-      changes = [];\n
-      updateSelection(cm);\n
-      updateScrollbars(cm);\n
-      if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {\n
-        forced = true;\n
-        continue;\n
-      }\n
-      forced = false;\n
+  function DisplayUpdate(cm, viewport, force) {\n
+    var display = cm.display;\n
 \n
-      // Clip forced viewport to actual scrollable area\n
-      if (viewPort)\n
-        viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,\n
-                            typeof viewPort == "number" ? viewPort : viewPort.top);\n
-      visible = visibleLines(cm.display, cm.doc, viewPort);\n
-      if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)\n
-        break;\n
-    }\n
+    this.viewport = viewport;\n
+    // Store some values that we\'ll need later (but don\'t want to force a relayout for)\n
+    this.visible = visibleLines(display, cm.doc, viewport);\n
+    this.editorIsHidden = !display.wrapper.offsetWidth;\n
+    this.wrapperHeight = display.wrapper.clientHeight;\n
+    this.wrapperWidth = display.wrapper.clientWidth;\n
+    this.oldDisplayWidth = displayWidth(cm);\n
+    this.force = force;\n
+    this.dims = getDimensions(cm);\n
+  }\n
 \n
-    if (updated) {\n
-      signalLater(cm, "update", cm);\n
-      if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)\n
-        signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);\n
+  function maybeClipScrollbars(cm) {\n
+    var display = cm.display;\n
+    if (!display.scrollbarsClipped && display.scroller.offsetWidth) {\n
+      display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;\n
+      display.heightForcer.style.height = scrollGap(cm) + "px";\n
+      display.sizer.style.marginBottom = -display.nativeBarWidth + "px";\n
+      display.sizer.style.borderRightWidth = scrollGap(cm) + "px";\n
+      display.scrollbarsClipped = true;\n
     }\n
-    return updated;\n
   }\n
 \n
-  // Uses a set of changes plus the current scroll position to\n
-  // determine which DOM updates have to be made, and makes the\n
-  // updates.\n
-  function updateDisplayInner(cm, changes, visible, forced) {\n
+  // Does the actual updating of the line display. Bails out\n
+  // (returning false) when there is nothing to be done and forced is\n
+  // false.\n
+  function updateDisplayIfNeeded(cm, update) {\n
     var display = cm.display, doc = cm.doc;\n
-    if (!display.wrapper.offsetWidth) {\n
-      display.showingFrom = display.showingTo = doc.first;\n
-      display.viewOffset = 0;\n
-      return;\n
+\n
+    if (update.editorIsHidden) {\n
+      resetView(cm);\n
+      return false;\n
     }\n
 \n
     // Bail out if the visible area is already rendered and nothing changed.\n
-    if (!forced && changes.length == 0 &&\n
-        visible.from > display.showingFrom && visible.to < display.showingTo)\n
-      return;\n
-\n
-    if (maybeUpdateLineNumberWidth(cm))\n
-      changes = [{from: doc.first, to: doc.first + doc.size}];\n
-    var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";\n
-    display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";\n
+    if (!update.force &&\n
+        update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&\n
+        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&\n
+        display.renderedView == display.view && countDirtyView(cm) == 0)\n
+      return false;\n
 \n
-    // Used to determine which lines need their line numbers updated\n
-    var positionsChangedFrom = Infinity;\n
-    if (cm.options.lineNumbers)\n
-      for (var i = 0; i < changes.length; ++i)\n
-        if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }\n
+    if (maybeUpdateLineNumberWidth(cm)) {\n
+      resetView(cm);\n
+      update.dims = getDimensions(cm);\n
+    }\n
 \n
+    // Compute a suitable new viewport (from & to)\n
     var end = doc.first + doc.size;\n
-    var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);\n
-    var to = Math.min(end, visible.to + cm.options.viewportMargin);\n
-    if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);\n
-    if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);\n
+    var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);\n
+    var to = Math.min(end, update.visible.to + cm.options.viewportMargin);\n
+    if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);\n
+    if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);\n
     if (sawCollapsedSpans) {\n
-      from = lineNo(visualLine(doc, getLine(doc, from)));\n
-      while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;\n
-    }\n
-\n
-    // Create a range of theoretically intact lines, and punch holes\n
-    // in that using the change info.\n
-    var intact = [{from: Math.max(display.showingFrom, doc.first),\n
-                   to: Math.min(display.showingTo, end)}];\n
-    if (intact[0].from >= intact[0].to) intact = [];\n
-    else intact = computeIntact(intact, changes);\n
-    // When merged lines are present, we might have to reduce the\n
-    // intact ranges because changes in continued fragments of the\n
-    // intact lines do require the lines to be redrawn.\n
-    if (sawCollapsedSpans)\n
-      for (var i = 0; i < intact.length; ++i) {\n
-        var range = intact[i], merged;\n
-        while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {\n
-          var newTo = merged.find().from.line;\n
-          if (newTo > range.from) range.to = newTo;\n
-          else { intact.splice(i--, 1); break; }\n
-        }\n
-      }\n
-\n
-    // Clip off the parts that won\'t be visible\n
-    var intactLines = 0;\n
-    for (var i = 0; i < intact.length; ++i) {\n
-      var range = intact[i];\n
-      if (range.from < from) range.from = from;\n
-      if (range.to > to) range.to = to;\n
-      if (range.from >= range.to) intact.splice(i--, 1);\n
-      else intactLines += range.to - range.from;\n
+      from = visualLineNo(cm.doc, from);\n
+      to = visualLineEndNo(cm.doc, to);\n
     }\n
-    if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {\n
-      updateViewOffset(cm);\n
-      return;\n
-    }\n
-    intact.sort(function(a, b) {return a.from - b.from;});\n
 \n
-    // Avoid crashing on IE\'s "unspecified error" when in iframes\n
-    try {\n
-      var focused = document.activeElement;\n
-    } catch(e) {}\n
-    if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";\n
-    patchDisplay(cm, from, to, intact, positionsChangedFrom);\n
-    display.lineDiv.style.display = "";\n
-    if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();\n
-\n
-    var different = from != display.showingFrom || to != display.showingTo ||\n
-      display.lastSizeC != display.wrapper.clientHeight;\n
-    // This is just a bogus formula that detects when the editor is\n
-    // resized or the font size changes.\n
+    var different = from != display.viewFrom || to != display.viewTo ||\n
+      display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;\n
+    adjustView(cm, from, to);\n
+\n
+    display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));\n
+    // Position the mover div to align with the current scroll position\n
+    cm.display.mover.style.top = display.viewOffset + "px";\n
+\n
+    var toUpdate = countDirtyView(cm);\n
+    if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&\n
+        (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))\n
+      return false;\n
+\n
+    // For big changes, we hide the enclosing element during the\n
+    // update, since that speeds up the operations on most browsers.\n
+    var focused = activeElt();\n
+    if (toUpdate > 4) display.lineDiv.style.display = "none";\n
+    patchDisplay(cm, display.updateLineNumbers, update.dims);\n
+    if (toUpdate > 4) display.lineDiv.style.display = "";\n
+    display.renderedView = display.view;\n
+    // There might have been a widget with a focused element that got\n
+    // hidden or updated, if so re-focus it.\n
+    if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();\n
+\n
+    // Prevent selection and cursors from interfering with the scroll\n
+    // width and height.\n
+    removeChildren(display.cursorDiv);\n
+    removeChildren(display.selectionDiv);\n
+    display.gutters.style.height = 0;\n
+\n
     if (different) {\n
-      display.lastSizeC = display.wrapper.clientHeight;\n
+      display.lastWrapHeight = update.wrapperHeight;\n
+      display.lastWrapWidth = update.wrapperWidth;\n
       startWorker(cm, 400);\n
     }\n
-    display.showingFrom = from; display.showingTo = to;\n
 \n
-    display.gutters.style.height = "";\n
-    updateHeightsInViewport(cm);\n
-    updateViewOffset(cm);\n
+    display.updateLineNumbers = null;\n
 \n
     return true;\n
   }\n
 \n
+  function postUpdateDisplay(cm, update) {\n
+    var force = update.force, viewport = update.viewport;\n
+    for (var first = true;; first = false) {\n
+      if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {\n
+        force = true;\n
+      } else {\n
+        force = false;\n
+        // Clip forced viewport to actual scrollable area.\n
+        if (viewport && viewport.top != null)\n
+          viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};\n
+        // Updated line heights might result in the drawn area not\n
+        // actually covering the viewport. Keep looping until it does.\n
+        update.visible = visibleLines(cm.display, cm.doc, viewport);\n
+        if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)\n
+          break;\n
+      }\n
+      if (!updateDisplayIfNeeded(cm, update)) break;\n
+      updateHeightsInViewport(cm);\n
+      var barMeasure = measureForScrollbars(cm);\n
+      updateSelection(cm);\n
+      setDocumentHeight(cm, barMeasure);\n
+      updateScrollbars(cm, barMeasure);\n
+    }\n
+\n
+    signalLater(cm, "update", cm);\n
+    if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {\n
+      signalLater(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);\n
+      cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;\n
+    }\n
+  }\n
+\n
+  function updateDisplaySimple(cm, viewport) {\n
+    var update = new DisplayUpdate(cm, viewport);\n
+    if (updateDisplayIfNeeded(cm, update)) {\n
+      updateHeightsInViewport(cm);\n
+      postUpdateDisplay(cm, update);\n
+      var barMeasure = measureForScrollbars(cm);\n
+      updateSelection(cm);\n
+      setDocumentHeight(cm, barMeasure);\n
+      updateScrollbars(cm, barMeasure);\n
+    }\n
+  }\n
+\n
+  function setDocumentHeight(cm, measure) {\n
+    cm.display.sizer.style.minHeight = measure.docHeight + "px";\n
+    var total = measure.docHeight + cm.display.barHeight;\n
+    cm.display.heightForcer.style.top = total + "px";\n
+    cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";\n
+  }\n
+\n
+  // Read the actual heights of the rendered lines, and update their\n
+  // stored heights to match.\n
   function updateHeightsInViewport(cm) {\n
     var display = cm.display;\n
     var prevBottom = display.lineDiv.offsetTop;\n
-    for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {\n
-      if (ie_lt8) {\n
-        var bot = node.offsetTop + node.offsetHeight;\n
+    for (var i = 0; i < display.view.length; i++) {\n
+      var cur = display.view[i], height;\n
+      if (cur.hidden) continue;\n
+      if (ie && ie_version < 8) {\n
+        var bot = cur.node.offsetTop + cur.node.offsetHeight;\n
         height = bot - prevBottom;\n
         prevBottom = bot;\n
       } else {\n
-        var box = getRect(node);\n
+        var box = cur.node.getBoundingClientRect();\n
         height = box.bottom - box.top;\n
       }\n
-      var diff = node.lineObj.height - height;\n
+      var diff = cur.line.height - height;\n
       if (height < 2) height = textHeight(display);\n
       if (diff > .001 || diff < -.001) {\n
-        updateLineHeight(node.lineObj, height);\n
-        var widgets = node.lineObj.widgets;\n
-        if (widgets) for (var i = 0; i < widgets.length; ++i)\n
-          widgets[i].height = widgets[i].node.offsetHeight;\n
+        updateLineHeight(cur.line, height);\n
+        updateWidgetHeight(cur.line);\n
+        if (cur.rest) for (var j = 0; j < cur.rest.length; j++)\n
+          updateWidgetHeight(cur.rest[j]);\n
       }\n
     }\n
   }\n
 \n
-  function updateViewOffset(cm) {\n
-    var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));\n
-    // Position the mover div to align with the current virtual scroll position\n
-    cm.display.mover.style.top = off + "px";\n
-  }\n
-\n
-  function computeIntact(intact, changes) {\n
-    for (var i = 0, l = changes.length || 0; i < l; ++i) {\n
-      var change = changes[i], intact2 = [], diff = change.diff || 0;\n
-      for (var j = 0, l2 = intact.length; j < l2; ++j) {\n
-        var range = intact[j];\n
-        if (change.to <= range.from && change.diff) {\n
-          intact2.push({from: range.from + diff, to: range.to + diff});\n
-        } else if (change.to <= range.from || change.from >= range.to) {\n
-          intact2.push(range);\n
-        } else {\n
-          if (change.from > range.from)\n
-            intact2.push({from: range.from, to: change.from});\n
-          if (change.to < range.to)\n
-            intact2.push({from: change.to + diff, to: range.to + diff});\n
-        }\n
-      }\n
-      intact = intact2;\n
-    }\n
-    return intact;\n
+  // Read and store the height of line widgets associated with the\n
+  // given line.\n
+  function updateWidgetHeight(line) {\n
+    if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)\n
+      line.widgets[i].height = line.widgets[i].node.offsetHeight;\n
   }\n
 \n
+  // Do a bulk-read of the DOM positions and sizes needed to draw the\n
+  // view, so that we don\'t interleave reading and writing to the DOM.\n
   function getDimensions(cm) {\n
     var d = cm.display, left = {}, width = {};\n
+    var gutterLeft = d.gutters.clientLeft;\n
     for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {\n
-      left[cm.options.gutters[i]] = n.offsetLeft;\n
-      width[cm.options.gutters[i]] = n.offsetWidth;\n
+      left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;\n
+      width[cm.options.gutters[i]] = n.clientWidth;\n
     }\n
     return {fixedPos: compensateForHScroll(d),\n
             gutterTotalWidth: d.gutters.offsetWidth,\n
@@ -665,154 +883,210 @@ window.CodeMirror = (function() {\n
             wrapperWidth: d.wrapper.clientWidth};\n
   }\n
 \n
-  function patchDisplay(cm, from, to, intact, updateNumbersFrom) {\n
-    var dims = getDimensions(cm);\n
+  // Sync the actual display DOM structure with display.view, removing\n
+  // nodes for lines that are no longer in view, and creating the ones\n
+  // that are not there yet, and updating the ones that are out of\n
+  // date.\n
+  function patchDisplay(cm, updateNumbersFrom, dims) {\n
     var display = cm.display, lineNumbers = cm.options.lineNumbers;\n
-    if (!intact.length && (!webkit || !cm.display.currentWheelTarget))\n
-      removeChildren(display.lineDiv);\n
     var container = display.lineDiv, cur = container.firstChild;\n
 \n
     function rm(node) {\n
       var next = node.nextSibling;\n
-      if (webkit && mac && cm.display.currentWheelTarget == node) {\n
+      // Works around a throw-scroll bug in OS X Webkit\n
+      if (webkit && mac && cm.display.currentWheelTarget == node)\n
         node.style.display = "none";\n
-        node.lineObj = null;\n
-      } else {\n
+      else\n
         node.parentNode.removeChild(node);\n
-      }\n
       return next;\n
     }\n
 \n
-    var nextIntact = intact.shift(), lineN = from;\n
-    cm.doc.iter(from, to, function(line) {\n
-      if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();\n
-      if (lineIsHidden(cm.doc, line)) {\n
-        if (line.height != 0) updateLineHeight(line, 0);\n
-        if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {\n
-          var w = line.widgets[i];\n
-          if (w.showIfHidden) {\n
-            var prev = cur.previousSibling;\n
-            if (/pre/i.test(prev.nodeName)) {\n
-              var wrap = elt("div", null, null, "position: relative");\n
-              prev.parentNode.replaceChild(wrap, prev);\n
-              wrap.appendChild(prev);\n
-              prev = wrap;\n
-            }\n
-            var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));\n
-            if (!w.handleMouseEvents) wnode.ignoreEvents = true;\n
-            positionLineWidget(w, wnode, prev, dims);\n
-          }\n
+    var view = display.view, lineN = display.viewFrom;\n
+    // Loop over the elements in the view, syncing cur (the DOM nodes\n
+    // in display.lineDiv) with the view as we go.\n
+    for (var i = 0; i < view.length; i++) {\n
+      var lineView = view[i];\n
+      if (lineView.hidden) {\n
+      } else if (!lineView.node) { // Not drawn yet\n
+        var node = buildLineElement(cm, lineView, lineN, dims);\n
+        container.insertBefore(node, cur);\n
+      } else { // Already drawn\n
+        while (cur != lineView.node) cur = rm(cur);\n
+        var updateNumber = lineNumbers && updateNumbersFrom != null &&\n
+          updateNumbersFrom <= lineN && lineView.lineNumber;\n
+        if (lineView.changes) {\n
+          if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;\n
+          updateLineForChanges(cm, lineView, lineN, dims);\n
         }\n
-      } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {\n
-        // This line is intact. Skip to the actual node. Update its\n
-        // line number if needed.\n
-        while (cur.lineObj != line) cur = rm(cur);\n
-        if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)\n
-          setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));\n
-        cur = cur.nextSibling;\n
-      } else {\n
-        // For lines with widgets, make an attempt to find and reuse\n
-        // the existing element, so that widgets aren\'t needlessly\n
-        // removed and re-inserted into the dom\n
-        if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)\n
-          if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }\n
-        // This line needs to be generated.\n
-        var lineNode = buildLineElement(cm, line, lineN, dims, reuse);\n
-        if (lineNode != reuse) {\n
-          container.insertBefore(lineNode, cur);\n
-        } else {\n
-          while (cur != reuse) cur = rm(cur);\n
-          cur = cur.nextSibling;\n
+        if (updateNumber) {\n
+          removeChildren(lineView.lineNumber);\n
+          lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));\n
         }\n
-\n
-        lineNode.lineObj = line;\n
+        cur = lineView.node.nextSibling;\n
       }\n
-      ++lineN;\n
-    });\n
+      lineN += lineView.size;\n
+    }\n
     while (cur) cur = rm(cur);\n
   }\n
 \n
-  function buildLineElement(cm, line, lineNo, dims, reuse) {\n
-    var built = buildLineContent(cm, line), lineElement = built.pre;\n
-    var markers = line.gutterMarkers, display = cm.display, wrap;\n
-\n
-    var bgClass = built.bgClass ? built.bgClass + " " + (line.bgClass || "") : line.bgClass;\n
-    if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets)\n
-      return lineElement;\n
+  // When an aspect of a line changes, a string is added to\n
+  // lineView.changes. This updates the relevant part of the line\'s\n
+  // DOM structure.\n
+  function updateLineForChanges(cm, lineView, lineN, dims) {\n
+    for (var j = 0; j < lineView.changes.length; j++) {\n
+      var type = lineView.changes[j];\n
+      if (type == "text") updateLineText(cm, lineView);\n
+      else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);\n
+      else if (type == "class") updateLineClasses(lineView);\n
+      else if (type == "widget") updateLineWidgets(lineView, dims);\n
+    }\n
+    lineView.changes = null;\n
+  }\n
 \n
-    // Lines with gutter elements, widgets or a background class need\n
-    // to be wrapped again, and have the extra elements added to the\n
-    // wrapper div\n
+  // Lines with gutter elements, widgets or a background class need to\n
+  // be wrapped, and have the extra elements added to the wrapper div\n
+  function ensureLineWrapped(lineView) {\n
+    if (lineView.node == lineView.text) {\n
+      lineView.node = elt("div", null, null, "position: relative");\n
+      if (lineView.text.parentNode)\n
+        lineView.text.parentNode.replaceChild(lineView.node, lineView.text);\n
+      lineView.node.appendChild(lineView.text);\n
+      if (ie && ie_version < 8) lineView.node.style.zIndex = 2;\n
+    }\n
+    return lineView.node;\n
+  }\n
 \n
-    if (reuse) {\n
-      reuse.alignable = null;\n
-      var isOk = true, widgetsSeen = 0, insertBefore = null;\n
-      for (var n = reuse.firstChild, next; n; n = next) {\n
-        next = n.nextSibling;\n
-        if (!/\\bCodeMirror-linewidget\\b/.test(n.className)) {\n
-          reuse.removeChild(n);\n
-        } else {\n
-          for (var i = 0; i < line.widgets.length; ++i) {\n
-            var widget = line.widgets[i];\n
-            if (widget.node == n.firstChild) {\n
-              if (!widget.above && !insertBefore) insertBefore = n;\n
-              positionLineWidget(widget, n, reuse, dims);\n
-              ++widgetsSeen;\n
-              break;\n
-            }\n
-          }\n
-          if (i == line.widgets.length) { isOk = false; break; }\n
-        }\n
-      }\n
-      reuse.insertBefore(lineElement, insertBefore);\n
-      if (isOk && widgetsSeen == line.widgets.length) {\n
-        wrap = reuse;\n
-        reuse.className = line.wrapClass || "";\n
-      }\n
+  function updateLineBackground(lineView) {\n
+    var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;\n
+    if (cls) cls += " CodeMirror-linebackground";\n
+    if (lineView.background) {\n
+      if (cls) lineView.background.className = cls;\n
+      else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }\n
+    } else if (cls) {\n
+      var wrap = ensureLineWrapped(lineView);\n
+      lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);\n
     }\n
-    if (!wrap) {\n
-      wrap = elt("div", null, line.wrapClass, "position: relative");\n
-      wrap.appendChild(lineElement);\n
+  }\n
+\n
+  // Wrapper around buildLineContent which will reuse the structure\n
+  // in display.externalMeasured when possible.\n
+  function getLineContent(cm, lineView) {\n
+    var ext = cm.display.externalMeasured;\n
+    if (ext && ext.line == lineView.line) {\n
+      cm.display.externalMeasured = null;\n
+      lineView.measure = ext.measure;\n
+      return ext.built;\n
     }\n
-    // Kludge to make sure the styled element lies behind the selection (by z-index)\n
-    if (bgClass)\n
-      wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild);\n
+    return buildLineContent(cm, lineView);\n
+  }\n
+\n
+  // Redraw the line\'s text. Interacts with the background and text\n
+  // classes because the mode may output tokens that influence these\n
+  // classes.\n
+  function updateLineText(cm, lineView) {\n
+    var cls = lineView.text.className;\n
+    var built = getLineContent(cm, lineView);\n
+    if (lineView.text == lineView.node) lineView.node = built.pre;\n
+    lineView.text.parentNode.replaceChild(built.pre, lineView.text);\n
+    lineView.text = built.pre;\n
+    if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {\n
+      lineView.bgClass = built.bgClass;\n
+      lineView.textClass = built.textClass;\n
+      updateLineClasses(lineView);\n
+    } else if (cls) {\n
+      lineView.text.className = cls;\n
+    }\n
+  }\n
+\n
+  function updateLineClasses(lineView) {\n
+    updateLineBackground(lineView);\n
+    if (lineView.line.wrapClass)\n
+      ensureLineWrapped(lineView).className = lineView.line.wrapClass;\n
+    else if (lineView.node != lineView.text)\n
+      lineView.node.className = "";\n
+    var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;\n
+    lineView.text.className = textClass || "";\n
+  }\n
+\n
+  function updateLineGutter(cm, lineView, lineN, dims) {\n
+    if (lineView.gutter) {\n
+      lineView.node.removeChild(lineView.gutter);\n
+      lineView.gutter = null;\n
+    }\n
+    var markers = lineView.line.gutterMarkers;\n
     if (cm.options.lineNumbers || markers) {\n
-      var gutterWrap = wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "position: absolute; left: " +\n
-                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),\n
-                                         lineElement);\n
-      if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);\n
+      var wrap = ensureLineWrapped(lineView);\n
+      var gutterWrap = lineView.gutter =\n
+        wrap.insertBefore(elt("div", null, "CodeMirror-gutter-wrapper", "left: " +\n
+                              (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +\n
+                              "px; width: " + dims.gutterTotalWidth + "px"),\n
+                          lineView.text);\n
+      if (lineView.line.gutterClass)\n
+        gutterWrap.className += " " + lineView.line.gutterClass;\n
       if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))\n
-        wrap.lineNumber = gutterWrap.appendChild(\n
-          elt("div", lineNumberFor(cm.options, lineNo),\n
+        lineView.lineNumber = gutterWrap.appendChild(\n
+          elt("div", lineNumberFor(cm.options, lineN),\n
               "CodeMirror-linenumber CodeMirror-gutter-elt",\n
               "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "\n
-              + display.lineNumInnerWidth + "px"));\n
-      if (markers)\n
-        for (var k = 0; k < cm.options.gutters.length; ++k) {\n
-          var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];\n
-          if (found)\n
-            gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +\n
-                                       dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));\n
-        }\n
+              + cm.display.lineNumInnerWidth + "px"));\n
+      if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {\n
+        var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];\n
+        if (found)\n
+          gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +\n
+                                     dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));\n
+      }\n
     }\n
-    if (ie_lt8) wrap.style.zIndex = 2;\n
-    if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {\n
+  }\n
+\n
+  function updateLineWidgets(lineView, dims) {\n
+    if (lineView.alignable) lineView.alignable = null;\n
+    for (var node = lineView.node.firstChild, next; node; node = next) {\n
+      var next = node.nextSibling;\n
+      if (node.className == "CodeMirror-linewidget")\n
+        lineView.node.removeChild(node);\n
+    }\n
+    insertLineWidgets(lineView, dims);\n
+  }\n
+\n
+  // Build a line\'s DOM representation from scratch\n
+  function buildLineElement(cm, lineView, lineN, dims) {\n
+    var built = getLineContent(cm, lineView);\n
+    lineView.text = lineView.node = built.pre;\n
+    if (built.bgClass) lineView.bgClass = built.bgClass;\n
+    if (built.textClass) lineView.textClass = built.textClass;\n
+\n
+    updateLineClasses(lineView);\n
+    updateLineGutter(cm, lineView, lineN, dims);\n
+    insertLineWidgets(lineView, dims);\n
+    return lineView.node;\n
+  }\n
+\n
+  // A lineView may contain multiple logical lines (when merged by\n
+  // collapsed spans). The widgets for all of them need to be drawn.\n
+  function insertLineWidgets(lineView, dims) {\n
+    insertLineWidgetsFor(lineView.line, lineView, dims, true);\n
+    if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)\n
+      insertLineWidgetsFor(lineView.rest[i], lineView, dims, false);\n
+  }\n
+\n
+  function insertLineWidgetsFor(line, lineView, dims, allowAbove) {\n
+    if (!line.widgets) return;\n
+    var wrap = ensureLineWrapped(lineView);\n
+    for (var i = 0, ws = line.widgets; i < ws.length; ++i) {\n
       var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");\n
-      if (!widget.handleMouseEvents) node.ignoreEvents = true;\n
-      positionLineWidget(widget, node, wrap, dims);\n
-      if (widget.above)\n
-        wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);\n
+      if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");\n
+      positionLineWidget(widget, node, lineView, dims);\n
+      if (allowAbove && widget.above)\n
+        wrap.insertBefore(node, lineView.gutter || lineView.text);\n
       else\n
         wrap.appendChild(node);\n
       signalLater(widget, "redraw");\n
     }\n
-    return wrap;\n
   }\n
 \n
-  function positionLineWidget(widget, node, wrap, dims) {\n
+  function positionLineWidget(widget, node, lineView, dims) {\n
     if (widget.noHScroll) {\n
-      (wrap.alignable || (wrap.alignable = [])).push(node);\n
+      (lineView.alignable || (lineView.alignable = [])).push(node);\n
       var width = dims.wrapperWidth;\n
       node.style.left = dims.fixedPos + "px";\n
       if (!widget.coverGutter) {\n
@@ -827,56 +1101,381 @@ window.CodeMirror = (function() {\n
       if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";\n
     }\n
   }\n
+\n
+  // POSITION OBJECT\n
+\n
+  // A Pos instance represents a position within the text.\n
+  var Pos = CodeMirror.Pos = function(line, ch) {\n
+    if (!(this instanceof Pos)) return new Pos(line, ch);\n
+    this.line = line; this.ch = ch;\n
+  };\n
+\n
+  // Compare two positions, return 0 if they are the same, a negative\n
+  // number when a is less, and a positive number otherwise.\n
+  var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };\n
+\n
+  function copyPos(x) {return Pos(x.line, x.ch);}\n
+  function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }\n
+  function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }\n
 \n
   // SELECTION / CURSOR\n
 \n
-  function updateSelection(cm) {\n
-    var display = cm.display;\n
-    var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);\n
-    if (collapsed || cm.options.showCursorWhenSelecting)\n
-      updateSelectionCursor(cm);\n
-    else\n
-      display.cursor.style.display = display.otherCursor.style.display = "none";\n
-    if (!collapsed)\n
-      updateSelectionRange(cm);\n
-    else\n
-      display.selectionDiv.style.display = "none";\n
+  // Selection objects are immutable. A new one is created every time\n
+  // the selection changes. A selection is one or more non-overlapping\n
+  // (and non-touching) ranges, sorted, and an integer that indicates\n
+  // which one is the primary selection (the one that\'s scrolled into\n
+  // view, that getCursor returns, etc).\n
+  function Selection(ranges, primIndex) {\n
+    this.ranges = ranges;\n
+    this.primIndex = primIndex;\n
+  }\n
+\n
+  Selection.prototype = {\n
+    primary: function() { return this.ranges[this.primIndex]; },\n
+    equals: function(other) {\n
+      if (other == this) return true;\n
+      if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;\n
+      for (var i = 0; i < this.ranges.length; i++) {\n
+        var here = this.ranges[i], there = other.ranges[i];\n
+        if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;\n
+      }\n
+      return true;\n
+    },\n
+    deepCopy: function() {\n
+      for (var out = [], i = 0; i < this.ranges.length; i++)\n
+        out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));\n
+      return new Selection(out, this.primIndex);\n
+    },\n
+    somethingSelected: function() {\n
+      for (var i = 0; i < this.ranges.length; i++)\n
+        if (!this.ranges[i].empty()) return true;\n
+      return false;\n
+    },\n
+    contains: function(pos, end) {\n
+      if (!end) end = pos;\n
+      for (var i = 0; i < this.ranges.length; i++) {\n
+        var range = this.ranges[i];\n
+        if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)\n
+          return i;\n
+      }\n
+      return -1;\n
+    }\n
+  };\n
+\n
+  function Range(anchor, head) {\n
+    this.anchor = anchor; this.head = head;\n
+  }\n
+\n
+  Range.prototype = {\n
+    from: function() { return minPos(this.anchor, this.head); },\n
+    to: function() { return maxPos(this.anchor, this.head); },\n
+    empty: function() {\n
+      return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;\n
+    }\n
+  };\n
+\n
+  // Take an unsorted, potentially overlapping set of ranges, and\n
+  // build a selection out of it. \'Consumes\' ranges array (modifying\n
+  // it).\n
+  function normalizeSelection(ranges, primIndex) {\n
+    var prim = ranges[primIndex];\n
+    ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });\n
+    primIndex = indexOf(ranges, prim);\n
+    for (var i = 1; i < ranges.length; i++) {\n
+      var cur = ranges[i], prev = ranges[i - 1];\n
+      if (cmp(prev.to(), cur.from()) >= 0) {\n
+        var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());\n
+        var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;\n
+        if (i <= primIndex) --primIndex;\n
+        ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));\n
+      }\n
+    }\n
+    return new Selection(ranges, primIndex);\n
+  }\n
+\n
+  function simpleSelection(anchor, head) {\n
+    return new Selection([new Range(anchor, head || anchor)], 0);\n
+  }\n
+\n
+  // Most of the external API clips given positions to make sure they\n
+  // actually exist within the document.\n
+  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}\n
+  function clipPos(doc, pos) {\n
+    if (pos.line < doc.first) return Pos(doc.first, 0);\n
+    var last = doc.first + doc.size - 1;\n
+    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);\n
+    return clipToLen(pos, getLine(doc, pos.line).text.length);\n
+  }\n
+  function clipToLen(pos, linelen) {\n
+    var ch = pos.ch;\n
+    if (ch == null || ch > linelen) return Pos(pos.line, linelen);\n
+    else if (ch < 0) return Pos(pos.line, 0);\n
+    else return pos;\n
+  }\n
+  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}\n
+  function clipPosArray(doc, array) {\n
+    for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);\n
+    return out;\n
+  }\n
+\n
+  // SELECTION UPDATES\n
+\n
+  // The \'scroll\' parameter given to many of these indicated whether\n
+  // the new cursor position should be scrolled into view after\n
+  // modifying the selection.\n
+\n
+  // If shift is held or the extend flag is set, extends a range to\n
+  // include a given position (and optionally a second position).\n
+  // Otherwise, simply returns the range between the given positions.\n
+  // Used for cursor motion and such.\n
+  function extendRange(doc, range, head, other) {\n
+    if (doc.cm && doc.cm.display.shift || doc.extend) {\n
+      var anchor = range.anchor;\n
+      if (other) {\n
+        var posBefore = cmp(head, anchor) < 0;\n
+        if (posBefore != (cmp(other, anchor) < 0)) {\n
+          anchor = head;\n
+          head = other;\n
+        } else if (posBefore != (cmp(head, other) < 0)) {\n
+          head = other;\n
+        }\n
+      }\n
+      return new Range(anchor, head);\n
+    } else {\n
+      return new Range(other || head, head);\n
+    }\n
+  }\n
+\n
+  // Extend the primary selection range, discard the rest.\n
+  function extendSelection(doc, head, other, options) {\n
+    setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);\n
+  }\n
+\n
+  // Extend all selections (pos is an array of selections with length\n
+  // equal the number of selections)\n
+  function extendSelections(doc, heads, options) {\n
+    for (var out = [], i = 0; i < doc.sel.ranges.length; i++)\n
+      out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);\n
+    var newSel = normalizeSelection(out, doc.sel.primIndex);\n
+    setSelection(doc, newSel, options);\n
+  }\n
+\n
+  // Updates a single range in the selection.\n
+  function replaceOneSelection(doc, i, range, options) {\n
+    var ranges = doc.sel.ranges.slice(0);\n
+    ranges[i] = range;\n
+    setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);\n
+  }\n
+\n
+  // Reset the selection to a single range.\n
+  function setSimpleSelection(doc, anchor, head, options) {\n
+    setSelection(doc, simpleSelection(anchor, head), options);\n
+  }\n
+\n
+  // Give beforeSelectionChange handlers a change to influence a\n
+  // selection update.\n
+  function filterSelectionChange(doc, sel) {\n
+    var obj = {\n
+      ranges: sel.ranges,\n
+      update: function(ranges) {\n
+        this.ranges = [];\n
+        for (var i = 0; i < ranges.length; i++)\n
+          this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),\n
+                                     clipPos(doc, ranges[i].head));\n
+      }\n
+    };\n
+    signal(doc, "beforeSelectionChange", doc, obj);\n
+    if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);\n
+    if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);\n
+    else return sel;\n
+  }\n
+\n
+  function setSelectionReplaceHistory(doc, sel, options) {\n
+    var done = doc.history.done, last = lst(done);\n
+    if (last && last.ranges) {\n
+      done[done.length - 1] = sel;\n
+      setSelectionNoUndo(doc, sel, options);\n
+    } else {\n
+      setSelection(doc, sel, options);\n
+    }\n
+  }\n
+\n
+  // Set a new selection.\n
+  function setSelection(doc, sel, options) {\n
+    setSelectionNoUndo(doc, sel, options);\n
+    addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);\n
+  }\n
+\n
+  function setSelectionNoUndo(doc, sel, options) {\n
+    if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))\n
+      sel = filterSelectionChange(doc, sel);\n
+\n
+    var bias = options && options.bias ||\n
+      (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);\n
+    setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));\n
+\n
+    if (!(options && options.scroll === false) && doc.cm)\n
+      ensureCursorVisible(doc.cm);\n
+  }\n
+\n
+  function setSelectionInner(doc, sel) {\n
+    if (sel.equals(doc.sel)) return;\n
+\n
+    doc.sel = sel;\n
+\n
+    if (doc.cm) {\n
+      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;\n
+      signalCursorActivity(doc.cm);\n
+    }\n
+    signalLater(doc, "cursorActivity", doc);\n
+  }\n
+\n
+  // Verify that the selection does not partially select any atomic\n
+  // marked ranges.\n
+  function reCheckSelection(doc) {\n
+    setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);\n
+  }\n
+\n
+  // Return a selection that does not partially select any atomic\n
+  // ranges.\n
+  function skipAtomicInSelection(doc, sel, bias, mayClear) {\n
+    var out;\n
+    for (var i = 0; i < sel.ranges.length; i++) {\n
+      var range = sel.ranges[i];\n
+      var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);\n
+      var newHead = skipAtomic(doc, range.head, bias, mayClear);\n
+      if (out || newAnchor != range.anchor || newHead != range.head) {\n
+        if (!out) out = sel.ranges.slice(0, i);\n
+        out[i] = new Range(newAnchor, newHead);\n
+      }\n
+    }\n
+    return out ? normalizeSelection(out, sel.primIndex) : sel;\n
+  }\n
+\n
+  // Ensure a given position is not inside an atomic range.\n
+  function skipAtomic(doc, pos, bias, mayClear) {\n
+    var flipped = false, curPos = pos;\n
+    var dir = bias || 1;\n
+    doc.cantEdit = false;\n
+    search: for (;;) {\n
+      var line = getLine(doc, curPos.line);\n
+      if (line.markedSpans) {\n
+        for (var i = 0; i < line.markedSpans.length; ++i) {\n
+          var sp = line.markedSpans[i], m = sp.marker;\n
+          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&\n
+              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {\n
+            if (mayClear) {\n
+              signal(m, "beforeCursorEnter");\n
+              if (m.explicitlyCleared) {\n
+                if (!line.markedSpans) break;\n
+                else {--i; continue;}\n
+              }\n
+            }\n
+            if (!m.atomic) continue;\n
+            var newPos = m.find(dir < 0 ? -1 : 1);\n
+            if (cmp(newPos, curPos) == 0) {\n
+              newPos.ch += dir;\n
+              if (newPos.ch < 0) {\n
+                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));\n
+                else newPos = null;\n
+              } else if (newPos.ch > line.text.length) {\n
+                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);\n
+                else newPos = null;\n
+              }\n
+              if (!newPos) {\n
+                if (flipped) {\n
+                  // Driven in a corner -- no valid cursor position found at all\n
+                  // -- try again *with* clearing, if we didn\'t already\n
+                  if (!mayClear) return skipAtomic(doc, pos, bias, true);\n
+                  // Otherwise, turn off editing until further notice, and return the start of the doc\n
+                  doc.cantEdit = true;\n
+                  return Pos(doc.first, 0);\n
+                }\n
+                flipped = true; newPos = pos; dir = -dir;\n
+              }\n
+            }\n
+            curPos = newPos;\n
+            continue search;\n
+          }\n
+        }\n
+      }\n
+      return curPos;\n
+    }\n
+  }\n
+\n
+  // SELECTION DRAWING\n
+\n
+  // Redraw the selection and/or cursor\n
+  function drawSelection(cm) {\n
+    var display = cm.display, doc = cm.doc, result = {};\n
+    var curFragment = result.cursors = document.createDocumentFragment();\n
+    var selFragment = result.selection = document.createDocumentFragment();\n
+\n
+    for (var i = 0; i < doc.sel.ranges.length; i++) {\n
+      var range = doc.sel.ranges[i];\n
+      var collapsed = range.empty();\n
+      if (collapsed || cm.options.showCursorWhenSelecting)\n
+        drawSelectionCursor(cm, range, curFragment);\n
+      if (!collapsed)\n
+        drawSelectionRange(cm, range, selFragment);\n
+    }\n
 \n
     // Move the hidden textarea near the cursor to prevent scrolling artifacts\n
     if (cm.options.moveInputWithCursor) {\n
-      var headPos = cursorCoords(cm, cm.doc.sel.head, "div");\n
-      var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);\n
-      display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,\n
-                                                        headPos.top + lineOff.top - wrapOff.top)) + "px";\n
-      display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,\n
-                                                         headPos.left + lineOff.left - wrapOff.left)) + "px";\n
+      var headPos = cursorCoords(cm, doc.sel.primary().head, "div");\n
+      var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();\n
+      result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,\n
+                                          headPos.top + lineOff.top - wrapOff.top));\n
+      result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,\n
+                                           headPos.left + lineOff.left - wrapOff.left));\n
     }\n
+\n
+    return result;\n
   }\n
 \n
-  // No selection, plain cursor\n
-  function updateSelectionCursor(cm) {\n
-    var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");\n
-    display.cursor.style.left = pos.left + "px";\n
-    display.cursor.style.top = pos.top + "px";\n
-    display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";\n
-    display.cursor.style.display = "";\n
+  function showSelection(cm, drawn) {\n
+    removeChildrenAndAdd(cm.display.cursorDiv, drawn.cursors);\n
+    removeChildrenAndAdd(cm.display.selectionDiv, drawn.selection);\n
+    if (drawn.teTop != null) {\n
+      cm.display.inputDiv.style.top = drawn.teTop + "px";\n
+      cm.display.inputDiv.style.left = drawn.teLeft + "px";\n
+    }\n
+  }\n
+\n
+  function updateSelection(cm) {\n
+    showSelection(cm, drawSelection(cm));\n
+  }\n
+\n
+  // Draws a cursor for the given range\n
+  function drawSelectionCursor(cm, range, output) {\n
+    var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine);\n
+\n
+    var cursor = output.appendChild(elt("div", "\\u00a0", "CodeMirror-cursor"));\n
+    cursor.style.left = pos.left + "px";\n
+    cursor.style.top = pos.top + "px";\n
+    cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";\n
 \n
     if (pos.other) {\n
-      display.otherCursor.style.display = "";\n
-      display.otherCursor.style.left = pos.other.left + "px";\n
-      display.otherCursor.style.top = pos.other.top + "px";\n
-      display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";\n
-    } else { display.otherCursor.style.display = "none"; }\n
+      // Secondary cursor, shown when on a \'jump\' in bi-directional text\n
+      var otherCursor = output.appendChild(elt("div", "\\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));\n
+      otherCursor.style.display = "";\n
+      otherCursor.style.left = pos.other.left + "px";\n
+      otherCursor.style.top = pos.other.top + "px";\n
+      otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";\n
+    }\n
   }\n
 \n
-  // Highlight selection\n
-  function updateSelectionRange(cm) {\n
-    var display = cm.display, doc = cm.doc, sel = cm.doc.sel;\n
+  // Draws the given range as a highlighted selection\n
+  function drawSelectionRange(cm, range, output) {\n
+    var display = cm.display, doc = cm.doc;\n
     var fragment = document.createDocumentFragment();\n
-    var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right;\n
+    var padding = paddingH(cm.display), leftSide = padding.left;\n
+    var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;\n
 \n
     function add(left, top, width, bottom) {\n
       if (top < 0) top = 0;\n
+      top = Math.round(top);\n
+      bottom = Math.round(bottom);\n
       fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +\n
                                "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +\n
                                "px; height: " + (bottom - top) + "px"));\n
@@ -918,13 +1517,14 @@ window.CodeMirror = (function() {\n
       return {start: start, end: end};\n
     }\n
 \n
-    if (sel.from.line == sel.to.line) {\n
-      drawForLine(sel.from.line, sel.from.ch, sel.to.ch);\n
+    var sFrom = range.from(), sTo = range.to();\n
+    if (sFrom.line == sTo.line) {\n
+      drawForLine(sFrom.line, sFrom.ch, sTo.ch);\n
     } else {\n
-      var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);\n
-      var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);\n
-      var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;\n
-      var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;\n
+      var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);\n
+      var singleVLine = visualLine(fromLine) == visualLine(toLine);\n
+      var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;\n
+      var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;\n
       if (singleVLine) {\n
         if (leftEnd.top < rightStart.top - 2) {\n
           add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);\n
@@ -937,8 +1537,7 @@ window.CodeMirror = (function() {\n
         add(leftSide, leftEnd.bottom, null, rightStart.top);\n
     }\n
 \n
-    removeChildrenAndAdd(display.selectionDiv, fragment);\n
-    display.selectionDiv.style.display = "";\n
+    output.appendChild(fragment);\n
   }\n
 \n
   // Cursor-blinking\n
@@ -947,37 +1546,42 @@ window.CodeMirror = (function() {\n
     var display = cm.display;\n
     clearInterval(display.blinker);\n
     var on = true;\n
-    display.cursor.style.visibility = display.otherCursor.style.visibility = "";\n
+    display.cursorDiv.style.visibility = "";\n
     if (cm.options.cursorBlinkRate > 0)\n
       display.blinker = setInterval(function() {\n
-        display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";\n
+        display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";\n
       }, cm.options.cursorBlinkRate);\n
+    else if (cm.options.cursorBlinkRate < 0)\n
+      display.cursorDiv.style.visibility = "hidden";\n
   }\n
 \n
   // HIGHLIGHT WORKER\n
 \n
   function startWorker(cm, time) {\n
-    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)\n
+    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)\n
       cm.state.highlight.set(time, bind(highlightWorker, cm));\n
   }\n
 \n
   function highlightWorker(cm) {\n
     var doc = cm.doc;\n
     if (doc.frontier < doc.first) doc.frontier = doc.first;\n
-    if (doc.frontier >= cm.display.showingTo) return;\n
+    if (doc.frontier >= cm.display.viewTo) return;\n
     var end = +new Date + cm.options.workTime;\n
     var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));\n
-    var changed = [], prevChange;\n
-    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {\n
-      if (doc.frontier >= cm.display.showingFrom) { // Visible\n
+    var changedLines = [];\n
+\n
+    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {\n
+      if (doc.frontier >= cm.display.viewFrom) { // Visible\n
         var oldStyles = line.styles;\n
-        line.styles = highlightLine(cm, line, state, true);\n
-        var ischange = !oldStyles || oldStyles.length != line.styles.length;\n
+        var highlighted = highlightLine(cm, line, state, true);\n
+        line.styles = highlighted.styles;\n
+        var oldCls = line.styleClasses, newCls = highlighted.classes;\n
+        if (newCls) line.styleClasses = newCls;\n
+        else if (oldCls) line.styleClasses = null;\n
+        var ischange = !oldStyles || oldStyles.length != line.styles.length ||\n
+          oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);\n
         for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];\n
-        if (ischange) {\n
-          if (prevChange && prevChange.end == doc.frontier) prevChange.end++;\n
-          else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});\n
-        }\n
+        if (ischange) changedLines.push(doc.frontier);\n
         line.stateAfter = copyState(doc.mode, state);\n
       } else {\n
         processLine(cm, line.text, state);\n
@@ -989,11 +1593,10 @@ window.CodeMirror = (function() {\n
         return true;\n
       }\n
     });\n
-    if (changed.length)\n
-      operation(cm, function() {\n
-        for (var i = 0; i < changed.length; ++i)\n
-          regChange(this, changed[i].start, changed[i].end);\n
-      })();\n
+    if (changedLines.length) runInOp(cm, function() {\n
+      for (var i = 0; i < changedLines.length; i++)\n
+        regLineChange(cm, changedLines[i], "text");\n
+    });\n
   }\n
 \n
   // Finds the line to start with when starting a parse. Tries to\n
@@ -1025,7 +1628,7 @@ window.CodeMirror = (function() {\n
     else state = copyState(doc.mode, state);\n
     doc.iter(pos, n, function(line) {\n
       processLine(cm, line.text, state);\n
-      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;\n
+      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;\n
       line.stateAfter = save ? copyState(doc.mode, state) : null;\n
       ++pos;\n
     });\n
@@ -1041,181 +1644,250 @@ window.CodeMirror = (function() {\n
     if (display.cachedPaddingH) return display.cachedPaddingH;\n
     var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));\n
     var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;\n
-    return display.cachedPaddingH = {left: parseInt(style.paddingLeft),\n
-                                     right: parseInt(style.paddingRight)};\n
-  }\n
-\n
-  function measureChar(cm, line, ch, data, bias) {\n
-    var dir = -1;\n
-    data = data || measureLine(cm, line);\n
-    if (data.crude) {\n
-      var left = data.left + ch * data.width;\n
-      return {left: left, right: left + data.width, top: data.top, bottom: data.bottom};\n
-    }\n
-\n
-    for (var pos = ch;; pos += dir) {\n
-      var r = data[pos];\n
-      if (r) break;\n
-      if (dir < 0 && pos == 0) dir = 1;\n
-    }\n
-    bias = pos > ch ? "left" : pos < ch ? "right" : bias;\n
-    if (bias == "left" && r.leftSide) r = r.leftSide;\n
-    else if (bias == "right" && r.rightSide) r = r.rightSide;\n
-    return {left: pos < ch ? r.right : r.left,\n
-            right: pos > ch ? r.left : r.right,\n
-            top: r.top,\n
-            bottom: r.bottom};\n
-  }\n
-\n
-  function findCachedMeasurement(cm, line) {\n
-    var cache = cm.display.measureLineCache;\n
-    for (var i = 0; i < cache.length; ++i) {\n
-      var memo = cache[i];\n
-      if (memo.text == line.text && memo.markedSpans == line.markedSpans &&\n
-          cm.display.scroller.clientWidth == memo.width &&\n
-          memo.classes == line.textClass + "|" + line.wrapClass)\n
-        return memo;\n
-    }\n
-  }\n
-\n
-  function clearCachedMeasurement(cm, line) {\n
-    var exists = findCachedMeasurement(cm, line);\n
-    if (exists) exists.text = exists.measure = exists.markedSpans = null;\n
-  }\n
-\n
-  function measureLine(cm, line) {\n
-    // First look in the cache\n
-    var cached = findCachedMeasurement(cm, line);\n
-    if (cached) return cached.measure;\n
-\n
-    // Failing that, recompute and store result in cache\n
-    var measure = measureLineInner(cm, line);\n
-    var cache = cm.display.measureLineCache;\n
-    var memo = {text: line.text, width: cm.display.scroller.clientWidth,\n
-                markedSpans: line.markedSpans, measure: measure,\n
-                classes: line.textClass + "|" + line.wrapClass};\n
-    if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;\n
-    else cache.push(memo);\n
-    return measure;\n
-  }\n
-\n
-  function measureLineInner(cm, line) {\n
-    if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom)\n
-      return crudelyMeasureLine(cm, line);\n
-\n
-    var display = cm.display, measure = emptyArray(line.text.length);\n
-    var pre = buildLineContent(cm, line, measure, true).pre;\n
-\n
-    // IE does not cache element positions of inline elements between\n
-    // calls to getBoundingClientRect. This makes the loop below,\n
-    // which gathers the positions of all the characters on the line,\n
-    // do an amount of layout work quadratic to the number of\n
-    // characters. When line wrapping is off, we try to improve things\n
-    // by first subdividing the line into a bunch of inline blocks, so\n
-    // that IE can reuse most of the layout information from caches\n
-    // for those blocks. This does interfere with line wrapping, so it\n
-    // doesn\'t work when wrapping is on, but in that case the\n
-    // situation is slightly better, since IE does cache line-wrapping\n
-    // information and only recomputes per-line.\n
-    if (old_ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {\n
-      var fragment = document.createDocumentFragment();\n
-      var chunk = 10, n = pre.childNodes.length;\n
-      for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {\n
-        var wrap = elt("div", null, null, "display: inline-block");\n
-        for (var j = 0; j < chunk && n; ++j) {\n
-          wrap.appendChild(pre.firstChild);\n
-          --n;\n
+    var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};\n
+    if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;\n
+    return data;\n
+  }\n
+\n
+  function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }\n
+  function displayWidth(cm) {\n
+    return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;\n
+  }\n
+  function displayHeight(cm) {\n
+    return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;\n
+  }\n
+\n
+  // Ensure the lineView.wrapping.heights array is populated. This is\n
+  // an array of bottom offsets for the lines that make up a drawn\n
+  // line. When lineWrapping is on, there might be more than one\n
+  // height.\n
+  function ensureLineHeights(cm, lineView, rect) {\n
+    var wrapping = cm.options.lineWrapping;\n
+    var curWidth = wrapping && displayWidth(cm);\n
+    if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {\n
+      var heights = lineView.measure.heights = [];\n
+      if (wrapping) {\n
+        lineView.measure.width = curWidth;\n
+        var rects = lineView.text.firstChild.getClientRects();\n
+        for (var i = 0; i < rects.length - 1; i++) {\n
+          var cur = rects[i], next = rects[i + 1];\n
+          if (Math.abs(cur.bottom - next.bottom) > 2)\n
+            heights.push((cur.bottom + next.top) / 2 - rect.top);\n
         }\n
-        fragment.appendChild(wrap);\n
       }\n
-      pre.appendChild(fragment);\n
-    }\n
-\n
-    removeChildrenAndAdd(display.measure, pre);\n
-\n
-    var outer = getRect(display.lineDiv);\n
-    var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;\n
-    // Work around an IE7/8 bug where it will sometimes have randomly\n
-    // replaced our pre with a clone at this point.\n
-    if (ie_lt9 && display.measure.first != pre)\n
-      removeChildrenAndAdd(display.measure, pre);\n
+      heights.push(rect.bottom - rect.top);\n
+    }\n
+  }\n
+\n
+  // Find a line map (mapping character offsets to text nodes) and a\n
+  // measurement cache for the given line number. (A line view might\n
+  // contain multiple lines when collapsed ranges are present.)\n
+  function mapFromLineView(lineView, line, lineN) {\n
+    if (lineView.line == line)\n
+      return {map: lineView.measure.map, cache: lineView.measure.cache};\n
+    for (var i = 0; i < lineView.rest.length; i++)\n
+      if (lineView.rest[i] == line)\n
+        return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};\n
+    for (var i = 0; i < lineView.rest.length; i++)\n
+      if (lineNo(lineView.rest[i]) > lineN)\n
+        return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};\n
+  }\n
+\n
+  // Render a line into the hidden node display.externalMeasured. Used\n
+  // when measurement is needed for a line that\'s not in the viewport.\n
+  function updateExternalMeasurement(cm, line) {\n
+    line = visualLine(line);\n
+    var lineN = lineNo(line);\n
+    var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);\n
+    view.lineN = lineN;\n
+    var built = view.built = buildLineContent(cm, view);\n
+    view.text = built.pre;\n
+    removeChildrenAndAdd(cm.display.lineMeasure, built.pre);\n
+    return view;\n
+  }\n
+\n
+  // Get a {top, bottom, left, right} box (in line-local coordinates)\n
+  // for a given character.\n
+  function measureChar(cm, line, ch, bias) {\n
+    return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);\n
+  }\n
+\n
+  // Find a line view that corresponds to the given line number.\n
+  function findViewForLine(cm, lineN) {\n
+    if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)\n
+      return cm.display.view[findViewIndex(cm, lineN)];\n
+    var ext = cm.display.externalMeasured;\n
+    if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)\n
+      return ext;\n
+  }\n
+\n
+  // Measurement can be split in two steps, the set-up work that\n
+  // applies to the whole line, and the measurement of the actual\n
+  // character. Functions like coordsChar, that need to do a lot of\n
+  // measurements in a row, can thus ensure that the set-up work is\n
+  // only done once.\n
+  function prepareMeasureForLine(cm, line) {\n
+    var lineN = lineNo(line);\n
+    var view = findViewForLine(cm, lineN);\n
+    if (view && !view.text)\n
+      view = null;\n
+    else if (view && view.changes)\n
+      updateLineForChanges(cm, view, lineN, getDimensions(cm));\n
+    if (!view)\n
+      view = updateExternalMeasurement(cm, line);\n
+\n
+    var info = mapFromLineView(view, line, lineN);\n
+    return {\n
+      line: line, view: view, rect: null,\n
+      map: info.map, cache: info.cache, before: info.before,\n
+      hasHeights: false\n
+    };\n
+  }\n
 \n
-    function measureRect(rect) {\n
-      var top = rect.top - outer.top, bot = rect.bottom - outer.top;\n
-      if (bot > maxBot) bot = maxBot;\n
-      if (top < 0) top = 0;\n
-      for (var i = vranges.length - 2; i >= 0; i -= 2) {\n
-        var rtop = vranges[i], rbot = vranges[i+1];\n
-        if (rtop > bot || rbot < top) continue;\n
-        if (rtop <= top && rbot >= bot ||\n
-            top <= rtop && bot >= rbot ||\n
-            Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {\n
-          vranges[i] = Math.min(top, rtop);\n
-          vranges[i+1] = Math.max(bot, rbot);\n
-          break;\n
-        }\n
+  // Given a prepared measurement object, measures the position of an\n
+  // actual character (or fetches it from the cache).\n
+  function measureCharPrepared(cm, prepared, ch, bias, varHeight) {\n
+    if (prepared.before) ch = -1;\n
+    var key = ch + (bias || ""), found;\n
+    if (prepared.cache.hasOwnProperty(key)) {\n
+      found = prepared.cache[key];\n
+    } else {\n
+      if (!prepared.rect)\n
+        prepared.rect = prepared.view.text.getBoundingClientRect();\n
+      if (!prepared.hasHeights) {\n
+        ensureLineHeights(cm, prepared.view, prepared.rect);\n
+        prepared.hasHeights = true;\n
+      }\n
+      found = measureCharInner(cm, prepared, ch, bias);\n
+      if (!found.bogus) prepared.cache[key] = found;\n
+    }\n
+    return {left: found.left, right: found.right,\n
+            top: varHeight ? found.rtop : found.top,\n
+            bottom: varHeight ? found.rbottom : found.bottom};\n
+  }\n
+\n
+  var nullRect = {left: 0, right: 0, top: 0, bottom: 0};\n
+\n
+  function measureCharInner(cm, prepared, ch, bias) {\n
+    var map = prepared.map;\n
+\n
+    var node, start, end, collapse;\n
+    // First, search the line map for the text node corresponding to,\n
+    // or closest to, the target character.\n
+    for (var i = 0; i < map.length; i += 3) {\n
+      var mStart = map[i], mEnd = map[i + 1];\n
+      if (ch < mStart) {\n
+        start = 0; end = 1;\n
+        collapse = "left";\n
+      } else if (ch < mEnd) {\n
+        start = ch - mStart;\n
+        end = start + 1;\n
+      } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {\n
+        end = mEnd - mStart;\n
+        start = end - 1;\n
+        if (ch >= mEnd) collapse = "right";\n
+      }\n
+      if (start != null) {\n
+        node = map[i + 2];\n
+        if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))\n
+          collapse = bias;\n
+        if (bias == "left" && start == 0)\n
+          while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {\n
+            node = map[(i -= 3) + 2];\n
+            collapse = "left";\n
+          }\n
+        if (bias == "right" && start == mEnd - mStart)\n
+          while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {\n
+            node = map[(i += 3) + 2];\n
+            collapse = "right";\n
+          }\n
+        break;\n
       }\n
-      if (i < 0) { i = vranges.length; vranges.push(top, bot); }\n
-      return {left: rect.left - outer.left,\n
-              right: rect.right - outer.left,\n
-              top: i, bottom: null};\n
-    }\n
-    function finishRect(rect) {\n
-      rect.bottom = vranges[rect.top+1];\n
-      rect.top = vranges[rect.top];\n
-    }\n
-\n
-    for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {\n
-      var node = cur, rect = null;\n
-      // A widget might wrap, needs special care\n
-      if (/\\bCodeMirror-widget\\b/.test(cur.className) && cur.getClientRects) {\n
-        if (cur.firstChild.nodeType == 1) node = cur.firstChild;\n
-        var rects = node.getClientRects();\n
-        if (rects.length > 1) {\n
-          rect = data[i] = measureRect(rects[0]);\n
-          rect.rightSide = measureRect(rects[rects.length - 1]);\n
+    }\n
+\n
+    var rect;\n
+    if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.\n
+      for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned\n
+        while (start && isExtendingChar(prepared.line.text.charAt(mStart + start))) --start;\n
+        while (mStart + end < mEnd && isExtendingChar(prepared.line.text.charAt(mStart + end))) ++end;\n
+        if (ie && ie_version < 9 && start == 0 && end == mEnd - mStart) {\n
+          rect = node.parentNode.getBoundingClientRect();\n
+        } else if (ie && cm.options.lineWrapping) {\n
+          var rects = range(node, start, end).getClientRects();\n
+          if (rects.length)\n
+            rect = rects[bias == "right" ? rects.length - 1 : 0];\n
+          else\n
+            rect = nullRect;\n
+        } else {\n
+          rect = range(node, start, end).getBoundingClientRect() || nullRect;\n
         }\n
+        if (rect.left || rect.right || start == 0) break;\n
+        end = start;\n
+        start = start - 1;\n
+        collapse = "right";\n
       }\n
-      if (!rect) rect = data[i] = measureRect(getRect(node));\n
-      if (cur.measureRight) rect.right = getRect(cur.measureRight).left - outer.left;\n
-      if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));\n
+      if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);\n
+    } else { // If it is a widget, simply get the box for the whole widget.\n
+      if (start > 0) collapse = bias = "right";\n
+      var rects;\n
+      if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)\n
+        rect = rects[bias == "right" ? rects.length - 1 : 0];\n
+      else\n
+        rect = node.getBoundingClientRect();\n
     }\n
-    removeChildren(cm.display.measure);\n
-    for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {\n
-      finishRect(cur);\n
-      if (cur.leftSide) finishRect(cur.leftSide);\n
-      if (cur.rightSide) finishRect(cur.rightSide);\n
+    if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {\n
+      var rSpan = node.parentNode.getClientRects()[0];\n
+      if (rSpan)\n
+        rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};\n
+      else\n
+        rect = nullRect;\n
     }\n
-    return data;\n
+\n
+    var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;\n
+    var mid = (rtop + rbot) / 2;\n
+    var heights = prepared.view.measure.heights;\n
+    for (var i = 0; i < heights.length - 1; i++)\n
+      if (mid < heights[i]) break;\n
+    var top = i ? heights[i - 1] : 0, bot = heights[i];\n
+    var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,\n
+                  right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,\n
+                  top: top, bottom: bot};\n
+    if (!rect.left && !rect.right) result.bogus = true;\n
+    if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }\n
+\n
+    return result;\n
   }\n
 \n
-  function crudelyMeasureLine(cm, line) {\n
-    var copy = new Line(line.text.slice(0, 100), null);\n
-    if (line.textClass) copy.textClass = line.textClass;\n
-    var measure = measureLineInner(cm, copy);\n
-    var left = measureChar(cm, copy, 0, measure, "left");\n
-    var right = measureChar(cm, copy, 99, measure, "right");\n
-    return {crude: true, top: left.top, left: left.left, bottom: left.bottom, width: (right.right - left.left) / 100};\n
+  // Work around problem with bounding client rects on ranges being\n
+  // returned incorrectly when zoomed on IE10 and below.\n
+  function maybeUpdateRectForZooming(measure, rect) {\n
+    if (!window.screen || screen.logicalXDPI == null ||\n
+        screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))\n
+      return rect;\n
+    var scaleX = screen.logicalXDPI / screen.deviceXDPI;\n
+    var scaleY = screen.logicalYDPI / screen.deviceYDPI;\n
+    return {left: rect.left * scaleX, right: rect.right * scaleX,\n
+            top: rect.top * scaleY, bottom: rect.bottom * scaleY};\n
   }\n
 \n
-  function measureLineWidth(cm, line) {\n
-    var hasBadSpan = false;\n
-    if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {\n
-      var sp = line.markedSpans[i];\n
-      if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;\n
+  function clearLineMeasurementCacheFor(lineView) {\n
+    if (lineView.measure) {\n
+      lineView.measure.cache = {};\n
+      lineView.measure.heights = null;\n
+      if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)\n
+        lineView.measure.caches[i] = {};\n
     }\n
-    var cached = !hasBadSpan && findCachedMeasurement(cm, line);\n
-    if (cached || line.text.length >= cm.options.crudeMeasuringFrom)\n
-      return measureChar(cm, line, line.text.length, cached && cached.measure, "right").right;\n
+  }\n
 \n
-    var pre = buildLineContent(cm, line, null, true).pre;\n
-    var end = pre.appendChild(zeroWidthElement(cm.display.measure));\n
-    removeChildrenAndAdd(cm.display.measure, pre);\n
-    return getRect(end).right - getRect(cm.display.lineDiv).left;\n
+  function clearLineMeasurementCache(cm) {\n
+    cm.display.externalMeasure = null;\n
+    removeChildren(cm.display.lineMeasure);\n
+    for (var i = 0; i < cm.display.view.length; i++)\n
+      clearLineMeasurementCacheFor(cm.display.view[i]);\n
   }\n
 \n
   function clearCaches(cm) {\n
-    cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;\n
+    clearLineMeasurementCache(cm);\n
     cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;\n
     if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;\n
     cm.display.lineNumChars = null;\n
@@ -1224,7 +1896,9 @@ window.CodeMirror = (function() {\n
   function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }\n
   function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }\n
 \n
-  // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"\n
+  // Converts a {top, bottom, left, right} box from line-local\n
+  // coordinates into another coordinate system. Context may be one of\n
+  // "line", "div" (display.lineDiv), "local"/null (editor), or "page".\n
   function intoCoordSystem(cm, lineObj, rect, context) {\n
     if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {\n
       var size = widgetHeight(lineObj.widgets[i]);\n
@@ -1232,11 +1906,11 @@ window.CodeMirror = (function() {\n
     }\n
     if (context == "line") return rect;\n
     if (!context) context = "local";\n
-    var yOff = heightAtLine(cm, lineObj);\n
+    var yOff = heightAtLine(lineObj);\n
     if (context == "local") yOff += paddingTop(cm.display);\n
     else yOff -= cm.display.viewOffset;\n
     if (context == "page" || context == "window") {\n
-      var lOff = getRect(cm.display.lineSpace);\n
+      var lOff = cm.display.lineSpace.getBoundingClientRect();\n
       yOff += lOff.top + (context == "window" ? 0 : pageScrollY());\n
       var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());\n
       rect.left += xOff; rect.right += xOff;\n
@@ -1245,8 +1919,8 @@ window.CodeMirror = (function() {\n
     return rect;\n
   }\n
 \n
-  // Context may be "window", "page", "div", or "local"/null\n
-  // Result is in "div" coords\n
+  // Coverts a box from "div" coords to another coordinate system.\n
+  // Context may be "window", "page", "div", or "local"/null.\n
   function fromCoordSystem(cm, coords, context) {\n
     if (context == "div") return coords;\n
     var left = coords.left, top = coords.top;\n
@@ -1255,25 +1929,28 @@ window.CodeMirror = (function() {\n
       left -= pageScrollX();\n
       top -= pageScrollY();\n
     } else if (context == "local" || !context) {\n
-      var localBox = getRect(cm.display.sizer);\n
+      var localBox = cm.display.sizer.getBoundingClientRect();\n
       left += localBox.left;\n
       top += localBox.top;\n
     }\n
 \n
-    var lineSpaceBox = getRect(cm.display.lineSpace);\n
+    var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();\n
     return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};\n
   }\n
 \n
   function charCoords(cm, pos, context, lineObj, bias) {\n
     if (!lineObj) lineObj = getLine(cm.doc, pos.line);\n
-    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);\n
+    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);\n
   }\n
 \n
-  function cursorCoords(cm, pos, context, lineObj, measurement) {\n
+  // Returns a box for a given cursor position, which may have an\n
+  // \'other\' property containing the position of the secondary cursor\n
+  // on a bidi boundary.\n
+  function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {\n
     lineObj = lineObj || getLine(cm.doc, pos.line);\n
-    if (!measurement) measurement = measureLine(cm, lineObj);\n
+    if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);\n
     function get(ch, right) {\n
-      var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");\n
+      var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);\n
       if (right) m.left = m.right; else m.right = m.left;\n
       return intoCoordSystem(cm, lineObj, m, context);\n
     }\n
@@ -1299,43 +1976,59 @@ window.CodeMirror = (function() {\n
     return val;\n
   }\n
 \n
+  // Used to cheaply estimate the coordinates for a position. Used for\n
+  // intermediate scroll updates.\n
+  function estimateCoords(cm, pos) {\n
+    var left = 0, pos = clipPos(cm.doc, pos);\n
+    if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;\n
+    var lineObj = getLine(cm.doc, pos.line);\n
+    var top = heightAtLine(lineObj) + paddingTop(cm.display);\n
+    return {left: left, right: left, top: top, bottom: top + lineObj.height};\n
+  }\n
+\n
+  // Positions returned by coordsChar contain some extra information.\n
+  // xRel is the relative x position of the input coordinates compared\n
+  // to the found position (so xRel > 0 means the coordinates are to\n
+  // the right of the character position, for example). When outside\n
+  // is true, that means the coordinates lie outside the line\'s\n
+  // vertical range.\n
   function PosWithInfo(line, ch, outside, xRel) {\n
-    var pos = new Pos(line, ch);\n
+    var pos = Pos(line, ch);\n
     pos.xRel = xRel;\n
     if (outside) pos.outside = true;\n
     return pos;\n
   }\n
 \n
-  // Coords must be lineSpace-local\n
+  // Compute the character position closest to the given coordinates.\n
+  // Input must be lineSpace-local ("div" coordinate system).\n
   function coordsChar(cm, x, y) {\n
     var doc = cm.doc;\n
     y += cm.display.viewOffset;\n
     if (y < 0) return PosWithInfo(doc.first, 0, true, -1);\n
-    var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;\n
-    if (lineNo > last)\n
+    var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;\n
+    if (lineN > last)\n
       return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);\n
     if (x < 0) x = 0;\n
 \n
+    var lineObj = getLine(doc, lineN);\n
     for (;;) {\n
-      var lineObj = getLine(doc, lineNo);\n
-      var found = coordsCharInner(cm, lineObj, lineNo, x, y);\n
+      var found = coordsCharInner(cm, lineObj, lineN, x, y);\n
       var merged = collapsedSpanAtEnd(lineObj);\n
-      var mergedPos = merged && merged.find();\n
+      var mergedPos = merged && merged.find(0, true);\n
       if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))\n
-        lineNo = mergedPos.to.line;\n
+        lineN = lineNo(lineObj = mergedPos.to.line);\n
       else\n
         return found;\n
     }\n
   }\n
 \n
   function coordsCharInner(cm, lineObj, lineNo, x, y) {\n
-    var innerOff = y - heightAtLine(cm, lineObj);\n
+    var innerOff = y - heightAtLine(lineObj);\n
     var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;\n
-    var measurement = measureLine(cm, lineObj);\n
+    var preparedMeasure = prepareMeasureForLine(cm, lineObj);\n
 \n
     function getX(ch) {\n
-      var sp = cursorCoords(cm, Pos(lineNo, ch), "line",\n
-                            lineObj, measurement);\n
+      var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);\n
       wrongLine = true;\n
       if (innerOff > sp.bottom) return sp.left - adjust;\n
       else if (innerOff < sp.top) return sp.left + adjust;\n
@@ -1355,7 +2048,7 @@ window.CodeMirror = (function() {\n
         var xDiff = x - (ch == from ? fromX : toX);\n
         while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;\n
         var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,\n
-                              xDiff < 0 ? -1 : xDiff ? 1 : 0);\n
+                              xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);\n
         return pos;\n
       }\n
       var step = Math.ceil(dist / 2), middle = from + step;\n
@@ -1370,6 +2063,7 @@ window.CodeMirror = (function() {\n
   }\n
 \n
   var measureText;\n
+  // Compute the default text height.\n
   function textHeight(display) {\n
     if (display.cachedTextHeight != null) return display.cachedTextHeight;\n
     if (measureText == null) {\n
@@ -1389,136 +2083,434 @@ window.CodeMirror = (function() {\n
     return height || 1;\n
   }\n
 \n
+  // Compute the default character width.\n
   function charWidth(display) {\n
     if (display.cachedCharWidth != null) return display.cachedCharWidth;\n
-    var anchor = elt("span", "x");\n
+    var anchor = elt("span", "xxxxxxxxxx");\n
     var pre = elt("pre", [anchor]);\n
     removeChildrenAndAdd(display.measure, pre);\n
-    var width = anchor.offsetWidth;\n
+    var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;\n
     if (width > 2) display.cachedCharWidth = width;\n
     return width || 10;\n
   }\n
 \n
   // OPERATIONS\n
 \n
-  // Operations are used to wrap changes in such a way that each\n
-  // change won\'t have to update the cursor and display (which would\n
-  // be awkward, slow, and error-prone), but instead updates are\n
-  // batched and then all combined and executed at once.\n
+  // Operations are used to wrap a series of changes to the editor\n
+  // state in such a way that each change won\'t have to update the\n
+  // cursor and display (which would be awkward, slow, and\n
+  // error-prone). Instead, display updates are batched and then all\n
+  // combined and executed at once.\n
+\n
+  var operationGroup = null;\n
 \n
   var nextOpId = 0;\n
+  // Start a new operation.\n
   function startOperation(cm) {\n
     cm.curOp = {\n
-      // An array of ranges of lines that have to be updated. See\n
-      // updateDisplay.\n
-      changes: [],\n
-      forceUpdate: false,\n
-      updateInput: null,\n
-      userSelChange: null,\n
-      textChanged: null,\n
-      selectionChanged: false,\n
-      cursorActivity: false,\n
-      updateMaxLine: false,\n
-      updateScrollPos: false,\n
-      id: ++nextOpId\n
+      cm: cm,\n
+      viewChanged: false,      // Flag that indicates that lines might need to be redrawn\n
+      startHeight: cm.doc.height, // Used to detect need to update scrollbar\n
+      forceUpdate: false,      // Used to force a redraw\n
+      updateInput: null,       // Whether to reset the input textarea\n
+      typing: false,           // Whether this reset should be careful to leave existing text (for compositing)\n
+      changeObjs: null,        // Accumulated changes, for firing change events\n
+      cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on\n
+      cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already\n
+      selectionChanged: false, // Whether the selection needs to be redrawn\n
+      updateMaxLine: false,    // Set when the widest line needs to be determined anew\n
+      scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet\n
+      scrollToPos: null,       // Used to scroll to a specific position\n
+      id: ++nextOpId           // Unique ID\n
     };\n
-    if (!delayedCallbackDepth++) delayedCallbacks = [];\n
+    if (operationGroup) {\n
+      operationGroup.ops.push(cm.curOp);\n
+    } else {\n
+      cm.curOp.ownsGroup = operationGroup = {\n
+        ops: [cm.curOp],\n
+        delayedCallbacks: []\n
+      };\n
+    }\n
   }\n
 \n
+  function fireCallbacksForOps(group) {\n
+    // Calls delayed callbacks and cursorActivity handlers until no\n
+    // new ones appear\n
+    var callbacks = group.delayedCallbacks, i = 0;\n
+    do {\n
+      for (; i < callbacks.length; i++)\n
+        callbacks[i]();\n
+      for (var j = 0; j < group.ops.length; j++) {\n
+        var op = group.ops[j];\n
+        if (op.cursorActivityHandlers)\n
+          while (op.cursorActivityCalled < op.cursorActivityHandlers.length)\n
+            op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);\n
+      }\n
+    } while (i < callbacks.length);\n
+  }\n
+\n
+  // Finish an operation, updating the display and signalling delayed events\n
   function endOperation(cm) {\n
-    var op = cm.curOp, doc = cm.doc, display = cm.display;\n
-    cm.curOp = null;\n
-\n
-    if (op.updateMaxLine) computeMaxLength(cm);\n
-    if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {\n
-      var width = measureLineWidth(cm, display.maxLine);\n
-      display.sizer.style.minWidth = Math.max(0, width + 3) + "px";\n
-      display.maxLineChanged = false;\n
-      var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);\n
-      if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)\n
-        setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);\n
-    }\n
-    var newScrollPos, updated;\n
-    if (op.updateScrollPos) {\n
-      newScrollPos = op.updateScrollPos;\n
-    } else if (op.selectionChanged && display.scroller.clientHeight) { // don\'t rescroll if not visible\n
-      var coords = cursorCoords(cm, doc.sel.head);\n
-      newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);\n
-    }\n
-    if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {\n
-      updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);\n
-      if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;\n
-    }\n
-    if (!updated && op.selectionChanged) updateSelection(cm);\n
-    if (op.updateScrollPos) {\n
-      var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, newScrollPos.scrollTop));\n
-      var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, newScrollPos.scrollLeft));\n
-      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;\n
-      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;\n
-      alignHorizontally(cm);\n
-      if (op.scrollToPos)\n
-        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),\n
-                          clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);\n
-    } else if (newScrollPos) {\n
-      scrollCursorIntoView(cm);\n
+    var op = cm.curOp, group = op.ownsGroup;\n
+    if (!group) return;\n
+\n
+    try { fireCallbacksForOps(group); }\n
+    finally {\n
+      operationGroup = null;\n
+      for (var i = 0; i < group.ops.length; i++)\n
+        group.ops[i].cm.curOp = null;\n
+      endOperations(group);\n
     }\n
+  }\n
+\n
+  // The DOM updates done when an operation finishes are batched so\n
+  // that the minimum number of relayouts are required.\n
+  function endOperations(group) {\n
+    var ops = group.ops;\n
+    for (var i = 0; i < ops.length; i++) // Read DOM\n
+      endOperation_R1(ops[i]);\n
+    for (var i = 0; i < ops.length; i++) // Write DOM (maybe)\n
+      endOperation_W1(ops[i]);\n
+    for (var i = 0; i < ops.length; i++) // Read DOM\n
+      endOperation_R2(ops[i]);\n
+    for (var i = 0; i < ops.length; i++) // Write DOM (maybe)\n
+      endOperation_W2(ops[i]);\n
+    for (var i = 0; i < ops.length; i++) // Read DOM\n
+      endOperation_finish(ops[i]);\n
+  }\n
+\n
+  function endOperation_R1(op) {\n
+    var cm = op.cm, display = cm.display;\n
+    maybeClipScrollbars(cm);\n
+    if (op.updateMaxLine) findMaxLine(cm);\n
+\n
+    op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||\n
+      op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||\n
+                         op.scrollToPos.to.line >= display.viewTo) ||\n
+      display.maxLineChanged && cm.options.lineWrapping;\n
+    op.update = op.mustUpdate &&\n
+      new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);\n
+  }\n
+\n
+  function endOperation_W1(op) {\n
+    op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);\n
+  }\n
+\n
+  function endOperation_R2(op) {\n
+    var cm = op.cm, display = cm.display;\n
+    if (op.updatedDisplay) updateHeightsInViewport(cm);\n
+\n
+    op.barMeasure = measureForScrollbars(cm);\n
+\n
+    // If the max line changed since it was last measured, measure it,\n
+    // and ensure the document\'s width matches it.\n
+    // updateDisplay_W2 will use these properties to do the actual resizing\n
+    if (display.maxLineChanged && !cm.options.lineWrapping) {\n
+      op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;\n
+      cm.display.sizerWidth = op.adjustWidthTo;\n
+      op.barMeasure.scrollWidth =\n
+        Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);\n
+      op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));\n
+    }\n
+\n
+    if (op.updatedDisplay || op.selectionChanged)\n
+      op.newSelectionNodes = drawSelection(cm);\n
+  }\n
+\n
+  function endOperation_W2(op) {\n
+    var cm = op.cm;\n
+\n
+    if (op.adjustWidthTo != null) {\n
+      cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";\n
+      if (op.maxScrollLeft < cm.doc.scrollLeft)\n
+        setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);\n
+      cm.display.maxLineChanged = false;\n
+    }\n
+\n
+    if (op.newSelectionNodes)\n
+      showSelection(cm, op.newSelectionNodes);\n
+    if (op.updatedDisplay)\n
+      setDocumentHeight(cm, op.barMeasure);\n
+    if (op.updatedDisplay || op.startHeight != cm.doc.height)\n
+      updateScrollbars(cm, op.barMeasure);\n
+\n
     if (op.selectionChanged) restartBlink(cm);\n
 \n
     if (cm.state.focused && op.updateInput)\n
-      resetInput(cm, op.userSelChange);\n
+      resetInput(cm, op.typing);\n
+  }\n
+\n
+  function endOperation_finish(op) {\n
+    var cm = op.cm, display = cm.display, doc = cm.doc;\n
 \n
+    if (op.updatedDisplay) postUpdateDisplay(cm, op.update);\n
+\n
+    // Abort mouse wheel delta measurement, when scrolling explicitly\n
+    if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))\n
+      display.wheelStartX = display.wheelStartY = null;\n
+\n
+    // Propagate the scroll position to the actual DOM scroller\n
+    if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {\n
+      doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));\n
+      display.scrollbars.setScrollTop(doc.scrollTop);\n
+      display.scroller.scrollTop = doc.scrollTop;\n
+    }\n
+    if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {\n
+      doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));\n
+      display.scrollbars.setScrollLeft(doc.scrollLeft);\n
+      display.scroller.scrollLeft = doc.scrollLeft;\n
+      alignHorizontally(cm);\n
+    }\n
+    // If we need to scroll a specific position into view, do so.\n
+    if (op.scrollToPos) {\n
+      var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),\n
+                                     clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);\n
+      if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);\n
+    }\n
+\n
+    // Fire events for markers that are hidden/unidden by editing or\n
+    // undoing\n
     var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;\n
     if (hidden) for (var i = 0; i < hidden.length; ++i)\n
       if (!hidden[i].lines.length) signal(hidden[i], "hide");\n
     if (unhidden) for (var i = 0; i < unhidden.length; ++i)\n
       if (unhidden[i].lines.length) signal(unhidden[i], "unhide");\n
 \n
-    var delayed;\n
-    if (!--delayedCallbackDepth) {\n
-      delayed = delayedCallbacks;\n
-      delayedCallbacks = null;\n
-    }\n
-    if (op.textChanged)\n
-      signal(cm, "change", cm, op.textChanged);\n
-    if (op.cursorActivity) signal(cm, "cursorActivity", cm);\n
-    if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();\n
+    if (display.wrapper.offsetHeight)\n
+      doc.scrollTop = cm.display.scroller.scrollTop;\n
+\n
+    // Fire change events, and delayed event handlers\n
+    if (op.changeObjs)\n
+      signal(cm, "changes", cm, op.changeObjs);\n
   }\n
 \n
+  // Run the given function in an operation\n
+  function runInOp(cm, f) {\n
+    if (cm.curOp) return f();\n
+    startOperation(cm);\n
+    try { return f(); }\n
+    finally { endOperation(cm); }\n
+  }\n
   // Wraps a function in an operation. Returns the wrapped function.\n
-  function operation(cm1, f) {\n
+  function operation(cm, f) {\n
     return function() {\n
-      var cm = cm1 || this, withOp = !cm.curOp;\n
-      if (withOp) startOperation(cm);\n
-      try { var result = f.apply(cm, arguments); }\n
-      finally { if (withOp) endOperation(cm); }\n
-      return result;\n
+      if (cm.curOp) return f.apply(cm, arguments);\n
+      startOperation(cm);\n
+      try { return f.apply(cm, arguments); }\n
+      finally { endOperation(cm); }\n
     };\n
   }\n
-  function docOperation(f) {\n
+  // Used to add methods to editor and doc instances, wrapping them in\n
+  // operations.\n
+  function methodOp(f) {\n
     return function() {\n
-      var withOp = this.cm && !this.cm.curOp, result;\n
-      if (withOp) startOperation(this.cm);\n
-      try { result = f.apply(this, arguments); }\n
-      finally { if (withOp) endOperation(this.cm); }\n
-      return result;\n
+      if (this.curOp) return f.apply(this, arguments);\n
+      startOperation(this);\n
+      try { return f.apply(this, arguments); }\n
+      finally { endOperation(this); }\n
     };\n
   }\n
-  function runInOp(cm, f) {\n
-    var withOp = !cm.curOp, result;\n
-    if (withOp) startOperation(cm);\n
-    try { result = f(); }\n
-    finally { if (withOp) endOperation(cm); }\n
-    return result;\n
+  function docMethodOp(f) {\n
+    return function() {\n
+      var cm = this.cm;\n
+      if (!cm || cm.curOp) return f.apply(this, arguments);\n
+      startOperation(cm);\n
+      try { return f.apply(this, arguments); }\n
+      finally { endOperation(cm); }\n
+    };\n
+  }\n
+\n
+  // VIEW TRACKING\n
+\n
+  // These objects are used to represent the visible (currently drawn)\n
+  // part of the document. A LineView may correspond to multiple\n
+  // logical lines, if those are connected by collapsed ranges.\n
+  function LineView(doc, line, lineN) {\n
+    // The starting line\n
+    this.line = line;\n
+    // Continuing lines, if any\n
+    this.rest = visualLineContinued(line);\n
+    // Number of logical lines in this visual line\n
+    this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;\n
+    this.node = this.text = null;\n
+    this.hidden = lineIsHidden(doc, line);\n
+  }\n
+\n
+  // Create a range of LineView objects for the given lines.\n
+  function buildViewArray(cm, from, to) {\n
+    var array = [], nextPos;\n
+    for (var pos = from; pos < to; pos = nextPos) {\n
+      var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);\n
+      nextPos = pos + view.size;\n
+      array.push(view);\n
+    }\n
+    return array;\n
+  }\n
+\n
+  // Updates the display.view data structure for a given change to the\n
+  // document. From and to are in pre-change coordinates. Lendiff is\n
+  // the amount of lines added or subtracted by the change. This is\n
+  // used for changes that span multiple lines, or change the way\n
+  // lines are divided into visual lines. regLineChange (below)\n
+  // registers single-line changes.\n
+  function regChange(cm, from, to, lendiff) {\n
+    if (from == null) from = cm.doc.first;\n
+    if (to == null) to = cm.doc.first + cm.doc.size;\n
+    if (!lendiff) lendiff = 0;\n
+\n
+    var display = cm.display;\n
+    if (lendiff && to < display.viewTo &&\n
+        (display.updateLineNumbers == null || display.updateLineNumbers > from))\n
+      display.updateLineNumbers = from;\n
+\n
+    cm.curOp.viewChanged = true;\n
+\n
+    if (from >= display.viewTo) { // Change after\n
+      if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)\n
+        resetView(cm);\n
+    } else if (to <= display.viewFrom) { // Change before\n
+      if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {\n
+        resetView(cm);\n
+      } else {\n
+        display.viewFrom += lendiff;\n
+        display.viewTo += lendiff;\n
+      }\n
+    } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap\n
+      resetView(cm);\n
+    } else if (from <= display.viewFrom) { // Top overlap\n
+      var cut = viewCuttingPoint(cm, to, to + lendiff, 1);\n
+      if (cut) {\n
+        display.view = display.view.slice(cut.index);\n
+        display.viewFrom = cut.lineN;\n
+        display.viewTo += lendiff;\n
+      } else {\n
+        resetView(cm);\n
+      }\n
+    } else if (to >= display.viewTo) { // Bottom overlap\n
+      var cut = viewCuttingPoint(cm, from, from, -1);\n
+      if (cut) {\n
+        display.view = display.view.slice(0, cut.index);\n
+        display.viewTo = cut.lineN;\n
+      } else {\n
+        resetView(cm);\n
+      }\n
+    } else { // Gap in the middle\n
+      var cutTop = viewCuttingPoint(cm, from, from, -1);\n
+      var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);\n
+      if (cutTop && cutBot) {\n
+        display.view = display.view.slice(0, cutTop.index)\n
+          .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))\n
+          .concat(display.view.slice(cutBot.index));\n
+        display.viewTo += lendiff;\n
+      } else {\n
+        resetView(cm);\n
+      }\n
+    }\n
+\n
+    var ext = display.externalMeasured;\n
+    if (ext) {\n
+      if (to < ext.lineN)\n
+        ext.lineN += lendiff;\n
+      else if (from < ext.lineN + ext.size)\n
+        display.externalMeasured = null;\n
+    }\n
+  }\n
+\n
+  // Register a change to a single line. Type must be one of "text",\n
+  // "gutter", "class", "widget"\n
+  function regLineChange(cm, line, type) {\n
+    cm.curOp.viewChanged = true;\n
+    var display = cm.display, ext = cm.display.externalMeasured;\n
+    if (ext && line >= ext.lineN && line < ext.lineN + ext.size)\n
+      display.externalMeasured = null;\n
+\n
+    if (line < display.viewFrom || line >= display.viewTo) return;\n
+    var lineView = display.view[findViewIndex(cm, line)];\n
+    if (lineView.node == null) return;\n
+    var arr = lineView.changes || (lineView.changes = []);\n
+    if (indexOf(arr, type) == -1) arr.push(type);\n
+  }\n
+\n
+  // Clear the view.\n
+  function resetView(cm) {\n
+    cm.display.viewFrom = cm.display.viewTo = cm.doc.first;\n
+    cm.display.view = [];\n
+    cm.display.viewOffset = 0;\n
+  }\n
+\n
+  // Find the view element corresponding to a given line. Return null\n
+  // when the line isn\'t visible.\n
+  function findViewIndex(cm, n) {\n
+    if (n >= cm.display.viewTo) return null;\n
+    n -= cm.display.viewFrom;\n
+    if (n < 0) return null;\n
+    var view = cm.display.view;\n
+    for (var i = 0; i < view.length; i++) {\n
+      n -= view[i].size;\n
+      if (n < 0) return i;\n
+    }\n
+  }\n
+\n
+  function viewCuttingPoint(cm, oldN, newN, dir) {\n
+    var index = findViewIndex(cm, oldN), diff, view = cm.display.view;\n
+    if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)\n
+      return {index: index, lineN: newN};\n
+    for (var i = 0, n = cm.display.viewFrom; i < index; i++)\n
+      n += view[i].size;\n
+    if (n != oldN) {\n
+      if (dir > 0) {\n
+        if (index == view.length - 1) return null;\n
+        diff = (n + view[index].size) - oldN;\n
+        index++;\n
+      } else {\n
+        diff = n - oldN;\n
+      }\n
+      oldN += diff; newN += diff;\n
+    }\n
+    while (visualLineNo(cm.doc, newN) != newN) {\n
+      if (index == (dir < 0 ? 0 : view.length - 1)) return null;\n
+      newN += dir * view[index - (dir < 0 ? 1 : 0)].size;\n
+      index += dir;\n
+    }\n
+    return {index: index, lineN: newN};\n
   }\n
 \n
-  function regChange(cm, from, to, lendiff) {\n
-    if (from == null) from = cm.doc.first;\n
-    if (to == null) to = cm.doc.first + cm.doc.size;\n
-    cm.curOp.changes.push({from: from, to: to, diff: lendiff});\n
+  // Force the view to cover a given range, adding empty view element\n
+  // or clipping off existing ones as needed.\n
+  function adjustView(cm, from, to) {\n
+    var display = cm.display, view = display.view;\n
+    if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {\n
+      display.view = buildViewArray(cm, from, to);\n
+      display.viewFrom = from;\n
+    } else {\n
+      if (display.viewFrom > from)\n
+        display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);\n
+      else if (display.viewFrom < from)\n
+        display.view = display.view.slice(findViewIndex(cm, from));\n
+      display.viewFrom = from;\n
+      if (display.viewTo < to)\n
+        display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));\n
+      else if (display.viewTo > to)\n
+        display.view = display.view.slice(0, findViewIndex(cm, to));\n
+    }\n
+    display.viewTo = to;\n
+  }\n
+\n
+  // Count the number of lines in the view whose DOM representation is\n
+  // out of date (or nonexistent).\n
+  function countDirtyView(cm) {\n
+    var view = cm.display.view, dirty = 0;\n
+    for (var i = 0; i < view.length; i++) {\n
+      var lineView = view[i];\n
+      if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;\n
+    }\n
+    return dirty;\n
   }\n
 \n
   // INPUT HANDLING\n
 \n
+  // Poll for input changes, using the normal rate of polling. This\n
+  // runs as long as the editor is focused.\n
   function slowPoll(cm) {\n
     if (cm.display.pollingFast) return;\n
     cm.display.poll.set(cm.options.pollInterval, function() {\n
@@ -1527,6 +2519,9 @@ window.CodeMirror = (function() {\n
     });\n
   }\n
 \n
+  // When an event has just come in that is likely to add or change\n
+  // something in the input textarea, we poll faster, to ensure that\n
+  // the change appears on the screen quickly.\n
   function fastPoll(cm) {\n
     var missed = false;\n
     cm.display.pollingFast = true;\n
@@ -1538,53 +2533,100 @@ window.CodeMirror = (function() {\n
     cm.display.poll.set(20, p);\n
   }\n
 \n
-  // prevInput is a hack to work with IME. If we reset the textarea\n
-  // on every change, that breaks IME. So we look for changes\n
-  // compared to the previous content instead. (Modern browsers have\n
-  // events that indicate IME taking place, but these are not widely\n
-  // supported or compatible enough yet to rely on.)\n
+  // This will be set to an array of strings when copying, so that,\n
+  // when pasting, we know what kind of selections the copied text\n
+  // was made out of.\n
+  var lastCopied = null;\n
+\n
+  // Read input from the textarea, and update the document to match.\n
+  // When something is selected, it is present in the textarea, and\n
+  // selected (unless it is huge, in which case a placeholder is\n
+  // used). When nothing is selected, the cursor sits after previously\n
+  // seen text (can be empty), which is stored in prevInput (we must\n
+  // not reset the textarea when typing, because that breaks IME).\n
   function readInput(cm) {\n
-    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;\n
-    if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false;\n
+    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc;\n
+    // Since this is called a *lot*, try to bail out as cheaply as\n
+    // possible when it is clear that nothing happened. hasSelection\n
+    // will be the case when there is a lot of text in the textarea,\n
+    // in which case reading its value would be expensive.\n
+    if (!cm.state.focused || (hasSelection(input) && !prevInput) || isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)\n
+      return false;\n
+    // See paste handler for more on the fakedLastChar kludge\n
     if (cm.state.pasteIncoming && cm.state.fakedLastChar) {\n
       input.value = input.value.substring(0, input.value.length - 1);\n
       cm.state.fakedLastChar = false;\n
     }\n
     var text = input.value;\n
-    if (text == prevInput && posEq(sel.from, sel.to)) return false;\n
-    if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {\n
-      resetInput(cm, true);\n
+    // If nothing changed, bail.\n
+    if (text == prevInput && !cm.somethingSelected()) return false;\n
+    // Work around nonsensical selection resetting in IE9/10, and\n
+    // inexplicable appearance of private area unicode characters on\n
+    // some key combos in Mac (#2689).\n
+    if (ie && ie_version >= 9 && cm.display.inputHasSelection === text ||\n
+        mac && /[\\uf700-\\uf7ff]/.test(text)) {\n
+      resetInput(cm);\n
       return false;\n
     }\n
 \n
     var withOp = !cm.curOp;\n
     if (withOp) startOperation(cm);\n
-    sel.shift = false;\n
+    cm.display.shift = false;\n
+\n
+    if (text.charCodeAt(0) == 0x200b && doc.sel == cm.display.selForContextMenu && !prevInput)\n
+      prevInput = "\\u200b";\n
+    // Find the part of the input that is actually new\n
     var same = 0, l = Math.min(prevInput.length, text.length);\n
     while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;\n
-    var from = sel.from, to = sel.to;\n
-    var inserted = text.slice(same);\n
-    if (same < prevInput.length)\n
-      from = Pos(from.line, from.ch - (prevInput.length - same));\n
-    else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)\n
-      to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + inserted.length));\n
-\n
-    var updateInput = cm.curOp.updateInput;\n
-    var changeEvent = {from: from, to: to, text: splitLines(inserted),\n
-                       origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};\n
-    makeChange(cm.doc, changeEvent, "end");\n
-    cm.curOp.updateInput = updateInput;\n
-    signalLater(cm, "inputRead", cm, changeEvent);\n
-    if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&\n
-        cm.options.smartIndent && sel.head.ch < 100) {\n
-      var electric = cm.getModeAt(sel.head).electricChars;\n
-      if (electric) for (var i = 0; i < electric.length; i++)\n
-        if (inserted.indexOf(electric.charAt(i)) > -1) {\n
-          indentLine(cm, sel.head.line, "smart");\n
-          break;\n
+    var inserted = text.slice(same), textLines = splitLines(inserted);\n
+\n
+    // When pasing N lines into N selections, insert one line per selection\n
+    var multiPaste = null;\n
+    if (cm.state.pasteIncoming && doc.sel.ranges.length > 1) {\n
+      if (lastCopied && lastCopied.join("\\n") == inserted)\n
+        multiPaste = doc.sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);\n
+      else if (textLines.length == doc.sel.ranges.length)\n
+        multiPaste = map(textLines, function(l) { return [l]; });\n
+    }\n
+\n
+    // Normal behavior is to insert the new text into every selection\n
+    for (var i = doc.sel.ranges.length - 1; i >= 0; i--) {\n
+      var range = doc.sel.ranges[i];\n
+      var from = range.from(), to = range.to();\n
+      // Handle deletion\n
+      if (same < prevInput.length)\n
+        from = Pos(from.line, from.ch - (prevInput.length - same));\n
+      // Handle overwrite\n
+      else if (cm.state.overwrite && range.empty() && !cm.state.pasteIncoming)\n
+        to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));\n
+      var updateInput = cm.curOp.updateInput;\n
+      var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,\n
+                         origin: cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input"};\n
+      makeChange(cm.doc, changeEvent);\n
+      signalLater(cm, "inputRead", cm, changeEvent);\n
+      // When an \'electric\' character is inserted, immediately trigger a reindent\n
+      if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&\n
+          cm.options.smartIndent && range.head.ch < 100 &&\n
+          (!i || doc.sel.ranges[i - 1].head.line != range.head.line)) {\n
+        var mode = cm.getModeAt(range.head);\n
+        var end = changeEnd(changeEvent);\n
+        if (mode.electricChars) {\n
+          for (var j = 0; j < mode.electricChars.length; j++)\n
+            if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {\n
+              indentLine(cm, end.line, "smart");\n
+              break;\n
+            }\n
+        } else if (mode.electricInput) {\n
+          if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))\n
+            indentLine(cm, end.line, "smart");\n
         }\n
+      }\n
     }\n
+    ensureCursorVisible(cm);\n
+    cm.curOp.updateInput = updateInput;\n
+    cm.curOp.typing = true;\n
 \n
+    // Don\'t leave long text in the textarea, since it makes further polling slow\n
     if (text.length > 1000 || text.indexOf("\\n") > -1) input.value = cm.display.prevInput = "";\n
     else cm.display.prevInput = text;\n
     if (withOp) endOperation(cm);\n
@@ -1592,25 +2634,29 @@ window.CodeMirror = (function() {\n
     return true;\n
   }\n
 \n
-  function resetInput(cm, user) {\n
+  // Reset the input to correspond to the selection (or to be empty,\n
+  // when not typing and nothing is selected)\n
+  function resetInput(cm, typing) {\n
+    if (cm.display.contextMenuPending) return;\n
     var minimal, selected, doc = cm.doc;\n
-    if (!posEq(doc.sel.from, doc.sel.to)) {\n
+    if (cm.somethingSelected()) {\n
       cm.display.prevInput = "";\n
+      var range = doc.sel.primary();\n
       minimal = hasCopyEvent &&\n
-        (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);\n
+        (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);\n
       var content = minimal ? "-" : selected || cm.getSelection();\n
       cm.display.input.value = content;\n
       if (cm.state.focused) selectInput(cm.display.input);\n
-      if (ie && !ie_lt9) cm.display.inputHasSelection = content;\n
-    } else if (user) {\n
+      if (ie && ie_version >= 9) cm.display.inputHasSelection = content;\n
+    } else if (!typing) {\n
       cm.display.prevInput = cm.display.input.value = "";\n
-      if (ie && !ie_lt9) cm.display.inputHasSelection = null;\n
+      if (ie && ie_version >= 9) cm.display.inputHasSelection = null;\n
     }\n
     cm.display.inaccurateSelection = minimal;\n
   }\n
 \n
   function focusInput(cm) {\n
-    if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))\n
+    if (cm.options.readOnly != "nocursor" && (!mobile || activeElt() != cm.display.input))\n
       cm.display.input.focus();\n
   }\n
 \n
@@ -1624,28 +2670,33 @@ window.CodeMirror = (function() {\n
 \n
   // EVENT HANDLERS\n
 \n
+  // Attach the necessary event handlers when initializing the editor\n
   function registerEventHandlers(cm) {\n
     var d = cm.display;\n
     on(d.scroller, "mousedown", operation(cm, onMouseDown));\n
-    if (old_ie)\n
+    // Older IE\'s will not fire a second mousedown for a double click\n
+    if (ie && ie_version < 11)\n
       on(d.scroller, "dblclick", operation(cm, function(e) {\n
         if (signalDOMEvent(cm, e)) return;\n
         var pos = posFromMouse(cm, e);\n
         if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;\n
         e_preventDefault(e);\n
-        var word = findWordAt(getLine(cm.doc, pos.line).text, pos);\n
-        extendSelection(cm.doc, word.from, word.to);\n
+        var word = cm.findWordAt(pos);\n
+        extendSelection(cm.doc, word.anchor, word.head);\n
       }));\n
     else\n
       on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });\n
+    // Prevent normal selection in the editor (we handle our own)\n
     on(d.lineSpace, "selectstart", function(e) {\n
       if (!eventInWidget(d, e)) e_preventDefault(e);\n
     });\n
-    // Gecko browsers fire contextmenu *after* opening the menu, at\n
+    // Some browsers fire contextmenu *after* opening the menu, at\n
     // which point we can\'t mess with it anymore. Context menu is\n
-    // handled in onMouseDown for Gecko.\n
-    if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});\n
+    // handled in onMouseDown for these browsers.\n
+    if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});\n
 \n
+    // Sync scrolling between fake scrollbars and real scrollable\n
+    // area, ensure viewport is updated when scrolling.\n
     on(d.scroller, "scroll", function() {\n
       if (d.scroller.clientHeight) {\n
         setScrollTop(cm, d.scroller.scrollTop);\n
@@ -1653,47 +2704,18 @@ window.CodeMirror = (function() {\n
         signal(cm, "scroll", cm);\n
       }\n
     });\n
-    on(d.scrollbarV, "scroll", function() {\n
-      if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);\n
-    });\n
-    on(d.scrollbarH, "scroll", function() {\n
-      if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);\n
-    });\n
 \n
+    // Listen to wheel events in order to try and update the viewport on time.\n
     on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});\n
     on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});\n
 \n
-    function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }\n
-    on(d.scrollbarH, "mousedown", reFocus);\n
-    on(d.scrollbarV, "mousedown", reFocus);\n
     // Prevent wrapper from ever scrolling\n
     on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });\n
 \n
-    var resizeTimer;\n
-    function onResize() {\n
-      if (resizeTimer == null) resizeTimer = setTimeout(function() {\n
-        resizeTimer = null;\n
-        // Might be a text scaling operation, clear size caches.\n
-        d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null;\n
-        clearCaches(cm);\n
-        runInOp(cm, bind(regChange, cm));\n
-      }, 100);\n
-    }\n
-    on(window, "resize", onResize);\n
-    // Above handler holds on to the editor and its data structures.\n
-    // Here we poll to unregister it when the editor is no longer in\n
-    // the document, so that it can be garbage-collected.\n
-    function unregister() {\n
-      for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}\n
-      if (p) setTimeout(unregister, 5000);\n
-      else off(window, "resize", onResize);\n
-    }\n
-    setTimeout(unregister, 5000);\n
-\n
-    on(d.input, "keyup", operation(cm, onKeyUp));\n
+    on(d.input, "keyup", function(e) { onKeyUp.call(cm, e); });\n
     on(d.input, "input", function() {\n
-      if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;\n
-      fastPoll(cm);\n
+      if (ie && ie_version >= 9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;\n
+      readInput(cm);\n
     });\n
     on(d.input, "keydown", operation(cm, onKeyDown));\n
     on(d.input, "keypress", operation(cm, onKeyPress));\n
@@ -1701,8 +2723,7 @@ window.CodeMirror = (function() {\n
     on(d.input, "blur", bind(onBlur, cm));\n
 \n
     function drag_(e) {\n
-      if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;\n
-      e_stop(e);\n
+      if (!signalDOMEvent(cm, e)) e_stop(e);\n
     }\n
     if (cm.options.dragDrop) {\n
       on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});\n
@@ -1712,6 +2733,7 @@ window.CodeMirror = (function() {\n
     }\n
     on(d.scroller, "paste", function(e) {\n
       if (eventInWidget(d, e)) return;\n
+      cm.state.pasteIncoming = true;\n
       focusInput(cm);\n
       fastPoll(cm);\n
     });\n
@@ -1722,61 +2744,111 @@ window.CodeMirror = (function() {\n
       if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {\n
         var start = d.input.selectionStart, end = d.input.selectionEnd;\n
         d.input.value += "$";\n
-        d.input.selectionStart = start;\n
+        // The selection end needs to be set before the start, otherwise there\n
+        // can be an intermediate non-empty selection between the two, which\n
+        // can override the middle-click paste buffer on linux and cause the\n
+        // wrong thing to get pasted.\n
         d.input.selectionEnd = end;\n
+        d.input.selectionStart = start;\n
         cm.state.fakedLastChar = true;\n
       }\n
       cm.state.pasteIncoming = true;\n
       fastPoll(cm);\n
     });\n
 \n
-    function prepareCopy(e) {\n
-      if (d.inaccurateSelection) {\n
-        d.prevInput = "";\n
-        d.inaccurateSelection = false;\n
-        d.input.value = cm.getSelection();\n
-        selectInput(d.input);\n
+    function prepareCopyCut(e) {\n
+      if (cm.somethingSelected()) {\n
+        lastCopied = cm.getSelections();\n
+        if (d.inaccurateSelection) {\n
+          d.prevInput = "";\n
+          d.inaccurateSelection = false;\n
+          d.input.value = lastCopied.join("\\n");\n
+          selectInput(d.input);\n
+        }\n
+      } else {\n
+        var text = [], ranges = [];\n
+        for (var i = 0; i < cm.doc.sel.ranges.length; i++) {\n
+          var line = cm.doc.sel.ranges[i].head.line;\n
+          var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};\n
+          ranges.push(lineRange);\n
+          text.push(cm.getRange(lineRange.anchor, lineRange.head));\n
+        }\n
+        if (e.type == "cut") {\n
+          cm.setSelections(ranges, null, sel_dontScroll);\n
+        } else {\n
+          d.prevInput = "";\n
+          d.input.value = text.join("\\n");\n
+          selectInput(d.input);\n
+        }\n
+        lastCopied = text;\n
       }\n
       if (e.type == "cut") cm.state.cutIncoming = true;\n
     }\n
-    on(d.input, "cut", prepareCopy);\n
-    on(d.input, "copy", prepareCopy);\n
+    on(d.input, "cut", prepareCopyCut);\n
+    on(d.input, "copy", prepareCopyCut);\n
 \n
     // Needed to handle Tab key in KHTML\n
     if (khtml) on(d.sizer, "mouseup", function() {\n
-      if (document.activeElement == d.input) d.input.blur();\n
+      if (activeElt() == d.input) d.input.blur();\n
       focusInput(cm);\n
     });\n
   }\n
 \n
+  // Called when the window resizes\n
+  function onResize(cm) {\n
+    var d = cm.display;\n
+    if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)\n
+      return;\n
+    // Might be a text scaling operation, clear size caches.\n
+    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n
+    d.scrollbarsClipped = false;\n
+    cm.setSize();\n
+  }\n
+\n
+  // MOUSE EVENTS\n
+\n
+  // Return true when the given mouse event happened in a widget\n
   function eventInWidget(display, e) {\n
     for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {\n
-      if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;\n
+      if (!n || n.getAttribute("cm-ignore-events") == "true" || n.parentNode == display.sizer && n != display.mover) return true;\n
     }\n
   }\n
 \n
-  function posFromMouse(cm, e, liberal) {\n
+  // Given a mouse event, find the corresponding position. If liberal\n
+  // is false, it checks whether a gutter or scrollbar was clicked,\n
+  // and returns null if it was. forRect is used by rectangular\n
+  // selections, and tries to estimate a character position even for\n
+  // coordinates beyond the right of the text.\n
+  function posFromMouse(cm, e, liberal, forRect) {\n
     var display = cm.display;\n
-    if (!liberal) {\n
-      var target = e_target(e);\n
-      if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||\n
-          target == display.scrollbarV || target == display.scrollbarV.firstChild ||\n
-          target == display.scrollbarFiller || target == display.gutterFiller) return null;\n
-    }\n
-    var x, y, space = getRect(display.lineSpace);\n
+    if (!liberal && e_target(e).getAttribute("not-content") == "true") return null;\n
+\n
+    var x, y, space = display.lineSpace.getBoundingClientRect();\n
     // Fails unpredictably on IE[67] when mouse is dragged around quickly.\n
-    try { x = e.clientX; y = e.clientY; } catch (e) { return null; }\n
-    return coordsChar(cm, x - space.left, y - space.top);\n
+    try { x = e.clientX - space.left; y = e.clientY - space.top; }\n
+    catch (e) { return null; }\n
+    var coords = coordsChar(cm, x, y), line;\n
+    if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {\n
+      var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;\n
+      coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));\n
+    }\n
+    return coords;\n
   }\n
 \n
-  var lastClick, lastDoubleClick;\n
+  // A mouse down can be a single click, double click, triple click,\n
+  // start of selection drag, start of text drag, new cursor\n
+  // (ctrl-click), rectangle drag (alt-drag), or xwin\n
+  // middle-click-paste. Or it might be a click on something we should\n
+  // not interfere with, such as a scrollbar or widget.\n
   function onMouseDown(e) {\n
     if (signalDOMEvent(this, e)) return;\n
-    var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;\n
-    sel.shift = e.shiftKey;\n
+    var cm = this, display = cm.display;\n
+    display.shift = e.shiftKey;\n
 \n
     if (eventInWidget(display, e)) {\n
       if (!webkit) {\n
+        // Briefly turn off draggability, to allow widgets to do\n
+        // normal dragging things.\n
         display.scroller.draggable = false;\n
         setTimeout(function(){display.scroller.draggable = true;}, 100);\n
       }\n
@@ -1787,90 +2859,173 @@ window.CodeMirror = (function() {\n
     window.focus();\n
 \n
     switch (e_button(e)) {\n
-    case 3:\n
-      if (captureMiddleClick) onContextMenu.call(cm, cm, e);\n
-      return;\n
+    case 1:\n
+      if (start)\n
+        leftButtonDown(cm, e, start);\n
+      else if (e_target(e) == display.scroller)\n
+        e_preventDefault(e);\n
+      break;\n
     case 2:\n
       if (webkit) cm.state.lastMiddleDown = +new Date;\n
       if (start) extendSelection(cm.doc, start);\n
       setTimeout(bind(focusInput, cm), 20);\n
       e_preventDefault(e);\n
-      return;\n
+      break;\n
+    case 3:\n
+      if (captureRightClick) onContextMenu(cm, e);\n
+      break;\n
     }\n
-    // For button 1, if it was clicked inside the editor\n
-    // (posFromMouse returning non-null), we have to adjust the\n
-    // selection.\n
-    if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}\n
+  }\n
 \n
+  var lastClick, lastDoubleClick;\n
+  function leftButtonDown(cm, e, start) {\n
     setTimeout(bind(ensureFocus, cm), 0);\n
 \n
-    var now = +new Date, type = "single";\n
-    if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {\n
+    var now = +new Date, type;\n
+    if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {\n
       type = "triple";\n
-      e_preventDefault(e);\n
-      setTimeout(bind(focusInput, cm), 20);\n
-      selectLine(cm, start.line);\n
-    } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {\n
+    } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {\n
       type = "double";\n
       lastDoubleClick = {time: now, pos: start};\n
-      e_preventDefault(e);\n
-      var word = findWordAt(getLine(doc, start.line).text, start);\n
-      extendSelection(cm.doc, word.from, word.to);\n
-    } else { lastClick = {time: now, pos: start}; }\n
-\n
-    var last = start;\n
-    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&\n
-        !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {\n
-      var dragEnd = operation(cm, function(e2) {\n
-        if (webkit) display.scroller.draggable = false;\n
-        cm.state.draggingText = false;\n
-        off(document, "mouseup", dragEnd);\n
-        off(display.scroller, "drop", dragEnd);\n
-        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n
-          e_preventDefault(e2);\n
-          extendSelection(cm.doc, start);\n
-          focusInput(cm);\n
-          // Work around unexplainable focus problem in IE9 (#2127)\n
-          if (old_ie && !ie_lt9)\n
-            setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);\n
-        }\n
-      });\n
-      // Let the drag handler handle this.\n
-      if (webkit) display.scroller.draggable = true;\n
-      cm.state.draggingText = dragEnd;\n
-      // IE\'s approach to draggable\n
-      if (display.scroller.dragDrop) display.scroller.dragDrop();\n
-      on(document, "mouseup", dragEnd);\n
-      on(display.scroller, "drop", dragEnd);\n
-      return;\n
+    } else {\n
+      type = "single";\n
+      lastClick = {time: now, pos: start};\n
     }\n
-    e_preventDefault(e);\n
-    if (type == "single") extendSelection(cm.doc, clipPos(doc, start));\n
 \n
-    var startstart = sel.from, startend = sel.to, lastPos = start;\n
-\n
-    function doSelect(cur) {\n
-      if (posEq(lastPos, cur)) return;\n
-      lastPos = cur;\n
+    var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;\n
+    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&\n
+        type == "single" && (contained = sel.contains(start)) > -1 &&\n
+        !sel.ranges[contained].empty())\n
+      leftButtonStartDrag(cm, e, start, modifier);\n
+    else\n
+      leftButtonSelect(cm, e, start, type, modifier);\n
+  }\n
 \n
-      if (type == "single") {\n
-        extendSelection(cm.doc, clipPos(doc, start), cur);\n
-        return;\n
+  // Start a text drag. When it ends, see if any dragging actually\n
+  // happen, and treat as a click if it didn\'t.\n
+  function leftButtonStartDrag(cm, e, start, modifier) {\n
+    var display = cm.display;\n
+    var dragEnd = operation(cm, function(e2) {\n
+      if (webkit) display.scroller.draggable = false;\n
+      cm.state.draggingText = false;\n
+      off(document, "mouseup", dragEnd);\n
+      off(display.scroller, "drop", dragEnd);\n
+      if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n
+        e_preventDefault(e2);\n
+        if (!modifier)\n
+          extendSelection(cm.doc, start);\n
+        focusInput(cm);\n
+        // Work around unexplainable focus problem in IE9 (#2127)\n
+        if (ie && ie_version == 9)\n
+          setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);\n
       }\n
+    });\n
+    // Let the drag handler handle this.\n
+    if (webkit) display.scroller.draggable = true;\n
+    cm.state.draggingText = dragEnd;\n
+    // IE\'s approach to draggable\n
+    if (display.scroller.dragDrop) display.scroller.dragDrop();\n
+    on(document, "mouseup", dragEnd);\n
+    on(display.scroller, "drop", dragEnd);\n
+  }\n
 \n
-      startstart = clipPos(doc, startstart);\n
-      startend = clipPos(doc, startend);\n
-      if (type == "double") {\n
-        var word = findWordAt(getLine(doc, cur.line).text, cur);\n
-        if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);\n
-        else extendSelection(cm.doc, startstart, word.to);\n
-      } else if (type == "triple") {\n
-        if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));\n
-        else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));\n
+  // Normal selection, as opposed to text dragging.\n
+  function leftButtonSelect(cm, e, start, type, addNew) {\n
+    var display = cm.display, doc = cm.doc;\n
+    e_preventDefault(e);\n
+\n
+    var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;\n
+    if (addNew && !e.shiftKey) {\n
+      ourIndex = doc.sel.contains(start);\n
+      if (ourIndex > -1)\n
+        ourRange = ranges[ourIndex];\n
+      else\n
+        ourRange = new Range(start, start);\n
+    } else {\n
+      ourRange = doc.sel.primary();\n
+    }\n
+\n
+    if (e.altKey) {\n
+      type = "rect";\n
+      if (!addNew) ourRange = new Range(start, start);\n
+      start = posFromMouse(cm, e, true, true);\n
+      ourIndex = -1;\n
+    } else if (type == "double") {\n
+      var word = cm.findWordAt(start);\n
+      if (cm.display.shift || doc.extend)\n
+        ourRange = extendRange(doc, ourRange, word.anchor, word.head);\n
+      else\n
+        ourRange = word;\n
+    } else if (type == "triple") {\n
+      var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));\n
+      if (cm.display.shift || doc.extend)\n
+        ourRange = extendRange(doc, ourRange, line.anchor, line.head);\n
+      else\n
+        ourRange = line;\n
+    } else {\n
+      ourRange = extendRange(doc, ourRange, start);\n
+    }\n
+\n
+    if (!addNew) {\n
+      ourIndex = 0;\n
+      setSelection(doc, new Selection([ourRange], 0), sel_mouse);\n
+      startSel = doc.sel;\n
+    } else if (ourIndex == -1) {\n
+      ourIndex = ranges.length;\n
+      setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),\n
+                   {scroll: false, origin: "*mouse"});\n
+    } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single") {\n
+      setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));\n
+      startSel = doc.sel;\n
+    } else {\n
+      replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);\n
+    }\n
+\n
+    var lastPos = start;\n
+    function extendTo(pos) {\n
+      if (cmp(lastPos, pos) == 0) return;\n
+      lastPos = pos;\n
+\n
+      if (type == "rect") {\n
+        var ranges = [], tabSize = cm.options.tabSize;\n
+        var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);\n
+        var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);\n
+        var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);\n
+        for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));\n
+             line <= end; line++) {\n
+          var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);\n
+          if (left == right)\n
+            ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));\n
+          else if (text.length > leftPos)\n
+            ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));\n
+        }\n
+        if (!ranges.length) ranges.push(new Range(start, start));\n
+        setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),\n
+                     {origin: "*mouse", scroll: false});\n
+        cm.scrollIntoView(pos);\n
+      } else {\n
+        var oldRange = ourRange;\n
+        var anchor = oldRange.anchor, head = pos;\n
+        if (type != "single") {\n
+          if (type == "double")\n
+            var range = cm.findWordAt(pos);\n
+          else\n
+            var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));\n
+          if (cmp(range.anchor, anchor) > 0) {\n
+            head = range.head;\n
+            anchor = minPos(oldRange.from(), range.anchor);\n
+          } else {\n
+            head = range.anchor;\n
+            anchor = maxPos(oldRange.to(), range.head);\n
+          }\n
+        }\n
+        var ranges = startSel.ranges.slice(0);\n
+        ranges[ourIndex] = new Range(clipPos(doc, anchor), head);\n
+        setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);\n
       }\n
     }\n
 \n
-    var editorSize = getRect(display.wrapper);\n
+    var editorSize = display.wrapper.getBoundingClientRect();\n
     // Used to ensure timeout re-tries don\'t fire when another extend\n
     // happened in the meantime (clearTimeout isn\'t reliable -- at\n
     // least on Chrome, the timeouts still happen even when cleared,\n
@@ -1879,12 +3034,11 @@ window.CodeMirror = (function() {\n
 \n
     function extend(e) {\n
       var curCount = ++counter;\n
-      var cur = posFromMouse(cm, e, true);\n
+      var cur = posFromMouse(cm, e, true, type == "rect");\n
       if (!cur) return;\n
-      if (!posEq(cur, last)) {\n
+      if (cmp(cur, lastPos) != 0) {\n
         ensureFocus(cm);\n
-        last = cur;\n
-        doSelect(cur);\n
+        extendTo(cur);\n
         var visible = visibleLines(display, doc);\n
         if (cur.line >= visible.to || cur.line < visible.from)\n
           setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);\n
@@ -1904,10 +3058,11 @@ window.CodeMirror = (function() {\n
       focusInput(cm);\n
       off(document, "mousemove", move);\n
       off(document, "mouseup", up);\n
+      doc.history.lastSelOrigin = null;\n
     }\n
 \n
     var move = operation(cm, function(e) {\n
-      if ((ie && !ie_lt10) ?  !e.buttons : !e_button(e)) done(e);\n
+      if (!e_button(e)) done(e);\n
       else extend(e);\n
     });\n
     var up = operation(cm, done);\n
@@ -1915,21 +3070,23 @@ window.CodeMirror = (function() {\n
     on(document, "mouseup", up);\n
   }\n
 \n
+  // Determines whether an event happened in the gutter, and fires the\n
+  // handlers for the corresponding event.\n
   function gutterEvent(cm, e, type, prevent, signalfn) {\n
     try { var mX = e.clientX, mY = e.clientY; }\n
     catch(e) { return false; }\n
-    if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;\n
+    if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;\n
     if (prevent) e_preventDefault(e);\n
 \n
     var display = cm.display;\n
-    var lineBox = getRect(display.lineDiv);\n
+    var lineBox = display.lineDiv.getBoundingClientRect();\n
 \n
     if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);\n
     mY -= lineBox.top - display.viewOffset;\n
 \n
     for (var i = 0; i < cm.options.gutters.length; ++i) {\n
       var g = display.gutters.childNodes[i];\n
-      if (g && getRect(g).right >= mX) {\n
+      if (g && g.getBoundingClientRect().right >= mX) {\n
         var line = lineAtHeight(cm.doc, mY);\n
         var gutter = cm.options.gutters[i];\n
         signalfn(cm, type, cm, line, gutter, e);\n
@@ -1937,11 +3094,6 @@ window.CodeMirror = (function() {\n
       }\n
     }\n
   }\n
-\n
-  function contextMenuInGutter(cm, e) {\n
-    if (!hasHandler(cm, "gutterContextMenu")) return false;\n
-    return gutterEvent(cm, e, "gutterContextMenu", false, signal);\n
-  }\n
 \n
   function clickInGutter(cm, e) {\n
     return gutterEvent(cm, e, "gutterClick", true, signalLater);\n
@@ -1953,29 +3105,33 @@ window.CodeMirror = (function() {\n
 \n
   function onDrop(e) {\n
     var cm = this;\n
-    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))\n
+    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))\n
       return;\n
     e_preventDefault(e);\n
     if (ie) lastDrop = +new Date;\n
     var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;\n
     if (!pos || isReadOnly(cm)) return;\n
+    // Might be a file drop, in which case we simply extract the text\n
+    // and insert it.\n
     if (files && files.length && window.FileReader && window.File) {\n
       var n = files.length, text = Array(n), read = 0;\n
       var loadFile = function(file, i) {\n
         var reader = new FileReader;\n
-        reader.onload = function() {\n
+        reader.onload = operation(cm, function() {\n
           text[i] = reader.result;\n
           if (++read == n) {\n
             pos = clipPos(cm.doc, pos);\n
-            makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\\n")), origin: "paste"}, "around");\n
+            var change = {from: pos, to: pos, text: splitLines(text.join("\\n")), origin: "paste"};\n
+            makeChange(cm.doc, change);\n
+            setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));\n
           }\n
-        };\n
+        });\n
         reader.readAsText(file);\n
       };\n
       for (var i = 0; i < n; ++i) loadFile(files[i], i);\n
-    } else {\n
+    } else { // Normal drop\n
       // Don\'t do a replace if the drop happened inside of the selected text.\n
-      if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {\n
+      if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {\n
         cm.state.draggingText(e);\n
         // Ensure the editor is re-focused\n
         setTimeout(bind(focusInput, cm), 20);\n
@@ -1984,10 +3140,12 @@ window.CodeMirror = (function() {\n
       try {\n
         var text = e.dataTransfer.getData("Text");\n
         if (text) {\n
-          var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;\n
-          setSelection(cm.doc, pos, pos);\n
-          if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");\n
-          cm.replaceSelection(text, null, "paste");\n
+          if (cm.state.draggingText && !(mac ? e.metaKey : e.ctrlKey))\n
+            var selected = cm.listSelections();\n
+          setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));\n
+          if (selected) for (var i = 0; i < selected.length; ++i)\n
+            replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");\n
+          cm.replaceSelection(text, "around", "paste");\n
           focusInput(cm);\n
         }\n
       }\n
@@ -1999,41 +3157,46 @@ window.CodeMirror = (function() {\n
     if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }\n
     if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;\n
 \n
-    var txt = cm.getSelection();\n
-    e.dataTransfer.setData("Text", txt);\n
+    e.dataTransfer.setData("Text", cm.getSelection());\n
 \n
     // Use dummy image instead of default browsers image.\n
     // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don\'t do it there.\n
     if (e.dataTransfer.setDragImage && !safari) {\n
       var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");\n
       img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";\n
-      if (opera) {\n
+      if (presto) {\n
         img.width = img.height = 1;\n
         cm.display.wrapper.appendChild(img);\n
         // Force a relayout, or Opera won\'t use our image for some obscure reason\n
         img._top = img.offsetTop;\n
       }\n
       e.dataTransfer.setDragImage(img, 0, 0);\n
-      if (opera) img.parentNode.removeChild(img);\n
+      if (presto) img.parentNode.removeChild(img);\n
     }\n
   }\n
 \n
+  // SCROLL EVENTS\n
+\n
+  // Sync the scrollable area and scrollbars, ensure the viewport\n
+  // covers the visible area.\n
   function setScrollTop(cm, val) {\n
     if (Math.abs(cm.doc.scrollTop - val) < 2) return;\n
     cm.doc.scrollTop = val;\n
-    if (!gecko) updateDisplay(cm, [], val);\n
+    if (!gecko) updateDisplaySimple(cm, {top: val});\n
     if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;\n
-    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;\n
-    if (gecko) updateDisplay(cm, []);\n
+    cm.display.scrollbars.setScrollTop(val);\n
+    if (gecko) updateDisplaySimple(cm);\n
     startWorker(cm, 100);\n
   }\n
+  // Sync scroller and scrollbar, ensure the gutter elements are\n
+  // aligned.\n
   function setScrollLeft(cm, val, isScroller) {\n
     if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;\n
     val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);\n
     cm.doc.scrollLeft = val;\n
     alignHorizontally(cm);\n
     if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;\n
-    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;\n
+    cm.display.scrollbars.setScrollLeft(val);\n
   }\n
 \n
   // Since the delta values reported on mouse wheel events are\n
@@ -2057,11 +3220,22 @@ window.CodeMirror = (function() {\n
   else if (chrome) wheelPixelsPerUnit = -.7;\n
   else if (safari) wheelPixelsPerUnit = -1/3;\n
 \n
-  function onScrollWheel(cm, e) {\n
+  var wheelEventDelta = function(e) {\n
     var dx = e.wheelDeltaX, dy = e.wheelDeltaY;\n
     if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;\n
     if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;\n
     else if (dy == null) dy = e.wheelDelta;\n
+    return {x: dx, y: dy};\n
+  };\n
+  CodeMirror.wheelEventPixels = function(e) {\n
+    var delta = wheelEventDelta(e);\n
+    delta.x *= wheelPixelsPerUnit;\n
+    delta.y *= wheelPixelsPerUnit;\n
+    return delta;\n
+  };\n
+\n
+  function onScrollWheel(cm, e) {\n
+    var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;\n
 \n
     var display = cm.display, scroll = display.scroller;\n
     // Quit if there\'s nothing to scroll here\n
@@ -2073,10 +3247,12 @@ window.CodeMirror = (function() {\n
     // This hack (see related code in patchDisplay) makes sure the\n
     // element is kept around.\n
     if (dy && mac && webkit) {\n
-      for (var cur = e.target; cur != scroll; cur = cur.parentNode) {\n
-        if (cur.lineObj) {\n
-          cm.display.currentWheelTarget = cur;\n
-          break;\n
+      outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {\n
+        for (var i = 0; i < view.length; i++) {\n
+          if (view[i].node == cur) {\n
+            cm.display.currentWheelTarget = cur;\n
+            break outer;\n
+          }\n
         }\n
       }\n
     }\n
@@ -2087,7 +3263,7 @@ window.CodeMirror = (function() {\n
     // estimated pixels/delta value, we just handle horizontal\n
     // scrolling entirely here. It\'ll be slightly off from native, but\n
     // better than glitching out.\n
-    if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {\n
+    if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {\n
       if (dy)\n
         setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));\n
       setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));\n
@@ -2096,12 +3272,14 @@ window.CodeMirror = (function() {\n
       return;\n
     }\n
 \n
+    // \'Project\' the visible viewport to cover the area that is being\n
+    // scrolled into view (if we know enough to estimate it).\n
     if (dy && wheelPixelsPerUnit != null) {\n
       var pixels = dy * wheelPixelsPerUnit;\n
       var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;\n
       if (pixels < 0) top = Math.max(0, top + pixels - 50);\n
       else bot = Math.min(cm.doc.height, bot + pixels + 50);\n
-      updateDisplay(cm, [], {top: top, bottom: bot});\n
+      updateDisplaySimple(cm, {top: top, bottom: bot});\n
     }\n
 \n
     if (wheelSamples < 20) {\n
@@ -2125,6 +3303,9 @@ window.CodeMirror = (function() {\n
     }\n
   }\n
 \n
+  // KEY EVENTS\n
+\n
+  // Run a handler that was bound to a key.\n
   function doHandleBinding(cm, bound, dropShift) {\n
     if (typeof bound == "string") {\n
       bound = commands[bound];\n
@@ -2133,120 +3314,151 @@ window.CodeMirror = (function() {\n
     // Ensure previous input has been read, so that the handler sees a\n
     // consistent view of the document\n
     if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;\n
-    var doc = cm.doc, prevShift = doc.sel.shift, done = false;\n
+    var prevShift = cm.display.shift, done = false;\n
     try {\n
       if (isReadOnly(cm)) cm.state.suppressEdits = true;\n
-      if (dropShift) doc.sel.shift = false;\n
+      if (dropShift) cm.display.shift = false;\n
       done = bound(cm) != Pass;\n
     } finally {\n
-      doc.sel.shift = prevShift;\n
+      cm.display.shift = prevShift;\n
       cm.state.suppressEdits = false;\n
     }\n
     return done;\n
   }\n
 \n
-  function allKeyMaps(cm) {\n
-    var maps = cm.state.keyMaps.slice(0);\n
-    if (cm.options.extraKeys) maps.push(cm.options.extraKeys);\n
-    maps.push(cm.options.keyMap);\n
-    return maps;\n
+  function lookupKeyForEditor(cm, name, handle) {\n
+    for (var i = 0; i < cm.state.keyMaps.length; i++) {\n
+      var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);\n
+      if (result) return result;\n
+    }\n
+    return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))\n
+      || lookupKey(name, cm.options.keyMap, handle, cm);\n
   }\n
 \n
-  var maybeTransition;\n
-  function handleKeyBinding(cm, e) {\n
-    // Handle auto keymap transitions\n
-    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;\n
-    clearTimeout(maybeTransition);\n
-    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {\n
-      if (getKeyMap(cm.options.keyMap) == startMap) {\n
-        cm.options.keyMap = (next.call ? next.call(null, cm) : next);\n
-        keyMapChanged(cm);\n
-      }\n
-    }, 50);\n
+  var stopSeq = new Delayed;\n
+  function dispatchKey(cm, name, e, handle) {\n
+    var seq = cm.state.keySeq;\n
+    if (seq) {\n
+      if (isModifierKey(name)) return "handled";\n
+      stopSeq.set(50, function() {\n
+        if (cm.state.keySeq == seq) {\n
+          cm.state.keySeq = null;\n
+          resetInput(cm);\n
+        }\n
+      });\n
+      name = seq + " " + name;\n
+    }\n
+    var result = lookupKeyForEditor(cm, name, handle);\n
 \n
-    var name = keyName(e, true), handled = false;\n
-    if (!name) return false;\n
-    var keymaps = allKeyMaps(cm);\n
+    if (result == "multi")\n
+      cm.state.keySeq = name;\n
+    if (result == "handled")\n
+      signalLater(cm, "keyHandled", cm, name, e);\n
 \n
-    if (e.shiftKey) {\n
-      // First try to resolve full name (including \'Shift-\'). Failing\n
-      // that, see if there is a cursor-motion command (starting with\n
-      // \'go\') bound to the keyname without \'Shift-\'.\n
-      handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})\n
-             || lookupKey(name, keymaps, function(b) {\n
-                  if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)\n
-                    return doHandleBinding(cm, b);\n
-                });\n
-    } else {\n
-      handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });\n
+    if (result == "handled" || result == "multi") {\n
+      e_preventDefault(e);\n
+      restartBlink(cm);\n
     }\n
 \n
-    if (handled) {\n
+    if (seq && !result && /\\\'$/.test(name)) {\n
       e_preventDefault(e);\n
-      restartBlink(cm);\n
-      if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }\n
-      signalLater(cm, "keyHandled", cm, name, e);\n
+      return true;\n
     }\n
-    return handled;\n
+    return !!result;\n
   }\n
 \n
-  function handleCharBinding(cm, e, ch) {\n
-    var handled = lookupKey("\'" + ch + "\'", allKeyMaps(cm),\n
-                            function(b) { return doHandleBinding(cm, b, true); });\n
-    if (handled) {\n
-      e_preventDefault(e);\n
-      restartBlink(cm);\n
-      signalLater(cm, "keyHandled", cm, "\'" + ch + "\'", e);\n
+  // Handle a key from the keydown event.\n
+  function handleKeyBinding(cm, e) {\n
+    var name = keyName(e, true);\n
+    if (!name) return false;\n
+\n
+    if (e.shiftKey && !cm.state.keySeq) {\n
+      // First try to resolve full name (including \'Shift-\'). Failing\n
+      // that, see if there is a cursor-motion command (starting with\n
+      // \'go\') bound to the keyname without \'Shift-\'.\n
+      return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})\n
+          || dispatchKey(cm, name, e, function(b) {\n
+               if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)\n
+                 return doHandleBinding(cm, b);\n
+             });\n
+    } else {\n
+      return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });\n
     }\n
-    return handled;\n
   }\n
 \n
-  function onKeyUp(e) {\n
-    var cm = this;\n
-    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;\n
-    if (e.keyCode == 16) cm.doc.sel.shift = false;\n
+  // Handle a key from the keypress event\n
+  function handleCharBinding(cm, e, ch) {\n
+    return dispatchKey(cm, "\'" + ch + "\'", e,\n
+                       function(b) { return doHandleBinding(cm, b, true); });\n
   }\n
 \n
   var lastStoppedKey = null;\n
   function onKeyDown(e) {\n
     var cm = this;\n
     ensureFocus(cm);\n
-    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;\n
-    if (old_ie && e.keyCode == 27) e.returnValue = false;\n
-    var code = e.keyCode;\n
+    if (signalDOMEvent(cm, e)) return;\n
     // IE does strange things with escape.\n
-    cm.doc.sel.shift = code == 16 || e.shiftKey;\n
-    // First give onKeyEvent option a chance to handle this.\n
+    if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;\n
+    var code = e.keyCode;\n
+    cm.display.shift = code == 16 || e.shiftKey;\n
     var handled = handleKeyBinding(cm, e);\n
-    if (opera) {\n
+    if (presto) {\n
       lastStoppedKey = handled ? code : null;\n
       // Opera has no cut event... we try to at least catch the key combo\n
       if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))\n
-        cm.replaceSelection("");\n
+        cm.replaceSelection("", null, "cut");\n
+    }\n
+\n
+    // Turn mouse into crosshair when Alt is held on Mac.\n
+    if (code == 18 && !/\\bCodeMirror-crosshair\\b/.test(cm.display.lineDiv.className))\n
+      showCrossHair(cm);\n
+  }\n
+\n
+  function showCrossHair(cm) {\n
+    var lineDiv = cm.display.lineDiv;\n
+    addClass(lineDiv, "CodeMirror-crosshair");\n
+\n
+    function up(e) {\n
+      if (e.keyCode == 18 || !e.altKey) {\n
+        rmClass(lineDiv, "CodeMirror-crosshair");\n
+        off(document, "keyup", up);\n
+        off(document, "mouseover", up);\n
+      }\n
     }\n
+    on(document, "keyup", up);\n
+    on(document, "mouseover", up);\n
+  }\n
+\n
+  function onKeyUp(e) {\n
+    if (e.keyCode == 16) this.doc.sel.shift = false;\n
+    signalDOMEvent(this, e);\n
   }\n
 \n
   function onKeyPress(e) {\n
     var cm = this;\n
-    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;\n
+    if (signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;\n
     var keyCode = e.keyCode, charCode = e.charCode;\n
-    if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}\n
-    if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;\n
+    if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}\n
+    if (((presto && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;\n
     var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n
     if (handleCharBinding(cm, e, ch)) return;\n
-    if (ie && !ie_lt9) cm.display.inputHasSelection = null;\n
+    if (ie && ie_version >= 9) cm.display.inputHasSelection = null;\n
     fastPoll(cm);\n
   }\n
+\n
+  // FOCUS/BLUR EVENTS\n
 \n
   function onFocus(cm) {\n
     if (cm.options.readOnly == "nocursor") return;\n
     if (!cm.state.focused) {\n
       signal(cm, "focus", cm);\n
       cm.state.focused = true;\n
-      if (cm.display.wrapper.className.search(/\\bCodeMirror-focused\\b/) == -1)\n
-        cm.display.wrapper.className += " CodeMirror-focused";\n
-      if (!cm.curOp) {\n
-        resetInput(cm, true);\n
+      addClass(cm.display.wrapper, "CodeMirror-focused");\n
+      // The prevInput test prevents this from firing when a context\n
+      // menu is closed (since the resetInput would kill the\n
+      // select-all detection hack)\n
+      if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {\n
+        resetInput(cm);\n
         if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730\n
       }\n
     }\n
@@ -2257,66 +3469,83 @@ window.CodeMirror = (function() {\n
     if (cm.state.focused) {\n
       signal(cm, "blur", cm);\n
       cm.state.focused = false;\n
-      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");\n
+      rmClass(cm.display.wrapper, "CodeMirror-focused");\n
     }\n
     clearInterval(cm.display.blinker);\n
-    setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);\n
+    setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);\n
   }\n
 \n
-  var detectingSelectAll;\n
+  // CONTEXT MENU HANDLING\n
+\n
+  // To make the context menu work, we need to briefly unhide the\n
+  // textarea (making it as unobtrusive as possible) to let the\n
+  // right-click take effect on it.\n
   function onContextMenu(cm, e) {\n
     if (signalDOMEvent(cm, e, "contextmenu")) return;\n
-    var display = cm.display, sel = cm.doc.sel;\n
+    var display = cm.display;\n
     if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;\n
 \n
     var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;\n
-    if (!pos || opera) return; // Opera is difficult.\n
+    if (!pos || presto) return; // Opera is difficult.\n
 \n
     // Reset the current text selection only if the click is done outside of the selection\n
     // and \'resetSelectionOnContextMenu\' option is true.\n
     var reset = cm.options.resetSelectionOnContextMenu;\n
-    if (reset && (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)))\n
-      operation(cm, setSelection)(cm.doc, pos, pos);\n
+    if (reset && cm.doc.sel.contains(pos) == -1)\n
+      operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);\n
 \n
     var oldCSS = display.input.style.cssText;\n
     display.inputDiv.style.position = "absolute";\n
     display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +\n
-      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: transparent; outline: none;" +\n
-      "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";\n
+      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +\n
+      (ie ? "rgba(255, 255, 255, .05)" : "transparent") +\n
+      "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";\n
+    if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)\n
     focusInput(cm);\n
-    resetInput(cm, true);\n
+    if (webkit) window.scrollTo(null, oldScrollY);\n
+    resetInput(cm);\n
     // Adds "Select all" to context menu in FF\n
-    if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";\n
-\n
+    if (!cm.somethingSelected()) display.input.value = display.prevInput = " ";\n
+    display.contextMenuPending = true;\n
+    display.selForContextMenu = cm.doc.sel;\n
+    clearTimeout(display.detectingSelectAll);\n
+\n
+    // Select-all will be greyed out if there\'s nothing to select, so\n
+    // this adds a zero-width space so that we can later check whether\n
+    // it got selected.\n
     function prepareSelectAllHack() {\n
       if (display.input.selectionStart != null) {\n
-        var extval = display.input.value = "\\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value);\n
-        display.prevInput = "\\u200b";\n
+        var selected = cm.somethingSelected();\n
+        var extval = display.input.value = "\\u200b" + (selected ? display.input.value : "");\n
+        display.prevInput = selected ? "" : "\\u200b";\n
         display.input.selectionStart = 1; display.input.selectionEnd = extval.length;\n
+        // Re-set this, in case some other handler touched the\n
+        // selection in the meantime.\n
+        display.selForContextMenu = cm.doc.sel;\n
       }\n
     }\n
     function rehide() {\n
+      display.contextMenuPending = false;\n
       display.inputDiv.style.position = "relative";\n
       display.input.style.cssText = oldCSS;\n
-      if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;\n
+      if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);\n
       slowPoll(cm);\n
 \n
       // Try to detect the user choosing select-all\n
       if (display.input.selectionStart != null) {\n
-        if (!ie || ie_lt9) prepareSelectAllHack();\n
-        clearTimeout(detectingSelectAll);\n
-        var i = 0, poll = function(){\n
-          if (display.prevInput == "\\u200b" && display.input.selectionStart == 0)\n
+        if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();\n
+        var i = 0, poll = function() {\n
+          if (display.selForContextMenu == cm.doc.sel && display.input.selectionStart == 0)\n
             operation(cm, commands.selectAll)(cm);\n
-          else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);\n
+          else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);\n
           else resetInput(cm);\n
         };\n
-        detectingSelectAll = setTimeout(poll, 200);\n
+        display.detectingSelectAll = setTimeout(poll, 200);\n
       }\n
     }\n
 \n
-    if (ie && !ie_lt9) prepareSelectAllHack();\n
-    if (captureMiddleClick) {\n
+    if (ie && ie_version >= 9) prepareSelectAllHack();\n
+    if (captureRightClick) {\n
       e_stop(e);\n
       var mouseup = function() {\n
         off(window, "mouseup", mouseup);\n
@@ -2327,55 +3556,72 @@ window.CodeMirror = (function() {\n
       setTimeout(rehide, 50);\n
     }\n
   }\n
+\n
+  function contextMenuInGutter(cm, e) {\n
+    if (!hasHandler(cm, "gutterContextMenu")) return false;\n
+    return gutterEvent(cm, e, "gutterContextMenu", false, signal);\n
+  }\n
 \n
   // UPDATING\n
 \n
+  // Compute the position of the end of a change (its \'to\' property\n
+  // refers to the pre-change end).\n
   var changeEnd = CodeMirror.changeEnd = function(change) {\n
     if (!change.text) return change.to;\n
     return Pos(change.from.line + change.text.length - 1,\n
                lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));\n
   };\n
 \n
-  // Make sure a position will be valid after the given change.\n
-  function clipPostChange(doc, change, pos) {\n
-    if (!posLess(change.from, pos)) return clipPos(doc, pos);\n
-    var diff = (change.text.length - 1) - (change.to.line - change.from.line);\n
-    if (pos.line > change.to.line + diff) {\n
-      var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;\n
-      if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);\n
-      return clipToLen(pos, getLine(doc, preLine).text.length);\n
-    }\n
-    if (pos.line == change.to.line + diff)\n
-      return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +\n
-                       getLine(doc, change.to.line).text.length - change.to.ch);\n
-    var inside = pos.line - change.from.line;\n
-    return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));\n
-  }\n
-\n
-  // Hint can be null|"end"|"start"|"around"|{anchor,head}\n
-  function computeSelAfterChange(doc, change, hint) {\n
-    if (hint && typeof hint == "object") // Assumed to be {anchor, head} object\n
-      return {anchor: clipPostChange(doc, change, hint.anchor),\n
-              head: clipPostChange(doc, change, hint.head)};\n
-\n
-    if (hint == "start") return {anchor: change.from, head: change.from};\n
-\n
-    var end = changeEnd(change);\n
-    if (hint == "around") return {anchor: change.from, head: end};\n
-    if (hint == "end") return {anchor: end, head: end};\n
-\n
-    // hint is null, leave the selection alone as much as possible\n
-    var adjustPos = function(pos) {\n
-      if (posLess(pos, change.from)) return pos;\n
-      if (!posLess(change.to, pos)) return end;\n
-\n
-      var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;\n
-      if (pos.line == change.to.line) ch += end.ch - change.to.ch;\n
-      return Pos(line, ch);\n
-    };\n
-    return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};\n
+  // Adjust a position to refer to the post-change position of the\n
+  // same text, or the end of the change if the change covers it.\n
+  function adjustForChange(pos, change) {\n
+    if (cmp(pos, change.from) < 0) return pos;\n
+    if (cmp(pos, change.to) <= 0) return changeEnd(change);\n
+\n
+    var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;\n
+    if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;\n
+    return Pos(line, ch);\n
+  }\n
+\n
+  function computeSelAfterChange(doc, change) {\n
+    var out = [];\n
+    for (var i = 0; i < doc.sel.ranges.length; i++) {\n
+      var range = doc.sel.ranges[i];\n
+      out.push(new Range(adjustForChange(range.anchor, change),\n
+                         adjustForChange(range.head, change)));\n
+    }\n
+    return normalizeSelection(out, doc.sel.primIndex);\n
+  }\n
+\n
+  function offsetPos(pos, old, nw) {\n
+    if (pos.line == old.line)\n
+      return Pos(nw.line, pos.ch - old.ch + nw.ch);\n
+    else\n
+      return Pos(nw.line + (pos.line - old.line), pos.ch);\n
+  }\n
+\n
+  // Used by replaceSelections to allow moving the selection to the\n
+  // start or around the replaced test. Hint may be "start" or "around".\n
+  function computeReplacedSel(doc, changes, hint) {\n
+    var out = [];\n
+    var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;\n
+    for (var i = 0; i < changes.length; i++) {\n
+      var change = changes[i];\n
+      var from = offsetPos(change.from, oldPrev, newPrev);\n
+      var to = offsetPos(changeEnd(change), oldPrev, newPrev);\n
+      oldPrev = change.to;\n
+      newPrev = to;\n
+      if (hint == "around") {\n
+        var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;\n
+        out[i] = new Range(inv ? to : from, inv ? from : to);\n
+      } else {\n
+        out[i] = new Range(from, from);\n
+      }\n
+    }\n
+    return new Selection(out, doc.sel.primIndex);\n
   }\n
 \n
+  // Allow "beforeChange" event handlers to influence a change\n
   function filterChange(doc, change, update) {\n
     var obj = {\n
       canceled: false,\n
@@ -2398,11 +3644,11 @@ window.CodeMirror = (function() {\n
     return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};\n
   }\n
 \n
-  // Replace the range from from to to by the strings in replacement.\n
-  // change is a {from, to, text [, origin]} object\n
-  function makeChange(doc, change, selUpdate, ignoreReadOnly) {\n
+  // Apply a change to a document, and add it to the document\'s\n
+  // history, and propagating it to all linked documents.\n
+  function makeChange(doc, change, ignoreReadOnly) {\n
     if (doc.cm) {\n
-      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);\n
+      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);\n
       if (doc.cm.state.suppressEdits) return;\n
     }\n
 \n
@@ -2415,19 +3661,17 @@ window.CodeMirror = (function() {\n
     // of read-only spans in its range.\n
     var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);\n
     if (split) {\n
-      for (var i = split.length - 1; i >= 1; --i)\n
-        makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});\n
-      if (split.length)\n
-        makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);\n
+      for (var i = split.length - 1; i >= 0; --i)\n
+        makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});\n
     } else {\n
-      makeChangeNoReadonly(doc, change, selUpdate);\n
+      makeChangeInner(doc, change);\n
     }\n
   }\n
 \n
-  function makeChangeNoReadonly(doc, change, selUpdate) {\n
-    if (change.text.length == 1 && change.text[0] == "" && posEq(change.from, change.to)) return;\n
-    var selAfter = computeSelAfterChange(doc, change, selUpdate);\n
-    addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);\n
+  function makeChangeInner(doc, change) {\n
+    if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;\n
+    var selAfter = computeSelAfterChange(doc, change);\n
+    addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);\n
 \n
     makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));\n
     var rebased = [];\n
@@ -2441,17 +3685,41 @@ window.CodeMirror = (function() {\n
     });\n
   }\n
 \n
-  function makeChangeFromHistory(doc, type) {\n
+  // Revert a change stored in a document\'s history.\n
+  function makeChangeFromHistory(doc, type, allowSelectionOnly) {\n
     if (doc.cm && doc.cm.state.suppressEdits) return;\n
 \n
-    var hist = doc.history;\n
-    var event = (type == "undo" ? hist.done : hist.undone).pop();\n
-    if (!event) return;\n
+    var hist = doc.history, event, selAfter = doc.sel;\n
+    var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;\n
+\n
+    // Verify that there is a useable event (so that ctrl-z won\'t\n
+    // needlessly clear selection events)\n
+    for (var i = 0; i < source.length; i++) {\n
+      event = source[i];\n
+      if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)\n
+        break;\n
+    }\n
+    if (i == source.length) return;\n
+    hist.lastOrigin = hist.lastSelOrigin = null;\n
+\n
+    for (;;) {\n
+      event = source.pop();\n
+      if (event.ranges) {\n
+        pushSelectionToHistory(event, dest);\n
+        if (allowSelectionOnly && !event.equals(doc.sel)) {\n
+          setSelection(doc, event, {clearRedo: false});\n
+          return;\n
+        }\n
+        selAfter = event;\n
+      }\n
+      else break;\n
+    }\n
 \n
-    var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,\n
-                anchorAfter: event.anchorBefore, headAfter: event.headBefore,\n
-                generation: hist.generation};\n
-    (type == "undo" ? hist.undone : hist.done).push(anti);\n
+    // Build up a reverse change object to add to the opposite history\n
+    // stack (redo when undoing, and vice versa).\n
+    var antiChanges = [];\n
+    pushSelectionToHistory(selAfter, dest);\n
+    dest.push({changes: antiChanges, generation: hist.generation});\n
     hist.generation = event.generation || ++hist.maxGeneration;\n
 \n
     var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");\n
@@ -2460,17 +3728,18 @@ window.CodeMirror = (function() {\n
       var change = event.changes[i];\n
       change.origin = type;\n
       if (filter && !filterChange(doc, change, false)) {\n
-        (type == "undo" ? hist.done : hist.undone).length = 0;\n
+        source.length = 0;\n
         return;\n
       }\n
 \n
-      anti.changes.push(historyChangeFromChange(doc, change));\n
+      antiChanges.push(historyChangeFromChange(doc, change));\n
 \n
-      var after = i ? computeSelAfterChange(doc, change, null)\n
-                    : {anchor: event.anchorBefore, head: event.headBefore};\n
+      var after = i ? computeSelAfterChange(doc, change) : lst(source);\n
       makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));\n
+      if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});\n
       var rebased = [];\n
 \n
+      // Propagate to the linked documents\n
       linkedDocs(doc, function(doc, sharedHist) {\n
         if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n
           rebaseHist(doc.history, change);\n
@@ -2481,14 +3750,24 @@ window.CodeMirror = (function() {\n
     }\n
   }\n
 \n
+  // Sub-views need their line numbers shifted when text is added\n
+  // above or below them in the parent document.\n
   function shiftDoc(doc, distance) {\n
-    function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}\n
+    if (distance == 0) return;\n
     doc.first += distance;\n
-    if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);\n
-    doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);\n
-    doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);\n
+    doc.sel = new Selection(map(doc.sel.ranges, function(range) {\n
+      return new Range(Pos(range.anchor.line + distance, range.anchor.ch),\n
+                       Pos(range.head.line + distance, range.head.ch));\n
+    }), doc.sel.primIndex);\n
+    if (doc.cm) {\n
+      regChange(doc.cm, doc.first, doc.first - distance, distance);\n
+      for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)\n
+        regLineChange(doc.cm, l, "gutter");\n
+    }\n
   }\n
 \n
+  // More lower-level change function, handling only a single document\n
+  // (not linked ones).\n
   function makeChangeSingleDoc(doc, change, selAfter, spans) {\n
     if (doc.cm && !doc.cm.curOp)\n
       return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);\n
@@ -2513,229 +3792,93 @@ window.CodeMirror = (function() {\n
     }\n
 \n
     change.removed = getBetween(doc, change.from, change.to);\n
-\n
-    if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);\n
-    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);\n
-    else updateDoc(doc, change, spans, selAfter);\n
-  }\n
-\n
-  function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {\n
-    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;\n
-\n
-    var recomputeMaxLength = false, checkWidthStart = from.line;\n
-    if (!cm.options.lineWrapping) {\n
-      checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));\n
-      doc.iter(checkWidthStart, to.line + 1, function(line) {\n
-        if (line == display.maxLine) {\n
-          recomputeMaxLength = true;\n
-          return true;\n
-        }\n
-      });\n
-    }\n
-\n
-    if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))\n
-      cm.curOp.cursorActivity = true;\n
-\n
-    updateDoc(doc, change, spans, selAfter, estimateHeight(cm));\n
-\n
-    if (!cm.options.lineWrapping) {\n
-      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {\n
-        var len = lineLength(doc, line);\n
-        if (len > display.maxLineLength) {\n
-          display.maxLine = line;\n
-          display.maxLineLength = len;\n
-          display.maxLineChanged = true;\n
-          recomputeMaxLength = false;\n
-        }\n
-      });\n
-      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;\n
-    }\n
-\n
-    // Adjust frontier, schedule worker\n
-    doc.frontier = Math.min(doc.frontier, from.line);\n
-    startWorker(cm, 400);\n
-\n
-    var lendiff = change.text.length - (to.line - from.line) - 1;\n
-    // Remember that these lines changed, for updating the display\n
-    regChange(cm, from.line, to.line + 1, lendiff);\n
-\n
-    if (hasHandler(cm, "change")) {\n
-      var changeObj = {from: from, to: to,\n
-                       text: change.text,\n
-                       removed: change.removed,\n
-                       origin: change.origin};\n
-      if (cm.curOp.textChanged) {\n
-        for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}\n
-        cur.next = changeObj;\n
-      } else cm.curOp.textChanged = changeObj;\n
-    }\n
-  }\n
-\n
-  function replaceRange(doc, code, from, to, origin) {\n
-    if (!to) to = from;\n
-    if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }\n
-    if (typeof code == "string") code = splitLines(code);\n
-    makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);\n
-  }\n
-\n
-  // POSITION OBJECT\n
-\n
-  function Pos(line, ch) {\n
-    if (!(this instanceof Pos)) return new Pos(line, ch);\n
-    this.line = line; this.ch = ch;\n
-  }\n
-  CodeMirror.Pos = Pos;\n
-\n
-  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}\n
-  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}\n
-  function cmp(a, b) {return a.line - b.line || a.ch - b.ch;}\n
-  function copyPos(x) {return Pos(x.line, x.ch);}\n
-\n
-  // SELECTION\n
-\n
-  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}\n
-  function clipPos(doc, pos) {\n
-    if (pos.line < doc.first) return Pos(doc.first, 0);\n
-    var last = doc.first + doc.size - 1;\n
-    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);\n
-    return clipToLen(pos, getLine(doc, pos.line).text.length);\n
-  }\n
-  function clipToLen(pos, linelen) {\n
-    var ch = pos.ch;\n
-    if (ch == null || ch > linelen) return Pos(pos.line, linelen);\n
-    else if (ch < 0) return Pos(pos.line, 0);\n
-    else return pos;\n
-  }\n
-  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}\n
-\n
-  // If shift is held, this will move the selection anchor. Otherwise,\n
-  // it\'ll set the whole selection.\n
-  function extendSelection(doc, pos, other, bias) {\n
-    if (doc.sel.shift || doc.sel.extend) {\n
-      var anchor = doc.sel.anchor;\n
-      if (other) {\n
-        var posBefore = posLess(pos, anchor);\n
-        if (posBefore != posLess(other, anchor)) {\n
-          anchor = pos;\n
-          pos = other;\n
-        } else if (posBefore != posLess(pos, other)) {\n
-          pos = other;\n
-        }\n
-      }\n
-      setSelection(doc, anchor, pos, bias);\n
-    } else {\n
-      setSelection(doc, pos, other || pos, bias);\n
-    }\n
-    if (doc.cm) doc.cm.curOp.userSelChange = true;\n
-  }\n
-\n
-  function filterSelectionChange(doc, anchor, head) {\n
-    var obj = {anchor: anchor, head: head};\n
-    signal(doc, "beforeSelectionChange", doc, obj);\n
-    if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);\n
-    obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);\n
-    return obj;\n
+\n
+    if (!selAfter) selAfter = computeSelAfterChange(doc, change);\n
+    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);\n
+    else updateDoc(doc, change, spans);\n
+    setSelectionNoUndo(doc, selAfter, sel_dontScroll);\n
   }\n
 \n
-  // Update the selection. Last two args are only used by\n
-  // updateDoc, since they have to be expressed in the line\n
-  // numbers before the update.\n
-  function setSelection(doc, anchor, head, bias, checkAtomic) {\n
-    if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {\n
-      var filtered = filterSelectionChange(doc, anchor, head);\n
-      head = filtered.head;\n
-      anchor = filtered.anchor;\n
+  // Handle the interaction of a change to a document with the editor\n
+  // that this document is part of.\n
+  function makeChangeSingleDocInEditor(cm, change, spans) {\n
+    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;\n
+\n
+    var recomputeMaxLength = false, checkWidthStart = from.line;\n
+    if (!cm.options.lineWrapping) {\n
+      checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));\n
+      doc.iter(checkWidthStart, to.line + 1, function(line) {\n
+        if (line == display.maxLine) {\n
+          recomputeMaxLength = true;\n
+          return true;\n
+        }\n
+      });\n
     }\n
 \n
-    var sel = doc.sel;\n
-    sel.goalColumn = null;\n
-    if (bias == null) bias = posLess(head, sel.head) ? -1 : 1;\n
-    // Skip over atomic spans.\n
-    if (checkAtomic || !posEq(anchor, sel.anchor))\n
-      anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");\n
-    if (checkAtomic || !posEq(head, sel.head))\n
-      head = skipAtomic(doc, head, bias, checkAtomic != "push");\n
+    if (doc.sel.contains(change.from, change.to) > -1)\n
+      signalCursorActivity(cm);\n
 \n
-    if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;\n
+    updateDoc(doc, change, spans, estimateHeight(cm));\n
 \n
-    sel.anchor = anchor; sel.head = head;\n
-    var inv = posLess(head, anchor);\n
-    sel.from = inv ? head : anchor;\n
-    sel.to = inv ? anchor : head;\n
+    if (!cm.options.lineWrapping) {\n
+      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {\n
+        var len = lineLength(line);\n
+        if (len > display.maxLineLength) {\n
+          display.maxLine = line;\n
+          display.maxLineLength = len;\n
+          display.maxLineChanged = true;\n
+          recomputeMaxLength = false;\n
+        }\n
+      });\n
+      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;\n
+    }\n
 \n
-    if (doc.cm)\n
-      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =\n
-        doc.cm.curOp.cursorActivity = true;\n
+    // Adjust frontier, schedule worker\n
+    doc.frontier = Math.min(doc.frontier, from.line);\n
+    startWorker(cm, 400);\n
 \n
-    signalLater(doc, "cursorActivity", doc);\n
+    var lendiff = change.text.length - (to.line - from.line) - 1;\n
+    // Remember that these lines changed, for updating the display\n
+    if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))\n
+      regLineChange(cm, from.line, "text");\n
+    else\n
+      regChange(cm, from.line, to.line + 1, lendiff);\n
+\n
+    var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");\n
+    if (changeHandler || changesHandler) {\n
+      var obj = {\n
+        from: from, to: to,\n
+        text: change.text,\n
+        removed: change.removed,\n
+        origin: change.origin\n
+      };\n
+      if (changeHandler) signalLater(cm, "change", cm, obj);\n
+      if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);\n
+    }\n
+    cm.display.selForContextMenu = null;\n
   }\n
 \n
-  function reCheckSelection(cm) {\n
-    setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");\n
+  function replaceRange(doc, code, from, to, origin) {\n
+    if (!to) to = from;\n
+    if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }\n
+    if (typeof code == "string") code = splitLines(code);\n
+    makeChange(doc, {from: from, to: to, text: code, origin: origin});\n
   }\n
 \n
-  function skipAtomic(doc, pos, bias, mayClear) {\n
-    var flipped = false, curPos = pos;\n
-    var dir = bias || 1;\n
-    doc.cantEdit = false;\n
-    search: for (;;) {\n
-      var line = getLine(doc, curPos.line);\n
-      if (line.markedSpans) {\n
-        for (var i = 0; i < line.markedSpans.length; ++i) {\n
-          var sp = line.markedSpans[i], m = sp.marker;\n
-          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&\n
-              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {\n
-            if (mayClear) {\n
-              signal(m, "beforeCursorEnter");\n
-              if (m.explicitlyCleared) {\n
-                if (!line.markedSpans) break;\n
-                else {--i; continue;}\n
-              }\n
-            }\n
-            if (!m.atomic) continue;\n
-            var newPos = m.find()[dir < 0 ? "from" : "to"];\n
-            if (posEq(newPos, curPos)) {\n
-              newPos.ch += dir;\n
-              if (newPos.ch < 0) {\n
-                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));\n
-                else newPos = null;\n
-              } else if (newPos.ch > line.text.length) {\n
-                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);\n
-                else newPos = null;\n
-              }\n
-              if (!newPos) {\n
-                if (flipped) {\n
-                  // Driven in a corner -- no valid cursor position found at all\n
-                  // -- try again *with* clearing, if we didn\'t already\n
-                  if (!mayClear) return skipAtomic(doc, pos, bias, true);\n
-                  // Otherwise, turn off editing until further notice, and return the start of the doc\n
-                  doc.cantEdit = true;\n
-                  return Pos(doc.first, 0);\n
-                }\n
-                flipped = true; newPos = pos; dir = -dir;\n
-              }\n
-            }\n
-            curPos = newPos;\n
-            continue search;\n
-          }\n
-        }\n
-      }\n
-      return curPos;\n
-    }\n
-  }\n
+  // SCROLLING THINGS INTO VIEW\n
 \n
-  // SCROLLING\n
+  // If an editor sits on the top or bottom of the window, partially\n
+  // scrolled out of view, this ensures that the cursor is visible.\n
+  function maybeScrollWindow(cm, coords) {\n
+    if (signalDOMEvent(cm, "scrollCursorIntoView")) return;\n
 \n
-  function scrollCursorIntoView(cm) {\n
-    var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin);\n
-    if (!cm.state.focused) return;\n
-    var display = cm.display, box = getRect(display.sizer), doScroll = null;\n
+    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;\n
     if (coords.top + box.top < 0) doScroll = true;\n
     else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;\n
     if (doScroll != null && !phantom) {\n
       var scrollNode = elt("div", "\\u200b", null, "position: absolute; top: " +\n
-                           (coords.top - display.viewOffset) + "px; height: " +\n
-                           (coords.bottom - coords.top + scrollerCutOff) + "px; left: " +\n
+                           (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +\n
+                           (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +\n
                            coords.left + "px; width: 2px;");\n
       cm.display.lineSpace.appendChild(scrollNode);\n
       scrollNode.scrollIntoView(doScroll);\n
@@ -2743,9 +3886,12 @@ window.CodeMirror = (function() {\n
     }\n
   }\n
 \n
+  // Scroll a given position into view (immediately), verifying that\n
+  // it actually became visible (as line heights are accurately\n
+  // measured, the position of something may \'drift\' during drawing).\n
   function scrollPosIntoView(cm, pos, end, margin) {\n
     if (margin == null) margin = 0;\n
-    for (;;) {\n
+    for (var limit = 0; limit < 5; limit++) {\n
       var changed = false, coords = cursorCoords(cm, pos);\n
       var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);\n
       var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),\n
@@ -2761,20 +3907,28 @@ window.CodeMirror = (function() {\n
         setScrollLeft(cm, scrollPos.scrollLeft);\n
         if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;\n
       }\n
-      if (!changed) return coords;\n
+      if (!changed) break;\n
     }\n
+    return coords;\n
   }\n
 \n
+  // Scroll a given set of coordinates into view (immediately).\n
   function scrollIntoView(cm, x1, y1, x2, y2) {\n
     var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);\n
     if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);\n
     if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);\n
   }\n
 \n
+  // Calculate a new scroll position needed to scroll the given\n
+  // rectangle into view. Returns an object with scrollTop and\n
+  // scrollLeft properties. When these are undefined, the\n
+  // vertical/horizontal position does not need to be adjusted.\n
   function calculateScrollPos(cm, x1, y1, x2, y2) {\n
     var display = cm.display, snapMargin = textHeight(cm.display);\n
     if (y1 < 0) y1 = 0;\n
-    var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};\n
+    var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;\n
+    var screen = displayHeight(cm), result = {};\n
+    if (y2 - y1 > screen) y2 = y1 + screen;\n
     var docBottom = cm.doc.height + paddingVert(display);\n
     var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;\n
     if (y1 < screentop) {\n
@@ -2784,38 +3938,72 @@ window.CodeMirror = (function() {\n
       if (newTop != screentop) result.scrollTop = newTop;\n
     }\n
 \n
-    var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;\n
-    x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;\n
-    var gutterw = display.gutters.offsetWidth;\n
-    var atLeft = x1 < gutterw + 10;\n
-    if (x1 < screenleft + gutterw || atLeft) {\n
-      if (atLeft) x1 = 0;\n
-      result.scrollLeft = Math.max(0, x1 - 10 - gutterw);\n
-    } else if (x2 > screenw + screenleft - 3) {\n
-      result.scrollLeft = x2 + 10 - screenw;\n
-    }\n
+    var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;\n
+    var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);\n
+    var tooWide = x2 - x1 > screenw;\n
+    if (tooWide) x2 = x1 + screenw;\n
+    if (x1 < 10)\n
+      result.scrollLeft = 0;\n
+    else if (x1 < screenleft)\n
+      result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));\n
+    else if (x2 > screenw + screenleft - 3)\n
+      result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;\n
     return result;\n
   }\n
 \n
-  function updateScrollPos(cm, left, top) {\n
-    cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,\n
-                                scrollTop: top == null ? cm.doc.scrollTop : top};\n
+  // Store a relative adjustment to the scroll position in the current\n
+  // operation (to be applied when the operation finishes).\n
+  function addToScrollPos(cm, left, top) {\n
+    if (left != null || top != null) resolveScrollToPos(cm);\n
+    if (left != null)\n
+      cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;\n
+    if (top != null)\n
+      cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;\n
+  }\n
+\n
+  // Make sure that at the end of the operation the current cursor is\n
+  // shown.\n
+  function ensureCursorVisible(cm) {\n
+    resolveScrollToPos(cm);\n
+    var cur = cm.getCursor(), from = cur, to = cur;\n
+    if (!cm.options.lineWrapping) {\n
+      from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;\n
+      to = Pos(cur.line, cur.ch + 1);\n
+    }\n
+    cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};\n
   }\n
 \n
-  function addToScrollPos(cm, left, top) {\n
-    var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});\n
-    var scroll = cm.display.scroller;\n
-    pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));\n
-    pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));\n
+  // When an operation has its scrollToPos property set, and another\n
+  // scroll action is applied before the end of the operation, this\n
+  // \'simulates\' scrolling that position into view in a cheap way, so\n
+  // that the effect of intermediate scroll commands is not ignored.\n
+  function resolveScrollToPos(cm) {\n
+    var range = cm.curOp.scrollToPos;\n
+    if (range) {\n
+      cm.curOp.scrollToPos = null;\n
+      var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);\n
+      var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),\n
+                                    Math.min(from.top, to.top) - range.margin,\n
+                                    Math.max(from.right, to.right),\n
+                                    Math.max(from.bottom, to.bottom) + range.margin);\n
+      cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);\n
+    }\n
   }\n
 \n
   // API UTILITIES\n
 \n
+  // Indent the given line. The how parameter can be "smart",\n
+  // "add"/null, "subtract", or "prev". When aggressive is false\n
+  // (typically set to true for forced single-line indents), empty\n
+  // lines are not indented, and places where the mode returns Pass\n
+  // are left alone.\n
   function indentLine(cm, n, how, aggressive) {\n
     var doc = cm.doc, state;\n
     if (how == null) how = "add";\n
     if (how == "smart") {\n
-      if (!cm.doc.mode.indent) how = "prev";\n
+      // Fall back to "prev" when the mode doesn\'t have an indentation\n
+      // method.\n
+      if (!doc.mode.indent) how = "prev";\n
       else state = getStateBefore(cm, n);\n
     }\n
 \n
@@ -2827,8 +4015,8 @@ window.CodeMirror = (function() {\n
       indentation = 0;\n
       how = "not";\n
     } else if (how == "smart") {\n
-      indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n
-      if (indentation == Pass) {\n
+      indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n
+      if (indentation == Pass || indentation > 150) {\n
         if (!aggressive) return;\n
         how = "prev";\n
       }\n
@@ -2850,23 +4038,69 @@ window.CodeMirror = (function() {\n
       for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\\t";}\n
     if (pos < indentation) indentString += spaceStr(indentation - pos);\n
 \n
-    if (indentString != curSpaceString)\n
-      replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");\n
-    else if (doc.sel.head.line == n && doc.sel.head.ch < curSpaceString.length)\n
-      setSelection(doc, Pos(n, curSpaceString.length), Pos(n, curSpaceString.length), 1);\n
+    if (indentString != curSpaceString) {\n
+      replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");\n
+    } else {\n
+      // Ensure that, if the cursor was in the whitespace at the start\n
+      // of the line, it is moved to the end of that space.\n
+      for (var i = 0; i < doc.sel.ranges.length; i++) {\n
+        var range = doc.sel.ranges[i];\n
+        if (range.head.line == n && range.head.ch < curSpaceString.length) {\n
+          var pos = Pos(n, curSpaceString.length);\n
+          replaceOneSelection(doc, i, new Range(pos, pos));\n
+          break;\n
+        }\n
+      }\n
+    }\n
     line.stateAfter = null;\n
   }\n
 \n
-  function changeLine(cm, handle, op) {\n
-    var no = handle, line = handle, doc = cm.doc;\n
+  // Utility for applying a change to a line by handle or number,\n
+  // returning the number and optionally registering the line as\n
+  // changed.\n
+  function changeLine(doc, handle, changeType, op) {\n
+    var no = handle, line = handle;\n
     if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));\n
     else no = lineNo(handle);\n
     if (no == null) return null;\n
-    if (op(line, no)) regChange(cm, no, no + 1);\n
-    else return null;\n
+    if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);\n
     return line;\n
   }\n
 \n
+  // Helper for deleting text near the selection(s), used to implement\n
+  // backspace, delete, and similar functionality.\n
+  function deleteNearSelection(cm, compute) {\n
+    var ranges = cm.doc.sel.ranges, kill = [];\n
+    // Build up a set of ranges to kill first, merging overlapping\n
+    // ranges.\n
+    for (var i = 0; i < ranges.length; i++) {\n
+      var toKill = compute(ranges[i]);\n
+      while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {\n
+        var replaced = kill.pop();\n
+        if (cmp(replaced.from, toKill.from) < 0) {\n
+          toKill.from = replaced.from;\n
+          break;\n
+        }\n
+      }\n
+      kill.push(toKill);\n
+    }\n
+    // Next, remove those actual ranges.\n
+    runInOp(cm, function() {\n
+      for (var i = kill.length - 1; i >= 0; i--)\n
+        replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");\n
+      ensureCursorVisible(cm);\n
+    });\n
+  }\n
+\n
+  // Used for horizontal relative motion. Dir is -1 or 1 (left or\n
+  // right), unit can be "char", "column" (like char, but doesn\'t\n
+  // cross line boundaries), "word" (across next word), or "group" (to\n
+  // the start of next group of word or non-word-non-whitespace\n
+  // chars). The visually param controls whether, in right-to-left\n
+  // text, direction 1 means to move towards the next index in the\n
+  // string, or towards the character to the right of the current\n
+  // position. The resulting position will have a hitSide=true\n
+  // property if it reached the end of the document.\n
   function findPosH(doc, pos, dir, unit, visually) {\n
     var line = pos.line, ch = pos.ch, origDir = dir;\n
     var lineObj = getLine(doc, line);\n
@@ -2892,10 +4126,11 @@ window.CodeMirror = (function() {\n
     else if (unit == "column") moveOnce(true);\n
     else if (unit == "word" || unit == "group") {\n
       var sawType = null, group = unit == "group";\n
+      var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");\n
       for (var first = true;; first = false) {\n
         if (dir < 0 && !moveOnce(!first)) break;\n
         var cur = lineObj.text.charAt(ch) || "\\n";\n
-        var type = isWordChar(cur) ? "w"\n
+        var type = isWordChar(cur, helper) ? "w"\n
           : group && cur == "\\n" ? "n"\n
           : !group || /\\s/.test(cur) ? null\n
           : "p";\n
@@ -2914,6 +4149,9 @@ window.CodeMirror = (function() {\n
     return result;\n
   }\n
 \n
+  // For relative vertical movement. Dir may be -1 or 1. Unit can be\n
+  // "page" or "line". The resulting position will have a hitSide=true\n
+  // property if it reached the end of the document.\n
   function findPosV(cm, pos, dir, unit) {\n
     var doc = cm.doc, x = pos.left, y;\n
     if (unit == "page") {\n
@@ -2931,28 +4169,15 @@ window.CodeMirror = (function() {\n
     return target;\n
   }\n
 \n
-  function findWordAt(line, pos) {\n
-    var start = pos.ch, end = pos.ch;\n
-    if (line) {\n
-      if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;\n
-      var startChar = line.charAt(start);\n
-      var check = isWordChar(startChar) ? isWordChar\n
-        : /\\s/.test(startChar) ? function(ch) {return /\\s/.test(ch);}\n
-        : function(ch) {return !/\\s/.test(ch) && !isWordChar(ch);};\n
-      while (start > 0 && check(line.charAt(start - 1))) --start;\n
-      while (end < line.length && check(line.charAt(end))) ++end;\n
-    }\n
-    return {from: Pos(pos.line, start), to: Pos(pos.line, end)};\n
-  }\n
-\n
-  function selectLine(cm, line) {\n
-    extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));\n
-  }\n
+  // EDITOR METHODS\n
 \n
-  // PROTOTYPE\n
+  // The publicly visible API. Note that methodOp(f) means\n
+  // \'wrap f in an operation, performed on its `this` parameter\'.\n
 \n
-  // The publicly visible API. Note that operation(null, f) means\n
-  // \'wrap f in an operation, performed on its `this` parameter\'\n
+  // This is not the complete set of editor methods. Most of the\n
+  // methods defined on the Doc type are also injected into\n
+  // CodeMirror.prototype, for backwards compatibility and\n
+  // convenience.\n
 \n
   CodeMirror.prototype = {\n
     constructor: CodeMirror,\n
@@ -2970,25 +4195,25 @@ window.CodeMirror = (function() {\n
     getDoc: function() {return this.doc;},\n
 \n
     addKeyMap: function(map, bottom) {\n
-      this.state.keyMaps[bottom ? "push" : "unshift"](map);\n
+      this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));\n
     },\n
     removeKeyMap: function(map) {\n
       var maps = this.state.keyMaps;\n
       for (var i = 0; i < maps.length; ++i)\n
-        if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {\n
+        if (maps[i] == map || maps[i].name == map) {\n
           maps.splice(i, 1);\n
           return true;\n
         }\n
     },\n
 \n
-    addOverlay: operation(null, function(spec, options) {\n
+    addOverlay: methodOp(function(spec, options) {\n
       var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);\n
       if (mode.startState) throw new Error("Overlays may not be stateful.");\n
       this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});\n
       this.state.modeGen++;\n
       regChange(this);\n
     }),\n
-    removeOverlay: operation(null, function(spec) {\n
+    removeOverlay: methodOp(function(spec) {\n
       var overlays = this.state.overlays;\n
       for (var i = 0; i < overlays.length; ++i) {\n
         var cur = overlays[i].modeSpec;\n
@@ -3001,51 +4226,58 @@ window.CodeMirror = (function() {\n
       }\n
     }),\n
 \n
-    indentLine: operation(null, function(n, dir, aggressive) {\n
+    indentLine: methodOp(function(n, dir, aggressive) {\n
       if (typeof dir != "string" && typeof dir != "number") {\n
         if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";\n
         else dir = dir ? "add" : "subtract";\n
       }\n
       if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);\n
     }),\n
-    indentSelection: operation(null, function(how) {\n
-      var sel = this.doc.sel;\n
-      if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how, true);\n
-      var e = sel.to.line - (sel.to.ch ? 0 : 1);\n
-      for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);\n
+    indentSelection: methodOp(function(how) {\n
+      var ranges = this.doc.sel.ranges, end = -1;\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var range = ranges[i];\n
+        if (!range.empty()) {\n
+          var from = range.from(), to = range.to();\n
+          var start = Math.max(end, from.line);\n
+          end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;\n
+          for (var j = start; j < end; ++j)\n
+            indentLine(this, j, how);\n
+          var newRanges = this.doc.sel.ranges;\n
+          if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)\n
+            replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);\n
+        } else if (range.head.line > end) {\n
+          indentLine(this, range.head.line, how, true);\n
+          end = range.head.line;\n
+          if (i == this.doc.sel.primIndex) ensureCursorVisible(this);\n
+        }\n
+      }\n
     }),\n
 \n
     // Fetch the parser token for a given character. Useful for hacks\n
     // that want to inspect the mode state (say, for completion).\n
     getTokenAt: function(pos, precise) {\n
-      var doc = this.doc;\n
-      pos = clipPos(doc, pos);\n
-      var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;\n
-      var line = getLine(doc, pos.line);\n
-      var stream = new StringStream(line.text, this.options.tabSize);\n
-      while (stream.pos < pos.ch && !stream.eol()) {\n
-        stream.start = stream.pos;\n
-        var style = mode.token(stream, state);\n
-      }\n
-      return {start: stream.start,\n
-              end: stream.pos,\n
-              string: stream.current(),\n
-              className: style || null, // Deprecated, use \'type\' instead\n
-              type: style || null,\n
-              state: state};\n
+      return takeToken(this, pos, precise);\n
+    },\n
+\n
+    getLineTokens: function(line, precise) {\n
+      return takeToken(this, Pos(line), precise, true);\n
     },\n
 \n
     getTokenTypeAt: function(pos) {\n
       pos = clipPos(this.doc, pos);\n
       var styles = getLineStyles(this, getLine(this.doc, pos.line));\n
       var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;\n
-      if (ch == 0) return styles[2];\n
-      for (;;) {\n
+      var type;\n
+      if (ch == 0) type = styles[2];\n
+      else for (;;) {\n
         var mid = (before + after) >> 1;\n
         if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;\n
         else if (styles[mid * 2 + 1] < ch) before = mid + 1;\n
-        else return styles[mid * 2 + 2];\n
+        else { type = styles[mid * 2 + 2]; break; }\n
       }\n
+      var cut = type ? type.indexOf("cm-overlay ") : -1;\n
+      return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);\n
     },\n
 \n
     getModeAt: function(pos) {\n
@@ -3089,10 +4321,10 @@ window.CodeMirror = (function() {\n
     },\n
 \n
     cursorCoords: function(start, mode) {\n
-      var pos, sel = this.doc.sel;\n
-      if (start == null) pos = sel.head;\n
+      var pos, range = this.doc.sel.primary();\n
+      if (start == null) pos = range.head;\n
       else if (typeof start == "object") pos = clipPos(this.doc, start);\n
-      else pos = start ? sel.from : sel.to;\n
+      else pos = start ? range.from() : range.to();\n
       return cursorCoords(this, pos, mode || "page");\n
     },\n
 \n
@@ -3114,15 +4346,15 @@ window.CodeMirror = (function() {\n
       if (line < this.doc.first) line = this.doc.first;\n
       else if (line > last) { line = last; end = true; }\n
       var lineObj = getLine(this.doc, line);\n
-      return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +\n
-        (end ? lineObj.height : 0);\n
+      return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +\n
+        (end ? this.doc.height - heightAtLine(lineObj) : 0);\n
     },\n
 \n
     defaultTextHeight: function() { return textHeight(this.display); },\n
     defaultCharWidth: function() { return charWidth(this.display); },\n
 \n
-    setGutterMarker: operation(null, function(line, gutterID, value) {\n
-      return changeLine(this, line, function(line) {\n
+    setGutterMarker: methodOp(function(line, gutterID, value) {\n
+      return changeLine(this.doc, line, "gutter", function(line) {\n
         var markers = line.gutterMarkers || (line.gutterMarkers = {});\n
         markers[gutterID] = value;\n
         if (!value && isEmpty(markers)) line.gutterMarkers = null;\n
@@ -3130,45 +4362,19 @@ window.CodeMirror = (function() {\n
       });\n
     }),\n
 \n
-    clearGutter: operation(null, function(gutterID) {\n
+    clearGutter: methodOp(function(gutterID) {\n
       var cm = this, doc = cm.doc, i = doc.first;\n
       doc.iter(function(line) {\n
         if (line.gutterMarkers && line.gutterMarkers[gutterID]) {\n
           line.gutterMarkers[gutterID] = null;\n
-          regChange(cm, i, i + 1);\n
+          regLineChange(cm, i, "gutter");\n
           if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;\n
         }\n
         ++i;\n
       });\n
     }),\n
 \n
-    addLineClass: operation(null, function(handle, where, cls) {\n
-      return changeLine(this, handle, function(line) {\n
-        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";\n
-        if (!line[prop]) line[prop] = cls;\n
-        else if (new RegExp("(?:^|\\\\s)" + cls + "(?:$|\\\\s)").test(line[prop])) return false;\n
-        else line[prop] += " " + cls;\n
-        return true;\n
-      });\n
-    }),\n
-\n
-    removeLineClass: operation(null, function(handle, where, cls) {\n
-      return changeLine(this, handle, function(line) {\n
-        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";\n
-        var cur = line[prop];\n
-        if (!cur) return false;\n
-        else if (cls == null) line[prop] = null;\n
-        else {\n
-          var found = cur.match(new RegExp("(?:^|\\\\s+)" + cls + "(?:$|\\\\s+)"));\n
-          if (!found) return false;\n
-          var end = found.index + found[0].length;\n
-          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;\n
-        }\n
-        return true;\n
-      });\n
-    }),\n
-\n
-    addLineWidget: operation(null, function(handle, node, options) {\n
+    addLineWidget: methodOp(function(handle, node, options) {\n
       return addLineWidget(this, handle, node, options);\n
     }),\n
 \n
@@ -3189,13 +4395,14 @@ window.CodeMirror = (function() {\n
               widgets: line.widgets};\n
     },\n
 \n
-    getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},\n
+    getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},\n
 \n
     addWidget: function(pos, node, scroll, vert, horiz) {\n
       var display = this.display;\n
       pos = cursorCoords(this, clipPos(this.doc, pos));\n
       var top = pos.bottom, left = pos.left;\n
       node.style.position = "absolute";\n
+      node.setAttribute("cm-ignore-events", "true");\n
       display.sizer.appendChild(node);\n
       if (vert == "over") {\n
         top = pos.top;\n
@@ -3224,9 +4431,9 @@ window.CodeMirror = (function() {\n
         scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);\n
     },\n
 \n
-    triggerOnKeyDown: operation(null, onKeyDown),\n
-    triggerOnKeyPress: operation(null, onKeyPress),\n
-    triggerOnKeyUp: operation(null, onKeyUp),\n
+    triggerOnKeyDown: methodOp(onKeyDown),\n
+    triggerOnKeyPress: methodOp(onKeyPress),\n
+    triggerOnKeyUp: onKeyUp,\n
 \n
     execCommand: function(cmd) {\n
       if (commands.hasOwnProperty(cmd))\n
@@ -3243,20 +4450,25 @@ window.CodeMirror = (function() {\n
       return cur;\n
     },\n
 \n
-    moveH: operation(null, function(dir, unit) {\n
-      var sel = this.doc.sel, pos;\n
-      if (sel.shift || sel.extend || posEq(sel.from, sel.to))\n
-        pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);\n
-      else\n
-        pos = dir < 0 ? sel.from : sel.to;\n
-      extendSelection(this.doc, pos, pos, dir);\n
+    moveH: methodOp(function(dir, unit) {\n
+      var cm = this;\n
+      cm.extendSelectionsBy(function(range) {\n
+        if (cm.display.shift || cm.doc.extend || range.empty())\n
+          return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);\n
+        else\n
+          return dir < 0 ? range.from() : range.to();\n
+      }, sel_move);\n
     }),\n
 \n
-    deleteH: operation(null, function(dir, unit) {\n
-      var sel = this.doc.sel;\n
-      if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");\n
-      else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");\n
-      this.curOp.userSelChange = true;\n
+    deleteH: methodOp(function(dir, unit) {\n
+      var sel = this.doc.sel, doc = this.doc;\n
+      if (sel.somethingSelected())\n
+        doc.replaceSelection("", null, "+delete");\n
+      else\n
+        deleteNearSelection(this, function(range) {\n
+          var other = findPosH(doc, range.head, dir, unit, false);\n
+          return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};\n
+        });\n
     }),\n
 \n
     findPosV: function(from, amount, unit, goalColumn) {\n
@@ -3272,93 +4484,130 @@ window.CodeMirror = (function() {\n
       return cur;\n
     },\n
 \n
-    moveV: operation(null, function(dir, unit) {\n
-      var sel = this.doc.sel, target, goal;\n
-      if (sel.shift || sel.extend || posEq(sel.from, sel.to)) {\n
-        var pos = cursorCoords(this, sel.head, "div");\n
-        if (sel.goalColumn != null) pos.left = sel.goalColumn;\n
-        target = findPosV(this, pos, dir, unit);\n
-        if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);\n
-        goal = pos.left;\n
-      } else {\n
-        target = dir < 0 ? sel.from : sel.to;\n
-      }\n
-      extendSelection(this.doc, target, target, dir);\n
-      if (goal != null) sel.goalColumn = goal;\n
+    moveV: methodOp(function(dir, unit) {\n
+      var cm = this, doc = this.doc, goals = [];\n
+      var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();\n
+      doc.extendSelectionsBy(function(range) {\n
+        if (collapse)\n
+          return dir < 0 ? range.from() : range.to();\n
+        var headPos = cursorCoords(cm, range.head, "div");\n
+        if (range.goalColumn != null) headPos.left = range.goalColumn;\n
+        goals.push(headPos.left);\n
+        var pos = findPosV(cm, headPos, dir, unit);\n
+        if (unit == "page" && range == doc.sel.primary())\n
+          addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);\n
+        return pos;\n
+      }, sel_move);\n
+      if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)\n
+        doc.sel.ranges[i].goalColumn = goals[i];\n
     }),\n
+\n
+    // Find the word at the given position (as returned by coordsChar).\n
+    findWordAt: function(pos) {\n
+      var doc = this.doc, line = getLine(doc, pos.line).text;\n
+      var start = pos.ch, end = pos.ch;\n
+      if (line) {\n
+        var helper = this.getHelper(pos, "wordChars");\n
+        if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;\n
+        var startChar = line.charAt(start);\n
+        var check = isWordChar(startChar, helper)\n
+          ? function(ch) { return isWordChar(ch, helper); }\n
+          : /\\s/.test(startChar) ? function(ch) {return /\\s/.test(ch);}\n
+          : function(ch) {return !/\\s/.test(ch) && !isWordChar(ch);};\n
+        while (start > 0 && check(line.charAt(start - 1))) --start;\n
+        while (end < line.length && check(line.charAt(end))) ++end;\n
+      }\n
+      return new Range(Pos(pos.line, start), Pos(pos.line, end));\n
+    },\n
 \n
     toggleOverwrite: function(value) {\n
       if (value != null && value == this.state.overwrite) return;\n
       if (this.state.overwrite = !this.state.overwrite)\n
-        this.display.cursor.className += " CodeMirror-overwrite";\n
+        addClass(this.display.cursorDiv, "CodeMirror-overwrite");\n
       else\n
-        this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");\n
+        rmClass(this.display.cursorDiv, "CodeMirror-overwrite");\n
 \n
       signal(this, "overwriteToggle", this, this.state.overwrite);\n
     },\n
-    hasFocus: function() { return document.activeElement == this.display.input; },\n
+    hasFocus: function() { return activeElt() == this.display.input; },\n
 \n
-    scrollTo: operation(null, function(x, y) {\n
-      updateScrollPos(this, x, y);\n
+    scrollTo: methodOp(function(x, y) {\n
+      if (x != null || y != null) resolveScrollToPos(this);\n
+      if (x != null) this.curOp.scrollLeft = x;\n
+      if (y != null) this.curOp.scrollTop = y;\n
     }),\n
     getScrollInfo: function() {\n
-      var scroller = this.display.scroller, co = scrollerCutOff;\n
+      var scroller = this.display.scroller;\n
       return {left: scroller.scrollLeft, top: scroller.scrollTop,\n
-              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,\n
-              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};\n
+              height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,\n
+              width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,\n
+              clientHeight: displayHeight(this), clientWidth: displayWidth(this)};\n
     },\n
 \n
-    scrollIntoView: operation(null, function(range, margin) {\n
-      if (range == null) range = {from: this.doc.sel.head, to: null};\n
-      else if (typeof range == "number") range = {from: Pos(range, 0), to: null};\n
-      else if (range.from == null) range = {from: range, to: null};\n
+    scrollIntoView: methodOp(function(range, margin) {\n
+      if (range == null) {\n
+        range = {from: this.doc.sel.primary().head, to: null};\n
+        if (margin == null) margin = this.options.cursorScrollMargin;\n
+      } else if (typeof range == "number") {\n
+        range = {from: Pos(range, 0), to: null};\n
+      } else if (range.from == null) {\n
+        range = {from: range, to: null};\n
+      }\n
       if (!range.to) range.to = range.from;\n
-      if (!margin) margin = 0;\n
+      range.margin = margin || 0;\n
 \n
-      var coords = range;\n
       if (range.from.line != null) {\n
-        this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin};\n
-        coords = {from: cursorCoords(this, range.from),\n
-                  to: cursorCoords(this, range.to)};\n
-      }\n
-      var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left),\n
-                                    Math.min(coords.from.top, coords.to.top) - margin,\n
-                                    Math.max(coords.from.right, coords.to.right),\n
-                                    Math.max(coords.from.bottom, coords.to.bottom) + margin);\n
-      updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);\n
+        resolveScrollToPos(this);\n
+        this.curOp.scrollToPos = range;\n
+      } else {\n
+        var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),\n
+                                      Math.min(range.from.top, range.to.top) - range.margin,\n
+                                      Math.max(range.from.right, range.to.right),\n
+                                      Math.max(range.from.bottom, range.to.bottom) + range.margin);\n
+        this.scrollTo(sPos.scrollLeft, sPos.scrollTop);\n
+      }\n
     }),\n
 \n
-    setSize: operation(null, function(width, height) {\n
+    setSize: methodOp(function(width, height) {\n
+      var cm = this;\n
       function interpret(val) {\n
         return typeof val == "number" || /^\\d+$/.test(String(val)) ? val + "px" : val;\n
       }\n
-      if (width != null) this.display.wrapper.style.width = interpret(width);\n
-      if (height != null) this.display.wrapper.style.height = interpret(height);\n
-      if (this.options.lineWrapping)\n
-        this.display.measureLineCache.length = this.display.measureLineCachePos = 0;\n
-      this.curOp.forceUpdate = true;\n
-      signal(this, "refresh", this);\n
+      if (width != null) cm.display.wrapper.style.width = interpret(width);\n
+      if (height != null) cm.display.wrapper.style.height = interpret(height);\n
+      if (cm.options.lineWrapping) clearLineMeasurementCache(this);\n
+      var lineNo = cm.display.viewFrom;\n
+      cm.doc.iter(lineNo, cm.display.viewTo, function(line) {\n
+        if (line.widgets) for (var i = 0; i < line.widgets.length; i++)\n
+          if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }\n
+        ++lineNo;\n
+      });\n
+      cm.curOp.forceUpdate = true;\n
+      signal(cm, "refresh", this);\n
     }),\n
 \n
     operation: function(f){return runInOp(this, f);},\n
 \n
-    refresh: operation(null, function() {\n
+    refresh: methodOp(function() {\n
       var oldHeight = this.display.cachedTextHeight;\n
-      clearCaches(this);\n
-      updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);\n
       regChange(this);\n
+      this.curOp.forceUpdate = true;\n
+      clearCaches(this);\n
+      this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);\n
+      updateGutterSpace(this);\n
       if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)\n
         estimateLineHeights(this);\n
       signal(this, "refresh", this);\n
     }),\n
 \n
-    swapDoc: operation(null, function(doc) {\n
+    swapDoc: methodOp(function(doc) {\n
       var old = this.doc;\n
       old.cm = null;\n
       attachDoc(this, doc);\n
       clearCaches(this);\n
-      resetInput(this, true);\n
-      updateScrollPos(this, doc.scrollLeft, doc.scrollTop);\n
+      resetInput(this);\n
+      this.scrollTo(doc.scrollLeft, doc.scrollTop);\n
+      this.curOp.forceScroll = true;\n
       signalLater(this, "swapDoc", this, old);\n
       return old;\n
     }),\n
@@ -3371,11 +4620,11 @@ window.CodeMirror = (function() {\n
   eventMixin(CodeMirror);\n
 \n
   // OPTION DEFAULTS\n
-\n
-  var optionHandlers = CodeMirror.optionHandlers = {};\n
 \n
   // The default configuration options.\n
   var defaults = CodeMirror.defaults = {};\n
+  // Functions to run when options are changed.\n
+  var optionHandlers = CodeMirror.optionHandlers = {};\n
 \n
   function option(name, deflt, handle, notOnInit) {\n
     CodeMirror.defaults[name] = deflt;\n
@@ -3383,6 +4632,7 @@ window.CodeMirror = (function() {\n
       notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;\n
   }\n
 \n
+  // Passed to option handlers when there is no old value.\n
   var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};\n
 \n
   // These two are, on init, called from the constructor because they\n
@@ -3403,7 +4653,7 @@ window.CodeMirror = (function() {\n
     clearCaches(cm);\n
     regChange(cm);\n
   }, true);\n
-  option("specialChars", /[\\t\\u0000-\\u0019\\u00ad\\u200b\\u2028\\u2029\\ufeff]/g, function(cm, val) {\n
+  option("specialChars", /[\\t\\u0000-\\u0019\\u00ad\\u200b-\\u200f\\u2028\\u2029\\ufeff]/g, function(cm, val) {\n
     cm.options.specialChars = new RegExp(val.source + (val.test("\\t") ? "" : "|\\t"), "g");\n
     cm.refresh();\n
   }, true);\n
@@ -3416,11 +4666,13 @@ window.CodeMirror = (function() {\n
     themeChanged(cm);\n
     guttersChanged(cm);\n
   }, true);\n
-  option("keyMap", "default", keyMapChanged);\n
+  option("keyMap", "default", function(cm, val, old) {\n
+    var next = getKeyMap(val);\n
+    var prev = old != CodeMirror.Init && getKeyMap(old);\n
+    if (prev && prev.detach) prev.detach(cm, next);\n
+    if (next.attach) next.attach(cm, prev || null);\n
+  });\n
   option("extraKeys", null);\n
-\n
-  option("onKeyEvent", null);\n
-  option("onDragEvent", null);\n
 \n
   option("lineWrapping", false, wrappingChanged, true);\n
   option("gutters", [], function(cm) {\n
@@ -3431,7 +4683,13 @@ window.CodeMirror = (function() {\n
     cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";\n
     cm.refresh();\n
   }, true);\n
-  option("coverGutterNextToScrollbar", false, updateScrollbars, true);\n
+  option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);\n
+  option("scrollbarStyle", "native", function(cm) {\n
+    initScrollbars(cm);\n
+    updateScrollbars(cm);\n
+    cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);\n
+    cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);\n
+  }, true);\n
   option("lineNumbers", false, function(cm) {\n
     setGuttersForLineNumbers(cm.options);\n
     guttersChanged(cm);\n
@@ -3449,25 +4707,25 @@ window.CodeMirror = (function() {\n
       cm.display.disabled = true;\n
     } else {\n
       cm.display.disabled = false;\n
-      if (!val) resetInput(cm, true);\n
+      if (!val) resetInput(cm);\n
     }\n
   });\n
-  option("disableInput", false, function(cm, val) {if (!val) resetInput(cm, true);}, true);\n
+  option("disableInput", false, function(cm, val) {if (!val) resetInput(cm);}, true);\n
   option("dragDrop", true);\n
 \n
   option("cursorBlinkRate", 530);\n
   option("cursorScrollMargin", 0);\n
-  option("cursorHeight", 1);\n
+  option("cursorHeight", 1, updateSelection, true);\n
+  option("singleCursorHeightPerLine", true, updateSelection, true);\n
   option("workTime", 100);\n
   option("workDelay", 100);\n
   option("flattenSpans", true, resetModeState, true);\n
   option("addModeClass", false, resetModeState, true);\n
   option("pollInterval", 100);\n
-  option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});\n
-  option("historyEventDelay", 500);\n
+  option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});\n
+  option("historyEventDelay", 1250);\n
   option("viewportMargin", 10, function(cm){cm.refresh();}, true);\n
   option("maxHighlightLength", 10000, resetModeState, true);\n
-  option("crudeMeasuringFrom", 10000);\n
   option("moveInputWithCursor", true, function(cm, val) {\n
     if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;\n
   });\n
@@ -3482,12 +4740,13 @@ window.CodeMirror = (function() {\n
   // Known modes, by name and by MIME\n
   var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};\n
 \n
+  // Extra arguments are stored as the mode\'s dependencies, which is\n
+  // used by (legacy) mechanisms like loadmode.js to automatically\n
+  // load a mode. (Preferred mechanism is the require/define calls.)\n
   CodeMirror.defineMode = function(name, mode) {\n
     if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;\n
-    if (arguments.length > 2) {\n
-      mode.dependencies = [];\n
-      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);\n
-    }\n
+    if (arguments.length > 2)\n
+      mode.dependencies = Array.prototype.slice.call(arguments, 2);\n
     modes[name] = mode;\n
   };\n
 \n
@@ -3495,6 +4754,8 @@ window.CodeMirror = (function() {\n
     mimeModes[mime] = spec;\n
   };\n
 \n
+  // Given a MIME type, a {name, ...options} config object, or a name\n
+  // string, return a mode config object.\n
   CodeMirror.resolveMode = function(spec) {\n
     if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {\n
       spec = mimeModes[spec];\n
@@ -3510,6 +4771,8 @@ window.CodeMirror = (function() {\n
     else return spec || {name: "null"};\n
   };\n
 \n
+  // Given a mode spec (anything that resolveMode accepts), find and\n
+  // initialize an actual mode object.\n
   CodeMirror.getMode = function(options, spec) {\n
     var spec = CodeMirror.resolveMode(spec);\n
     var mfactory = modes[spec.name];\n
@@ -3531,11 +4794,14 @@ window.CodeMirror = (function() {\n
     return modeObj;\n
   };\n
 \n
+  // Minimal default mode.\n
   CodeMirror.defineMode("null", function() {\n
     return {token: function(stream) {stream.skipToEnd();}};\n
   });\n
   CodeMirror.defineMIME("text/plain", "null");\n
 \n
+  // This can be used to attach properties to mode objects from\n
+  // outside the actual mode definition.\n
   var modeExtensions = CodeMirror.modeExtensions = {};\n
   CodeMirror.extendMode = function(mode, properties) {\n
     var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});\n
@@ -3564,16 +4830,13 @@ window.CodeMirror = (function() {\n
     CodeMirror.registerHelper(type, name, value);\n
     helpers[type]._global.push({pred: predicate, val: value});\n
   };\n
-\n
-  // UTILITIES\n
-\n
-  CodeMirror.isWordChar = isWordChar;\n
 \n
   // MODE STATE HANDLING\n
 \n
-  // Utility functions for working with state. Exported because modes\n
-  // sometimes need to do this.\n
-  function copyState(mode, state) {\n
+  // Utility functions for working with state. Exported because nested\n
+  // modes need to do this for their inner modes.\n
+\n
+  var copyState = CodeMirror.copyState = function(mode, state) {\n
     if (state === true) return state;\n
     if (mode.copyState) return mode.copyState(state);\n
     var nstate = {};\n
@@ -3583,14 +4846,14 @@ window.CodeMirror = (function() {\n
       nstate[n] = val;\n
     }\n
     return nstate;\n
-  }\n
-  CodeMirror.copyState = copyState;\n
+  };\n
 \n
-  function startState(mode, a1, a2) {\n
+  var startState = CodeMirror.startState = function(mode, a1, a2) {\n
     return mode.startState ? mode.startState(a1, a2) : true;\n
-  }\n
-  CodeMirror.startState = startState;\n
+  };\n
 \n
+  // Given a mode and a state (for that mode), find the inner mode and\n
+  // state at the position that the state refers to.\n
   CodeMirror.innerMode = function(mode, state) {\n
     while (mode.innerMode) {\n
       var info = mode.innerMode(state);\n
@@ -3603,49 +4866,89 @@ window.CodeMirror = (function() {\n
 \n
   // STANDARD COMMANDS\n
 \n
+  // Commands are parameter-less actions that can be performed on an\n
+  // editor, mostly used for keybindings.\n
   var commands = CodeMirror.commands = {\n
-    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},\n
+    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},\n
+    singleSelection: function(cm) {\n
+      cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);\n
+    },\n
     killLine: function(cm) {\n
-      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);\n
-      if (!sel && cm.getLine(from.line).length == from.ch)\n
-        cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");\n
-      else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");\n
+      deleteNearSelection(cm, function(range) {\n
+        if (range.empty()) {\n
+          var len = getLine(cm.doc, range.head.line).text.length;\n
+          if (range.head.ch == len && range.head.line < cm.lastLine())\n
+            return {from: range.head, to: Pos(range.head.line + 1, 0)};\n
+          else\n
+            return {from: range.head, to: Pos(range.head.line, len)};\n
+        } else {\n
+          return {from: range.from(), to: range.to()};\n
+        }\n
+      });\n
     },\n
     deleteLine: function(cm) {\n
-      var l = cm.getCursor().line;\n
-      cm.replaceRange("", Pos(l, 0), Pos(l + 1, 0), "+delete");\n
+      deleteNearSelection(cm, function(range) {\n
+        return {from: Pos(range.from().line, 0),\n
+                to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};\n
+      });\n
     },\n
     delLineLeft: function(cm) {\n
-      var cur = cm.getCursor();\n
-      cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");\n
+      deleteNearSelection(cm, function(range) {\n
+        return {from: Pos(range.from().line, 0), to: range.from()};\n
+      });\n
+    },\n
+    delWrappedLineLeft: function(cm) {\n
+      deleteNearSelection(cm, function(range) {\n
+        var top = cm.charCoords(range.head, "div").top + 5;\n
+        var leftPos = cm.coordsChar({left: 0, top: top}, "div");\n
+        return {from: leftPos, to: range.from()};\n
+      });\n
+    },\n
+    delWrappedLineRight: function(cm) {\n
+      deleteNearSelection(cm, function(range) {\n
+        var top = cm.charCoords(range.head, "div").top + 5;\n
+        var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");\n
+        return {from: range.from(), to: rightPos };\n
+      });\n
     },\n
     undo: function(cm) {cm.undo();},\n
     redo: function(cm) {cm.redo();},\n
+    undoSelection: function(cm) {cm.undoSelection();},\n
+    redoSelection: function(cm) {cm.redoSelection();},\n
     goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},\n
     goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},\n
     goLineStart: function(cm) {\n
-      cm.extendSelection(lineStart(cm, cm.getCursor().line));\n
+      cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },\n
+                            {origin: "+move", bias: 1});\n
     },\n
     goLineStartSmart: function(cm) {\n
-      var cur = cm.getCursor(), start = lineStart(cm, cur.line);\n
-      var line = cm.getLineHandle(start.line);\n
-      var order = getOrder(line);\n
-      if (!order || order[0].level == 0) {\n
-        var firstNonWS = Math.max(0, line.text.search(/\\S/));\n
-        var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;\n
-        cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));\n
-      } else cm.extendSelection(start);\n
+      cm.extendSelectionsBy(function(range) {\n
+        return lineStartSmart(cm, range.head);\n
+      }, {origin: "+move", bias: 1});\n
     },\n
     goLineEnd: function(cm) {\n
-      cm.extendSelection(lineEnd(cm, cm.getCursor().line));\n
+      cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },\n
+                            {origin: "+move", bias: -1});\n
     },\n
     goLineRight: function(cm) {\n
-      var top = cm.charCoords(cm.getCursor(), "div").top + 5;\n
-      cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));\n
+      cm.extendSelectionsBy(function(range) {\n
+        var top = cm.charCoords(range.head, "div").top + 5;\n
+        return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");\n
+      }, sel_move);\n
     },\n
     goLineLeft: function(cm) {\n
-      var top = cm.charCoords(cm.getCursor(), "div").top + 5;\n
-      cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));\n
+      cm.extendSelectionsBy(function(range) {\n
+        var top = cm.charCoords(range.head, "div").top + 5;\n
+        return cm.coordsChar({left: 0, top: top}, "div");\n
+      }, sel_move);\n
+    },\n
+    goLineLeftSmart: function(cm) {\n
+      cm.extendSelectionsBy(function(range) {\n
+        var top = cm.charCoords(range.head, "div").top + 5;\n
+        var pos = cm.coordsChar({left: 0, top: top}, "div");\n
+        if (pos.ch < cm.getLine(pos.line).search(/\\S/)) return lineStartSmart(cm, range.head);\n
+        return pos;\n
+      }, sel_move);\n
     },\n
     goLineUp: function(cm) {cm.moveV(-1, "line");},\n
     goLineDown: function(cm) {cm.moveV(1, "line");},\n
@@ -3668,114 +4971,193 @@ window.CodeMirror = (function() {\n
     indentAuto: function(cm) {cm.indentSelection("smart");},\n
     indentMore: function(cm) {cm.indentSelection("add");},\n
     indentLess: function(cm) {cm.indentSelection("subtract");},\n
-    insertTab: function(cm) {\n
-      cm.replaceSelection("\\t", "end", "+input");\n
+    insertTab: function(cm) {cm.replaceSelection("\\t");},\n
+    insertSoftTab: function(cm) {\n
+      var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var pos = ranges[i].from();\n
+        var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);\n
+        spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));\n
+      }\n
+      cm.replaceSelections(spaces);\n
     },\n
     defaultTab: function(cm) {\n
       if (cm.somethingSelected()) cm.indentSelection("add");\n
-      else cm.replaceSelection("\\t", "end", "+input");\n
+      else cm.execCommand("insertTab");\n
     },\n
     transposeChars: function(cm) {\n
-      var cur = cm.getCursor(), line = cm.getLine(cur.line);\n
-      if (cur.ch > 0 && cur.ch < line.length - 1)\n
-        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),\n
-                        Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));\n
+      runInOp(cm, function() {\n
+        var ranges = cm.listSelections(), newSel = [];\n
+        for (var i = 0; i < ranges.length; i++) {\n
+          var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;\n
+          if (line) {\n
+            if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);\n
+            if (cur.ch > 0) {\n
+              cur = new Pos(cur.line, cur.ch + 1);\n
+              cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),\n
+                              Pos(cur.line, cur.ch - 2), cur, "+transpose");\n
+            } else if (cur.line > cm.doc.first) {\n
+              var prev = getLine(cm.doc, cur.line - 1).text;\n
+              if (prev)\n
+                cm.replaceRange(line.charAt(0) + "\\n" + prev.charAt(prev.length - 1),\n
+                                Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");\n
+            }\n
+          }\n
+          newSel.push(new Range(cur, cur));\n
+        }\n
+        cm.setSelections(newSel);\n
+      });\n
     },\n
     newlineAndIndent: function(cm) {\n
-      operation(cm, function() {\n
-        cm.replaceSelection("\\n", "end", "+input");\n
-        cm.indentLine(cm.getCursor().line, null, true);\n
-      })();\n
+      runInOp(cm, function() {\n
+        var len = cm.listSelections().length;\n
+        for (var i = 0; i < len; i++) {\n
+          var range = cm.listSelections()[i];\n
+          cm.replaceRange("\\n", range.anchor, range.head, "+input");\n
+          cm.indentLine(range.from().line + 1, null, true);\n
+          ensureCursorVisible(cm);\n
+        }\n
+      });\n
     },\n
     toggleOverwrite: function(cm) {cm.toggleOverwrite();}\n
   };\n
+\n
 \n
   // STANDARD KEYMAPS\n
 \n
   var keyMap = CodeMirror.keyMap = {};\n
+\n
   keyMap.basic = {\n
     "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",\n
     "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",\n
     "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",\n
     "Tab": "defaultTab", "Shift-Tab": "indentAuto",\n
-    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"\n
+    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",\n
+    "Esc": "singleSelection"\n
   };\n
   // Note that the save and find-related commands aren\'t defined by\n
-  // default. Unknown commands are simply ignored.\n
+  // default. User code or addons can define them. Unknown commands\n
+  // are simply ignored.\n
   keyMap.pcDefault = {\n
     "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",\n
-    "Ctrl-Home": "goDocStart", "Ctrl-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",\n
+    "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",\n
     "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",\n
     "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",\n
     "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",\n
     "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",\n
+    "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",\n
     fallthrough: "basic"\n
   };\n
+  // Very basic readline/emacs-style bindings, which are standard on Mac.\n
+  keyMap.emacsy = {\n
+    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",\n
+    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",\n
+    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",\n
+    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"\n
+  };\n
   keyMap.macDefault = {\n
     "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",\n
-    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",\n
-    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",\n
+    "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",\n
+    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",\n
     "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",\n
     "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",\n
-    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",\n
+    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",\n
+    "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",\n
     fallthrough: ["basic", "emacsy"]\n
   };\n
   keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;\n
-  keyMap.emacsy = {\n
-    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",\n
-    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",\n
-    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",\n
-    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"\n
-  };\n
 \n
   // KEYMAP DISPATCH\n
 \n
-  function getKeyMap(val) {\n
-    if (typeof val == "string") return keyMap[val];\n
-    else return val;\n
-  }\n
-\n
-  function lookupKey(name, maps, handle) {\n
-    function lookup(map) {\n
-      map = getKeyMap(map);\n
-      var found = map[name];\n
-      if (found === false) return "stop";\n
-      if (found != null && handle(found)) return true;\n
-      if (map.nofallthrough) return "stop";\n
-\n
-      var fallthrough = map.fallthrough;\n
-      if (fallthrough == null) return false;\n
-      if (Object.prototype.toString.call(fallthrough) != "[object Array]")\n
-        return lookup(fallthrough);\n
-      for (var i = 0, e = fallthrough.length; i < e; ++i) {\n
-        var done = lookup(fallthrough[i]);\n
-        if (done) return done;\n
+  function normalizeKeyName(name) {\n
+    var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];\n
+    var alt, ctrl, shift, cmd;\n
+    for (var i = 0; i < parts.length - 1; i++) {\n
+      var mod = parts[i];\n
+      if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;\n
+      else if (/^a(lt)?$/i.test(mod)) alt = true;\n
+      else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;\n
+      else if (/^s(hift)$/i.test(mod)) shift = true;\n
+      else throw new Error("Unrecognized modifier name: " + mod);\n
+    }\n
+    if (alt) name = "Alt-" + name;\n
+    if (ctrl) name = "Ctrl-" + name;\n
+    if (cmd) name = "Cmd-" + name;\n
+    if (shift) name = "Shift-" + name;\n
+    return name;\n
+  }\n
+\n
+  // This is a kludge to keep keymaps mostly working as raw objects\n
+  // (backwards compatibility) while at the same time support features\n
+  // like normalization and multi-stroke key bindings. It compiles a\n
+  // new normalized keymap, and then updates the old object to reflect\n
+  // this.\n
+  CodeMirror.normalizeKeyMap = function(keymap) {\n
+    var copy = {};\n
+    for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {\n
+      var value = keymap[keyname];\n
+      if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;\n
+      if (value == "...") { delete keymap[keyname]; continue; }\n
+\n
+      var keys = map(keyname.split(" "), normalizeKeyName);\n
+      for (var i = 0; i < keys.length; i++) {\n
+        var val, name;\n
+        if (i == keys.length - 1) {\n
+          name = keyname;\n
+          val = value;\n
+        } else {\n
+          name = keys.slice(0, i + 1).join(" ");\n
+          val = "...";\n
+        }\n
+        var prev = copy[name];\n
+        if (!prev) copy[name] = val;\n
+        else if (prev != val) throw new Error("Inconsistent bindings for " + name);\n
       }\n
-      return false;\n
+      delete keymap[keyname];\n
     }\n
+    for (var prop in copy) keymap[prop] = copy[prop];\n
+    return keymap;\n
+  };\n
 \n
-    for (var i = 0; i < maps.length; ++i) {\n
-      var done = lookup(maps[i]);\n
-      if (done) return done != "stop";\n
+  var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {\n
+    map = getKeyMap(map);\n
+    var found = map.call ? map.call(key, context) : map[key];\n
+    if (found === false) return "nothing";\n
+    if (found === "...") return "multi";\n
+    if (found != null && handle(found)) return "handled";\n
+\n
+    if (map.fallthrough) {\n
+      if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")\n
+        return lookupKey(key, map.fallthrough, handle, context);\n
+      for (var i = 0; i < map.fallthrough.length; i++) {\n
+        var result = lookupKey(key, map.fallthrough[i], handle, context);\n
+        if (result) return result;\n
+      }\n
     }\n
-  }\n
-  function isModifierKey(event) {\n
-    var name = keyNames[event.keyCode];\n
+  };\n
+\n
+  // Modifier key presses don\'t count as \'real\' key presses for the\n
+  // purpose of keymap fallthrough.\n
+  var isModifierKey = CodeMirror.isModifierKey = function(value) {\n
+    var name = typeof value == "string" ? value : keyNames[value.keyCode];\n
     return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";\n
-  }\n
-  function keyName(event, noShift) {\n
-    if (opera && event.keyCode == 34 && event["char"]) return false;\n
-    var name = keyNames[event.keyCode];\n
+  };\n
+\n
+  // Look up the name of a key as indicated by an event object.\n
+  var keyName = CodeMirror.keyName = function(event, noShift) {\n
+    if (presto && event.keyCode == 34 && event["char"]) return false;\n
+    var base = keyNames[event.keyCode], name = base;\n
     if (name == null || event.altGraphKey) return false;\n
-    if (event.altKey) name = "Alt-" + name;\n
-    if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;\n
-    if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;\n
-    if (!noShift && event.shiftKey) name = "Shift-" + name;\n
+    if (event.altKey && base != "Alt") name = "Alt-" + name;\n
+    if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;\n
+    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;\n
+    if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;\n
     return name;\n
+  };\n
+\n
+  function getKeyMap(val) {\n
+    return typeof val == "string" ? keyMap[val] : val;\n
   }\n
-  CodeMirror.lookupKey = lookupKey;\n
-  CodeMirror.isModifierKey = isModifierKey;\n
-  CodeMirror.keyName = keyName;\n
 \n
   // FROMTEXTAREA\n
 \n
@@ -3789,9 +5171,7 @@ window.CodeMirror = (function() {\n
     // Set autofocus to true if this textarea is focused, or if it has\n
     // autofocus and no other element is focused.\n
     if (options.autofocus == null) {\n
-      var hasFocus = document.body;\n
-      // doc.activeElement occasionally throws on IE\n
-      try { hasFocus = document.activeElement; } catch(e) {}\n
+      var hasFocus = activeElt();\n
       options.autofocus = hasFocus == textarea ||\n
         textarea.getAttribute("autofocus") != null && hasFocus == document.body;\n
     }\n
@@ -3820,6 +5200,7 @@ window.CodeMirror = (function() {\n
     cm.save = save;\n
     cm.getTextArea = function() { return textarea; };\n
     cm.toTextArea = function() {\n
+      cm.toTextArea = isNaN; // Prevent this from being ran twice\n
       save();\n
       textarea.parentNode.removeChild(cm.getWrapperElement());\n
       textarea.style.display = "";\n
@@ -3837,14 +5218,13 @@ window.CodeMirror = (function() {\n
   // Fed to the mode parsers, provides helper functions to make\n
   // parsers more succinct.\n
 \n
-  // The character stream used by a mode\'s parser.\n
-  function StringStream(string, tabSize) {\n
+  var StringStream = CodeMirror.StringStream = function(string, tabSize) {\n
     this.pos = this.start = 0;\n
     this.string = string;\n
     this.tabSize = tabSize || 8;\n
     this.lastColumnPos = this.lastColumnValue = 0;\n
     this.lineStart = 0;\n
-  }\n
+  };\n
 \n
   StringStream.prototype = {\n
     eol: function() {return this.pos >= this.string.length;},\n
@@ -3909,18 +5289,27 @@ window.CodeMirror = (function() {\n
       finally { this.lineStart -= n; }\n
     }\n
   };\n
-  CodeMirror.StringStream = StringStream;\n
 \n
   // TEXTMARKERS\n
 \n
-  function TextMarker(doc, type) {\n
+  // Created with markText and setBookmark methods. A TextMarker is a\n
+  // handle that can be used to clear or find a marked position in the\n
+  // document. Line objects hold arrays (markedSpans) containing\n
+  // {from, to, marker} object pointing to such marker objects, and\n
+  // indicating that such a marker is present on that line. Multiple\n
+  // lines may point to the same marker when it spans across lines.\n
+  // The spans will have null for their from/to properties when the\n
+  // marker continues beyond the start/end of the line. Markers have\n
+  // links back to the lines they currently touch.\n
+\n
+  var TextMarker = CodeMirror.TextMarker = function(doc, type) {\n
     this.lines = [];\n
     this.type = type;\n
     this.doc = doc;\n
-  }\n
-  CodeMirror.TextMarker = TextMarker;\n
+  };\n
   eventMixin(TextMarker);\n
 \n
+  // Clear the marker.\n
   TextMarker.prototype.clear = function() {\n
     if (this.explicitlyCleared) return;\n
     var cm = this.doc.cm, withOp = cm && !cm.curOp;\n
@@ -3933,15 +5322,17 @@ window.CodeMirror = (function() {\n
     for (var i = 0; i < this.lines.length; ++i) {\n
       var line = this.lines[i];\n
       var span = getMarkedSpanFor(line.markedSpans, this);\n
-      if (span.to != null) max = lineNo(line);\n
+      if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");\n
+      else if (cm) {\n
+        if (span.to != null) max = lineNo(line);\n
+        if (span.from != null) min = lineNo(line);\n
+      }\n
       line.markedSpans = removeMarkedSpan(line.markedSpans, span);\n
-      if (span.from != null)\n
-        min = lineNo(line);\n
-      else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)\n
+      if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)\n
         updateLineHeight(line, textHeight(cm.display));\n
     }\n
     if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {\n
-      var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);\n
+      var visual = visualLine(this.lines[i]), len = lineLength(visual);\n
       if (len > cm.display.maxLineLength) {\n
         cm.display.maxLine = visual;\n
         cm.display.maxLineLength = len;\n
@@ -3949,46 +5340,62 @@ window.CodeMirror = (function() {\n
       }\n
     }\n
 \n
-    if (min != null && cm) regChange(cm, min, max + 1);\n
+    if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);\n
     this.lines.length = 0;\n
     this.explicitlyCleared = true;\n
     if (this.atomic && this.doc.cantEdit) {\n
       this.doc.cantEdit = false;\n
-      if (cm) reCheckSelection(cm);\n
+      if (cm) reCheckSelection(cm.doc);\n
     }\n
+    if (cm) signalLater(cm, "markerCleared", cm, this);\n
     if (withOp) endOperation(cm);\n
+    if (this.parent) this.parent.clear();\n
   };\n
 \n
-  TextMarker.prototype.find = function(bothSides) {\n
+  // Find the position of the marker in the document. Returns a {from,\n
+  // to} object by default. Side can be passed to get a specific side\n
+  // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the\n
+  // Pos objects returned contain a line object, rather than a line\n
+  // number (used to prevent looking up the same line twice).\n
+  TextMarker.prototype.find = function(side, lineObj) {\n
+    if (side == null && this.type == "bookmark") side = 1;\n
     var from, to;\n
     for (var i = 0; i < this.lines.length; ++i) {\n
       var line = this.lines[i];\n
       var span = getMarkedSpanFor(line.markedSpans, this);\n
-      if (span.from != null || span.to != null) {\n
-        var found = lineNo(line);\n
-        if (span.from != null) from = Pos(found, span.from);\n
-        if (span.to != null) to = Pos(found, span.to);\n
+      if (span.from != null) {\n
+        from = Pos(lineObj ? line : lineNo(line), span.from);\n
+        if (side == -1) return from;\n
+      }\n
+      if (span.to != null) {\n
+        to = Pos(lineObj ? line : lineNo(line), span.to);\n
+        if (side == 1) return to;\n
       }\n
     }\n
-    if (this.type == "bookmark" && !bothSides) return from;\n
     return from && {from: from, to: to};\n
   };\n
 \n
+  // Signals that the marker\'s widget changed, and surrounding layout\n
+  // should be recomputed.\n
   TextMarker.prototype.changed = function() {\n
-    var pos = this.find(), cm = this.doc.cm;\n
+    var pos = this.find(-1, true), widget = this, cm = this.doc.cm;\n
     if (!pos || !cm) return;\n
-    if (this.type != "bookmark") pos = pos.from;\n
-    var line = getLine(this.doc, pos.line);\n
-    clearCachedMeasurement(cm, line);\n
-    if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {\n
-      for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {\n
-        if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);\n
-        break;\n
+    runInOp(cm, function() {\n
+      var line = pos.line, lineN = lineNo(pos.line);\n
+      var view = findViewForLine(cm, lineN);\n
+      if (view) {\n
+        clearLineMeasurementCacheFor(view);\n
+        cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;\n
       }\n
-      runInOp(cm, function() {\n
-        cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;\n
-      });\n
-    }\n
+      cm.curOp.updateMaxLine = true;\n
+      if (!lineIsHidden(widget.doc, line) && widget.height != null) {\n
+        var oldHeight = widget.height;\n
+        widget.height = null;\n
+        var dHeight = widgetHeight(widget) - oldHeight;\n
+        if (dHeight)\n
+          updateLineHeight(line, line.height + dHeight);\n
+      }\n
+    });\n
   };\n
 \n
   TextMarker.prototype.attachLine = function(line) {\n
@@ -4007,20 +5414,31 @@ window.CodeMirror = (function() {\n
     }\n
   };\n
 \n
+  // Collapsed markers have unique ids, in order to be able to order\n
+  // them, which is needed for uniquely determining an outer marker\n
+  // when they overlap (they may nest, but not partially overlap).\n
   var nextMarkerId = 0;\n
 \n
+  // Create a marker, wire it up to the right lines, and\n
   function markText(doc, from, to, options, type) {\n
+    // Shared markers (across linked documents) are handled separately\n
+    // (markTextShared will call out to this again, once per\n
+    // document).\n
     if (options && options.shared) return markTextShared(doc, from, to, options, type);\n
+    // Ensure we are in an operation.\n
     if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);\n
 \n
-    var marker = new TextMarker(doc, type);\n
-    if (options) copyObj(options, marker);\n
-    if (posLess(to, from) || posEq(from, to) && marker.clearWhenEmpty !== false)\n
+    var marker = new TextMarker(doc, type), diff = cmp(from, to);\n
+    if (options) copyObj(options, marker, false);\n
+    // Don\'t connect empty markers unless clearWhenEmpty is false\n
+    if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)\n
       return marker;\n
     if (marker.replacedWith) {\n
+      // Showing up as a widget implies collapsed (widget replaces text)\n
       marker.collapsed = true;\n
-      marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");\n
-      if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;\n
+      marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");\n
+      if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");\n
+      if (options.insertLeft) marker.widgetNode.insertLeft = true;\n
     }\n
     if (marker.collapsed) {\n
       if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||\n
@@ -4030,20 +5448,19 @@ window.CodeMirror = (function() {\n
     }\n
 \n
     if (marker.addToHistory)\n
-      addToHistory(doc, {from: from, to: to, origin: "markText"},\n
-                   {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);\n
+      addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);\n
 \n
     var curLine = from.line, cm = doc.cm, updateMaxLine;\n
     doc.iter(curLine, to.line + 1, function(line) {\n
-      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)\n
+      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)\n
         updateMaxLine = true;\n
-      var span = {from: null, to: null, marker: marker};\n
-      if (curLine == from.line) span.from = from.ch;\n
-      if (curLine == to.line) span.to = to.ch;\n
       if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);\n
-      addMarkedSpan(line, span);\n
+      addMarkedSpan(line, new MarkedSpan(marker,\n
+                                         curLine == from.line ? from.ch : null,\n
+                                         curLine == to.line ? to.ch : null));\n
       ++curLine;\n
     });\n
+    // lineIsHidden depends on the presence of the spans, so needs a second pass\n
     if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {\n
       if (lineIsHidden(doc, line)) updateLineHeight(line, 0);\n
     });\n
@@ -4060,25 +5477,29 @@ window.CodeMirror = (function() {\n
       marker.atomic = true;\n
     }\n
     if (cm) {\n
+      // Sync editor state\n
       if (updateMaxLine) cm.curOp.updateMaxLine = true;\n
-      if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)\n
+      if (marker.collapsed)\n
         regChange(cm, from.line, to.line + 1);\n
-      if (marker.atomic) reCheckSelection(cm);\n
+      else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)\n
+        for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");\n
+      if (marker.atomic) reCheckSelection(cm.doc);\n
+      signalLater(cm, "markerAdded", cm, marker);\n
     }\n
     return marker;\n
   }\n
 \n
   // SHARED TEXTMARKERS\n
 \n
-  function SharedTextMarker(markers, primary) {\n
+  // A shared marker spans multiple linked documents. It is\n
+  // implemented as a meta-marker-object controlling multiple normal\n
+  // markers.\n
+  var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {\n
     this.markers = markers;\n
     this.primary = primary;\n
-    for (var i = 0, me = this; i < markers.length; ++i) {\n
+    for (var i = 0; i < markers.length; ++i)\n
       markers[i].parent = this;\n
-      on(markers[i], "clear", function(){me.clear();});\n
-    }\n
-  }\n
-  CodeMirror.SharedTextMarker = SharedTextMarker;\n
+  };\n
   eventMixin(SharedTextMarker);\n
 \n
   SharedTextMarker.prototype.clear = function() {\n
@@ -4088,17 +5509,17 @@ window.CodeMirror = (function() {\n
       this.markers[i].clear();\n
     signalLater(this, "clear");\n
   };\n
-  SharedTextMarker.prototype.find = function() {\n
-    return this.primary.find();\n
+  SharedTextMarker.prototype.find = function(side, lineObj) {\n
+    return this.primary.find(side, lineObj);\n
   };\n
 \n
   function markTextShared(doc, from, to, options, type) {\n
     options = copyObj(options);\n
     options.shared = false;\n
     var markers = [markText(doc, from, to, options, type)], primary = markers[0];\n
-    var widget = options.replacedWith;\n
+    var widget = options.widgetNode;\n
     linkedDocs(doc, function(doc) {\n
-      if (widget) options.replacedWith = widget.cloneNode(true);\n
+      if (widget) options.widgetNode = widget.cloneNode(true);\n
       markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));\n
       for (var i = 0; i < doc.linked.length; ++i)\n
         if (doc.linked[i].isParent) return;\n
@@ -4106,59 +5527,105 @@ window.CodeMirror = (function() {\n
     });\n
     return new SharedTextMarker(markers, primary);\n
   }\n
+\n
+  function findSharedMarkers(doc) {\n
+    return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),\n
+                         function(m) { return m.parent; });\n
+  }\n
+\n
+  function copySharedMarkers(doc, markers) {\n
+    for (var i = 0; i < markers.length; i++) {\n
+      var marker = markers[i], pos = marker.find();\n
+      var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);\n
+      if (cmp(mFrom, mTo)) {\n
+        var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);\n
+        marker.markers.push(subMark);\n
+        subMark.parent = marker;\n
+      }\n
+    }\n
+  }\n
+\n
+  function detachSharedMarkers(markers) {\n
+    for (var i = 0; i < markers.length; i++) {\n
+      var marker = markers[i], linked = [marker.primary.doc];;\n
+      linkedDocs(marker.primary.doc, function(d) { linked.push(d); });\n
+      for (var j = 0; j < marker.markers.length; j++) {\n
+        var subMarker = marker.markers[j];\n
+        if (indexOf(linked, subMarker.doc) == -1) {\n
+          subMarker.parent = null;\n
+          marker.markers.splice(j--, 1);\n
+        }\n
+      }\n
+    }\n
+  }\n
 \n
   // TEXTMARKER SPANS\n
 \n
+  function MarkedSpan(marker, from, to) {\n
+    this.marker = marker;\n
+    this.from = from; this.to = to;\n
+  }\n
+\n
+  // Search an array of spans for a span matching the given marker.\n
   function getMarkedSpanFor(spans, marker) {\n
     if (spans) for (var i = 0; i < spans.length; ++i) {\n
       var span = spans[i];\n
       if (span.marker == marker) return span;\n
     }\n
   }\n
+  // Remove a span from an array, returning undefined if no spans are\n
+  // left (we don\'t store arrays for lines without spans).\n
   function removeMarkedSpan(spans, span) {\n
     for (var r, i = 0; i < spans.length; ++i)\n
       if (spans[i] != span) (r || (r = [])).push(spans[i]);\n
     return r;\n
   }\n
+  // Add a span to a line.\n
   function addMarkedSpan(line, span) {\n
     line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];\n
     span.marker.attachLine(line);\n
   }\n
 \n
+  // Used for the algorithm that adjusts markers for a change in the\n
+  // document. These functions cut an array of spans at a given\n
+  // character position, returning an array of remaining chunks (or\n
+  // undefined if nothing remains).\n
   function markedSpansBefore(old, startCh, isInsert) {\n
     if (old) for (var i = 0, nw; i < old.length; ++i) {\n
       var span = old[i], marker = span.marker;\n
       var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);\n
       if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {\n
         var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);\n
-        (nw || (nw = [])).push({from: span.from,\n
-                                to: endsAfter ? null : span.to,\n
-                                marker: marker});\n
+        (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));\n
       }\n
     }\n
     return nw;\n
   }\n
-\n
   function markedSpansAfter(old, endCh, isInsert) {\n
     if (old) for (var i = 0, nw; i < old.length; ++i) {\n
       var span = old[i], marker = span.marker;\n
       var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);\n
       if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {\n
         var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);\n
-        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,\n
-                                to: span.to == null ? null : span.to - endCh,\n
-                                marker: marker});\n
+        (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,\n
+                                              span.to == null ? null : span.to - endCh));\n
       }\n
     }\n
     return nw;\n
   }\n
 \n
+  // Given a change object, compute the new set of marker spans that\n
+  // cover the line in which the change took place. Removes spans\n
+  // entirely within the change, reconnects spans belonging to the\n
+  // same marker that appear on both sides of the change, and cuts off\n
+  // spans partially within the change. Returns an array of span\n
+  // arrays with one element for each line in (after) the change.\n
   function stretchSpansOverChange(doc, change) {\n
     var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;\n
     var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;\n
     if (!oldFirst && !oldLast) return null;\n
 \n
-    var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);\n
+    var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;\n
     // Get the spans that \'stick out\' on both sides\n
     var first = markedSpansBefore(oldFirst, startCh, isInsert);\n
     var last = markedSpansAfter(oldLast, endCh, isInsert);\n
@@ -4204,7 +5671,7 @@ window.CodeMirror = (function() {\n
       if (gap > 0 && first)\n
         for (var i = 0; i < first.length; ++i)\n
           if (first[i].to == null)\n
-            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});\n
+            (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));\n
       for (var i = 0; i < gap; ++i)\n
         newMarkers.push(gapMarkers);\n
       newMarkers.push(last);\n
@@ -4212,6 +5679,8 @@ window.CodeMirror = (function() {\n
     return newMarkers;\n
   }\n
 \n
+  // Remove spans that are empty and don\'t have a clearWhenEmpty\n
+  // option of false.\n
   function clearEmptySpans(spans) {\n
     for (var i = 0; i < spans.length; ++i) {\n
       var span = spans[i];\n
@@ -4222,6 +5691,10 @@ window.CodeMirror = (function() {\n
     return spans;\n
   }\n
 \n
+  // Used for un/re-doing changes from the history. Combines the\n
+  // result of computing the existing spans with the set of spans that\n
+  // existed in the history (so that deleting around a span and then\n
+  // undoing brings back the span).\n
   function mergeOldSpans(doc, change) {\n
     var old = getOldSpans(doc, change);\n
     var stretched = stretchSpansOverChange(doc, change);\n
@@ -4244,6 +5717,7 @@ window.CodeMirror = (function() {\n
     return old;\n
   }\n
 \n
+  // Used to \'clip\' out readOnly ranges when making a change.\n
   function removeReadOnlyRanges(doc, from, to) {\n
     var markers = null;\n
     doc.iter(from.line, to.line + 1, function(line) {\n
@@ -4256,14 +5730,14 @@ window.CodeMirror = (function() {\n
     if (!markers) return null;\n
     var parts = [{from: from, to: to}];\n
     for (var i = 0; i < markers.length; ++i) {\n
-      var mk = markers[i], m = mk.find();\n
+      var mk = markers[i], m = mk.find(0);\n
       for (var j = 0; j < parts.length; ++j) {\n
         var p = parts[j];\n
-        if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;\n
-        var newParts = [j, 1];\n
-        if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))\n
+        if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;\n
+        var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);\n
+        if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)\n
           newParts.push({from: p.from, to: m.from});\n
-        if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))\n
+        if (dto > 0 || !mk.inclusiveRight && !dto)\n
           newParts.push({from: m.to, to: p.to});\n
         parts.splice.apply(parts, newParts);\n
         j += newParts.length - 1;\n
@@ -4272,9 +5746,29 @@ window.CodeMirror = (function() {\n
     return parts;\n
   }\n
 \n
+  // Connect or disconnect spans from a line.\n
+  function detachMarkedSpans(line) {\n
+    var spans = line.markedSpans;\n
+    if (!spans) return;\n
+    for (var i = 0; i < spans.length; ++i)\n
+      spans[i].marker.detachLine(line);\n
+    line.markedSpans = null;\n
+  }\n
+  function attachMarkedSpans(line, spans) {\n
+    if (!spans) return;\n
+    for (var i = 0; i < spans.length; ++i)\n
+      spans[i].marker.attachLine(line);\n
+    line.markedSpans = spans;\n
+  }\n
+\n
+  // Helpers used when computing which overlapping collapsed span\n
+  // counts as the larger one.\n
   function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }\n
   function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }\n
 \n
+  // Returns a number indicating which of two overlapping collapsed\n
+  // spans is larger (and thus includes the other). Falls back to\n
+  // comparing ids when the spans cover exactly the same range.\n
   function compareCollapsedMarkers(a, b) {\n
     var lenDiff = a.lines.length - b.lines.length;\n
     if (lenDiff != 0) return lenDiff;\n
@@ -4286,6 +5780,8 @@ window.CodeMirror = (function() {\n
     return b.id - a.id;\n
   }\n
 \n
+  // Find out whether a line ends or starts in a collapsed span. If\n
+  // so, return the marker for that span.\n
   function collapsedSpanAtSide(line, start) {\n
     var sps = sawCollapsedSpans && line.markedSpans, found;\n
     if (sps) for (var sp, i = 0; i < sps.length; ++i) {\n
@@ -4299,72 +5795,98 @@ window.CodeMirror = (function() {\n
   function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }\n
   function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }\n
 \n
+  // Test whether there exists a collapsed span that partially\n
+  // overlaps (covers the start or end, but not both) of a new span.\n
+  // Such overlap is not allowed.\n
   function conflictingCollapsedRange(doc, lineNo, from, to, marker) {\n
     var line = getLine(doc, lineNo);\n
     var sps = sawCollapsedSpans && line.markedSpans;\n
     if (sps) for (var i = 0; i < sps.length; ++i) {\n
       var sp = sps[i];\n
       if (!sp.marker.collapsed) continue;\n
-      var found = sp.marker.find(true);\n
+      var found = sp.marker.find(0);\n
       var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);\n
       var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);\n
       if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;\n
-      if (fromCmp <= 0 && (cmp(found.to, from) || extraRight(sp.marker) - extraLeft(marker)) > 0 ||\n
-          fromCmp >= 0 && (cmp(found.from, to) || extraLeft(sp.marker) - extraRight(marker)) < 0)\n
+      if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||\n
+          fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))\n
         return true;\n
     }\n
   }\n
 \n
-  function visualLine(doc, line) {\n
+  // A visual line is a line as drawn on the screen. Folding, for\n
+  // example, can cause multiple logical lines to appear on the same\n
+  // visual line. This finds the start of the visual line that the\n
+  // given line is part of (usually that is the line itself).\n
+  function visualLine(line) {\n
     var merged;\n
     while (merged = collapsedSpanAtStart(line))\n
-      line = getLine(doc, merged.find().from.line);\n
+      line = merged.find(-1, true).line;\n
     return line;\n
   }\n
 \n
+  // Returns an array of logical lines that continue the visual line\n
+  // started by the argument, or undefined if there are no such lines.\n
+  function visualLineContinued(line) {\n
+    var merged, lines;\n
+    while (merged = collapsedSpanAtEnd(line)) {\n
+      line = merged.find(1, true).line;\n
+      (lines || (lines = [])).push(line);\n
+    }\n
+    return lines;\n
+  }\n
+\n
+  // Get the line number of the start of the visual line that the\n
+  // given line number is part of.\n
+  function visualLineNo(doc, lineN) {\n
+    var line = getLine(doc, lineN), vis = visualLine(line);\n
+    if (line == vis) return lineN;\n
+    return lineNo(vis);\n
+  }\n
+  // Get the line number of the start of the next visual line after\n
+  // the given line.\n
+  function visualLineEndNo(doc, lineN) {\n
+    if (lineN > doc.lastLine()) return lineN;\n
+    var line = getLine(doc, lineN), merged;\n
+    if (!lineIsHidden(doc, line)) return lineN;\n
+    while (merged = collapsedSpanAtEnd(line))\n
+      line = merged.find(1, true).line;\n
+    return lineNo(line) + 1;\n
+  }\n
+\n
+  // Compute whether a line is hidden. Lines count as hidden when they\n
+  // are part of a visual line that starts with another line, or when\n
+  // they are entirely covered by collapsed, non-widget span.\n
   function lineIsHidden(doc, line) {\n
     var sps = sawCollapsedSpans && line.markedSpans;\n
     if (sps) for (var sp, i = 0; i < sps.length; ++i) {\n
       sp = sps[i];\n
       if (!sp.marker.collapsed) continue;\n
       if (sp.from == null) return true;\n
-      if (sp.marker.replacedWith) continue;\n
+      if (sp.marker.widgetNode) continue;\n
       if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))\n
         return true;\n
     }\n
   }\n
   function lineIsHiddenInner(doc, line, span) {\n
     if (span.to == null) {\n
-      var end = span.marker.find().to, endLine = getLine(doc, end.line);\n
-      return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));\n
+      var end = span.marker.find(1, true);\n
+      return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));\n
     }\n
     if (span.marker.inclusiveRight && span.to == line.text.length)\n
       return true;\n
     for (var sp, i = 0; i < line.markedSpans.length; ++i) {\n
       sp = line.markedSpans[i];\n
-      if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&\n
+      if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&\n
           (sp.to == null || sp.to != span.from) &&\n
           (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&\n
           lineIsHiddenInner(doc, line, sp)) return true;\n
     }\n
   }\n
-\n
-  function detachMarkedSpans(line) {\n
-    var spans = line.markedSpans;\n
-    if (!spans) return;\n
-    for (var i = 0; i < spans.length; ++i)\n
-      spans[i].marker.detachLine(line);\n
-    line.markedSpans = null;\n
-  }\n
-\n
-  function attachMarkedSpans(line, spans) {\n
-    if (!spans) return;\n
-    for (var i = 0; i < spans.length; ++i)\n
-      spans[i].marker.attachLine(line);\n
-    line.markedSpans = spans;\n
-  }\n
 \n
   // LINE WIDGETS\n
+\n
+  // Line widgets are block elements displayed above or below a line.\n
 \n
   var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {\n
     if (options) for (var opt in options) if (options.hasOwnProperty(opt))\n
@@ -4373,54 +5895,59 @@ window.CodeMirror = (function() {\n
     this.node = node;\n
   };\n
   eventMixin(LineWidget);\n
-  function widgetOperation(f) {\n
-    return function() {\n
-      var withOp = !this.cm.curOp;\n
-      if (withOp) startOperation(this.cm);\n
-      try {var result = f.apply(this, arguments);}\n
-      finally {if (withOp) endOperation(this.cm);}\n
-      return result;\n
-    };\n
+\n
+  function adjustScrollWhenAboveVisible(cm, line, diff) {\n
+    if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))\n
+      addToScrollPos(cm, null, diff);\n
   }\n
-  LineWidget.prototype.clear = widgetOperation(function() {\n
-    var ws = this.line.widgets, no = lineNo(this.line);\n
+\n
+  LineWidget.prototype.clear = function() {\n
+    var cm = this.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);\n
     if (no == null || !ws) return;\n
     for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);\n
-    if (!ws.length) this.line.widgets = null;\n
-    var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;\n
-    updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));\n
-    if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);\n
-    regChange(this.cm, no, no + 1);\n
-  });\n
-  LineWidget.prototype.changed = widgetOperation(function() {\n
-    var oldH = this.height;\n
+    if (!ws.length) line.widgets = null;\n
+    var height = widgetHeight(this);\n
+    runInOp(cm, function() {\n
+      adjustScrollWhenAboveVisible(cm, line, -height);\n
+      regLineChange(cm, no, "widget");\n
+      updateLineHeight(line, Math.max(0, line.height - height));\n
+    });\n
+  };\n
+  LineWidget.prototype.changed = function() {\n
+    var oldH = this.height, cm = this.cm, line = this.line;\n
     this.height = null;\n
     var diff = widgetHeight(this) - oldH;\n
     if (!diff) return;\n
-    updateLineHeight(this.line, this.line.height + diff);\n
-    var no = lineNo(this.line);\n
-    regChange(this.cm, no, no + 1);\n
-  });\n
+    runInOp(cm, function() {\n
+      cm.curOp.forceUpdate = true;\n
+      adjustScrollWhenAboveVisible(cm, line, diff);\n
+      updateLineHeight(line, line.height + diff);\n
+    });\n
+  };\n
 \n
   function widgetHeight(widget) {\n
     if (widget.height != null) return widget.height;\n
-    if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)\n
-      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));\n
+    if (!contains(document.body, widget.node)) {\n
+      var parentStyle = "position: relative;";\n
+      if (widget.coverGutter)\n
+        parentStyle += "margin-left: -" + widget.cm.getGutterElement().offsetWidth + "px;";\n
+      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, parentStyle));\n
+    }\n
     return widget.height = widget.node.offsetHeight;\n
   }\n
 \n
   function addLineWidget(cm, handle, node, options) {\n
     var widget = new LineWidget(cm, node, options);\n
     if (widget.noHScroll) cm.display.alignWidgets = true;\n
-    changeLine(cm, handle, function(line) {\n
+    changeLine(cm.doc, handle, "widget", function(line) {\n
       var widgets = line.widgets || (line.widgets = []);\n
       if (widget.insertAt == null) widgets.push(widget);\n
       else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);\n
       widget.line = line;\n
-      if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {\n
-        var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;\n
+      if (!lineIsHidden(cm.doc, line)) {\n
+        var aboveVisible = heightAtLine(line) < cm.doc.scrollTop;\n
         updateLineHeight(line, line.height + widgetHeight(widget));\n
-        if (aboveVisible) addToScrollPos(cm, 0, widget.height);\n
+        if (aboveVisible) addToScrollPos(cm, null, widget.height);\n
         cm.curOp.forceUpdate = true;\n
       }\n
       return true;\n
@@ -4440,6 +5967,9 @@ window.CodeMirror = (function() {\n
   eventMixin(Line);\n
   Line.prototype.lineNo = function() { return lineNo(this); };\n
 \n
+  // Change the content (text, markers) of a line. Automatically\n
+  // invalidates cached information and tries to re-estimate the\n
+  // line\'s height.\n
   function updateLine(line, text, markedSpans, estimateHeight) {\n
     line.text = text;\n
     if (line.stateAfter) line.stateAfter = null;\n
@@ -4451,20 +5981,72 @@ window.CodeMirror = (function() {\n
     if (estHeight != line.height) updateLineHeight(line, estHeight);\n
   }\n
 \n
+  // Detach a line from the document tree and its markers.\n
   function cleanUpLine(line) {\n
     line.parent = null;\n
     detachMarkedSpans(line);\n
   }\n
 \n
-  // Run the given mode\'s parser over a line, update the styles\n
-  // array, which contains alternating fragments of text and CSS\n
-  // classes.\n
-  function runMode(cm, text, mode, state, f, forceToEnd) {\n
+  function extractLineClasses(type, output) {\n
+    if (type) for (;;) {\n
+      var lineClass = type.match(/(?:^|\\s+)line-(background-)?(\\S+)/);\n
+      if (!lineClass) break;\n
+      type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);\n
+      var prop = lineClass[1] ? "bgClass" : "textClass";\n
+      if (output[prop] == null)\n
+        output[prop] = lineClass[2];\n
+      else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop]))\n
+        output[prop] += " " + lineClass[2];\n
+    }\n
+    return type;\n
+  }\n
+\n
+  function callBlankLine(mode, state) {\n
+    if (mode.blankLine) return mode.blankLine(state);\n
+    if (!mode.innerMode) return;\n
+    var inner = CodeMirror.innerMode(mode, state);\n
+    if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);\n
+  }\n
+\n
+  function readToken(mode, stream, state, inner) {\n
+    for (var i = 0; i < 10; i++) {\n
+      if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;\n
+      var style = mode.token(stream, state);\n
+      if (stream.pos > stream.start) return style;\n
+    }\n
+    throw new Error("Mode " + mode.name + " failed to advance stream.");\n
+  }\n
+\n
+  // Utility for getTokenAt and getLineTokens\n
+  function takeToken(cm, pos, precise, asArray) {\n
+    function getObj(copy) {\n
+      return {start: stream.start, end: stream.pos,\n
+              string: stream.current(),\n
+              type: style || null,\n
+              state: copy ? copyState(doc.mode, state) : state};\n
+    }\n
+\n
+    var doc = cm.doc, mode = doc.mode, style;\n
+    pos = clipPos(doc, pos);\n
+    var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);\n
+    var stream = new StringStream(line.text, cm.options.tabSize), tokens;\n
+    if (asArray) tokens = [];\n
+    while ((asArray || stream.pos < pos.ch) && !stream.eol()) {\n
+      stream.start = stream.pos;\n
+      style = readToken(mode, stream, state);\n
+      if (asArray) tokens.push(getObj(true));\n
+    }\n
+    return asArray ? tokens : getObj();\n
+  }\n
+\n
+  // Run the given mode\'s parser over a line, calling f for each token.\n
+  function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {\n
     var flattenSpans = mode.flattenSpans;\n
     if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;\n
     var curStart = 0, curStyle = null;\n
     var stream = new StringStream(text, cm.options.tabSize), style;\n
-    if (text == "" && mode.blankLine) mode.blankLine(state);\n
+    var inner = cm.options.addModeClass && [null];\n
+    if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);\n
     while (!stream.eol()) {\n
       if (stream.pos > cm.options.maxHighlightLength) {\n
         flattenSpans = false;\n
@@ -4472,15 +6054,18 @@ window.CodeMirror = (function() {\n
         stream.pos = text.length;\n
         style = null;\n
       } else {\n
-        style = mode.token(stream, state);\n
+        style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);\n
       }\n
-      if (cm.options.addModeClass) {\n
-        var mName = CodeMirror.innerMode(mode, state).mode.name;\n
+      if (inner) {\n
+        var mName = inner[0].name;\n
         if (mName) style = "m-" + (style ? mName + " " + style : mName);\n
       }\n
       if (!flattenSpans || curStyle != style) {\n
-        if (curStart < stream.start) f(stream.start, curStyle);\n
-        curStart = stream.start; curStyle = style;\n
+        while (curStart < stream.start) {\n
+          curStart = Math.min(stream.start, curStart + 50000);\n
+          f(curStart, curStyle);\n
+        }\n
+        curStyle = style;\n
       }\n
       stream.start = stream.pos;\n
     }\n
@@ -4492,14 +6077,18 @@ window.CodeMirror = (function() {\n
     }\n
   }\n
 \n
+  // Compute a style array (an array starting with a mode generation\n
+  // -- for invalidation -- followed by pairs of end positions and\n
+  // style strings), which is used to highlight the tokens on the\n
+  // line.\n
   function highlightLine(cm, line, state, forceToEnd) {\n
     // A styles array always starts with a number identifying the\n
     // mode/overlays that it is based on (for easy invalidation).\n
-    var st = [cm.state.modeGen];\n
+    var st = [cm.state.modeGen], lineClasses = {};\n
     // Compute the base array of styles\n
     runMode(cm, line.text, cm.doc.mode, state, function(end, style) {\n
       st.push(end, style);\n
-    }, forceToEnd);\n
+    }, lineClasses, forceToEnd);\n
 \n
     // Run overlays, adjust style array.\n
     for (var o = 0; o < cm.state.overlays.length; ++o) {\n
@@ -4516,106 +6105,112 @@ window.CodeMirror = (function() {\n
         }\n
         if (!style) return;\n
         if (overlay.opaque) {\n
-          st.splice(start, i - start, end, style);\n
+          st.splice(start, i - start, end, "cm-overlay " + style);\n
           i = start + 2;\n
         } else {\n
           for (; start < i; start += 2) {\n
             var cur = st[start+1];\n
-            st[start+1] = cur ? cur + " " + style : style;\n
+            st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;\n
           }\n
         }\n
-      });\n
+      }, lineClasses);\n
     }\n
 \n
-    return st;\n
+    return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};\n
   }\n
 \n
-  function getLineStyles(cm, line) {\n
-    if (!line.styles || line.styles[0] != cm.state.modeGen)\n
-      line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));\n
+  function getLineStyles(cm, line, updateFrontier) {\n
+    if (!line.styles || line.styles[0] != cm.state.modeGen) {\n
+      var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));\n
+      line.styles = result.styles;\n
+      if (result.classes) line.styleClasses = result.classes;\n
+      else if (line.styleClasses) line.styleClasses = null;\n
+      if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;\n
+    }\n
     return line.styles;\n
   }\n
 \n
   // Lightweight form of highlight -- proceed over this line and\n
-  // update state, but don\'t save a style array.\n
+  // update state, but don\'t save a style array. Used for lines that\n
+  // aren\'t currently visible.\n
   function processLine(cm, text, state, startAt) {\n
     var mode = cm.doc.mode;\n
     var stream = new StringStream(text, cm.options.tabSize);\n
     stream.start = stream.pos = startAt || 0;\n
-    if (text == "" && mode.blankLine) mode.blankLine(state);\n
+    if (text == "") callBlankLine(mode, state);\n
     while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {\n
-      mode.token(stream, state);\n
+      readToken(mode, stream, state);\n
       stream.start = stream.pos;\n
     }\n
   }\n
 \n
+  // Convert a style as returned by a mode (either null, or a string\n
+  // containing one or more styles) to a CSS style. This is cached,\n
+  // and also looks for line-wide styles.\n
   var styleToClassCache = {}, styleToClassCacheWithMode = {};\n
-  function interpretTokenStyle(style, builder) {\n
-    if (!style) return null;\n
-    for (;;) {\n
-      var lineClass = style.match(/(?:^|\\s+)line-(background-)?(\\S+)/);\n
-      if (!lineClass) break;\n
-      style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);\n
-      var prop = lineClass[1] ? "bgClass" : "textClass";\n
-      if (builder[prop] == null)\n
-        builder[prop] = lineClass[2];\n
-      else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(builder[prop]))\n
-        builder[prop] += " " + lineClass[2];\n
-    }\n
-    if (/^\\s*$/.test(style)) return null;\n
-    var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;\n
+  function interpretTokenStyle(style, options) {\n
+    if (!style || /^\\s*$/.test(style)) return null;\n
+    var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;\n
     return cache[style] ||\n
       (cache[style] = style.replace(/\\S+/g, "cm-$&"));\n
   }\n
 \n
-  function buildLineContent(cm, realLine, measure, copyWidgets) {\n
-    var merged, line = realLine, empty = true;\n
-    while (merged = collapsedSpanAtStart(line))\n
-      line = getLine(cm.doc, merged.find().from.line);\n
-\n
-    var builder = {pre: elt("pre"), col: 0, pos: 0,\n
-                   measure: null, measuredSomething: false, cm: cm,\n
-                   copyWidgets: copyWidgets};\n
-\n
-    do {\n
-      if (line.text) empty = false;\n
-      builder.measure = line == realLine && measure;\n
+  // Render the DOM representation of the text of a line. Also builds\n
+  // up a \'line map\', which points at the DOM nodes that represent\n
+  // specific stretches of text, and is used by the measuring code.\n
+  // The returned object contains the DOM node, this map, and\n
+  // information about line-wide styles that were set by the mode.\n
+  function buildLineContent(cm, lineView) {\n
+    // The padding-right forces the element to have a \'border\', which\n
+    // is needed on Webkit to be able to get line-level bounding\n
+    // rectangles for it (in measureChar).\n
+    var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);\n
+    var builder = {pre: elt("pre", [content]), content: content, col: 0, pos: 0, cm: cm};\n
+    lineView.measure = {};\n
+\n
+    // Iterate over the logical lines that make up this visual line.\n
+    for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {\n
+      var line = i ? lineView.rest[i - 1] : lineView.line, order;\n
       builder.pos = 0;\n
-      builder.addToken = builder.measure ? buildTokenMeasure : buildToken;\n
+      builder.addToken = buildToken;\n
+      // Optionally wire in some hacks into the token-rendering\n
+      // algorithm, to deal with browser quirks.\n
       if ((ie || webkit) && cm.getOption("lineWrapping"))\n
         builder.addToken = buildTokenSplitSpaces(builder.addToken);\n
-      var next = insertLineContent(line, builder, getLineStyles(cm, line));\n
-      if (measure && line == realLine && !builder.measuredSomething) {\n
-        measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));\n
-        builder.measuredSomething = true;\n
-      }\n
-      if (next) line = getLine(cm.doc, next.to.line);\n
-    } while (next);\n
-\n
-    if (measure && !builder.measuredSomething && !measure[0])\n
-      measure[0] = builder.pre.appendChild(empty ? elt("span", "\\u00a0") : zeroWidthElement(cm.display.measure));\n
-    if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))\n
-      builder.pre.appendChild(document.createTextNode("\\u00a0"));\n
-\n
-    var order;\n
-    // Work around problem with the reported dimensions of single-char\n
-    // direction spans on IE (issue #1129). See also the comment in\n
-    // cursorCoords.\n
-    if (measure && ie && (order = getOrder(line))) {\n
-      var l = order.length - 1;\n
-      if (order[l].from == order[l].to) --l;\n
-      var last = order[l], prev = order[l - 1];\n
-      if (last.from + 1 == last.to && prev && last.level < prev.level) {\n
-        var span = measure[builder.pos - 1];\n
-        if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),\n
-                                               span.nextSibling);\n
-      }\n
-    }\n
-\n
-    var textClass = builder.textClass ? builder.textClass + " " + (realLine.textClass || "") : realLine.textClass;\n
-    if (textClass) builder.pre.className = textClass;\n
-\n
-    signal(cm, "renderLine", cm, realLine, builder.pre);\n
+      if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))\n
+        builder.addToken = buildTokenBadBidi(builder.addToken, order);\n
+      builder.map = [];\n
+      var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);\n
+      insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));\n
+      if (line.styleClasses) {\n
+        if (line.styleClasses.bgClass)\n
+          builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");\n
+        if (line.styleClasses.textClass)\n
+          builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");\n
+      }\n
+\n
+      // Ensure at least a single node is present, for measuring.\n
+      if (builder.map.length == 0)\n
+        builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));\n
+\n
+      // Store the map and a cache object for the current logical line\n
+      if (i == 0) {\n
+        lineView.measure.map = builder.map;\n
+        lineView.measure.cache = {};\n
+      } else {\n
+        (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);\n
+        (lineView.measure.caches || (lineView.measure.caches = [])).push({});\n
+      }\n
+    }\n
+\n
+    // See issue #2901\n
+    if (webkit && /\\bcm-tab\\b/.test(builder.content.lastChild.className))\n
+      builder.content.className = "cm-tab-wrap-hack";\n
+\n
+    signal(cm, "renderLine", cm, lineView.line, builder.pre);\n
+    if (builder.pre.className)\n
+      builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");\n
+\n
     return builder;\n
   }\n
 \n
@@ -4625,12 +6220,17 @@ window.CodeMirror = (function() {\n
     return token;\n
   }\n
 \n
-  function buildToken(builder, text, style, startStyle, endStyle, title) {\n
+  // Build up the DOM representation for a single token, and add it to\n
+  // the line map. Takes care to render special characters separately.\n
+  function buildToken(builder, text, style, startStyle, endStyle, title, css) {\n
     if (!text) return;\n
-    var special = builder.cm.options.specialChars;\n
+    var special = builder.cm.options.specialChars, mustWrap = false;\n
     if (!special.test(text)) {\n
       builder.col += text.length;\n
       var content = document.createTextNode(text);\n
+      builder.map.push(builder.pos, builder.pos + text.length, content);\n
+      if (ie && ie_version < 9) mustWrap = true;\n
+      builder.pos += text.length;\n
     } else {\n
       var content = document.createDocumentFragment(), pos = 0;\n
       while (true) {\n
@@ -4638,56 +6238,38 @@ window.CodeMirror = (function() {\n
         var m = special.exec(text);\n
         var skipped = m ? m.index - pos : text.length - pos;\n
         if (skipped) {\n
-          content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));\n
+          var txt = document.createTextNode(text.slice(pos, pos + skipped));\n
+          if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));\n
+          else content.appendChild(txt);\n
+          builder.map.push(builder.pos, builder.pos + skipped, txt);\n
           builder.col += skipped;\n
+          builder.pos += skipped;\n
         }\n
         if (!m) break;\n
         pos += skipped + 1;\n
         if (m[0] == "\\t") {\n
           var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;\n
-          content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));\n
+          var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));\n
           builder.col += tabWidth;\n
         } else {\n
-          var token = builder.cm.options.specialCharPlaceholder(m[0]);\n
-          content.appendChild(token);\n
+          var txt = builder.cm.options.specialCharPlaceholder(m[0]);\n
+          if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));\n
+          else content.appendChild(txt);\n
           builder.col += 1;\n
         }\n
+        builder.map.push(builder.pos, builder.pos + 1, txt);\n
+        builder.pos++;\n
       }\n
     }\n
-    if (style || startStyle || endStyle || builder.measure) {\n
+    if (style || startStyle || endStyle || mustWrap || css) {\n
       var fullStyle = style || "";\n
       if (startStyle) fullStyle += startStyle;\n
       if (endStyle) fullStyle += endStyle;\n
-      var token = elt("span", [content], fullStyle);\n
+      var token = elt("span", [content], fullStyle, css);\n
       if (title) token.title = title;\n
-      return builder.pre.appendChild(token);\n
-    }\n
-    builder.pre.appendChild(content);\n
-  }\n
-\n
-  function buildTokenMeasure(builder, text, style, startStyle, endStyle) {\n
-    var wrapping = builder.cm.options.lineWrapping;\n
-    for (var i = 0; i < text.length; ++i) {\n
-      var start = i == 0, to = i + 1;\n
-      while (to < text.length && isExtendingChar(text.charAt(to))) ++to;\n
-      var ch = text.slice(i, to);\n
-      i = to - 1;\n
-      if (i && wrapping && spanAffectsWrapping(text, i))\n
-        builder.pre.appendChild(elt("wbr"));\n
-      var old = builder.measure[builder.pos];\n
-      var span = builder.measure[builder.pos] =\n
-        buildToken(builder, ch, style,\n
-                   start && startStyle, i == text.length - 1 && endStyle);\n
-      if (old) span.leftSide = old.leftSide || old;\n
-      // In IE single-space nodes wrap differently than spaces\n
-      // embedded in larger text nodes, except when set to\n
-      // white-space: normal (issue #1268).\n
-      if (old_ie && wrapping && ch == " " && i && !/\\s/.test(text.charAt(i - 1)) &&\n
-          i < text.length - 1 && !/\\s/.test(text.charAt(i + 1)))\n
-        span.style.whiteSpace = "normal";\n
-      builder.pos += ch.length;\n
-    }\n
-    if (text.length) builder.measuredSomething = true;\n
+      return builder.content.appendChild(token);\n
+    }\n
+    builder.content.appendChild(content);\n
   }\n
 \n
   function buildTokenSplitSpaces(inner) {\n
@@ -4698,29 +6280,36 @@ window.CodeMirror = (function() {\n
       return out;\n
     }\n
     return function(builder, text, style, startStyle, endStyle, title) {\n
-      return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);\n
+      inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);\n
     };\n
   }\n
 \n
-  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {\n
-    var widget = !ignoreWidget && marker.replacedWith;\n
-    if (widget) {\n
-      if (builder.copyWidgets) widget = widget.cloneNode(true);\n
-      builder.pre.appendChild(widget);\n
-      if (builder.measure) {\n
-        if (size) {\n
-          builder.measure[builder.pos] = widget;\n
-        } else {\n
-          var elt = zeroWidthElement(builder.cm.display.measure);\n
-          if (marker.type == "bookmark" && !marker.insertLeft)\n
-            builder.measure[builder.pos] = builder.pre.appendChild(elt);\n
-          else if (builder.measure[builder.pos])\n
-            return;\n
-          else\n
-            builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);\n
+  // Work around nonsense dimensions being reported for stretches of\n
+  // right-to-left text.\n
+  function buildTokenBadBidi(inner, order) {\n
+    return function(builder, text, style, startStyle, endStyle, title) {\n
+      style = style ? style + " cm-force-border" : "cm-force-border";\n
+      var start = builder.pos, end = start + text.length;\n
+      for (;;) {\n
+        // Find the part that overlaps with the start of this text\n
+        for (var i = 0; i < order.length; i++) {\n
+          var part = order[i];\n
+          if (part.to > start && part.from <= start) break;\n
         }\n
-        builder.measuredSomething = true;\n
+        if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title);\n
+        inner(builder, text.slice(0, part.to - start), style, startStyle, null, title);\n
+        startStyle = null;\n
+        text = text.slice(part.to - start);\n
+        start = part.to;\n
       }\n
+    };\n
+  }\n
+\n
+  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {\n
+    var widget = !ignoreWidget && marker.widgetNode;\n
+    if (widget) {\n
+      builder.map.push(builder.pos, builder.pos + size, widget);\n
+      builder.content.appendChild(widget);\n
     }\n
     builder.pos += size;\n
   }\n
@@ -4731,15 +6320,15 @@ window.CodeMirror = (function() {\n
     var spans = line.markedSpans, allText = line.text, at = 0;\n
     if (!spans) {\n
       for (var i = 1; i < styles.length; i+=2)\n
-        builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));\n
+        builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));\n
       return;\n
     }\n
 \n
-    var len = allText.length, pos = 0, i = 1, text = "", style;\n
+    var len = allText.length, pos = 0, i = 1, text = "", style, css;\n
     var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;\n
     for (;;) {\n
       if (nextChange == pos) { // Update current marker set\n
-        spanStyle = spanEndStyle = spanStartStyle = title = "";\n
+        spanStyle = spanEndStyle = spanStartStyle = title = css = "";\n
         collapsed = null; nextChange = Infinity;\n
         var foundBookmarks = [];\n
         for (var j = 0; j < spans.length; ++j) {\n
@@ -4747,6 +6336,7 @@ window.CodeMirror = (function() {\n
           if (sp.from <= pos && (sp.to == null || sp.to > pos)) {\n
             if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }\n
             if (m.className) spanStyle += " " + m.className;\n
+            if (m.css) css = m.css;\n
             if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;\n
             if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;\n
             if (m.title && !title) title = m.title;\n
@@ -4755,12 +6345,12 @@ window.CodeMirror = (function() {\n
           } else if (sp.from > pos && nextChange > sp.from) {\n
             nextChange = sp.from;\n
           }\n
-          if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);\n
+          if (m.type == "bookmark" && sp.from == pos && m.widgetNode) foundBookmarks.push(m);\n
         }\n
         if (collapsed && (collapsed.from || 0) == pos) {\n
-          buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,\n
+          buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,\n
                              collapsed.marker, collapsed.from == null);\n
-          if (collapsed.to == null) return collapsed.marker.find();\n
+          if (collapsed.to == null) return;\n
         }\n
         if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)\n
           buildCollapsedSpan(builder, 0, foundBookmarks[j]);\n
@@ -4774,21 +6364,30 @@ window.CodeMirror = (function() {\n
           if (!collapsed) {\n
             var tokenText = end > upto ? text.slice(0, upto - pos) : text;\n
             builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,\n
-                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);\n
+                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);\n
           }\n
           if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}\n
           pos = end;\n
           spanStartStyle = "";\n
         }\n
         text = allText.slice(at, at = styles[i++]);\n
-        style = interpretTokenStyle(styles[i++], builder);\n
+        style = interpretTokenStyle(styles[i++], builder.cm.options);\n
       }\n
     }\n
   }\n
 \n
   // DOCUMENT DATA STRUCTURE\n
 \n
-  function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {\n
+  // By default, updates that start and end at the beginning of a line\n
+  // are treated specially, in order to make the association of line\n
+  // widgets and marker elements with the text behave more intuitive.\n
+  function isWholeLineUpdate(doc, change) {\n
+    return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&\n
+      (!doc.cm || doc.cm.options.wholeLineUpdateBefore);\n
+  }\n
+\n
+  // Perform a change on the document data structure.\n
+  function updateDoc(doc, change, markedSpans, estimateHeight) {\n
     function spansFor(n) {return markedSpans ? markedSpans[n] : null;}\n
     function update(line, text, spans) {\n
       updateLine(line, text, spans, estimateHeight);\n
@@ -4799,12 +6398,11 @@ window.CodeMirror = (function() {\n
     var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);\n
     var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;\n
 \n
-    // First adjust the line structure\n
-    if (from.ch == 0 && to.ch == 0 && lastText == "" &&\n
-        (!doc.cm || doc.cm.options.wholeLineUpdateBefore)) {\n
+    // Adjust the line structure\n
+    if (isWholeLineUpdate(doc, change)) {\n
       // This is a whole-line replace. Treated specially to make\n
       // sure line objects move the way they are supposed to.\n
-      for (var i = 0, e = text.length - 1, added = []; i < e; ++i)\n
+      for (var i = 0, added = []; i < text.length - 1; ++i)\n
         added.push(new Line(text[i], spansFor(i), estimateHeight));\n
       update(lastLine, lastLine.text, lastSpans);\n
       if (nlines) doc.remove(from.line, nlines);\n
@@ -4813,7 +6411,7 @@ window.CodeMirror = (function() {\n
       if (text.length == 1) {\n
         update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);\n
       } else {\n
-        for (var added = [], i = 1, e = text.length - 1; i < e; ++i)\n
+        for (var added = [], i = 1; i < text.length - 1; ++i)\n
           added.push(new Line(text[i], spansFor(i), estimateHeight));\n
         added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));\n
         update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n
@@ -4825,20 +6423,32 @@ window.CodeMirror = (function() {\n
     } else {\n
       update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n
       update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);\n
-      for (var i = 1, e = text.length - 1, added = []; i < e; ++i)\n
+      for (var i = 1, added = []; i < text.length - 1; ++i)\n
         added.push(new Line(text[i], spansFor(i), estimateHeight));\n
       if (nlines > 1) doc.remove(from.line + 1, nlines - 1);\n
       doc.insert(from.line + 1, added);\n
     }\n
 \n
     signalLater(doc, "change", doc, change);\n
-    setSelection(doc, selAfter.anchor, selAfter.head, null, true);\n
   }\n
+\n
+  // The document is represented as a BTree consisting of leaves, with\n
+  // chunk of lines in them, and branches, with up to ten leaves or\n
+  // other branch nodes below them. The top node is always a branch\n
+  // node, and is the document object itself (meaning it has\n
+  // additional methods and properties).\n
+  //\n
+  // All nodes have parent links. The tree is used both to go from\n
+  // line numbers to line objects, and to go from objects to numbers.\n
+  // It also indexes by height, and is used to convert between height\n
+  // and line object, and to find the total height of the document.\n
+  //\n
+  // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html\n
 \n
   function LeafChunk(lines) {\n
     this.lines = lines;\n
     this.parent = null;\n
-    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {\n
+    for (var i = 0, height = 0; i < lines.length; ++i) {\n
       lines[i].parent = this;\n
       height += lines[i].height;\n
     }\n
@@ -4847,6 +6457,7 @@ window.CodeMirror = (function() {\n
 \n
   LeafChunk.prototype = {\n
     chunkSize: function() { return this.lines.length; },\n
+    // Remove the n lines at offset \'at\'.\n
     removeInner: function(at, n) {\n
       for (var i = at, e = at + n; i < e; ++i) {\n
         var line = this.lines[i];\n
@@ -4856,14 +6467,18 @@ window.CodeMirror = (function() {\n
       }\n
       this.lines.splice(at, n);\n
     },\n
+    // Helper used to collapse a small branch into a single leaf.\n
     collapse: function(lines) {\n
-      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));\n
+      lines.push.apply(lines, this.lines);\n
     },\n
+    // Insert the given array of lines at offset \'at\', count them as\n
+    // having the given height.\n
     insertInner: function(at, lines, height) {\n
       this.height += height;\n
       this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));\n
-      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;\n
+      for (var i = 0; i < lines.length; ++i) lines[i].parent = this;\n
     },\n
+    // Used to iterate over a part of the tree.\n
     iterN: function(at, n, op) {\n
       for (var e = at + n; at < e; ++at)\n
         if (op(this.lines[at])) return true;\n
@@ -4873,7 +6488,7 @@ window.CodeMirror = (function() {\n
   function BranchChunk(children) {\n
     this.children = children;\n
     var size = 0, height = 0;\n
-    for (var i = 0, e = children.length; i < e; ++i) {\n
+    for (var i = 0; i < children.length; ++i) {\n
       var ch = children[i];\n
       size += ch.chunkSize(); height += ch.height;\n
       ch.parent = this;\n
@@ -4898,7 +6513,10 @@ window.CodeMirror = (function() {\n
           at = 0;\n
         } else at -= sz;\n
       }\n
-      if (this.size - n < 25) {\n
+      // If the result is smaller than 25 lines, ensure that it is a\n
+      // single leaf node.\n
+      if (this.size - n < 25 &&\n
+          (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {\n
         var lines = [];\n
         this.collapse(lines);\n
         this.children = [new LeafChunk(lines)];\n
@@ -4906,12 +6524,12 @@ window.CodeMirror = (function() {\n
       }\n
     },\n
     collapse: function(lines) {\n
-      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);\n
+      for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);\n
     },\n
     insertInner: function(at, lines, height) {\n
       this.size += lines.length;\n
       this.height += height;\n
-      for (var i = 0, e = this.children.length; i < e; ++i) {\n
+      for (var i = 0; i < this.children.length; ++i) {\n
         var child = this.children[i], sz = child.chunkSize();\n
         if (at <= sz) {\n
           child.insertInner(at, lines, height);\n
@@ -4930,6 +6548,7 @@ window.CodeMirror = (function() {\n
         at -= sz;\n
       }\n
     },\n
+    // When a node has grown, check whether it should be split.\n
     maybeSpill: function() {\n
       if (this.children.length <= 10) return;\n
       var me = this;\n
@@ -4952,7 +6571,7 @@ window.CodeMirror = (function() {\n
       me.parent.maybeSpill();\n
     },\n
     iterN: function(at, n, op) {\n
-      for (var i = 0, e = this.children.length; i < e; ++i) {\n
+      for (var i = 0; i < this.children.length; ++i) {\n
         var child = this.children[i], sz = child.chunkSize();\n
         if (at < sz) {\n
           var used = Math.min(n, sz - at);\n
@@ -4973,43 +6592,52 @@ window.CodeMirror = (function() {\n
     this.first = firstLine;\n
     this.scrollTop = this.scrollLeft = 0;\n
     this.cantEdit = false;\n
-    this.history = makeHistory();\n
     this.cleanGeneration = 1;\n
     this.frontier = firstLine;\n
     var start = Pos(firstLine, 0);\n
-    this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};\n
+    this.sel = simpleSelection(start);\n
+    this.history = new History(null);\n
     this.id = ++nextDocId;\n
     this.modeOption = mode;\n
 \n
     if (typeof text == "string") text = splitLines(text);\n
-    updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});\n
+    updateDoc(this, {from: start, to: start, text: text});\n
+    setSelection(this, simpleSelection(start), sel_dontScroll);\n
   };\n
 \n
   Doc.prototype = createObj(BranchChunk.prototype, {\n
     constructor: Doc,\n
+    // Iterate over the document. Supports two forms -- with only one\n
+    // argument, it calls that for each line in the document. With\n
+    // three, it iterates over the range given by the first two (with\n
+    // the second being non-inclusive).\n
     iter: function(from, to, op) {\n
       if (op) this.iterN(from - this.first, to - from, op);\n
       else this.iterN(this.first, this.first + this.size, from);\n
     },\n
 \n
+    // Non-public interface for adding and removing lines.\n
     insert: function(at, lines) {\n
       var height = 0;\n
-      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;\n
+      for (var i = 0; i < lines.length; ++i) height += lines[i].height;\n
       this.insertInner(at - this.first, lines, height);\n
     },\n
     remove: function(at, n) { this.removeInner(at - this.first, n); },\n
+\n
+    // From here, the methods are part of the public interface. Most\n
+    // are also available from CodeMirror (editor) instances.\n
 \n
     getValue: function(lineSep) {\n
       var lines = getLines(this, this.first, this.first + this.size);\n
       if (lineSep === false) return lines;\n
       return lines.join(lineSep || "\\n");\n
     },\n
-    setValue: function(code) {\n
+    setValue: docMethodOp(function(code) {\n
       var top = Pos(this.first, 0), last = this.first + this.size - 1;\n
       makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),\n
-                        text: splitLines(code), origin: "setValue"},\n
-                 {head: top, anchor: top}, true);\n
-    },\n
+                        text: splitLines(code), origin: "setValue"}, true);\n
+      setSelection(this, simpleSelection(top));\n
+    }),\n
     replaceRange: function(code, from, to, origin) {\n
       from = clipPos(this, from);\n
       to = to ? clipPos(this, to) : from;\n
@@ -5022,21 +6650,13 @@ window.CodeMirror = (function() {\n
     },\n
 \n
     getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},\n
-    setLine: function(line, text) {\n
-      if (isLine(this, line))\n
-        replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));\n
-    },\n
-    removeLine: function(line) {\n
-      if (line) replaceRange(this, "", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));\n
-      else replaceRange(this, "", Pos(0, 0), clipPos(this, Pos(1, 0)));\n
-    },\n
 \n
     getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},\n
     getLineNumber: function(line) {return lineNo(line);},\n
 \n
     getLineHandleVisualStart: function(line) {\n
       if (typeof line == "number") line = getLine(this, line);\n
-      return visualLine(this, line);\n
+      return visualLine(line);\n
     },\n
 \n
     lineCount: function() {return this.size;},\n
@@ -5046,48 +6666,103 @@ window.CodeMirror = (function() {\n
     clipPos: function(pos) {return clipPos(this, pos);},\n
 \n
     getCursor: function(start) {\n
-      var sel = this.sel, pos;\n
-      if (start == null || start == "head") pos = sel.head;\n
-      else if (start == "anchor") pos = sel.anchor;\n
-      else if (start == "end" || start === false) pos = sel.to;\n
-      else pos = sel.from;\n
-      return copyPos(pos);\n
+      var range = this.sel.primary(), pos;\n
+      if (start == null || start == "head") pos = range.head;\n
+      else if (start == "anchor") pos = range.anchor;\n
+      else if (start == "end" || start == "to" || start === false) pos = range.to();\n
+      else pos = range.from();\n
+      return pos;\n
     },\n
-    somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},\n
+    listSelections: function() { return this.sel.ranges; },\n
+    somethingSelected: function() {return this.sel.somethingSelected();},\n
 \n
-    setCursor: docOperation(function(line, ch, extend) {\n
-      var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);\n
-      if (extend) extendSelection(this, pos);\n
-      else setSelection(this, pos, pos);\n
+    setCursor: docMethodOp(function(line, ch, options) {\n
+      setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);\n
+    }),\n
+    setSelection: docMethodOp(function(anchor, head, options) {\n
+      setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);\n
+    }),\n
+    extendSelection: docMethodOp(function(head, other, options) {\n
+      extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);\n
+    }),\n
+    extendSelections: docMethodOp(function(heads, options) {\n
+      extendSelections(this, clipPosArray(this, heads, options));\n
     }),\n
-    setSelection: docOperation(function(anchor, head, bias) {\n
-      setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);\n
+    extendSelectionsBy: docMethodOp(function(f, options) {\n
+      extendSelections(this, map(this.sel.ranges, f), options);\n
     }),\n
-    extendSelection: docOperation(function(from, to, bias) {\n
-      extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);\n
+    setSelections: docMethodOp(function(ranges, primary, options) {\n
+      if (!ranges.length) return;\n
+      for (var i = 0, out = []; i < ranges.length; i++)\n
+        out[i] = new Range(clipPos(this, ranges[i].anchor),\n
+                           clipPos(this, ranges[i].head));\n
+      if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);\n
+      setSelection(this, normalizeSelection(out, primary), options);\n
+    }),\n
+    addSelection: docMethodOp(function(anchor, head, options) {\n
+      var ranges = this.sel.ranges.slice(0);\n
+      ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));\n
+      setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);\n
     }),\n
 \n
-    getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},\n
+    getSelection: function(lineSep) {\n
+      var ranges = this.sel.ranges, lines;\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var sel = getBetween(this, ranges[i].from(), ranges[i].to());\n
+        lines = lines ? lines.concat(sel) : sel;\n
+      }\n
+      if (lineSep === false) return lines;\n
+      else return lines.join(lineSep || "\\n");\n
+    },\n
+    getSelections: function(lineSep) {\n
+      var parts = [], ranges = this.sel.ranges;\n
+      for (var i = 0; i < ranges.length; i++) {\n
+        var sel = getBetween(this, ranges[i].from(), ranges[i].to());\n
+        if (lineSep !== false) sel = sel.join(lineSep || "\\n");\n
+        parts[i] = sel;\n
+      }\n
+      return parts;\n
+    },\n
     replaceSelection: function(code, collapse, origin) {\n
-      makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");\n
+      var dup = [];\n
+      for (var i = 0; i < this.sel.ranges.length; i++)\n
+        dup[i] = code;\n
+      this.replaceSelections(dup, collapse, origin || "+input");\n
     },\n
-    undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),\n
-    redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),\n
+    replaceSelections: docMethodOp(function(code, collapse, origin) {\n
+      var changes = [], sel = this.sel;\n
+      for (var i = 0; i < sel.ranges.length; i++) {\n
+        var range = sel.ranges[i];\n
+        changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};\n
+      }\n
+      var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);\n
+      for (var i = changes.length - 1; i >= 0; i--)\n
+        makeChange(this, changes[i]);\n
+      if (newSel) setSelectionReplaceHistory(this, newSel);\n
+      else if (this.cm) ensureCursorVisible(this.cm);\n
+    }),\n
+    undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),\n
+    redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),\n
+    undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),\n
+    redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),\n
 \n
-    setExtending: function(val) {this.sel.extend = val;},\n
+    setExtending: function(val) {this.extend = val;},\n
+    getExtending: function() {return this.extend;},\n
 \n
     historySize: function() {\n
-      var hist = this.history;\n
-      return {undo: hist.done.length, redo: hist.undone.length};\n
+      var hist = this.history, done = 0, undone = 0;\n
+      for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;\n
+      for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;\n
+      return {undo: done, redo: undone};\n
     },\n
-    clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},\n
+    clearHistory: function() {this.history = new History(this.history.maxGeneration);},\n
 \n
     markClean: function() {\n
       this.cleanGeneration = this.changeGeneration(true);\n
     },\n
     changeGeneration: function(forceSplit) {\n
       if (forceSplit)\n
-        this.history.lastOp = this.history.lastOrigin = null;\n
+        this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;\n
       return this.history.generation;\n
     },\n
     isClean: function (gen) {\n
@@ -5099,10 +6774,39 @@ window.CodeMirror = (function() {\n
               undone: copyHistoryArray(this.history.undone)};\n
     },\n
     setHistory: function(histData) {\n
-      var hist = this.history = makeHistory(this.history.maxGeneration);\n
-      hist.done = histData.done.slice(0);\n
-      hist.undone = histData.undone.slice(0);\n
+      var hist = this.history = new History(this.history.maxGeneration);\n
+      hist.done = copyHistoryArray(histData.done.slice(0), null, true);\n
+      hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);\n
     },\n
+\n
+    addLineClass: docMethodOp(function(handle, where, cls) {\n
+      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {\n
+        var prop = where == "text" ? "textClass"\n
+                 : where == "background" ? "bgClass"\n
+                 : where == "gutter" ? "gutterClass" : "wrapClass";\n
+        if (!line[prop]) line[prop] = cls;\n
+        else if (classTest(cls).test(line[prop])) return false;\n
+        else line[prop] += " " + cls;\n
+        return true;\n
+      });\n
+    }),\n
+    removeLineClass: docMethodOp(function(handle, where, cls) {\n
+      return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {\n
+        var prop = where == "text" ? "textClass"\n
+                 : where == "background" ? "bgClass"\n
+                 : where == "gutter" ? "gutterClass" : "wrapClass";\n
+        var cur = line[prop];\n
+        if (!cur) return false;\n
+        else if (cls == null) line[prop] = null;\n
+        else {\n
+          var found = cur.match(classTest(cls));\n
+          if (!found) return false;\n
+          var end = found.index + found[0].length;\n
+          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;\n
+        }\n
+        return true;\n
+      });\n
+    }),\n
 \n
     markText: function(from, to, options) {\n
       return markText(this, clipPos(this, from), clipPos(this, to), options, "range");\n
@@ -5110,7 +6814,7 @@ window.CodeMirror = (function() {\n
     setBookmark: function(pos, options) {\n
       var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),\n
                       insertLeft: options && options.insertLeft,\n
-                      clearWhenEmpty: false};\n
+                      clearWhenEmpty: false, shared: options && options.shared};\n
       pos = clipPos(this, pos);\n
       return markText(this, pos, pos, realOpts, "bookmark");\n
     },\n
@@ -5125,7 +6829,7 @@ window.CodeMirror = (function() {\n
       }\n
       return markers;\n
     },\n
-    findMarks: function(from, to) {\n
+    findMarks: function(from, to, filter) {\n
       from = clipPos(this, from); to = clipPos(this, to);\n
       var found = [], lineNo = from.line;\n
       this.iter(from.line, to.line + 1, function(line) {\n
@@ -5134,7 +6838,8 @@ window.CodeMirror = (function() {\n
           var span = spans[i];\n
           if (!(lineNo == from.line && from.ch > span.to ||\n
                 span.from == null && lineNo != from.line||\n
-                lineNo == to.line && span.from > to.ch))\n
+                lineNo == to.line && span.from > to.ch) &&\n
+              (!filter || filter(span.marker)))\n
             found.push(span.marker.parent || span.marker);\n
         }\n
         ++lineNo;\n
@@ -5174,8 +6879,8 @@ window.CodeMirror = (function() {\n
     copy: function(copyHistory) {\n
       var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);\n
       doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;\n
-      doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,\n
-                 shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};\n
+      doc.sel = this.sel;\n
+      doc.extend = false;\n
       if (copyHistory) {\n
         doc.history.undoDepth = this.history.undoDepth;\n
         doc.setHistory(this.getHistory());\n
@@ -5192,6 +6897,7 @@ window.CodeMirror = (function() {\n
       if (options.sharedHist) copy.history = this.history;\n
       (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});\n
       copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];\n
+      copySharedMarkers(copy, findSharedMarkers(this));\n
       return copy;\n
     },\n
     unlinkDoc: function(other) {\n
@@ -5201,13 +6907,14 @@ window.CodeMirror = (function() {\n
         if (link.doc != other) continue;\n
         this.linked.splice(i, 1);\n
         other.unlinkDoc(this);\n
+        detachSharedMarkers(findSharedMarkers(this));\n
         break;\n
       }\n
       // If the histories were shared, split them again\n
       if (other.history == this.history) {\n
         var splitIds = [other.id];\n
         linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);\n
-        other.history = makeHistory();\n
+        other.history = new History(null);\n
         other.history.done = copyHistoryArray(this.history.done, splitIds);\n
         other.history.undone = copyHistoryArray(this.history.undone, splitIds);\n
       }\n
@@ -5218,9 +6925,10 @@ window.CodeMirror = (function() {\n
     getEditor: function() {return this.cm;}\n
   });\n
 \n
+  // Public alias.\n
   Doc.prototype.eachLine = Doc.prototype.iter;\n
 \n
-  // The Doc methods that should be available on CodeMirror instances\n
+  // Set up methods on CodeMirror\'s prototype to redirect to the editor\'s document.\n
   var dontDelegate = "iter insert remove copy getEditor".split(" ");\n
   for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)\n
     CodeMirror.prototype[prop] = (function(method) {\n
@@ -5229,6 +6937,7 @@ window.CodeMirror = (function() {\n
 \n
   eventMixin(Doc);\n
 \n
+  // Call f for all linked documents.\n
   function linkedDocs(doc, f, sharedHistOnly) {\n
     function propagate(doc, skip, sharedHist) {\n
       if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {\n
@@ -5243,22 +6952,25 @@ window.CodeMirror = (function() {\n
     propagate(doc, null, true);\n
   }\n
 \n
+  // Attach a document to an editor.\n
   function attachDoc(cm, doc) {\n
     if (doc.cm) throw new Error("This document is already in use.");\n
     cm.doc = doc;\n
     doc.cm = cm;\n
     estimateLineHeights(cm);\n
     loadMode(cm);\n
-    if (!cm.options.lineWrapping) computeMaxLength(cm);\n
+    if (!cm.options.lineWrapping) findMaxLine(cm);\n
     cm.options.mode = doc.modeOption;\n
     regChange(cm);\n
   }\n
 \n
   // LINE UTILITIES\n
 \n
-  function getLine(chunk, n) {\n
-    n -= chunk.first;\n
-    while (!chunk.lines) {\n
+  // Find the line object corresponding to the given line number.\n
+  function getLine(doc, n) {\n
+    n -= doc.first;\n
+    if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");\n
+    for (var chunk = doc; !chunk.lines;) {\n
       for (var i = 0;; ++i) {\n
         var child = chunk.children[i], sz = child.chunkSize();\n
         if (n < sz) { chunk = child; break; }\n
@@ -5268,6 +6980,8 @@ window.CodeMirror = (function() {\n
     return chunk.lines[n];\n
   }\n
 \n
+  // Get the part of a document between two positions, as an array of\n
+  // strings.\n
   function getBetween(doc, start, end) {\n
     var out = [], n = start.line;\n
     doc.iter(start.line, end.line + 1, function(line) {\n
@@ -5279,17 +6993,22 @@ window.CodeMirror = (function() {\n
     });\n
     return out;\n
   }\n
+  // Get the lines between from and to, as array of strings.\n
   function getLines(doc, from, to) {\n
     var out = [];\n
     doc.iter(from, to, function(line) { out.push(line.text); });\n
     return out;\n
   }\n
 \n
+  // Update the height of a line, propagating the height change\n
+  // upwards to parent nodes.\n
   function updateLineHeight(line, height) {\n
     var diff = height - line.height;\n
-    for (var n = line; n; n = n.parent) n.height += diff;\n
+    if (diff) for (var n = line; n; n = n.parent) n.height += diff;\n
   }\n
 \n
+  // Given a line object, find its line number by walking up through\n
+  // its parent links.\n
   function lineNo(line) {\n
     if (line.parent == null) return null;\n
     var cur = line.parent, no = indexOf(cur.lines, line);\n
@@ -5302,10 +7021,12 @@ window.CodeMirror = (function() {\n
     return no + cur.first;\n
   }\n
 \n
+  // Find the line at the given vertical position, using the height\n
+  // information in the document tree.\n
   function lineAtHeight(chunk, h) {\n
     var n = chunk.first;\n
     outer: do {\n
-      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n
+      for (var i = 0; i < chunk.children.length; ++i) {\n
         var child = chunk.children[i], ch = child.height;\n
         if (h < ch) { chunk = child; continue outer; }\n
         h -= ch;\n
@@ -5313,7 +7034,7 @@ window.CodeMirror = (function() {\n
       }\n
       return n;\n
     } while (!chunk.lines);\n
-    for (var i = 0, e = chunk.lines.length; i < e; ++i) {\n
+    for (var i = 0; i < chunk.lines.length; ++i) {\n
       var line = chunk.lines[i], lh = line.height;\n
       if (h < lh) break;\n
       h -= lh;\n
@@ -5321,8 +7042,10 @@ window.CodeMirror = (function() {\n
     return n + i;\n
   }\n
 \n
-  function heightAtLine(cm, lineObj) {\n
-    lineObj = visualLine(cm.doc, lineObj);\n
+\n
+  // Find the height above the given line.\n
+  function heightAtLine(lineObj) {\n
+    lineObj = visualLine(lineObj);\n
 \n
     var h = 0, chunk = lineObj.parent;\n
     for (var i = 0; i < chunk.lines.length; ++i) {\n
@@ -5340,6 +7063,9 @@ window.CodeMirror = (function() {\n
     return h;\n
   }\n
 \n
+  // Get the bidi ordering for the given line (and cache it). Returns\n
+  // false for lines that are fully left-to-right, and an array of\n
+  // BidiSpan objects otherwise.\n
   function getOrder(line) {\n
     var order = line.order;\n
     if (order == null) order = line.order = bidiOrdering(line.text);\n
@@ -5348,50 +7074,70 @@ window.CodeMirror = (function() {\n
 \n
   // HISTORY\n
 \n
-  function makeHistory(startGen) {\n
-    return {\n
-      // Arrays of history events. Doing something adds an event to\n
-      // done and clears undo. Undoing moves events from done to\n
-      // undone, redoing moves them in the other direction.\n
-      done: [], undone: [], undoDepth: Infinity,\n
-      // Used to track when changes can be merged into a single undo\n
-      // event\n
-      lastTime: 0, lastOp: null, lastOrigin: null,\n
-      // Used by the isClean() method\n
-      generation: startGen || 1, maxGeneration: startGen || 1\n
-    };\n
-  }\n
-\n
-  function attachLocalSpans(doc, change, from, to) {\n
-    var existing = change["spans_" + doc.id], n = 0;\n
-    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {\n
-      if (line.markedSpans)\n
-        (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;\n
-      ++n;\n
-    });\n
-  }\n
-\n
+  function History(startGen) {\n
+    // Arrays of change events and selections. Doing something adds an\n
+    // event to done and clears undo. Undoing moves events from done\n
+    // to undone, redoing moves them in the other direction.\n
+    this.done = []; this.undone = [];\n
+    this.undoDepth = Infinity;\n
+    // Used to track when changes can be merged into a single undo\n
+    // event\n
+    this.lastModTime = this.lastSelTime = 0;\n
+    this.lastOp = this.lastSelOp = null;\n
+    this.lastOrigin = this.lastSelOrigin = null;\n
+    // Used by the isClean() method\n
+    this.generation = this.maxGeneration = startGen || 1;\n
+  }\n
+\n
+  // Create a history change event from an updateDoc-style change\n
+  // object.\n
   function historyChangeFromChange(doc, change) {\n
-    var from = { line: change.from.line, ch: change.from.ch };\n
-    var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};\n
+    var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};\n
     attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);\n
     linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);\n
     return histChange;\n
   }\n
 \n
-  function addToHistory(doc, change, selAfter, opId) {\n
+  // Pop all selection events off the end of a history array. Stop at\n
+  // a change event.\n
+  function clearSelectionEvents(array) {\n
+    while (array.length) {\n
+      var last = lst(array);\n
+      if (last.ranges) array.pop();\n
+      else break;\n
+    }\n
+  }\n
+\n
+  // Find the top change event in the history. Pop off selection\n
+  // events that are in the way.\n
+  function lastChangeEvent(hist, force) {\n
+    if (force) {\n
+      clearSelectionEvents(hist.done);\n
+      return lst(hist.done);\n
+    } else if (hist.done.length && !lst(hist.done).ranges) {\n
+      return lst(hist.done);\n
+    } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {\n
+      hist.done.pop();\n
+      return lst(hist.done);\n
+    }\n
+  }\n
+\n
+  // Register a change in the history. Merges changes that are within\n
+  // a single operation, ore are close together with an origin that\n
+  // allows merging (starting with "+") into a single event.\n
+  function addChangeToHistory(doc, change, selAfter, opId) {\n
     var hist = doc.history;\n
     hist.undone.length = 0;\n
-    var time = +new Date, cur = lst(hist.done);\n
+    var time = +new Date, cur;\n
 \n
-    if (cur &&\n
-        (hist.lastOp == opId ||\n
+    if ((hist.lastOp == opId ||\n
          hist.lastOrigin == change.origin && change.origin &&\n
-         ((change.origin.charAt(0) == "+" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||\n
-          change.origin.charAt(0) == "*"))) {\n
+         ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||\n
+          change.origin.charAt(0) == "*")) &&\n
+        (cur = lastChangeEvent(hist, hist.lastOp == opId))) {\n
       // Merge this change into the last event\n
       var last = lst(cur.changes);\n
-      if (posEq(change.from, change.to) && posEq(change.from, last.to)) {\n
+      if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {\n
         // Optimized case for simple insertion -- don\'t want to add\n
         // new changesets for every character typed\n
         last.to = changeEnd(change);\n
@@ -5399,25 +7145,81 @@ window.CodeMirror = (function() {\n
         // Add new sub-event\n
         cur.changes.push(historyChangeFromChange(doc, change));\n
       }\n
-      cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;\n
     } else {\n
       // Can not be merged, start a new event.\n
+      var before = lst(hist.done);\n
+      if (!before || !before.ranges)\n
+        pushSelectionToHistory(doc.sel, hist.done);\n
       cur = {changes: [historyChangeFromChange(doc, change)],\n
-             generation: hist.generation,\n
-             anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,\n
-             anchorAfter: selAfter.anchor, headAfter: selAfter.head};\n
+             generation: hist.generation};\n
       hist.done.push(cur);\n
-      while (hist.done.length > hist.undoDepth)\n
+      while (hist.done.length > hist.undoDepth) {\n
         hist.done.shift();\n
+        if (!hist.done[0].ranges) hist.done.shift();\n
+      }\n
     }\n
+    hist.done.push(selAfter);\n
     hist.generation = ++hist.maxGeneration;\n
-    hist.lastTime = time;\n
-    hist.lastOp = opId;\n
-    hist.lastOrigin = change.origin;\n
+    hist.lastModTime = hist.lastSelTime = time;\n
+    hist.lastOp = hist.lastSelOp = opId;\n
+    hist.lastOrigin = hist.lastSelOrigin = change.origin;\n
 \n
     if (!last) signal(doc, "historyAdded");\n
   }\n
 \n
+  function selectionEventCanBeMerged(doc, origin, prev, sel) {\n
+    var ch = origin.charAt(0);\n
+    return ch == "*" ||\n
+      ch == "+" &&\n
+      prev.ranges.length == sel.ranges.length &&\n
+      prev.somethingSelected() == sel.somethingSelected() &&\n
+      new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);\n
+  }\n
+\n
+  // Called whenever the selection changes, sets the new selection as\n
+  // the pending selection in the history, and pushes the old pending\n
+  // selection into the \'done\' array when it was significantly\n
+  // different (in number of selected ranges, emptiness, or time).\n
+  function addSelectionToHistory(doc, sel, opId, options) {\n
+    var hist = doc.history, origin = options && options.origin;\n
+\n
+    // A new event is started when the previous origin does not match\n
+    // the current, or the origins don\'t allow matching. Origins\n
+    // starting with * are always merged, those starting with + are\n
+    // merged when similar and close together in time.\n
+    if (opId == hist.lastSelOp ||\n
+        (origin && hist.lastSelOrigin == origin &&\n
+         (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||\n
+          selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))\n
+      hist.done[hist.done.length - 1] = sel;\n
+    else\n
+      pushSelectionToHistory(sel, hist.done);\n
+\n
+    hist.lastSelTime = +new Date;\n
+    hist.lastSelOrigin = origin;\n
+    hist.lastSelOp = opId;\n
+    if (options && options.clearRedo !== false)\n
+      clearSelectionEvents(hist.undone);\n
+  }\n
+\n
+  function pushSelectionToHistory(sel, dest) {\n
+    var top = lst(dest);\n
+    if (!(top && top.ranges && top.equals(sel)))\n
+      dest.push(sel);\n
+  }\n
+\n
+  // Used to store marked span information in the history.\n
+  function attachLocalSpans(doc, change, from, to) {\n
+    var existing = change["spans_" + doc.id], n = 0;\n
+    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {\n
+      if (line.markedSpans)\n
+        (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;\n
+      ++n;\n
+    });\n
+  }\n
+\n
+  // When un/re-doing restores text containing marked spans, those\n
+  // that have been explicitly cleared should not be restored.\n
   function removeClearedSpans(spans) {\n
     if (!spans) return null;\n
     for (var i = 0, out; i < spans.length; ++i) {\n
@@ -5427,6 +7229,7 @@ window.CodeMirror = (function() {\n
     return !out ? spans : out.length ? out : null;\n
   }\n
 \n
+  // Retrieve and filter the old marked spans stored in a change event.\n
   function getOldSpans(doc, change) {\n
     var found = change["spans_" + doc.id];\n
     if (!found) return null;\n
@@ -5437,11 +7240,15 @@ window.CodeMirror = (function() {\n
 \n
   // Used both to provide a JSON-safe object in .getHistory, and, when\n
   // detaching a document, to split the history in two\n
-  function copyHistoryArray(events, newGroup) {\n
+  function copyHistoryArray(events, newGroup, instantiateSel) {\n
     for (var i = 0, copy = []; i < events.length; ++i) {\n
-      var event = events[i], changes = event.changes, newChanges = [];\n
-      copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,\n
-                 anchorAfter: event.anchorAfter, headAfter: event.headAfter});\n
+      var event = events[i];\n
+      if (event.ranges) {\n
+        copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);\n
+        continue;\n
+      }\n
+      var changes = event.changes, newChanges = [];\n
+      copy.push({changes: newChanges});\n
       for (var j = 0; j < changes.length; ++j) {\n
         var change = changes[j], m;\n
         newChanges.push({from: change.from, to: change.to, text: change.text});\n
@@ -5458,7 +7265,7 @@ window.CodeMirror = (function() {\n
 \n
   // Rebasing/resetting history to deal with externally-sourced changes\n
 \n
-  function rebaseHistSel(pos, from, to, diff) {\n
+  function rebaseHistSelSingle(pos, from, to, diff) {\n
     if (to < pos.line) {\n
       pos.line += diff;\n
     } else if (from < pos.line) {\n
@@ -5477,28 +7284,27 @@ window.CodeMirror = (function() {\n
   function rebaseHistArray(array, from, to, diff) {\n
     for (var i = 0; i < array.length; ++i) {\n
       var sub = array[i], ok = true;\n
+      if (sub.ranges) {\n
+        if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }\n
+        for (var j = 0; j < sub.ranges.length; j++) {\n
+          rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);\n
+          rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);\n
+        }\n
+        continue;\n
+      }\n
       for (var j = 0; j < sub.changes.length; ++j) {\n
         var cur = sub.changes[j];\n
-        if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }\n
         if (to < cur.from.line) {\n
-          cur.from.line += diff;\n
-          cur.to.line += diff;\n
+          cur.from = Pos(cur.from.line + diff, cur.from.ch);\n
+          cur.to = Pos(cur.to.line + diff, cur.to.ch);\n
         } else if (from <= cur.to.line) {\n
           ok = false;\n
           break;\n
         }\n
       }\n
-      if (!sub.copied) {\n
-        sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);\n
-        sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);\n
-        sub.copied = true;\n
-      }\n
       if (!ok) {\n
         array.splice(0, i + 1);\n
         i = 0;\n
-      } else {\n
-        rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);\n
-        rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);\n
       }\n
     }\n
   }\n
@@ -5509,30 +7315,23 @@ window.CodeMirror = (function() {\n
     rebaseHistArray(hist.undone, from, to, diff);\n
   }\n
 \n
-  // EVENT OPERATORS\n
+  // EVENT UTILITIES\n
 \n
-  function stopMethod() {e_stop(this);}\n
-  // Ensure an event has a stop method.\n
-  function addStop(event) {\n
-    if (!event.stop) event.stop = stopMethod;\n
-    return event;\n
-  }\n
+  // Due to the fact that we still support jurassic IE versions, some\n
+  // compatibility wrappers are needed.\n
 \n
-  function e_preventDefault(e) {\n
+  var e_preventDefault = CodeMirror.e_preventDefault = function(e) {\n
     if (e.preventDefault) e.preventDefault();\n
     else e.returnValue = false;\n
-  }\n
-  function e_stopPropagation(e) {\n
+  };\n
+  var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {\n
     if (e.stopPropagation) e.stopPropagation();\n
     else e.cancelBubble = true;\n
-  }\n
+  };\n
   function e_defaultPrevented(e) {\n
     return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;\n
   }\n
-  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}\n
-  CodeMirror.e_stop = e_stop;\n
-  CodeMirror.e_preventDefault = e_preventDefault;\n
-  CodeMirror.e_stopPropagation = e_stopPropagation;\n
+  var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};\n
 \n
   function e_target(e) {return e.target || e.srcElement;}\n
   function e_button(e) {\n
@@ -5548,7 +7347,10 @@ window.CodeMirror = (function() {\n
 \n
   // EVENT HANDLING\n
 \n
-  function on(emitter, type, f) {\n
+  // Lightweight event framework. on/off also work on DOM nodes,\n
+  // registering native DOM handlers.\n
+\n
+  var on = CodeMirror.on = function(emitter, type, f) {\n
     if (emitter.addEventListener)\n
       emitter.addEventListener(type, f, false);\n
     else if (emitter.attachEvent)\n
@@ -5558,9 +7360,9 @@ window.CodeMirror = (function() {\n
       var arr = map[type] || (map[type] = []);\n
       arr.push(f);\n
     }\n
-  }\n
+  };\n
 \n
-  function off(emitter, type, f) {\n
+  var off = CodeMirror.off = function(emitter, type, f) {\n
     if (emitter.removeEventListener)\n
       emitter.removeEventListener(type, f, false);\n
     else if (emitter.detachEvent)\n
@@ -5571,40 +7373,63 @@ window.CodeMirror = (function() {\n
       for (var i = 0; i < arr.length; ++i)\n
         if (arr[i] == f) { arr.splice(i, 1); break; }\n
     }\n
-  }\n
+  };\n
 \n
-  function signal(emitter, type /*, values...*/) {\n
+  var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {\n
     var arr = emitter._handlers && emitter._handlers[type];\n
     if (!arr) return;\n
     var args = Array.prototype.slice.call(arguments, 2);\n
     for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);\n
-  }\n
+  };\n
+\n
+  var orphanDelayedCallbacks = null;\n
 \n
-  var delayedCallbacks, delayedCallbackDepth = 0;\n
+  // Often, we want to signal events at a point where we are in the\n
+  // middle of some work, but don\'t want the handler to start calling\n
+  // other methods on the editor, which might be in an inconsistent\n
+  // state or simply not expect any other events to happen.\n
+  // signalLater looks whether there are any handlers, and schedules\n
+  // them to be executed when the last operation ends, or, if no\n
+  // operation is active, when a timeout fires.\n
   function signalLater(emitter, type /*, values...*/) {\n
     var arr = emitter._handlers && emitter._handlers[type];\n
     if (!arr) return;\n
-    var args = Array.prototype.slice.call(arguments, 2);\n
-    if (!delayedCallbacks) {\n
-      ++delayedCallbackDepth;\n
-      delayedCallbacks = [];\n
-      setTimeout(fireDelayed, 0);\n
+    var args = Array.prototype.slice.call(arguments, 2), list;\n
+    if (operationGroup) {\n
+      list = operationGroup.delayedCallbacks;\n
+    } else if (orphanDelayedCallbacks) {\n
+      list = orphanDelayedCallbacks;\n
+    } else {\n
+      list = orphanDelayedCallbacks = [];\n
+      setTimeout(fireOrphanDelayed, 0);\n
     }\n
     function bnd(f) {return function(){f.apply(null, args);};};\n
     for (var i = 0; i < arr.length; ++i)\n
-      delayedCallbacks.push(bnd(arr[i]));\n
+      list.push(bnd(arr[i]));\n
   }\n
 \n
+  function fireOrphanDelayed() {\n
+    var delayed = orphanDelayedCallbacks;\n
+    orphanDelayedCallbacks = null;\n
+    for (var i = 0; i < delayed.length; ++i) delayed[i]();\n
+  }\n
+\n
+  // The DOM events that CodeMirror handles can be overridden by\n
+  // registering a (non-DOM) handler on the editor for the event name,\n
+  // and preventDefault-ing the event in that handler.\n
   function signalDOMEvent(cm, e, override) {\n
+    if (typeof e == "string")\n
+      e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};\n
     signal(cm, override || e.type, cm, e);\n
     return e_defaultPrevented(e) || e.codemirrorIgnore;\n
   }\n
 \n
-  function fireDelayed() {\n
-    --delayedCallbackDepth;\n
-    var delayed = delayedCallbacks;\n
-    delayedCallbacks = null;\n
-    for (var i = 0; i < delayed.length; ++i) delayed[i]();\n
+  function signalCursorActivity(cm) {\n
+    var arr = cm._handlers && cm._handlers.cursorActivity;\n
+    if (!arr) return;\n
+    var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);\n
+    for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)\n
+      set.push(arr[i]);\n
   }\n
 \n
   function hasHandler(emitter, type) {\n
@@ -5612,8 +7437,8 @@ window.CodeMirror = (function() {\n
     return arr && arr.length > 0;\n
   }\n
 \n
-  CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;\n
-\n
+  // Add on and off methods to a constructor\'s prototype, to make\n
+  // registering events on such objects more convenient.\n
   function eventMixin(ctor) {\n
     ctor.prototype.on = function(type, f) {on(this, type, f);};\n
     ctor.prototype.off = function(type, f) {off(this, type, f);};\n
@@ -5622,29 +7447,53 @@ window.CodeMirror = (function() {\n
   // MISC UTILITIES\n
 \n
   // Number of pixels added to scroller and sizer to hide scrollbar\n
-  var scrollerCutOff = 30;\n
+  var scrollerGap = 30;\n
 \n
   // Returned or thrown by various protocols to signal \'I\'m not\n
   // handling this\'.\n
   var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};\n
+\n
+  // Reused option objects for setSelection & friends\n
+  var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};\n
 \n
   function Delayed() {this.id = null;}\n
-  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};\n
+  Delayed.prototype.set = function(ms, f) {\n
+    clearTimeout(this.id);\n
+    this.id = setTimeout(f, ms);\n
+  };\n
 \n
   // Counts the column offset in a string, taking tabs into account.\n
   // Used mostly to find indentation.\n
-  function countColumn(string, end, tabSize, startIndex, startValue) {\n
+  var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {\n
     if (end == null) {\n
       end = string.search(/[^\\s\\u00a0]/);\n
       if (end == -1) end = string.length;\n
     }\n
-    for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {\n
-      if (string.charAt(i) == "\\t") n += tabSize - (n % tabSize);\n
-      else ++n;\n
+    for (var i = startIndex || 0, n = startValue || 0;;) {\n
+      var nextTab = string.indexOf("\\t", i);\n
+      if (nextTab < 0 || nextTab >= end)\n
+        return n + (end - i);\n
+      n += nextTab - i;\n
+      n += tabSize - (n % tabSize);\n
+      i = nextTab + 1;\n
+    }\n
+  };\n
+\n
+  // The inverse of countColumn -- find the offset that corresponds to\n
+  // a particular column.\n
+  function findColumn(string, goal, tabSize) {\n
+    for (var pos = 0, col = 0;;) {\n
+      var nextTab = string.indexOf("\\t", pos);\n
+      if (nextTab == -1) nextTab = string.length;\n
+      var skipped = nextTab - pos;\n
+      if (nextTab == string.length || col + skipped >= goal)\n
+        return pos + Math.min(skipped, goal - col);\n
+      col += nextTab - pos;\n
+      col += tabSize - (col % tabSize);\n
+      pos = nextTab + 1;\n
+      if (col >= goal) return pos;\n
     }\n
-    return n;\n
   }\n
-  CodeMirror.countColumn = countColumn;\n
 \n
   var spaceStrs = [""];\n
   function spaceStr(n) {\n
@@ -5655,52 +7504,60 @@ window.CodeMirror = (function() {\n
 \n
   function lst(arr) { return arr[arr.length-1]; }\n
 \n
-  function selectInput(node) {\n
-    if (ios) { // Mobile Safari apparently has a bug where select() is broken.\n
-      node.selectionStart = 0;\n
-      node.selectionEnd = node.value.length;\n
-    } else {\n
-      // Suppress mysterious IE10 errors\n
-      try { node.select(); }\n
-      catch(_e) {}\n
-    }\n
-  }\n
+  var selectInput = function(node) { node.select(); };\n
+  if (ios) // Mobile Safari apparently has a bug where select() is broken.\n
+    selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };\n
+  else if (ie) // Suppress mysterious IE10 errors\n
+    selectInput = function(node) { try { node.select(); } catch(_e) {} };\n
 \n
-  function indexOf(collection, elt) {\n
-    if (collection.indexOf) return collection.indexOf(elt);\n
-    for (var i = 0, e = collection.length; i < e; ++i)\n
-      if (collection[i] == elt) return i;\n
+  function indexOf(array, elt) {\n
+    for (var i = 0; i < array.length; ++i)\n
+      if (array[i] == elt) return i;\n
     return -1;\n
   }\n
+  if ([].indexOf) indexOf = function(array, elt) { return array.indexOf(elt); };\n
+  function map(array, f) {\n
+    var out = [];\n
+    for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);\n
+    return out;\n
+  }\n
+  if ([].map) map = function(array, f) { return array.map(f); };\n
 \n
   function createObj(base, props) {\n
-    function Obj() {}\n
-    Obj.prototype = base;\n
-    var inst = new Obj();\n
+    var inst;\n
+    if (Object.create) {\n
+      inst = Object.create(base);\n
+    } else {\n
+      var ctor = function() {};\n
+      ctor.prototype = base;\n
+      inst = new ctor();\n
+    }\n
     if (props) copyObj(props, inst);\n
     return inst;\n
-  }\n
+  };\n
 \n
-  function copyObj(obj, target) {\n
+  function copyObj(obj, target, overwrite) {\n
     if (!target) target = {};\n
-    for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];\n
+    for (var prop in obj)\n
+      if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))\n
+        target[prop] = obj[prop];\n
     return target;\n
   }\n
-\n
-  function emptyArray(size) {\n
-    for (var a = [], i = 0; i < size; ++i) a.push(undefined);\n
-    return a;\n
-  }\n
 \n
   function bind(f) {\n
     var args = Array.prototype.slice.call(arguments, 1);\n
     return function(){return f.apply(null, args);};\n
   }\n
 \n
-  var nonASCIISingleCaseWordChar = /[\\u00df\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;\n
-  function isWordChar(ch) {\n
+  var nonASCIISingleCaseWordChar = /[\\u00df\\u0590-\\u05f4\\u0600-\\u06ff\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;\n
+  var isWordCharBasic = CodeMirror.isWordChar = function(ch) {\n
     return /\\w/.test(ch) || ch > "\\x80" &&\n
       (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));\n
+  };\n
+  function isWordChar(ch, helper) {\n
+    if (!helper) return isWordCharBasic(ch);\n
+    if (helper.source.indexOf("\\\\w") > -1 && isWordCharBasic(ch)) return true;\n
+    return helper.test(ch);\n
   }\n
 \n
   function isEmpty(obj) {\n
@@ -5708,6 +7565,11 @@ window.CodeMirror = (function() {\n
     return true;\n
   }\n
 \n
+  // Extending unicode characters. A series of a non-extending char +\n
+  // any number of extending chars is treated as a single unit as far\n
+  // as editing and measuring is concerned. This is not fully correct,\n
+  // since some scripts/fonts/browsers also treat other configurations\n
+  // of code points as a group.\n
   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]/;\n
   function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }\n
 \n
@@ -5717,10 +7579,27 @@ window.CodeMirror = (function() {\n
     var e = document.createElement(tag);\n
     if (className) e.className = className;\n
     if (style) e.style.cssText = style;\n
-    if (typeof content == "string") setTextContent(e, content);\n
+    if (typeof content == "string") e.appendChild(document.createTextNode(content));\n
     else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);\n
     return e;\n
   }\n
+\n
+  var range;\n
+  if (document.createRange) range = function(node, start, end) {\n
+    var r = document.createRange();\n
+    r.setEnd(node, end);\n
+    r.setStart(node, start);\n
+    return r;\n
+  };\n
+  else range = function(node, start, end) {\n
+    var r = document.body.createTextRange();\n
+    try { r.moveToElementText(node.parentNode); }\n
+    catch(e) { return r; }\n
+    r.collapse(true);\n
+    r.moveEnd("character", end);\n
+    r.moveStart("character", start);\n
+    return r;\n
+  };\n
 \n
   function removeChildren(e) {\n
     for (var count = e.childNodes.length; count > 0; --count)\n
@@ -5732,17 +7611,76 @@ window.CodeMirror = (function() {\n
     return removeChildren(parent).appendChild(e);\n
   }\n
 \n
-  function setTextContent(e, str) {\n
-    if (ie_lt9) {\n
-      e.innerHTML = "";\n
-      e.appendChild(document.createTextNode(str));\n
-    } else e.textContent = str;\n
+  function contains(parent, child) {\n
+    if (parent.contains)\n
+      return parent.contains(child);\n
+    while (child = child.parentNode)\n
+      if (child == parent) return true;\n
+  }\n
+\n
+  function activeElt() { return document.activeElement; }\n
+  // Older versions of IE throws unspecified error when touching\n
+  // document.activeElement in some cases (during loading, in iframe)\n
+  if (ie && ie_version < 11) activeElt = function() {\n
+    try { return document.activeElement; }\n
+    catch(e) { return document.body; }\n
+  };\n
+\n
+  function classTest(cls) { return new RegExp("(^|\\\\s)" + cls + "(?:$|\\\\s)\\\\s*"); }\n
+  var rmClass = CodeMirror.rmClass = function(node, cls) {\n
+    var current = node.className;\n
+    var match = classTest(cls).exec(current);\n
+    if (match) {\n
+      var after = current.slice(match.index + match[0].length);\n
+      node.className = current.slice(0, match.index) + (after ? match[1] + after : "");\n
+    }\n
+  };\n
+  var addClass = CodeMirror.addClass = function(node, cls) {\n
+    var current = node.className;\n
+    if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;\n
+  };\n
+  function joinClasses(a, b) {\n
+    var as = a.split(" ");\n
+    for (var i = 0; i < as.length; i++)\n
+      if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];\n
+    return b;\n
+  }\n
+\n
+  // WINDOW-WIDE EVENTS\n
+\n
+  // These must be handled carefully, because naively registering a\n
+  // handler for each editor will cause the editors to never be\n
+  // garbage collected.\n
+\n
+  function forEachCodeMirror(f) {\n
+    if (!document.body.getElementsByClassName) return;\n
+    var byClass = document.body.getElementsByClassName("CodeMirror");\n
+    for (var i = 0; i < byClass.length; i++) {\n
+      var cm = byClass[i].CodeMirror;\n
+      if (cm) f(cm);\n
+    }\n
   }\n
 \n
-  function getRect(node) {\n
-    return node.getBoundingClientRect();\n
+  var globalsRegistered = false;\n
+  function ensureGlobalHandlers() {\n
+    if (globalsRegistered) return;\n
+    registerGlobalHandlers();\n
+    globalsRegistered = true;\n
+  }\n
+  function registerGlobalHandlers() {\n
+    // When the window resizes, we need to refresh active editors.\n
+    var resizeTimer;\n
+    on(window, "resize", function() {\n
+      if (resizeTimer == null) resizeTimer = setTimeout(function() {\n
+        resizeTimer = null;\n
+        forEachCodeMirror(onResize);\n
+      }, 100);\n
+    });\n
+    // When the window loses focus, we want to show the editor as blurred\n
+    on(window, "blur", function() {\n
+      forEachCodeMirror(onBlur);\n
+    });\n
   }\n
-  CodeMirror.replaceGetRect = function(f) { getRect = f; };\n
 \n
   // FEATURE DETECTION\n
 \n
@@ -5750,50 +7688,10 @@ window.CodeMirror = (function() {\n
   var dragAndDrop = function() {\n
     // There is *some* kind of drag-and-drop support in IE6-8, but I\n
     // couldn\'t get it to work yet.\n
-    if (ie_lt9) return false;\n
+    if (ie && ie_version < 9) return false;\n
     var div = elt(\'div\');\n
     return "draggable" in div || "dragDrop" in div;\n
   }();\n
-\n
-  // For a reason I have yet to figure out, some browsers disallow\n
-  // word wrapping between certain characters *only* if a new inline\n
-  // element is started between them. This makes it hard to reliably\n
-  // measure the position of things, since that requires inserting an\n
-  // extra span. This terribly fragile set of tests matches the\n
-  // character combinations that suffer from this phenomenon on the\n
-  // various browsers.\n
-  function spanAffectsWrapping() { return false; }\n
-  if (gecko) // Only for "$\'"\n
-    spanAffectsWrapping = function(str, i) {\n
-      return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;\n
-    };\n
-  else if (safari && !/Version\\/([6-9]|\\d\\d)\\b/.test(navigator.userAgent))\n
-    spanAffectsWrapping = function(str, i) {\n
-      return /\\-[^ \\-?]|\\?[^ !\\\'\\"\\),.\\-\\/:;\\?\\]\\}]/.test(str.slice(i - 1, i + 1));\n
-    };\n
-  else if (webkit && /Chrome\\/(?:29|[3-9]\\d|\\d\\d\\d)\\./.test(navigator.userAgent))\n
-    spanAffectsWrapping = function(str, i) {\n
-      var code = str.charCodeAt(i - 1);\n
-      return code >= 8208 && code <= 8212;\n
-    };\n
-  else if (webkit)\n
-    spanAffectsWrapping = function(str, i) {\n
-      if (i > 1 && str.charCodeAt(i - 1) == 45) {\n
-        if (/\\w/.test(str.charAt(i - 2)) && /[^\\-?\\.]/.test(str.charAt(i))) return true;\n
-        if (i > 2 && /[\\d\\.,]/.test(str.charAt(i - 2)) && /[\\d\\.,]/.test(str.charAt(i))) return false;\n
-      }\n
-      return /[~!#%&*)=+}\\]\\\\|\\"\\.>,:;][({[<]|-[^\\-?\\.\\u2010-\\u201f\\u2026]|\\?[\\w~`@#$%\\^&*(_=+{[|><]|\\u2026[\\w~`@#$%\\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));\n
-    };\n
-\n
-  var knownScrollbarWidth;\n
-  function scrollbarWidth(measure) {\n
-    if (knownScrollbarWidth != null) return knownScrollbarWidth;\n
-    var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");\n
-    removeChildrenAndAdd(measure, test);\n
-    if (test.offsetWidth)\n
-      knownScrollbarWidth = test.offsetHeight - test.clientHeight;\n
-    return knownScrollbarWidth || 0;\n
-  }\n
 \n
   var zwspSupported;\n
   function zeroWidthElement(measure) {\n
@@ -5801,15 +7699,26 @@ window.CodeMirror = (function() {\n
       var test = elt("span", "\\u200b");\n
       removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));\n
       if (measure.firstChild.offsetHeight != 0)\n
-        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;\n
+        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);\n
     }\n
     if (zwspSupported) return elt("span", "\\u200b");\n
     else return elt("span", "\\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");\n
   }\n
+\n
+  // Feature-detect IE\'s crummy client rect reporting for bidi text\n
+  var badBidiRects;\n
+  function hasBadBidiRects(measure) {\n
+    if (badBidiRects != null) return badBidiRects;\n
+    var txt = removeChildrenAndAdd(measure, document.createTextNode("A\\u062eA"));\n
+    var r0 = range(txt, 0, 1).getBoundingClientRect();\n
+    if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)\n
+    var r1 = range(txt, 1, 2).getBoundingClientRect();\n
+    return badBidiRects = (r1.right - r0.right < 3);\n
+  }\n
 \n
   // See if "".split is the broken IE version, if so, provide an\n
   // alternative way to split lines.\n
-  var splitLines = "\\n\\nb".split(/\\n/).length != 3 ? function(string) {\n
+  var splitLines = CodeMirror.splitLines = "\\n\\nb".split(/\\n/).length != 3 ? function(string) {\n
     var pos = 0, result = [], l = string.length;\n
     while (pos <= l) {\n
       var nl = string.indexOf("\\n", pos);\n
@@ -5826,7 +7735,6 @@ window.CodeMirror = (function() {\n
     }\n
     return result;\n
   } : function(string){return string.split(/\\r\\n?|\\n/);};\n
-  CodeMirror.splitLines = splitLines;\n
 \n
   var hasSelection = window.getSelection ? function(te) {\n
     try { return te.selectionStart != te.selectionEnd; }\n
@@ -5842,10 +7750,19 @@ window.CodeMirror = (function() {\n
     var e = elt("div");\n
     if ("oncopy" in e) return true;\n
     e.setAttribute("oncopy", "return;");\n
-    return typeof e.oncopy == \'function\';\n
+    return typeof e.oncopy == "function";\n
   })();\n
 \n
-  // KEY NAMING\n
+  var badZoomedRects = null;\n
+  function hasBadZoomedRects(measure) {\n
+    if (badZoomedRects != null) return badZoomedRects;\n
+    var node = removeChildrenAndAdd(measure, elt("span", "x"));\n
+    var normal = node.getBoundingClientRect();\n
+    var fromRange = range(node, 0, 1).getBoundingClientRect();\n
+    return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;\n
+  }\n
+\n
+  // KEY NAMES\n
 \n
   var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",\n
                   19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",\n
@@ -5891,19 +7808,32 @@ window.CodeMirror = (function() {\n
 \n
   function lineStart(cm, lineN) {\n
     var line = getLine(cm.doc, lineN);\n
-    var visual = visualLine(cm.doc, line);\n
+    var visual = visualLine(line);\n
     if (visual != line) lineN = lineNo(visual);\n
     var order = getOrder(visual);\n
     var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);\n
     return Pos(lineN, ch);\n
   }\n
   function lineEnd(cm, lineN) {\n
-    var merged, line;\n
-    while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))\n
-      lineN = merged.find().to.line;\n
+    var merged, line = getLine(cm.doc, lineN);\n
+    while (merged = collapsedSpanAtEnd(line)) {\n
+      line = merged.find(1, true).line;\n
+      lineN = null;\n
+    }\n
     var order = getOrder(line);\n
     var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);\n
-    return Pos(lineN, ch);\n
+    return Pos(lineN == null ? lineNo(line) : lineN, ch);\n
+  }\n
+  function lineStartSmart(cm, pos) {\n
+    var start = lineStart(cm, pos.line);\n
+    var line = getLine(cm.doc, start.line);\n
+    var order = getOrder(line);\n
+    if (!order || order[0].level == 0) {\n
+      var firstNonWS = Math.max(0, line.text.search(/\\S/));\n
+      var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;\n
+      return Pos(start.line, inWS ? 0 : firstNonWS);\n
+    }\n
+    return start;\n
   }\n
 \n
   function compareBidiLevel(order, a, b) {\n
@@ -5940,12 +7870,11 @@ window.CodeMirror = (function() {\n
     return pos;\n
   }\n
 \n
-  // This is somewhat involved. It is needed in order to move\n
-  // \'visually\' through bi-directional text -- i.e., pressing left\n
-  // should make the cursor go left, even when in RTL text. The\n
-  // tricky part is the \'jumps\', where RTL and LTR text touch each\n
-  // other. This often requires the cursor offset to move more than\n
-  // one unit, in order to visually move one unit.\n
+  // This is needed in order to move \'visually\' through bi-directional\n
+  // text -- i.e., pressing left should make the cursor go left, even\n
+  // when in RTL text. The tricky part is the \'jumps\', where RTL and\n
+  // LTR text touch each other. This often requires the cursor offset\n
+  // to move more than one unit, in order to visually move one unit.\n
   function moveVisually(line, start, dir, byUnit) {\n
     var bidi = getOrder(line);\n
     if (!bidi) return moveLogically(line, start, dir, byUnit);\n
@@ -6000,14 +7929,16 @@ window.CodeMirror = (function() {\n
   // objects) in the order in which they occur visually.\n
   var bidiOrdering = (function() {\n
     // Character types for codepoints 0 to 0xff\n
-    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";\n
+    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";\n
     // Character types for codepoints 0x600 to 0x6ff\n
-    var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";\n
+    var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";\n
     function charType(code) {\n
-      if (code <= 0xff) return lowTypes.charAt(code);\n
+      if (code <= 0xf7) return lowTypes.charAt(code);\n
       else if (0x590 <= code && code <= 0x5f4) return "R";\n
-      else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);\n
-      else if (0x700 <= code && code <= 0x8ac) return "r";\n
+      else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);\n
+      else if (0x6ee <= code && code <= 0x8ac) return "r";\n
+      else if (0x2000 <= code && code <= 0x200b) return "w";\n
+      else if (code == 0x200c) return "b";\n
       else return "L";\n
     }\n
 \n
@@ -6015,6 +7946,11 @@ window.CodeMirror = (function() {\n
     var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;\n
     // Browsers seem to always treat the boundaries of block elements as being L.\n
     var outerType = "L";\n
+\n
+    function BidiSpan(level, from, to) {\n
+      this.level = level;\n
+      this.from = from; this.to = to;\n
+    }\n
 \n
     return function(str) {\n
       if (!bidiRE.test(str)) return false;\n
@@ -6105,32 +8041,32 @@ window.CodeMirror = (function() {\n
         if (countsAsLeft.test(types[i])) {\n
           var start = i;\n
           for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}\n
-          order.push({from: start, to: i, level: 0});\n
+          order.push(new BidiSpan(0, start, i));\n
         } else {\n
           var pos = i, at = order.length;\n
           for (++i; i < len && types[i] != "L"; ++i) {}\n
           for (var j = pos; j < i;) {\n
             if (countsAsNum.test(types[j])) {\n
-              if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});\n
+              if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));\n
               var nstart = j;\n
               for (++j; j < i && countsAsNum.test(types[j]); ++j) {}\n
-              order.splice(at, 0, {from: nstart, to: j, level: 2});\n
+              order.splice(at, 0, new BidiSpan(2, nstart, j));\n
               pos = j;\n
             } else ++j;\n
           }\n
-          if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});\n
+          if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));\n
         }\n
       }\n
       if (order[0].level == 1 && (m = str.match(/^\\s+/))) {\n
         order[0].from = m[0].length;\n
-        order.unshift({from: 0, to: m[0].length, level: 0});\n
+        order.unshift(new BidiSpan(0, 0, m[0].length));\n
       }\n
       if (lst(order).level == 1 && (m = str.match(/\\s+$/))) {\n
         lst(order).to -= m[0].length;\n
-        order.push({from: len - m[0].length, to: len, level: 0});\n
+        order.push(new BidiSpan(0, len - m[0].length, len));\n
       }\n
       if (order[0].level != lst(order).level)\n
-        order.push({from: len, to: len, level: order[0].level});\n
+        order.push(new BidiSpan(order[0].level, len, len));\n
 \n
       return order;\n
     };\n
@@ -6138,10 +8074,10 @@ window.CodeMirror = (function() {\n
 \n
   // THE END\n
 \n
-  CodeMirror.version = "3.22.0";\n
+  CodeMirror.version = "4.11.0";\n
 \n
   return CodeMirror;\n
-})();\n
+});\n
 
 
 ]]></string> </value>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/apl/apl.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/apl/apl.js.xml
index 74ebc98d3624978f38ff2e978fa42f954b5980e8..8dc7da77e1a711b198533c9238d39db45405cf86 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/apl/apl.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/apl/apl.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403098.15</string> </value>
+            <value> <string>ts21897136.33</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("apl", function() {\n
   var builtInOps = {\n
     ".": "innerProduct",\n
@@ -182,6 +195,8 @@ CodeMirror.defineMode("apl", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/apl", "apl");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -192,7 +207,7 @@ CodeMirror.defineMIME("text/apl", "apl");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4312</int> </value>
+            <value> <int>4773</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/asterisk/asterisk.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/asterisk/asterisk.js.xml
index 7c90fcdf964f6bf2b982c378ebe6a3858e5dc433..993d31323b87d1322bb9f37e53388ad7b87aec69 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/asterisk/asterisk.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/asterisk/asterisk.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403086.22</string> </value>
+            <value> <string>ts21897149.93</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*\n
  * =====================================================================================\n
  *\n
@@ -38,6 +41,16 @@
  * =====================================================================================\n
  */\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("asterisk", function() {\n
   var atoms    = ["exten", "same", "include","ignorepat","switch"],\n
       dpcmd    = ["#include","#exec"],\n
@@ -205,6 +218,8 @@ CodeMirror.defineMode("asterisk", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-asterisk", "asterisk");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -215,7 +230,7 @@ CodeMirror.defineMIME("text/x-asterisk", "asterisk");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7015</int> </value>
+            <value> <int>7476</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/clike.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/clike.js.xml
index 6b0f05a788af726a2d6d693eef1cdd5472ae06c3..f2957365a635290296390261a93fc6b7ee15cf17 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/clike.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/clike.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403090.93</string> </value>
+            <value> <string>ts21897144.33</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("clike", function(config, parserConfig) {\n
   var indentUnit = config.indentUnit,\n
       statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n
@@ -31,7 +44,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
       blockKeywords = parserConfig.blockKeywords || {},\n
       atoms = parserConfig.atoms || {},\n
       hooks = parserConfig.hooks || {},\n
-      multiLineStrings = parserConfig.multiLineStrings;\n
+      multiLineStrings = parserConfig.multiLineStrings,\n
+      indentStatements = parserConfig.indentStatements !== false;\n
   var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n
 \n
   var curPunc;\n
@@ -68,7 +82,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
       stream.eatWhile(isOperatorChar);\n
       return "operator";\n
     }\n
-    stream.eatWhile(/[\\w\\$_]/);\n
+    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n
     var cur = stream.current();\n
     if (keywords.propertyIsEnumerable(cur)) {\n
       if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";\n
@@ -162,7 +176,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
         while (ctx.type == "statement") ctx = popContext(state);\n
       }\n
       else if (curPunc == ctx.type) popContext(state);\n
-      else if (((ctx.type == "}" || ctx.type == "top") && curPunc != \';\') || (ctx.type == "statement" && curPunc == "newstatement"))\n
+      else if (indentStatements &&\n
+               (((ctx.type == "}" || ctx.type == "top") && curPunc != \';\') ||\n
+                (ctx.type == "statement" && curPunc == "newstatement")))\n
         pushContext(state, stream.column(), "statement");\n
       state.startOfLine = false;\n
       return style;\n
@@ -187,7 +203,6 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
   };\n
 });\n
 \n
-(function() {\n
   function words(str) {\n
     var obj = {}, words = str.split(" ");\n
     for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
@@ -214,6 +229,30 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
     }\n
     return "meta";\n
   }\n
+\n
+  function cpp11StringHook(stream, state) {\n
+    stream.backUp(1);\n
+    // Raw strings.\n
+    if (stream.match(/(R|u8R|uR|UR|LR)/)) {\n
+      var match = stream.match(/"([^\\s\\\\()]{0,16})\\(/);\n
+      if (!match) {\n
+        return false;\n
+      }\n
+      state.cpp11RawStringDelim = match[1];\n
+      state.tokenize = tokenRawString;\n
+      return tokenRawString(stream, state);\n
+    }\n
+    // Unicode strings/chars.\n
+    if (stream.match(/(u8|u|U|L)/)) {\n
+      if (stream.match(/["\']/, /* eat */ false)) {\n
+        return "string";\n
+      }\n
+      return false;\n
+    }\n
+    // Ignore this hook.\n
+    stream.next();\n
+    return false;\n
+  }\n
 \n
   // C#-style strings where "" escapes a quote.\n
   function tokenAtString(stream, state) {\n
@@ -226,8 +265,22 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
     }\n
     return "string";\n
   }\n
+\n
+  // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where\n
+  // <delim> can be a string up to 16 characters long.\n
+  function tokenRawString(stream, state) {\n
+    // Escape characters that have special regex meanings.\n
+    var delim = state.cpp11RawStringDelim.replace(/[^\\w\\s]/g, \'\\\\$&\');\n
+    var match = stream.match(new RegExp(".*?\\\\)" + delim + \'"\'));\n
+    if (match)\n
+      state.tokenize = null;\n
+    else\n
+      stream.skipToEnd();\n
+    return "string";\n
+  }\n
 \n
   function def(mimes, mode) {\n
+    if (typeof mimes == "string") mimes = [mimes];\n
     var words = [];\n
     function add(obj) {\n
       if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))\n
@@ -259,13 +312,21 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
     keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +\n
                     "static_cast typeid catch operator template typename class friend private " +\n
                     "this using const_cast inline public throw virtual delete mutable protected " +\n
-                    "wchar_t"),\n
+                    "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +\n
+                    "static_assert override"),\n
     blockKeywords: words("catch class do else finally for if struct switch try while"),\n
     atoms: words("true false null"),\n
-    hooks: {"#": cppHook},\n
+    hooks: {\n
+      "#": cppHook,\n
+      "u": cpp11StringHook,\n
+      "U": cpp11StringHook,\n
+      "L": cpp11StringHook,\n
+      "R": cpp11StringHook\n
+    },\n
     modeProps: {fold: ["brace", "include"]}\n
   });\n
-  CodeMirror.defineMIME("text/x-java", {\n
+\n
+  def("text/x-java", {\n
     name: "clike",\n
     keywords: words("abstract assert boolean break byte case catch char class const continue default " +\n
                     "do double else enum extends final finally float for goto if implements import " +\n
@@ -282,7 +343,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
     },\n
     modeProps: {fold: ["brace", "import"]}\n
   });\n
-  CodeMirror.defineMIME("text/x-csharp", {\n
+\n
+  def("text/x-csharp", {\n
     name: "clike",\n
     keywords: words("abstract as base break case catch checked class const continue" +\n
                     " default delegate do else enum event explicit extern finally fixed for" +\n
@@ -308,7 +370,20 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
       }\n
     }\n
   });\n
-  CodeMirror.defineMIME("text/x-scala", {\n
+\n
+  function tokenTripleString(stream, state) {\n
+    var escaped = false;\n
+    while (!stream.eol()) {\n
+      if (!escaped && stream.match(\'"""\')) {\n
+        state.tokenize = null;\n
+        break;\n
+      }\n
+      escaped = stream.next() != "\\\\" && !escaped;\n
+    }\n
+    return "string";\n
+  }\n
+\n
+  def("text/x-scala", {\n
     name: "clike",\n
     keywords: words(\n
 \n
@@ -333,18 +408,24 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
       "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +\n
       "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +\n
       "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"\n
-\n
-\n
     ),\n
+    multiLineStrings: true,\n
     blockKeywords: words("catch class do else finally for forSome if match switch try while"),\n
     atoms: words("true false null"),\n
+    indentStatements: false,\n
     hooks: {\n
       "@": function(stream) {\n
         stream.eatWhile(/[\\w\\$_]/);\n
         return "meta";\n
+      },\n
+      \'"\': function(stream, state) {\n
+        if (!stream.match(\'""\')) return false;\n
+        state.tokenize = tokenTripleString;\n
+        return state.tokenize(stream, state);\n
       }\n
     }\n
   });\n
+\n
   def(["x-shader/x-vertex", "x-shader/x-fragment"], {\n
     name: "clike",\n
     keywords: words("float int bool void " +\n
@@ -402,7 +483,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
     hooks: {"#": cppHook},\n
     modeProps: {fold: ["brace", "include"]}\n
   });\n
-}());\n
+\n
+  def("text/x-nesc", {\n
+    name: "clike",\n
+    keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +\n
+                    "implementation includes interface module new norace nx_struct nx_union post provides " +\n
+                    "signal task uses abstract extends"),\n
+    blockKeywords: words("case do else for if switch while struct"),\n
+    atoms: words("null"),\n
+    hooks: {"#": cppHook},\n
+    modeProps: {fold: ["brace", "include"]}\n
+  });\n
+\n
+  def("text/x-objectivec", {\n
+    name: "clike",\n
+    keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +\n
+                    "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),\n
+    atoms: words("YES NO NULL NILL ON OFF"),\n
+    hooks: {\n
+      "@": function(stream) {\n
+        stream.eatWhile(/[\\w\\$]/);\n
+        return "keyword";\n
+      },\n
+      "#": cppHook\n
+    },\n
+    modeProps: {fold: "brace"}\n
+  });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -413,7 +521,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>15517</int> </value>
+            <value> <int>18939</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/scala.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/scala.html.xml
index 3bce078d31e7485dadf231b1fb5dd4cbf06c6ba7..97ab5f8c957fd1cc45e0f57c5b3a3de9b45e3190 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/scala.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clike/scala.html.xml
@@ -48,12 +48,12 @@
 <script src="../../addon/edit/matchbrackets.js"></script>\n
 <script src="clike.js"></script>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../../index.html">Home</a>\n
     <li><a href="../../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="../index.html">Language modes</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clojure/clojure.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clojure/clojure.js.xml
index bd3c60b5152b8c14cccf9127780390f902ce8f8a..27cb1880a4cee7cba2ffc689e680058bccac60f5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clojure/clojure.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/clojure/clojure.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403095.71</string> </value>
+            <value> <string>ts21897138.86</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,13 +22,27 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Author: Hans Engel\n
  * Branched from CodeMirror\'s Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)\n
  */\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("clojure", function (options) {\n
     var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",\n
-        ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword";\n
+        ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";\n
     var INDENT_WORD_SKIP = options.indentUnit || 2;\n
     var NORMAL_INDENT_UNIT = options.indentUnit || 2;\n
 \n
@@ -69,7 +83,7 @@ CodeMirror.defineMode("clojure", function (options) {\n
         sign: /[+-]/,\n
         exponent: /e/i,\n
         keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n
-        symbol: /[\\w*+!\\-\\._?:<>\\/]/\n
+        symbol: /[\\w*+!\\-\\._?:<>\\/\\xa1-\\uffff]/\n
     };\n
 \n
     function stateStack(indent, type, prev) { // represents a state stack object\n
@@ -124,7 +138,7 @@ CodeMirror.defineMode("clojure", function (options) {\n
         var first = stream.next();\n
         // Read special literals: backspace, newline, space, return.\n
         // Just read all lowercase letters.\n
-        if (first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {\n
+        if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {\n
             return;\n
         }\n
         // Read unicode character: \\u1000 \\uA0a1\n
@@ -230,7 +244,9 @@ CodeMirror.defineMode("clojure", function (options) {\n
                             returnType = BUILTIN;\n
                         } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {\n
                             returnType = ATOM;\n
-                        } else returnType = null;\n
+                        } else {\n
+                          returnType = VAR;\n
+                        }\n
                     }\n
             }\n
 \n
@@ -247,6 +263,8 @@ CodeMirror.defineMode("clojure", function (options) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-clojure", "clojure");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -257,7 +275,7 @@ CodeMirror.defineMIME("text/x-clojure", "clojure");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>14262</int> </value>
+            <value> <int>14815</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cobol/cobol.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cobol/cobol.js.xml
index 6b0f930e0ef597d3665e9c2426cb5a2f2b6202df..0839be0224f8529da2c1c5afacb44eb1b1153cf1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cobol/cobol.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cobol/cobol.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403092.12</string> </value>
+            <value> <string>ts21897142.93</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Author: Gautam Mehta\n
  * Branched from CodeMirror\'s Scheme mode\n
  */\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("cobol", function () {\n
   var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",\n
       ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header",\n
@@ -262,6 +275,8 @@ CodeMirror.defineMode("cobol", function () {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-cobol", "cobol");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -272,7 +287,7 @@ CodeMirror.defineMIME("text/x-cobol", "cobol");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9827</int> </value>
+            <value> <int>10288</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/coffeescript/coffeescript.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/coffeescript/coffeescript.js.xml
index da6451dfafedd4ff2948c0fbb92dd45754e4d4d3..caae9e463e4339c97662cfdb9596a8a32620d483 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/coffeescript/coffeescript.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/coffeescript/coffeescript.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403101.73</string> </value>
+            <value> <string>ts21897133.52</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,18 +22,31 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Link to the project\'s GitHub page:\n
  * https://github.com/pickhardt/coffeescript-codemirror-mode\n
  */\n
-CodeMirror.defineMode("coffeescript", function(conf) {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode("coffeescript", function(conf, parserConf) {\n
   var ERRORCLASS = "error";\n
 \n
   function wordRegexp(words) {\n
     return new RegExp("^((" + words.join(")|(") + "))\\\\b");\n
   }\n
 \n
-  var operators = /^(?:->|=>|\\+[+=]?|-[\\-=]?|\\*[\\*=]?|\\/[\\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\\|=?|\\^=?|\\~|!|\\?)/;\n
+  var operators = /^(?:->|=>|\\+[+=]?|-[\\-=]?|\\*[\\*=]?|\\/[\\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\\|=?|\\^=?|\\~|!|\\?|(or|and|\\|\\||&&|\\?)=)/;\n
   var delimiters = /^(?:[()\\[\\]{},:`=;]|\\.\\.?\\.?)/;\n
   var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;\n
   var properties = /^(@|this\\.)[_A-Za-z$][_A-Za-z$0-9]*/;\n
@@ -45,7 +58,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {\n
                         "switch", "try", "catch", "finally", "class"];\n
   var commonKeywords = ["break", "by", "continue", "debugger", "delete",\n
                         "do", "in", "of", "new", "return", "then",\n
-                        "this", "throw", "when", "until"];\n
+                        "this", "@", "throw", "when", "until", "extends"];\n
 \n
   var keywords = wordRegexp(indentKeywords.concat(commonKeywords));\n
 \n
@@ -202,7 +215,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {\n
         }\n
       }\n
       if (singleline) {\n
-        if (conf.mode.singleLineStringErrors) {\n
+        if (parserConf.singleLineStringErrors) {\n
           outclass = ERRORCLASS;\n
         } else {\n
           state.tokenize = tokenBase;\n
@@ -228,7 +241,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {\n
     type = type || "coffee";\n
     var offset = 0, align = false, alignOffset = null;\n
     for (var scope = state.scope; scope; scope = scope.prev) {\n
-      if (scope.type === "coffee") {\n
+      if (scope.type === "coffee" || scope.type == "}") {\n
         offset = scope.offset + conf.indentUnit;\n
         break;\n
       }\n
@@ -289,7 +302,7 @@ CodeMirror.defineMode("coffeescript", function(conf) {\n
 \n
     // Handle scope changes.\n
     if (current === "return") {\n
-      state.dedent += 1;\n
+      state.dedent = true;\n
     }\n
     if (((current === "->" || current === "=>") &&\n
          !state.lambda &&\n
@@ -321,9 +334,10 @@ CodeMirror.defineMode("coffeescript", function(conf) {\n
       if (state.scope.type == current)\n
         state.scope = state.scope.prev;\n
     }\n
-    if (state.dedent > 0 && stream.eol() && state.scope.type == "coffee") {\n
-      if (state.scope.prev) state.scope = state.scope.prev;\n
-      state.dedent -= 1;\n
+    if (state.dedent && stream.eol()) {\n
+      if (state.scope.type == "coffee" && state.scope.prev)\n
+        state.scope = state.scope.prev;\n
+      state.dedent = false;\n
     }\n
 \n
     return style;\n
@@ -375,6 +389,8 @@ CodeMirror.defineMode("coffeescript", function(conf) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -385,7 +401,7 @@ CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9647</int> </value>
+            <value> <int>10188</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/commonlisp/commonlisp.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/commonlisp/commonlisp.js.xml
index 0526ce983fa60613383dd423f7ffbcea1de6bd37..f2c6b5c6087ceade468bfea70b884333e5ef8923 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/commonlisp/commonlisp.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/commonlisp/commonlisp.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403090.53</string> </value>
+            <value> <string>ts21897144.74</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,21 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("commonlisp", function (config) {\n
+  var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;\n
   var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;\n
   var numLiteral = /^(?:[+\\-]?(?:\\d+|\\d*\\.\\d+)(?:[efd][+\\-]?\\d+)?|[+\\-]?\\d+(?:\\/[+\\-]?\\d+)?|#b[+\\-]?[01]+|#o[+\\-]?[0-7]+|#x[+\\-]?[\\da-f]+)/;\n
   var symbol = /[^\\s\'`,@()\\[\\]";]/;\n
@@ -63,8 +77,8 @@ CodeMirror.defineMode("commonlisp", function (config) {\n
       var name = readSym(stream);\n
       if (name == ".") return null;\n
       type = "symbol";\n
-      if (name == "nil" || name == "t") return "atom";\n
-      if (name.charAt(0) == ":") return "keyword";\n
+      if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom";\n
+      if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword";\n
       if (name.charAt(0) == "&") return "variable-2";\n
       return "variable";\n
     }\n
@@ -91,7 +105,7 @@ CodeMirror.defineMode("commonlisp", function (config) {\n
 \n
   return {\n
     startState: function () {\n
-      return {ctx: {prev: null, start: 0, indentTo: 0}, tokenize: base};\n
+      return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};\n
     },\n
 \n
     token: function (stream, state) {\n
@@ -109,6 +123,7 @@ CodeMirror.defineMode("commonlisp", function (config) {\n
         } else if (state.ctx.indentTo == "next") {\n
           state.ctx.indentTo = stream.column();\n
         }\n
+        state.lastType = type;\n
       }\n
       if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};\n
       else if (type == "close") state.ctx = state.ctx.prev || state.ctx;\n
@@ -127,6 +142,8 @@ CodeMirror.defineMode("commonlisp", function (config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -137,7 +154,7 @@ CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3614</int> </value>
+            <value> <int>4446</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/css.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/css.js.xml
index 943559410b537699694868e77ab08e0e5424f556..4df16ef63a8fac842649bc1ef0c144abc192e7e1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/css.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/css.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403094.79</string> </value>
+            <value> <string>ts21897139.7</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,9 +22,20 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.defineMode("css", function(config, parserConfig) {\n
-  "use strict";\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
 \n
+CodeMirror.defineMode("css", function(config, parserConfig) {\n
   if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");\n
 \n
   var indentUnit = config.indentUnit,\n
@@ -32,6 +43,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
       mediaTypes = parserConfig.mediaTypes || {},\n
       mediaFeatures = parserConfig.mediaFeatures || {},\n
       propertyKeywords = parserConfig.propertyKeywords || {},\n
+      nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},\n
       colorKeywords = parserConfig.colorKeywords || {},\n
       valueKeywords = parserConfig.valueKeywords || {},\n
       fontProperties = parserConfig.fontProperties || {},\n
@@ -69,7 +81,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
       if (/[\\d.]/.test(stream.peek())) {\n
         stream.eatWhile(/[\\w.%]/);\n
         return ret("number", "unit");\n
-      } else if (stream.match(/^[^-]+-/)) {\n
+      } else if (stream.match(/^\\w+-/)) {\n
         return ret("meta", "meta");\n
       }\n
     } else if (/[,+>*\\/]/.test(ch)) {\n
@@ -107,7 +119,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
 \n
   function tokenParenthesized(stream, state) {\n
     stream.next(); // Must be \'(\'\n
-    if (!stream.match(/\\s*[\\"\\\']/, false))\n
+    if (!stream.match(/\\s*[\\"\\\')]/, false))\n
       state.tokenize = tokenString(")");\n
     else\n
       state.tokenize = null;\n
@@ -179,18 +191,22 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     } else if (type == ":") {\n
       return "pseudo";\n
     } else if (allowNested && type == "(") {\n
-      return pushContext(state, stream, "params");\n
+      return pushContext(state, stream, "parens");\n
     }\n
     return state.context.type;\n
   };\n
 \n
   states.block = function(type, stream, state) {\n
     if (type == "word") {\n
-      if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) {\n
+      var word = stream.current().toLowerCase();\n
+      if (propertyKeywords.hasOwnProperty(word)) {\n
         override = "property";\n
         return "maybeprop";\n
+      } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {\n
+        override = "string-2";\n
+        return "maybeprop";\n
       } else if (allowNested) {\n
-        override = stream.match(/^\\s*:/, false) ? "property" : "tag";\n
+        override = stream.match(/^\\s*:(?:\\s|$)/, false) ? "property" : "tag";\n
         return "block";\n
       } else {\n
         override += " error";\n
@@ -236,6 +252,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
   states.parens = function(type, stream, state) {\n
     if (type == "{" || type == "}") return popAndPass(type, stream, state);\n
     if (type == ")") return popContext(state);\n
+    if (type == "(") return pushContext(state, stream, "parens");\n
+    if (type == "word") wordAsValue(stream);\n
     return "parens";\n
   };\n
 \n
@@ -310,13 +328,6 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     if (type != "variable") override = "error";\n
     return "interpolation";\n
   };\n
-\n
-  states.params = function(type, stream, state) {\n
-    if (type == ")") return popContext(state);\n
-    if (type == "{" || type == "}") return popAndPass(type, stream, state);\n
-    if (type == "word") wordAsValue(stream);\n
-    return "params";\n
-  };\n
 \n
   return {\n
     startState: function(base) {\n
@@ -340,10 +351,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     indent: function(state, textAfter) {\n
       var cx = state.context, ch = textAfter && textAfter.charAt(0);\n
       var indent = cx.indent;\n
-      if (cx.type == "prop" && ch == "}") cx = cx.prev;\n
+      if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;\n
       if (cx.prev &&\n
           (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||\n
-           ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") ||\n
+           ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||\n
            ch == "{" && (cx.type == "at" || cx.type == "media"))) {\n
         indent = cx.indent - indentUnit;\n
         cx = cx.prev;\n
@@ -358,7 +369,6 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
   };\n
 });\n
 \n
-(function() {\n
   function keySet(array) {\n
     var keys = {};\n
     for (var i = 0; i < array.length; ++i) {\n
@@ -434,7 +444,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     "marker-offset", "marks", "marquee-direction", "marquee-loop",\n
     "marquee-play-count", "marquee-speed", "marquee-style", "max-height",\n
     "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",\n
-    "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",\n
+    "nav-left", "nav-right", "nav-up", "object-fit", "object-position",\n
+    "opacity", "order", "orphans", "outline",\n
     "outline-color", "outline-offset", "outline-style", "outline-width",\n
     "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",\n
     "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",\n
@@ -445,8 +456,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     "region-break-before", "region-break-inside", "region-fragment",\n
     "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",\n
     "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",\n
-    "ruby-position", "ruby-span", "shape-inside", "shape-outside", "size",\n
-    "speak", "speak-as", "speak-header",\n
+    "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",\n
+    "shape-outside", "size", "speak", "speak-as", "speak-header",\n
     "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",\n
     "tab-size", "table-layout", "target", "target-name", "target-new",\n
     "target-position", "text-align", "text-align-last", "text-decoration",\n
@@ -461,18 +472,26 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     "vertical-align", "visibility", "voice-balance", "voice-duration",\n
     "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",\n
     "voice-volume", "volume", "white-space", "widows", "width", "word-break",\n
-    "word-spacing", "word-wrap", "z-index", "zoom",\n
+    "word-spacing", "word-wrap", "z-index",\n
     // SVG-specific\n
     "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",\n
     "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",\n
-    "color-interpolation", "color-interpolation-filters", "color-profile",\n
+    "color-interpolation", "color-interpolation-filters",\n
     "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",\n
     "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",\n
     "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",\n
     "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",\n
     "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",\n
-    "glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode"\n
+    "glyph-orientation-vertical", "text-anchor", "writing-mode"\n
   ], propertyKeywords = keySet(propertyKeywords_);\n
+\n
+  var nonStandardPropertyKeywords_ = [\n
+    "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",\n
+    "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",\n
+    "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",\n
+    "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",\n
+    "searchfield-results-decoration", "zoom"\n
+  ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);\n
 \n
   var colorKeywords_ = [\n
     "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",\n
@@ -496,8 +515,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",\n
     "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",\n
     "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",\n
-    "purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon",\n
-    "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",\n
+    "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",\n
+    "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",\n
     "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",\n
     "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",\n
     "whitesmoke", "yellow", "yellowgreen"\n
@@ -593,7 +612,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     "font-stretch", "font-weight", "font-style"\n
   ], fontProperties = keySet(fontProperties_);\n
 \n
-  var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);\n
+  var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_)\n
+    .concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);\n
   CodeMirror.registerHelper("hintWords", "css", allWords);\n
 \n
   function tokenCComment(stream, state) {\n
@@ -622,6 +642,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     mediaTypes: mediaTypes,\n
     mediaFeatures: mediaFeatures,\n
     propertyKeywords: propertyKeywords,\n
+    nonStandardPropertyKeywords: nonStandardPropertyKeywords,\n
     colorKeywords: colorKeywords,\n
     valueKeywords: valueKeywords,\n
     fontProperties: fontProperties,\n
@@ -644,6 +665,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     mediaTypes: mediaTypes,\n
     mediaFeatures: mediaFeatures,\n
     propertyKeywords: propertyKeywords,\n
+    nonStandardPropertyKeywords: nonStandardPropertyKeywords,\n
     colorKeywords: colorKeywords,\n
     valueKeywords: valueKeywords,\n
     fontProperties: fontProperties,\n
@@ -661,7 +683,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
         }\n
       },\n
       ":": function(stream) {\n
-        if (stream.match(/\\s*{/))\n
+        if (stream.match(/\\s*\\{/))\n
           return [null, "{"];\n
         return false;\n
       },\n
@@ -684,6 +706,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     mediaTypes: mediaTypes,\n
     mediaFeatures: mediaFeatures,\n
     propertyKeywords: propertyKeywords,\n
+    nonStandardPropertyKeywords: nonStandardPropertyKeywords,\n
     colorKeywords: colorKeywords,\n
     valueKeywords: valueKeywords,\n
     fontProperties: fontProperties,\n
@@ -714,7 +737,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
     name: "css",\n
     helperType: "less"\n
   });\n
-})();\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -725,7 +749,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>30365</int> </value>
+            <value> <int>31664</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less.html.xml
index e2072fc47e60b4c414b99b64cec7a51013e722cd..d0c6abd77c419f571f7cd2fc7935f925858bf081 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less.html.xml
@@ -48,12 +48,12 @@
 <script src="css.js"></script>\n
 <style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../../index.html">Home</a>\n
     <li><a href="../../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="../index.html">Language modes</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less_test.js.xml
index 2dd99af196329a9735218a61a1ad6478d80f68b0..a2f14da84ccb0e1dd6a29137a19694fcb4423993 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/less_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403095.41</string> </value>
+            <value> <string>ts21897139.19</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   "use strict";\n
 \n
@@ -80,7 +83,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1663</int> </value>
+            <value> <int>1791</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss.html.xml
index c1bba5aa7c2a66a09b8b359bba872d6cc1c02668..e01fc303a8901c3f2eedc1fa24fa2e6457b870b8 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss.html.xml
@@ -47,12 +47,12 @@
 <script src="css.js"></script>\n
 <style>.CodeMirror {background: #f8f8f8;}</style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../../index.html">Home</a>\n
     <li><a href="../../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="../index.html">Language modes</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss_test.js.xml
index adf1018130935ea9ddf0e3a3e9b1f033954e12a7..7c2919a3e4ffc5120543d43ad1775c99954e45de 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/scss_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403094.69</string> </value>
+            <value> <string>ts21897139.85</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,10 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>(function() {\n
+            <value> <string>// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
   var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }\n
 \n
@@ -135,7 +138,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2997</int> </value>
+            <value> <int>3125</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/test.js.xml
index 951fefd802321d252fb3147b979885499a37c022..abc10afeb5210f26289eeb9a3a817a461c90120d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/css/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403095.08</string> </value>
+            <value> <string>ts21897139.39</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   var mode = CodeMirror.getMode({indentUnit: 2}, "css");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
@@ -140,6 +143,19 @@
      "  [property src]: [atom url]([string http://blah]),",\n
      "    [atom url]([string http://foo]);",\n
      "}");\n
+\n
+  MT("empty_url",\n
+     "[def @import] [tag url]() [tag screen];");\n
+\n
+  MT("parens",\n
+     "[qualifier .foo] {",\n
+     "  [property background-image]: [variable fade]([atom #000], [number 20%]);",\n
+     "  [property border-image]: [variable linear-gradient](",\n
+     "    [atom to] [atom bottom],",\n
+     "    [variable fade]([atom #000], [number 20%]) [number 0%],",\n
+     "    [variable fade]([atom #000], [number 20%]) [number 100%]",\n
+     "  );",\n
+     "}");\n
 })();\n
 
 
@@ -151,7 +167,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3644</int> </value>
+            <value> <int>4227</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cypher.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cypher.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c938281589b7883f8c744ce6356e74d5a6d141bd
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cypher.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>cypher</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cypher/cypher.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cypher/cypher.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..64d4c0d1684867ed37db0d57010f69c8258003cf
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/cypher/cypher.js.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897138.57</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>cypher.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// By the Neo4j Team and contributors.\n
+// https://github.com/neo4j-contrib/CodeMirror\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+  var wordRegexp = function(words) {\n
+    return new RegExp("^(?:" + words.join("|") + ")$", "i");\n
+  };\n
+\n
+  CodeMirror.defineMode("cypher", function(config) {\n
+    var tokenBase = function(stream/*, state*/) {\n
+      var ch = stream.next(), curPunc = null;\n
+      if (ch === "\\"" || ch === "\'") {\n
+        stream.match(/.+?["\']/);\n
+        return "string";\n
+      }\n
+      if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n
+        curPunc = ch;\n
+        return "node";\n
+      } else if (ch === "/" && stream.eat("/")) {\n
+        stream.skipToEnd();\n
+        return "comment";\n
+      } else if (operatorChars.test(ch)) {\n
+        stream.eatWhile(operatorChars);\n
+        return null;\n
+      } else {\n
+        stream.eatWhile(/[_\\w\\d]/);\n
+        if (stream.eat(":")) {\n
+          stream.eatWhile(/[\\w\\d_\\-]/);\n
+          return "atom";\n
+        }\n
+        var word = stream.current();\n
+        if (funcs.test(word)) return "builtin";\n
+        if (preds.test(word)) return "def";\n
+        if (keywords.test(word)) return "keyword";\n
+        return "variable";\n
+      }\n
+    };\n
+    var pushContext = function(state, type, col) {\n
+      return state.context = {\n
+        prev: state.context,\n
+        indent: state.indent,\n
+        col: col,\n
+        type: type\n
+      };\n
+    };\n
+    var popContext = function(state) {\n
+      state.indent = state.context.indent;\n
+      return state.context = state.context.prev;\n
+    };\n
+    var indentUnit = config.indentUnit;\n
+    var curPunc;\n
+    var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);\n
+    var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]);\n
+    var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);\n
+    var operatorChars = /[*+\\-<>=&|~%^]/;\n
+\n
+    return {\n
+      startState: function(/*base*/) {\n
+        return {\n
+          tokenize: tokenBase,\n
+          context: null,\n
+          indent: 0,\n
+          col: 0\n
+        };\n
+      },\n
+      token: function(stream, state) {\n
+        if (stream.sol()) {\n
+          if (state.context && (state.context.align == null)) {\n
+            state.context.align = false;\n
+          }\n
+          state.indent = stream.indentation();\n
+        }\n
+        if (stream.eatSpace()) {\n
+          return null;\n
+        }\n
+        var style = state.tokenize(stream, state);\n
+        if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") {\n
+          state.context.align = true;\n
+        }\n
+        if (curPunc === "(") {\n
+          pushContext(state, ")", stream.column());\n
+        } else if (curPunc === "[") {\n
+          pushContext(state, "]", stream.column());\n
+        } else if (curPunc === "{") {\n
+          pushContext(state, "}", stream.column());\n
+        } else if (/[\\]\\}\\)]/.test(curPunc)) {\n
+          while (state.context && state.context.type === "pattern") {\n
+            popContext(state);\n
+          }\n
+          if (state.context && curPunc === state.context.type) {\n
+            popContext(state);\n
+          }\n
+        } else if (curPunc === "." && state.context && state.context.type === "pattern") {\n
+          popContext(state);\n
+        } else if (/atom|string|variable/.test(style) && state.context) {\n
+          if (/[\\}\\]]/.test(state.context.type)) {\n
+            pushContext(state, "pattern", stream.column());\n
+          } else if (state.context.type === "pattern" && !state.context.align) {\n
+            state.context.align = true;\n
+            state.context.col = stream.column();\n
+          }\n
+        }\n
+        return style;\n
+      },\n
+      indent: function(state, textAfter) {\n
+        var firstChar = textAfter && textAfter.charAt(0);\n
+        var context = state.context;\n
+        if (/[\\]\\}]/.test(firstChar)) {\n
+          while (context && context.type === "pattern") {\n
+            context = context.prev;\n
+          }\n
+        }\n
+        var closing = context && firstChar === context.type;\n
+        if (!context) return 0;\n
+        if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent;\n
+        if (context.align) return context.col + (closing ? 0 : 1);\n
+        return context.indent + (closing ? 0 : indentUnit);\n
+      }\n
+    };\n
+  });\n
+\n
+  CodeMirror.modeExtensions["cypher"] = {\n
+    autoFormatLineBreaks: function(text) {\n
+      var i, lines, reProcessedPortion;\n
+      var lines = text.split("\\n");\n
+      var reProcessedPortion = /\\s+\\b(return|where|order by|match|with|skip|limit|create|delete|set)\\b\\s/g;\n
+      for (var i = 0; i < lines.length; i++)\n
+        lines[i] = lines[i].replace(reProcessedPortion, " \\n$1 ").trim();\n
+      return lines.join("\\n");\n
+    }\n
+  };\n
+\n
+  CodeMirror.defineMIME("application/x-cypher-query", "cypher");\n
+\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>6196</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/d/d.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/d/d.js.xml
index e0fc5e6a6e4de0104a142b11bf2d6dcbb083cff6..598455b057ecce29e9b64efcb1b41ca449fe83a3 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/d/d.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/d/d.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403095.98</string> </value>
+            <value> <string>ts21897138.44</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("d", function(config, parserConfig) {\n
   var indentUnit = config.indentUnit,\n
       statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n
@@ -71,7 +84,7 @@ CodeMirror.defineMode("d", function(config, parserConfig) {\n
       stream.eatWhile(isOperatorChar);\n
       return "operator";\n
     }\n
-    stream.eatWhile(/[\\w\\$_]/);\n
+    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n
     var cur = stream.current();\n
     if (keywords.propertyIsEnumerable(cur)) {\n
       if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";\n
@@ -197,7 +210,6 @@ CodeMirror.defineMode("d", function(config, parserConfig) {\n
   };\n
 });\n
 \n
-(function() {\n
   function words(str) {\n
     var obj = {}, words = str.split(" ");\n
     for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
@@ -226,7 +238,8 @@ CodeMirror.defineMode("d", function(config, parserConfig) {\n
       }\n
     }\n
   });\n
-}());\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -237,7 +250,7 @@ CodeMirror.defineMode("d", function(config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7114</int> </value>
+            <value> <int>7566</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/less.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dart.xml
similarity index 91%
rename from bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/less.xml
rename to bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dart.xml
index a9c24bc8eb37d3e27c6b394d951c141b657257ea..b232c7ea3742c2599a0cc8a737a1b08fff317fa6 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/less.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dart.xml
@@ -14,7 +14,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>less</string> </value>
+            <value> <string>dart</string> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dart/dart.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dart/dart.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2f0c94e567422d74559298f2a7e2512baba21df0
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dart/dart.js.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897141.64</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>dart.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../clike/clike"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../clike/clike"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  var keywords = ("this super static final const abstract class extends external factory " +\n
+    "implements get native operator set typedef with enum throw rethrow " +\n
+    "assert break case continue default in return new deferred async await " +\n
+    "try catch finally do else for if switch while import library export " +\n
+    "part of show hide is").split(" ");\n
+  var blockKeywords = "try catch finally do else for if switch while".split(" ");\n
+  var atoms = "true false null".split(" ");\n
+  var builtins = "void bool num int double dynamic var String".split(" ");\n
+\n
+  function set(words) {\n
+    var obj = {};\n
+    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
+    return obj;\n
+  }\n
+\n
+  CodeMirror.defineMIME("application/dart", {\n
+    name: "clike",\n
+    keywords: set(keywords),\n
+    multiLineStrings: true,\n
+    blockKeywords: set(blockKeywords),\n
+    builtin: set(builtins),\n
+    atoms: set(atoms),\n
+    hooks: {\n
+      "@": function(stream) {\n
+        stream.eatWhile(/[\\w\\$_]/);\n
+        return "meta";\n
+      }\n
+    }\n
+  });\n
+\n
+  CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));\n
+\n
+  // This is needed to make loading through meta.js work.\n
+  CodeMirror.defineMode("dart", function(conf) {\n
+    return CodeMirror.getMode(conf, "application/dart");\n
+  }, "clike");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1820</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/diff/diff.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/diff/diff.js.xml
index cfd5c27ba4056b3cd0fb54eb6735ef682944b879..9962d525ce6a79a98948fb69cb915720772b218f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/diff/diff.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/diff/diff.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403088.96</string> </value>
+            <value> <string>ts21897146.81</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,22 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>CodeMirror.defineMode("diff", function() {\n
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode("diff", function() {\n
 \n
   var TOKEN_NAMES = {\n
     \'+\': \'positive\',\n
@@ -52,7 +67,11 @@
 });\n
 \n
 CodeMirror.defineMIME("text/x-diff", "diff");\n
-</string> </value>
+\n
+});\n
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -60,7 +79,7 @@ CodeMirror.defineMIME("text/x-diff", "diff");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>677</int> </value>
+            <value> <int>1138</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/django.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/django.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1150cb9e28040a42c81147940eeee5a00dfe3eec
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/django.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>django</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/django/django.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/django/django.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2b2ba22789ef2a83634be815dcee539a66793e91
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/django/django.js.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897141.45</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>django.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),\n
+        require("../../addon/mode/overlay"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed",\n
+            "../../addon/mode/overlay"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("django:inner", function() {\n
+    var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",\n
+                    "loop", "none", "self", "super", "if", "endif", "as", "not", "and",\n
+                    "else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal",\n
+                    "ifnotequal", "endifnotequal", "extends", "include", "load", "length", "comment",\n
+                    "endcomment", "empty"];\n
+    keywords = new RegExp("^((" + keywords.join(")|(") + "))\\\\b");\n
+\n
+    function tokenBase (stream, state) {\n
+      stream.eatWhile(/[^\\{]/);\n
+      var ch = stream.next();\n
+      if (ch == "{") {\n
+        if (ch = stream.eat(/\\{|%|#/)) {\n
+          state.tokenize = inTag(ch);\n
+          return "tag";\n
+        }\n
+      }\n
+    }\n
+    function inTag (close) {\n
+      if (close == "{") {\n
+        close = "}";\n
+      }\n
+      return function (stream, state) {\n
+        var ch = stream.next();\n
+        if ((ch == close) && stream.eat("}")) {\n
+          state.tokenize = tokenBase;\n
+          return "tag";\n
+        }\n
+        if (stream.match(keywords)) {\n
+          return "keyword";\n
+        }\n
+        return close == "#" ? "comment" : "string";\n
+      };\n
+    }\n
+    return {\n
+      startState: function () {\n
+        return {tokenize: tokenBase};\n
+      },\n
+      token: function (stream, state) {\n
+        return state.tokenize(stream, state);\n
+      }\n
+    };\n
+  });\n
+\n
+  CodeMirror.defineMode("django", function(config) {\n
+    var htmlBase = CodeMirror.getMode(config, "text/html");\n
+    var djangoInner = CodeMirror.getMode(config, "django:inner");\n
+    return CodeMirror.overlayMode(htmlBase, djangoInner);\n
+  });\n
+\n
+  CodeMirror.defineMIME("text/x-django", "django");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2316</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dockerfile.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dockerfile.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f151aace47a7e1de0d8d3d271a66bb32dad30889
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dockerfile.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>dockerfile</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dockerfile/dockerfile.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dockerfile/dockerfile.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..75f0c4feda5ae3c75831447e82774b5232b5f7f1
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dockerfile/dockerfile.js.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897149.58</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>dockerfile.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../../addon/mode/simple"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  // Collect all Dockerfile directives\n
+  var instructions = ["from", "maintainer", "run", "cmd", "expose", "env",\n
+                      "add", "copy", "entrypoint", "volume", "user",\n
+                      "workdir", "onbuild"],\n
+      instructionRegex = "(" + instructions.join(\'|\') + ")",\n
+      instructionOnlyLine = new RegExp(instructionRegex + "\\\\s*$", "i"),\n
+      instructionWithArguments = new RegExp(instructionRegex + "(\\\\s+)", "i");\n
+\n
+  CodeMirror.defineSimpleMode("dockerfile", {\n
+    start: [\n
+      // Block comment: This is a line starting with a comment\n
+      {\n
+        regex: /#.*$/,\n
+        token: "comment"\n
+      },\n
+      // Highlight an instruction without any arguments (for convenience)\n
+      {\n
+        regex: instructionOnlyLine,\n
+        token: "variable-2"\n
+      },\n
+      // Highlight an instruction followed by arguments\n
+      {\n
+        regex: instructionWithArguments,\n
+        token: ["variable-2", null],\n
+        next: "arguments"\n
+      },\n
+      {\n
+        regex: /./,\n
+        token: null\n
+      }\n
+    ],\n
+    arguments: [\n
+      {\n
+        // Line comment without instruction arguments is an error\n
+        regex: /#.*$/,\n
+        token: "error",\n
+        next: "start"\n
+      },\n
+      {\n
+        regex: /[^#]+\\\\$/,\n
+        token: null\n
+      },\n
+      {\n
+        // Match everything except for the inline comment\n
+        regex: /[^#]+/,\n
+        token: null,\n
+        next: "start"\n
+      },\n
+      {\n
+        regex: /$/,\n
+        token: null,\n
+        next: "start"\n
+      },\n
+      // Fail safe return to start\n
+      {\n
+        token: null,\n
+        next: "start"\n
+      }\n
+    ]\n
+  });\n
+\n
+  CodeMirror.defineMIME("text/x-dockerfile", "dockerfile");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2171</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dtd/dtd.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dtd/dtd.js.xml
index 6184314f6e2d8633791a4d846f70d9b0221dfe07..cc4be99d6364d3b93f7745f382cfbdbb783b65bb 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dtd/dtd.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dtd/dtd.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403086.07</string> </value>
+            <value> <string>ts21897150.03</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,13 +22,26 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*\n
   DTD mode\n
   Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>\n
-  Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues\n
+  Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues\n
   GitHub: @peterkroon\n
 */\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("dtd", function(config) {\n
   var indentUnit = config.indentUnit, type;\n
   function ret(style, tp) {type = tp; return style;}\n
@@ -149,6 +162,8 @@ CodeMirror.defineMode("dtd", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("application/xml-dtd", "dtd");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -159,7 +174,7 @@ CodeMirror.defineMIME("application/xml-dtd", "dtd");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4344</int> </value>
+            <value> <int>4808</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dylan.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dylan.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b9f9047d44b7de0a8b50eefc0dd943103b3c1eff
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dylan.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>dylan</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dylan/dylan.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dylan/dylan.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cb9f277428c86a52def31e0dc2df38cdd89af7bd
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/dylan/dylan.js.xml
@@ -0,0 +1,343 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897146.23</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>dylan.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode("dylan", function(_config) {\n
+  // Words\n
+  var words = {\n
+    // Words that introduce unnamed definitions like "define interface"\n
+    unnamedDefinition: ["interface"],\n
+\n
+    // Words that introduce simple named definitions like "define library"\n
+    namedDefinition: ["module", "library", "macro",\n
+                      "C-struct", "C-union",\n
+                      "C-function", "C-callable-wrapper"\n
+                     ],\n
+\n
+    // Words that introduce type definitions like "define class".\n
+    // These are also parameterized like "define method" and are\n
+    // appended to otherParameterizedDefinitionWords\n
+    typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"],\n
+\n
+    // Words that introduce trickier definitions like "define method".\n
+    // These require special definitions to be added to startExpressions\n
+    otherParameterizedDefinition: ["method", "function",\n
+                                   "C-variable", "C-address"\n
+                                  ],\n
+\n
+    // Words that introduce module constant definitions.\n
+    // These must also be simple definitions and are\n
+    // appended to otherSimpleDefinitionWords\n
+    constantSimpleDefinition: ["constant"],\n
+\n
+    // Words that introduce module variable definitions.\n
+    // These must also be simple definitions and are\n
+    // appended to otherSimpleDefinitionWords\n
+    variableSimpleDefinition: ["variable"],\n
+\n
+    // Other words that introduce simple definitions\n
+    // (without implicit bodies).\n
+    otherSimpleDefinition: ["generic", "domain",\n
+                            "C-pointer-type",\n
+                            "table"\n
+                           ],\n
+\n
+    // Words that begin statements with implicit bodies.\n
+    statement: ["if", "block", "begin", "method", "case",\n
+                "for", "select", "when", "unless", "until",\n
+                "while", "iterate", "profiling", "dynamic-bind"\n
+               ],\n
+\n
+    // Patterns that act as separators in compound statements.\n
+    // This may include any general pattern that must be indented\n
+    // specially.\n
+    separator: ["finally", "exception", "cleanup", "else",\n
+                "elseif", "afterwards"\n
+               ],\n
+\n
+    // Keywords that do not require special indentation handling,\n
+    // but which should be highlighted\n
+    other: ["above", "below", "by", "from", "handler", "in",\n
+            "instance", "let", "local", "otherwise", "slot",\n
+            "subclass", "then", "to", "keyed-by", "virtual"\n
+           ],\n
+\n
+    // Condition signaling function calls\n
+    signalingCalls: ["signal", "error", "cerror",\n
+                     "break", "check-type", "abort"\n
+                    ]\n
+  };\n
+\n
+  words["otherDefinition"] =\n
+    words["unnamedDefinition"]\n
+    .concat(words["namedDefinition"])\n
+    .concat(words["otherParameterizedDefinition"]);\n
+\n
+  words["definition"] =\n
+    words["typeParameterizedDefinition"]\n
+    .concat(words["otherDefinition"]);\n
+\n
+  words["parameterizedDefinition"] =\n
+    words["typeParameterizedDefinition"]\n
+    .concat(words["otherParameterizedDefinition"]);\n
+\n
+  words["simpleDefinition"] =\n
+    words["constantSimpleDefinition"]\n
+    .concat(words["variableSimpleDefinition"])\n
+    .concat(words["otherSimpleDefinition"]);\n
+\n
+  words["keyword"] =\n
+    words["statement"]\n
+    .concat(words["separator"])\n
+    .concat(words["other"]);\n
+\n
+  // Patterns\n
+  var symbolPattern = "[-_a-zA-Z?!*@<>$%]+";\n
+  var symbol = new RegExp("^" + symbolPattern);\n
+  var patterns = {\n
+    // Symbols with special syntax\n
+    symbolKeyword: symbolPattern + ":",\n
+    symbolClass: "<" + symbolPattern + ">",\n
+    symbolGlobal: "\\\\*" + symbolPattern + "\\\\*",\n
+    symbolConstant: "\\\\$" + symbolPattern\n
+  };\n
+  var patternStyles = {\n
+    symbolKeyword: "atom",\n
+    symbolClass: "tag",\n
+    symbolGlobal: "variable-2",\n
+    symbolConstant: "variable-3"\n
+  };\n
+\n
+  // Compile all patterns to regular expressions\n
+  for (var patternName in patterns)\n
+    if (patterns.hasOwnProperty(patternName))\n
+      patterns[patternName] = new RegExp("^" + patterns[patternName]);\n
+\n
+  // Names beginning "with-" and "without-" are commonly\n
+  // used as statement macro\n
+  patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];\n
+\n
+  var styles = {};\n
+  styles["keyword"] = "keyword";\n
+  styles["definition"] = "def";\n
+  styles["simpleDefinition"] = "def";\n
+  styles["signalingCalls"] = "builtin";\n
+\n
+  // protected words lookup table\n
+  var wordLookup = {};\n
+  var styleLookup = {};\n
+\n
+  [\n
+    "keyword",\n
+    "definition",\n
+    "simpleDefinition",\n
+    "signalingCalls"\n
+  ].forEach(function(type) {\n
+    words[type].forEach(function(word) {\n
+      wordLookup[word] = type;\n
+      styleLookup[word] = styles[type];\n
+    });\n
+  });\n
+\n
+\n
+  function chain(stream, state, f) {\n
+    state.tokenize = f;\n
+    return f(stream, state);\n
+  }\n
+\n
+  var type, content;\n
+\n
+  function ret(_type, style, _content) {\n
+    type = _type;\n
+    content = _content;\n
+    return style;\n
+  }\n
+\n
+  function tokenBase(stream, state) {\n
+    // String\n
+    var ch = stream.peek();\n
+    if (ch == "\'" || ch == \'"\') {\n
+      stream.next();\n
+      return chain(stream, state, tokenString(ch, "string", "string"));\n
+    }\n
+    // Comment\n
+    else if (ch == "/") {\n
+      stream.next();\n
+      if (stream.eat("*")) {\n
+        return chain(stream, state, tokenComment);\n
+      } else if (stream.eat("/")) {\n
+        stream.skipToEnd();\n
+        return ret("comment", "comment");\n
+      } else {\n
+        stream.skipTo(" ");\n
+        return ret("operator", "operator");\n
+      }\n
+    }\n
+    // Decimal\n
+    else if (/\\d/.test(ch)) {\n
+      stream.match(/^\\d*(?:\\.\\d*)?(?:e[+\\-]?\\d+)?/);\n
+      return ret("number", "number");\n
+    }\n
+    // Hash\n
+    else if (ch == "#") {\n
+      stream.next();\n
+      // Symbol with string syntax\n
+      ch = stream.peek();\n
+      if (ch == \'"\') {\n
+        stream.next();\n
+        return chain(stream, state, tokenString(\'"\', "symbol", "string-2"));\n
+      }\n
+      // Binary number\n
+      else if (ch == "b") {\n
+        stream.next();\n
+        stream.eatWhile(/[01]/);\n
+        return ret("number", "number");\n
+      }\n
+      // Hex number\n
+      else if (ch == "x") {\n
+        stream.next();\n
+        stream.eatWhile(/[\\da-f]/i);\n
+        return ret("number", "number");\n
+      }\n
+      // Octal number\n
+      else if (ch == "o") {\n
+        stream.next();\n
+        stream.eatWhile(/[0-7]/);\n
+        return ret("number", "number");\n
+      }\n
+      // Hash symbol\n
+      else {\n
+        stream.eatWhile(/[-a-zA-Z]/);\n
+        return ret("hash", "keyword");\n
+      }\n
+    } else if (stream.match("end")) {\n
+      return ret("end", "keyword");\n
+    }\n
+    for (var name in patterns) {\n
+      if (patterns.hasOwnProperty(name)) {\n
+        var pattern = patterns[name];\n
+        if ((pattern instanceof Array && pattern.some(function(p) {\n
+          return stream.match(p);\n
+        })) || stream.match(pattern))\n
+          return ret(name, patternStyles[name], stream.current());\n
+      }\n
+    }\n
+    if (stream.match("define")) {\n
+      return ret("definition", "def");\n
+    } else {\n
+      stream.eatWhile(/[\\w\\-]/);\n
+      // Keyword\n
+      if (wordLookup[stream.current()]) {\n
+        return ret(wordLookup[stream.current()], styleLookup[stream.current()], stream.current());\n
+      } else if (stream.current().match(symbol)) {\n
+        return ret("variable", "variable");\n
+      } else {\n
+        stream.next();\n
+        return ret("other", "variable-2");\n
+      }\n
+    }\n
+  }\n
+\n
+  function tokenComment(stream, state) {\n
+    var maybeEnd = false,\n
+    ch;\n
+    while ((ch = stream.next())) {\n
+      if (ch == "/" && maybeEnd) {\n
+        state.tokenize = tokenBase;\n
+        break;\n
+      }\n
+      maybeEnd = (ch == "*");\n
+    }\n
+    return ret("comment", "comment");\n
+  }\n
+\n
+  function tokenString(quote, type, style) {\n
+    return function(stream, state) {\n
+      var next, end = false;\n
+      while ((next = stream.next()) != null) {\n
+        if (next == quote) {\n
+          end = true;\n
+          break;\n
+        }\n
+      }\n
+      if (end)\n
+        state.tokenize = tokenBase;\n
+      return ret(type, style);\n
+    };\n
+  }\n
+\n
+  // Interface\n
+  return {\n
+    startState: function() {\n
+      return {\n
+        tokenize: tokenBase,\n
+        currentIndent: 0\n
+      };\n
+    },\n
+    token: function(stream, state) {\n
+      if (stream.eatSpace())\n
+        return null;\n
+      var style = state.tokenize(stream, state);\n
+      return style;\n
+    },\n
+    blockCommentStart: "/*",\n
+    blockCommentEnd: "*/"\n
+  };\n
+});\n
+\n
+CodeMirror.defineMIME("text/x-dylan", "dylan");\n
+\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>8778</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ebnf.xml
similarity index 91%
rename from bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec.xml
rename to bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ebnf.xml
index 7935fab2568bf530121f3afcce7de44c4e1a4a5a..4bcf6379db5f5cf2c03ce744fc77cb692f9dc753 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ebnf.xml
@@ -14,7 +14,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>spec</string> </value>
+            <value> <string>ebnf</string> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ebnf/ebnf.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ebnf/ebnf.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7b44034b22df3328193b077b52b64687dd83d0a9
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ebnf/ebnf.js.xml
@@ -0,0 +1,239 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897145.81</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ebnf.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("ebnf", function (config) {\n
+    var commentType = {slash: 0, parenthesis: 1};\n
+    var stateType = {comment: 0, _string: 1, characterClass: 2};\n
+    var bracesMode = null;\n
+\n
+    if (config.bracesMode)\n
+      bracesMode = CodeMirror.getMode(config, config.bracesMode);\n
+\n
+    return {\n
+      startState: function () {\n
+        return {\n
+          stringType: null,\n
+          commentType: null,\n
+          braced: 0,\n
+          lhs: true,\n
+          localState: null,\n
+          stack: [],\n
+          inDefinition: false\n
+        };\n
+      },\n
+      token: function (stream, state) {\n
+        if (!stream) return;\n
+\n
+        //check for state changes\n
+        if (state.stack.length === 0) {\n
+          //strings\n
+          if ((stream.peek() == \'"\') || (stream.peek() == "\'")) {\n
+            state.stringType = stream.peek();\n
+            stream.next(); // Skip quote\n
+            state.stack.unshift(stateType._string);\n
+          } else if (stream.match(/^\\/\\*/)) { //comments starting with /*\n
+            state.stack.unshift(stateType.comment);\n
+            state.commentType = commentType.slash;\n
+          } else if (stream.match(/^\\(\\*/)) { //comments starting with (*\n
+            state.stack.unshift(stateType.comment);\n
+            state.commentType = commentType.parenthesis;\n
+          }\n
+        }\n
+\n
+        //return state\n
+        //stack has\n
+        switch (state.stack[0]) {\n
+        case stateType._string:\n
+          while (state.stack[0] === stateType._string && !stream.eol()) {\n
+            if (stream.peek() === state.stringType) {\n
+              stream.next(); // Skip quote\n
+              state.stack.shift(); // Clear flag\n
+            } else if (stream.peek() === "\\\\") {\n
+              stream.next();\n
+              stream.next();\n
+            } else {\n
+              stream.match(/^.[^\\\\\\"\\\']*/);\n
+            }\n
+          }\n
+          return state.lhs ? "property string" : "string"; // Token style\n
+\n
+        case stateType.comment:\n
+          while (state.stack[0] === stateType.comment && !stream.eol()) {\n
+            if (state.commentType === commentType.slash && stream.match(/\\*\\//)) {\n
+              state.stack.shift(); // Clear flag\n
+              state.commentType = null;\n
+            } else if (state.commentType === commentType.parenthesis && stream.match(/\\*\\)/)) {\n
+              state.stack.shift(); // Clear flag\n
+              state.commentType = null;\n
+            } else {\n
+              stream.match(/^.[^\\*]*/);\n
+            }\n
+          }\n
+          return "comment";\n
+\n
+        case stateType.characterClass:\n
+          while (state.stack[0] === stateType.characterClass && !stream.eol()) {\n
+            if (!(stream.match(/^[^\\]\\\\]+/) || stream.match(/^\\\\./))) {\n
+              state.stack.shift();\n
+            }\n
+          }\n
+          return "operator";\n
+        }\n
+\n
+        var peek = stream.peek();\n
+\n
+        if (bracesMode !== null && (state.braced || peek === "{")) {\n
+          if (state.localState === null)\n
+            state.localState = bracesMode.startState();\n
+\n
+          var token = bracesMode.token(stream, state.localState),\n
+          text = stream.current();\n
+\n
+          if (!token) {\n
+            for (var i = 0; i < text.length; i++) {\n
+              if (text[i] === "{") {\n
+                if (state.braced === 0) {\n
+                  token = "matchingbracket";\n
+                }\n
+                state.braced++;\n
+              } else if (text[i] === "}") {\n
+                state.braced--;\n
+                if (state.braced === 0) {\n
+                  token = "matchingbracket";\n
+                }\n
+              }\n
+            }\n
+          }\n
+          return token;\n
+        }\n
+\n
+        //no stack\n
+        switch (peek) {\n
+        case "[":\n
+          stream.next();\n
+          state.stack.unshift(stateType.characterClass);\n
+          return "bracket";\n
+        case ":":\n
+        case "|":\n
+        case ";":\n
+          stream.next();\n
+          return "operator";\n
+        case "%":\n
+          if (stream.match("%%")) {\n
+            return "header";\n
+          } else if (stream.match(/[%][A-Za-z]+/)) {\n
+            return "keyword";\n
+          } else if (stream.match(/[%][}]/)) {\n
+            return "matchingbracket";\n
+          }\n
+          break;\n
+        case "/":\n
+          if (stream.match(/[\\/][A-Za-z]+/)) {\n
+          return "keyword";\n
+        }\n
+        case "\\\\":\n
+          if (stream.match(/[\\][a-z]+/)) {\n
+            return "string-2";\n
+          }\n
+        case ".":\n
+          if (stream.match(".")) {\n
+            return "atom";\n
+          }\n
+        case "*":\n
+        case "-":\n
+        case "+":\n
+        case "^":\n
+          if (stream.match(peek)) {\n
+            return "atom";\n
+          }\n
+        case "$":\n
+          if (stream.match("$$")) {\n
+            return "builtin";\n
+          } else if (stream.match(/[$][0-9]+/)) {\n
+            return "variable-3";\n
+          }\n
+        case "<":\n
+          if (stream.match(/<<[a-zA-Z_]+>>/)) {\n
+            return "builtin";\n
+          }\n
+        }\n
+\n
+        if (stream.match(/^\\/\\//)) {\n
+          stream.skipToEnd();\n
+          return "comment";\n
+        } else if (stream.match(/return/)) {\n
+          return "operator";\n
+        } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {\n
+          if (stream.match(/(?=[\\(.])/)) {\n
+            return "variable";\n
+          } else if (stream.match(/(?=[\\s\\n]*[:=])/)) {\n
+            return "def";\n
+          }\n
+          return "variable-2";\n
+        } else if (["[", "]", "(", ")"].indexOf(stream.peek()) != -1) {\n
+          stream.next();\n
+          return "bracket";\n
+        } else if (!stream.eatSpace()) {\n
+          stream.next();\n
+        }\n
+        return null;\n
+      }\n
+    };\n
+  });\n
+\n
+  CodeMirror.defineMIME("text/x-ebnf", "ebnf");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>6075</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ecl/ecl.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ecl/ecl.js.xml
index 92e240b79913281c07e2ef94b5f561a8fe233fee..2f09408f298639ddf6eaaf6dcd18656626c2c787 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ecl/ecl.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ecl/ecl.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403100.9</string> </value>
+            <value> <string>ts21897134.06</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("ecl", function(config) {\n
 \n
   function words(str) {\n
@@ -214,6 +227,8 @@ CodeMirror.defineMode("ecl", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-ecl", "ecl");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -224,7 +239,7 @@ CodeMirror.defineMIME("text/x-ecl", "ecl");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>8428</int> </value>
+            <value> <int>8889</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/eiffel/eiffel.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/eiffel/eiffel.js.xml
index a65c881410f3dbd6e93feb84b88cf8a5c2709d41..44ed56c1d07192a52aec559bd9ebe7e3ecac7460 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/eiffel/eiffel.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/eiffel/eiffel.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403088.63</string> </value>
+            <value> <string>ts21897147.15</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("eiffel", function() {\n
   function wordObj(words) {\n
     var o = {};\n
@@ -169,6 +182,8 @@ CodeMirror.defineMode("eiffel", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-eiffel", "eiffel");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -179,7 +194,7 @@ CodeMirror.defineMIME("text/x-eiffel", "eiffel");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3318</int> </value>
+            <value> <int>3779</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/erlang/erlang.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/erlang/erlang.js.xml
index 99c5eee04e9f0335d6feadd0c68abe86ba1e6bfe..3fea48b95e5ff85c133fe3014677ace9f7329577 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/erlang/erlang.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/erlang/erlang.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403087.35</string> </value>
+            <value> <string>ts21897148.75</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*jshint unused:true, eqnull:true, curly:true, bitwise:true */\n
 /*jshint undef:true, latedef:true, trailing:true */\n
 /*global CodeMirror:true */\n
@@ -36,6 +39,16 @@
 //   old guard/bif/conversion clashes (e.g. "float/1")\n
 //   type/spec/opaque\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMIME("text/x-erlang", "erlang");\n
 \n
 CodeMirror.defineMode("erlang", function(cmCfg) {\n
@@ -372,7 +385,7 @@ CodeMirror.defineMode("erlang", function(cmCfg) {\n
     switch (type) {\n
       case "atom":        return "atom";\n
       case "attribute":   return "attribute";\n
-      case "boolean":     return "special";\n
+      case "boolean":     return "atom";\n
       case "builtin":     return "builtin";\n
       case "close_paren": return null;\n
       case "colon":       return null;\n
@@ -629,6 +642,8 @@ CodeMirror.defineMode("erlang", function(cmCfg) {\n
     lineComment: "%"\n
   };\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -639,7 +654,7 @@ CodeMirror.defineMode("erlang", function(cmCfg) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>18585</int> </value>
+            <value> <int>19043</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/fortran/fortran.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/fortran/fortran.js.xml
index 2d1aa703fa8330a5444759752606756cb75a956f..a8ead06dd197a94c3acd785c5dbbc24e7bbffde7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/fortran/fortran.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/fortran/fortran.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403090.76</string> </value>
+            <value> <string>ts21897144.52</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("fortran", function() {\n
   function words(array) {\n
     var keys = {};\n
@@ -195,6 +208,8 @@ CodeMirror.defineMode("fortran", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-fortran", "fortran");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -205,7 +220,7 @@ CodeMirror.defineMIME("text/x-fortran", "fortran");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>8225</int> </value>
+            <value> <int>8686</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gas/gas.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gas/gas.js.xml
index cd6426bc40c0681f9181223a4d931aacf1ae70d4..13cc735d3476fa93a322a14b7806c9381818673c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gas/gas.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gas/gas.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403096.64</string> </value>
+            <value> <string>ts21897137.99</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("gas", function(_config, parserConfig) {\n
   \'use strict\';\n
 \n
@@ -352,6 +365,8 @@ CodeMirror.defineMode("gas", function(_config, parserConfig) {\n
     blockCommentEnd: "*/"\n
   };\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -362,7 +377,7 @@ CodeMirror.defineMode("gas", function(_config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>8425</int> </value>
+            <value> <int>8886</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/gfm.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/gfm.js.xml
index a16250be35614df42a71e42ebad2191e766c7dba..09a2c6dd4b07b2cd5b66f81abc6e87a7e522134c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/gfm.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/gfm.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403096.79</string> </value>
+            <value> <string>ts21897137.84</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("gfm", function(config, modeConfig) {\n
   var codeDepth = 0;\n
   function blankLine(state) {\n
@@ -44,6 +57,8 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) {\n
       };\n
     },\n
     token: function(stream, state) {\n
+      state.combineTokens = null;\n
+\n
       // Hack to prevent formatting override inside code blocks (block and inline)\n
       if (state.codeBlock) {\n
         if (stream.match(/^```/)) {\n
@@ -91,19 +106,22 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) {\n
           // User/Project@SHA\n
           // User@SHA\n
           // SHA\n
+          state.combineTokens = true;\n
           return "link";\n
         } else if (stream.match(/^(?:[a-zA-Z0-9\\-_]+\\/)?(?:[a-zA-Z0-9\\-_]+)?#[0-9]+\\b/)) {\n
           // User/Project#Num\n
           // User#Num\n
           // #Num\n
+          state.combineTokens = true;\n
           return "link";\n
         }\n
       }\n
-      if (stream.match(/^((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]|\\([^\\s()<>]*\\))+(?:\\([^\\s()<>]*\\)|[^\\s`!()\\[\\]{};:\'".,<>?芦禄鈥溾€濃€樷€橾))/i) &&\n
+      if (stream.match(/^((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]|\\([^\\s()<>]*\\))+(?:\\([^\\s()<>]*\\)|[^\\s`*!()\\[\\]{};:\'".,<>?芦禄鈥溾€濃€樷€橾))/i) &&\n
          stream.string.slice(stream.start - 2, stream.start) != "](") {\n
         // URLs\n
         // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls\n
         // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine\n
+        state.combineTokens = true;\n
         return "link";\n
       }\n
       stream.next();\n
@@ -115,7 +133,8 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) {\n
   var markdownConfig = {\n
     underscoresBreakWords: false,\n
     taskLists: true,\n
-    fencedCodeBlocks: true\n
+    fencedCodeBlocks: true,\n
+    strikethrough: true\n
   };\n
   for (var attr in modeConfig) {\n
     markdownConfig[attr] = modeConfig[attr];\n
@@ -124,6 +143,8 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) {\n
   CodeMirror.defineMIME("gfmBase", markdownConfig);\n
   return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);\n
 }, "markdown");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -134,7 +155,7 @@ CodeMirror.defineMode("gfm", function(config, modeConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3119</int> </value>
+            <value> <int>3875</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/test.js.xml
index 5508dcf657333ba6c328ae5a11b4a73bbc424d77..552e674f42d919c174d27196a4416a683617ea12 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gfm/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403097.0</string> </value>
+            <value> <string>ts21897137.65</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   var mode = CodeMirror.getMode({tabSize: 4}, "gfm");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
@@ -42,6 +45,12 @@
   FT("taskList",\n
      "[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2  foo]",\n
      "[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2  foo]");\n
+\n
+  FT("formatting_strikethrough",\n
+     "[strikethrough&formatting&formatting-strikethrough ~~][strikethrough foo][strikethrough&formatting&formatting-strikethrough ~~]");\n
+\n
+  FT("formatting_strikethrough",\n
+     "foo [strikethrough&formatting&formatting-strikethrough ~~][strikethrough bar][strikethrough&formatting&formatting-strikethrough ~~]");\n
 \n
   MT("emInWordAsterisk",\n
      "foo[em *bar*]hello");\n
@@ -96,6 +105,9 @@
 \n
   MT("SHA",\n
      "foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar");\n
+\n
+  MT("SHAEmphasis",\n
+     "[em *foo ][em&link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");\n
 \n
   MT("shortSHA",\n
      "foo [link be6a8cc] bar");\n
@@ -111,21 +123,36 @@
 \n
   MT("userSHA",\n
      "foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello");\n
+\n
+  MT("userSHAEmphasis",\n
+     "[em *foo ][em&link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");\n
 \n
   MT("userProjectSHA",\n
      "foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world");\n
+\n
+  MT("userProjectSHAEmphasis",\n
+     "[em *foo ][em&link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]");\n
 \n
   MT("num",\n
      "foo [link #1] bar");\n
+\n
+  MT("numEmphasis",\n
+     "[em *foo ][em&link #1][em *]");\n
 \n
   MT("badNum",\n
      "foo #1bar hello");\n
 \n
   MT("userNum",\n
      "foo [link bar#1] hello");\n
+\n
+  MT("userNumEmphasis",\n
+     "[em *foo ][em&link bar#1][em *]");\n
 \n
   MT("userProjectNum",\n
      "foo [link bar/hello#1] world");\n
+\n
+  MT("userProjectNumEmphasis",\n
+     "[em *foo ][em&link bar/hello#1][em *]");\n
 \n
   MT("vanillaLink",\n
      "foo [link http://www.example.com/] bar");\n
@@ -135,6 +162,9 @@
 \n
   MT("vanillaLinkExtension",\n
      "foo [link http://www.example.com/index.html] bar");\n
+\n
+  MT("vanillaLinkEmphasis",\n
+     "foo [em *][em&link http://www.example.com/index.html][em *] bar");\n
 \n
   MT("notALink",\n
      "[comment ```css]",\n
@@ -150,6 +180,60 @@
      "[comment `foo]",\n
      "",\n
      "[link http://www.example.com/]");\n
+\n
+  MT("headerCodeBlockGithub",\n
+     "[header&header-1 # heading]",\n
+     "",\n
+     "[comment ```]",\n
+     "[comment code]",\n
+     "[comment ```]",\n
+     "",\n
+     "Commit: [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2]",\n
+     "Issue: [link #1]",\n
+     "Link: [link http://www.example.com/]");\n
+\n
+  MT("strikethrough",\n
+     "[strikethrough ~~foo~~]");\n
+\n
+  MT("strikethroughWithStartingSpace",\n
+     "~~ foo~~");\n
+\n
+  MT("strikethroughUnclosedStrayTildes",\n
+    "[strikethrough ~~foo~~~]");\n
+\n
+  MT("strikethroughUnclosedStrayTildes",\n
+     "[strikethrough ~~foo ~~]");\n
+\n
+  MT("strikethroughUnclosedStrayTildes",\n
+    "[strikethrough ~~foo ~~ bar]");\n
+\n
+  MT("strikethroughUnclosedStrayTildes",\n
+    "[strikethrough ~~foo ~~ bar~~]hello");\n
+\n
+  MT("strikethroughOneLetter",\n
+     "[strikethrough ~~a~~]");\n
+\n
+  MT("strikethroughWrapped",\n
+     "[strikethrough ~~foo]",\n
+     "[strikethrough foo~~]");\n
+\n
+  MT("strikethroughParagraph",\n
+     "[strikethrough ~~foo]",\n
+     "",\n
+     "foo[strikethrough ~~bar]");\n
+\n
+  MT("strikethroughEm",\n
+     "[strikethrough ~~foo][em&strikethrough *bar*][strikethrough ~~]");\n
+\n
+  MT("strikethroughEm",\n
+     "[em *][em&strikethrough ~~foo~~][em *]");\n
+\n
+  MT("strikethroughStrong",\n
+     "[strikethrough ~~][strong&strikethrough **foo**][strikethrough ~~]");\n
+\n
+  MT("strikethroughStrong",\n
+     "[strong **][strong&strikethrough ~~foo~~][strong **]");\n
+\n
 })();\n
 
 
@@ -161,7 +245,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4478</int> </value>
+            <value> <int>6922</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gherkin/gherkin.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gherkin/gherkin.js.xml
index 801470ed21a3642d93cde352ebcfad11c6c9d47a..46e43c4cf8b0484298866a4a05e2021922f7e65b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gherkin/gherkin.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/gherkin/gherkin.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403102.2</string> </value>
+            <value> <string>ts21897133.2</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,9 +22,12 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*\n
 Gherkin mode - http://www.cukes.info/\n
-Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues\n
+Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues\n
 */\n
 \n
 // Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js\n
@@ -37,6 +40,16 @@ Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues\n
 //  keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/\n
 //};\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("gherkin", function () {\n
   return {\n
     startState: function () {\n
@@ -185,6 +198,8 @@ CodeMirror.defineMode("gherkin", function () {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-feature", "gherkin");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -195,7 +210,7 @@ CodeMirror.defineMIME("text/x-feature", "gherkin");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>12793</int> </value>
+            <value> <int>13257</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/go/go.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/go/go.js.xml
index 2beb8680c25e02e46e39127b0fd82ab1d5e8c061..d018d998d0bf00790cacb3006286942be77da9d7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/go/go.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/go/go.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403097.68</string> </value>
+            <value> <string>ts21897136.87</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("go", function(config) {\n
   var indentUnit = config.indentUnit;\n
 \n
@@ -82,7 +95,7 @@ CodeMirror.defineMode("go", function(config) {\n
       stream.eatWhile(isOperatorChar);\n
       return "operator";\n
     }\n
-    stream.eatWhile(/[\\w\\$_]/);\n
+    stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n
     var cur = stream.current();\n
     if (keywords.propertyIsEnumerable(cur)) {\n
       if (cur == "case" || cur == "default") curPunc = "case";\n
@@ -183,6 +196,7 @@ CodeMirror.defineMode("go", function(config) {\n
     },\n
 \n
     electricChars: "{}):",\n
+    fold: "brace",\n
     blockCommentStart: "/*",\n
     blockCommentEnd: "*/",\n
     lineComment: "//"\n
@@ -190,6 +204,8 @@ CodeMirror.defineMode("go", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-go", "go");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -200,7 +216,7 @@ CodeMirror.defineMIME("text/x-go", "go");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5394</int> </value>
+            <value> <int>5885</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/groovy/groovy.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/groovy/groovy.js.xml
index 8e5528a27274737348641b226f9f5f1aef9f3450..da9f842d8a9cc2d6ad6e0b673df5ed7704db2457 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/groovy/groovy.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/groovy/groovy.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403100.16</string> </value>
+            <value> <string>ts21897134.69</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("groovy", function(config) {\n
   function words(str) {\n
     var obj = {}, words = str.split(" ");\n
@@ -233,6 +246,8 @@ CodeMirror.defineMode("groovy", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-groovy", "groovy");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -243,7 +258,7 @@ CodeMirror.defineMIME("text/x-groovy", "groovy");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7164</int> </value>
+            <value> <int>7625</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/haml.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/haml.js.xml
index b1e57d021f11f0af89d965d00be2bd8f8dd2f1b7..b60d7e353fb031158d37088ffead832f280c6789 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/haml.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/haml.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403091.51</string> </value>
+            <value> <string>ts21897143.56</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,8 +22,18 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
-  "use strict";\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
 \n
   // full haml mode. This handled embeded ruby and html fragments too\n
   CodeMirror.defineMode("haml", function(config) {\n
@@ -89,7 +99,7 @@
       // donot handle --> as valid ruby, make it HTML close comment instead\n
       if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {\n
         state.tokenize = ruby;\n
-        return null;\n
+        return state.tokenize(stream, state);\n
       }\n
 \n
       if (state.previousToken.style == "hamlTag" ||\n
@@ -97,10 +107,10 @@
           state.previousToken.style == "hamlAttribute") {\n
         if (ch == "(") {\n
           state.tokenize = rubyInQuote(")");\n
-          return null;\n
+          return state.tokenize(stream, state);\n
         } else if (ch == "{") {\n
           state.tokenize = rubyInQuote("}");\n
-          return null;\n
+          return state.tokenize(stream, state);\n
         }\n
       }\n
 \n
@@ -170,7 +180,7 @@
   }, "htmlmixed", "ruby");\n
 \n
   CodeMirror.defineMIME("text/x-haml", "haml");\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -181,7 +191,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4675</int> </value>
+            <value> <int>5275</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/test.js.xml
index 0f0521968d412ec08b3afc42a19511609e30b318..7459adea481d2fcb04e13f95dd4099015a85ac4e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haml/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403091.68</string> </value>
+            <value> <string>ts21897143.42</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
@@ -52,7 +55,7 @@
      "[tag %a]([variable title][operator =][string \\"test\\"]){[atom :title] [operator =>] [string \\"test\\"]}");\n
 \n
   MT("htmlCode",\n
-     "[tag <h1>]Title[tag </h1>]");\n
+     "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");\n
 \n
   MT("rubyBlock",\n
      "[operator =][variable-2 @item]");\n
@@ -74,9 +77,9 @@
       "  [comment -# this is a comment]",\n
       "     [comment and this is a comment too]",\n
       "  Date/Time",\n
-      "  [operator -] [variable now] [operator =] [tag DateTime][operator .][variable now]",\n
+      "  [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]",\n
       "  [tag %strong=] [variable now]",\n
-      "  [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][variable parse]([string \\"December 31, 2006\\"])",\n
+      "  [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \\"December 31, 2006\\"])",\n
       "     [operator =][string \\"Happy\\"]",\n
       "     [operator =][string \\"Belated\\"]",\n
       "     [operator =][string \\"Birthday\\"]");\n
@@ -126,7 +129,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2826</int> </value>
+            <value> <int>3010</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haskell/haskell.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haskell/haskell.js.xml
index f8bff85cb558f534051bc0b4c23f6c02d84ee0df..7afd74b90aecb8a456109f851bb666b6bfa5dd19 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haskell/haskell.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haskell/haskell.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403102.98</string> </value>
+            <value> <string>ts21897132.32</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("haskell", function(_config, modeConfig) {\n
 \n
   function switchState(source, setState, f) {\n
@@ -35,7 +48,7 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {\n
   var digitRE = /\\d/;\n
   var hexitRE = /[0-9A-Fa-f]/;\n
   var octitRE = /[0-7]/;\n
-  var idRE = /[a-z_A-Z0-9\']/;\n
+  var idRE = /[a-z_A-Z0-9\'\\xa1-\\uffff]/;\n
   var symbolRE = /[-!#$%&*+.\\/<=>?@\\\\^|~:]/;\n
   var specialRE = /[(),;[\\]`{}]/;\n
   var whiteCharRE = /[ \\t\\v\\f]/; // newlines are handled in tokenizer\n
@@ -274,6 +287,8 @@ CodeMirror.defineMode("haskell", function(_config, modeConfig) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-haskell", "haskell");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -284,7 +299,7 @@ CodeMirror.defineMIME("text/x-haskell", "haskell");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7629</int> </value>
+            <value> <int>8101</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haxe/haxe.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haxe/haxe.js.xml
index 06246f836c83d47e5e2ea954945ebca13b7a386b..5c374d3380088cff149dd5734c80c2b40206fa38 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haxe/haxe.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/haxe/haxe.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403095.51</string> </value>
+            <value> <string>ts21897139.05</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("haxe", function(config, parserConfig) {\n
   var indentUnit = config.indentUnit;\n
 \n
@@ -40,7 +53,7 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {\n
       "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),\n
       "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),\n
       "in": operator, "never": kw("property_access"), "trace":kw("trace"),\n
-    "class": type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,\n
+    "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,\n
       "true": atom, "false": atom, "null": atom\n
     };\n
   }();\n
@@ -259,11 +272,12 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {\n
   poplex.lex = true;\n
 \n
   function expect(wanted) {\n
-    return function(type) {\n
+    function f(type) {\n
       if (type == wanted) return cont();\n
       else if (wanted == ";") return pass();\n
-      else return cont(arguments.callee);\n
+      else return cont(f);\n
     };\n
+    return f;\n
   }\n
 \n
   function statement(type) {\n
@@ -329,12 +343,13 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {\n
 \n
   function importdef (type, value) {\n
   if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }\n
-  else if(type == "variable" || type == "property" || type == ".") return cont(importdef);\n
+  else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef);\n
   }\n
 \n
   function typedef (type, value)\n
   {\n
   if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }\n
+  else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); }\n
   }\n
 \n
   function maybelabel(type) {\n
@@ -446,11 +461,85 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {\n
       else return lexical.indented + (closing ? 0 : indentUnit);\n
     },\n
 \n
-    electricChars: "{}"\n
+    electricChars: "{}",\n
+    blockCommentStart: "/*",\n
+    blockCommentEnd: "*/",\n
+    lineComment: "//"\n
   };\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-haxe", "haxe");\n
+\n
+CodeMirror.defineMode("hxml", function () {\n
+\n
+  return {\n
+    startState: function () {\n
+      return {\n
+        define: false,\n
+        inString: false\n
+      };\n
+    },\n
+    token: function (stream, state) {\n
+      var ch = stream.peek();\n
+      var sol = stream.sol();\n
+\n
+      ///* comments */\n
+      if (ch == "#") {\n
+        stream.skipToEnd();\n
+        return "comment";\n
+      }\n
+      if (sol && ch == "-") {\n
+        var style = "variable-2";\n
+\n
+        stream.eat(/-/);\n
+\n
+        if (stream.peek() == "-") {\n
+          stream.eat(/-/);\n
+          style = "keyword a";\n
+        }\n
+\n
+        if (stream.peek() == "D") {\n
+          stream.eat(/[D]/);\n
+          style = "keyword c";\n
+          state.define = true;\n
+        }\n
+\n
+        stream.eatWhile(/[A-Z]/i);\n
+        return style;\n
+      }\n
+\n
+      var ch = stream.peek();\n
+\n
+      if (state.inString == false && ch == "\'") {\n
+        state.inString = true;\n
+        ch = stream.next();\n
+      }\n
+\n
+      if (state.inString == true) {\n
+        if (stream.skipTo("\'")) {\n
+\n
+        } else {\n
+          stream.skipToEnd();\n
+        }\n
+\n
+        if (stream.peek() == "\'") {\n
+          stream.next();\n
+          state.inString = false;\n
+        }\n
+\n
+        return "string";\n
+      }\n
+\n
+      stream.next();\n
+      return null;\n
+    },\n
+    lineComment: "#"\n
+  };\n
+});\n
+\n
+CodeMirror.defineMIME("text/x-hxml", "hxml");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -461,7 +550,7 @@ CodeMirror.defineMIME("text/x-haxe", "haxe");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>15104</int> </value>
+            <value> <int>17064</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlembedded/htmlembedded.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlembedded/htmlembedded.js.xml
index acf471d55907a6ddf16626c8c5021fc9c937d5ae..ccbd06294b08458eb9500480b99a2f1d1b965418 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlembedded/htmlembedded.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlembedded/htmlembedded.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403097.58</string> </value>
+            <value> <string>ts21897137.0</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {\n
 \n
   //config settings\n
@@ -93,6 +106,8 @@ CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingMode
 CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});\n
 CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});\n
 CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"});\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -103,7 +118,7 @@ CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingMode
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2594</int> </value>
+            <value> <int>3116</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlmixed/htmlmixed.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlmixed/htmlmixed.js.xml
index b3f0082514c58559399c4cf9b2fe41cfe5f30a76..583d6b53887a87b966601c983d9ad9fa43128437 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlmixed/htmlmixed.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/htmlmixed/htmlmixed.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403086.62</string> </value>
+            <value> <string>ts21897149.26</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {\n
   var htmlMode = CodeMirror.getMode(config, {name: "xml",\n
                                              htmlMode: true,\n
@@ -41,6 +54,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {\n
 \n
   function html(stream, state) {\n
     var tagName = state.htmlState.tagName;\n
+    if (tagName) tagName = tagName.toLowerCase();\n
     var style = htmlMode.token(stream, state.htmlState);\n
     if (tagName == "script" && /\\btag\\b/.test(style) && stream.current() == ">") {\n
       // Script block: mode to change to depends on type attribute\n
@@ -79,7 +93,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {\n
     if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n
       state.token = html;\n
       state.localState = state.localMode = null;\n
-      return html(stream, state);\n
+      return null;\n
     }\n
     return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n
                        state.localMode.token(stream, state.localState));\n
@@ -88,7 +102,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {\n
     if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n
       state.token = html;\n
       state.localState = state.localMode = null;\n
-      return html(stream, state);\n
+      return null;\n
     }\n
     return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n
                        cssMode.token(stream, state.localState));\n
@@ -127,6 +141,8 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {\n
 }, "xml", "javascript", "css");\n
 \n
 CodeMirror.defineMIME("text/html", "htmlmixed");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -137,7 +153,7 @@ CodeMirror.defineMIME("text/html", "htmlmixed");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4388</int> </value>
+            <value> <int>5008</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/http/http.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/http/http.js.xml
index d5c79506b8667250dc779eb39bc63d6394d1eaa5..9602a9377d4ad8ac2547b33dd51a3be5efdb836d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/http/http.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/http/http.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403094.37</string> </value>
+            <value> <string>ts21897140.19</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("http", function() {\n
   function failFirstLine(stream, state) {\n
     stream.skipToEnd();\n
@@ -120,6 +133,8 @@ CodeMirror.defineMode("http", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("message/http", "http");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -130,7 +145,7 @@ CodeMirror.defineMIME("message/http", "http");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2334</int> </value>
+            <value> <int>2795</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/idl.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/idl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..31e7b5bcad65fa319b0d3cab8aaedb33056e9c37
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/idl.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>idl</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/idl/idl.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/idl/idl.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2ac3ce1a51e7d2112afe91b9412d106f03145b98
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/idl/idl.js.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897143.88</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>idl.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  function wordRegexp(words) {\n
+    return new RegExp(\'^((\' + words.join(\')|(\') + \'))\\\\b\', \'i\');\n
+  };\n
+\n
+  var builtinArray = [\n
+    \'a_correlate\', \'abs\', \'acos\', \'adapt_hist_equal\', \'alog\',\n
+    \'alog2\', \'alog10\', \'amoeba\', \'annotate\', \'app_user_dir\',\n
+    \'app_user_dir_query\', \'arg_present\', \'array_equal\', \'array_indices\',\n
+    \'arrow\', \'ascii_template\', \'asin\', \'assoc\', \'atan\',\n
+    \'axis\', \'axis\', \'bandpass_filter\', \'bandreject_filter\', \'barplot\',\n
+    \'bar_plot\', \'beseli\', \'beselj\', \'beselk\', \'besely\',\n
+    \'beta\', \'biginteger\', \'bilinear\', \'bin_date\', \'binary_template\',\n
+    \'bindgen\', \'binomial\', \'bit_ffs\', \'bit_population\', \'blas_axpy\',\n
+    \'blk_con\', \'boolarr\', \'boolean\', \'boxplot\', \'box_cursor\',\n
+    \'breakpoint\', \'broyden\', \'bubbleplot\', \'butterworth\', \'bytarr\',\n
+    \'byte\', \'byteorder\', \'bytscl\', \'c_correlate\', \'calendar\',\n
+    \'caldat\', \'call_external\', \'call_function\', \'call_method\',\n
+    \'call_procedure\', \'canny\', \'catch\', \'cd\', \'cdf\', \'ceil\',\n
+    \'chebyshev\', \'check_math\', \'chisqr_cvf\', \'chisqr_pdf\', \'choldc\',\n
+    \'cholsol\', \'cindgen\', \'cir_3pnt\', \'clipboard\', \'close\',\n
+    \'clust_wts\', \'cluster\', \'cluster_tree\', \'cmyk_convert\', \'code_coverage\',\n
+    \'color_convert\', \'color_exchange\', \'color_quan\', \'color_range_map\',\n
+    \'colorbar\', \'colorize_sample\', \'colormap_applicable\',\n
+    \'colormap_gradient\', \'colormap_rotation\', \'colortable\',\n
+    \'comfit\', \'command_line_args\', \'common\', \'compile_opt\', \'complex\',\n
+    \'complexarr\', \'complexround\', \'compute_mesh_normals\', \'cond\', \'congrid\',\n
+    \'conj\', \'constrained_min\', \'contour\', \'contour\', \'convert_coord\',\n
+    \'convol\', \'convol_fft\', \'coord2to3\', \'copy_lun\', \'correlate\',\n
+    \'cos\', \'cosh\', \'cpu\', \'cramer\', \'createboxplotdata\',\n
+    \'create_cursor\', \'create_struct\', \'create_view\', \'crossp\', \'crvlength\',\n
+    \'ct_luminance\', \'cti_test\', \'cursor\', \'curvefit\', \'cv_coord\',\n
+    \'cvttobm\', \'cw_animate\', \'cw_animate_getp\', \'cw_animate_load\',\n
+    \'cw_animate_run\', \'cw_arcball\', \'cw_bgroup\', \'cw_clr_index\',\n
+    \'cw_colorsel\', \'cw_defroi\', \'cw_field\', \'cw_filesel\', \'cw_form\',\n
+    \'cw_fslider\', \'cw_light_editor\', \'cw_light_editor_get\',\n
+    \'cw_light_editor_set\', \'cw_orient\', \'cw_palette_editor\',\n
+    \'cw_palette_editor_get\', \'cw_palette_editor_set\', \'cw_pdmenu\',\n
+    \'cw_rgbslider\', \'cw_tmpl\', \'cw_zoom\', \'db_exists\',\n
+    \'dblarr\', \'dcindgen\', \'dcomplex\', \'dcomplexarr\', \'define_key\',\n
+    \'define_msgblk\', \'define_msgblk_from_file\', \'defroi\', \'defsysv\',\n
+    \'delvar\', \'dendro_plot\', \'dendrogram\', \'deriv\', \'derivsig\',\n
+    \'determ\', \'device\', \'dfpmin\', \'diag_matrix\', \'dialog_dbconnect\',\n
+    \'dialog_message\', \'dialog_pickfile\', \'dialog_printersetup\',\n
+    \'dialog_printjob\', \'dialog_read_image\',\n
+    \'dialog_write_image\', \'dictionary\', \'digital_filter\', \'dilate\', \'dindgen\',\n
+    \'dissolve\', \'dist\', \'distance_measure\', \'dlm_load\', \'dlm_register\',\n
+    \'doc_library\', \'double\', \'draw_roi\', \'edge_dog\', \'efont\',\n
+    \'eigenql\', \'eigenvec\', \'ellipse\', \'elmhes\', \'emboss\',\n
+    \'empty\', \'enable_sysrtn\', \'eof\', \'eos\', \'erase\',\n
+    \'erf\', \'erfc\', \'erfcx\', \'erode\', \'errorplot\',\n
+    \'errplot\', \'estimator_filter\', \'execute\', \'exit\', \'exp\',\n
+    \'expand\', \'expand_path\', \'expint\', \'extrac\', \'extract_slice\',\n
+    \'f_cvf\', \'f_pdf\', \'factorial\', \'fft\', \'file_basename\',\n
+    \'file_chmod\', \'file_copy\', \'file_delete\', \'file_dirname\',\n
+    \'file_expand_path\', \'file_gunzip\', \'file_gzip\', \'file_info\',\n
+    \'file_lines\', \'file_link\', \'file_mkdir\', \'file_move\',\n
+    \'file_poll_input\', \'file_readlink\', \'file_same\',\n
+    \'file_search\', \'file_tar\', \'file_test\', \'file_untar\', \'file_unzip\',\n
+    \'file_which\', \'file_zip\', \'filepath\', \'findgen\', \'finite\',\n
+    \'fix\', \'flick\', \'float\', \'floor\', \'flow3\',\n
+    \'fltarr\', \'flush\', \'format_axis_values\', \'forward_function\', \'free_lun\',\n
+    \'fstat\', \'fulstr\', \'funct\', \'function\', \'fv_test\',\n
+    \'fx_root\', \'fz_roots\', \'gamma\', \'gamma_ct\', \'gauss_cvf\',\n
+    \'gauss_pdf\', \'gauss_smooth\', \'gauss2dfit\', \'gaussfit\',\n
+    \'gaussian_function\', \'gaussint\', \'get_drive_list\', \'get_dxf_objects\',\n
+    \'get_kbrd\', \'get_login_info\',\n
+    \'get_lun\', \'get_screen_size\', \'getenv\', \'getwindows\', \'greg2jul\',\n
+    \'grib\', \'grid_input\', \'grid_tps\', \'grid3\', \'griddata\',\n
+    \'gs_iter\', \'h_eq_ct\', \'h_eq_int\', \'hanning\', \'hash\',\n
+    \'hdf\', \'hdf5\', \'heap_free\', \'heap_gc\', \'heap_nosave\',\n
+    \'heap_refcount\', \'heap_save\', \'help\', \'hilbert\', \'hist_2d\',\n
+    \'hist_equal\', \'histogram\', \'hls\', \'hough\', \'hqr\',\n
+    \'hsv\', \'i18n_multibytetoutf8\',\n
+    \'i18n_multibytetowidechar\', \'i18n_utf8tomultibyte\',\n
+    \'i18n_widechartomultibyte\',\n
+    \'ibeta\', \'icontour\', \'iconvertcoord\', \'idelete\', \'identity\',\n
+    \'idl_base64\', \'idl_container\', \'idl_validname\',\n
+    \'idlexbr_assistant\', \'idlitsys_createtool\',\n
+    \'idlunit\', \'iellipse\', \'igamma\', \'igetcurrent\', \'igetdata\',\n
+    \'igetid\', \'igetproperty\', \'iimage\', \'image\', \'image_cont\',\n
+    \'image_statistics\', \'image_threshold\', \'imaginary\', \'imap\', \'indgen\',\n
+    \'int_2d\', \'int_3d\', \'int_tabulated\', \'intarr\', \'interpol\',\n
+    \'interpolate\', \'interval_volume\', \'invert\', \'ioctl\', \'iopen\',\n
+    \'ir_filter\', \'iplot\', \'ipolygon\', \'ipolyline\', \'iputdata\',\n
+    \'iregister\', \'ireset\', \'iresolve\', \'irotate\', \'isa\',\n
+    \'isave\', \'iscale\', \'isetcurrent\', \'isetproperty\', \'ishft\',\n
+    \'isocontour\', \'isosurface\', \'isurface\', \'itext\', \'itranslate\',\n
+    \'ivector\', \'ivolume\', \'izoom\', \'journal\', \'json_parse\',\n
+    \'json_serialize\', \'jul2greg\', \'julday\', \'keyword_set\', \'krig2d\',\n
+    \'kurtosis\', \'kw_test\', \'l64indgen\', \'la_choldc\', \'la_cholmprove\',\n
+    \'la_cholsol\', \'la_determ\', \'la_eigenproblem\', \'la_eigenql\', \'la_eigenvec\',\n
+    \'la_elmhes\', \'la_gm_linear_model\', \'la_hqr\', \'la_invert\',\n
+    \'la_least_square_equality\', \'la_least_squares\', \'la_linear_equation\',\n
+    \'la_ludc\', \'la_lumprove\', \'la_lusol\',\n
+    \'la_svd\', \'la_tridc\', \'la_trimprove\', \'la_triql\', \'la_trired\',\n
+    \'la_trisol\', \'label_date\', \'label_region\', \'ladfit\', \'laguerre\',\n
+    \'lambda\', \'lambdap\', \'lambertw\', \'laplacian\', \'least_squares_filter\',\n
+    \'leefilt\', \'legend\', \'legendre\', \'linbcg\', \'lindgen\',\n
+    \'linfit\', \'linkimage\', \'list\', \'ll_arc_distance\', \'lmfit\',\n
+    \'lmgr\', \'lngamma\', \'lnp_test\', \'loadct\', \'locale_get\',\n
+    \'logical_and\', \'logical_or\', \'logical_true\', \'lon64arr\', \'lonarr\',\n
+    \'long\', \'long64\', \'lsode\', \'lu_complex\', \'ludc\',\n
+    \'lumprove\', \'lusol\', \'m_correlate\', \'machar\', \'make_array\',\n
+    \'make_dll\', \'make_rt\', \'map\', \'mapcontinents\', \'mapgrid\',\n
+    \'map_2points\', \'map_continents\', \'map_grid\', \'map_image\', \'map_patch\',\n
+    \'map_proj_forward\', \'map_proj_image\', \'map_proj_info\',\n
+    \'map_proj_init\', \'map_proj_inverse\',\n
+    \'map_set\', \'matrix_multiply\', \'matrix_power\', \'max\', \'md_test\',\n
+    \'mean\', \'meanabsdev\', \'mean_filter\', \'median\', \'memory\',\n
+    \'mesh_clip\', \'mesh_decimate\', \'mesh_issolid\',\n
+    \'mesh_merge\', \'mesh_numtriangles\',\n
+    \'mesh_obj\', \'mesh_smooth\', \'mesh_surfacearea\',\n
+    \'mesh_validate\', \'mesh_volume\',\n
+    \'message\', \'min\', \'min_curve_surf\', \'mk_html_help\', \'modifyct\',\n
+    \'moment\', \'morph_close\', \'morph_distance\',\n
+    \'morph_gradient\', \'morph_hitormiss\',\n
+    \'morph_open\', \'morph_thin\', \'morph_tophat\', \'multi\', \'n_elements\',\n
+    \'n_params\', \'n_tags\', \'ncdf\', \'newton\', \'noise_hurl\',\n
+    \'noise_pick\', \'noise_scatter\', \'noise_slur\', \'norm\', \'obj_class\',\n
+    \'obj_destroy\', \'obj_hasmethod\', \'obj_isa\', \'obj_new\', \'obj_valid\',\n
+    \'objarr\', \'on_error\', \'on_ioerror\', \'online_help\', \'openr\',\n
+    \'openu\', \'openw\', \'oplot\', \'oploterr\', \'orderedhash\',\n
+    \'p_correlate\', \'parse_url\', \'particle_trace\', \'path_cache\', \'path_sep\',\n
+    \'pcomp\', \'plot\', \'plot3d\', \'plot\', \'plot_3dbox\',\n
+    \'plot_field\', \'ploterr\', \'plots\', \'polar_contour\', \'polar_surface\',\n
+    \'polyfill\', \'polyshade\', \'pnt_line\', \'point_lun\', \'polarplot\',\n
+    \'poly\', \'poly_2d\', \'poly_area\', \'poly_fit\', \'polyfillv\',\n
+    \'polygon\', \'polyline\', \'polywarp\', \'popd\', \'powell\',\n
+    \'pref_commit\', \'pref_get\', \'pref_set\', \'prewitt\', \'primes\',\n
+    \'print\', \'printf\', \'printd\', \'pro\', \'product\',\n
+    \'profile\', \'profiler\', \'profiles\', \'project_vol\', \'ps_show_fonts\',\n
+    \'psafm\', \'pseudo\', \'ptr_free\', \'ptr_new\', \'ptr_valid\',\n
+    \'ptrarr\', \'pushd\', \'qgrid3\', \'qhull\', \'qromb\',\n
+    \'qromo\', \'qsimp\', \'query_*\', \'query_ascii\', \'query_bmp\',\n
+    \'query_csv\', \'query_dicom\', \'query_gif\', \'query_image\', \'query_jpeg\',\n
+    \'query_jpeg2000\', \'query_mrsid\', \'query_pict\', \'query_png\', \'query_ppm\',\n
+    \'query_srf\', \'query_tiff\', \'query_video\', \'query_wav\', \'r_correlate\',\n
+    \'r_test\', \'radon\', \'randomn\', \'randomu\', \'ranks\',\n
+    \'rdpix\', \'read\', \'readf\', \'read_ascii\', \'read_binary\',\n
+    \'read_bmp\', \'read_csv\', \'read_dicom\', \'read_gif\', \'read_image\',\n
+    \'read_interfile\', \'read_jpeg\', \'read_jpeg2000\', \'read_mrsid\', \'read_pict\',\n
+    \'read_png\', \'read_ppm\', \'read_spr\', \'read_srf\', \'read_sylk\',\n
+    \'read_tiff\', \'read_video\', \'read_wav\', \'read_wave\', \'read_x11_bitmap\',\n
+    \'read_xwd\', \'reads\', \'readu\', \'real_part\', \'rebin\',\n
+    \'recall_commands\', \'recon3\', \'reduce_colors\', \'reform\', \'region_grow\',\n
+    \'register_cursor\', \'regress\', \'replicate\',\n
+    \'replicate_inplace\', \'resolve_all\',\n
+    \'resolve_routine\', \'restore\', \'retall\', \'return\', \'reverse\',\n
+    \'rk4\', \'roberts\', \'rot\', \'rotate\', \'round\',\n
+    \'routine_filepath\', \'routine_info\', \'rs_test\', \'s_test\', \'save\',\n
+    \'savgol\', \'scale3\', \'scale3d\', \'scatterplot\', \'scatterplot3d\',\n
+    \'scope_level\', \'scope_traceback\', \'scope_varfetch\',\n
+    \'scope_varname\', \'search2d\',\n
+    \'search3d\', \'sem_create\', \'sem_delete\', \'sem_lock\', \'sem_release\',\n
+    \'set_plot\', \'set_shading\', \'setenv\', \'sfit\', \'shade_surf\',\n
+    \'shade_surf_irr\', \'shade_volume\', \'shift\', \'shift_diff\', \'shmdebug\',\n
+    \'shmmap\', \'shmunmap\', \'shmvar\', \'show3\', \'showfont\',\n
+    \'signum\', \'simplex\', \'sin\', \'sindgen\', \'sinh\',\n
+    \'size\', \'skewness\', \'skip_lun\', \'slicer3\', \'slide_image\',\n
+    \'smooth\', \'sobel\', \'socket\', \'sort\', \'spawn\',\n
+    \'sph_4pnt\', \'sph_scat\', \'spher_harm\', \'spl_init\', \'spl_interp\',\n
+    \'spline\', \'spline_p\', \'sprsab\', \'sprsax\', \'sprsin\',\n
+    \'sprstp\', \'sqrt\', \'standardize\', \'stddev\', \'stop\',\n
+    \'strarr\', \'strcmp\', \'strcompress\', \'streamline\', \'streamline\',\n
+    \'stregex\', \'stretch\', \'string\', \'strjoin\', \'strlen\',\n
+    \'strlowcase\', \'strmatch\', \'strmessage\', \'strmid\', \'strpos\',\n
+    \'strput\', \'strsplit\', \'strtrim\', \'struct_assign\', \'struct_hide\',\n
+    \'strupcase\', \'surface\', \'surface\', \'surfr\', \'svdc\',\n
+    \'svdfit\', \'svsol\', \'swap_endian\', \'swap_endian_inplace\', \'symbol\',\n
+    \'systime\', \'t_cvf\', \'t_pdf\', \'t3d\', \'tag_names\',\n
+    \'tan\', \'tanh\', \'tek_color\', \'temporary\', \'terminal_size\',\n
+    \'tetra_clip\', \'tetra_surface\', \'tetra_volume\', \'text\', \'thin\',\n
+    \'thread\', \'threed\', \'tic\', \'time_test2\', \'timegen\',\n
+    \'timer\', \'timestamp\', \'timestamptovalues\', \'tm_test\', \'toc\',\n
+    \'total\', \'trace\', \'transpose\', \'tri_surf\', \'triangulate\',\n
+    \'trigrid\', \'triql\', \'trired\', \'trisol\', \'truncate_lun\',\n
+    \'ts_coef\', \'ts_diff\', \'ts_fcast\', \'ts_smooth\', \'tv\',\n
+    \'tvcrs\', \'tvlct\', \'tvrd\', \'tvscl\', \'typename\',\n
+    \'uindgen\', \'uint\', \'uintarr\', \'ul64indgen\', \'ulindgen\',\n
+    \'ulon64arr\', \'ulonarr\', \'ulong\', \'ulong64\', \'uniq\',\n
+    \'unsharp_mask\', \'usersym\', \'value_locate\', \'variance\', \'vector\',\n
+    \'vector_field\', \'vel\', \'velovect\', \'vert_t3d\', \'voigt\',\n
+    \'volume\', \'voronoi\', \'voxel_proj\', \'wait\', \'warp_tri\',\n
+    \'watershed\', \'wdelete\', \'wf_draw\', \'where\', \'widget_base\',\n
+    \'widget_button\', \'widget_combobox\', \'widget_control\',\n
+    \'widget_displaycontextmenu\', \'widget_draw\',\n
+    \'widget_droplist\', \'widget_event\', \'widget_info\',\n
+    \'widget_label\', \'widget_list\',\n
+    \'widget_propertysheet\', \'widget_slider\', \'widget_tab\',\n
+    \'widget_table\', \'widget_text\',\n
+    \'widget_tree\', \'widget_tree_move\', \'widget_window\',\n
+    \'wiener_filter\', \'window\',\n
+    \'window\', \'write_bmp\', \'write_csv\', \'write_gif\', \'write_image\',\n
+    \'write_jpeg\', \'write_jpeg2000\', \'write_nrif\', \'write_pict\', \'write_png\',\n
+    \'write_ppm\', \'write_spr\', \'write_srf\', \'write_sylk\', \'write_tiff\',\n
+    \'write_video\', \'write_wav\', \'write_wave\', \'writeu\', \'wset\',\n
+    \'wshow\', \'wtn\', \'wv_applet\', \'wv_cwt\', \'wv_cw_wavelet\',\n
+    \'wv_denoise\', \'wv_dwt\', \'wv_fn_coiflet\',\n
+    \'wv_fn_daubechies\', \'wv_fn_gaussian\',\n
+    \'wv_fn_haar\', \'wv_fn_morlet\', \'wv_fn_paul\',\n
+    \'wv_fn_symlet\', \'wv_import_data\',\n
+    \'wv_import_wavelet\', \'wv_plot3d_wps\', \'wv_plot_multires\',\n
+    \'wv_pwt\', \'wv_tool_denoise\',\n
+    \'xbm_edit\', \'xdisplayfile\', \'xdxf\', \'xfont\', \'xinteranimate\',\n
+    \'xloadct\', \'xmanager\', \'xmng_tmpl\', \'xmtool\', \'xobjview\',\n
+    \'xobjview_rotate\', \'xobjview_write_image\',\n
+    \'xpalette\', \'xpcolor\', \'xplot3d\',\n
+    \'xregistered\', \'xroi\', \'xsq_test\', \'xsurface\', \'xvaredit\',\n
+    \'xvolume\', \'xvolume_rotate\', \'xvolume_write_image\',\n
+    \'xyouts\', \'zlib_compress\', \'zlib_uncompress\', \'zoom\', \'zoom_24\'\n
+  ];\n
+  var builtins = wordRegexp(builtinArray);\n
+\n
+  var keywordArray = [\n
+    \'begin\', \'end\', \'endcase\', \'endfor\',\n
+    \'endwhile\', \'endif\', \'endrep\', \'endforeach\',\n
+    \'break\', \'case\', \'continue\', \'for\',\n
+    \'foreach\', \'goto\', \'if\', \'then\', \'else\',\n
+    \'repeat\', \'until\', \'switch\', \'while\',\n
+    \'do\', \'pro\', \'function\'\n
+  ];\n
+  var keywords = wordRegexp(keywordArray);\n
+\n
+  CodeMirror.registerHelper("hintWords", "idl", builtinArray.concat(keywordArray));\n
+\n
+  var identifiers = new RegExp(\'^[_a-z\\xa1-\\uffff][_a-z0-9\\xa1-\\uffff]*\', \'i\');\n
+\n
+  var singleOperators = /[+\\-*&=<>\\/@#~$]/;\n
+  var boolOperators = new RegExp(\'(and|or|eq|lt|le|gt|ge|ne|not)\', \'i\');\n
+\n
+  function tokenBase(stream) {\n
+    // whitespaces\n
+    if (stream.eatSpace()) return null;\n
+\n
+    // Handle one line Comments\n
+    if (stream.match(\';\')) {\n
+      stream.skipToEnd();\n
+      return \'comment\';\n
+    }\n
+\n
+    // Handle Number Literals\n
+    if (stream.match(/^[0-9\\.+-]/, false)) {\n
+      if (stream.match(/^[+-]?0x[0-9a-fA-F]+/))\n
+        return \'number\';\n
+      if (stream.match(/^[+-]?\\d*\\.\\d+([EeDd][+-]?\\d+)?/))\n
+        return \'number\';\n
+      if (stream.match(/^[+-]?\\d+([EeDd][+-]?\\d+)?/))\n
+        return \'number\';\n
+    }\n
+\n
+    // Handle Strings\n
+    if (stream.match(/^"([^"]|(""))*"/)) { return \'string\'; }\n
+    if (stream.match(/^\'([^\']|(\'\'))*\'/)) { return \'string\'; }\n
+\n
+    // Handle words\n
+    if (stream.match(keywords)) { return \'keyword\'; }\n
+    if (stream.match(builtins)) { return \'builtin\'; }\n
+    if (stream.match(identifiers)) { return \'variable\'; }\n
+\n
+    if (stream.match(singleOperators) || stream.match(boolOperators)) {\n
+      return \'operator\'; }\n
+\n
+    // Handle non-detected items\n
+    stream.next();\n
+    return \'error\';\n
+  };\n
+\n
+  CodeMirror.defineMode(\'idl\', function() {\n
+    return {\n
+      token: function(stream) {\n
+        return tokenBase(stream);\n
+      }\n
+    };\n
+  });\n
+\n
+  CodeMirror.defineMIME(\'text/x-idl\', \'idl\');\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>14892</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jade/jade.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jade/jade.js.xml
index ce1e8f18c7f052d5d35e95e44d7dc67f8267dde8..84e6bdd0745568d8614bc0d77f11824bc5ee6bef 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jade/jade.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jade/jade.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403103.12</string> </value>
+            <value> <string>ts21897132.18</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,96 +22,596 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.defineMode("jade", function () {\n
-  var symbol_regex1 = /^(?:~|!|%|\\^|\\*|\\+|=|\\\\|:|;|,|\\/|\\?|&|<|>|\\|)/;\n
-  var open_paren_regex = /^(\\(|\\[)/;\n
-  var close_paren_regex = /^(\\)|\\])/;\n
-  var keyword_regex1 = /^(if|else|return|var|function|include|doctype|each)/;\n
-  var keyword_regex2 = /^(#|{|}|\\.)/;\n
-  var keyword_regex3 = /^(in)/;\n
-  var html_regex1 = /^(html|head|title|meta|link|script|body|br|div|input|span|a|img)/;\n
-  var html_regex2 = /^(h1|h2|h3|h4|h5|p|strong|em)/;\n
-  return {\n
-    startState: function () {\n
-      return {\n
-        inString: false,\n
-        stringType: "",\n
-        beforeTag: true,\n
-        justMatchedKeyword: false,\n
-        afterParen: false\n
-      };\n
-    },\n
-    token: function (stream, state) {\n
-      //check for state changes\n
-      if (!state.inString && ((stream.peek() == \'"\') || (stream.peek() == "\'"))) {\n
-        state.stringType = stream.peek();\n
-        stream.next(); // Skip quote\n
-        state.inString = true; // Update state\n
-      }\n
-\n
-      //return state\n
-      if (state.inString) {\n
-        if (stream.skipTo(state.stringType)) { // Quote found on this line\n
-          stream.next(); // Skip quote\n
-          state.inString = false; // Clear flag\n
-        } else {\n
-          stream.skipToEnd(); // Rest of line is string\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../javascript/javascript", "../css/css", "../htmlmixed/htmlmixed"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode(\'jade\', function (config) {\n
+  // token types\n
+  var KEYWORD = \'keyword\';\n
+  var DOCTYPE = \'meta\';\n
+  var ID = \'builtin\';\n
+  var CLASS = \'qualifier\';\n
+\n
+  var ATTRS_NEST = {\n
+    \'{\': \'}\',\n
+    \'(\': \')\',\n
+    \'[\': \']\'\n
+  };\n
+\n
+  var jsMode = CodeMirror.getMode(config, \'javascript\');\n
+\n
+  function State() {\n
+    this.javaScriptLine = false;\n
+    this.javaScriptLineExcludesColon = false;\n
+\n
+    this.javaScriptArguments = false;\n
+    this.javaScriptArgumentsDepth = 0;\n
+\n
+    this.isInterpolating = false;\n
+    this.interpolationNesting = 0;\n
+\n
+    this.jsState = jsMode.startState();\n
+\n
+    this.restOfLine = \'\';\n
+\n
+    this.isIncludeFiltered = false;\n
+    this.isEach = false;\n
+\n
+    this.lastTag = \'\';\n
+    this.scriptType = \'\';\n
+\n
+    // Attributes Mode\n
+    this.isAttrs = false;\n
+    this.attrsNest = [];\n
+    this.inAttributeName = true;\n
+    this.attributeIsType = false;\n
+    this.attrValue = \'\';\n
+\n
+    // Indented Mode\n
+    this.indentOf = Infinity;\n
+    this.indentToken = \'\';\n
+\n
+    this.innerMode = null;\n
+    this.innerState = null;\n
+\n
+    this.innerModeForLine = false;\n
+  }\n
+  /**\n
+   * Safely copy a state\n
+   *\n
+   * @return {State}\n
+   */\n
+  State.prototype.copy = function () {\n
+    var res = new State();\n
+    res.javaScriptLine = this.javaScriptLine;\n
+    res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon;\n
+    res.javaScriptArguments = this.javaScriptArguments;\n
+    res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;\n
+    res.isInterpolating = this.isInterpolating;\n
+    res.interpolationNesting = this.intpolationNesting;\n
+\n
+    res.jsState = CodeMirror.copyState(jsMode, this.jsState);\n
+\n
+    res.innerMode = this.innerMode;\n
+    if (this.innerMode && this.innerState) {\n
+      res.innerState = CodeMirror.copyState(this.innerMode, this.innerState);\n
+    }\n
+\n
+    res.restOfLine = this.restOfLine;\n
+\n
+    res.isIncludeFiltered = this.isIncludeFiltered;\n
+    res.isEach = this.isEach;\n
+    res.lastTag = this.lastTag;\n
+    res.scriptType = this.scriptType;\n
+    res.isAttrs = this.isAttrs;\n
+    res.attrsNest = this.attrsNest.slice();\n
+    res.inAttributeName = this.inAttributeName;\n
+    res.attributeIsType = this.attributeIsType;\n
+    res.attrValue = this.attrValue;\n
+    res.indentOf = this.indentOf;\n
+    res.indentToken = this.indentToken;\n
+\n
+    res.innerModeForLine = this.innerModeForLine;\n
+\n
+    return res;\n
+  };\n
+\n
+  function javaScript(stream, state) {\n
+    if (stream.sol()) {\n
+      // if javaScriptLine was set at end of line, ignore it\n
+      state.javaScriptLine = false;\n
+      state.javaScriptLineExcludesColon = false;\n
+    }\n
+    if (state.javaScriptLine) {\n
+      if (state.javaScriptLineExcludesColon && stream.peek() === \':\') {\n
+        state.javaScriptLine = false;\n
+        state.javaScriptLineExcludesColon = false;\n
+        return;\n
+      }\n
+      var tok = jsMode.token(stream, state.jsState);\n
+      if (stream.eol()) state.javaScriptLine = false;\n
+      return tok || true;\n
+    }\n
+  }\n
+  function javaScriptArguments(stream, state) {\n
+    if (state.javaScriptArguments) {\n
+      if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== \'(\') {\n
+        state.javaScriptArguments = false;\n
+        return;\n
+      }\n
+      if (stream.peek() === \'(\') {\n
+        state.javaScriptArgumentsDepth++;\n
+      } else if (stream.peek() === \')\') {\n
+        state.javaScriptArgumentsDepth--;\n
+      }\n
+      if (state.javaScriptArgumentsDepth === 0) {\n
+        state.javaScriptArguments = false;\n
+        return;\n
+      }\n
+\n
+      var tok = jsMode.token(stream, state.jsState);\n
+      return tok || true;\n
+    }\n
+  }\n
+\n
+  function yieldStatement(stream) {\n
+    if (stream.match(/^yield\\b/)) {\n
+        return \'keyword\';\n
+    }\n
+  }\n
+\n
+  function doctype(stream) {\n
+    if (stream.match(/^(?:doctype) *([^\\n]+)?/)) {\n
+        return DOCTYPE;\n
+    }\n
+  }\n
+\n
+  function interpolation(stream, state) {\n
+    if (stream.match(\'#{\')) {\n
+      state.isInterpolating = true;\n
+      state.interpolationNesting = 0;\n
+      return \'punctuation\';\n
+    }\n
+  }\n
+\n
+  function interpolationContinued(stream, state) {\n
+    if (state.isInterpolating) {\n
+      if (stream.peek() === \'}\') {\n
+        state.interpolationNesting--;\n
+        if (state.interpolationNesting < 0) {\n
+          stream.next();\n
+          state.isInterpolating = false;\n
+          return \'puncutation\';\n
         }\n
-        state.justMatchedKeyword = false;\n
-        return "string"; // Token style\n
-      } else if (stream.sol() && stream.eatSpace()) {\n
-        if (stream.match(keyword_regex1)) {\n
-          state.justMatchedKeyword = true;\n
-          stream.eatSpace();\n
-          return "keyword";\n
+      } else if (stream.peek() === \'{\') {\n
+        state.interpolationNesting++;\n
+      }\n
+      return jsMode.token(stream, state.jsState) || true;\n
+    }\n
+  }\n
+\n
+  function caseStatement(stream, state) {\n
+    if (stream.match(/^case\\b/)) {\n
+      state.javaScriptLine = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function when(stream, state) {\n
+    if (stream.match(/^when\\b/)) {\n
+      state.javaScriptLine = true;\n
+      state.javaScriptLineExcludesColon = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function defaultStatement(stream) {\n
+    if (stream.match(/^default\\b/)) {\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function extendsStatement(stream, state) {\n
+    if (stream.match(/^extends?\\b/)) {\n
+      state.restOfLine = \'string\';\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function append(stream, state) {\n
+    if (stream.match(/^append\\b/)) {\n
+      state.restOfLine = \'variable\';\n
+      return KEYWORD;\n
+    }\n
+  }\n
+  function prepend(stream, state) {\n
+    if (stream.match(/^prepend\\b/)) {\n
+      state.restOfLine = \'variable\';\n
+      return KEYWORD;\n
+    }\n
+  }\n
+  function block(stream, state) {\n
+    if (stream.match(/^block\\b *(?:(prepend|append)\\b)?/)) {\n
+      state.restOfLine = \'variable\';\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function include(stream, state) {\n
+    if (stream.match(/^include\\b/)) {\n
+      state.restOfLine = \'string\';\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function includeFiltered(stream, state) {\n
+    if (stream.match(/^include:([a-zA-Z0-9\\-]+)/, false) && stream.match(\'include\')) {\n
+      state.isIncludeFiltered = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function includeFilteredContinued(stream, state) {\n
+    if (state.isIncludeFiltered) {\n
+      var tok = filter(stream, state);\n
+      state.isIncludeFiltered = false;\n
+      state.restOfLine = \'string\';\n
+      return tok;\n
+    }\n
+  }\n
+\n
+  function mixin(stream, state) {\n
+    if (stream.match(/^mixin\\b/)) {\n
+      state.javaScriptLine = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function call(stream, state) {\n
+    if (stream.match(/^\\+([-\\w]+)/)) {\n
+      if (!stream.match(/^\\( *[-\\w]+ *=/, false)) {\n
+        state.javaScriptArguments = true;\n
+        state.javaScriptArgumentsDepth = 0;\n
+      }\n
+      return \'variable\';\n
+    }\n
+    if (stream.match(/^\\+#{/, false)) {\n
+      stream.next();\n
+      state.mixinCallAfter = true;\n
+      return interpolation(stream, state);\n
+    }\n
+  }\n
+  function callArguments(stream, state) {\n
+    if (state.mixinCallAfter) {\n
+      state.mixinCallAfter = false;\n
+      if (!stream.match(/^\\( *[-\\w]+ *=/, false)) {\n
+        state.javaScriptArguments = true;\n
+        state.javaScriptArgumentsDepth = 0;\n
+      }\n
+      return true;\n
+    }\n
+  }\n
+\n
+  function conditional(stream, state) {\n
+    if (stream.match(/^(if|unless|else if|else)\\b/)) {\n
+      state.javaScriptLine = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function each(stream, state) {\n
+    if (stream.match(/^(- *)?(each|for)\\b/)) {\n
+      state.isEach = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+  function eachContinued(stream, state) {\n
+    if (state.isEach) {\n
+      if (stream.match(/^ in\\b/)) {\n
+        state.javaScriptLine = true;\n
+        state.isEach = false;\n
+        return KEYWORD;\n
+      } else if (stream.sol() || stream.eol()) {\n
+        state.isEach = false;\n
+      } else if (stream.next()) {\n
+        while (!stream.match(/^ in\\b/, false) && stream.next());\n
+        return \'variable\';\n
+      }\n
+    }\n
+  }\n
+\n
+  function whileStatement(stream, state) {\n
+    if (stream.match(/^while\\b/)) {\n
+      state.javaScriptLine = true;\n
+      return KEYWORD;\n
+    }\n
+  }\n
+\n
+  function tag(stream, state) {\n
+    var captures;\n
+    if (captures = stream.match(/^(\\w(?:[-:\\w]*\\w)?)\\/?/)) {\n
+      state.lastTag = captures[1].toLowerCase();\n
+      if (state.lastTag === \'script\') {\n
+        state.scriptType = \'application/javascript\';\n
+      }\n
+      return \'tag\';\n
+    }\n
+  }\n
+\n
+  function filter(stream, state) {\n
+    if (stream.match(/^:([\\w\\-]+)/)) {\n
+      var innerMode;\n
+      if (config && config.innerModes) {\n
+        innerMode = config.innerModes(stream.current().substring(1));\n
+      }\n
+      if (!innerMode) {\n
+        innerMode = stream.current().substring(1);\n
+      }\n
+      if (typeof innerMode === \'string\') {\n
+        innerMode = CodeMirror.getMode(config, innerMode);\n
+      }\n
+      setInnerMode(stream, state, innerMode);\n
+      return \'atom\';\n
+    }\n
+  }\n
+\n
+  function code(stream, state) {\n
+    if (stream.match(/^(!?=|-)/)) {\n
+      state.javaScriptLine = true;\n
+      return \'punctuation\';\n
+    }\n
+  }\n
+\n
+  function id(stream) {\n
+    if (stream.match(/^#([\\w-]+)/)) {\n
+      return ID;\n
+    }\n
+  }\n
+\n
+  function className(stream) {\n
+    if (stream.match(/^\\.([\\w-]+)/)) {\n
+      return CLASS;\n
+    }\n
+  }\n
+\n
+  function attrs(stream, state) {\n
+    if (stream.peek() == \'(\') {\n
+      stream.next();\n
+      state.isAttrs = true;\n
+      state.attrsNest = [];\n
+      state.inAttributeName = true;\n
+      state.attrValue = \'\';\n
+      state.attributeIsType = false;\n
+      return \'punctuation\';\n
+    }\n
+  }\n
+\n
+  function attrsContinued(stream, state) {\n
+    if (state.isAttrs) {\n
+      if (ATTRS_NEST[stream.peek()]) {\n
+        state.attrsNest.push(ATTRS_NEST[stream.peek()]);\n
+      }\n
+      if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) {\n
+        state.attrsNest.pop();\n
+      } else  if (stream.eat(\')\')) {\n
+        state.isAttrs = false;\n
+        return \'punctuation\';\n
+      }\n
+      if (state.inAttributeName && stream.match(/^[^=,\\)!]+/)) {\n
+        if (stream.peek() === \'=\' || stream.peek() === \'!\') {\n
+          state.inAttributeName = false;\n
+          state.jsState = jsMode.startState();\n
+          if (state.lastTag === \'script\' && stream.current().trim().toLowerCase() === \'type\') {\n
+            state.attributeIsType = true;\n
+          } else {\n
+            state.attributeIsType = false;\n
+          }\n
         }\n
-        if (stream.match(html_regex1) || stream.match(html_regex2)) {\n
-          state.justMatchedKeyword = true;\n
-          return "variable";\n
+        return \'attribute\';\n
+      }\n
+\n
+      var tok = jsMode.token(stream, state.jsState);\n
+      if (state.attributeIsType && tok === \'string\') {\n
+        state.scriptType = stream.current().toString();\n
+      }\n
+      if (state.attrsNest.length === 0 && (tok === \'string\' || tok === \'variable\' || tok === \'keyword\')) {\n
+        try {\n
+          Function(\'\', \'var x \' + state.attrValue.replace(/,\\s*$/, \'\').replace(/^!/, \'\'));\n
+          state.inAttributeName = true;\n
+          state.attrValue = \'\';\n
+          stream.backUp(stream.current().length);\n
+          return attrsContinued(stream, state);\n
+        } catch (ex) {\n
+          //not the end of an attribute\n
         }\n
-      } else if (stream.sol() && stream.match(keyword_regex1)) {\n
-        state.justMatchedKeyword = true;\n
-        stream.eatSpace();\n
-        return "keyword";\n
-      } else if (stream.sol() && (stream.match(html_regex1) || stream.match(html_regex2))) {\n
-        state.justMatchedKeyword = true;\n
-        return "variable";\n
-      } else if (stream.eatSpace()) {\n
-        state.justMatchedKeyword = false;\n
-        if (stream.match(keyword_regex3) && stream.eatSpace()) {\n
-          state.justMatchedKeyword = true;\n
-          return "keyword";\n
+      }\n
+      state.attrValue += stream.current();\n
+      return tok || true;\n
+    }\n
+  }\n
+\n
+  function attributesBlock(stream, state) {\n
+    if (stream.match(/^&attributes\\b/)) {\n
+      state.javaScriptArguments = true;\n
+      state.javaScriptArgumentsDepth = 0;\n
+      return \'keyword\';\n
+    }\n
+  }\n
+\n
+  function indent(stream) {\n
+    if (stream.sol() && stream.eatSpace()) {\n
+      return \'indent\';\n
+    }\n
+  }\n
+\n
+  function comment(stream, state) {\n
+    if (stream.match(/^ *\\/\\/(-)?([^\\n]*)/)) {\n
+      state.indentOf = stream.indentation();\n
+      state.indentToken = \'comment\';\n
+      return \'comment\';\n
+    }\n
+  }\n
+\n
+  function colon(stream) {\n
+    if (stream.match(/^: */)) {\n
+      return \'colon\';\n
+    }\n
+  }\n
+\n
+  function text(stream, state) {\n
+    if (stream.match(/^(?:\\| ?| )([^\\n]+)/)) {\n
+      return \'string\';\n
+    }\n
+    if (stream.match(/^(<[^\\n]*)/, false)) {\n
+      // html string\n
+      setInnerMode(stream, state, \'htmlmixed\');\n
+      state.innerModeForLine = true;\n
+      return innerMode(stream, state, true);\n
+    }\n
+  }\n
+\n
+  function dot(stream, state) {\n
+    if (stream.eat(\'.\')) {\n
+      var innerMode = null;\n
+      if (state.lastTag === \'script\' && state.scriptType.toLowerCase().indexOf(\'javascript\') != -1) {\n
+        innerMode = state.scriptType.toLowerCase().replace(/"|\'/g, \'\');\n
+      } else if (state.lastTag === \'style\') {\n
+        innerMode = \'css\';\n
+      }\n
+      setInnerMode(stream, state, innerMode);\n
+      return \'dot\';\n
+    }\n
+  }\n
+\n
+  function fail(stream) {\n
+    stream.next();\n
+    return null;\n
+  }\n
+\n
+\n
+  function setInnerMode(stream, state, mode) {\n
+    mode = CodeMirror.mimeModes[mode] || mode;\n
+    mode = config.innerModes ? config.innerModes(mode) || mode : mode;\n
+    mode = CodeMirror.mimeModes[mode] || mode;\n
+    mode = CodeMirror.getMode(config, mode);\n
+    state.indentOf = stream.indentation();\n
+\n
+    if (mode && mode.name !== \'null\') {\n
+      state.innerMode = mode;\n
+    } else {\n
+      state.indentToken = \'string\';\n
+    }\n
+  }\n
+  function innerMode(stream, state, force) {\n
+    if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {\n
+      if (state.innerMode) {\n
+        if (!state.innerState) {\n
+          state.innerState = state.innerMode.startState ? state.innerMode.startState(stream.indentation()) : {};\n
         }\n
-      } else if (stream.match(symbol_regex1)) {\n
-        state.justMatchedKeyword = false;\n
-        return "atom";\n
-      } else if (stream.match(open_paren_regex)) {\n
-        state.afterParen = true;\n
-        state.justMatchedKeyword = true;\n
-        return "def";\n
-      } else if (stream.match(close_paren_regex)) {\n
-        state.afterParen = false;\n
-        state.justMatchedKeyword = true;\n
-        return "def";\n
-      } else if (stream.match(keyword_regex2)) {\n
-        state.justMatchedKeyword = true;\n
-        return "keyword";\n
-      } else if (stream.eatSpace()) {\n
-        state.justMatchedKeyword = false;\n
+        return stream.hideFirstChars(state.indentOf + 2, function () {\n
+          return state.innerMode.token(stream, state.innerState) || true;\n
+        });\n
       } else {\n
-        stream.next();\n
-        if (state.justMatchedKeyword) {\n
-          return "property";\n
-        } else if (state.afterParen) {\n
-          return "property";\n
-        }\n
+        stream.skipToEnd();\n
+        return state.indentToken;\n
       }\n
-      return null;\n
+    } else if (stream.sol()) {\n
+      state.indentOf = Infinity;\n
+      state.indentToken = null;\n
+      state.innerMode = null;\n
+      state.innerState = null;\n
+    }\n
+  }\n
+  function restOfLine(stream, state) {\n
+    if (stream.sol()) {\n
+      // if restOfLine was set at end of line, ignore it\n
+      state.restOfLine = \'\';\n
     }\n
+    if (state.restOfLine) {\n
+      stream.skipToEnd();\n
+      var tok = state.restOfLine;\n
+      state.restOfLine = \'\';\n
+      return tok;\n
+    }\n
+  }\n
+\n
+\n
+  function startState() {\n
+    return new State();\n
+  }\n
+  function copyState(state) {\n
+    return state.copy();\n
+  }\n
+  /**\n
+   * Get the next token in the stream\n
+   *\n
+   * @param {Stream} stream\n
+   * @param {State} state\n
+   */\n
+  function nextToken(stream, state) {\n
+    var tok = innerMode(stream, state)\n
+      || restOfLine(stream, state)\n
+      || interpolationContinued(stream, state)\n
+      || includeFilteredContinued(stream, state)\n
+      || eachContinued(stream, state)\n
+      || attrsContinued(stream, state)\n
+      || javaScript(stream, state)\n
+      || javaScriptArguments(stream, state)\n
+      || callArguments(stream, state)\n
+\n
+      || yieldStatement(stream, state)\n
+      || doctype(stream, state)\n
+      || interpolation(stream, state)\n
+      || caseStatement(stream, state)\n
+      || when(stream, state)\n
+      || defaultStatement(stream, state)\n
+      || extendsStatement(stream, state)\n
+      || append(stream, state)\n
+      || prepend(stream, state)\n
+      || block(stream, state)\n
+      || include(stream, state)\n
+      || includeFiltered(stream, state)\n
+      || mixin(stream, state)\n
+      || call(stream, state)\n
+      || conditional(stream, state)\n
+      || each(stream, state)\n
+      || whileStatement(stream, state)\n
+      || tag(stream, state)\n
+      || filter(stream, state)\n
+      || code(stream, state)\n
+      || id(stream, state)\n
+      || className(stream, state)\n
+      || attrs(stream, state)\n
+      || attributesBlock(stream, state)\n
+      || indent(stream, state)\n
+      || text(stream, state)\n
+      || comment(stream, state)\n
+      || colon(stream, state)\n
+      || dot(stream, state)\n
+      || fail(stream, state);\n
+\n
+    return tok === true ? null : tok;\n
+  }\n
+  return {\n
+    startState: startState,\n
+    copyState: copyState,\n
+    token: nextToken\n
   };\n
 });\n
 \n
 CodeMirror.defineMIME(\'text/x-jade\', \'jade\');\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -122,7 +622,7 @@ CodeMirror.defineMIME(\'text/x-jade\', \'jade\');\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3135</int> </value>
+            <value> <int>15936</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/javascript.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/javascript.js.xml
index 799cbd2276e3f1a9e0f4f5d7289ac1db94d13703..b26c93f8947b022a52606666dcac266de9e9b23c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/javascript.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/javascript.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403101.31</string> </value>
+            <value> <string>ts21897133.82</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,14 +22,28 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // TODO actually recognize syntax of TypeScript constructs\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
   var indentUnit = config.indentUnit;\n
   var statementIndent = parserConfig.statementIndent;\n
   var jsonldMode = parserConfig.jsonld;\n
   var jsonMode = parserConfig.json || jsonldMode;\n
   var isTS = parserConfig.typescript;\n
+  var wordRE = parserConfig.wordCharacters || /[\\w$\\xa1-\\uffff]/;\n
 \n
   // Tokenizer\n
 \n
@@ -143,8 +157,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     } else if (isOperatorChar.test(ch)) {\n
       stream.eatWhile(isOperatorChar);\n
       return ret("operator", "operator", stream.current());\n
-    } else {\n
-      stream.eatWhile(/[\\w\\$_]/);\n
+    } else if (wordRE.test(ch)) {\n
+      stream.eatWhile(wordRE);\n
       var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n
       return (known && state.lastType != ".") ? ret(known.type, known.style, word) :\n
                      ret("variable", "variable", word);\n
@@ -213,8 +227,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
         if (--depth == 0) break;\n
       } else if (bracket >= 3 && bracket < 6) {\n
         ++depth;\n
-      } else if (/[$\\w]/.test(ch)) {\n
+      } else if (wordRE.test(ch)) {\n
         sawSomething = true;\n
+      } else if (/["\'\\/]/.test(ch)) {\n
+        return;\n
       } else if (sawSomething && !depth) {\n
         ++pos;\n
         break;\n
@@ -249,7 +265,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     var cc = state.cc;\n
     // Communicate our context to the combinators.\n
     // (Less wasteful than consing up a hundred closures on every call.)\n
-    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n
+    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;\n
 \n
     if (!state.lexical.hasOwnProperty("align"))\n
       state.lexical.align = true;\n
@@ -309,6 +325,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     var result = function() {\n
       var state = cx.state, indent = state.indented;\n
       if (state.lexical.type == "stat") indent = state.lexical.indented;\n
+      else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)\n
+        indent = outer.indented;\n
       state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);\n
     };\n
     result.lex = true;\n
@@ -325,11 +343,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
   poplex.lex = true;\n
 \n
   function expect(wanted) {\n
-    return function(type) {\n
+    function exp(type) {\n
       if (type == wanted) return cont();\n
       else if (wanted == ";") return pass();\n
-      else return cont(arguments.callee);\n
+      else return cont(exp);\n
     };\n
+    return exp;\n
   }\n
 \n
   function statement(type, value) {\n
@@ -338,7 +357,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     if (type == "keyword b") return cont(pushlex("form"), statement, poplex);\n
     if (type == "{") return cont(pushlex("}"), block, poplex);\n
     if (type == ";") return cont();\n
-    if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);\n
+    if (type == "if") {\n
+      if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)\n
+        cx.state.cc.pop()();\n
+      return cont(pushlex("form"), expression, statement, poplex, maybeelse);\n
+    }\n
     if (type == "function") return cont(functiondef);\n
     if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);\n
     if (type == "variable") return cont(pushlex("stat"), maybelabel);\n
@@ -349,7 +372,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),\n
                                      statement, poplex, popcontext);\n
     if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);\n
-    if (type == "class") return cont(pushlex("form"), className, objlit, poplex);\n
+    if (type == "class") return cont(pushlex("form"), className, poplex);\n
     if (type == "export") return cont(pushlex("form"), afterExport, poplex);\n
     if (type == "import") return cont(pushlex("form"), afterImport, poplex);\n
     return pass(pushlex("stat"), expression, expect(";"), poplex);\n
@@ -369,12 +392,13 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
 \n
     var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;\n
     if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);\n
-    if (type == "function") return cont(functiondef);\n
+    if (type == "function") return cont(functiondef, maybeop);\n
     if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);\n
     if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);\n
     if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);\n
     if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);\n
     if (type == "{") return contCommasep(objprop, "}", null, maybeop);\n
+    if (type == "quasi") { return pass(quasi, maybeop); }\n
     return cont();\n
   }\n
   function maybeexpression(type) {\n
@@ -393,38 +417,37 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
   function maybeoperatorNoComma(type, value, noComma) {\n
     var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;\n
     var expr = noComma == false ? expression : expressionNoComma;\n
-    if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);\n
+    if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);\n
     if (type == "operator") {\n
       if (/\\+\\+|--/.test(value)) return cont(me);\n
       if (value == "?") return cont(expression, expect(":"), expr);\n
       return cont(expr);\n
     }\n
-    if (type == "quasi") { cx.cc.push(me); return quasi(value); }\n
+    if (type == "quasi") { return pass(quasi, me); }\n
     if (type == ";") return;\n
     if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);\n
     if (type == ".") return cont(property, me);\n
     if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);\n
   }\n
-  function quasi(value) {\n
-    if (value.slice(value.length - 2) != "${") return cont();\n
+  function quasi(type, value) {\n
+    if (type != "quasi") return pass();\n
+    if (value.slice(value.length - 2) != "${") return cont(quasi);\n
     return cont(expression, continueQuasi);\n
   }\n
   function continueQuasi(type) {\n
     if (type == "}") {\n
       cx.marked = "string-2";\n
       cx.state.tokenize = tokenQuasi;\n
-      return cont();\n
+      return cont(quasi);\n
     }\n
   }\n
   function arrowBody(type) {\n
     findFatArrow(cx.stream, cx.state);\n
-    if (type == "{") return pass(statement);\n
-    return pass(expression);\n
+    return pass(type == "{" ? statement : expression);\n
   }\n
   function arrowBodyNoComma(type) {\n
     findFatArrow(cx.stream, cx.state);\n
-    if (type == "{") return pass(statement);\n
-    return pass(expressionNoComma);\n
+    return pass(type == "{" ? statement : expressionNoComma);\n
   }\n
   function maybelabel(type) {\n
     if (type == ":") return cont(poplex, statement);\n
@@ -434,15 +457,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     if (type == "variable") {cx.marked = "property"; return cont();}\n
   }\n
   function objprop(type, value) {\n
-    if (type == "variable") {\n
+    if (type == "variable" || cx.style == "keyword") {\n
       cx.marked = "property";\n
       if (value == "get" || value == "set") return cont(getterSetter);\n
+      return cont(afterprop);\n
     } else if (type == "number" || type == "string") {\n
-      cx.marked = jsonldMode ? "property" : (type + " property");\n
+      cx.marked = jsonldMode ? "property" : (cx.style + " property");\n
+      return cont(afterprop);\n
+    } else if (type == "jsonld-keyword") {\n
+      return cont(afterprop);\n
     } else if (type == "[") {\n
       return cont(expression, expect("]"), afterprop);\n
     }\n
-    if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);\n
   }\n
   function getterSetter(type) {\n
     if (type != "variable") return pass(afterprop);\n
@@ -506,7 +532,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
     if (type == ",") return cont(vardef);\n
   }\n
   function maybeelse(type, value) {\n
-    if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);\n
+    if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);\n
   }\n
   function forspec(type) {\n
     if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);\n
@@ -541,11 +567,27 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
   function className(type, value) {\n
     if (type == "variable") {register(value); return cont(classNameAfter);}\n
   }\n
-  function classNameAfter(_type, value) {\n
-    if (value == "extends") return cont(expression);\n
+  function classNameAfter(type, value) {\n
+    if (value == "extends") return cont(expression, classNameAfter);\n
+    if (type == "{") return cont(pushlex("}"), classBody, poplex);\n
+  }\n
+  function classBody(type, value) {\n
+    if (type == "variable" || cx.style == "keyword") {\n
+      cx.marked = "property";\n
+      if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);\n
+      return cont(functiondef, classBody);\n
+    }\n
+    if (value == "*") {\n
+      cx.marked = "keyword";\n
+      return cont(classBody);\n
+    }\n
+    if (type == ";") return cont(classBody);\n
+    if (type == "}") return cont();\n
   }\n
-  function objlit(type) {\n
-    if (type == "{") return contCommasep(objprop, "}");\n
+  function classGetterSetter(type) {\n
+    if (type != "variable") return pass();\n
+    cx.marked = "property";\n
+    return cont();\n
   }\n
   function afterModule(type, value) {\n
     if (type == "string") return cont(statement);\n
@@ -574,7 +616,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
   }\n
   function maybeArrayComprehension(type) {\n
     if (type == "for") return pass(comprehension, expect("]"));\n
-    if (type == ",") return cont(commasep(expressionNoComma, "]"));\n
+    if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));\n
     return pass(commasep(expressionNoComma, "]"));\n
   }\n
   function comprehension(type) {\n
@@ -595,7 +637,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
         context: parserConfig.localVars && {vars: parserConfig.localVars},\n
         indented: 0\n
       };\n
-      if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;\n
+      if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")\n
+        state.globalVars = parserConfig.globalVars;\n
       return state;\n
     },\n
 \n
@@ -618,7 +661,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
       if (state.tokenize != tokenBase) return 0;\n
       var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n
       // Kludge to prevent \'maybelse\' from blocking lexical scope pops\n
-      for (var i = state.cc.length - 1; i >= 0; --i) {\n
+      if (!/^\\s*else\\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {\n
         var c = state.cc[i];\n
         if (c == poplex) lexical = lexical.prev;\n
         else if (c != maybeelse) break;\n
@@ -639,7 +682,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
       else return lexical.indented + (closing ? 0 : indentUnit);\n
     },\n
 \n
-    electricChars: ":{}",\n
+    electricInput: /^\\s*(?:case .*?:|default:|\\{|\\})$/,\n
     blockCommentStart: jsonMode ? null : "/*",\n
     blockCommentEnd: jsonMode ? null : "*/",\n
     lineComment: jsonMode ? null : "//",\n
@@ -651,15 +694,20 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {\n
   };\n
 });\n
 \n
+CodeMirror.registerHelper("wordChars", "javascript", /[\\w$]/);\n
+\n
 CodeMirror.defineMIME("text/javascript", "javascript");\n
 CodeMirror.defineMIME("text/ecmascript", "javascript");\n
 CodeMirror.defineMIME("application/javascript", "javascript");\n
+CodeMirror.defineMIME("application/x-javascript", "javascript");\n
 CodeMirror.defineMIME("application/ecmascript", "javascript");\n
 CodeMirror.defineMIME("application/json", {name: "javascript", json: true});\n
 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});\n
 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});\n
 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });\n
 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -670,7 +718,7 @@ CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>24265</int> </value>
+            <value> <int>26146</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/json-ld.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/json-ld.html.xml
index b508ad1f2a24324b5498dcd38f5f2dd173736c7e..5ee197f20b5fe4b52eac965effd2f011a9d77723 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/json-ld.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/json-ld.html.xml
@@ -50,12 +50,12 @@
 <script src="javascript.js"></script>\n
 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n
 <div id="nav">\n
-  <a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"/></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"/></a>\n
 \n
   <ul>\n
     <li><a href="../../index.html">Home</a>\n
     <li><a href="../../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="../index.html">Language modes</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/test.js.xml
index d1b63005ae8d6c8c5719ae74887d818ad58d62b3..9be93f46d9755b425cbf276969bbf1e4b0a153e7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403101.45</string> </value>
+            <value> <string>ts21897133.73</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   var mode = CodeMirror.getMode({indentUnit: 2}, "javascript");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
@@ -37,10 +40,18 @@
      "  [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);",\n
      "  [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",\n
      "})();");\n
+\n
+  MT("class_body",\n
+     "[keyword class] [variable Foo] {",\n
+     "  [property constructor]() {}",\n
+     "  [property sayName]() {",\n
+     "    [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",\n
+     "  }",\n
+     "}");\n
 \n
   MT("class",\n
      "[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",\n
-     "  [[ [string-2 /expr/] ]]: [number 24],",\n
+     "  [property get] [property prop]() { [keyword return] [number 24]; }",\n
      "  [property constructor]([def x], [def y]) {",\n
      "    [keyword super]([string \'something\']);",\n
      "    [keyword this].[property x] [operator =] [variable-2 x];",\n
@@ -73,6 +84,12 @@
      "  [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",\n
      "    [keyword yield] [variable-2 i];",\n
      "}");\n
+\n
+  MT("quotedStringAddition",\n
+     "[keyword let] [variable f] [operator =] [variable a] [operator +] [string \'fatarrow\'] [operator +] [variable c];");\n
+\n
+  MT("quotedFatArrow",\n
+     "[keyword let] [variable f] [operator =] [variable a] [operator +] [string \'=>\'] [operator +] [variable c];");\n
 \n
   MT("fatArrow",\n
      "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",\n
@@ -93,6 +110,9 @@
 \n
   MT("quasi",\n
      "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");\n
+\n
+  MT("quasi_no_function",\n
+     "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");\n
 \n
   MT("indent_statement",\n
      "[keyword var] [variable x] [operator =] [number 10]",\n
@@ -127,6 +147,28 @@
      "{",\n
      "  [keyword debugger];",\n
      "}");\n
+\n
+  MT("indent_else",\n
+     "[keyword for] (;;)",\n
+     "  [keyword if] ([variable foo])",\n
+     "    [keyword if] ([variable bar])",\n
+     "      [number 1];",\n
+     "    [keyword else]",\n
+     "      [number 2];",\n
+     "  [keyword else]",\n
+     "    [number 3];");\n
+\n
+  MT("indent_funarg",\n
+     "[variable foo]([number 10000],",\n
+     "    [keyword function]([def a]) {",\n
+     "  [keyword debugger];",\n
+     "};");\n
+\n
+  MT("indent_below_if",\n
+     "[keyword for] (;;)",\n
+     "  [keyword if] ([variable foo])",\n
+     "    [number 1];",\n
+     "[number 2];");\n
 \n
   MT("multilinestring",\n
      "[keyword var] [variable x] [operator =] [string \'foo\\\\]",\n
@@ -134,6 +176,13 @@
 \n
   MT("scary_regexp",\n
      "[string-2 /foo[[/]]bar/];");\n
+\n
+  MT("indent_strange_array",\n
+     "[keyword var] [variable x] [operator =] [[",\n
+     "  [number 1],,",\n
+     "  [number 2],",\n
+     "]];",\n
+     "[number 10];");\n
 \n
   var jsonld_mode = CodeMirror.getMode(\n
     {indentUnit: 2},\n
@@ -183,7 +232,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5874</int> </value>
+            <value> <int>7449</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/typescript.html.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/typescript.html.xml
index 5de9e64cde2c7f1bcb9cb97beaf37fcf99edb840..1308f9fab0a72ff55cf043cda792ba9ea10fb563 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/typescript.html.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/javascript/typescript.html.xml
@@ -47,12 +47,12 @@
 <script src="javascript.js"></script>\n
 <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n
 <div id=nav>\n
-  <a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a>\n
+  <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>\n
 \n
   <ul>\n
     <li><a href="../../index.html">Home</a>\n
     <li><a href="../../doc/manual.html">Manual</a>\n
-    <li><a href="https://github.com/marijnh/codemirror">Code</a>\n
+    <li><a href="https://github.com/codemirror/codemirror">Code</a>\n
   </ul>\n
   <ul>\n
     <li><a href="../index.html">Language modes</a>\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jinja2/jinja2.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jinja2/jinja2.js.xml
index 0b702d5b8c07d302afa9acb7e20845dc371d495f..a2beb01ead0b3da6194f104e7b67b95ea0fd3294 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jinja2/jinja2.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/jinja2/jinja2.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403090.19</string> </value>
+            <value> <string>ts21897145.11</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,57 +22,147 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.defineMode("jinja2", function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("jinja2", function() {\n
     var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif",\n
-                    "extends", "filter", "endfilter", "firstof", "for",\n
-                    "endfor", "if", "endif", "ifchanged", "endifchanged",\n
-                    "ifequal", "endifequal", "ifnotequal",\n
-                    "endifnotequal", "in", "include", "load", "not", "now", "or",\n
-                    "parsed", "regroup", "reversed", "spaceless",\n
-                    "endspaceless", "ssi", "templatetag", "openblock",\n
-                    "closeblock", "openvariable", "closevariable",\n
-                    "openbrace", "closebrace", "opencomment",\n
-                    "closecomment", "widthratio", "url", "with", "endwith",\n
-                    "get_current_language", "trans", "noop", "blocktrans",\n
-                    "endblocktrans", "get_available_languages",\n
-                    "get_current_language_bidi", "plural"];\n
-    keywords = new RegExp("^((" + keywords.join(")|(") + "))\\\\b");\n
+      "extends", "filter", "endfilter", "firstof", "for",\n
+      "endfor", "if", "endif", "ifchanged", "endifchanged",\n
+      "ifequal", "endifequal", "ifnotequal",\n
+      "endifnotequal", "in", "include", "load", "not", "now", "or",\n
+      "parsed", "regroup", "reversed", "spaceless",\n
+      "endspaceless", "ssi", "templatetag", "openblock",\n
+      "closeblock", "openvariable", "closevariable",\n
+      "openbrace", "closebrace", "opencomment",\n
+      "closecomment", "widthratio", "url", "with", "endwith",\n
+      "get_current_language", "trans", "endtrans", "noop", "blocktrans",\n
+      "endblocktrans", "get_available_languages",\n
+      "get_current_language_bidi", "plural"],\n
+    operator = /^[+\\-*&%=<>!?|~^]/,\n
+    sign = /^[:\\[\\(\\{]/,\n
+    atom = ["true", "false"],\n
+    number = /^(\\d[+\\-\\*\\/])?\\d+(\\.\\d+)?/;\n
+\n
+    keywords = new RegExp("((" + keywords.join(")|(") + "))\\\\b");\n
+    atom = new RegExp("((" + atom.join(")|(") + "))\\\\b");\n
 \n
     function tokenBase (stream, state) {\n
-        var ch = stream.next();\n
-        if (ch == "{") {\n
-            if (ch = stream.eat(/\\{|%|#/)) {\n
-                stream.eat("-");\n
-                state.tokenize = inTag(ch);\n
-                return "tag";\n
-            }\n
+      var ch = stream.peek();\n
+\n
+      //Comment\n
+      if (state.incomment) {\n
+        if(!stream.skipTo("#}")) {\n
+          stream.skipToEnd();\n
+        } else {\n
+          stream.eatWhile(/\\#|}/);\n
+          state.incomment = false;\n
+        }\n
+        return "comment";\n
+      //Tag\n
+      } else if (state.intag) {\n
+        //After operator\n
+        if(state.operator) {\n
+          state.operator = false;\n
+          if(stream.match(atom)) {\n
+            return "atom";\n
+          }\n
+          if(stream.match(number)) {\n
+            return "number";\n
+          }\n
         }\n
-    }\n
-    function inTag (close) {\n
-        if (close == "{") {\n
-            close = "}";\n
+        //After sign\n
+        if(state.sign) {\n
+          state.sign = false;\n
+          if(stream.match(atom)) {\n
+            return "atom";\n
+          }\n
+          if(stream.match(number)) {\n
+            return "number";\n
+          }\n
         }\n
-        return function (stream, state) {\n
-            var ch = stream.next();\n
-            if ((ch == close || (ch == "-" && stream.eat(close)))\n
-                && stream.eat("}")) {\n
-                state.tokenize = tokenBase;\n
-                return "tag";\n
+\n
+        if(state.instring) {\n
+          if(ch == state.instring) {\n
+            state.instring = false;\n
+          }\n
+          stream.next();\n
+          return "string";\n
+        } else if(ch == "\'" || ch == \'"\') {\n
+          state.instring = ch;\n
+          stream.next();\n
+          return "string";\n
+        } else if(stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) {\n
+          state.intag = false;\n
+          return "tag";\n
+        } else if(stream.match(operator)) {\n
+          state.operator = true;\n
+          return "operator";\n
+        } else if(stream.match(sign)) {\n
+          state.sign = true;\n
+        } else {\n
+          if(stream.eat(" ") || stream.sol()) {\n
+            if(stream.match(keywords)) {\n
+              return "keyword";\n
             }\n
-            if (stream.match(keywords)) {\n
-                return "keyword";\n
+            if(stream.match(atom)) {\n
+              return "atom";\n
             }\n
-            return close == "#" ? "comment" : "string";\n
-        };\n
-    }\n
-    return {\n
-        startState: function () {\n
-            return {tokenize: tokenBase};\n
-        },\n
-        token: function (stream, state) {\n
-            return state.tokenize(stream, state);\n
+            if(stream.match(number)) {\n
+              return "number";\n
+            }\n
+            if(stream.sol()) {\n
+              stream.next();\n
+            }\n
+          } else {\n
+            stream.next();\n
+          }\n
+\n
+        }\n
+        return "variable";\n
+      } else if (stream.eat("{")) {\n
+        if (ch = stream.eat("#")) {\n
+          state.incomment = true;\n
+          if(!stream.skipTo("#}")) {\n
+            stream.skipToEnd();\n
+          } else {\n
+            stream.eatWhile(/\\#|}/);\n
+            state.incomment = false;\n
+          }\n
+          return "comment";\n
+        //Open tag\n
+        } else if (ch = stream.eat(/\\{|%/)) {\n
+          //Cache close tag\n
+          state.intag = ch;\n
+          if(ch == "{") {\n
+            state.intag = "}";\n
+          }\n
+          stream.eat("-");\n
+          return "tag";\n
         }\n
+      }\n
+      stream.next();\n
+    };\n
+\n
+    return {\n
+      startState: function () {\n
+        return {tokenize: tokenBase};\n
+      },\n
+      token: function (stream, state) {\n
+        return state.tokenize(stream, state);\n
+      }\n
     };\n
+  });\n
 });\n
 
 
@@ -84,7 +174,7 @@ CodeMirror.defineMode("jinja2", function() {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2053</int> </value>
+            <value> <int>4284</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/julia/julia.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/julia/julia.js.xml
index de1aee60736bed2e37a6d2825de78908454a8e58..16fca7d28d1f0684bf124101b99faab8d985f2da 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/julia/julia.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/julia/julia.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403098.41</string> </value>
+            <value> <string>ts21897136.09</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("julia", function(_conf, parserConf) {\n
   var ERRORCLASS = \'error\';\n
 \n
@@ -31,7 +44,7 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {\n
 \n
   var operators = parserConf.operators || /^\\.?[|&^\\\\%*+\\-<>!=\\/]=?|\\?|~|:|\\$|\\.[<>]|<<=?|>>>?=?|\\.[<>=]=|->?|\\/\\/|\\bin\\b/;\n
   var delimiters = parserConf.delimiters || /^[;,()[\\]{}]/;\n
-  var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*!*/;\n
+  var identifiers = parserConf.identifiers|| /^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*!*/;\n
   var blockOpeners = ["begin", "function", "type", "immutable", "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", "finally", "catch", "do"];\n
   var blockClosers = ["end", "else", "elseif", "catch", "finally"];\n
   var keywordList = [\'if\', \'else\', \'elseif\', \'while\', \'for\', \'begin\', \'let\', \'end\', \'do\', \'try\', \'catch\', \'finally\', \'return\', \'break\', \'continue\', \'global\', \'local\', \'const\', \'export\', \'import\', \'importall\', \'using\', \'function\', \'macro\', \'module\', \'baremodule\', \'type\', \'immutable\', \'quote\', \'typealias\', \'abstract\', \'bitstype\', \'ccall\'];\n
@@ -308,6 +321,8 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {\n
 \n
 \n
 CodeMirror.defineMIME("text/x-julia", "julia");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -318,7 +333,7 @@ CodeMirror.defineMIME("text/x-julia", "julia");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7728</int> </value>
+            <value> <int>8215</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/kotlin.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/kotlin.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f638a40e41ef94e7e950d44f1e10c6a874cf9c41
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/kotlin.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>kotlin</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/kotlin/kotlin.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/kotlin/kotlin.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..19f43d2d79ee6fa07a0f9ff398e818fdf24dec46
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/kotlin/kotlin.js.xml
@@ -0,0 +1,324 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897145.7</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>kotlin.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode("kotlin", function (config, parserConfig) {\n
+  function words(str) {\n
+    var obj = {}, words = str.split(" ");\n
+    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
+    return obj;\n
+  }\n
+\n
+  var multiLineStrings = parserConfig.multiLineStrings;\n
+\n
+  var keywords = words(\n
+          "package continue return object while break class data trait throw super" +\n
+          " when type this else This try val var fun for is in if do as true false null get set");\n
+  var softKeywords = words("import" +\n
+      " where by get set abstract enum open annotation override private public internal" +\n
+      " protected catch out vararg inline finally final ref");\n
+  var blockKeywords = words("catch class do else finally for if where try while enum");\n
+  var atoms = words("null true false this");\n
+\n
+  var curPunc;\n
+\n
+  function tokenBase(stream, state) {\n
+    var ch = stream.next();\n
+    if (ch == \'"\' || ch == "\'") {\n
+      return startString(ch, stream, state);\n
+    }\n
+    // Wildcard import w/o trailing semicolon (import smth.*)\n
+    if (ch == "." && stream.eat("*")) {\n
+      return "word";\n
+    }\n
+    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n
+      curPunc = ch;\n
+      return null;\n
+    }\n
+    if (/\\d/.test(ch)) {\n
+      if (stream.eat(/eE/)) {\n
+        stream.eat(/\\+\\-/);\n
+        stream.eatWhile(/\\d/);\n
+      }\n
+      return "number";\n
+    }\n
+    if (ch == "/") {\n
+      if (stream.eat("*")) {\n
+        state.tokenize.push(tokenComment);\n
+        return tokenComment(stream, state);\n
+      }\n
+      if (stream.eat("/")) {\n
+        stream.skipToEnd();\n
+        return "comment";\n
+      }\n
+      if (expectExpression(state.lastToken)) {\n
+        return startString(ch, stream, state);\n
+      }\n
+    }\n
+    // Commented\n
+    if (ch == "-" && stream.eat(">")) {\n
+      curPunc = "->";\n
+      return null;\n
+    }\n
+    if (/[\\-+*&%=<>!?|\\/~]/.test(ch)) {\n
+      stream.eatWhile(/[\\-+*&%=<>|~]/);\n
+      return "operator";\n
+    }\n
+    stream.eatWhile(/[\\w\\$_]/);\n
+\n
+    var cur = stream.current();\n
+    if (atoms.propertyIsEnumerable(cur)) {\n
+      return "atom";\n
+    }\n
+    if (softKeywords.propertyIsEnumerable(cur)) {\n
+      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";\n
+      return "softKeyword";\n
+    }\n
+\n
+    if (keywords.propertyIsEnumerable(cur)) {\n
+      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";\n
+      return "keyword";\n
+    }\n
+    return "word";\n
+  }\n
+\n
+  tokenBase.isBase = true;\n
+\n
+  function startString(quote, stream, state) {\n
+    var tripleQuoted = false;\n
+    if (quote != "/" && stream.eat(quote)) {\n
+      if (stream.eat(quote)) tripleQuoted = true;\n
+      else return "string";\n
+    }\n
+    function t(stream, state) {\n
+      var escaped = false, next, end = !tripleQuoted;\n
+\n
+      while ((next = stream.next()) != null) {\n
+        if (next == quote && !escaped) {\n
+          if (!tripleQuoted) {\n
+            break;\n
+          }\n
+          if (stream.match(quote + quote)) {\n
+            end = true;\n
+            break;\n
+          }\n
+        }\n
+\n
+        if (quote == \'"\' && next == "$" && !escaped && stream.eat("{")) {\n
+          state.tokenize.push(tokenBaseUntilBrace());\n
+          return "string";\n
+        }\n
+\n
+        if (next == "$" && !escaped && !stream.eat(" ")) {\n
+          state.tokenize.push(tokenBaseUntilSpace());\n
+          return "string";\n
+        }\n
+        escaped = !escaped && next == "\\\\";\n
+      }\n
+      if (multiLineStrings)\n
+        state.tokenize.push(t);\n
+      if (end) state.tokenize.pop();\n
+      return "string";\n
+    }\n
+\n
+    state.tokenize.push(t);\n
+    return t(stream, state);\n
+  }\n
+\n
+  function tokenBaseUntilBrace() {\n
+    var depth = 1;\n
+\n
+    function t(stream, state) {\n
+      if (stream.peek() == "}") {\n
+        depth--;\n
+        if (depth == 0) {\n
+          state.tokenize.pop();\n
+          return state.tokenize[state.tokenize.length - 1](stream, state);\n
+        }\n
+      } else if (stream.peek() == "{") {\n
+        depth++;\n
+      }\n
+      return tokenBase(stream, state);\n
+    }\n
+\n
+    t.isBase = true;\n
+    return t;\n
+  }\n
+\n
+  function tokenBaseUntilSpace() {\n
+    function t(stream, state) {\n
+      if (stream.eat(/[\\w]/)) {\n
+        var isWord = stream.eatWhile(/[\\w]/);\n
+        if (isWord) {\n
+          state.tokenize.pop();\n
+          return "word";\n
+        }\n
+      }\n
+      state.tokenize.pop();\n
+      return "string";\n
+    }\n
+\n
+    t.isBase = true;\n
+    return t;\n
+  }\n
+\n
+  function tokenComment(stream, state) {\n
+    var maybeEnd = false, ch;\n
+    while (ch = stream.next()) {\n
+      if (ch == "/" && maybeEnd) {\n
+        state.tokenize.pop();\n
+        break;\n
+      }\n
+      maybeEnd = (ch == "*");\n
+    }\n
+    return "comment";\n
+  }\n
+\n
+  function expectExpression(last) {\n
+    return !last || last == "operator" || last == "->" || /[\\.\\[\\{\\(,;:]/.test(last) ||\n
+        last == "newstatement" || last == "keyword" || last == "proplabel";\n
+  }\n
+\n
+  function Context(indented, column, type, align, prev) {\n
+    this.indented = indented;\n
+    this.column = column;\n
+    this.type = type;\n
+    this.align = align;\n
+    this.prev = prev;\n
+  }\n
+\n
+  function pushContext(state, col, type) {\n
+    return state.context = new Context(state.indented, col, type, null, state.context);\n
+  }\n
+\n
+  function popContext(state) {\n
+    var t = state.context.type;\n
+    if (t == ")" || t == "]" || t == "}")\n
+      state.indented = state.context.indented;\n
+    return state.context = state.context.prev;\n
+  }\n
+\n
+  // Interface\n
+\n
+  return {\n
+    startState: function (basecolumn) {\n
+      return {\n
+        tokenize: [tokenBase],\n
+        context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),\n
+        indented: 0,\n
+        startOfLine: true,\n
+        lastToken: null\n
+      };\n
+    },\n
+\n
+    token: function (stream, state) {\n
+      var ctx = state.context;\n
+      if (stream.sol()) {\n
+        if (ctx.align == null) ctx.align = false;\n
+        state.indented = stream.indentation();\n
+        state.startOfLine = true;\n
+        // Automatic semicolon insertion\n
+        if (ctx.type == "statement" && !expectExpression(state.lastToken)) {\n
+          popContext(state);\n
+          ctx = state.context;\n
+        }\n
+      }\n
+      if (stream.eatSpace()) return null;\n
+      curPunc = null;\n
+      var style = state.tokenize[state.tokenize.length - 1](stream, state);\n
+      if (style == "comment") return style;\n
+      if (ctx.align == null) ctx.align = true;\n
+      if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);\n
+      // Handle indentation for {x -> \\n ... }\n
+      else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {\n
+        popContext(state);\n
+        state.context.align = false;\n
+      }\n
+      else if (curPunc == "{") pushContext(state, stream.column(), "}");\n
+      else if (curPunc == "[") pushContext(state, stream.column(), "]");\n
+      else if (curPunc == "(") pushContext(state, stream.column(), ")");\n
+      else if (curPunc == "}") {\n
+        while (ctx.type == "statement") ctx = popContext(state);\n
+        if (ctx.type == "}") ctx = popContext(state);\n
+        while (ctx.type == "statement") ctx = popContext(state);\n
+      }\n
+      else if (curPunc == ctx.type) popContext(state);\n
+      else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))\n
+        pushContext(state, stream.column(), "statement");\n
+      state.startOfLine = false;\n
+      state.lastToken = curPunc || style;\n
+      return style;\n
+    },\n
+\n
+    indent: function (state, textAfter) {\n
+      if (!state.tokenize[state.tokenize.length - 1].isBase) return 0;\n
+      var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;\n
+      if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;\n
+      var closing = firstChar == ctx.type;\n
+      if (ctx.type == "statement") {\n
+        return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);\n
+      }\n
+      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n
+      else return ctx.indented + (closing ? 0 : config.indentUnit);\n
+    },\n
+\n
+    electricChars: "{}"\n
+  };\n
+});\n
+\n
+CodeMirror.defineMIME("text/x-kotlin", "kotlin");\n
+\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>8410</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/less/less.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/less/less.js.xml
deleted file mode 100644
index 52fc140d1df69f8723222b326e2ffacf1cfc9346..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/less/less.js.xml
+++ /dev/null
@@ -1,391 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403099.96</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>less.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-/*\n
-  LESS mode - http://www.lesscss.org/\n
-  Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>\n
-  Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues\n
-  GitHub: @peterkroon\n
-*/\n
-\n
-CodeMirror.defineMode("less", function(config) {\n
-  var indentUnit = config.indentUnit, type;\n
-  function ret(style, tp) {type = tp; return style;}\n
-\n
-  var selectors = /(^\\:root$|^\\:nth\\-child$|^\\:nth\\-last\\-child$|^\\:nth\\-of\\-type$|^\\:nth\\-last\\-of\\-type$|^\\:first\\-child$|^\\:last\\-child$|^\\:first\\-of\\-type$|^\\:last\\-of\\-type$|^\\:only\\-child$|^\\:only\\-of\\-type$|^\\:empty$|^\\:link|^\\:visited$|^\\:active$|^\\:hover$|^\\:focus$|^\\:target$|^\\:lang$|^\\:enabled^\\:disabled$|^\\:checked$|^\\:first\\-line$|^\\:first\\-letter$|^\\:before$|^\\:after$|^\\:not$|^\\:required$|^\\:invalid$)/;\n
-\n
-  function tokenBase(stream, state) {\n
-    var ch = stream.next();\n
-\n
-    if (ch == "@") {stream.eatWhile(/[\\w\\-]/); return ret("meta", stream.current());}\n
-    else if (ch == "/" && stream.eat("*")) {\n
-      state.tokenize = tokenCComment;\n
-      return tokenCComment(stream, state);\n
-    } else if (ch == "<" && stream.eat("!")) {\n
-      state.tokenize = tokenSGMLComment;\n
-      return tokenSGMLComment(stream, state);\n
-    } else if (ch == "=") ret(null, "compare");\n
-    else if (ch == "|" && stream.eat("=")) return ret(null, "compare");\n
-    else if (ch == "\\"" || ch == "\'") {\n
-      state.tokenize = tokenString(ch);\n
-      return state.tokenize(stream, state);\n
-    } else if (ch == "/") { // e.g.: .png will not be parsed as a class\n
-      if(stream.eat("/")){\n
-        state.tokenize = tokenSComment;\n
-        return tokenSComment(stream, state);\n
-      } else {\n
-        if(type == "string" || type == "(") return ret("string", "string");\n
-        if(state.stack[state.stack.length-1] !== undefined) return ret(null, ch);\n
-        stream.eatWhile(/[\\a-zA-Z0-9\\-_.\\s]/);\n
-        if( /\\/|\\)|#/.test(stream.peek() || (stream.eatSpace() && stream.peek() === ")"))  || stream.eol() )return ret("string", "string"); // let url(/images/logo.png) without quotes return as string\n
-      }\n
-    } else if (ch == "!") {\n
-      stream.match(/^\\s*\\w*/);\n
-      return ret("keyword", "important");\n
-    } else if (/\\d/.test(ch)) {\n
-      stream.eatWhile(/[\\w.%]/);\n
-      return ret("number", "unit");\n
-    } else if (/[,+<>*\\/]/.test(ch)) {\n
-      if(stream.peek() == "=" || type == "a")return ret("string", "string");\n
-      if(ch === ",")return ret(null, ch);\n
-      return ret(null, "select-op");\n
-    } else if (/[;{}:\\[\\]()~\\|]/.test(ch)) {\n
-      if(ch == ":"){\n
-        stream.eatWhile(/[a-z\\\\\\-]/);\n
-        if( selectors.test(stream.current()) ){\n
-          return ret("tag", "tag");\n
-        } else if(stream.peek() == ":"){//::-webkit-search-decoration\n
-          stream.next();\n
-          stream.eatWhile(/[a-z\\\\\\-]/);\n
-          if(stream.current().match(/\\:\\:\\-(o|ms|moz|webkit)\\-/))return ret("string", "string");\n
-          if( selectors.test(stream.current().substring(1)) )return ret("tag", "tag");\n
-          return ret(null, ch);\n
-        } else {\n
-          return ret(null, ch);\n
-        }\n
-      } else if(ch == "~"){\n
-        if(type == "r")return ret("string", "string");\n
-      } else {\n
-        return ret(null, ch);\n
-      }\n
-    } else if (ch == ".") {\n
-      if(type == "(")return ret("string", "string"); // allow url(../image.png)\n
-      stream.eatWhile(/[\\a-zA-Z0-9\\-_]/);\n
-      if(stream.peek() === " ")stream.eatSpace();\n
-      if(stream.peek() === ")" || type === ":")return ret("number", "unit");//rgba(0,0,0,.25);\n
-      else if(stream.current().length >1){\n
-        if(state.stack[state.stack.length-1] === "rule" && !stream.match(/^[{,+(]/, false)) return ret("number", "unit");\n
-      }\n
-      return ret("tag", "tag");\n
-    } else if (ch == "#") {\n
-      //we don\'t eat white-space, we want the hex color and or id only\n
-      stream.eatWhile(/[A-Za-z0-9]/);\n
-      //check if there is a proper hex color length e.g. #eee || #eeeEEE\n
-      if(stream.current().length == 4 || stream.current().length == 7){\n
-        if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream\n
-          //when not a valid hex value, parse as id\n
-          if(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret("atom", "tag");\n
-          //eat white-space\n
-          stream.eatSpace();\n
-          //when hex value declaration doesn\'t end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don\'t end with[;,]\n
-          if( /[\\/<>.(){!$%^&*_\\-\\\\?=+\\|#\'~`]/.test(stream.peek()) ){\n
-            if(type === "select-op")return ret("number", "unit"); else return ret("atom", "tag");\n
-          }\n
-          //#time { color: #aaa }\n
-          else if(stream.peek() == "}" )return ret("number", "unit");\n
-          //we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa\n
-          else if( /[a-zA-Z\\\\]/.test(stream.peek()) )return ret("atom", "tag");\n
-          //when a hex value is on the end of a line, parse as id\n
-          else if(stream.eol())return ret("atom", "tag");\n
-          //default\n
-          else return ret("number", "unit");\n
-        } else {//when not a valid hexvalue in the current stream e.g. #footer\n
-          stream.eatWhile(/[\\w\\\\\\-]/);\n
-          return ret("atom", stream.current());\n
-        }\n
-      } else {//when not a valid hexvalue length\n
-        stream.eatWhile(/[\\w\\\\\\-]/);\n
-        if(state.stack[state.stack.length-1] === "rule")return ret("atom", stream.current());return ret("atom", stream.current());\n
-        return ret("atom", "tag");\n
-      }\n
-    } else if (ch == "&") {\n
-      stream.eatWhile(/[\\w\\-]/);\n
-      return ret(null, ch);\n
-    } else {\n
-      stream.eatWhile(/[\\w\\\\\\-_%.{]/);\n
-      if(stream.current().match(/\\\\/) !== null){\n
-        if(stream.current().charAt(stream.current().length-1) === "\\\\"){\n
-          stream.eat(/\\\'|\\"|\\)|\\(/);\n
-          while(stream.eatWhile(/[\\w\\\\\\-_%.{]/)){\n
-            stream.eat(/\\\'|\\"|\\)|\\(/);\n
-          }\n
-          return ret("string", stream.current());\n
-        }\n
-      } //else if(type === "tag")return ret("tag", "tag");\n
-        else if(type == "string"){\n
-        if(state.stack[state.stack.length-1] === "{" && stream.peek() === ":")return ret("variable", "variable");\n
-        if(stream.peek() === "/")stream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n
-        return ret(type, stream.current());\n
-      } else if(stream.current().match(/(^http$|^https$)/) != null){\n
-        stream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n
-        if(stream.peek() === "/")stream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n
-        return ret("string", "string");\n
-      } else if(stream.peek() == "<" || stream.peek() == ">" || stream.peek() == "+"){\n
-        if(type === "(" && (stream.current() === "n" || stream.current() === "-n"))return ret("string", stream.current());\n
-        return ret("tag", "tag");\n
-      } else if( /\\(/.test(stream.peek()) ){\n
-        if(stream.current() === "when")return ret("variable","variable");\n
-        else if(state.stack[state.stack.length-1] === "@media" && stream.current() === "and")return ret("variable",stream.current());\n
-        return ret(null, ch);\n
-      } else if (stream.peek() == "/" && state.stack[state.stack.length-1] !== undefined){ // url(dir/center/image.png)\n
-        if(stream.peek() === "/")stream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n
-        return ret("string", stream.current());\n
-      } else if( stream.current().match(/\\-\\d|\\-.\\d/) ){ // match e.g.: -5px -0.4 etc... only colorize the minus sign\n
-        //commment out these 2 comment if you want the minus sign to be parsed as null -500px\n
-        //stream.backUp(stream.current().length-1);\n
-        //return ret(null, ch);\n
-        return ret("number", "unit");\n
-      } else if( /\\/|[\\s\\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){\n
-        if(stream.current().substring(stream.current().length-1,stream.current().length) == "{"){\n
-          stream.backUp(1);\n
-          return ret("tag", "tag");\n
-        }//end if\n
-        stream.eatSpace();\n
-        if( /[{<>.a-zA-Z\\/]/.test(stream.peek())  || stream.eol() )return ret("tag", "tag"); // e.g. button.icon-plus\n
-        return ret("string", "string"); // let url(/images/logo.png) without quotes return as string\n
-      } else if( stream.eol() || stream.peek() == "[" || stream.peek() == "#" || type == "tag" ){\n
-\n
-        if(stream.current().substring(stream.current().length-1,stream.current().length) == "{")stream.backUp(1);\n
-        else if(state.stack[state.stack.length-1] === "border-color" || state.stack[state.stack.length-1] === "background-position" || state.stack[state.stack.length-1] === "font-family")return ret(null, stream.current());\n
-        else if(type === "tag")return ret("tag", "tag");\n
-        else if((type === ":" || type === "unit") && state.stack[state.stack.length-1] === "rule")return ret(null, stream.current());\n
-        else if(state.stack[state.stack.length-1] === "rule" && type === "tag")return ret("string", stream.current());\n
-        else if(state.stack[state.stack.length-1] === ";" && type === ":")return ret(null, stream.current());\n
-        //else if(state.stack[state.stack.length-1] === ";" || type === "")return ret("variable", stream.current());\n
-        else if(stream.peek() === "#" && type !== undefined && type.match(/\\+|,|tag|select\\-op|}|{|;/g) === null)return ret("string", stream.current());\n
-        else if(type === "variable")return ret(null, stream.current());\n
-        else if(state.stack[state.stack.length-1] === "{" && type === "comment")return ret("variable", stream.current());\n
-        else if(state.stack.length === 0 && (type === ";" || type === "comment"))return ret("tag", stream.current());\n
-        else if((state.stack[state.stack.length-1] === "{" || type === ";") && state.stack[state.stack.length-1] !== "@media{")return ret("variable", stream.current());\n
-        else if(state.stack[state.stack.length-2] === "{" && state.stack[state.stack.length-1] === ";")return ret("variable", stream.current());\n
-\n
-        return ret("tag", "tag");\n
-      } else if(type == "compare" || type == "a" || type == "("){\n
-        return ret("string", "string");\n
-      } else if(type == "|" || stream.current() == "-" || type == "["){\n
-        if (type == "|" && stream.match(/^[\\]=~]/, false)) return ret("number", stream.current());\n
-        else if(type == "|" )return ret("tag", "tag");\n
-        else if(type == "["){\n
-          stream.eatWhile(/\\w\\-/);\n
-          return ret("number", stream.current());\n
-        }\n
-        return ret(null, ch);\n
-      } else if((stream.peek() == ":") || ( stream.eatSpace() && stream.peek() == ":")) {\n
-        stream.next();\n
-        var t_v = stream.peek() == ":" ? true : false;\n
-        if(!t_v){\n
-          var old_pos = stream.pos;\n
-          var sc = stream.current().length;\n
-          stream.eatWhile(/[a-z\\\\\\-]/);\n
-          var new_pos = stream.pos;\n
-          if(stream.current().substring(sc-1).match(selectors) != null){\n
-            stream.backUp(new_pos-(old_pos-1));\n
-            return ret("tag", "tag");\n
-          } else stream.backUp(new_pos-(old_pos-1));\n
-        } else {\n
-          stream.backUp(1);\n
-        }\n
-        if(t_v)return ret("tag", "tag"); else return ret("variable", "variable");\n
-      } else if(state.stack[state.stack.length-1]  === "font-family" || state.stack[state.stack.length-1]  === "background-position" || state.stack[state.stack.length-1]  === "border-color"){\n
-        return ret(null, null);\n
-      } else {\n
-\n
-        if(state.stack[state.stack.length-1] === null && type === ":")return ret(null, stream.current());\n
-\n
-        //else if((type === ")" && state.stack[state.stack.length-1] === "rule") || (state.stack[state.stack.length-2] === "{" && state.stack[state.stack.length-1] === "rule" && type === "variable"))return ret(null, stream.current());\n
-\n
-        else if (/\\^|\\$/.test(stream.current()) && stream.match(/^[~=]/, false)) return ret("string", "string");//att^=val\n
-\n
-        else if(type === "unit" && state.stack[state.stack.length-1] === "rule")return ret(null, "unit");\n
-        else if(type === "unit" && state.stack[state.stack.length-1] === ";")return ret(null, "unit");\n
-        else if(type === ")" && state.stack[state.stack.length-1] === "rule")return ret(null, "unit");\n
-        else if(type && type.match("@") !== null  && state.stack[state.stack.length-1] === "rule")return ret(null, "unit");\n
-        //else if(type === "unit" && state.stack[state.stack.length-1] === "rule")return ret(null, stream.current());\n
-\n
-        else if((type === ";" || type === "}" || type === ",") && state.stack[state.stack.length-1] === ";")return ret("tag", stream.current());\n
-        else if((type === ";" && stream.peek() !== undefined && !stream.match(/^[{\\.]/, false)) ||\n
-                (type === ";" && stream.eatSpace() && !stream.match(/^[{\\.]/))) return ret("variable", stream.current());\n
-        else if((type === "@media" && state.stack[state.stack.length-1] === "@media") || type === "@namespace")return ret("tag", stream.current());\n
-\n
-        else if(type === "{"  && state.stack[state.stack.length-1] === ";" && stream.peek() === "{")return ret("tag", "tag");\n
-        else if((type === "{" || type === ":") && state.stack[state.stack.length-1] === ";")return ret(null, stream.current());\n
-        else if((state.stack[state.stack.length-1] === "{" && stream.eatSpace() && !stream.match(/^[\\.#]/)) || type === "select-op"  || (state.stack[state.stack.length-1] === "rule" && type === ",") )return ret("tag", "tag");\n
-        else if(type === "variable" && state.stack[state.stack.length-1] === "rule")return ret("tag", "tag");\n
-        else if((stream.eatSpace() && stream.peek() === "{") || stream.eol() || stream.peek() === "{")return ret("tag", "tag");\n
-        //this one messes up indentation\n
-        //else if((type === "}" && stream.peek() !== ":") || (type === "}" && stream.eatSpace() && stream.peek() !== ":"))return(type, "tag");\n
-\n
-        else if(type === ")" && (stream.current() == "and" || stream.current() == "and "))return ret("variable", "variable");\n
-        else if(type === ")" && (stream.current() == "when" || stream.current() == "when "))return ret("variable", "variable");\n
-        else if(type === ")" || type === "comment" || type === "{")return ret("tag", "tag");\n
-        else if(stream.sol())return ret("tag", "tag");\n
-        else if((stream.eatSpace() && stream.peek() === "#") || stream.peek() === "#")return ret("tag", "tag");\n
-        else if(state.stack.length === 0)return ret("tag", "tag");\n
-        else if(type === ";" && stream.peek() !== undefined && stream.match(/^[\\.|#]/g)) return ret("tag", "tag");\n
-\n
-        else if(type === ":"){stream.eatSpace();return ret(null, stream.current());}\n
-\n
-        else if(stream.current() === "and " || stream.current() === "and")return ret("variable", stream.current());\n
-        else if(type === ";" && state.stack[state.stack.length-1] === "{")return ret("variable", stream.current());\n
-\n
-        else if(state.stack[state.stack.length-1] === "rule")return ret(null, stream.current());\n
-\n
-        return ret("tag", stream.current());\n
-      }\n
-    }\n
-  }\n
-\n
-  function tokenSComment(stream, state) { // SComment = Slash comment\n
-    stream.skipToEnd();\n
-    state.tokenize = tokenBase;\n
-    return ret("comment", "comment");\n
-  }\n
-\n
-  function tokenCComment(stream, state) {\n
-    var maybeEnd = false, ch;\n
-    while ((ch = stream.next()) != null) {\n
-      if (maybeEnd && ch == "/") {\n
-        state.tokenize = tokenBase;\n
-        break;\n
-      }\n
-      maybeEnd = (ch == "*");\n
-    }\n
-    return ret("comment", "comment");\n
-  }\n
-\n
-  function tokenSGMLComment(stream, state) {\n
-    var dashes = 0, ch;\n
-    while ((ch = stream.next()) != null) {\n
-      if (dashes >= 2 && ch == ">") {\n
-        state.tokenize = tokenBase;\n
-        break;\n
-      }\n
-      dashes = (ch == "-") ? dashes + 1 : 0;\n
-    }\n
-    return ret("comment", "comment");\n
-  }\n
-\n
-  function tokenString(quote) {\n
-    return function(stream, state) {\n
-      var escaped = false, ch;\n
-      while ((ch = stream.next()) != null) {\n
-        if (ch == quote && !escaped)\n
-          break;\n
-        escaped = !escaped && ch == "\\\\";\n
-      }\n
-      if (!escaped) state.tokenize = tokenBase;\n
-      return ret("string", "string");\n
-    };\n
-  }\n
-\n
-  return {\n
-    startState: function(base) {\n
-      return {tokenize: tokenBase,\n
-              baseIndent: base || 0,\n
-              stack: []};\n
-    },\n
-\n
-    token: function(stream, state) {\n
-      if (stream.eatSpace()) return null;\n
-      var style = state.tokenize(stream, state);\n
-\n
-      var context = state.stack[state.stack.length-1];\n
-      if (type == "hash" && context == "rule") style = "atom";\n
-      else if (style == "variable") {\n
-        if (context == "rule") style = null; //"tag"\n
-        else if (!context || context == "@media{") {\n
-          style = stream.current() == "when"  ? "variable" :\n
-          /[\\s,|\\s\\)|\\s]/.test(stream.peek()) ? "tag"      : type;\n
-        }\n
-      }\n
-\n
-      if (context == "rule" && /^[\\{\\};]$/.test(type))\n
-        state.stack.pop();\n
-      if (type == "{") {\n
-        if (context == "@media") state.stack[state.stack.length-1] = "@media{";\n
-        else state.stack.push("{");\n
-      }\n
-      else if (type == "}") state.stack.pop();\n
-      else if (type == "@media") state.stack.push("@media");\n
-      else if (stream.current() === "font-family") state.stack[state.stack.length-1] = "font-family";\n
-      else if (stream.current() === "background-position") state.stack[state.stack.length-1] = "background-position";\n
-      else if (stream.current() === "border-color") state.stack[state.stack.length-1] = "border-color";\n
-      else if (context == "{" && type != "comment" && type !== "tag") state.stack.push("rule");\n
-      else if (stream.peek() === ":" && stream.current().match(/@|#/) === null) style = type;\n
-      if(type === ";" && (state.stack[state.stack.length-1] == "font-family" || state.stack[state.stack.length-1] == "background-position" || state.stack[state.stack.length-1] == "border-color"))state.stack[state.stack.length-1] = stream.current();\n
-      else if(type === "tag" && stream.peek() === ")" && stream.current().match(/\\:/) === null){type = null; style = null;}\n
-      // ????\n
-      else if((type === "variable" && stream.peek() === ")") || (type === "variable" && stream.eatSpace() && stream.peek() === ")"))return ret(null,stream.current());\n
-      return style;\n
-    },\n
-\n
-    indent: function(state, textAfter) {\n
-      var n = state.stack.length;\n
-      if (/^\\}/.test(textAfter))\n
-        n -= state.stack[state.stack.length-1] === "rule" ? 2 : 1;\n
-      else if (state.stack[state.stack.length-2] === "{")\n
-        n -= state.stack[state.stack.length-1] === "rule" ? 1 : 0;\n
-      return state.baseIndent + n * indentUnit;\n
-    },\n
-\n
-    electricChars: "}",\n
-    blockCommentStart: "/*",\n
-    blockCommentEnd: "*/",\n
-    lineComment: "//"\n
-  };\n
-});\n
-\n
-CodeMirror.defineMIME("text/x-less", "less");\n
-if (!CodeMirror.mimeModes.hasOwnProperty("text/css"))\n
-  CodeMirror.defineMIME("text/css", "less");\n
-
-
-]]></string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>18994</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.js.xml
index bd1b9e62d69d0ba5c1572e7949545139308fff52..fcd227bcdb7198bf9742c494c7e830f3f64c0528 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403094.2</string> </value>
+            <value> <string>ts21897140.55</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,22 +22,35 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Link to the project\'s GitHub page:\n
  * https://github.com/duralog/CodeMirror\n
  */\n
-(function() {\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
   CodeMirror.defineMode(\'livescript\', function(){\n
-    var tokenBase, external;\n
-    tokenBase = function(stream, state){\n
-      var next_rule, nr, i$, len$, r, m;\n
-      if (next_rule = state.next || \'start\') {\n
+    var tokenBase = function(stream, state) {\n
+      var next_rule = state.next || "start";\n
+      if (next_rule) {\n
         state.next = state.next;\n
-        if (Array.isArray(nr = Rules[next_rule])) {\n
-          for (i$ = 0, len$ = nr.length; i$ < len$; ++i$) {\n
-            r = nr[i$];\n
+        var nr = Rules[next_rule];\n
+        if (nr.splice) {\n
+          for (var i$ = 0; i$ < nr.length; ++i$) {\n
+            var r = nr[i$], m;\n
             if (r.regex && (m = stream.match(r.regex))) {\n
-              state.next = r.next;\n
+              state.next = r.next || state.next;\n
               return r.token;\n
             }\n
           }\n
@@ -57,7 +70,7 @@
       stream.next();\n
       return \'error\';\n
     };\n
-    external = {\n
+    var external = {\n
       startState: function(){\n
         return {\n
           next: \'start\',\n
@@ -65,8 +78,8 @@
         };\n
       },\n
       token: function(stream, state){\n
-        var style;\n
-        style = tokenBase(stream, state);\n
+        while (stream.pos == stream.start)\n
+          var style = tokenBase(stream, state);\n
         state.lastToken = {\n
           style: style,\n
           indent: stream.indentation(),\n
@@ -75,8 +88,7 @@
         return style.replace(/\\./g, \' \');\n
       },\n
       indent: function(state){\n
-        var indentation;\n
-        indentation = state.lastToken.indent;\n
+        var indentation = state.lastToken.indent;\n
         if (state.lastToken.content.match(indenter)) {\n
           indentation += 2;\n
         }\n
@@ -216,7 +228,7 @@
         next: \'start\'\n
       }, {\n
         token: \'text\',\n
-        regex: \'.\',\n
+        regex: \'\',\n
         next: \'start\'\n
       }\n
     ],\n
@@ -275,20 +287,21 @@
   };\n
   for (var idx in Rules) {\n
     var r = Rules[idx];\n
-    if (Array.isArray(r)) {\n
+    if (r.splice) {\n
       for (var i = 0, len = r.length; i < len; ++i) {\n
         var rr = r[i];\n
-        if (rr.regex) {\n
+        if (typeof rr.regex === \'string\') {\n
           Rules[idx][i].regex = new RegExp(\'^\' + rr.regex);\n
         }\n
       }\n
-    } else if (r.regex) {\n
+    } else if (typeof rr.regex === \'string\') {\n
       Rules[idx].regex = new RegExp(\'^\' + r.regex);\n
     }\n
   }\n
-})();\n
 \n
-CodeMirror.defineMIME(\'text/x-livescript\', \'livescript\');\n
+  CodeMirror.defineMIME(\'text/x-livescript\', \'livescript\');\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -299,7 +312,7 @@ CodeMirror.defineMIME(\'text/x-livescript\', \'livescript\');\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7177</int> </value>
+            <value> <int>7644</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.ls.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.ls.xml
deleted file mode 100644
index 84791f925b713b1bd19504047c30ab47c0394339..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/livescript/livescript.ls.xml
+++ /dev/null
@@ -1,302 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>livescript.ls</string> </value>
-        </item>
-        <item>
-            <key> <string>_vars</string> </key>
-            <value>
-              <dictionary/>
-            </value>
-        </item>
-        <item>
-            <key> <string>globals</string> </key>
-            <value>
-              <dictionary/>
-            </value>
-        </item>
-        <item>
-            <key> <string>raw</string> </key>
-            <value> <string encoding="cdata"><![CDATA[
-
-/**\n
- * Link to the project\'s GitHub page:\n
- * https://github.com/duralog/CodeMirror\n
- */\n
-CodeMirror.defineMode \'livescript\', (conf) ->\n
-  tokenBase = (stream, state) ->\n
-    #indent =\n
-    if next_rule = state.next or \\start\n
-      state.next = state.next\n
-      if Array.isArray nr = Rules[next_rule]\n
-        for r in nr\n
-          if r.regex and m = stream.match r.regex\n
-            state.next = r.next\n
-            return r.token\n
-        stream.next!\n
-        return \\error\n
-      if stream.match r = Rules[next_rule]\n
-        if r.regex and stream.match r.regex\n
-          state.next = r.next\n
-          return r.token\n
-        else\n
-          stream.next!\n
-          return \\error\n
-    stream.next!\n
-    return \'error\'\n
-  external = {\n
-    startState: (basecolumn) ->\n
-      {\n
-        next: \\start\n
-        lastToken: null\n
-      }\n
-    token: (stream, state) ->\n
-      style = tokenBase stream, state #tokenLexer stream, state\n
-      state.lastToken = {\n
-        style: style\n
-        indent: stream.indentation!\n
-        content: stream.current!\n
-      }\n
-      style.replace /\\./g, \' \'\n
-    indent: (state, textAfter) ->\n
-      # XXX this won\'t work with backcalls\n
-      indentation = state.lastToken.indent\n
-      if state.lastToken.content.match indenter then indentation += 2\n
-      return indentation\n
-  }\n
-  external\n
-\n
-### Highlight Rules\n
-# taken from mode-ls.ls\n
-\n
-indenter = // (?\n
-    : [({[=:]\n
-    | [-~]>\n
-    | \\b (?: e(?:lse|xport) | d(?:o|efault) | t(?:ry|hen) | finally |\n
-             import (?:\\s* all)? | const | var |\n
-             let | new | catch (?:\\s* #identifier)? )\n
-  ) \\s* $ //\n
-\n
-identifier = /(?![\\d\\s])[$\\w\\xAA-\\uFFDC](?:(?!\\s)[$\\w\\xAA-\\uFFDC]|-[A-Za-z])*/$\n
-keywordend = /(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))/$\n
-stringfill = token: \\string, regex: \'.+\'\n
-\n
-Rules =\n
-  start:\n
-    * token: \\comment.doc\n
-      regex: \'/\\\\*\'\n
-      next : \\comment\n
-\n
-    * token: \\comment\n
-      regex: \'#.*\'\n
-\n
-    * token: \\keyword\n
-      regex: //(?\n
-        :t(?:h(?:is|row|en)|ry|ypeof!?)\n
-        |c(?:on(?:tinue|st)|a(?:se|tch)|lass)\n
-        |i(?:n(?:stanceof)?|mp(?:ort(?:\\s+all)?|lements)|[fs])\n
-        |d(?:e(?:fault|lete|bugger)|o)\n
-        |f(?:or(?:\\s+own)?|inally|unction)\n
-        |s(?:uper|witch)\n
-        |e(?:lse|x(?:tends|port)|val)\n
-        |a(?:nd|rguments)\n
-        |n(?:ew|ot)\n
-        |un(?:less|til)\n
-        |w(?:hile|ith)\n
-        |o[fr]|return|break|let|var|loop\n
-      )//$ + keywordend\n
-\n
-    * token: \\constant.language\n
-      regex: \'(?:true|false|yes|no|on|off|null|void|undefined)\' + keywordend\n
-\n
-    * token: \\invalid.illegal\n
-      regex: \'(?\n
-        :p(?:ackage|r(?:ivate|otected)|ublic)\n
-        |i(?:mplements|nterface)\n
-        |enum|static|yield\n
-      )\' + keywordend\n
-\n
-    * token: \\language.support.class\n
-      regex: \'(?\n
-        :R(?:e(?:gExp|ferenceError)|angeError)\n
-        |S(?:tring|yntaxError)\n
-        |E(?:rror|valError)\n
-        |Array|Boolean|Date|Function|Number|Object|TypeError|URIError\n
-      )\' + keywordend\n
-\n
-    * token: \\language.support.function\n
-      regex: \'(?\n
-        :is(?:NaN|Finite)\n
-        |parse(?:Int|Float)\n
-        |Math|JSON\n
-        |(?:en|de)codeURI(?:Component)?\n
-      )\' + keywordend\n
-\n
-    * token: \\variable.language\n
-      regex: \'(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)\' + keywordend\n
-\n
-    * token: \\identifier\n
-      regex: identifier + /\\s*:(?![:=])/$\n
-\n
-    * token: \\variable\n
-      regex: identifier\n
-\n
-    * token: \\keyword.operator\n
-      regex: /(?:\\.{3}|\\s+\\?)/$\n
-\n
-    * token: \\keyword.variable\n
-      regex: /(?:@+|::|\\.\\.)/$\n
-      next : \\key\n
-\n
-    * token: \\keyword.operator\n
-      regex: /\\.\\s*/$\n
-      next : \\key\n
-\n
-    * token: \\string\n
-      regex: /\\\\\\S[^\\s,;)}\\]]*/$\n
-\n
-    * token: \\string.doc\n
-      regex: \\\'\'\'\n
-      next : \\qdoc\n
-\n
-    * token: \\string.doc\n
-      regex: \\"""\n
-      next : \\qqdoc\n
-\n
-    * token: \\string\n
-      regex: \\\'\n
-      next : \\qstring\n
-\n
-    * token: \\string\n
-      regex: \\"\n
-      next : \\qqstring\n
-\n
-    * token: \\string\n
-      regex: \\`\n
-      next : \\js\n
-\n
-    * token: \\string\n
-      regex: \'<\\\\[\'\n
-      next : \\words\n
-\n
-    * token: \\string.regex\n
-      regex: \\//\n
-      next : \\heregex\n
-\n
-    * token: \\string.regex\n
-      regex: //\n
-        /(?: [^ [ / \\n \\\\ ]*\n
-          (?: (?: \\\\.\n
-                | \\[ [^\\]\\n\\\\]* (?:\\\\.[^\\]\\n\\\\]*)* \\]\n
-              ) [^ [ / \\n \\\\ ]*\n
-          )*\n
-        )/ [gimy$]{0,4}\n
-      //$\n
-      next : \\key\n
-\n
-    * token: \\constant.numeric\n
-      regex: \'(?:0x[\\\\da-fA-F][\\\\da-fA-F_]*\n
-                |(?:[2-9]|[12]\\\\d|3[0-6])r[\\\\da-zA-Z][\\\\da-zA-Z_]*\n
-                |(?:\\\\d[\\\\d_]*(?:\\\\.\\\\d[\\\\d_]*)?|\\\\.\\\\d[\\\\d_]*)\n
-                 (?:e[+-]?\\\\d[\\\\d_]*)?[\\\\w$]*)\'\n
-\n
-    * token: \\lparen\n
-      regex: \'[({[]\'\n
-\n
-    * token: \\rparen\n
-      regex: \'[)}\\\\]]\'\n
-      next : \\key\n
-\n
-    * token: \\keyword.operator\n
-      regex: \\\\\\S+\n
-\n
-    * token: \\text\n
-      regex: \\\\\\s+\n
-\n
-  heregex:\n
-    * token: \\string.regex\n
-      regex: \'.*?//[gimy$?]{0,4}\'\n
-      next : \\start\n
-    * token: \\string.regex\n
-      regex: \'\\\\s*#{\'\n
-    * token: \\comment.regex\n
-      regex: \'\\\\s+(?:#.*)?\'\n
-    * token: \\string.regex\n
-      regex: \'\\\\S+\'\n
-\n
-  key:\n
-    * token: \\keyword.operator\n
-      regex: \'[.?@!]+\'\n
-    * token: \\identifier\n
-      regex: identifier\n
-      next : \\start\n
-    * token: \\text\n
-      regex: \'.\'\n
-      next : \\start\n
-\n
-  comment:\n
-    * token: \\comment.doc\n
-      regex: \'.*?\\\\*/\'\n
-      next : \\start\n
-    * token: \\comment.doc\n
-      regex: \'.+\'\n
-\n
-  qdoc:\n
-    token: \\string\n
-    regex: ".*?\'\'\'"\n
-    next : \\key\n
-    stringfill\n
-\n
-  qqdoc:\n
-    token: \\string\n
-    regex: \'.*?"""\'\n
-    next : \\key\n
-    stringfill\n
-\n
-  qstring:\n
-    token: \\string\n
-    regex: /[^\\\\\']*(?:\\\\.[^\\\\\']*)*\'/$\n
-    next : \\key\n
-    stringfill\n
-\n
-  qqstring:\n
-    token: \\string\n
-    regex: /[^\\\\"]*(?:\\\\.[^\\\\"]*)*"/$\n
-    next : \\key\n
-    stringfill\n
-\n
-  js:\n
-    token: \\string\n
-    regex: /[^\\\\`]*(?:\\\\.[^\\\\`]*)*`/$\n
-    next : \\key\n
-    stringfill\n
-\n
-  words:\n
-    token: \\string\n
-    regex: \'.*?\\\\]>\'\n
-    next : \\key\n
-    stringfill\n
-\n
-# for optimization, precompile the regexps\n
-for idx, r of Rules\n
-  if Array.isArray r\n
-    for rr, i in r\n
-      if rr.regex then Rules[idx][i].regex = new RegExp \'^\'+rr.regex\n
-  else if r.regex then Rules[idx].regex = new RegExp \'^\'+r.regex\n
-\n
-CodeMirror.defineMIME \'text/x-livescript\', \'livescript\'\n
-
-
-]]></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/lua/lua.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/lua/lua.js.xml
index 358a8431efb8e2828dcf7a58cbdce9b977571094..fec28fae3b2e83b8fc3acbd772b83c5acaecad96 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/lua/lua.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/lua/lua.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403087.04</string> </value>
+            <value> <string>ts21897148.96</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak\'s\n
 // CodeMirror 1 mode.\n
 // highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting\n
 \n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("lua", function(config, parserConfig) {\n
   var indentUnit = config.indentUnit;\n
 \n
@@ -166,6 +179,8 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-lua", "lua");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -176,7 +191,7 @@ CodeMirror.defineMIME("text/x-lua", "lua");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5489</int> </value>
+            <value> <int>5950</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/markdown.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/markdown.js.xml
index 6e6377038e1e114d508928e6593756c7b1db725d..dd7f85c9c348b97f8b5c36053b981aea77f0931c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/markdown.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/markdown.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403087.55</string> </value>
+            <value> <string>ts21897148.45</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,49 +22,32 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
 \n
   var htmlFound = CodeMirror.modes.hasOwnProperty("xml");\n
   var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");\n
-  var aliases = {\n
-    html: "htmlmixed",\n
-    js: "javascript",\n
-    json: "application/json",\n
-    c: "text/x-csrc",\n
-    "c++": "text/x-c++src",\n
-    java: "text/x-java",\n
-    csharp: "text/x-csharp",\n
-    "c#": "text/x-csharp",\n
-    scala: "text/x-scala"\n
-  };\n
-\n
-  var getMode = (function () {\n
-    var i, modes = {}, mimes = {}, mime;\n
 \n
-    var list = [];\n
-    for (var m in CodeMirror.modes)\n
-      if (CodeMirror.modes.propertyIsEnumerable(m)) list.push(m);\n
-    for (i = 0; i < list.length; i++) {\n
-      modes[list[i]] = list[i];\n
+  function getMode(name) {\n
+    if (CodeMirror.findModeByName) {\n
+      var found = CodeMirror.findModeByName(name);\n
+      if (found) name = found.mime || found.mimes[0];\n
     }\n
-    var mimesList = [];\n
-    for (var m in CodeMirror.mimeModes)\n
-      if (CodeMirror.mimeModes.propertyIsEnumerable(m))\n
-        mimesList.push({mime: m, mode: CodeMirror.mimeModes[m]});\n
-    for (i = 0; i < mimesList.length; i++) {\n
-      mime = mimesList[i].mime;\n
-      mimes[mime] = mimesList[i].mime;\n
-    }\n
-\n
-    for (var a in aliases) {\n
-      if (aliases[a] in modes || aliases[a] in mimes)\n
-        modes[a] = aliases[a];\n
-    }\n
-\n
-    return function (lang) {\n
-      return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;\n
-    };\n
-  }());\n
+    var mode = CodeMirror.getMode(cmCfg, name);\n
+    return mode.name == "null" ? null : mode;\n
+  }\n
 \n
   // Should characters that affect highlighting be highlighted separate?\n
   // Does not include characters that will be output (such as `1.` and `-` for lists)\n
@@ -85,6 +68,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
 \n
   // Turn on task lists? ("- [ ] " and "- [x] ")\n
   if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;\n
+\n
+  // Turn on strikethrough syntax\n
+  if (modeCfg.strikethrough === undefined)\n
+    modeCfg.strikethrough = false;\n
 \n
   var codeDepth = 0;\n
 \n
@@ -102,7 +89,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
   ,   linktext = \'link\'\n
   ,   linkhref = \'string\'\n
   ,   em       = \'em\'\n
-  ,   strong   = \'strong\';\n
+  ,   strong   = \'strong\'\n
+  ,   strikethrough = \'strikethrough\';\n
 \n
   var hrRE = /^([*\\-=_])(?:\\s*\\1){2,}\\s*$/\n
   ,   ulRE = /^[*\\-+]\\s+/\n
@@ -110,7 +98,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
   ,   taskListRE = /^\\[(x| )\\](?=\\s)/ // Must follow ulRE or olRE\n
   ,   atxHeaderRE = /^#+/\n
   ,   setextHeaderRE = /^(?:\\={1,}|-{1,})$/\n
-  ,   textRE = /^[^#!\\[\\]*_\\\\<>` "\'(]+/;\n
+  ,   textRE = /^[^#!\\[\\]*_\\\\<>` "\'(~]+/;\n
 \n
   function switchInline(stream, state, f) {\n
     state.f = state.inline = f;\n
@@ -132,6 +120,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
     state.em = false;\n
     // Reset STRONG state\n
     state.strong = false;\n
+    // Reset strikethrough state\n
+    state.strikethrough = false;\n
     // Reset state.quote\n
     state.quote = 0;\n
     if (!htmlFound && state.f == htmlBlock) {\n
@@ -208,11 +198,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
       state.f = state.inline;\n
       if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];\n
       return getType(state);\n
-    } else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\\w+#]*)/, true)) {\n
+    } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \\t]*([\\w+#]*)/, true)) {\n
       // try switching mode\n
       state.localMode = getMode(RegExp.$1);\n
       if (state.localMode) state.localState = state.localMode.startState();\n
-      switchBlock(stream, state, local);\n
+      state.f = state.block = local;\n
       if (modeCfg.highlightFormatting) state.formatting = "code-block";\n
       state.code = true;\n
       return getType(state);\n
@@ -223,7 +213,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
 \n
   function htmlBlock(stream, state) {\n
     var style = htmlMode.token(stream, state.htmlState);\n
-    if ((htmlFound && !state.htmlState.tagName && !state.htmlState.context) ||\n
+    if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||\n
         (state.md_inside && stream.current().indexOf(">") > -1)) {\n
       state.f = inlineNormal;\n
       state.block = blockNormal;\n
@@ -233,15 +223,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
   }\n
 \n
   function local(stream, state) {\n
-    if (stream.sol() && stream.match(/^```/, true)) {\n
+    if (stream.sol() && stream.match("```", false)) {\n
       state.localMode = state.localState = null;\n
-      state.f = inlineNormal;\n
-      state.block = blockNormal;\n
-      if (modeCfg.highlightFormatting) state.formatting = "code-block";\n
-      state.code = true;\n
-      var returnType = getType(state);\n
-      state.code = false;\n
-      return returnType;\n
+      state.f = state.block = leavingLocal;\n
+      return null;\n
     } else if (state.localMode) {\n
       return state.localMode.token(stream, state.localState);\n
     } else {\n
@@ -249,6 +234,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
       return code;\n
     }\n
   }\n
+\n
+  function leavingLocal(stream, state) {\n
+    stream.match("```");\n
+    state.block = blockNormal;\n
+    state.f = inlineNormal;\n
+    if (modeCfg.highlightFormatting) state.formatting = "code-block";\n
+    state.code = true;\n
+    var returnType = getType(state);\n
+    state.code = false;\n
+    return returnType;\n
+  }\n
 \n
   // Inline\n
   function getType(state) {\n
@@ -294,6 +290,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
 \n
     if (state.strong) { styles.push(strong); }\n
     if (state.em) { styles.push(em); }\n
+    if (state.strikethrough) { styles.push(strikethrough); }\n
 \n
     if (state.linkText) { styles.push(linktext); }\n
 \n
@@ -370,16 +367,13 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
     var sol = stream.sol();\n
 \n
     var ch = stream.next();\n
-\n
-    if (state.escape) {\n
-      state.escape = false;\n
-      return getType(state);\n
-    }\n
 \n
     if (ch === \'\\\\\') {\n
-      if (modeCfg.highlightFormatting) state.formatting = "escape";\n
-      state.escape = true;\n
-      return getType(state);\n
+      stream.next();\n
+      if (modeCfg.highlightFormatting) {\n
+        var type = getType(state);\n
+        return type ? type + " formatting-escape" : "formatting-escape";\n
+      }\n
     }\n
 \n
     // Matches link titles present on next line\n
@@ -426,13 +420,13 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
       return image;\n
     }\n
 \n
-    if (ch === \'[\' && stream.match(/.*\\](\\(| ?\\[)/, false)) {\n
+    if (ch === \'[\' && stream.match(/.*\\](\\(.*\\)| ?\\[.*\\])/, false)) {\n
       state.linkText = true;\n
       if (modeCfg.highlightFormatting) state.formatting = "link";\n
       return getType(state);\n
     }\n
 \n
-    if (ch === \']\' && state.linkText) {\n
+    if (ch === \']\' && state.linkText && stream.match(/\\(.*\\)| ?\\[.*\\]/, false)) {\n
       if (modeCfg.highlightFormatting) state.formatting = "link";\n
       var type = getType(state);\n
       state.linkText = false;\n
@@ -524,6 +518,29 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
         }\n
       }\n
     }\n
+\n
+    if (modeCfg.strikethrough) {\n
+      if (ch === \'~\' && stream.eatWhile(ch)) {\n
+        if (state.strikethrough) {// Remove strikethrough\n
+          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";\n
+          var t = getType(state);\n
+          state.strikethrough = false;\n
+          return t;\n
+        } else if (stream.match(/^[^\\s]/, false)) {// Add strikethrough\n
+          state.strikethrough = true;\n
+          if (modeCfg.highlightFormatting) state.formatting = "strikethrough";\n
+          return getType(state);\n
+        }\n
+      } else if (ch === \' \') {\n
+        if (stream.match(/^~~/, true)) { // Probably surrounded by space\n
+          if (stream.peek() === \' \') { // Surrounded by spaces, ignore\n
+            return getType(state);\n
+          } else { // Not surrounded by spaces, back up pointer\n
+            stream.backUp(2);\n
+          }\n
+        }\n
+      }\n
+    }\n
 \n
     if (ch === \' \') {\n
       if (stream.match(/ +$/, false)) {\n
@@ -661,7 +678,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
         inline: inlineNormal,\n
         text: handleText,\n
 \n
-        escape: false,\n
         formatting: false,\n
         linkText: false,\n
         linkHref: false,\n
@@ -674,7 +690,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
         listDepth: 0,\n
         quote: 0,\n
         trailingSpace: 0,\n
-        trailingSpaceNewLine: false\n
+        trailingSpaceNewLine: false,\n
+        strikethrough: false\n
       };\n
     },\n
 \n
@@ -694,11 +711,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
 \n
         inline: s.inline,\n
         text: s.text,\n
-        escape: false,\n
         formatting: false,\n
         linkTitle: s.linkTitle,\n
         em: s.em,\n
         strong: s.strong,\n
+        strikethrough: s.strikethrough,\n
         header: s.header,\n
         taskList: s.taskList,\n
         list: s.list,\n
@@ -716,21 +733,19 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
       state.formatting = false;\n
 \n
       if (stream.sol()) {\n
-        var forceBlankLine = stream.match(/^\\s*$/, true) || state.header;\n
+        var forceBlankLine = !!state.header;\n
 \n
         // Reset state.header\n
         state.header = 0;\n
 \n
-        if (forceBlankLine) {\n
+        if (stream.match(/^\\s*$/, true) || forceBlankLine) {\n
           state.prevLineHasContent = false;\n
-          return blankLine(state);\n
+          blankLine(state);\n
+          return forceBlankLine ? this.token(stream, state) : null;\n
         } else {\n
           state.prevLineHasContent = state.thisLineHasContent;\n
           state.thisLineHasContent = true;\n
         }\n
-\n
-        // Reset state.escape\n
-        state.escape = false;\n
 \n
         // Reset state.taskList\n
         state.taskList = false;\n
@@ -770,6 +785,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {\n
 }, "xml");\n
 \n
 CodeMirror.defineMIME("text/x-markdown", "markdown");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -780,7 +797,7 @@ CodeMirror.defineMIME("text/x-markdown", "markdown");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>22372</int> </value>
+            <value> <int>23434</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/test.js.xml
index c8868b2b613ec726458238e6adb2bfd613f16a61..57be26663607a2766b3c494ed528f7caaf79bcf1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/markdown/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403087.75</string> </value>
+            <value> <string>ts21897148.27</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   var mode = CodeMirror.getMode({tabSize: 4}, "markdown");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
@@ -75,7 +78,7 @@
      "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]");\n
 \n
   FT("formatting_escape",\n
-     "[formatting&formatting-escape \\\\]*");\n
+     "[formatting-escape \\\\*]");\n
 \n
   MT("plainText",\n
      "foo");\n
@@ -112,6 +115,14 @@
      "    [comment bar]",\n
      "        [comment hello]",\n
      "    [comment world]");\n
+\n
+  // Code blocks should end even after extra indented lines\n
+  MT("codeBlocksWithTrailingIndentedLine",\n
+     "    [comment foo]",\n
+     "        [comment bar]",\n
+     "    [comment baz]",\n
+     "    ",\n
+     "hello");\n
 \n
   // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)\n
   MT("codeBlocksUsing1Tab",\n
@@ -745,6 +756,25 @@
      "[comment ```]",\n
      "foo",\n
      "[comment ```]");\n
+\n
+  // Tests that require XML mode\n
+\n
+  MT("xmlMode",\n
+     "[tag&bracket <][tag div][tag&bracket >]",\n
+     "*foo*",\n
+     "[tag&bracket <][tag http://github.com][tag&bracket />]",\n
+     "[tag&bracket </][tag div][tag&bracket >]",\n
+     "[link <http://github.com/>]");\n
+\n
+  MT("xmlModeWithMarkdownInside",\n
+     "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]",\n
+     "[em *foo*]",\n
+     "[link <http://github.com/>]",\n
+     "[tag </div>]",\n
+     "[link <http://github.com/>]",\n
+     "[tag&bracket <][tag div][tag&bracket >]",\n
+     "[tag&bracket </][tag div][tag&bracket >]");\n
+\n
 })();\n
 
 
@@ -756,7 +786,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>19952</int> </value>
+            <value> <int>20871</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/meta.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/meta.js.xml
index 837b7d4094040b40adc1d189f1fa3541a36c9263..19e232cd727602e2a34f6aa734516ee3de7c817c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/meta.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/meta.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403098.55</string> </value>
+            <value> <string>ts21897135.95</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,102 +20,176 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>CodeMirror.modeInfo = [\n
-  {name: \'APL\', mime: \'text/apl\', mode: \'apl\'},\n
-  {name: \'Asterisk\', mime: \'text/x-asterisk\', mode: \'asterisk\'},\n
-  {name: \'C\', mime: \'text/x-csrc\', mode: \'clike\'},\n
-  {name: \'C++\', mime: \'text/x-c++src\', mode: \'clike\'},\n
-  {name: \'Cobol\', mime: \'text/x-cobol\', mode: \'cobol\'},\n
-  {name: \'Java\', mime: \'text/x-java\', mode: \'clike\'},\n
-  {name: \'C#\', mime: \'text/x-csharp\', mode: \'clike\'},\n
-  {name: \'Scala\', mime: \'text/x-scala\', mode: \'clike\'},\n
-  {name: \'Clojure\', mime: \'text/x-clojure\', mode: \'clojure\'},\n
-  {name: \'CoffeeScript\', mime: \'text/x-coffeescript\', mode: \'coffeescript\'},\n
-  {name: \'Common Lisp\', mime: \'text/x-common-lisp\', mode: \'commonlisp\'},\n
-  {name: \'CSS\', mime: \'text/css\', mode: \'css\'},\n
-  {name: \'D\', mime: \'text/x-d\', mode: \'d\'},\n
-  {name: \'diff\', mime: \'text/x-diff\', mode: \'diff\'},\n
-  {name: \'DTD\', mime: \'application/xml-dtd\', mode: \'dtd\'},\n
-  {name: \'ECL\', mime: \'text/x-ecl\', mode: \'ecl\'},\n
-  {name: \'Eiffel\', mime: \'text/x-eiffel\', mode: \'eiffel\'},\n
-  {name: \'Erlang\', mime: \'text/x-erlang\', mode: \'erlang\'},\n
-  {name: \'Fortran\', mime: \'text/x-fortran\', mode: \'fortran\'},\n
-  {name: \'F#\', mime: \'text/x-fsharp\', mode: \'mllike\'},\n
-  {name: \'Gas\', mime: \'text/x-gas\', mode: \'gas\'},\n
-  {name: \'Gherkin\', mime: \'text/x-feature\', mode: \'gherkin\'},\n
-  {name: \'GitHub Flavored Markdown\', mime: \'text/x-gfm\', mode: \'gfm\'},\n
-  {name: \'Go\', mime: \'text/x-go\', mode: \'go\'},\n
-  {name: \'Groovy\', mime: \'text/x-groovy\', mode: \'groovy\'},\n
-  {name: \'HAML\', mime: \'text/x-haml\', mode: \'haml\'},\n
-  {name: \'Haskell\', mime: \'text/x-haskell\', mode: \'haskell\'},\n
-  {name: \'Haxe\', mime: \'text/x-haxe\', mode: \'haxe\'},\n
-  {name: \'ASP.NET\', mime: \'application/x-aspx\', mode: \'htmlembedded\'},\n
-  {name: \'Embedded Javascript\', mime: \'application/x-ejs\', mode: \'htmlembedded\'},\n
-  {name: \'JavaServer Pages\', mime: \'application/x-jsp\', mode: \'htmlembedded\'},\n
-  {name: \'HTML\', mime: \'text/html\', mode: \'htmlmixed\'},\n
-  {name: \'HTTP\', mime: \'message/http\', mode: \'http\'},\n
-  {name: \'Jade\', mime: \'text/x-jade\', mode: \'jade\'},\n
-  {name: \'JavaScript\', mime: \'text/javascript\', mode: \'javascript\'},\n
-  {name: \'JSON\', mime: \'application/x-json\', mode: \'javascript\'},\n
-  {name: \'JSON\', mime: \'application/json\', mode: \'javascript\'},\n
-  {name: \'JSON-LD\', mime: \'application/ld+json\', mode: \'javascript\'},\n
-  {name: \'TypeScript\', mime: \'application/typescript\', mode: \'javascript\'},\n
-  {name: \'Jinja2\', mime: null, mode: \'jinja2\'},\n
-  {name: \'Julia\', mime: \'text/x-julia\', mode: \'julia\'},\n
-  {name: \'LESS\', mime: \'text/x-less\', mode: \'less\'},\n
-  {name: \'LiveScript\', mime: \'text/x-livescript\', mode: \'livescript\'},\n
-  {name: \'Lua\', mime: \'text/x-lua\', mode: \'lua\'},\n
-  {name: \'Markdown (GitHub-flavour)\', mime: \'text/x-markdown\', mode: \'markdown\'},\n
-  {name: \'mIRC\', mime: \'text/mirc\', mode: \'mirc\'},\n
-  {name: \'Nginx\', mime: \'text/x-nginx-conf\', mode: \'nginx\'},\n
-  {name: \'NTriples\', mime: \'text/n-triples\', mode: \'ntriples\'},\n
-  {name: \'OCaml\', mime: \'text/x-ocaml\', mode: \'mllike\'},\n
-  {name: \'Octave\', mime: \'text/x-octave\', mode: \'octave\'},\n
-  {name: \'Pascal\', mime: \'text/x-pascal\', mode: \'pascal\'},\n
-  {name: \'PEG.js\', mime: null, mode: \'pegjs\'},\n
-  {name: \'Perl\', mime: \'text/x-perl\', mode: \'perl\'},\n
-  {name: \'PHP\', mime: \'text/x-php\', mode: \'php\'},\n
-  {name: \'PHP(HTML)\', mime: \'application/x-httpd-php\', mode: \'php\'},\n
-  {name: \'Pig\', mime: \'text/x-pig\', mode: \'pig\'},\n
-  {name: \'Plain Text\', mime: \'text/plain\', mode: \'null\'},\n
-  {name: \'Properties files\', mime: \'text/x-properties\', mode: \'properties\'},\n
-  {name: \'Python\', mime: \'text/x-python\', mode: \'python\'},\n
-  {name: \'Puppet\', mime: \'text/x-puppet\', mode: \'puppet\'},\n
-  {name: \'Cython\', mime: \'text/x-cython\', mode: \'python\'},\n
-  {name: \'R\', mime: \'text/x-rsrc\', mode: \'r\'},\n
-  {name: \'reStructuredText\', mime: \'text/x-rst\', mode: \'rst\'},\n
-  {name: \'Ruby\', mime: \'text/x-ruby\', mode: \'ruby\'},\n
-  {name: \'Rust\', mime: \'text/x-rustsrc\', mode: \'rust\'},\n
-  {name: \'Sass\', mime: \'text/x-sass\', mode: \'sass\'},\n
-  {name: \'Scheme\', mime: \'text/x-scheme\', mode: \'scheme\'},\n
-  {name: \'SCSS\', mime: \'text/x-scss\', mode: \'css\'},\n
-  {name: \'Shell\', mime: \'text/x-sh\', mode: \'shell\'},\n
-  {name: \'Sieve\', mime: \'application/sieve\', mode: \'sieve\'},\n
-  {name: \'Smalltalk\', mime: \'text/x-stsrc\', mode: \'smalltalk\'},\n
-  {name: \'Smarty\', mime: \'text/x-smarty\', mode: \'smarty\'},\n
-  {name: \'SmartyMixed\', mime: \'text/x-smarty\', mode: \'smartymixed\'},\n
-  {name: \'Solr\', mime: \'text/x-solr\', mode: \'solr\'},\n
-  {name: \'SPARQL\', mime: \'application/x-sparql-query\', mode: \'sparql\'},\n
-  {name: \'SQL\', mime: \'text/x-sql\', mode: \'sql\'},\n
-  {name: \'MariaDB\', mime: \'text/x-mariadb\', mode: \'sql\'},\n
-  {name: \'sTeX\', mime: \'text/x-stex\', mode: \'stex\'},\n
-  {name: \'LaTeX\', mime: \'text/x-latex\', mode: \'stex\'},\n
-  {name: \'Tcl\', mime: \'text/x-tcl\', mode: \'tcl\'},\n
-  {name: \'TiddlyWiki \', mime: \'text/x-tiddlywiki\', mode: \'tiddlywiki\'},\n
-  {name: \'Tiki wiki\', mime: \'text/tiki\', mode: \'tiki\'},\n
-  {name: \'TOML\', mime: \'text/x-toml\', mode: \'toml\'},\n
-  {name: \'Turtle\', mime: \'text/turtle\', mode: \'turtle\'},\n
-  {name: \'VB.NET\', mime: \'text/x-vb\', mode: \'vb\'},\n
-  {name: \'VBScript\', mime: \'text/vbscript\', mode: \'vbscript\'},\n
-  {name: \'Velocity\', mime: \'text/velocity\', mode: \'velocity\'},\n
-  {name: \'Verilog\', mime: \'text/x-verilog\', mode: \'verilog\'},\n
-  {name: \'XML\', mime: \'application/xml\', mode: \'xml\'},\n
-  {name: \'HTML\', mime: \'text/html\', mode: \'xml\'},\n
-  {name: \'XQuery\', mime: \'application/xquery\', mode: \'xquery\'},\n
-  {name: \'YAML\', mime: \'text/x-yaml\', mode: \'yaml\'},\n
-  {name: \'Z80\', mime: \'text/x-z80\', mode: \'z80\'}\n
-];\n
-</string> </value>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.modeInfo = [\n
+    {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},\n
+    {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk"},\n
+    {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]},\n
+    {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "hpp", "h++"], alias: ["cpp"]},\n
+    {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},\n
+    {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},\n
+    {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj"]},\n
+    {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},\n
+    {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},\n
+    {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher"},\n
+    {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},\n
+    {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},\n
+    {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},\n
+    {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},\n
+    {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},\n
+    {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},\n
+    {name: "Django", mime: "text/x-django", mode: "django"},\n
+    {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile"},\n
+    {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},\n
+    {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},\n
+    {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},\n
+    {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},\n
+    {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},\n
+    {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},\n
+    {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},\n
+    {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},\n
+    {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]},\n
+    {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},\n
+    {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},\n
+    {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},\n
+    {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm"},\n
+    {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},\n
+    {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]},\n
+    {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},\n
+    {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},\n
+    {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},\n
+    {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},\n
+    {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},\n
+    {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]},\n
+    {name: "HTTP", mime: "message/http", mode: "http"},\n
+    {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},\n
+    {name: "Jade", mime: "text/x-jade", mode: "jade", ext: ["jade"]},\n
+    {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},\n
+    {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},\n
+    {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],\n
+     mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},\n
+    {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},\n
+    {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", alias: ["jsonld"]},\n
+    {name: "Jinja2", mime: "null", mode: "jinja2"},\n
+    {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},\n
+    {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]},\n
+    {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},\n
+    {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},\n
+    {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},\n
+    {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},\n
+    {name: "mIRC", mime: "text/mirc", mode: "mirc"},\n
+    {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},\n
+    {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},\n
+    {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},\n
+    {name: "MySQL", mime: "text/x-mysql", mode: "sql"},\n
+    {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx"},\n
+    {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},\n
+    {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]},\n
+    {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},\n
+    {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},\n
+    {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},\n
+    {name: "PEG.js", mime: "null", mode: "pegjs"},\n
+    {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},\n
+    {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]},\n
+    {name: "Pig", mime: "text/x-pig", mode: "pig"},\n
+    {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},\n
+    {name: "PLSQL", mime: "text/x-plsql", mode: "sql"},\n
+    {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},\n
+    {name: "Python", mime: "text/x-python", mode: "python", ext: ["py", "pyw"]},\n
+    {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},\n
+    {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},\n
+    {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r"], alias: ["rscript"]},\n
+    {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},\n
+    {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},\n
+    {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},\n
+    {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},\n
+    {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},\n
+    {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},\n
+    {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},\n
+    {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},\n
+    {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},\n
+    {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]},\n
+    {name: "Sieve", mime: "application/sieve", mode: "sieve"},\n
+    {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim"},\n
+    {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},\n
+    {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},\n
+    {name: "SmartyMixed", mime: "text/x-smarty", mode: "smartymixed"},\n
+    {name: "Solr", mime: "text/x-solr", mode: "solr"},\n
+    {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},\n
+    {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},\n
+    {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},\n
+    {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},\n
+    {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"},\n
+    {name: "sTeX", mime: "text/x-stex", mode: "stex"},\n
+    {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]},\n
+    {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]},\n
+    {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},\n
+    {name: "Textile", mime: "text/x-textile", mode: "textile"},\n
+    {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},\n
+    {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},\n
+    {name: "TOML", mime: "text/x-toml", mode: "toml"},\n
+    {name: "Tornado", mime: "text/x-tornado", mode: "tornado"},\n
+    {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},\n
+    {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},\n
+    {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},\n
+    {name: "VBScript", mime: "text/vbscript", mode: "vbscript"},\n
+    {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},\n
+    {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},\n
+    {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]},\n
+    {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},\n
+    {name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml"], alias: ["yml"]},\n
+    {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]}\n
+  ];\n
+  // Ensure all modes have a mime property for backwards compatibility\n
+  for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n
+    var info = CodeMirror.modeInfo[i];\n
+    if (info.mimes) info.mime = info.mimes[0];\n
+  }\n
+\n
+  CodeMirror.findModeByMIME = function(mime) {\n
+    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n
+      var info = CodeMirror.modeInfo[i];\n
+      if (info.mime == mime) return info;\n
+      if (info.mimes) for (var j = 0; j < info.mimes.length; j++)\n
+        if (info.mimes[j] == mime) return info;\n
+    }\n
+  };\n
+\n
+  CodeMirror.findModeByExtension = function(ext) {\n
+    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n
+      var info = CodeMirror.modeInfo[i];\n
+      if (info.ext) for (var j = 0; j < info.ext.length; j++)\n
+        if (info.ext[j] == ext) return info;\n
+    }\n
+  };\n
+\n
+  CodeMirror.findModeByName = function(name) {\n
+    name = name.toLowerCase();\n
+    for (var i = 0; i < CodeMirror.modeInfo.length; i++) {\n
+      var info = CodeMirror.modeInfo[i];\n
+      if (info.name.toLowerCase() == name) return info;\n
+      if (info.alias) for (var j = 0; j < info.alias.length; j++)\n
+        if (info.alias[j].toLowerCase() == name) return info;\n
+    }\n
+  };\n
+});\n
+
+
+]]></string> </value>
         </item>
         <item>
             <key> <string>precondition</string> </key>
@@ -123,7 +197,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5484</int> </value>
+            <value> <int>10995</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mirc/mirc.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mirc/mirc.js.xml
index 74d12d1b3d338248b52e47862e7b04f1ba367ae9..99de3d043161eaaacdcb285c13461ef6c899b05f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mirc/mirc.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mirc/mirc.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403089.86</string> </value>
+            <value> <string>ts21897145.5</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,21 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 //mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O\'Hara\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMIME("text/mirc", "mirc");\n
 CodeMirror.defineMode("mirc", function() {\n
   function parseWords(str) {\n
@@ -199,6 +213,8 @@ CodeMirror.defineMode("mirc", function() {\n
     }\n
   };\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -209,7 +225,7 @@ CodeMirror.defineMode("mirc", function() {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9620</int> </value>
+            <value> <int>10082</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mllike/mllike.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mllike/mllike.js.xml
index f13e5d22513bc2c0dfd9fbc1a9e9035a2450aad0..67ed064b3cee44d9ed6c7b64837bbb92b62ed411 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mllike/mllike.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/mllike/mllike.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403099.34</string> </value>
+            <value> <string>ts21897135.14</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,8 +22,20 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.defineMode(\'mllike\', function(_config, parserConfig) {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
 \n
+CodeMirror.defineMode(\'mllike\', function(_config, parserConfig) {\n
   var words = {\n
     \'let\': \'keyword\',\n
     \'rec\': \'keyword\',\n
@@ -213,6 +225,8 @@ CodeMirror.defineMIME(\'text/x-fsharp\', {\n
   },\n
   slashComments: true\n
 });\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -223,7 +237,7 @@ CodeMirror.defineMIME(\'text/x-fsharp\', {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4531</int> </value>
+            <value> <int>4991</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/modelica.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/modelica.xml
new file mode 100644
index 0000000000000000000000000000000000000000..41d6171b7d5a015755d7b4693ecf2d43757d196b
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/modelica.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>modelica</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/modelica/modelica.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/modelica/modelica.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b8284509dff0e7e9b28be826cc2d9f61ce9c2e22
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/modelica/modelica.js.xml
@@ -0,0 +1,289 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897136.69</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>modelica.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// Modelica support for CodeMirror, copyright (c) by Lennart Ochel\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})\n
+\n
+(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("modelica", function(config, parserConfig) {\n
+\n
+    var indentUnit = config.indentUnit;\n
+    var keywords = parserConfig.keywords || {};\n
+    var builtin = parserConfig.builtin || {};\n
+    var atoms = parserConfig.atoms || {};\n
+\n
+    var isSingleOperatorChar = /[;=\\(:\\),{}.*<>+\\-\\/^\\[\\]]/;\n
+    var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\\.\\+|\\.\\-|\\.\\*|\\.\\/|\\.\\^)/;\n
+    var isDigit = /[0-9]/;\n
+    var isNonDigit = /[_a-zA-Z]/;\n
+\n
+    function tokenLineComment(stream, state) {\n
+      stream.skipToEnd();\n
+      state.tokenize = null;\n
+      return "comment";\n
+    }\n
+\n
+    function tokenBlockComment(stream, state) {\n
+      var maybeEnd = false, ch;\n
+      while (ch = stream.next()) {\n
+        if (maybeEnd && ch == "/") {\n
+          state.tokenize = null;\n
+          break;\n
+        }\n
+        maybeEnd = (ch == "*");\n
+      }\n
+      return "comment";\n
+    }\n
+\n
+    function tokenString(stream, state) {\n
+      var escaped = false, ch;\n
+      while ((ch = stream.next()) != null) {\n
+        if (ch == \'"\' && !escaped) {\n
+          state.tokenize = null;\n
+          state.sol = false;\n
+          break;\n
+        }\n
+        escaped = !escaped && ch == "\\\\";\n
+      }\n
+\n
+      return "string";\n
+    }\n
+\n
+    function tokenIdent(stream, state) {\n
+      stream.eatWhile(isDigit);\n
+      while (stream.eat(isDigit) || stream.eat(isNonDigit)) { }\n
+\n
+\n
+      var cur = stream.current();\n
+\n
+      if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++;\n
+      else if(state.sol && cur == "end" && state.level > 0) state.level--;\n
+\n
+      state.tokenize = null;\n
+      state.sol = false;\n
+\n
+      if (keywords.propertyIsEnumerable(cur)) return "keyword";\n
+      else if (builtin.propertyIsEnumerable(cur)) return "builtin";\n
+      else if (atoms.propertyIsEnumerable(cur)) return "atom";\n
+      else return "variable";\n
+    }\n
+\n
+    function tokenQIdent(stream, state) {\n
+      while (stream.eat(/[^\']/)) { }\n
+\n
+      state.tokenize = null;\n
+      state.sol = false;\n
+\n
+      if(stream.eat("\'"))\n
+        return "variable";\n
+      else\n
+        return "error";\n
+    }\n
+\n
+    function tokenUnsignedNuber(stream, state) {\n
+      stream.eatWhile(isDigit);\n
+      if (stream.eat(\'.\')) {\n
+        stream.eatWhile(isDigit);\n
+      }\n
+      if (stream.eat(\'e\') || stream.eat(\'E\')) {\n
+        if (!stream.eat(\'-\'))\n
+          stream.eat(\'+\');\n
+        stream.eatWhile(isDigit);\n
+      }\n
+\n
+      state.tokenize = null;\n
+      state.sol = false;\n
+      return "number";\n
+    }\n
+\n
+    // Interface\n
+    return {\n
+      startState: function() {\n
+        return {\n
+          tokenize: null,\n
+          level: 0,\n
+          sol: true\n
+        };\n
+      },\n
+\n
+      token: function(stream, state) {\n
+        if(state.tokenize != null) {\n
+          return state.tokenize(stream, state);\n
+        }\n
+\n
+        if(stream.sol()) {\n
+          state.sol = true;\n
+        }\n
+\n
+        // WHITESPACE\n
+        if(stream.eatSpace()) {\n
+          state.tokenize = null;\n
+          return null;\n
+        }\n
+\n
+        var ch = stream.next();\n
+\n
+        // LINECOMMENT\n
+        if(ch == \'/\' && stream.eat(\'/\')) {\n
+          state.tokenize = tokenLineComment;\n
+        }\n
+        // BLOCKCOMMENT\n
+        else if(ch == \'/\' && stream.eat(\'*\')) {\n
+          state.tokenize = tokenBlockComment;\n
+        }\n
+        // TWO SYMBOL TOKENS\n
+        else if(isDoubleOperatorChar.test(ch+stream.peek())) {\n
+          stream.next();\n
+          state.tokenize = null;\n
+          return "operator";\n
+        }\n
+        // SINGLE SYMBOL TOKENS\n
+        else if(isSingleOperatorChar.test(ch)) {\n
+          state.tokenize = null;\n
+          return "operator";\n
+        }\n
+        // IDENT\n
+        else if(isNonDigit.test(ch)) {\n
+          state.tokenize = tokenIdent;\n
+        }\n
+        // Q-IDENT\n
+        else if(ch == "\'" && stream.peek() && stream.peek() != "\'") {\n
+          state.tokenize = tokenQIdent;\n
+        }\n
+        // STRING\n
+        else if(ch == \'"\') {\n
+          state.tokenize = tokenString;\n
+        }\n
+        // UNSIGNED_NUBER\n
+        else if(isDigit.test(ch)) {\n
+          state.tokenize = tokenUnsignedNuber;\n
+        }\n
+        // ERROR\n
+        else {\n
+          state.tokenize = null;\n
+          return "error";\n
+        }\n
+\n
+        return state.tokenize(stream, state);\n
+      },\n
+\n
+      indent: function(state, textAfter) {\n
+        if (state.tokenize != null) return CodeMirror.Pass;\n
+\n
+        var level = state.level;\n
+        if(/(algorithm)/.test(textAfter)) level--;\n
+        if(/(equation)/.test(textAfter)) level--;\n
+        if(/(initial algorithm)/.test(textAfter)) level--;\n
+        if(/(initial equation)/.test(textAfter)) level--;\n
+        if(/(end)/.test(textAfter)) level--;\n
+\n
+        if(level > 0)\n
+          return indentUnit*level;\n
+        else\n
+          return 0;\n
+      },\n
+\n
+      blockCommentStart: "/*",\n
+      blockCommentEnd: "*/",\n
+      lineComment: "//"\n
+    };\n
+  });\n
+\n
+  function words(str) {\n
+    var obj = {}, words = str.split(" ");\n
+    for (var i=0; i<words.length; ++i)\n
+      obj[words[i]] = true;\n
+    return obj;\n
+  }\n
+\n
+  var modelicaKeywords = "algorithm and annotation assert block break class connect connector constant constrainedby der discrete each else elseif elsewhen encapsulated end enumeration equation expandable extends external false final flow for function if import impure in initial inner input loop model not operator or outer output package parameter partial protected public pure record redeclare replaceable return stream then true type when while within";\n
+  var modelicaBuiltin = "abs acos actualStream asin atan atan2 cardinality ceil cos cosh delay div edge exp floor getInstanceName homotopy inStream integer log log10 mod pre reinit rem semiLinear sign sin sinh spatialDistribution sqrt tan tanh";\n
+  var modelicaAtoms = "Real Boolean Integer String";\n
+\n
+  function def(mimes, mode) {\n
+    if (typeof mimes == "string")\n
+      mimes = [mimes];\n
+\n
+    var words = [];\n
+\n
+    function add(obj) {\n
+      if (obj)\n
+        for (var prop in obj)\n
+          if (obj.hasOwnProperty(prop))\n
+            words.push(prop);\n
+    }\n
+\n
+    add(mode.keywords);\n
+    add(mode.builtin);\n
+    add(mode.atoms);\n
+\n
+    if (words.length) {\n
+      mode.helperType = mimes[0];\n
+      CodeMirror.registerHelper("hintWords", mimes[0], words);\n
+    }\n
+\n
+    for (var i=0; i<mimes.length; ++i)\n
+      CodeMirror.defineMIME(mimes[i], mode);\n
+  }\n
+\n
+  def(["text/x-modelica"], {\n
+    name: "modelica",\n
+    keywords: words(modelicaKeywords),\n
+    builtin: words(modelicaBuiltin),\n
+    atoms: words(modelicaAtoms)\n
+  });\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>6930</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/nginx/nginx.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/nginx/nginx.js.xml
index afda1294aa039779d6818f47ec53c3c256984caf..588a06e6279d62e2702cb3b3756ed4a3adec3da3 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/nginx/nginx.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/nginx/nginx.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403098.69</string> </value>
+            <value> <string>ts21897135.85</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("nginx", function(config) {\n
 \n
   function words(str) {\n
@@ -185,6 +198,8 @@ CodeMirror.defineMode("nginx", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -195,7 +210,7 @@ CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9708</int> </value>
+            <value> <int>10169</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ntriples/ntriples.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ntriples/ntriples.js.xml
index 1c68701fae8a4e0defc641f8aee61c9f6c86de0d..2ecca4143821081e875f72bf670f10979a493905 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ntriples/ntriples.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ntriples/ntriples.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403088.86</string> </value>
+            <value> <string>ts21897146.96</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**********************************************************\n
 * This script provides syntax highlighting support for\n
 * the Ntriples format.\n
@@ -49,6 +52,17 @@
              -> ERROR\n
          }\n
 */\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("ntriples", function() {\n
 \n
   var Location = {\n
@@ -192,6 +206,8 @@ CodeMirror.defineMode("ntriples", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/n-triples", "ntriples");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -202,7 +218,7 @@ CodeMirror.defineMIME("text/n-triples", "ntriples");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6181</int> </value>
+            <value> <int>6643</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/octave/octave.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/octave/octave.js.xml
index 5f02c2678c0dfbbe55397b555a2fd194337154a5..fb96d9458575d4b42eb41494de1630e54e3a2376 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/octave/octave.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/octave/octave.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403100.32</string> </value>
+            <value> <string>ts21897134.53</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("octave", function() {\n
   function wordRegexp(words) {\n
     return new RegExp("^((" + words.join(")|(") + "))\\\\b");\n
@@ -33,7 +46,7 @@ CodeMirror.defineMode("octave", function() {\n
   var doubleDelimiters = new RegExp("^((!=)|(\\\\+=)|(\\\\-=)|(\\\\*=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))");\n
   var tripleDelimiters = new RegExp("^((>>=)|(<<=))");\n
   var expressionEnd = new RegExp("^[\\\\]\\\\)]");\n
-  var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");\n
+  var identifiers = new RegExp("^[_A-Za-z\\xa1-\\uffff][_A-Za-z0-9\\xa1-\\uffff]*");\n
 \n
   var builtins = wordRegexp([\n
     \'error\', \'eval\', \'function\', \'abs\', \'acos\', \'atan\', \'asin\', \'cos\',\n
@@ -142,6 +155,8 @@ CodeMirror.defineMode("octave", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-octave", "octave");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -152,7 +167,7 @@ CodeMirror.defineMIME("text/x-octave", "octave");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3980</int> </value>
+            <value> <int>4463</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pascal/pascal.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pascal/pascal.js.xml
index e3a0a498280cedeaa4c003a99d9275a5af5029cc..447d644e8812d504aff5f3c1145261796f778e0d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pascal/pascal.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pascal/pascal.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403096.38</string> </value>
+            <value> <string>ts21897138.2</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("pascal", function() {\n
   function words(str) {\n
     var obj = {}, words = str.split(" ");\n
@@ -116,6 +129,8 @@ CodeMirror.defineMode("pascal", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-pascal", "pascal");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -126,7 +141,7 @@ CodeMirror.defineMIME("text/x-pascal", "pascal");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2594</int> </value>
+            <value> <int>3055</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pegjs/pegjs.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pegjs/pegjs.js.xml
index e4a9e4a78386a1d9cb59139320b3460cbd365576..e15fce8cb41e8e1952508296610958474e345349 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pegjs/pegjs.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pegjs/pegjs.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403093.68</string> </value>
+            <value> <string>ts21897141.27</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../javascript/javascript"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../javascript/javascript"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("pegjs", function (config) {\n
   var jsMode = CodeMirror.getMode(config, "javascript");\n
 \n
@@ -121,6 +134,8 @@ CodeMirror.defineMode("pegjs", function (config) {\n
     }\n
   };\n
 }, "javascript");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -131,7 +146,7 @@ CodeMirror.defineMode("pegjs", function (config) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3036</int> </value>
+            <value> <int>3562</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/perl/perl.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/perl/perl.js.xml
index 2014cb60e93ae50d591912b0a512e975e08ae394..f8355183cb5262e1df066616651073ee0f663f45 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/perl/perl.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/perl/perl.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403102.54</string> </value>
+            <value> <string>ts21897132.8</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,8 +22,22 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)\n
 // This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("perl",function(){\n
         // http://perldoc.perl.org\n
         var PERL={                                      //   null - magic touch\n
@@ -533,7 +547,7 @@ CodeMirror.defineMode("perl",function(){\n
                         return tokenSOMETHING(stream,state,\'=cut\');}\n
                 var ch=stream.next();\n
                 if(ch==\'"\'||ch=="\'"){                           // NOTE: \' or " or <<\'SOMETHING\'\\n...\\nSOMETHING\\n or <<"SOMETHING"\\n...\\nSOMETHING\\n\n
-                        if(stream.prefix(3)=="<<"+ch){\n
+                        if(prefix(stream, 3)=="<<"+ch){\n
                                 var p=stream.pos;\n
                                 stream.eatWhile(/\\w/);\n
                                 var n=stream.current().substr(1);\n
@@ -542,94 +556,94 @@ CodeMirror.defineMode("perl",function(){\n
                                 stream.pos=p;}\n
                         return tokenChain(stream,state,[ch],"string");}\n
                 if(ch=="q"){\n
-                        var c=stream.look(-2);\n
+                        var c=look(stream, -2);\n
                         if(!(c&&/\\w/.test(c))){\n
-                                c=stream.look(0);\n
+                                c=look(stream, 0);\n
                                 if(c=="x"){\n
-                                        c=stream.look(1);\n
+                                        c=look(stream, 1);\n
                                         if(c=="("){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}\n
                                         if(c=="["){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}\n
                                         if(c=="{"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}\n
                                         if(c=="<"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}\n
                                         if(/[\\^\'"!~\\/]/.test(c)){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}\n
                                 else if(c=="q"){\n
-                                        c=stream.look(1);\n
+                                        c=look(stream, 1);\n
                                         if(c=="("){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[")"],"string");}\n
                                         if(c=="["){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["]"],"string");}\n
                                         if(c=="{"){\n
-stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["}"],"string");}\n
                                         if(c=="<"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[">"],"string");}\n
                                         if(/[\\^\'"!~\\/]/.test(c)){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,[stream.eat(c)],"string");}}\n
                                 else if(c=="w"){\n
-                                        c=stream.look(1);\n
+                                        c=look(stream, 1);\n
                                         if(c=="("){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[")"],"bracket");}\n
                                         if(c=="["){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["]"],"bracket");}\n
                                         if(c=="{"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["}"],"bracket");}\n
                                         if(c=="<"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[">"],"bracket");}\n
                                         if(/[\\^\'"!~\\/]/.test(c)){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,[stream.eat(c)],"bracket");}}\n
                                 else if(c=="r"){\n
-                                        c=stream.look(1);\n
+                                        c=look(stream, 1);\n
                                         if(c=="("){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}\n
                                         if(c=="["){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}\n
                                         if(c=="{"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}\n
                                         if(c=="<"){\n
-                                                stream.eatSuffix(2);\n
+                                                eatSuffix(stream, 2);\n
                                                 return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}\n
                                         if(/[\\^\'"!~\\/]/.test(c)){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}\n
                                 else if(/[\\^\'"!~\\/(\\[{<]/.test(c)){\n
                                         if(c=="("){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,[")"],"string");}\n
                                         if(c=="["){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,["]"],"string");}\n
                                         if(c=="{"){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,["}"],"string");}\n
                                         if(c=="<"){\n
-                                                stream.eatSuffix(1);\n
+                                                eatSuffix(stream, 1);\n
                                                 return tokenChain(stream,state,[">"],"string");}\n
                                         if(/[\\^\'"!~\\/]/.test(c)){\n
                                                 return tokenChain(stream,state,[stream.eat(c)],"string");}}}}\n
                 if(ch=="m"){\n
-                        var c=stream.look(-2);\n
+                        var c=look(stream, -2);\n
                         if(!(c&&/\\w/.test(c))){\n
                                 c=stream.eat(/[(\\[{<\\^\'"!~\\/]/);\n
                                 if(c){\n
@@ -644,7 +658,7 @@ stream.eatSuffix(2);\n
                                         if(c=="<"){\n
                                                 return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}}\n
                 if(ch=="s"){\n
-                        var c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n
+                        var c=/[\\/>\\]})\\w]/.test(look(stream, -2));\n
                         if(!c){\n
                                 c=stream.eat(/[(\\[{<\\^\'"!~\\/]/);\n
                                 if(c){\n
@@ -658,7 +672,7 @@ stream.eatSuffix(2);\n
                                                 return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);\n
                                         return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}\n
                 if(ch=="y"){\n
-                        var c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n
+                        var c=/[\\/>\\]})\\w]/.test(look(stream, -2));\n
                         if(!c){\n
                                 c=stream.eat(/[(\\[{<\\^\'"!~\\/]/);\n
                                 if(c){\n
@@ -672,7 +686,7 @@ stream.eatSuffix(2);\n
                                                 return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);\n
                                         return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}\n
                 if(ch=="t"){\n
-                        var c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n
+                        var c=/[\\/>\\]})\\w]/.test(look(stream, -2));\n
                         if(!c){\n
                                 c=stream.eat("r");if(c){\n
                                 c=stream.eat(/[(\\[{<\\^\'"!~\\/]/);\n
@@ -689,7 +703,7 @@ stream.eatSuffix(2);\n
                 if(ch=="`"){\n
                         return tokenChain(stream,state,[ch],"variable-2");}\n
                 if(ch=="/"){\n
-                        if(!/~\\s*$/.test(stream.prefix()))\n
+                        if(!/~\\s*$/.test(prefix(stream)))\n
                                 return "operator";\n
                         else\n
                                 return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}\n
@@ -701,7 +715,7 @@ stream.eatSuffix(2);\n
                                 stream.pos=p;}\n
                 if(/[$@%]/.test(ch)){\n
                         var p=stream.pos;\n
-                        if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\\\\-#?@;:&`~\\^!\\[\\]*\'"$+.,\\/<>()]/)){\n
+                        if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\\\\-#?@;:&`~\\^!\\[\\]*\'"$+.,\\/<>()]/)){\n
                                 var c=stream.current();\n
                                 if(PERL[c])\n
                                         return "variable-2";}\n
@@ -714,7 +728,7 @@ stream.eatSuffix(2);\n
                                 else\n
                                         return "variable";}}\n
                 if(ch=="#"){\n
-                        if(stream.look(-2)!="$"){\n
+                        if(look(stream, -2)!="$"){\n
                                 stream.skipToEnd();\n
                                 return "comment";}}\n
                 if(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/.test(ch)){\n
@@ -726,23 +740,23 @@ stream.eatSuffix(2);\n
                                 stream.pos=p;}\n
                 if(ch=="_"){\n
                         if(stream.pos==1){\n
-                                if(stream.suffix(6)=="_END__"){\n
+                                if(suffix(stream, 6)=="_END__"){\n
                                         return tokenChain(stream,state,[\'\\0\'],"comment");}\n
-                                else if(stream.suffix(7)=="_DATA__"){\n
+                                else if(suffix(stream, 7)=="_DATA__"){\n
                                         return tokenChain(stream,state,[\'\\0\'],"variable-2");}\n
-                                else if(stream.suffix(7)=="_C__"){\n
+                                else if(suffix(stream, 7)=="_C__"){\n
                                         return tokenChain(stream,state,[\'\\0\'],"string");}}}\n
                 if(/\\w/.test(ch)){\n
                         var p=stream.pos;\n
-                        if(stream.look(-2)=="{"&&(stream.look(0)=="}"||stream.eatWhile(/\\w/)&&stream.look(0)=="}"))\n
+                        if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\\w/)&&look(stream, 0)=="}"))\n
                                 return "string";\n
                         else\n
                                 stream.pos=p;}\n
                 if(/[A-Z]/.test(ch)){\n
-                        var l=stream.look(-2);\n
+                        var l=look(stream, -2);\n
                         var p=stream.pos;\n
                         stream.eatWhile(/[A-Z_]/);\n
-                        if(/[\\da-z]/.test(stream.look(0))){\n
+                        if(/[\\da-z]/.test(look(stream, 0))){\n
                                 stream.pos=p;}\n
                         else{\n
                                 var c=PERL[stream.current()];\n
@@ -766,7 +780,7 @@ stream.eatSuffix(2);\n
                                 else\n
                                         return "meta";}}\n
                 if(/[a-zA-Z_]/.test(ch)){\n
-                        var l=stream.look(-2);\n
+                        var l=look(stream, -2);\n
                         stream.eatWhile(/\\w/);\n
                         var c=PERL[stream.current()];\n
                         if(!c)\n
@@ -798,46 +812,48 @@ stream.eatSuffix(2);\n
                                 style:null,\n
                                 tail:null};},\n
                 token:function(stream,state){\n
-                        return (state.tokenize||tokenPerl)(stream,state);},\n
-                electricChars:"{}"};});\n
+                        return (state.tokenize||tokenPerl)(stream,state);}\n
+                };});\n
+\n
+CodeMirror.registerHelper("wordChars", "perl", /[\\w$]/);\n
 \n
 CodeMirror.defineMIME("text/x-perl", "perl");\n
 \n
 // it\'s like "peek", but need for look-ahead or look-behind if index < 0\n
-CodeMirror.StringStream.prototype.look=function(c){\n
-        return this.string.charAt(this.pos+(c||0));};\n
+function look(stream, c){\n
+  return stream.string.charAt(stream.pos+(c||0));\n
+}\n
 \n
 // return a part of prefix of current stream from current position\n
-CodeMirror.StringStream.prototype.prefix=function(c){\n
-        if(c){\n
-                var x=this.pos-c;\n
-                return this.string.substr((x>=0?x:0),c);}\n
-        else{\n
-                return this.string.substr(0,this.pos-1);}};\n
+function prefix(stream, c){\n
+  if(c){\n
+    var x=stream.pos-c;\n
+    return stream.string.substr((x>=0?x:0),c);}\n
+  else{\n
+    return stream.string.substr(0,stream.pos-1);\n
+  }\n
+}\n
 \n
 // return a part of suffix of current stream from current position\n
-CodeMirror.StringStream.prototype.suffix=function(c){\n
-        var y=this.string.length;\n
-        var x=y-this.pos+1;\n
-        return this.string.substr(this.pos,(c&&c<y?c:x));};\n
-\n
-// return a part of suffix of current stream from current position and change current position\n
-CodeMirror.StringStream.prototype.nsuffix=function(c){\n
-        var p=this.pos;\n
-        var l=c||(this.string.length-this.pos+1);\n
-        this.pos+=l;\n
-        return this.string.substr(p,l);};\n
+function suffix(stream, c){\n
+  var y=stream.string.length;\n
+  var x=y-stream.pos+1;\n
+  return stream.string.substr(stream.pos,(c&&c<y?c:x));\n
+}\n
 \n
 // eating and vomiting a part of stream from current position\n
-CodeMirror.StringStream.prototype.eatSuffix=function(c){\n
-        var x=this.pos+c;\n
-        var y;\n
-        if(x<=0)\n
-                this.pos=0;\n
-        else if(x>=(y=this.string.length-1))\n
-                this.pos=y;\n
-        else\n
-                this.pos=x;};\n
+function eatSuffix(stream, c){\n
+  var x=stream.pos+c;\n
+  var y;\n
+  if(x<=0)\n
+    stream.pos=0;\n
+  else if(x>=(y=stream.string.length-1))\n
+    stream.pos=y;\n
+  else\n
+    stream.pos=x;\n
+}\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -848,7 +864,7 @@ CodeMirror.StringStream.prototype.eatSuffix=function(c){\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>56029</int> </value>
+            <value> <int>56126</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/php.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/php.js.xml
index 44cebb86e0f5976aa242b0f1c3e2098cd311a19b..71c5f096fb3ccb3e09341f1cf84d3c50c3158fbc 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/php.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/php.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403097.31</string> </value>
+            <value> <string>ts21897137.42</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,30 +22,104 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-(function() {\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
   function keywords(str) {\n
     var obj = {}, words = str.split(" ");\n
     for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
     return obj;\n
   }\n
-  function heredoc(delim) {\n
-    return function(stream, state) {\n
-      if (stream.match(delim)) state.tokenize = null;\n
-      else stream.skipToEnd();\n
+\n
+  // Helper for stringWithEscapes\n
+  function matchSequence(list, end) {\n
+    if (list.length == 0) return stringWithEscapes(end);\n
+    return function (stream, state) {\n
+      var patterns = list[0];\n
+      for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {\n
+        state.tokenize = matchSequence(list.slice(1), end);\n
+        return patterns[i][1];\n
+      }\n
+      state.tokenize = stringWithEscapes(end);\n
       return "string";\n
     };\n
   }\n
+  function stringWithEscapes(closing) {\n
+    return function(stream, state) { return stringWithEscapes_(stream, state, closing); };\n
+  }\n
+  function stringWithEscapes_(stream, state, closing) {\n
+    // "Complex" syntax\n
+    if (stream.match("${", false) || stream.match("{$", false)) {\n
+      state.tokenize = null;\n
+      return "string";\n
+    }\n
+\n
+    // Simple syntax\n
+    if (stream.match(/^\\$[a-zA-Z_][a-zA-Z0-9_]*/)) {\n
+      // After the variable name there may appear array or object operator.\n
+      if (stream.match("[", false)) {\n
+        // Match array operator\n
+        state.tokenize = matchSequence([\n
+          [["[", null]],\n
+          [[/\\d[\\w\\.]*/, "number"],\n
+           [/\\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"],\n
+           [/[\\w\\$]+/, "variable"]],\n
+          [["]", null]]\n
+        ], closing);\n
+      }\n
+      if (stream.match(/\\-\\>\\w/, false)) {\n
+        // Match object operator\n
+        state.tokenize = matchSequence([\n
+          [["->", null]],\n
+          [[/[\\w]+/, "variable"]]\n
+        ], closing);\n
+      }\n
+      return "variable-2";\n
+    }\n
+\n
+    var escaped = false;\n
+    // Normal string\n
+    while (!stream.eol() &&\n
+           (escaped || (!stream.match("{$", false) &&\n
+                        !stream.match(/^(\\$[a-zA-Z_][a-zA-Z0-9_]*|\\$\\{)/, false)))) {\n
+      if (!escaped && stream.match(closing)) {\n
+        state.tokenize = null;\n
+        state.tokStack.pop(); state.tokStack.pop();\n
+        break;\n
+      }\n
+      escaped = stream.next() == "\\\\" && !escaped;\n
+    }\n
+    return "string";\n
+  }\n
+\n
+  var phpKeywords = "abstract and array as break case catch class clone const continue declare default " +\n
+    "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +\n
+    "for foreach function global goto if implements interface instanceof namespace " +\n
+    "new or private protected public static switch throw trait try use var while xor " +\n
+    "die echo empty exit eval include include_once isset list require require_once return " +\n
+    "print unset __halt_compiler self static parent yield insteadof finally";\n
+  var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";\n
+  var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";\n
+  CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));\n
+  CodeMirror.registerHelper("wordChars", "php", /[\\w$]/);\n
+\n
   var phpConfig = {\n
     name: "clike",\n
-    keywords: keywords("abstract and array as break case catch class clone const continue declare default " +\n
-                       "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +\n
-                       "for foreach function global goto if implements interface instanceof namespace " +\n
-                       "new or private protected public static switch throw trait try use var while xor " +\n
-                       "die echo empty exit eval include include_once isset list require require_once return " +\n
-                       "print unset __halt_compiler self static parent yield insteadof finally"),\n
+    helperType: "php",\n
+    keywords: keywords(phpKeywords),\n
     blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"),\n
-    atoms: keywords("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__"),\n
-    builtin: keywords("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once"),\n
+    atoms: keywords(phpAtoms),\n
+    builtin: keywords(phpBuiltin),\n
     multiLineStrings: true,\n
     hooks: {\n
       "$": function(stream) {\n
@@ -55,8 +129,12 @@
       "<": function(stream, state) {\n
         if (stream.match(/<</)) {\n
           stream.eatWhile(/[\\w\\.]/);\n
-          state.tokenize = heredoc(stream.current().slice(3));\n
-          return state.tokenize(stream, state);\n
+          var delim = stream.current().slice(3);\n
+          if (delim) {\n
+            (state.tokStack || (state.tokStack = [])).push(delim, 0);\n
+            state.tokenize = stringWithEscapes(delim);\n
+            return "string";\n
+          }\n
         }\n
         return false;\n
       },\n
@@ -70,6 +148,23 @@
           return "comment";\n
         }\n
         return false;\n
+      },\n
+      \'"\': function(_stream, state) {\n
+        (state.tokStack || (state.tokStack = [])).push(\'"\', 0);\n
+        state.tokenize = stringWithEscapes(\'"\');\n
+        return "string";\n
+      },\n
+      "{": function(_stream, state) {\n
+        if (state.tokStack && state.tokStack.length)\n
+          state.tokStack[state.tokStack.length - 1]++;\n
+        return false;\n
+      },\n
+      "}": function(_stream, state) {\n
+        if (state.tokStack && state.tokStack.length > 0 &&\n
+            !--state.tokStack[state.tokStack.length - 1]) {\n
+          state.tokenize = stringWithEscapes(state.tokStack[state.tokStack.length - 2]);\n
+        }\n
+        return false;\n
       }\n
     }\n
   };\n
@@ -152,7 +247,7 @@
   CodeMirror.defineMIME("application/x-httpd-php", "php");\n
   CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});\n
   CodeMirror.defineMIME("text/x-php", phpConfig);\n
-})();\n
+});\n
 
 
 ]]></string> </value>
@@ -163,7 +258,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>12563</int> </value>
+            <value> <int>17661</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2d5299f30aacdb4f4e7e145ba11fe9393e0b4453
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/php/test.js.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897137.21</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
+  var mode = CodeMirror.getMode({indentUnit: 2}, "php");\n
+  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
+\n
+  MT(\'simple_test\',\n
+     \'[meta <?php] \' +\n
+     \'[keyword echo] [string "aaa"]; \' +\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_non_alphanumeric\',\n
+     \'[meta <?php]\',\n
+     \'[keyword echo] [string "aaa$~$!$@$#$$$%$^$&$*$($)$.$<$>$/$\\\\$}$\\\\\\"$:$;$?$|$[[$]]$+$=aaa"]\',\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_digits\',\n
+     \'[meta <?php]\',\n
+     \'[keyword echo] [string "aaa$1$2$3$4$5$6$7$8$9$0aaa"]\',\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_simple_syntax_1\',\n
+     \'[meta <?php]\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaa][string .aaa"];\',\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_simple_syntax_2\',\n
+     \'[meta <?php]\',\n
+     \'[keyword echo] [string "][variable-2 $aaaa][[\',\'[number 2]\',         \']][string aa"];\',\n
+     \'[keyword echo] [string "][variable-2 $aaaa][[\',\'[number 2345]\',      \']][string aa"];\',\n
+     \'[keyword echo] [string "][variable-2 $aaaa][[\',\'[number 2.3]\',       \']][string aa"];\',\n
+     \'[keyword echo] [string "][variable-2 $aaaa][[\',\'[variable aaaaa]\',   \']][string aa"];\',\n
+     \'[keyword echo] [string "][variable-2 $aaaa][[\',\'[variable-2 $aaaaa]\',\']][string aa"];\',\n
+\n
+     \'[keyword echo] [string "1aaa][variable-2 $aaaa][[\',\'[number 2]\',         \']][string aa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa][[\',\'[number 2345]\',      \']][string aa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa][[\',\'[number 2.3]\',       \']][string aa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa][[\',\'[variable aaaaa]\',   \']][string aa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa][[\',\'[variable-2 $aaaaa]\',\']][string aa"];\',\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_simple_syntax_3\',\n
+     \'[meta <?php]\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string .aaaaaa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa][string ->][variable-2 $aaaaa][string .aaaaaa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string [[2]].aaaaaa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string ->aaaa2.aaaaaa"];\',\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_escaping\',\n
+     \'[meta <?php] [comment /* Escaping */]\',\n
+     \'[keyword echo] [string "aaa\\\\$aaaa->aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa\\\\$aaaa[[2]]aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa\\\\$aaaa[[asd]]aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa{\\\\$aaaa->aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa{\\\\$aaaa[[2]]aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa{\\\\aaaaa[[asd]]aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa\\\\${aaaa->aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa\\\\${aaaa[[2]]aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa\\\\${aaaa[[asd]]aaa.aaa"];\',\n
+     \'[meta ?>]\');\n
+\n
+  MT(\'variable_interpolation_complex_syntax_1\',\n
+     \'[meta <?php]\',\n
+     \'[keyword echo] [string "aaa][variable-2 $]{[variable aaaa]}[string ->aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa]}[string ->aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa][[\',\'  [number 42]\',\']]}[string ->aaa.aaa"];\',\n
+     \'[keyword echo] [string "aaa][variable-2 $]{[variable aaaa][meta ?>]aaaaaa\');\n
+\n
+  MT(\'variable_interpolation_complex_syntax_2\',\n
+     \'[meta <?php] [comment /* Monsters */]\',\n
+     \'[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>} $aaa<?php } */]}[string ->aaa.aaa"];\',\n
+     \'[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>*/][[\',\'  [string "aaa][variable-2 $aaa][string {}][variable-2 $]{[variable aaa]}[string "]\',\']]}[string ->aaa.aaa"];\',\n
+     \'[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*} } $aaa } */]}[string ->aaa.aaa"];\');\n
+\n
+\n
+  function build_recursive_monsters(nt, t, n){\n
+    var monsters = [t];\n
+    for (var i = 1; i <= n; ++i)\n
+      monsters[i] = nt.join(monsters[i - 1]);\n
+    return monsters;\n
+  }\n
+\n
+  var m1 = build_recursive_monsters(\n
+    [\'[string "][variable-2 $]{[variable aaa] [operator +] \', \'}[string "]\'],\n
+    \'[comment /* }?>} */] [string "aaa][variable-2 $aaa][string .aaa"]\',\n
+    10\n
+  );\n
+\n
+  MT(\'variable_interpolation_complex_syntax_3_1\',\n
+     \'[meta <?php] [comment /* Recursive monsters */]\',\n
+     \'[keyword echo] \' + m1[4] + \';\',\n
+     \'[keyword echo] \' + m1[7] + \';\',\n
+     \'[keyword echo] \' + m1[8] + \';\',\n
+     \'[keyword echo] \' + m1[5] + \';\',\n
+     \'[keyword echo] \' + m1[1] + \';\',\n
+     \'[keyword echo] \' + m1[6] + \';\',\n
+     \'[keyword echo] \' + m1[9] + \';\',\n
+     \'[keyword echo] \' + m1[0] + \';\',\n
+     \'[keyword echo] \' + m1[10] + \';\',\n
+     \'[keyword echo] \' + m1[2] + \';\',\n
+     \'[keyword echo] \' + m1[3] + \';\',\n
+     \'[keyword echo] [string "end"];\',\n
+     \'[meta ?>]\');\n
+\n
+  var m2 = build_recursive_monsters(\n
+    [\'[string "a][variable-2 $]{[variable aaa] [operator +] \', \' [operator +] \', \'}[string .a"]\'],\n
+    \'[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]\',\n
+    5\n
+  );\n
+\n
+  MT(\'variable_interpolation_complex_syntax_3_2\',\n
+     \'[meta <?php] [comment /* Recursive monsters 2 */]\',\n
+     \'[keyword echo] \' + m2[0] + \';\',\n
+     \'[keyword echo] \' + m2[1] + \';\',\n
+     \'[keyword echo] \' + m2[5] + \';\',\n
+     \'[keyword echo] \' + m2[4] + \';\',\n
+     \'[keyword echo] \' + m2[2] + \';\',\n
+     \'[keyword echo] \' + m2[3] + \';\',\n
+     \'[keyword echo] [string "end"];\',\n
+     \'[meta ?>]\');\n
+\n
+  function build_recursive_monsters_2(mf1, mf2, nt, t, n){\n
+    var monsters = [t];\n
+    for (var i = 1; i <= n; ++i)\n
+      monsters[i] = nt[0] + mf1[i - 1] + nt[1] + mf2[i - 1] + nt[2] + monsters[i - 1] + nt[3];\n
+    return monsters;\n
+  }\n
+\n
+  var m3 = build_recursive_monsters_2(\n
+    m1,\n
+    m2,\n
+    [\'[string "a][variable-2 $]{[variable aaa] [operator +] \', \' [operator +] \', \' [operator +] \', \'}[string .a"]\'],\n
+    \'[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]\',\n
+    4\n
+  );\n
+\n
+  MT(\'variable_interpolation_complex_syntax_3_3\',\n
+     \'[meta <?php] [comment /* Recursive monsters 2 */]\',\n
+     \'[keyword echo] \' + m3[4] + \';\',\n
+     \'[keyword echo] \' + m3[0] + \';\',\n
+     \'[keyword echo] \' + m3[3] + \';\',\n
+     \'[keyword echo] \' + m3[1] + \';\',\n
+     \'[keyword echo] \' + m3[2] + \';\',\n
+     \'[keyword echo] [string "end"];\',\n
+     \'[meta ?>]\');\n
+\n
+  MT("variable_interpolation_heredoc",\n
+     "[meta <?php]",\n
+     "[string <<<here]",\n
+     "[string doc ][variable-2 $]{[variable yay]}[string more]",\n
+     "[string here]; [comment // normal]");\n
+})();\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>6637</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pig/pig.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pig/pig.js.xml
index 9cb2b41dff26677cf1c3d17d94abb279d5dd3d2f..3ad015c51c8869d3313b2d47cd102108ba103410 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pig/pig.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/pig/pig.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403094.51</string> </value>
+            <value> <string>ts21897140.05</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,12 +22,25 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*\n
  *      Pig Latin Mode for CodeMirror 2\n
  *      @author Prasanth Jayachandran\n
  *      @link   https://github.com/prasanthj/pig-codemirror-2\n
  *  This implementation is adapted from PL/SQL mode in CodeMirror 2.\n
  */\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("pig", function(_config, parserConfig) {\n
   var keywords = parserConfig.keywords,\n
   builtins = parserConfig.builtins,\n
@@ -192,7 +205,11 @@ CodeMirror.defineMode("pig", function(_config, parserConfig) {\n
     keywords: keywords(pKeywords),\n
     types: keywords(pTypes)\n
   });\n
+\n
+  CodeMirror.registerHelper("hintWords", "pig", (pBuiltins + pTypes + pKeywords).split(" "));\n
 }());\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -203,7 +220,7 @@ CodeMirror.defineMode("pig", function(_config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5556</int> </value>
+            <value> <int>6112</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/properties/properties.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/properties/properties.js.xml
index 18e8dedaf0070f57fb41d355d1a8e8bfe5dbac5f..3d314dad1a4e4cf7116e10b59128cb7d608dac60 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/properties/properties.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/properties/properties.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403092.3</string> </value>
+            <value> <string>ts21897142.78</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("properties", function() {\n
   return {\n
     token: function(stream, state) {\n
@@ -85,6 +98,8 @@ CodeMirror.defineMode("properties", function() {\n
 \n
 CodeMirror.defineMIME("text/x-properties", "properties");\n
 CodeMirror.defineMIME("text/x-ini", "properties");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -95,7 +110,7 @@ CodeMirror.defineMIME("text/x-ini", "properties");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>1734</int> </value>
+            <value> <int>2195</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/puppet/puppet.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/puppet/puppet.js.xml
index 074bf43d04a3ed27263f10195b3e76393813bbaf..f7bdbb2e114fd22258a2502fd59a28d0617941e0 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/puppet/puppet.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/puppet/puppet.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403100.42</string> </value>
+            <value> <string>ts21897134.39</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("puppet", function () {\n
   // Stores the words from the define method\n
   var words = {};\n
@@ -151,11 +164,11 @@ CodeMirror.defineMode("puppet", function () {\n
       return words[word];\n
     }\n
     // Is there a match on a reference?\n
-    if (/(\\s+)?[A-Z]/.test(word)) {\n
+    if (/(^|\\s+)[A-Z][\\w:_]+/.test(word)) {\n
       // Negate the next()\n
       stream.backUp(1);\n
       // Match the full reference\n
-      stream.match(/(\\s+)?[A-Z][\\w:_]+/);\n
+      stream.match(/(^|\\s+)[A-Z][\\w:_]+/);\n
       return \'def\';\n
     }\n
     // Have we matched the prior resource regex?\n
@@ -187,7 +200,7 @@ CodeMirror.defineMode("puppet", function () {\n
     // Match characters that we are going to assume\n
     // are trying to be regex\n
     if (ch == \'/\') {\n
-      stream.match(/.*\\//);\n
+      stream.match(/.*?\\//);\n
       return \'variable-3\';\n
     }\n
     // Match all the numbers\n
@@ -225,7 +238,10 @@ CodeMirror.defineMode("puppet", function () {\n
     }\n
   };\n
 });\n
+\n
 CodeMirror.defineMIME("text/x-puppet", "puppet");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -236,7 +252,7 @@ CodeMirror.defineMIME("text/x-puppet", "puppet");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7102</int> </value>
+            <value> <int>7574</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/python/python.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/python/python.js.xml
index bb7a02cff192f9a16a3e70bd07ee01f2ff2df34c..9dcc5004075974e11984965d8c969e55ec3c5089 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/python/python.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/python/python.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403097.94</string> </value>
+            <value> <string>ts21897136.51</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,376 +22,356 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-CodeMirror.defineMode("python", function(conf, parserConf) {\n
-    var ERRORCLASS = \'error\';\n
-\n
-    function wordRegexp(words) {\n
-        return new RegExp("^((" + words.join(")|(") + "))\\\\b");\n
-    }\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
 \n
-    var singleOperators = parserConf.singleOperators || new RegExp("^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!]");\n
-    var singleDelimiters = parserConf.singleDelimiters || new RegExp(\'^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]\');\n
+  function wordRegexp(words) {\n
+    return new RegExp("^((" + words.join(")|(") + "))\\\\b");\n
+  }\n
+\n
+  var wordOperators = wordRegexp(["and", "or", "not", "is"]);\n
+  var commonKeywords = ["as", "assert", "break", "class", "continue",\n
+                        "def", "del", "elif", "else", "except", "finally",\n
+                        "for", "from", "global", "if", "import",\n
+                        "lambda", "pass", "raise", "return",\n
+                        "try", "while", "with", "yield", "in"];\n
+  var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",\n
+                        "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",\n
+                        "enumerate", "eval", "filter", "float", "format", "frozenset",\n
+                        "getattr", "globals", "hasattr", "hash", "help", "hex", "id",\n
+                        "input", "int", "isinstance", "issubclass", "iter", "len",\n
+                        "list", "locals", "map", "max", "memoryview", "min", "next",\n
+                        "object", "oct", "open", "ord", "pow", "property", "range",\n
+                        "repr", "reversed", "round", "set", "setattr", "slice",\n
+                        "sorted", "staticmethod", "str", "sum", "super", "tuple",\n
+                        "type", "vars", "zip", "__import__", "NotImplemented",\n
+                        "Ellipsis", "__debug__"];\n
+  var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile",\n
+                        "file", "intern", "long", "raw_input", "reduce", "reload",\n
+                        "unichr", "unicode", "xrange", "False", "True", "None"],\n
+             keywords: ["exec", "print"]};\n
+  var py3 = {builtins: ["ascii", "bytes", "exec", "print"],\n
+             keywords: ["nonlocal", "False", "True", "None"]};\n
+\n
+  CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));\n
+\n
+  function top(state) {\n
+    return state.scopes[state.scopes.length - 1];\n
+  }\n
+\n
+  CodeMirror.defineMode("python", function(conf, parserConf) {\n
+    var ERRORCLASS = "error";\n
+\n
+    var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]");\n
     var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\\\*\\\\*))");\n
     var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))");\n
     var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\\\*\\\\*=))");\n
-    var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");\n
-    var hangingIndent = parserConf.hangingIndent || parserConf.indentUnit;\n
-\n
-    var wordOperators = wordRegexp([\'and\', \'or\', \'not\', \'is\', \'in\']);\n
-    var commonkeywords = [\'as\', \'assert\', \'break\', \'class\', \'continue\',\n
-                          \'def\', \'del\', \'elif\', \'else\', \'except\', \'finally\',\n
-                          \'for\', \'from\', \'global\', \'if\', \'import\',\n
-                          \'lambda\', \'pass\', \'raise\', \'return\',\n
-                          \'try\', \'while\', \'with\', \'yield\'];\n
-    var commonBuiltins = [\'abs\', \'all\', \'any\', \'bin\', \'bool\', \'bytearray\', \'callable\', \'chr\',\n
-                          \'classmethod\', \'compile\', \'complex\', \'delattr\', \'dict\', \'dir\', \'divmod\',\n
-                          \'enumerate\', \'eval\', \'filter\', \'float\', \'format\', \'frozenset\',\n
-                          \'getattr\', \'globals\', \'hasattr\', \'hash\', \'help\', \'hex\', \'id\',\n
-                          \'input\', \'int\', \'isinstance\', \'issubclass\', \'iter\', \'len\',\n
-                          \'list\', \'locals\', \'map\', \'max\', \'memoryview\', \'min\', \'next\',\n
-                          \'object\', \'oct\', \'open\', \'ord\', \'pow\', \'property\', \'range\',\n
-                          \'repr\', \'reversed\', \'round\', \'set\', \'setattr\', \'slice\',\n
-                          \'sorted\', \'staticmethod\', \'str\', \'sum\', \'super\', \'tuple\',\n
-                          \'type\', \'vars\', \'zip\', \'__import__\', \'NotImplemented\',\n
-                          \'Ellipsis\', \'__debug__\'];\n
-    var py2 = {\'builtins\': [\'apply\', \'basestring\', \'buffer\', \'cmp\', \'coerce\', \'execfile\',\n
-                            \'file\', \'intern\', \'long\', \'raw_input\', \'reduce\', \'reload\',\n
-                            \'unichr\', \'unicode\', \'xrange\', \'False\', \'True\', \'None\'],\n
-               \'keywords\': [\'exec\', \'print\']};\n
-    var py3 = {\'builtins\': [\'ascii\', \'bytes\', \'exec\', \'print\'],\n
-               \'keywords\': [\'nonlocal\', \'False\', \'True\', \'None\']};\n
 \n
+    if (parserConf.version && parseInt(parserConf.version, 10) == 3){\n
+        // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator\n
+        var singleOperators = parserConf.singleOperators || new RegExp("^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!@]");\n
+        var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\\u00A1-\\uFFFF][_A-Za-z0-9\\u00A1-\\uFFFF]*");\n
+    } else {\n
+        var singleOperators = parserConf.singleOperators || new RegExp("^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!]");\n
+        var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");\n
+    }\n
+\n
+    var hangingIndent = parserConf.hangingIndent || conf.indentUnit;\n
+\n
+    var myKeywords = commonKeywords, myBuiltins = commonBuiltins;\n
     if(parserConf.extra_keywords != undefined){\n
-        commonkeywords = commonkeywords.concat(parserConf.extra_keywords);\n
+      myKeywords = myKeywords.concat(parserConf.extra_keywords);\n
     }\n
     if(parserConf.extra_builtins != undefined){\n
-        commonBuiltins = commonBuiltins.concat(parserConf.extra_builtins);\n
+      myBuiltins = myBuiltins.concat(parserConf.extra_builtins);\n
     }\n
-    if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) {\n
-        commonkeywords = commonkeywords.concat(py3.keywords);\n
-        commonBuiltins = commonBuiltins.concat(py3.builtins);\n
-        var stringPrefixes = new RegExp("^(([rb]|(br))?(\'{3}|\\"{3}|[\'\\"]))", "i");\n
+    if (parserConf.version && parseInt(parserConf.version, 10) == 3) {\n
+      myKeywords = myKeywords.concat(py3.keywords);\n
+      myBuiltins = myBuiltins.concat(py3.builtins);\n
+      var stringPrefixes = new RegExp("^(([rb]|(br))?(\'{3}|\\"{3}|[\'\\"]))", "i");\n
     } else {\n
-        commonkeywords = commonkeywords.concat(py2.keywords);\n
-        commonBuiltins = commonBuiltins.concat(py2.builtins);\n
-        var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?(\'{3}|\\"{3}|[\'\\"]))", "i");\n
+      myKeywords = myKeywords.concat(py2.keywords);\n
+      myBuiltins = myBuiltins.concat(py2.builtins);\n
+      var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?(\'{3}|\\"{3}|[\'\\"]))", "i");\n
     }\n
-    var keywords = wordRegexp(commonkeywords);\n
-    var builtins = wordRegexp(commonBuiltins);\n
-\n
-    var indentInfo = null;\n
+    var keywords = wordRegexp(myKeywords);\n
+    var builtins = wordRegexp(myBuiltins);\n
 \n
     // tokenizers\n
     function tokenBase(stream, state) {\n
-        // Handle scope changes\n
-        if (stream.sol()) {\n
-            var scopeOffset = state.scopes[0].offset;\n
-            if (stream.eatSpace()) {\n
-                var lineOffset = stream.indentation();\n
-                if (lineOffset > scopeOffset) {\n
-                    indentInfo = \'indent\';\n
-                } else if (lineOffset < scopeOffset) {\n
-                    indentInfo = \'dedent\';\n
-                }\n
-                return null;\n
-            } else {\n
-                if (scopeOffset > 0) {\n
-                    dedent(stream, state);\n
-                }\n
-            }\n
-        }\n
+      // Handle scope changes\n
+      if (stream.sol() && top(state).type == "py") {\n
+        var scopeOffset = top(state).offset;\n
         if (stream.eatSpace()) {\n
-            return null;\n
+          var lineOffset = stream.indentation();\n
+          if (lineOffset > scopeOffset)\n
+            pushScope(stream, state, "py");\n
+          else if (lineOffset < scopeOffset && dedent(stream, state))\n
+            state.errorToken = true;\n
+          return null;\n
+        } else {\n
+          var style = tokenBaseInner(stream, state);\n
+          if (scopeOffset > 0 && dedent(stream, state))\n
+            style += " " + ERRORCLASS;\n
+          return style;\n
         }\n
+      }\n
+      return tokenBaseInner(stream, state);\n
+    }\n
 \n
-        var ch = stream.peek();\n
-\n
-        // Handle Comments\n
-        if (ch === \'#\') {\n
-            stream.skipToEnd();\n
-            return \'comment\';\n
+    function tokenBaseInner(stream, state) {\n
+      if (stream.eatSpace()) return null;\n
+\n
+      var ch = stream.peek();\n
+\n
+      // Handle Comments\n
+      if (ch == "#") {\n
+        stream.skipToEnd();\n
+        return "comment";\n
+      }\n
+\n
+      // Handle Number Literals\n
+      if (stream.match(/^[0-9\\.]/, false)) {\n
+        var floatLiteral = false;\n
+        // Floats\n
+        if (stream.match(/^\\d*\\.\\d+(e[\\+\\-]?\\d+)?/i)) { floatLiteral = true; }\n
+        if (stream.match(/^\\d+\\.\\d*/)) { floatLiteral = true; }\n
+        if (stream.match(/^\\.\\d+/)) { floatLiteral = true; }\n
+        if (floatLiteral) {\n
+          // Float literals may be "imaginary"\n
+          stream.eat(/J/i);\n
+          return "number";\n
         }\n
-\n
-        // Handle Number Literals\n
-        if (stream.match(/^[0-9\\.]/, false)) {\n
-            var floatLiteral = false;\n
-            // Floats\n
-            if (stream.match(/^\\d*\\.\\d+(e[\\+\\-]?\\d+)?/i)) { floatLiteral = true; }\n
-            if (stream.match(/^\\d+\\.\\d*/)) { floatLiteral = true; }\n
-            if (stream.match(/^\\.\\d+/)) { floatLiteral = true; }\n
-            if (floatLiteral) {\n
-                // Float literals may be "imaginary"\n
-                stream.eat(/J/i);\n
-                return \'number\';\n
-            }\n
-            // Integers\n
-            var intLiteral = false;\n
-            // Hex\n
-            if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }\n
-            // Binary\n
-            if (stream.match(/^0b[01]+/i)) { intLiteral = true; }\n
-            // Octal\n
-            if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }\n
-            // Decimal\n
-            if (stream.match(/^[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n
-                // Decimal literals may be "imaginary"\n
-                stream.eat(/J/i);\n
-                // TODO - Can you have imaginary longs?\n
-                intLiteral = true;\n
-            }\n
-            // Zero by itself with no other piece of number.\n
-            if (stream.match(/^0(?![\\dx])/i)) { intLiteral = true; }\n
-            if (intLiteral) {\n
-                // Integer literals may be "long"\n
-                stream.eat(/L/i);\n
-                return \'number\';\n
-            }\n
+        // Integers\n
+        var intLiteral = false;\n
+        // Hex\n
+        if (stream.match(/^0x[0-9a-f]+/i)) intLiteral = true;\n
+        // Binary\n
+        if (stream.match(/^0b[01]+/i)) intLiteral = true;\n
+        // Octal\n
+        if (stream.match(/^0o[0-7]+/i)) intLiteral = true;\n
+        // Decimal\n
+        if (stream.match(/^[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n
+          // Decimal literals may be "imaginary"\n
+          stream.eat(/J/i);\n
+          // TODO - Can you have imaginary longs?\n
+          intLiteral = true;\n
         }\n
-\n
-        // Handle Strings\n
-        if (stream.match(stringPrefixes)) {\n
-            state.tokenize = tokenStringFactory(stream.current());\n
-            return state.tokenize(stream, state);\n
+        // Zero by itself with no other piece of number.\n
+        if (stream.match(/^0(?![\\dx])/i)) intLiteral = true;\n
+        if (intLiteral) {\n
+          // Integer literals may be "long"\n
+          stream.eat(/L/i);\n
+          return "number";\n
         }\n
+      }\n
 \n
-        // Handle operators and Delimiters\n
-        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {\n
-            return null;\n
-        }\n
-        if (stream.match(doubleOperators)\n
-            || stream.match(singleOperators)\n
-            || stream.match(wordOperators)) {\n
-            return \'operator\';\n
-        }\n
-        if (stream.match(singleDelimiters)) {\n
-            return null;\n
-        }\n
+      // Handle Strings\n
+      if (stream.match(stringPrefixes)) {\n
+        state.tokenize = tokenStringFactory(stream.current());\n
+        return state.tokenize(stream, state);\n
+      }\n
 \n
-        if (stream.match(keywords)) {\n
-            return \'keyword\';\n
-        }\n
+      // Handle operators and Delimiters\n
+      if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))\n
+        return null;\n
 \n
-        if (stream.match(builtins)) {\n
-            return \'builtin\';\n
-        }\n
+      if (stream.match(doubleOperators)\n
+          || stream.match(singleOperators)\n
+          || stream.match(wordOperators))\n
+        return "operator";\n
 \n
-        if (stream.match(/^(self|cls)\\b/)) {\n
-            return "variable-2";\n
-        }\n
+      if (stream.match(singleDelimiters))\n
+        return null;\n
 \n
-        if (stream.match(identifiers)) {\n
-            if (state.lastToken == \'def\' || state.lastToken == \'class\') {\n
-                return \'def\';\n
-            }\n
-            return \'variable\';\n
-        }\n
+      if (stream.match(keywords))\n
+        return "keyword";\n
+\n
+      if (stream.match(builtins))\n
+        return "builtin";\n
+\n
+      if (stream.match(/^(self|cls)\\b/))\n
+        return "variable-2";\n
 \n
-        // Handle non-detected items\n
-        stream.next();\n
-        return ERRORCLASS;\n
+      if (stream.match(identifiers)) {\n
+        if (state.lastToken == "def" || state.lastToken == "class")\n
+          return "def";\n
+        return "variable";\n
+      }\n
+\n
+      // Handle non-detected items\n
+      stream.next();\n
+      return ERRORCLASS;\n
     }\n
 \n
     function tokenStringFactory(delimiter) {\n
-        while (\'rub\'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {\n
-            delimiter = delimiter.substr(1);\n
-        }\n
-        var singleline = delimiter.length == 1;\n
-        var OUTCLASS = \'string\';\n
-\n
-        function tokenString(stream, state) {\n
-            while (!stream.eol()) {\n
-                stream.eatWhile(/[^\'"\\\\]/);\n
-                if (stream.eat(\'\\\\\')) {\n
-                    stream.next();\n
-                    if (singleline && stream.eol()) {\n
-                        return OUTCLASS;\n
-                    }\n
-                } else if (stream.match(delimiter)) {\n
-                    state.tokenize = tokenBase;\n
-                    return OUTCLASS;\n
-                } else {\n
-                    stream.eat(/[\'"]/);\n
-                }\n
-            }\n
-            if (singleline) {\n
-                if (parserConf.singleLineStringErrors) {\n
-                    return ERRORCLASS;\n
-                } else {\n
-                    state.tokenize = tokenBase;\n
-                }\n
-            }\n
+      while ("rub".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)\n
+        delimiter = delimiter.substr(1);\n
+\n
+      var singleline = delimiter.length == 1;\n
+      var OUTCLASS = "string";\n
+\n
+      function tokenString(stream, state) {\n
+        while (!stream.eol()) {\n
+          stream.eatWhile(/[^\'"\\\\]/);\n
+          if (stream.eat("\\\\")) {\n
+            stream.next();\n
+            if (singleline && stream.eol())\n
+              return OUTCLASS;\n
+          } else if (stream.match(delimiter)) {\n
+            state.tokenize = tokenBase;\n
             return OUTCLASS;\n
+          } else {\n
+            stream.eat(/[\'"]/);\n
+          }\n
+        }\n
+        if (singleline) {\n
+          if (parserConf.singleLineStringErrors)\n
+            return ERRORCLASS;\n
+          else\n
+            state.tokenize = tokenBase;\n
         }\n
-        tokenString.isString = true;\n
-        return tokenString;\n
+        return OUTCLASS;\n
+      }\n
+      tokenString.isString = true;\n
+      return tokenString;\n
     }\n
 \n
-    function indent(stream, state, type) {\n
-        type = type || \'py\';\n
-        var indentUnit = 0;\n
-        if (type === \'py\') {\n
-            if (state.scopes[0].type !== \'py\') {\n
-                state.scopes[0].offset = stream.indentation();\n
-                return;\n
-            }\n
-            for (var i = 0; i < state.scopes.length; ++i) {\n
-                if (state.scopes[i].type === \'py\') {\n
-                    indentUnit = state.scopes[i].offset + conf.indentUnit;\n
-                    break;\n
-                }\n
-            }\n
-        } else if (stream.match(/\\s*($|#)/, false)) {\n
-            // An open paren/bracket/brace with only space or comments after it\n
-            // on the line will indent the next line a fixed amount, to make it\n
-            // easier to put arguments, list items, etc. on their own lines.\n
-            indentUnit = stream.indentation() + hangingIndent;\n
-        } else {\n
-            indentUnit = stream.column() + stream.current().length;\n
-        }\n
-        state.scopes.unshift({\n
-            offset: indentUnit,\n
-            type: type\n
-        });\n
+    function pushScope(stream, state, type) {\n
+      var offset = 0, align = null;\n
+      if (type == "py") {\n
+        while (top(state).type != "py")\n
+          state.scopes.pop();\n
+      }\n
+      offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent);\n
+      if (type != "py" && !stream.match(/^(\\s|#.*)*$/, false))\n
+        align = stream.column() + 1;\n
+      state.scopes.push({offset: offset, type: type, align: align});\n
     }\n
 \n
-    function dedent(stream, state, type) {\n
-        type = type || \'py\';\n
-        if (state.scopes.length == 1) return;\n
-        if (state.scopes[0].type === \'py\') {\n
-            var _indent = stream.indentation();\n
-            var _indent_index = -1;\n
-            for (var i = 0; i < state.scopes.length; ++i) {\n
-                if (_indent === state.scopes[i].offset) {\n
-                    _indent_index = i;\n
-                    break;\n
-                }\n
-            }\n
-            if (_indent_index === -1) {\n
-                return true;\n
-            }\n
-            while (state.scopes[0].offset !== _indent) {\n
-                state.scopes.shift();\n
-            }\n
-            return false;\n
-        } else {\n
-            if (type === \'py\') {\n
-                state.scopes[0].offset = stream.indentation();\n
-                return false;\n
-            } else {\n
-                if (state.scopes[0].type != type) {\n
-                    return true;\n
-                }\n
-                state.scopes.shift();\n
-                return false;\n
-            }\n
-        }\n
+    function dedent(stream, state) {\n
+      var indented = stream.indentation();\n
+      while (top(state).offset > indented) {\n
+        if (top(state).type != "py") return true;\n
+        state.scopes.pop();\n
+      }\n
+      return top(state).offset != indented;\n
     }\n
 \n
     function tokenLexer(stream, state) {\n
-        indentInfo = null;\n
-        var style = state.tokenize(stream, state);\n
-        var current = stream.current();\n
-\n
-        // Handle \'.\' connected identifiers\n
-        if (current === \'.\') {\n
-            style = stream.match(identifiers, false) ? null : ERRORCLASS;\n
-            if (style === null && state.lastStyle === \'meta\') {\n
-                // Apply \'meta\' style to \'.\' connected identifiers when\n
-                // appropriate.\n
-                style = \'meta\';\n
-            }\n
-            return style;\n
-        }\n
-\n
-        // Handle decorators\n
-        if (current === \'@\') {\n
-            return stream.match(identifiers, false) ? \'meta\' : ERRORCLASS;\n
-        }\n
-\n
-        if ((style === \'variable\' || style === \'builtin\')\n
-            && state.lastStyle === \'meta\') {\n
-            style = \'meta\';\n
+      var style = state.tokenize(stream, state);\n
+      var current = stream.current();\n
+\n
+      // Handle \'.\' connected identifiers\n
+      if (current == ".") {\n
+        style = stream.match(identifiers, false) ? null : ERRORCLASS;\n
+        if (style == null && state.lastStyle == "meta") {\n
+          // Apply \'meta\' style to \'.\' connected identifiers when\n
+          // appropriate.\n
+          style = "meta";\n
         }\n
+        return style;\n
+      }\n
 \n
-        // Handle scope changes.\n
-        if (current === \'pass\' || current === \'return\') {\n
-            state.dedent += 1;\n
-        }\n
-        if (current === \'lambda\') state.lambda = true;\n
-        if ((current === \':\' && !state.lambda && state.scopes[0].type == \'py\')\n
-            || indentInfo === \'indent\') {\n
-            indent(stream, state);\n
-        }\n
-        var delimiter_index = \'[({\'.indexOf(current);\n
-        if (delimiter_index !== -1) {\n
-            indent(stream, state, \'])}\'.slice(delimiter_index, delimiter_index+1));\n
-        }\n
-        if (indentInfo === \'dedent\') {\n
-            if (dedent(stream, state)) {\n
-                return ERRORCLASS;\n
-            }\n
-        }\n
-        delimiter_index = \'])}\'.indexOf(current);\n
-        if (delimiter_index !== -1) {\n
-            if (dedent(stream, state, current)) {\n
-                return ERRORCLASS;\n
-            }\n
-        }\n
-        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == \'py\') {\n
-            if (state.scopes.length > 1) state.scopes.shift();\n
-            state.dedent -= 1;\n
+      // Handle decorators\n
+      if (current == "@"){\n
+        if(parserConf.version && parseInt(parserConf.version, 10) == 3){\n
+            return stream.match(identifiers, false) ? "meta" : "operator";\n
+        } else {\n
+            return stream.match(identifiers, false) ? "meta" : ERRORCLASS;\n
         }\n
-\n
-        return style;\n
+      }\n
+\n
+      if ((style == "variable" || style == "builtin")\n
+          && state.lastStyle == "meta")\n
+        style = "meta";\n
+\n
+      // Handle scope changes.\n
+      if (current == "pass" || current == "return")\n
+        state.dedent += 1;\n
+\n
+      if (current == "lambda") state.lambda = true;\n
+      if (current == ":" && !state.lambda && top(state).type == "py")\n
+        pushScope(stream, state, "py");\n
+\n
+      var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1;\n
+      if (delimiter_index != -1)\n
+        pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));\n
+\n
+      delimiter_index = "])}".indexOf(current);\n
+      if (delimiter_index != -1) {\n
+        if (top(state).type == current) state.scopes.pop();\n
+        else return ERRORCLASS;\n
+      }\n
+      if (state.dedent > 0 && stream.eol() && top(state).type == "py") {\n
+        if (state.scopes.length > 1) state.scopes.pop();\n
+        state.dedent -= 1;\n
+      }\n
+\n
+      return style;\n
     }\n
 \n
     var external = {\n
-        startState: function(basecolumn) {\n
-            return {\n
-              tokenize: tokenBase,\n
-              scopes: [{offset:basecolumn || 0, type:\'py\'}],\n
-              lastStyle: null,\n
-              lastToken: null,\n
-              lambda: false,\n
-              dedent: 0\n
-          };\n
-        },\n
-\n
-        token: function(stream, state) {\n
-            var style = tokenLexer(stream, state);\n
-\n
-            state.lastStyle = style;\n
-\n
-            var current = stream.current();\n
-            if (current && style) {\n
-                state.lastToken = current;\n
-            }\n
-\n
-            if (stream.eol() && state.lambda) {\n
-                state.lambda = false;\n
-            }\n
-            return style;\n
-        },\n
-\n
-        indent: function(state) {\n
-            if (state.tokenize != tokenBase) {\n
-                return state.tokenize.isString ? CodeMirror.Pass : 0;\n
-            }\n
-\n
-            return state.scopes[0].offset;\n
-        },\n
-\n
-        lineComment: "#",\n
-        fold: "indent"\n
+      startState: function(basecolumn) {\n
+        return {\n
+          tokenize: tokenBase,\n
+          scopes: [{offset: basecolumn || 0, type: "py", align: null}],\n
+          lastStyle: null,\n
+          lastToken: null,\n
+          lambda: false,\n
+          dedent: 0\n
+        };\n
+      },\n
+\n
+      token: function(stream, state) {\n
+        var addErr = state.errorToken;\n
+        if (addErr) state.errorToken = false;\n
+        var style = tokenLexer(stream, state);\n
+\n
+        state.lastStyle = style;\n
+\n
+        var current = stream.current();\n
+        if (current && style)\n
+          state.lastToken = current;\n
+\n
+        if (stream.eol() && state.lambda)\n
+          state.lambda = false;\n
+        return addErr ? style + " " + ERRORCLASS : style;\n
+      },\n
+\n
+      indent: function(state, textAfter) {\n
+        if (state.tokenize != tokenBase)\n
+          return state.tokenize.isString ? CodeMirror.Pass : 0;\n
+\n
+        var scope = top(state);\n
+        var closing = textAfter && textAfter.charAt(0) == scope.type;\n
+        if (scope.align != null)\n
+          return scope.align - (closing ? 1 : 0);\n
+        else if (closing && state.scopes.length > 1)\n
+          return state.scopes[state.scopes.length - 2].offset;\n
+        else\n
+          return scope.offset;\n
+      },\n
+\n
+      lineComment: "#",\n
+      fold: "indent"\n
     };\n
     return external;\n
-});\n
+  });\n
 \n
-CodeMirror.defineMIME("text/x-python", "python");\n
+  CodeMirror.defineMIME("text/x-python", "python");\n
 \n
-(function() {\n
-  "use strict";\n
-  var words = function(str){return str.split(\' \');};\n
+  var words = function(str) { return str.split(" "); };\n
 \n
   CodeMirror.defineMIME("text/x-cython", {\n
     name: "python",\n
@@ -399,7 +379,8 @@ CodeMirror.defineMIME("text/x-python", "python");\n
                           "extern gil include nogil property public"+\n
                           "readonly struct union DEF IF ELIF ELSE")\n
   });\n
-})();\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -410,7 +391,7 @@ CodeMirror.defineMIME("text/x-python", "python");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>13699</int> </value>
+            <value> <int>12869</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/q/q.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/q/q.js.xml
index 49ba780348b9068884180e50f7afdf65e069ed83..dd36e8d4082e3cb209a41e88e19ea71033015057 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/q/q.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/q/q.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403089.57</string> </value>
+            <value> <string>ts21897146.04</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("q",function(config){\n
   var indentUnit=config.indentUnit,\n
       curPunc,\n
@@ -146,6 +159,8 @@ CodeMirror.defineMode("q",function(config){\n
   };\n
 });\n
 CodeMirror.defineMIME("text/x-q","q");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -156,7 +171,7 @@ CodeMirror.defineMIME("text/x-q","q");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6156</int> </value>
+            <value> <int>6617</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/r/r.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/r/r.js.xml
index b2781086393ca4c170c0ef02a9df91a08b943bd5..f97b274db3872f1de0af7a77c9d1efa0e72adcfa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/r/r.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/r/r.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403086.35</string> </value>
+            <value> <string>ts21897149.78</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("r", function(config) {\n
   function wordObj(str) {\n
     var words = str.split(" "), res = {};\n
@@ -162,11 +175,15 @@ CodeMirror.defineMode("r", function(config) {\n
       if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit);\n
       else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n
       else return ctx.indent + (closing ? 0 : config.indentUnit);\n
-    }\n
+    },\n
+\n
+    lineComment: "#"\n
   };\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-rsrc", "r");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -177,7 +194,7 @@ CodeMirror.defineMIME("text/x-rsrc", "r");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5138</int> </value>
+            <value> <int>5622</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes.xml
index bbc37e37a39e7cc2abc8bc95c4dcbda3566a47ed..21ccfaeed0c2e72837bff8fcdf2698dde9d666a1 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes.xml
@@ -6,12 +6,6 @@
     </pickle>
     <pickle>
       <dictionary>
-        <item>
-            <key> <string>_objects</string> </key>
-            <value>
-              <tuple/>
-            </value>
-        </item>
         <item>
             <key> <string>id</string> </key>
             <value> <string>changes</string> </value>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes/changes.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes/changes.js.xml
deleted file mode 100644
index bd4a9bbf90ce1288ea36db7f7a879c6085fb4209..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/changes/changes.js.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="File" module="OFS.Image"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403092.7</string> </value>
-        </item>
-        <item>
-            <key> <string>__name__</string> </key>
-            <value> <string>changes.js</string> </value>
-        </item>
-        <item>
-            <key> <string>content_type</string> </key>
-            <value> <string>application/javascript</string> </value>
-        </item>
-        <item>
-            <key> <string>data</string> </key>
-            <value> <string>CodeMirror.defineMode("changes", function() {\n
-  var headerSeperator = /^-+$/;\n
-  var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)  ?\\d{1,2} \\d{2}:\\d{2}(:\\d{2})? [A-Z]{3,4} \\d{4} - /;\n
-  var simpleEmail = /^[\\w+.-]+@[\\w.-]+/;\n
-\n
-  return {\n
-    token: function(stream) {\n
-      if (stream.sol()) {\n
-        if (stream.match(headerSeperator)) { return \'tag\'; }\n
-        if (stream.match(headerLine)) { return \'tag\'; }\n
-      }\n
-      if (stream.match(simpleEmail)) { return \'string\'; }\n
-      stream.next();\n
-      return null;\n
-    }\n
-  };\n
-});\n
-\n
-CodeMirror.defineMIME("text/x-rpm-changes", "changes");\n
-</string> </value>
-        </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>636</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec/spec.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/rpm.js.xml
similarity index 72%
rename from bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec/spec.js.xml
rename to bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/rpm.js.xml
index 80e1654c892a12912922097dda86f36a3f82081c..ac4d8f588b72ea626306032eaad293185647a836 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/spec/spec.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rpm/rpm.js.xml
@@ -8,11 +8,11 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403092.4</string> </value>
+            <value> <string>ts21897142.68</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
-            <value> <string>spec.js</string> </value>
+            <value> <string>rpm.js</string> </value>
         </item>
         <item>
             <key> <string>content_type</string> </key>
@@ -22,9 +22,42 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode("rpm-changes", function() {\n
+  var headerSeperator = /^-+$/;\n
+  var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)  ?\\d{1,2} \\d{2}:\\d{2}(:\\d{2})? [A-Z]{3,4} \\d{4} - /;\n
+  var simpleEmail = /^[\\w+.-]+@[\\w.-]+/;\n
+\n
+  return {\n
+    token: function(stream) {\n
+      if (stream.sol()) {\n
+        if (stream.match(headerSeperator)) { return \'tag\'; }\n
+        if (stream.match(headerLine)) { return \'tag\'; }\n
+      }\n
+      if (stream.match(simpleEmail)) { return \'string\'; }\n
+      stream.next();\n
+      return null;\n
+    }\n
+  };\n
+});\n
+\n
+CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes");\n
+\n
 // Quick and dirty spec file highlighting\n
 \n
-CodeMirror.defineMode("spec", function() {\n
+CodeMirror.defineMode("rpm-spec", function() {\n
   var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;\n
 \n
   var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\\(\\w+\\))?|Obsoletes|Conflicts|Recommends|Source\\d*|Patch\\d*|ExclusiveArch|NoSource|Supplements):/;\n
@@ -87,7 +120,9 @@ CodeMirror.defineMode("spec", function() {\n
   };\n
 });\n
 \n
-CodeMirror.defineMIME("text/x-rpm-spec", "spec");\n
+CodeMirror.defineMIME("text/x-rpm-spec", "rpm-spec");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -98,7 +133,7 @@ CodeMirror.defineMIME("text/x-rpm-spec", "spec");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2703</int> </value>
+            <value> <int>3817</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rst/rst.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rst/rst.js.xml
index 55d3625857c0468731216aa7beca747a1a835c74..72b2d88aad9983f58f51b729334ab1957bc2eece 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rst/rst.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rst/rst.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403089.45</string> </value>
+            <value> <string>ts21897146.34</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode(\'rst\', function (config, options) {\n
 \n
   var rx_strong = /^\\*\\*[^\\*\\s](?:[^\\*]*[^\\*\\s])?\\*\\*/;\n
@@ -90,19 +103,6 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
       return typeof args[n] != \'undefined\' ? args[n] : match;\n
     });\n
   }\n
-\n
-  function AssertException(message) {\n
-    this.message = message;\n
-  }\n
-\n
-  AssertException.prototype.toString = function () {\n
-    return \'AssertException: \' + this.message;\n
-  };\n
-\n
-  function assert(expression, message) {\n
-    if (!expression) throw new AssertException(message);\n
-    return expression;\n
-  }\n
 \n
   ///////////////////////////////////////////////////////////////////////////\n
   ///////////////////////////////////////////////////////////////////////////\n
@@ -196,12 +196,12 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_normal, context(rx_role_pre, 1));\n
-        assert(stream.match(/^:/));\n
+        stream.match(/^:/);\n
         token = \'meta\';\n
         break;\n
       case 1:\n
         change(state, to_normal, context(rx_role_pre, 2));\n
-        assert(stream.match(rx_NAME));\n
+        stream.match(rx_NAME);\n
         token = \'keyword\';\n
 \n
         if (stream.current().match(/^(?:math|latex)/)) {\n
@@ -210,7 +210,7 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
         break;\n
       case 2:\n
         change(state, to_normal, context(rx_role_pre, 3));\n
-        assert(stream.match(/^:`/));\n
+        stream.match(/^:`/);\n
         token = \'meta\';\n
         break;\n
       case 3:\n
@@ -232,21 +232,20 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
         }\n
 \n
         change(state, to_normal, context(rx_role_pre, 4));\n
-        assert(stream.match(rx_TEXT2));\n
+        stream.match(rx_TEXT2);\n
         token = \'string\';\n
         break;\n
       case 4:\n
         change(state, to_normal, context(rx_role_pre, 5));\n
-        assert(stream.match(/^`/));\n
+        stream.match(/^`/);\n
         token = \'meta\';\n
         break;\n
       case 5:\n
         change(state, to_normal, context(rx_role_pre, 6));\n
-        assert(stream.match(rx_TAIL));\n
+        stream.match(rx_TAIL);\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (phase(state) == rx_role_suf ||\n
                stream.match(rx_role_suf, false)) {\n
@@ -254,62 +253,60 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_normal, context(rx_role_suf, 1));\n
-        assert(stream.match(/^`/));\n
+        stream.match(/^`/);\n
         token = \'meta\';\n
         break;\n
       case 1:\n
         change(state, to_normal, context(rx_role_suf, 2));\n
-        assert(stream.match(rx_TEXT2));\n
+        stream.match(rx_TEXT2);\n
         token = \'string\';\n
         break;\n
       case 2:\n
         change(state, to_normal, context(rx_role_suf, 3));\n
-        assert(stream.match(/^`:/));\n
+        stream.match(/^`:/);\n
         token = \'meta\';\n
         break;\n
       case 3:\n
         change(state, to_normal, context(rx_role_suf, 4));\n
-        assert(stream.match(rx_NAME));\n
+        stream.match(rx_NAME);\n
         token = \'keyword\';\n
         break;\n
       case 4:\n
         change(state, to_normal, context(rx_role_suf, 5));\n
-        assert(stream.match(/^:/));\n
+        stream.match(/^:/);\n
         token = \'meta\';\n
         break;\n
       case 5:\n
         change(state, to_normal, context(rx_role_suf, 6));\n
-        assert(stream.match(rx_TAIL));\n
+        stream.match(rx_TAIL);\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (phase(state) == rx_role || stream.match(rx_role, false)) {\n
 \n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_normal, context(rx_role, 1));\n
-        assert(stream.match(/^:/));\n
+        stream.match(/^:/);\n
         token = \'meta\';\n
         break;\n
       case 1:\n
         change(state, to_normal, context(rx_role, 2));\n
-        assert(stream.match(rx_NAME));\n
+        stream.match(rx_NAME);\n
         token = \'keyword\';\n
         break;\n
       case 2:\n
         change(state, to_normal, context(rx_role, 3));\n
-        assert(stream.match(/^:/));\n
+        stream.match(/^:/);\n
         token = \'meta\';\n
         break;\n
       case 3:\n
         change(state, to_normal, context(rx_role, 4));\n
-        assert(stream.match(rx_TAIL));\n
+        stream.match(rx_TAIL);\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (phase(state) == rx_substitution_ref ||\n
                stream.match(rx_substitution_ref, false)) {\n
@@ -317,7 +314,7 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_normal, context(rx_substitution_ref, 1));\n
-        assert(stream.match(rx_substitution_text));\n
+        stream.match(rx_substitution_text);\n
         token = \'variable-2\';\n
         break;\n
       case 1:\n
@@ -326,7 +323,6 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (stream.match(rx_footnote_ref)) {\n
       change(state, to_normal);\n
@@ -352,21 +348,20 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
         break;\n
       case 1:\n
         change(state, to_normal, context(rx_link_ref2, 2));\n
-        assert(stream.match(/^`/));\n
+        stream.match(/^`/);\n
         token = \'link\';\n
         break;\n
       case 2:\n
         change(state, to_normal, context(rx_link_ref2, 3));\n
-        assert(stream.match(rx_TEXT2));\n
+        stream.match(rx_TEXT2);\n
         break;\n
       case 3:\n
         change(state, to_normal, context(rx_link_ref2, 4));\n
-        assert(stream.match(/^`_/));\n
+        stream.match(/^`_/);\n
         token = \'link\';\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (stream.match(rx_verbatim)) {\n
       change(state, to_verbatim);\n
@@ -391,26 +386,25 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_explicit, context(rx_substitution, 1));\n
-        assert(stream.match(rx_substitution_text));\n
+        stream.match(rx_substitution_text);\n
         token = \'variable-2\';\n
         break;\n
       case 1:\n
         change(state, to_explicit, context(rx_substitution, 2));\n
-        assert(stream.match(rx_substitution_sepa));\n
+        stream.match(rx_substitution_sepa);\n
         break;\n
       case 2:\n
         change(state, to_explicit, context(rx_substitution, 3));\n
-        assert(stream.match(rx_substitution_name));\n
+        stream.match(rx_substitution_name);\n
         token = \'keyword\';\n
         break;\n
       case 3:\n
         change(state, to_explicit, context(rx_substitution, 4));\n
-        assert(stream.match(rx_substitution_tail));\n
+        stream.match(rx_substitution_tail);\n
         token = \'meta\';\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (phase(state) == rx_directive ||\n
                stream.match(rx_directive, false)) {\n
@@ -418,7 +412,7 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_explicit, context(rx_directive, 1));\n
-        assert(stream.match(rx_directive_name));\n
+        stream.match(rx_directive_name);\n
         token = \'keyword\';\n
 \n
         if (stream.current().match(/^(?:math|latex)/))\n
@@ -428,7 +422,7 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
         break;\n
       case 1:\n
         change(state, to_explicit, context(rx_directive, 2));\n
-        assert(stream.match(rx_directive_tail));\n
+        stream.match(rx_directive_tail);\n
         token = \'meta\';\n
 \n
         if (stream.match(/^latex\\s*$/) || state.tmp_stex) {\n
@@ -447,25 +441,23 @@ CodeMirror.defineMode(\'rst-base\', function (config) {\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (phase(state) == rx_link || stream.match(rx_link, false)) {\n
 \n
       switch (stage(state)) {\n
       case 0:\n
         change(state, to_explicit, context(rx_link, 1));\n
-        assert(stream.match(rx_link_head));\n
-        assert(stream.match(rx_link_name));\n
+        stream.match(rx_link_head);\n
+        stream.match(rx_link_name);\n
         token = \'link\';\n
         break;\n
       case 1:\n
         change(state, to_explicit, context(rx_link, 2));\n
-        assert(stream.match(rx_link_tail));\n
+        stream.match(rx_link_tail);\n
         token = \'meta\';\n
         break;\n
       default:\n
         change(state, to_normal);\n
-        assert(stream.current() == \'\');\n
       }\n
     } else if (stream.match(rx_footnote)) {\n
       change(state, to_normal);\n
@@ -585,6 +577,8 @@ CodeMirror.defineMIME(\'text/x-rst\', \'rst\');\n
 \n
 ///////////////////////////////////////////////////////////////////////////////\n
 ///////////////////////////////////////////////////////////////////////////////\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -595,7 +589,7 @@ CodeMirror.defineMIME(\'text/x-rst\', \'rst\');\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>17786</int> </value>
+            <value> <int>17547</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/ruby.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/ruby.js.xml
index 86d704e4101db25214d7ea3fcc7220274dda1d14..7a2906f676d4eb4c8e6668bc52368d361e512967 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/ruby.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/ruby.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403091.96</string> </value>
+            <value> <string>ts21897143.12</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("ruby", function(config) {\n
   function wordObj(words) {\n
     var o = {};\n
@@ -57,16 +70,30 @@ CodeMirror.defineMode("ruby", function(config) {\n
     var ch = stream.next(), m;\n
     if (ch == "`" || ch == "\'" || ch == \'"\') {\n
       return chain(readQuoted(ch, "string", ch == \'"\' || ch == "`"), stream, state);\n
-    } else if (ch == "/" && !stream.eol() && stream.peek() != " ") {\n
-      if (stream.eat("=")) return "operator";\n
-      return chain(readQuoted(ch, "string-2", true), stream, state);\n
+    } else if (ch == "/") {\n
+      var currentIndex = stream.current().length;\n
+      if (stream.skipTo("/")) {\n
+        var search_till = stream.current().length;\n
+        stream.backUp(stream.current().length - currentIndex);\n
+        var balance = 0;  // balance brackets\n
+        while (stream.current().length < search_till) {\n
+          var chchr = stream.next();\n
+          if (chchr == "(") balance += 1;\n
+          else if (chchr == ")") balance -= 1;\n
+          if (balance < 0) break;\n
+        }\n
+        stream.backUp(stream.current().length - currentIndex);\n
+        if (balance == 0)\n
+          return chain(readQuoted(ch, "string-2", true), stream, state);\n
+      }\n
+      return "operator";\n
     } else if (ch == "%") {\n
       var style = "string", embed = true;\n
       if (stream.eat("s")) style = "atom";\n
       else if (stream.eat(/[WQ]/)) style = "string";\n
       else if (stream.eat(/[r]/)) style = "string-2";\n
       else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; }\n
-      var delim = stream.eat(/[^\\w\\s]/);\n
+      var delim = stream.eat(/[^\\w\\s=]/);\n
       if (!delim) return "operator";\n
       if (matching.propertyIsEnumerable(delim)) delim = matching[delim];\n
       return chain(readQuoted(delim, style, embed, true), stream, state);\n
@@ -104,16 +131,16 @@ CodeMirror.defineMode("ruby", function(config) {\n
       }\n
 \n
       // Symbols can\'t start by a digit\n
-      if (stream.eat(/[a-zA-Z$@_]/)) {\n
-        stream.eatWhile(/[\\w]/);\n
+      if (stream.eat(/[a-zA-Z$@_\\xa1-\\uffff]/)) {\n
+        stream.eatWhile(/[\\w$\\xa1-\\uffff]/);\n
         // Only one ? ! = is allowed and only as the last character\n
         stream.eat(/[\\?\\!\\=]/);\n
         return "atom";\n
       }\n
       return "operator";\n
-    } else if (ch == "@" && stream.match(/^@?[a-zA-Z_]/)) {\n
+    } else if (ch == "@" && stream.match(/^@?[a-zA-Z_\\xa1-\\uffff]/)) {\n
       stream.eat("@");\n
-      stream.eatWhile(/[\\w]/);\n
+      stream.eatWhile(/[\\w\\xa1-\\uffff]/);\n
       return "variable-2";\n
     } else if (ch == "$") {\n
       if (stream.eat(/[a-zA-Z_]/)) {\n
@@ -124,8 +151,8 @@ CodeMirror.defineMode("ruby", function(config) {\n
         stream.next(); // Must be a special global like $: or $!\n
       }\n
       return "variable-3";\n
-    } else if (/[a-zA-Z_]/.test(ch)) {\n
-      stream.eatWhile(/[\\w]/);\n
+    } else if (/[a-zA-Z_\\xa1-\\uffff]/.test(ch)) {\n
+      stream.eatWhile(/[\\w\\xa1-\\uffff]/);\n
       stream.eat(/[\\?\\!]/);\n
       if (stream.eat(":")) return "atom";\n
       return "ident";\n
@@ -138,24 +165,26 @@ CodeMirror.defineMode("ruby", function(config) {\n
     } else if (ch == "-" && stream.eat(">")) {\n
       return "arrow";\n
     } else if (/[=+\\-\\/*:\\.^%<>~|]/.test(ch)) {\n
-      stream.eatWhile(/[=+\\-\\/*:\\.^%<>~|]/);\n
+      var more = stream.eatWhile(/[=+\\-\\/*:\\.^%<>~|]/);\n
+      if (ch == "." && !more) curPunc = ".";\n
       return "operator";\n
     } else {\n
       return null;\n
     }\n
   }\n
 \n
-  function tokenBaseUntilBrace() {\n
-    var depth = 1;\n
+  function tokenBaseUntilBrace(depth) {\n
+    if (!depth) depth = 1;\n
     return function(stream, state) {\n
       if (stream.peek() == "}") {\n
-        depth--;\n
-        if (depth == 0) {\n
+        if (depth == 1) {\n
           state.tokenize.pop();\n
           return state.tokenize[state.tokenize.length-1](stream, state);\n
+        } else {\n
+          state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1);\n
         }\n
       } else if (stream.peek() == "{") {\n
-        depth++;\n
+        state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1);\n
       }\n
       return tokenBase(stream, state);\n
     };\n
@@ -229,20 +258,25 @@ CodeMirror.defineMode("ruby", function(config) {\n
     token: function(stream, state) {\n
       if (stream.sol()) state.indented = stream.indentation();\n
       var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;\n
+      var thisTok = curPunc;\n
       if (style == "ident") {\n
         var word = stream.current();\n
-        style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"\n
+        style = state.lastTok == "." ? "property"\n
+          : keywords.propertyIsEnumerable(stream.current()) ? "keyword"\n
           : /^[A-Z]/.test(word) ? "tag"\n
           : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"\n
           : "variable";\n
-        if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";\n
-        else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";\n
-        else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())\n
-          kwtype = "indent";\n
-        else if (word == "do" && state.context.indented < state.indented)\n
-          kwtype = "indent";\n
+        if (style == "keyword") {\n
+          thisTok = word;\n
+          if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";\n
+          else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";\n
+          else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())\n
+            kwtype = "indent";\n
+          else if (word == "do" && state.context.indented < state.indented)\n
+            kwtype = "indent";\n
+        }\n
       }\n
-      if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;\n
+      if (curPunc || (style && style != "comment")) state.lastTok = thisTok;\n
       if (curPunc == "|") state.varList = !state.varList;\n
 \n
       if (kwtype == "indent" || /[\\(\\[\\{]/.test(curPunc))\n
@@ -272,6 +306,7 @@ CodeMirror.defineMode("ruby", function(config) {\n
 \n
 CodeMirror.defineMIME("text/x-ruby", "ruby");\n
 \n
+});\n
 
 
 ]]></string> </value>
@@ -282,7 +317,7 @@ CodeMirror.defineMIME("text/x-ruby", "ruby");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9048</int> </value>
+            <value> <int>10445</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/test.js.xml
index a1f6d90125b96f1edaddcff415711fa38a9130a5..53a081db64fb0c3396ff3ba5adc7e8cf9259cb59 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/ruby/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403091.86</string> </value>
+            <value> <string>ts21897143.26</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,10 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>(function() {\n
+            <value> <string>// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
   var mode = CodeMirror.getMode({indentUnit: 2}, "ruby");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
 \n
@@ -39,7 +42,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>342</int> </value>
+            <value> <int>470</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rust/rust.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rust/rust.js.xml
index 25d60cc821f44a06ab89e68099f8686eef9c8085..d1c3a12d3518fdb7d9a9f8fe74cd791099e8b05b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rust/rust.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/rust/rust.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403093.83</string> </value>
+            <value> <string>ts21897140.79</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("rust", function() {\n
   var indentUnit = 4, altIndentUnit = 2;\n
   var valKeywords = {\n
-    "if": "if-style", "while": "if-style", "else": "else-style",\n
+    "if": "if-style", "while": "if-style", "loop": "else-style", "else": "else-style",\n
     "do": "else-style", "ret": "else-style", "fail": "else-style",\n
     "break": "atom", "cont": "atom", "const": "let", "resource": "fn",\n
     "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface",\n
@@ -33,7 +46,7 @@ CodeMirror.defineMode("rust", function() {\n
     "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",\n
     "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",\n
     "export": "else-style", "copy": "op", "log": "op", "log_err": "op",\n
-    "use": "op", "bind": "op", "self": "atom"\n
+    "use": "op", "bind": "op", "self": "atom", "struct": "enum"\n
   };\n
   var typeKeywords = function() {\n
     var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};\n
@@ -458,6 +471,8 @@ CodeMirror.defineMode("rust", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-rustsrc", "rust");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -468,7 +483,7 @@ CodeMirror.defineMIME("text/x-rustsrc", "rust");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>15543</int> </value>
+            <value> <int>16044</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sass/sass.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sass/sass.js.xml
index e1ccdb74913cca02030e63500c84e93ee3f37120..6822ccc8e81c60a139656690544985289fb81d9e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sass/sass.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sass/sass.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403091.19</string> </value>
+            <value> <string>ts21897144.11</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("sass", function(config) {\n
-  var tokenRegexp = function(words){\n
+  function tokenRegexp(words) {\n
     return new RegExp("^" + words.join("|"));\n
-  };\n
+  }\n
 \n
   var keywords = ["true", "false", "null", "auto"];\n
   var keywordsRegexp = new RegExp("^" + keywords.join("|"));\n
@@ -35,246 +48,233 @@ CodeMirror.defineMode("sass", function(config) {\n
 \n
   var pseudoElementsRegexp = /^::?[\\w\\-]+/;\n
 \n
-  var urlTokens = function(stream, state){\n
+  function urlTokens(stream, state) {\n
     var ch = stream.peek();\n
 \n
-    if (ch === ")"){\n
+    if (ch === ")") {\n
       stream.next();\n
       state.tokenizer = tokenBase;\n
       return "operator";\n
-    }else if (ch === "("){\n
+    } else if (ch === "(") {\n
       stream.next();\n
       stream.eatSpace();\n
 \n
       return "operator";\n
-    }else if (ch === "\'" || ch === \'"\'){\n
+    } else if (ch === "\'" || ch === \'"\') {\n
       state.tokenizer = buildStringTokenizer(stream.next());\n
       return "string";\n
-    }else{\n
+    } else {\n
       state.tokenizer = buildStringTokenizer(")", false);\n
       return "string";\n
     }\n
-  };\n
-  var multilineComment = function(stream, state) {\n
-    if (stream.skipTo("*/")){\n
-      stream.next();\n
-      stream.next();\n
-      state.tokenizer = tokenBase;\n
-    }else {\n
-      stream.next();\n
-    }\n
+  }\n
+  function comment(indentation, multiLine) {\n
+    return function(stream, state) {\n
+      if (stream.sol() && stream.indentation() <= indentation) {\n
+        state.tokenizer = tokenBase;\n
+        return tokenBase(stream, state);\n
+      }\n
 \n
-    return "comment";\n
-  };\n
+      if (multiLine && stream.skipTo("*/")) {\n
+        stream.next();\n
+        stream.next();\n
+        state.tokenizer = tokenBase;\n
+      } else {\n
+        stream.next();\n
+      }\n
+\n
+      return "comment";\n
+    };\n
+  }\n
 \n
-  var buildStringTokenizer = function(quote, greedy){\n
-    if(greedy == null){ greedy = true; }\n
+  function buildStringTokenizer(quote, greedy) {\n
+    if(greedy == null) { greedy = true; }\n
 \n
-    function stringTokenizer(stream, state){\n
+    function stringTokenizer(stream, state) {\n
       var nextChar = stream.next();\n
       var peekChar = stream.peek();\n
       var previousChar = stream.string.charAt(stream.pos-2);\n
 \n
       var endingString = ((nextChar !== "\\\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\\\"));\n
 \n
-      /*\n
-      console.log("previousChar: " + previousChar);\n
-      console.log("nextChar: " + nextChar);\n
-      console.log("peekChar: " + peekChar);\n
-      console.log("ending: " + endingString);\n
-      */\n
-\n
-      if (endingString){\n
+      if (endingString) {\n
         if (nextChar !== quote && greedy) { stream.next(); }\n
         state.tokenizer = tokenBase;\n
         return "string";\n
-      }else if (nextChar === "#" && peekChar === "{"){\n
+      } else if (nextChar === "#" && peekChar === "{") {\n
         state.tokenizer = buildInterpolationTokenizer(stringTokenizer);\n
         stream.next();\n
         return "operator";\n
-      }else {\n
+      } else {\n
         return "string";\n
       }\n
     }\n
 \n
     return stringTokenizer;\n
-  };\n
+  }\n
 \n
-  var buildInterpolationTokenizer = function(currentTokenizer){\n
-    return function(stream, state){\n
-      if (stream.peek() === "}"){\n
+  function buildInterpolationTokenizer(currentTokenizer) {\n
+    return function(stream, state) {\n
+      if (stream.peek() === "}") {\n
         stream.next();\n
         state.tokenizer = currentTokenizer;\n
         return "operator";\n
-      }else{\n
+      } else {\n
         return tokenBase(stream, state);\n
       }\n
     };\n
-  };\n
+  }\n
 \n
-  var indent = function(state){\n
-    if (state.indentCount == 0){\n
+  function indent(state) {\n
+    if (state.indentCount == 0) {\n
       state.indentCount++;\n
       var lastScopeOffset = state.scopes[0].offset;\n
       var currentOffset = lastScopeOffset + config.indentUnit;\n
       state.scopes.unshift({ offset:currentOffset });\n
     }\n
-  };\n
+  }\n
 \n
-  var dedent = function(state){\n
-    if (state.scopes.length == 1) { return; }\n
+  function dedent(state) {\n
+    if (state.scopes.length == 1) return;\n
 \n
     state.scopes.shift();\n
-  };\n
+  }\n
 \n
-  var tokenBase = function(stream, state) {\n
+  function tokenBase(stream, state) {\n
     var ch = stream.peek();\n
 \n
-    // Single line Comment\n
-    if (stream.match(\'//\')) {\n
-      stream.skipToEnd();\n
-      return "comment";\n
+    // Comment\n
+    if (stream.match("/*")) {\n
+      state.tokenizer = comment(stream.indentation(), true);\n
+      return state.tokenizer(stream, state);\n
     }\n
-\n
-    // Multiline Comment\n
-    if (stream.match(\'/*\')){\n
-      state.tokenizer = multilineComment;\n
+    if (stream.match("//")) {\n
+      state.tokenizer = comment(stream.indentation(), false);\n
       return state.tokenizer(stream, state);\n
     }\n
 \n
     // Interpolation\n
-    if (stream.match(\'#{\')){\n
-    state.tokenizer = buildInterpolationTokenizer(tokenBase);\n
+    if (stream.match("#{")) {\n
+      state.tokenizer = buildInterpolationTokenizer(tokenBase);\n
       return "operator";\n
     }\n
 \n
-    if (ch === "."){\n
+    if (ch === ".") {\n
       stream.next();\n
 \n
       // Match class selectors\n
-      if (stream.match(/^[\\w-]+/)){\n
+      if (stream.match(/^[\\w-]+/)) {\n
         indent(state);\n
         return "atom";\n
-      }else if (stream.peek() === "#"){\n
+      } else if (stream.peek() === "#") {\n
         indent(state);\n
         return "atom";\n
-      }else{\n
+      } else {\n
         return "operator";\n
       }\n
     }\n
 \n
-    if (ch === "#"){\n
+    if (ch === "#") {\n
       stream.next();\n
 \n
       // Hex numbers\n
-      if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){\n
+      if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/))\n
         return "number";\n
-      }\n
 \n
       // ID selectors\n
-      if (stream.match(/^[\\w-]+/)){\n
+      if (stream.match(/^[\\w-]+/)) {\n
         indent(state);\n
         return "atom";\n
       }\n
 \n
-      if (stream.peek() === "#"){\n
+      if (stream.peek() === "#") {\n
         indent(state);\n
         return "atom";\n
       }\n
     }\n
 \n
     // Numbers\n
-    if (stream.match(/^-?[0-9\\.]+/)){\n
+    if (stream.match(/^-?[0-9\\.]+/))\n
       return "number";\n
-    }\n
 \n
     // Units\n
-    if (stream.match(/^(px|em|in)\\b/)){\n
+    if (stream.match(/^(px|em|in)\\b/))\n
       return "unit";\n
-    }\n
 \n
-    if (stream.match(keywordsRegexp)){\n
+    if (stream.match(keywordsRegexp))\n
       return "keyword";\n
-    }\n
 \n
-    if (stream.match(/^url/) && stream.peek() === "("){\n
+    if (stream.match(/^url/) && stream.peek() === "(") {\n
       state.tokenizer = urlTokens;\n
       return "atom";\n
     }\n
 \n
     // Variables\n
-    if (ch === "$"){\n
+    if (ch === "$") {\n
       stream.next();\n
       stream.eatWhile(/[\\w-]/);\n
 \n
-      if (stream.peek() === ":"){\n
+      if (stream.peek() === ":") {\n
         stream.next();\n
         return "variable-2";\n
-      }else{\n
+      } else {\n
         return "variable-3";\n
       }\n
     }\n
 \n
-    if (ch === "!"){\n
+    if (ch === "!") {\n
       stream.next();\n
-\n
-      if (stream.match(/^[\\w]+/)){\n
-        return "keyword";\n
-      }\n
-\n
-      return "operator";\n
+      return stream.match(/^[\\w]+/) ? "keyword": "operator";\n
     }\n
 \n
-    if (ch === "="){\n
+    if (ch === "=") {\n
       stream.next();\n
 \n
       // Match shortcut mixin definition\n
-      if (stream.match(/^[\\w-]+/)){\n
+      if (stream.match(/^[\\w-]+/)) {\n
         indent(state);\n
         return "meta";\n
-      }else {\n
+      } else {\n
         return "operator";\n
       }\n
     }\n
 \n
-    if (ch === "+"){\n
+    if (ch === "+") {\n
       stream.next();\n
 \n
       // Match shortcut mixin definition\n
-      if (stream.match(/^[\\w-]+/)){\n
+      if (stream.match(/^[\\w-]+/))\n
         return "variable-3";\n
-      }else {\n
+      else\n
         return "operator";\n
-      }\n
     }\n
 \n
     // Indent Directives\n
-    if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)){\n
+    if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) {\n
       indent(state);\n
       return "meta";\n
     }\n
 \n
     // Other Directives\n
-    if (ch === "@"){\n
+    if (ch === "@") {\n
       stream.next();\n
       stream.eatWhile(/[\\w-]/);\n
       return "meta";\n
     }\n
 \n
     // Strings\n
-    if (ch === \'"\' || ch === "\'"){\n
+    if (ch === \'"\' || ch === "\'") {\n
       stream.next();\n
       state.tokenizer = buildStringTokenizer(ch);\n
       return "string";\n
     }\n
 \n
     // Pseudo element selectors\n
-    if (ch == \':\' && stream.match(pseudoElementsRegexp)){\n
+    if (ch == ":" && stream.match(pseudoElementsRegexp))\n
       return "keyword";\n
-    }\n
 \n
     // atoms\n
-    if (stream.eatWhile(/[\\w-&]/)){\n
+    if (stream.eatWhile(/[\\w-&]/)) {\n
       // matches a property definition\n
       if (stream.peek() === ":" && !stream.match(pseudoElementsRegexp, false))\n
         return "property";\n
@@ -282,43 +282,37 @@ CodeMirror.defineMode("sass", function(config) {\n
         return "atom";\n
     }\n
 \n
-    if (stream.match(opRegexp)){\n
+    if (stream.match(opRegexp))\n
       return "operator";\n
-    }\n
 \n
     // If we haven\'t returned by now, we move 1 character\n
     // and return an error\n
     stream.next();\n
     return null;\n
-  };\n
+  }\n
 \n
-  var tokenLexer = function(stream, state) {\n
-    if (stream.sol()){\n
-      state.indentCount = 0;\n
-    }\n
+  function tokenLexer(stream, state) {\n
+    if (stream.sol()) state.indentCount = 0;\n
     var style = state.tokenizer(stream, state);\n
     var current = stream.current();\n
 \n
-    if (current === "@return"){\n
+    if (current === "@return")\n
       dedent(state);\n
-    }\n
 \n
-    if (style === "atom"){\n
+    if (style === "atom")\n
       indent(state);\n
-    }\n
 \n
-    if (style !== null){\n
+    if (style !== null) {\n
       var startOfToken = stream.pos - current.length;\n
       var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);\n
 \n
       var newScopes = [];\n
 \n
-      for (var i = 0; i < state.scopes.length; i++){\n
+      for (var i = 0; i < state.scopes.length; i++) {\n
         var scope = state.scopes[i];\n
 \n
-        if (scope.offset <= withCurrentIndent){\n
+        if (scope.offset <= withCurrentIndent)\n
           newScopes.push(scope);\n
-        }\n
       }\n
 \n
       state.scopes = newScopes;\n
@@ -326,13 +320,14 @@ CodeMirror.defineMode("sass", function(config) {\n
 \n
 \n
     return style;\n
-  };\n
+  }\n
 \n
   return {\n
     startState: function() {\n
       return {\n
         tokenizer: tokenBase,\n
-        scopes: [{offset: 0, type: \'sass\'}],\n
+        scopes: [{offset: 0, type: "sass"}],\n
+        indentCount: 0,\n
         definedVars: [],\n
         definedMixins: []\n
       };\n
@@ -352,6 +347,8 @@ CodeMirror.defineMode("sass", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-sass", "sass");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -362,7 +359,7 @@ CodeMirror.defineMIME("text/x-sass", "sass");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7429</int> </value>
+            <value> <int>7831</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/scheme/scheme.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/scheme/scheme.js.xml
index 8df8d46528d6881094dbf00d1a090e6ae0f917c1..559e88a1d24b03315dbd1b01706420fc4940616e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/scheme/scheme.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/scheme/scheme.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403103.47</string> </value>
+            <value> <string>ts21897132.01</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,9 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Author: Koh Zi Han, based on implementation by Koh Zi Chun\n
  */\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("scheme", function () {\n
     var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",\n
         ATOM = "atom", NUMBER = "number", BRACKET = "bracket";\n
@@ -254,6 +268,8 @@ CodeMirror.defineMode("scheme", function () {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-scheme", "scheme");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -264,7 +280,7 @@ CodeMirror.defineMIME("text/x-scheme", "scheme");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>12931</int> </value>
+            <value> <int>13393</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/shell.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/shell.js.xml
index 8ee037645c125ad14e795eb8fc7eeff4c7bcfe66..644778b246893a77c951ee69153d19cfc7c183ee 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/shell.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/shell.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403093.15</string> </value>
+            <value> <string>ts21897142.05</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode(\'shell\', function() {\n
 \n
   var words = {};\n
@@ -47,10 +60,15 @@ CodeMirror.defineMode(\'shell\', function() {\n
     \'touch vi vim wall wc wget who write yes zsh\');\n
 \n
   function tokenBase(stream, state) {\n
+    if (stream.eatSpace()) return null;\n
 \n
     var sol = stream.sol();\n
     var ch = stream.next();\n
 \n
+    if (ch === \'\\\\\') {\n
+      stream.next();\n
+      return null;\n
+    }\n
     if (ch === \'\\\'\' || ch === \'"\' || ch === \'`\') {\n
       state.tokens.unshift(tokenString(ch));\n
       return tokenize(stream, state);\n
@@ -77,7 +95,7 @@ CodeMirror.defineMode(\'shell\', function() {\n
     }\n
     if (/\\d/.test(ch)) {\n
       stream.eatWhile(/\\d/);\n
-      if(!/\\w/.test(stream.peek())) {\n
+      if(stream.eol() || !/\\w/.test(stream.peek())) {\n
         return \'number\';\n
       }\n
     }\n
@@ -133,13 +151,16 @@ CodeMirror.defineMode(\'shell\', function() {\n
   return {\n
     startState: function() {return {tokens:[]};},\n
     token: function(stream, state) {\n
-      if (stream.eatSpace()) return null;\n
       return tokenize(stream, state);\n
-    }\n
+    },\n
+    lineComment: \'#\',\n
+    fold: "brace"\n
   };\n
 });\n
 \n
 CodeMirror.defineMIME(\'text/x-sh\', \'shell\');\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -150,7 +171,7 @@ CodeMirror.defineMIME(\'text/x-sh\', \'shell\');\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3207</int> </value>
+            <value> <int>3792</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44596bb89414f4f50fd68c37d6de8e9680956711
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/shell/test.js.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897142.15</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
+  var mode = CodeMirror.getMode({}, "shell");\n
+  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
+\n
+  MT("var",\n
+     "text [def $var] text");\n
+  MT("varBraces",\n
+     "text[def ${var}]text");\n
+  MT("varVar",\n
+     "text [def $a$b] text");\n
+  MT("varBracesVarBraces",\n
+     "text[def ${a}${b}]text");\n
+\n
+  MT("singleQuotedVar",\n
+     "[string \'text $var text\']");\n
+  MT("singleQuotedVarBraces",\n
+     "[string \'text ${var} text\']");\n
+\n
+  MT("doubleQuotedVar",\n
+     \'[string "text ][def $var][string  text"]\');\n
+  MT("doubleQuotedVarBraces",\n
+     \'[string "text][def ${var}][string text"]\');\n
+  MT("doubleQuotedVarPunct",\n
+     \'[string "text ][def $@][string  text"]\');\n
+  MT("doubleQuotedVarVar",\n
+     \'[string "][def $a$b][string "]\');\n
+  MT("doubleQuotedVarBracesVarBraces",\n
+     \'[string "][def ${a}${b}][string "]\');\n
+\n
+  MT("notAString",\n
+     "text\\\\\'text");\n
+  MT("escapes",\n
+     "outside\\\\\'\\\\\\"\\\\`\\\\\\\\[string \\"inside\\\\`\\\\\'\\\\\\"\\\\\\\\`\\\\$notAVar\\"]outside\\\\$\\\\(notASubShell\\\\)");\n
+\n
+  MT("subshell",\n
+     "[builtin echo] [quote $(whoami)] s log, stardate [quote `date`].");\n
+  MT("doubleQuotedSubshell",\n
+     "[builtin echo] [string \\"][quote $(whoami)][string \'s log, stardate `date`.\\"]");\n
+\n
+  MT("hashbang",\n
+     "[meta #!/bin/bash]");\n
+  MT("comment",\n
+     "text [comment # Blurb]");\n
+\n
+  MT("numbers",\n
+     "[number 0] [number 1] [number 2]");\n
+  MT("keywords",\n
+     "[keyword while] [atom true]; [keyword do]",\n
+     "  [builtin sleep] [number 3]",\n
+     "[keyword done]");\n
+  MT("options",\n
+     "[builtin ls] [attribute -l] [attribute --human-readable]");\n
+  MT("operator",\n
+     "[def var][operator =]value");\n
+})();\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1772</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sieve/sieve.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sieve/sieve.js.xml
index ef9aa0f6e1f905fc77bfced8771ca9381abd039a..c0e522308c5e8a0a8f59c9f1fd0ccd3a285ac622 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sieve/sieve.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sieve/sieve.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403088.49</string> </value>
+            <value> <string>ts21897147.29</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,10 +22,18 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-/*\n
- * See LICENSE in this directory for the license under which this code\n
- * is released.\n
- */\n
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
 \n
 CodeMirror.defineMode("sieve", function(config) {\n
   function words(str) {\n
@@ -205,6 +213,8 @@ CodeMirror.defineMode("sieve", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("application/sieve", "sieve");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -215,7 +225,7 @@ CodeMirror.defineMIME("application/sieve", "sieve");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3919</int> </value>
+            <value> <int>4285</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a7b064e7e8e5496e9dfb007d914999cf0599e64f
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>slim</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim/slim.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim/slim.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e8a85f33a63a4a6eebc075eab44133a1ef8c02b7
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim/slim.js.xml
@@ -0,0 +1,619 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897147.93</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>slim.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+  CodeMirror.defineMode("slim", function(config) {\n
+    var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});\n
+    var rubyMode = CodeMirror.getMode(config, "ruby");\n
+    var modes = { html: htmlMode, ruby: rubyMode };\n
+    var embedded = {\n
+      ruby: "ruby",\n
+      javascript: "javascript",\n
+      css: "text/css",\n
+      sass: "text/x-sass",\n
+      scss: "text/x-scss",\n
+      less: "text/x-less",\n
+      styl: "text/x-styl", // no highlighting so far\n
+      coffee: "coffeescript",\n
+      asciidoc: "text/x-asciidoc",\n
+      markdown: "text/x-markdown",\n
+      textile: "text/x-textile", // no highlighting so far\n
+      creole: "text/x-creole", // no highlighting so far\n
+      wiki: "text/x-wiki", // no highlighting so far\n
+      mediawiki: "text/x-mediawiki", // no highlighting so far\n
+      rdoc: "text/x-rdoc", // no highlighting so far\n
+      builder: "text/x-builder", // no highlighting so far\n
+      nokogiri: "text/x-nokogiri", // no highlighting so far\n
+      erb: "application/x-erb"\n
+    };\n
+    var embeddedRegexp = function(map){\n
+      var arr = [];\n
+      for(var key in map) arr.push(key);\n
+      return new RegExp("^("+arr.join(\'|\')+"):");\n
+    }(embedded);\n
+\n
+    var styleMap = {\n
+      "commentLine": "comment",\n
+      "slimSwitch": "operator special",\n
+      "slimTag": "tag",\n
+      "slimId": "attribute def",\n
+      "slimClass": "attribute qualifier",\n
+      "slimAttribute": "attribute",\n
+      "slimSubmode": "keyword special",\n
+      "closeAttributeTag": null,\n
+      "slimDoctype": null,\n
+      "lineContinuation": null\n
+    };\n
+    var closing = {\n
+      "{": "}",\n
+      "[": "]",\n
+      "(": ")"\n
+    };\n
+\n
+    var nameStartChar = "_a-zA-Z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";\n
+    var nameChar = nameStartChar + "\\\\-0-9\\xB7\\u0300-\\u036F\\u203F-\\u2040";\n
+    var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)");\n
+    var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\\\."+nameChar+"]*(?=\\\\s*=)");\n
+    var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\\\."+nameChar+"]*");\n
+    var classNameRegexp = /^\\.-?[_a-zA-Z]+[\\w\\-]*/;\n
+    var classIdRegexp = /^#[_a-zA-Z]+[\\w\\-]*/;\n
+\n
+    function backup(pos, tokenize, style) {\n
+      var restore = function(stream, state) {\n
+        state.tokenize = tokenize;\n
+        if (stream.pos < pos) {\n
+          stream.pos = pos;\n
+          return style;\n
+        }\n
+        return state.tokenize(stream, state);\n
+      };\n
+      return function(stream, state) {\n
+        state.tokenize = restore;\n
+        return tokenize(stream, state);\n
+      };\n
+    }\n
+\n
+    function maybeBackup(stream, state, pat, offset, style) {\n
+      var cur = stream.current();\n
+      var idx = cur.search(pat);\n
+      if (idx > -1) {\n
+        state.tokenize = backup(stream.pos, state.tokenize, style);\n
+        stream.backUp(cur.length - idx - offset);\n
+      }\n
+      return style;\n
+    }\n
+\n
+    function continueLine(state, column) {\n
+      state.stack = {\n
+        parent: state.stack,\n
+        style: "continuation",\n
+        indented: column,\n
+        tokenize: state.line\n
+      };\n
+      state.line = state.tokenize;\n
+    }\n
+    function finishContinue(state) {\n
+      if (state.line == state.tokenize) {\n
+        state.line = state.stack.tokenize;\n
+        state.stack = state.stack.parent;\n
+      }\n
+    }\n
+\n
+    function lineContinuable(column, tokenize) {\n
+      return function(stream, state) {\n
+        finishContinue(state);\n
+        if (stream.match(/^\\\\$/)) {\n
+          continueLine(state, column);\n
+          return "lineContinuation";\n
+        }\n
+        var style = tokenize(stream, state);\n
+        if (stream.eol() && stream.current().match(/(?:^|[^\\\\])(?:\\\\\\\\)*\\\\$/)) {\n
+          stream.backUp(1);\n
+        }\n
+        return style;\n
+      };\n
+    }\n
+    function commaContinuable(column, tokenize) {\n
+      return function(stream, state) {\n
+        finishContinue(state);\n
+        var style = tokenize(stream, state);\n
+        if (stream.eol() && stream.current().match(/,$/)) {\n
+          continueLine(state, column);\n
+        }\n
+        return style;\n
+      };\n
+    }\n
+\n
+    function rubyInQuote(endQuote, tokenize) {\n
+      // TODO: add multi line support\n
+      return function(stream, state) {\n
+        var ch = stream.peek();\n
+        if (ch == endQuote && state.rubyState.tokenize.length == 1) {\n
+          // step out of ruby context as it seems to complete processing all the braces\n
+          stream.next();\n
+          state.tokenize = tokenize;\n
+          return "closeAttributeTag";\n
+        } else {\n
+          return ruby(stream, state);\n
+        }\n
+      };\n
+    }\n
+    function startRubySplat(tokenize) {\n
+      var rubyState;\n
+      var runSplat = function(stream, state) {\n
+        if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) {\n
+          stream.backUp(1);\n
+          if (stream.eatSpace()) {\n
+            state.rubyState = rubyState;\n
+            state.tokenize = tokenize;\n
+            return tokenize(stream, state);\n
+          }\n
+          stream.next();\n
+        }\n
+        return ruby(stream, state);\n
+      };\n
+      return function(stream, state) {\n
+        rubyState = state.rubyState;\n
+        state.rubyState = rubyMode.startState();\n
+        state.tokenize = runSplat;\n
+        return ruby(stream, state);\n
+      };\n
+    }\n
+\n
+    function ruby(stream, state) {\n
+      return rubyMode.token(stream, state.rubyState);\n
+    }\n
+\n
+    function htmlLine(stream, state) {\n
+      if (stream.match(/^\\\\$/)) {\n
+        return "lineContinuation";\n
+      }\n
+      return html(stream, state);\n
+    }\n
+    function html(stream, state) {\n
+      if (stream.match(/^#\\{/)) {\n
+        state.tokenize = rubyInQuote("}", state.tokenize);\n
+        return null;\n
+      }\n
+      return maybeBackup(stream, state, /[^\\\\]#\\{/, 1, htmlMode.token(stream, state.htmlState));\n
+    }\n
+\n
+    function startHtmlLine(lastTokenize) {\n
+      return function(stream, state) {\n
+        var style = htmlLine(stream, state);\n
+        if (stream.eol()) state.tokenize = lastTokenize;\n
+        return style;\n
+      };\n
+    }\n
+\n
+    function startHtmlMode(stream, state, offset) {\n
+      state.stack = {\n
+        parent: state.stack,\n
+        style: "html",\n
+        indented: stream.column() + offset, // pipe + space\n
+        tokenize: state.line\n
+      };\n
+      state.line = state.tokenize = html;\n
+      return null;\n
+    }\n
+\n
+    function comment(stream, state) {\n
+      stream.skipToEnd();\n
+      return state.stack.style;\n
+    }\n
+\n
+    function commentMode(stream, state) {\n
+      state.stack = {\n
+        parent: state.stack,\n
+        style: "comment",\n
+        indented: state.indented + 1,\n
+        tokenize: state.line\n
+      };\n
+      state.line = comment;\n
+      return comment(stream, state);\n
+    }\n
+\n
+    function attributeWrapper(stream, state) {\n
+      if (stream.eat(state.stack.endQuote)) {\n
+        state.line = state.stack.line;\n
+        state.tokenize = state.stack.tokenize;\n
+        state.stack = state.stack.parent;\n
+        return null;\n
+      }\n
+      if (stream.match(wrappedAttributeNameRegexp)) {\n
+        state.tokenize = attributeWrapperAssign;\n
+        return "slimAttribute";\n
+      }\n
+      stream.next();\n
+      return null;\n
+    }\n
+    function attributeWrapperAssign(stream, state) {\n
+      if (stream.match(/^==?/)) {\n
+        state.tokenize = attributeWrapperValue;\n
+        return null;\n
+      }\n
+      return attributeWrapper(stream, state);\n
+    }\n
+    function attributeWrapperValue(stream, state) {\n
+      var ch = stream.peek();\n
+      if (ch == \'"\' || ch == "\\\'") {\n
+        state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper);\n
+        stream.next();\n
+        return state.tokenize(stream, state);\n
+      }\n
+      if (ch == \'[\') {\n
+        return startRubySplat(attributeWrapper)(stream, state);\n
+      }\n
+      if (stream.match(/^(true|false|nil)\\b/)) {\n
+        state.tokenize = attributeWrapper;\n
+        return "keyword";\n
+      }\n
+      return startRubySplat(attributeWrapper)(stream, state);\n
+    }\n
+\n
+    function startAttributeWrapperMode(state, endQuote, tokenize) {\n
+      state.stack = {\n
+        parent: state.stack,\n
+        style: "wrapper",\n
+        indented: state.indented + 1,\n
+        tokenize: tokenize,\n
+        line: state.line,\n
+        endQuote: endQuote\n
+      };\n
+      state.line = state.tokenize = attributeWrapper;\n
+      return null;\n
+    }\n
+\n
+    function sub(stream, state) {\n
+      if (stream.match(/^#\\{/)) {\n
+        state.tokenize = rubyInQuote("}", state.tokenize);\n
+        return null;\n
+      }\n
+      var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize);\n
+      subStream.pos = stream.pos - state.stack.indented;\n
+      subStream.start = stream.start - state.stack.indented;\n
+      subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented;\n
+      subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented;\n
+      var style = state.subMode.token(subStream, state.subState);\n
+      stream.pos = subStream.pos + state.stack.indented;\n
+      return style;\n
+    }\n
+    function firstSub(stream, state) {\n
+      state.stack.indented = stream.column();\n
+      state.line = state.tokenize = sub;\n
+      return state.tokenize(stream, state);\n
+    }\n
+\n
+    function createMode(mode) {\n
+      var query = embedded[mode];\n
+      var spec = CodeMirror.mimeModes[query];\n
+      if (spec) {\n
+        return CodeMirror.getMode(config, spec);\n
+      }\n
+      var factory = CodeMirror.modes[query];\n
+      if (factory) {\n
+        return factory(config, {name: query});\n
+      }\n
+      return CodeMirror.getMode(config, "null");\n
+    }\n
+\n
+    function getMode(mode) {\n
+      if (!modes.hasOwnProperty(mode)) {\n
+        return modes[mode] = createMode(mode);\n
+      }\n
+      return modes[mode];\n
+    }\n
+\n
+    function startSubMode(mode, state) {\n
+      var subMode = getMode(mode);\n
+      var subState = subMode.startState && subMode.startState();\n
+\n
+      state.subMode = subMode;\n
+      state.subState = subState;\n
+\n
+      state.stack = {\n
+        parent: state.stack,\n
+        style: "sub",\n
+        indented: state.indented + 1,\n
+        tokenize: state.line\n
+      };\n
+      state.line = state.tokenize = firstSub;\n
+      return "slimSubmode";\n
+    }\n
+\n
+    function doctypeLine(stream, _state) {\n
+      stream.skipToEnd();\n
+      return "slimDoctype";\n
+    }\n
+\n
+    function startLine(stream, state) {\n
+      var ch = stream.peek();\n
+      if (ch == \'<\') {\n
+        return (state.tokenize = startHtmlLine(state.tokenize))(stream, state);\n
+      }\n
+      if (stream.match(/^[|\']/)) {\n
+        return startHtmlMode(stream, state, 1);\n
+      }\n
+      if (stream.match(/^\\/(!|\\[\\w+])?/)) {\n
+        return commentMode(stream, state);\n
+      }\n
+      if (stream.match(/^(-|==?[<>]?)/)) {\n
+        state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby));\n
+        return "slimSwitch";\n
+      }\n
+      if (stream.match(/^doctype\\b/)) {\n
+        state.tokenize = doctypeLine;\n
+        return "keyword";\n
+      }\n
+\n
+      var m = stream.match(embeddedRegexp);\n
+      if (m) {\n
+        return startSubMode(m[1], state);\n
+      }\n
+\n
+      return slimTag(stream, state);\n
+    }\n
+\n
+    function slim(stream, state) {\n
+      if (state.startOfLine) {\n
+        return startLine(stream, state);\n
+      }\n
+      return slimTag(stream, state);\n
+    }\n
+\n
+    function slimTag(stream, state) {\n
+      if (stream.eat(\'*\')) {\n
+        state.tokenize = startRubySplat(slimTagExtras);\n
+        return null;\n
+      }\n
+      if (stream.match(nameRegexp)) {\n
+        state.tokenize = slimTagExtras;\n
+        return "slimTag";\n
+      }\n
+      return slimClass(stream, state);\n
+    }\n
+    function slimTagExtras(stream, state) {\n
+      if (stream.match(/^(<>?|><?)/)) {\n
+        state.tokenize = slimClass;\n
+        return null;\n
+      }\n
+      return slimClass(stream, state);\n
+    }\n
+    function slimClass(stream, state) {\n
+      if (stream.match(classIdRegexp)) {\n
+        state.tokenize = slimClass;\n
+        return "slimId";\n
+      }\n
+      if (stream.match(classNameRegexp)) {\n
+        state.tokenize = slimClass;\n
+        return "slimClass";\n
+      }\n
+      return slimAttribute(stream, state);\n
+    }\n
+    function slimAttribute(stream, state) {\n
+      if (stream.match(/^([\\[\\{\\(])/)) {\n
+        return startAttributeWrapperMode(state, closing[RegExp.$1], slimAttribute);\n
+      }\n
+      if (stream.match(attributeNameRegexp)) {\n
+        state.tokenize = slimAttributeAssign;\n
+        return "slimAttribute";\n
+      }\n
+      if (stream.peek() == \'*\') {\n
+        stream.next();\n
+        state.tokenize = startRubySplat(slimContent);\n
+        return null;\n
+      }\n
+      return slimContent(stream, state);\n
+    }\n
+    function slimAttributeAssign(stream, state) {\n
+      if (stream.match(/^==?/)) {\n
+        state.tokenize = slimAttributeValue;\n
+        return null;\n
+      }\n
+      // should never happen, because of forward lookup\n
+      return slimAttribute(stream, state);\n
+    }\n
+\n
+    function slimAttributeValue(stream, state) {\n
+      var ch = stream.peek();\n
+      if (ch == \'"\' || ch == "\\\'") {\n
+        state.tokenize = readQuoted(ch, "string", true, false, slimAttribute);\n
+        stream.next();\n
+        return state.tokenize(stream, state);\n
+      }\n
+      if (ch == \'[\') {\n
+        return startRubySplat(slimAttribute)(stream, state);\n
+      }\n
+      if (ch == \':\') {\n
+        return startRubySplat(slimAttributeSymbols)(stream, state);\n
+      }\n
+      if (stream.match(/^(true|false|nil)\\b/)) {\n
+        state.tokenize = slimAttribute;\n
+        return "keyword";\n
+      }\n
+      return startRubySplat(slimAttribute)(stream, state);\n
+    }\n
+    function slimAttributeSymbols(stream, state) {\n
+      stream.backUp(1);\n
+      if (stream.match(/^[^\\s],(?=:)/)) {\n
+        state.tokenize = startRubySplat(slimAttributeSymbols);\n
+        return null;\n
+      }\n
+      stream.next();\n
+      return slimAttribute(stream, state);\n
+    }\n
+    function readQuoted(quote, style, embed, unescaped, nextTokenize) {\n
+      return function(stream, state) {\n
+        finishContinue(state);\n
+        var fresh = stream.current().length == 0;\n
+        if (stream.match(/^\\\\$/, fresh)) {\n
+          if (!fresh) return style;\n
+          continueLine(state, state.indented);\n
+          return "lineContinuation";\n
+        }\n
+        if (stream.match(/^#\\{/, fresh)) {\n
+          if (!fresh) return style;\n
+          state.tokenize = rubyInQuote("}", state.tokenize);\n
+          return null;\n
+        }\n
+        var escaped = false, ch;\n
+        while ((ch = stream.next()) != null) {\n
+          if (ch == quote && (unescaped || !escaped)) {\n
+            state.tokenize = nextTokenize;\n
+            break;\n
+          }\n
+          if (embed && ch == "#" && !escaped) {\n
+            if (stream.eat("{")) {\n
+              stream.backUp(2);\n
+              break;\n
+            }\n
+          }\n
+          escaped = !escaped && ch == "\\\\";\n
+        }\n
+        if (stream.eol() && escaped) {\n
+          stream.backUp(1);\n
+        }\n
+        return style;\n
+      };\n
+    }\n
+    function slimContent(stream, state) {\n
+      if (stream.match(/^==?/)) {\n
+        state.tokenize = ruby;\n
+        return "slimSwitch";\n
+      }\n
+      if (stream.match(/^\\/$/)) { // tag close hint\n
+        state.tokenize = slim;\n
+        return null;\n
+      }\n
+      if (stream.match(/^:/)) { // inline tag\n
+        state.tokenize = slimTag;\n
+        return "slimSwitch";\n
+      }\n
+      startHtmlMode(stream, state, 0);\n
+      return state.tokenize(stream, state);\n
+    }\n
+\n
+    var mode = {\n
+      // default to html mode\n
+      startState: function() {\n
+        var htmlState = htmlMode.startState();\n
+        var rubyState = rubyMode.startState();\n
+        return {\n
+          htmlState: htmlState,\n
+          rubyState: rubyState,\n
+          stack: null,\n
+          last: null,\n
+          tokenize: slim,\n
+          line: slim,\n
+          indented: 0\n
+        };\n
+      },\n
+\n
+      copyState: function(state) {\n
+        return {\n
+          htmlState : CodeMirror.copyState(htmlMode, state.htmlState),\n
+          rubyState: CodeMirror.copyState(rubyMode, state.rubyState),\n
+          subMode: state.subMode,\n
+          subState: state.subMode && CodeMirror.copyState(state.subMode, state.subState),\n
+          stack: state.stack,\n
+          last: state.last,\n
+          tokenize: state.tokenize,\n
+          line: state.line\n
+        };\n
+      },\n
+\n
+      token: function(stream, state) {\n
+        if (stream.sol()) {\n
+          state.indented = stream.indentation();\n
+          state.startOfLine = true;\n
+          state.tokenize = state.line;\n
+          while (state.stack && state.stack.indented > state.indented && state.last != "slimSubmode") {\n
+            state.line = state.tokenize = state.stack.tokenize;\n
+            state.stack = state.stack.parent;\n
+            state.subMode = null;\n
+            state.subState = null;\n
+          }\n
+        }\n
+        if (stream.eatSpace()) return null;\n
+        var style = state.tokenize(stream, state);\n
+        state.startOfLine = false;\n
+        if (style) state.last = style;\n
+        return styleMap.hasOwnProperty(style) ? styleMap[style] : style;\n
+      },\n
+\n
+      blankLine: function(state) {\n
+        if (state.subMode && state.subMode.blankLine) {\n
+          return state.subMode.blankLine(state.subState);\n
+        }\n
+      },\n
+\n
+      innerMode: function(state) {\n
+        if (state.subMode) return {state: state.subState, mode: state.subMode};\n
+        return {state: state, mode: mode};\n
+      }\n
+\n
+      //indent: function(state) {\n
+      //  return state.indented;\n
+      //}\n
+    };\n
+    return mode;\n
+  }, "htmlmixed", "ruby");\n
+\n
+  CodeMirror.defineMIME("text/x-slim", "slim");\n
+  CodeMirror.defineMIME("application/x-slim", "slim");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>18008</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9468743b0daf945486ff6c7f049a26e722f13d98
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/slim/test.js.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897148.06</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh\n
+\n
+(function() {\n
+  var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim");\n
+  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
+\n
+  // Requires at least one media query\n
+  MT("elementName",\n
+     "[tag h1] Hey There");\n
+\n
+  MT("oneElementPerLine",\n
+     "[tag h1] Hey There .h2");\n
+\n
+  MT("idShortcut",\n
+     "[attribute&def #test] Hey There");\n
+\n
+  MT("tagWithIdShortcuts",\n
+     "[tag h1][attribute&def #test] Hey There");\n
+\n
+  MT("classShortcut",\n
+     "[attribute&qualifier .hello] Hey There");\n
+\n
+  MT("tagWithIdAndClassShortcuts",\n
+     "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There");\n
+\n
+  MT("docType",\n
+     "[keyword doctype] xml");\n
+\n
+  MT("comment",\n
+     "[comment / Hello WORLD]");\n
+\n
+  MT("notComment",\n
+     "[tag h1] This is not a / comment ");\n
+\n
+  MT("attributes",\n
+     "[tag a]([attribute title]=[string \\"test\\"]) [attribute href]=[string \\"link\\"]}");\n
+\n
+  MT("multiLineAttributes",\n
+     "[tag a]([attribute title]=[string \\"test\\"]",\n
+     "  ) [attribute href]=[string \\"link\\"]}");\n
+\n
+  MT("htmlCode",\n
+     "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");\n
+\n
+  MT("rubyBlock",\n
+     "[operator&special =][variable-2 @item]");\n
+\n
+  MT("selectorRubyBlock",\n
+     "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]");\n
+\n
+  MT("nestedRubyBlock",\n
+      "[tag a]",\n
+      "  [operator&special =][variable puts] [string \\"test\\"]");\n
+\n
+  MT("multilinePlaintext",\n
+      "[tag p]",\n
+      "  | Hello,",\n
+      "    World");\n
+\n
+  MT("multilineRuby",\n
+      "[tag p]",\n
+      "  [comment /# this is a comment]",\n
+      "     [comment and this is a comment too]",\n
+      "  | Date/Time",\n
+      "  [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]",\n
+      "  [tag strong][operator&special =] [variable now]",\n
+      "  [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \\"December 31, 2006\\"])",\n
+      "     [operator&special =][string \\"Happy\\"]",\n
+      "     [operator&special =][string \\"Belated\\"]",\n
+      "     [operator&special =][string \\"Birthday\\"]");\n
+\n
+  MT("multilineComment",\n
+      "[comment /]",\n
+      "  [comment Multiline]",\n
+      "  [comment Comment]");\n
+\n
+  MT("hamlAfterRubyTag",\n
+    "[attribute&qualifier .block]",\n
+    "  [tag strong][operator&special =] [variable now]",\n
+    "  [attribute&qualifier .test]",\n
+    "     [operator&special =][variable now]",\n
+    "  [attribute&qualifier .right]");\n
+\n
+  MT("stretchedRuby",\n
+     "[operator&special =] [variable puts] [string \\"Hello\\"],",\n
+     "   [string \\"World\\"]");\n
+\n
+  MT("interpolationInHashAttribute",\n
+     "[tag div]{[attribute id] = [string \\"]#{[variable test]}[string _]#{[variable ting]}[string \\"]} test");\n
+\n
+  MT("interpolationInHTMLAttribute",\n
+     "[tag div]([attribute title]=[string \\"]#{[variable test]}[string _]#{[variable ting]()}[string \\"]) Test");\n
+})();\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3130</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smalltalk/smalltalk.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smalltalk/smalltalk.js.xml
index b5366eaf8b73e48343006352b6a8d1ad96426b22..d27a643556bb74e507a2e2a1f5c653b78ead0a72 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smalltalk/smalltalk.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smalltalk/smalltalk.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403090.0</string> </value>
+            <value> <string>ts21897145.35</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode(\'smalltalk\', function(config) {\n
 \n
   var specialChars = /[+\\-\\/\\\\*~<>=@%|&?!.,:;^]/;\n
@@ -64,7 +77,7 @@ CodeMirror.defineMode(\'smalltalk\', function(config) {\n
         stream.next();\n
         token = nextSymbol(stream, new Context(nextSymbol, context));\n
       } else {\n
-        if (stream.eatWhile(/[^ .{}\\[\\]()]/))\n
+        if (stream.eatWhile(/[^\\s.{}\\[\\]()]/))\n
           token.name = \'string-2\';\n
         else\n
           token.name = \'meta\';\n
@@ -72,7 +85,7 @@ CodeMirror.defineMode(\'smalltalk\', function(config) {\n
 \n
     } else if (aChar === \'$\') {\n
       if (stream.next() === \'<\') {\n
-        stream.eatWhile(/[^ >]/);\n
+        stream.eatWhile(/[^\\s>]/);\n
         stream.next();\n
       }\n
       token.name = \'string-2\';\n
@@ -175,6 +188,8 @@ CodeMirror.defineMode(\'smalltalk\', function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME(\'text/x-stsrc\', {name: \'smalltalk\'});\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -185,7 +200,7 @@ CodeMirror.defineMIME(\'text/x-stsrc\', {name: \'smalltalk\'});\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4080</int> </value>
+            <value> <int>4543</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smarty/smarty.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smarty/smarty.js.xml
index 617852d0fd6830877e304feaf7f0788613bf1a88..e6ddff6b66ac4ff708d75fb1b6c4b4e76ca7d6ed 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smarty/smarty.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smarty/smarty.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403096.18</string> </value>
+            <value> <string>ts21897138.3</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,9 +22,23 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
  * Smarty 2 and 3 mode.\n
  */\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("smarty", function(config) {\n
   "use strict";\n
 \n
@@ -227,6 +241,8 @@ CodeMirror.defineMode("smarty", function(config) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-smarty", "smarty");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -237,7 +253,7 @@ CodeMirror.defineMIME("text/x-smarty", "smarty");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5957</int> </value>
+            <value> <int>6419</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smartymixed/smartymixed.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smartymixed/smartymixed.js.xml
index 46dec0aca5d4b7cd245ede72bed9a64cfe0d9a1a..b454cb5800c41434f0124daaae60db5bd0d9753f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smartymixed/smartymixed.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/smartymixed/smartymixed.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403087.25</string> </value>
+            <value> <string>ts21897148.81</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /**\n
 * @file smartymixed.js\n
 * @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML)\n
@@ -29,12 +32,25 @@
 * @version 3.0\n
 * @date 05.07.2013\n
 */\n
+\n
+// Warning: Don\'t base other modes on this one. This here is a\n
+// terrible way to write a mixed mode.\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../smarty/smarty"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../smarty/smarty"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("smartymixed", function(config) {\n
-  var settings, regs, helpers, parsers,\n
-  htmlMixedMode = CodeMirror.getMode(config, "htmlmixed"),\n
-  smartyMode = CodeMirror.getMode(config, "smarty"),\n
+  var htmlMixedMode = CodeMirror.getMode(config, "htmlmixed");\n
+  var smartyMode = CodeMirror.getMode(config, "smarty");\n
 \n
-  settings = {\n
+  var settings = {\n
     rightDelimiter: \'}\',\n
     leftDelimiter: \'{\'\n
   };\n
@@ -46,15 +62,18 @@ CodeMirror.defineMode("smartymixed", function(config) {\n
     settings.rightDelimiter = config.rightDelimiter;\n
   }\n
 \n
-  regs = {\n
-    smartyComment: new RegExp("^" + settings.leftDelimiter + "\\\\*"),\n
-    literalOpen: new RegExp(settings.leftDelimiter + "literal" + settings.rightDelimiter),\n
-    literalClose: new RegExp(settings.leftDelimiter + "\\/literal" + settings.rightDelimiter),\n
-    hasLeftDelimeter: new RegExp(".*" + settings.leftDelimiter),\n
-    htmlHasLeftDelimeter: new RegExp("[^<>]*" + settings.leftDelimiter)\n
+  function reEsc(str) { return str.replace(/[^\\s\\w]/g, "\\\\$&"); }\n
+\n
+  var reLeft = reEsc(settings.leftDelimiter), reRight = reEsc(settings.rightDelimiter);\n
+  var regs = {\n
+    smartyComment: new RegExp("^" + reRight + "\\\\*"),\n
+    literalOpen: new RegExp(reLeft + "literal" + reRight),\n
+    literalClose: new RegExp(reLeft + "\\/literal" + reRight),\n
+    hasLeftDelimeter: new RegExp(".*" + reLeft),\n
+    htmlHasLeftDelimeter: new RegExp("[^<>]*" + reLeft)\n
   };\n
 \n
-  helpers = {\n
+  var helpers = {\n
     chain: function(stream, state, parser) {\n
       state.tokenize = parser;\n
       return parser(stream, state);\n
@@ -80,9 +99,13 @@ CodeMirror.defineMode("smartymixed", function(config) {\n
     }\n
   };\n
 \n
-  parsers = {\n
+  var parsers = {\n
     html: function(stream, state) {\n
-      if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false) && state.htmlMixedState.htmlState.tagName === null) {\n
+      var htmlTagName = state.htmlMixedState.htmlState.context && state.htmlMixedState.htmlState.context.tagName\n
+        ? state.htmlMixedState.htmlState.context.tagName\n
+        : null;\n
+\n
+      if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false) && htmlTagName === null) {\n
         state.tokenize = parsers.smarty;\n
         state.localMode = smartyMode;\n
         state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, ""));\n
@@ -190,11 +213,12 @@ CodeMirror.defineMode("smartymixed", function(config) {\n
       };\n
     }\n
   };\n
-},\n
-"htmlmixed");\n
+}, "htmlmixed", "smarty");\n
 \n
 CodeMirror.defineMIME("text/x-smarty", "smartymixed");\n
 // vim: et ts=2 sts=2 sw=2\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -205,7 +229,7 @@ CodeMirror.defineMIME("text/x-smarty", "smartymixed");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5765</int> </value>
+            <value> <int>6638</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/solr/solr.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/solr/solr.js.xml
index ba35e74120e537f5f03dab9a4a75b1f6f65d69c9..1b9ea67a677c94b2eddcb1111366c340844d803d 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/solr/solr.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/solr/solr.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403091.34</string> </value>
+            <value> <string>ts21897143.74</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("solr", function() {\n
   "use strict";\n
 \n
@@ -111,6 +124,8 @@ CodeMirror.defineMode("solr", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-solr", "solr");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -121,7 +136,7 @@ CodeMirror.defineMIME("text/x-solr", "solr");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2217</int> </value>
+            <value> <int>2678</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/soy.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/soy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12ba2fe82dcba4c6388bbbc20c96a96a5bcfedef
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/soy.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>soy</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/soy/soy.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/soy/soy.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d1e93aa9ef7701ba5acc1b8d4f84a3898d1a19b4
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/soy/soy.js.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897149.45</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>soy.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  var indentingTags = ["template", "literal", "msg", "fallbackmsg", "let", "if", "elseif",\n
+                       "else", "switch", "case", "default", "foreach", "ifempty", "for",\n
+                       "call", "param", "deltemplate", "delcall", "log"];\n
+\n
+  CodeMirror.defineMode("soy", function(config) {\n
+    var textMode = CodeMirror.getMode(config, "text/plain");\n
+    var modes = {\n
+      html: CodeMirror.getMode(config, {name: "text/html", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}),\n
+      attributes: textMode,\n
+      text: textMode,\n
+      uri: textMode,\n
+      css: CodeMirror.getMode(config, "text/css"),\n
+      js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit})\n
+    };\n
+\n
+    function last(array) {\n
+      return array[array.length - 1];\n
+    }\n
+\n
+    function tokenUntil(stream, state, untilRegExp) {\n
+      var oldString = stream.string;\n
+      var match = untilRegExp.exec(oldString.substr(stream.pos));\n
+      if (match) {\n
+        // We don\'t use backUp because it backs up just the position, not the state.\n
+        // This uses an undocumented API.\n
+        stream.string = oldString.substr(0, stream.pos + match.index);\n
+      }\n
+      var result = stream.hideFirstChars(state.indent, function() {\n
+        return state.localMode.token(stream, state.localState);\n
+      });\n
+      stream.string = oldString;\n
+      return result;\n
+    }\n
+\n
+    return {\n
+      startState: function() {\n
+        return {\n
+          kind: [],\n
+          kindTag: [],\n
+          soyState: [],\n
+          indent: 0,\n
+          localMode: modes.html,\n
+          localState: CodeMirror.startState(modes.html)\n
+        };\n
+      },\n
+\n
+      copyState: function(state) {\n
+        return {\n
+          tag: state.tag, // Last seen Soy tag.\n
+          kind: state.kind.concat([]), // Values of kind="" attributes.\n
+          kindTag: state.kindTag.concat([]), // Opened tags with kind="" attributes.\n
+          soyState: state.soyState.concat([]),\n
+          indent: state.indent, // Indentation of the following line.\n
+          localMode: state.localMode,\n
+          localState: CodeMirror.copyState(state.localMode, state.localState)\n
+        };\n
+      },\n
+\n
+      token: function(stream, state) {\n
+        var match;\n
+\n
+        switch (last(state.soyState)) {\n
+          case "comment":\n
+            if (stream.match(/^.*?\\*\\//)) {\n
+              state.soyState.pop();\n
+            } else {\n
+              stream.skipToEnd();\n
+            }\n
+            return "comment";\n
+\n
+          case "variable":\n
+            if (stream.match(/^}/)) {\n
+              state.indent -= 2 * config.indentUnit;\n
+              state.soyState.pop();\n
+              return "variable-2";\n
+            }\n
+            stream.next();\n
+            return null;\n
+\n
+          case "tag":\n
+            if (stream.match(/^\\/?}/)) {\n
+              if (state.tag == "/template" || state.tag == "/deltemplate") state.indent = 0;\n
+              else state.indent -= (stream.current() == "/}" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1) * config.indentUnit;\n
+              state.soyState.pop();\n
+              return "keyword";\n
+            } else if (stream.match(/^(\\w+)(?==)/)) {\n
+              if (stream.current() == "kind" && (match = stream.match(/^="([^"]+)/, false))) {\n
+                var kind = match[1];\n
+                state.kind.push(kind);\n
+                state.kindTag.push(state.tag);\n
+                state.localMode = modes[kind] || modes.html;\n
+                state.localState = CodeMirror.startState(state.localMode);\n
+              }\n
+              return "attribute";\n
+            } else if (stream.match(/^"/)) {\n
+              state.soyState.push("string");\n
+              return "string";\n
+            }\n
+            stream.next();\n
+            return null;\n
+\n
+          case "literal":\n
+            if (stream.match(/^(?=\\{\\/literal})/)) {\n
+              state.indent -= config.indentUnit;\n
+              state.soyState.pop();\n
+              return this.token(stream, state);\n
+            }\n
+            return tokenUntil(stream, state, /\\{\\/literal}/);\n
+\n
+          case "string":\n
+            if (stream.match(/^.*?"/)) {\n
+              state.soyState.pop();\n
+            } else {\n
+              stream.skipToEnd();\n
+            }\n
+            return "string";\n
+        }\n
+\n
+        if (stream.match(/^\\/\\*/)) {\n
+          state.soyState.push("comment");\n
+          return "comment";\n
+        } else if (stream.match(stream.sol() ? /^\\s*\\/\\/.*/ : /^\\s+\\/\\/.*/)) {\n
+          return "comment";\n
+        } else if (stream.match(/^\\{\\$\\w*/)) {\n
+          state.indent += 2 * config.indentUnit;\n
+          state.soyState.push("variable");\n
+          return "variable-2";\n
+        } else if (stream.match(/^\\{literal}/)) {\n
+          state.indent += config.indentUnit;\n
+          state.soyState.push("literal");\n
+          return "keyword";\n
+        } else if (match = stream.match(/^\\{([\\/@\\\\]?\\w*)/)) {\n
+          if (match[1] != "/switch")\n
+            state.indent += (/^(\\/|(else|elseif|case|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit;\n
+          state.tag = match[1];\n
+          if (state.tag == "/" + last(state.kindTag)) {\n
+            // We found the tag that opened the current kind="".\n
+            state.kind.pop();\n
+            state.kindTag.pop();\n
+            state.localMode = modes[last(state.kind)] || modes.html;\n
+            state.localState = CodeMirror.startState(state.localMode);\n
+          }\n
+          state.soyState.push("tag");\n
+          return "keyword";\n
+        }\n
+\n
+        return tokenUntil(stream, state, /\\{|\\s+\\/\\/|\\/\\*/);\n
+      },\n
+\n
+      indent: function(state, textAfter) {\n
+        var indent = state.indent, top = last(state.soyState);\n
+        if (top == "comment") return CodeMirror.Pass;\n
+\n
+        if (top == "literal") {\n
+          if (/^\\{\\/literal}/.test(textAfter)) indent -= config.indentUnit;\n
+        } else {\n
+          if (/^\\s*\\{\\/(template|deltemplate)\\b/.test(textAfter)) return 0;\n
+          if (/^\\{(\\/|(fallbackmsg|elseif|else|ifempty)\\b)/.test(textAfter)) indent -= config.indentUnit;\n
+          if (state.tag != "switch" && /^\\{(case|default)\\b/.test(textAfter)) indent -= config.indentUnit;\n
+          if (/^\\{\\/switch\\b/.test(textAfter)) indent -= config.indentUnit;\n
+        }\n
+        if (indent && state.localMode.indent)\n
+          indent += state.localMode.indent(state.localState, textAfter);\n
+        return indent;\n
+      },\n
+\n
+      innerMode: function(state) {\n
+        if (state.soyState.length && last(state.soyState) != "literal") return null;\n
+        else return {state: state.localState, mode: state.localMode};\n
+      },\n
+\n
+      electricInput: /^\\s*\\{(\\/|\\/template|\\/deltemplate|\\/switch|fallbackmsg|elseif|else|case|default|ifempty|\\/literal\\})$/,\n
+      lineComment: "//",\n
+      blockCommentStart: "/*",\n
+      blockCommentEnd: "*/",\n
+      blockCommentContinue: " * ",\n
+      fold: "indent"\n
+    };\n
+  }, "htmlmixed");\n
+\n
+  CodeMirror.registerHelper("hintWords", "soy", indentingTags.concat(\n
+      ["delpackage", "namespace", "alias", "print", "css", "debugger"]));\n
+\n
+  CodeMirror.defineMIME("text/x-soy", "soy");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>7555</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sparql/sparql.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sparql/sparql.js.xml
index dcaddd3a05942d593aaebbae016c2061cbe50388..ff21c47849c45eb22a64b7756d226d93c6698962 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sparql/sparql.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sparql/sparql.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403093.35</string> </value>
+            <value> <string>ts21897141.88</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("sparql", function(config) {\n
   var indentUnit = config.indentUnit;\n
   var curPunc;\n
@@ -30,18 +43,28 @@ CodeMirror.defineMode("sparql", function(config) {\n
     return new RegExp("^(?:" + words.join("|") + ")$", "i");\n
   }\n
   var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",\n
+                        "iri", "uri", "bnode", "count", "sum", "min", "max", "avg", "sample",\n
+                        "group_concat", "rand", "abs", "ceil", "floor", "round", "concat", "substr", "strlen",\n
+                        "replace", "ucase", "lcase", "encode_for_uri", "contains", "strstarts", "strends",\n
+                        "strbefore", "strafter", "year", "month", "day", "hours", "minutes", "seconds",\n
+                        "timezone", "tz", "now", "uuid", "struuid", "md5", "sha1", "sha256", "sha384",\n
+                        "sha512", "coalesce", "if", "strlang", "strdt", "isnumeric", "regex", "exists",\n
                         "isblank", "isliteral", "a"]);\n
   var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",\n
                              "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",\n
                              "graph", "by", "asc", "desc", "as", "having", "undef", "values", "group",\n
                              "minus", "in", "not", "service", "silent", "using", "insert", "delete", "union",\n
+                             "true", "false", "with",\n
                              "data", "copy", "to", "move", "add", "create", "drop", "clear", "load"]);\n
-  var operatorChars = /[*+\\-<>=&|]/;\n
+  var operatorChars = /[*+\\-<>=&|\\^\\/!\\?]/;\n
 \n
   function tokenBase(stream, state) {\n
     var ch = stream.next();\n
     curPunc = null;\n
     if (ch == "$" || ch == "?") {\n
+      if(ch == "?" && stream.match(/\\s/, false)){\n
+        return "operator";\n
+      }\n
       stream.match(/^[\\w\\d]*/);\n
       return "variable-2";\n
     }\n
@@ -55,7 +78,7 @@ CodeMirror.defineMode("sparql", function(config) {\n
     }\n
     else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n
       curPunc = ch;\n
-      return null;\n
+      return "bracket";\n
     }\n
     else if (ch == "#") {\n
       stream.skipToEnd();\n
@@ -63,12 +86,16 @@ CodeMirror.defineMode("sparql", function(config) {\n
     }\n
     else if (operatorChars.test(ch)) {\n
       stream.eatWhile(operatorChars);\n
-      return null;\n
+      return "operator";\n
     }\n
     else if (ch == ":") {\n
       stream.eatWhile(/[\\w\\d\\._\\-]/);\n
       return "atom";\n
     }\n
+    else if (ch == "@") {\n
+      stream.eatWhile(/[a-z\\d\\-]/i);\n
+      return "meta";\n
+    }\n
     else {\n
       stream.eatWhile(/[_\\w\\d]/);\n
       if (stream.eat(":")) {\n
@@ -77,7 +104,7 @@ CodeMirror.defineMode("sparql", function(config) {\n
       }\n
       var word = stream.current();\n
       if (ops.test(word))\n
-        return null;\n
+        return "builtin";\n
       else if (keywords.test(word))\n
         return "keyword";\n
       else\n
@@ -166,7 +193,9 @@ CodeMirror.defineMode("sparql", function(config) {\n
   };\n
 });\n
 \n
-CodeMirror.defineMIME("application/x-sparql-query", "sparql");\n
+CodeMirror.defineMIME("application/sparql-query", "sparql");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -177,7 +206,7 @@ CodeMirror.defineMIME("application/x-sparql-query", "sparql");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4835</int> </value>
+            <value> <int>6169</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/spreadsheet.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/spreadsheet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..96312045983a060184c0a9dd009ca6afb14d6275
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/spreadsheet.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>spreadsheet</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/spreadsheet/spreadsheet.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/spreadsheet/spreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f470dab88747a0388c3295b7c6931f75d104469d
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/spreadsheet/spreadsheet.js.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897148.6</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>spreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("spreadsheet", function () {\n
+    return {\n
+      startState: function () {\n
+        return {\n
+          stringType: null,\n
+          stack: []\n
+        };\n
+      },\n
+      token: function (stream, state) {\n
+        if (!stream) return;\n
+\n
+        //check for state changes\n
+        if (state.stack.length === 0) {\n
+          //strings\n
+          if ((stream.peek() == \'"\') || (stream.peek() == "\'")) {\n
+            state.stringType = stream.peek();\n
+            stream.next(); // Skip quote\n
+            state.stack.unshift("string");\n
+          }\n
+        }\n
+\n
+        //return state\n
+        //stack has\n
+        switch (state.stack[0]) {\n
+        case "string":\n
+          while (state.stack[0] === "string" && !stream.eol()) {\n
+            if (stream.peek() === state.stringType) {\n
+              stream.next(); // Skip quote\n
+              state.stack.shift(); // Clear flag\n
+            } else if (stream.peek() === "\\\\") {\n
+              stream.next();\n
+              stream.next();\n
+            } else {\n
+              stream.match(/^.[^\\\\\\"\\\']*/);\n
+            }\n
+          }\n
+          return "string";\n
+\n
+        case "characterClass":\n
+          while (state.stack[0] === "characterClass" && !stream.eol()) {\n
+            if (!(stream.match(/^[^\\]\\\\]+/) || stream.match(/^\\\\./)))\n
+              state.stack.shift();\n
+          }\n
+          return "operator";\n
+        }\n
+\n
+        var peek = stream.peek();\n
+\n
+        //no stack\n
+        switch (peek) {\n
+        case "[":\n
+          stream.next();\n
+          state.stack.unshift("characterClass");\n
+          return "bracket";\n
+        case ":":\n
+          stream.next();\n
+          return "operator";\n
+        case "\\\\":\n
+          if (stream.match(/\\\\[a-z]+/)) return "string-2";\n
+          else return null;\n
+        case ".":\n
+        case ",":\n
+        case ";":\n
+        case "*":\n
+        case "-":\n
+        case "+":\n
+        case "^":\n
+        case "<":\n
+        case "/":\n
+        case "=":\n
+          stream.next();\n
+          return "atom";\n
+        case "$":\n
+          stream.next();\n
+          return "builtin";\n
+        }\n
+\n
+        if (stream.match(/\\d+/)) {\n
+          if (stream.match(/^\\w+/)) return "error";\n
+          return "number";\n
+        } else if (stream.match(/^[a-zA-Z_]\\w*/)) {\n
+          if (stream.match(/(?=[\\(.])/, false)) return "keyword";\n
+          return "variable-2";\n
+        } else if (["[", "]", "(", ")", "{", "}"].indexOf(peek) != -1) {\n
+          stream.next();\n
+          return "bracket";\n
+        } else if (!stream.eatSpace()) {\n
+          stream.next();\n
+        }\n
+        return null;\n
+      }\n
+    };\n
+  });\n
+\n
+  CodeMirror.defineMIME("text/x-spreadsheet", "spreadsheet");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3084</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sql/sql.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sql/sql.js.xml
index 2f858eccfa74656de39568d67d3841c55a55636e..4498195754ee5ae269400fd95d83fc17322e7162 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sql/sql.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/sql/sql.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403097.14</string> </value>
+            <value> <string>ts21897137.56</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("sql", function(config, parserConfig) {\n
   "use strict";\n
 \n
@@ -224,7 +237,8 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {\n
     while ((ch = stream.next()) != null) {\n
       if (ch == "`" && !stream.eat("`")) return "variable-2";\n
     }\n
-    return null;\n
+    stream.backUp(stream.current().length - 1);\n
+    return stream.eatWhile(/\\w/) ? "variable-2" : null;\n
   }\n
 \n
   // variable token\n
@@ -356,16 +370,27 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {\n
     dateSQL:    set("date time timestamp"),\n
     support:    set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")\n
   });\n
+\n
+  // Created to support specific hive keywords\n
+  CodeMirror.defineMIME("text/x-hive", {\n
+    name: "sql",\n
+    keywords: set("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"),\n
+    builtin: set("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"),\n
+    atoms: set("false true null unknown"),\n
+    operatorChars: /^[*+\\-%<>!=]/,\n
+    dateSQL: set("date timestamp"),\n
+    support: set("ODBCdotTable doubleQuote binaryNumber hexNumber")\n
+  });\n
 }());\n
 \n
+});\n
+\n
 /*\n
   How Properties of Mime Types are used by SQL Mode\n
   =================================================\n
 \n
   keywords:\n
     A list of keywords you want to be highlighted.\n
-  functions:\n
-    A list of function names you want to be highlighted.\n
   builtin:\n
     A list of builtin types you want to be highlighted (if you want types to be of class "builtin" instead of "keyword").\n
   operatorChars:\n
@@ -398,7 +423,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>23907</int> </value>
+            <value> <int>26276</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/stex.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/stex.js.xml
index 0ed8c25e74ad02fbfd37d24ecd976d335a82f107..6102f62fe8916ee1df7567cfebb75bdd30ccb618 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/stex.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/stex.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403089.16</string> </value>
+            <value> <string>ts21897146.65</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,63 +22,76 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*\n
  * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)\n
  * Licence: MIT\n
  */\n
 \n
-CodeMirror.defineMode("stex", function() {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("stex", function() {\n
     "use strict";\n
 \n
     function pushCommand(state, command) {\n
-        state.cmdState.push(command);\n
+      state.cmdState.push(command);\n
     }\n
 \n
     function peekCommand(state) {\n
-        if (state.cmdState.length > 0) {\n
-            return state.cmdState[state.cmdState.length - 1];\n
-        } else {\n
-            return null;\n
-        }\n
+      if (state.cmdState.length > 0) {\n
+        return state.cmdState[state.cmdState.length - 1];\n
+      } else {\n
+        return null;\n
+      }\n
     }\n
 \n
     function popCommand(state) {\n
-        var plug = state.cmdState.pop();\n
-        if (plug) {\n
-            plug.closeBracket();\n
-        }\n
+      var plug = state.cmdState.pop();\n
+      if (plug) {\n
+        plug.closeBracket();\n
+      }\n
     }\n
 \n
     // returns the non-default plugin closest to the end of the list\n
     function getMostPowerful(state) {\n
-        var context = state.cmdState;\n
-        for (var i = context.length - 1; i >= 0; i--) {\n
-            var plug = context[i];\n
-            if (plug.name == "DEFAULT") {\n
-                continue;\n
-            }\n
-            return plug;\n
+      var context = state.cmdState;\n
+      for (var i = context.length - 1; i >= 0; i--) {\n
+        var plug = context[i];\n
+        if (plug.name == "DEFAULT") {\n
+          continue;\n
         }\n
-        return { styleIdentifier: function() { return null; } };\n
+        return plug;\n
+      }\n
+      return { styleIdentifier: function() { return null; } };\n
     }\n
 \n
     function addPluginPattern(pluginName, cmdStyle, styles) {\n
-        return function () {\n
-            this.name = pluginName;\n
-            this.bracketNo = 0;\n
-            this.style = cmdStyle;\n
-            this.styles = styles;\n
-            this.argument = null;   // \\begin and \\end have arguments that follow. These are stored in the plugin\n
+      return function () {\n
+        this.name = pluginName;\n
+        this.bracketNo = 0;\n
+        this.style = cmdStyle;\n
+        this.styles = styles;\n
+        this.argument = null;   // \\begin and \\end have arguments that follow. These are stored in the plugin\n
 \n
-            this.styleIdentifier = function() {\n
-                return this.styles[this.bracketNo - 1] || null;\n
-            };\n
-            this.openBracket = function() {\n
-                this.bracketNo++;\n
-                return "bracket";\n
-            };\n
-            this.closeBracket = function() {};\n
+        this.styleIdentifier = function() {\n
+          return this.styles[this.bracketNo - 1] || null;\n
         };\n
+        this.openBracket = function() {\n
+          this.bracketNo++;\n
+          return "bracket";\n
+        };\n
+        this.closeBracket = function() {};\n
+      };\n
     }\n
 \n
     var plugins = {};\n
@@ -90,184 +103,176 @@ CodeMirror.defineMode("stex", function() {\n
     plugins["end"] = addPluginPattern("end", "tag", ["atom"]);\n
 \n
     plugins["DEFAULT"] = function () {\n
-        this.name = "DEFAULT";\n
-        this.style = "tag";\n
+      this.name = "DEFAULT";\n
+      this.style = "tag";\n
 \n
-        this.styleIdentifier = this.openBracket = this.closeBracket = function() {};\n
+      this.styleIdentifier = this.openBracket = this.closeBracket = function() {};\n
     };\n
 \n
     function setState(state, f) {\n
-        state.f = f;\n
+      state.f = f;\n
     }\n
 \n
     // called when in a normal (no environment) context\n
     function normal(source, state) {\n
-        var plug;\n
-        // Do we look like \'\\command\' ?  If so, attempt to apply the plugin \'command\'\n
-        if (source.match(/^\\\\[a-zA-Z@]+/)) {\n
-            var cmdName = source.current().slice(1);\n
-            plug = plugins[cmdName] || plugins["DEFAULT"];\n
-            plug = new plug();\n
-            pushCommand(state, plug);\n
-            setState(state, beginParams);\n
-            return plug.style;\n
-        }\n
+      var plug;\n
+      // Do we look like \'\\command\' ?  If so, attempt to apply the plugin \'command\'\n
+      if (source.match(/^\\\\[a-zA-Z@]+/)) {\n
+        var cmdName = source.current().slice(1);\n
+        plug = plugins[cmdName] || plugins["DEFAULT"];\n
+        plug = new plug();\n
+        pushCommand(state, plug);\n
+        setState(state, beginParams);\n
+        return plug.style;\n
+      }\n
 \n
-        // escape characters\n
-        if (source.match(/^\\\\[$&%#{}_]/)) {\n
-          return "tag";\n
-        }\n
+      // escape characters\n
+      if (source.match(/^\\\\[$&%#{}_]/)) {\n
+        return "tag";\n
+      }\n
 \n
-        // white space control characters\n
-        if (source.match(/^\\\\[,;!\\/\\\\]/)) {\n
-          return "tag";\n
-        }\n
+      // white space control characters\n
+      if (source.match(/^\\\\[,;!\\/\\\\]/)) {\n
+        return "tag";\n
+      }\n
 \n
-        // find if we\'re starting various math modes\n
-        if (source.match("\\\\[")) {\n
-            setState(state, function(source, state){ return inMathMode(source, state, "\\\\]"); });\n
-            return "keyword";\n
-        }\n
-        if (source.match("$$")) {\n
-            setState(state, function(source, state){ return inMathMode(source, state, "$$"); });\n
-            return "keyword";\n
-        }\n
-        if (source.match("$")) {\n
-            setState(state, function(source, state){ return inMathMode(source, state, "$"); });\n
-            return "keyword";\n
-        }\n
+      // find if we\'re starting various math modes\n
+      if (source.match("\\\\[")) {\n
+        setState(state, function(source, state){ return inMathMode(source, state, "\\\\]"); });\n
+        return "keyword";\n
+      }\n
+      if (source.match("$$")) {\n
+        setState(state, function(source, state){ return inMathMode(source, state, "$$"); });\n
+        return "keyword";\n
+      }\n
+      if (source.match("$")) {\n
+        setState(state, function(source, state){ return inMathMode(source, state, "$"); });\n
+        return "keyword";\n
+      }\n
 \n
-        var ch = source.next();\n
-        if (ch == "%") {\n
-            // special case: % at end of its own line; stay in same state\n
-            if (!source.eol()) {\n
-              setState(state, inCComment);\n
-            }\n
-            return "comment";\n
-        }\n
-        else if (ch == \'}\' || ch == \']\') {\n
-            plug = peekCommand(state);\n
-            if (plug) {\n
-                plug.closeBracket(ch);\n
-                setState(state, beginParams);\n
-            } else {\n
-                return "error";\n
-            }\n
-            return "bracket";\n
-        } else if (ch == \'{\' || ch == \'[\') {\n
-            plug = plugins["DEFAULT"];\n
-            plug = new plug();\n
-            pushCommand(state, plug);\n
-            return "bracket";\n
-        }\n
-        else if (/\\d/.test(ch)) {\n
-            source.eatWhile(/[\\w.%]/);\n
-            return "atom";\n
-        }\n
-        else {\n
-            source.eatWhile(/[\\w\\-_]/);\n
-            plug = getMostPowerful(state);\n
-            if (plug.name == \'begin\') {\n
-                plug.argument = source.current();\n
-            }\n
-            return plug.styleIdentifier();\n
-        }\n
-    }\n
-\n
-    function inCComment(source, state) {\n
+      var ch = source.next();\n
+      if (ch == "%") {\n
         source.skipToEnd();\n
-        setState(state, normal);\n
         return "comment";\n
+      } else if (ch == \'}\' || ch == \']\') {\n
+        plug = peekCommand(state);\n
+        if (plug) {\n
+          plug.closeBracket(ch);\n
+          setState(state, beginParams);\n
+        } else {\n
+          return "error";\n
+        }\n
+        return "bracket";\n
+      } else if (ch == \'{\' || ch == \'[\') {\n
+        plug = plugins["DEFAULT"];\n
+        plug = new plug();\n
+        pushCommand(state, plug);\n
+        return "bracket";\n
+      } else if (/\\d/.test(ch)) {\n
+        source.eatWhile(/[\\w.%]/);\n
+        return "atom";\n
+      } else {\n
+        source.eatWhile(/[\\w\\-_]/);\n
+        plug = getMostPowerful(state);\n
+        if (plug.name == \'begin\') {\n
+          plug.argument = source.current();\n
+        }\n
+        return plug.styleIdentifier();\n
+      }\n
     }\n
 \n
     function inMathMode(source, state, endModeSeq) {\n
-        if (source.eatSpace()) {\n
-            return null;\n
-        }\n
-        if (source.match(endModeSeq)) {\n
-            setState(state, normal);\n
-            return "keyword";\n
-        }\n
-        if (source.match(/^\\\\[a-zA-Z@]+/)) {\n
-            return "tag";\n
-        }\n
-        if (source.match(/^[a-zA-Z]+/)) {\n
-            return "variable-2";\n
-        }\n
-        // escape characters\n
-        if (source.match(/^\\\\[$&%#{}_]/)) {\n
-          return "tag";\n
-        }\n
-        // white space control characters\n
-        if (source.match(/^\\\\[,;!\\/]/)) {\n
-          return "tag";\n
-        }\n
-        // special math-mode characters\n
-        if (source.match(/^[\\^_&]/)) {\n
-          return "tag";\n
-        }\n
-        // non-special characters\n
-        if (source.match(/^[+\\-<>|=,\\/@!*:;\'"`~#?]/)) {\n
-            return null;\n
-        }\n
-        if (source.match(/^(\\d+\\.\\d*|\\d*\\.\\d+|\\d+)/)) {\n
-          return "number";\n
-        }\n
-        var ch = source.next();\n
-        if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {\n
-            return "bracket";\n
-        }\n
+      if (source.eatSpace()) {\n
+        return null;\n
+      }\n
+      if (source.match(endModeSeq)) {\n
+        setState(state, normal);\n
+        return "keyword";\n
+      }\n
+      if (source.match(/^\\\\[a-zA-Z@]+/)) {\n
+        return "tag";\n
+      }\n
+      if (source.match(/^[a-zA-Z]+/)) {\n
+        return "variable-2";\n
+      }\n
+      // escape characters\n
+      if (source.match(/^\\\\[$&%#{}_]/)) {\n
+        return "tag";\n
+      }\n
+      // white space control characters\n
+      if (source.match(/^\\\\[,;!\\/]/)) {\n
+        return "tag";\n
+      }\n
+      // special math-mode characters\n
+      if (source.match(/^[\\^_&]/)) {\n
+        return "tag";\n
+      }\n
+      // non-special characters\n
+      if (source.match(/^[+\\-<>|=,\\/@!*:;\'"`~#?]/)) {\n
+        return null;\n
+      }\n
+      if (source.match(/^(\\d+\\.\\d*|\\d*\\.\\d+|\\d+)/)) {\n
+        return "number";\n
+      }\n
+      var ch = source.next();\n
+      if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {\n
+        return "bracket";\n
+      }\n
 \n
-        // eat comments here, because inCComment returns us to normal state!\n
-        if (ch == "%") {\n
-            if (!source.eol()) {\n
-                source.skipToEnd();\n
-            }\n
-            return "comment";\n
-        }\n
-        return "error";\n
+      if (ch == "%") {\n
+        source.skipToEnd();\n
+        return "comment";\n
+      }\n
+      return "error";\n
     }\n
 \n
     function beginParams(source, state) {\n
-        var ch = source.peek(), lastPlug;\n
-        if (ch == \'{\' || ch == \'[\') {\n
-            lastPlug = peekCommand(state);\n
-            lastPlug.openBracket(ch);\n
-            source.eat(ch);\n
-            setState(state, normal);\n
-            return "bracket";\n
-        }\n
-        if (/[ \\t\\r]/.test(ch)) {\n
-            source.eat(ch);\n
-            return null;\n
-        }\n
+      var ch = source.peek(), lastPlug;\n
+      if (ch == \'{\' || ch == \'[\') {\n
+        lastPlug = peekCommand(state);\n
+        lastPlug.openBracket(ch);\n
+        source.eat(ch);\n
         setState(state, normal);\n
-        popCommand(state);\n
+        return "bracket";\n
+      }\n
+      if (/[ \\t\\r]/.test(ch)) {\n
+        source.eat(ch);\n
+        return null;\n
+      }\n
+      setState(state, normal);\n
+      popCommand(state);\n
 \n
-        return normal(source, state);\n
+      return normal(source, state);\n
     }\n
 \n
     return {\n
-        startState: function() {\n
-            return {\n
-                cmdState: [],\n
-                f: normal\n
-            };\n
-        },\n
-        copyState: function(s) {\n
-            return {\n
-                cmdState: s.cmdState.slice(),\n
-                f: s.f\n
-            };\n
-        },\n
-        token: function(stream, state) {\n
-            return state.f(stream, state);\n
-        }\n
+      startState: function() {\n
+        return {\n
+          cmdState: [],\n
+          f: normal\n
+        };\n
+      },\n
+      copyState: function(s) {\n
+        return {\n
+          cmdState: s.cmdState.slice(),\n
+          f: s.f\n
+        };\n
+      },\n
+      token: function(stream, state) {\n
+        return state.f(stream, state);\n
+      },\n
+      blankLine: function(state) {\n
+        state.f = normal;\n
+        state.cmdState.length = 0;\n
+      },\n
+      lineComment: "%"\n
     };\n
-});\n
+  });\n
 \n
-CodeMirror.defineMIME("text/x-stex", "stex");\n
-CodeMirror.defineMIME("text/x-latex", "stex");\n
+  CodeMirror.defineMIME("text/x-stex", "stex");\n
+  CodeMirror.defineMIME("text/x-latex", "stex");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -278,7 +283,7 @@ CodeMirror.defineMIME("text/x-latex", "stex");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7273</int> </value>
+            <value> <int>6932</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/test.js.xml
index ebd24537cab8383a9dafa35aa1ab15a7f56c606d..2ef757710f6db6c96ce5845a49adf547493c941e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/stex/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403089.32</string> </value>
+            <value> <string>ts21897146.49</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 (function() {\n
   var mode = CodeMirror.getMode({tabSize: 4}, "stex");\n
   function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
@@ -152,7 +155,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2978</int> </value>
+            <value> <int>3106</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tcl/tcl.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tcl/tcl.js.xml
index 85fc1c1d91f1815aa6c0112b7b4bc436e70da8c5..f5f2f04f36d2682a96ac5b56a2f4d3f50e7de316 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tcl/tcl.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tcl/tcl.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403101.94</string> </value>
+            <value> <string>ts21897133.37</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,7 +22,21 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 //tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O\'Hara\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("tcl", function() {\n
   function parseWords(str) {\n
     var obj = {}, words = str.split(" ");\n
@@ -88,7 +102,7 @@ CodeMirror.defineMode("tcl", function() {\n
         return "comment";\n
       }\n
       else {\n
-        stream.eatWhile(/[\\w\\$_{}]/);\n
+        stream.eatWhile(/[\\w\\$_{}\\xa1-\\uffff]/);\n
         var word = stream.current().toLowerCase();\n
         if (keywords && keywords.propertyIsEnumerable(word))\n
           return "keyword";\n
@@ -153,6 +167,8 @@ CodeMirror.defineMode("tcl", function() {\n
     };\n
 });\n
 CodeMirror.defineMIME("text/x-tcl", "tcl");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -163,7 +179,7 @@ CodeMirror.defineMIME("text/x-tcl", "tcl");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4533</int> </value>
+            <value> <int>5006</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0ad31cc4f52e2fd5583b35695f8d6fea03f29068
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>textile</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..99a04b6c4502ccb73d0682d9fb94301480ce2858
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile/test.js.xml
@@ -0,0 +1,461 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897141.08</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
+  var mode = CodeMirror.getMode({tabSize: 4}, \'textile\');\n
+  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
+\n
+  MT(\'simpleParagraphs\',\n
+      \'Some text.\',\n
+      \'\',\n
+      \'Some more text.\');\n
+\n
+  /*\n
+   * Phrase Modifiers\n
+   */\n
+\n
+  MT(\'em\',\n
+      \'foo [em _bar_]\');\n
+\n
+  MT(\'emBoogus\',\n
+      \'code_mirror\');\n
+\n
+  MT(\'strong\',\n
+      \'foo [strong *bar*]\');\n
+\n
+  MT(\'strongBogus\',\n
+      \'3 * 3 = 9\');\n
+\n
+  MT(\'italic\',\n
+      \'foo [em __bar__]\');\n
+\n
+  MT(\'italicBogus\',\n
+      \'code__mirror\');\n
+\n
+  MT(\'bold\',\n
+      \'foo [strong **bar**]\');\n
+\n
+  MT(\'boldBogus\',\n
+      \'3 ** 3 = 27\');\n
+\n
+  MT(\'simpleLink\',\n
+      \'[link "CodeMirror":http://codemirror.net]\');\n
+\n
+  MT(\'referenceLink\',\n
+      \'[link "CodeMirror":code_mirror]\',\n
+      \'Normal Text.\',\n
+      \'[link [[code_mirror]]http://codemirror.net]\');\n
+\n
+  MT(\'footCite\',\n
+      \'foo bar[qualifier [[1]]]\');\n
+\n
+  MT(\'footCiteBogus\',\n
+      \'foo bar[[1a2]]\');\n
+\n
+  MT(\'special-characters\',\n
+          \'Registered [tag (r)], \' +\n
+          \'Trademark [tag (tm)], and \' +\n
+          \'Copyright [tag (c)] 2008\');\n
+\n
+  MT(\'cite\',\n
+      "A book is [keyword ??The Count of Monte Cristo??] by Dumas.");\n
+\n
+  MT(\'additionAndDeletion\',\n
+      \'The news networks declared [negative -Al Gore-] \' +\n
+        \'[positive +George W. Bush+] the winner in Florida.\');\n
+\n
+  MT(\'subAndSup\',\n
+      \'f(x, n) = log [builtin ~4~] x [builtin ^n^]\');\n
+\n
+  MT(\'spanAndCode\',\n
+      \'A [quote %span element%] and [atom @code element@]\');\n
+\n
+  MT(\'spanBogus\',\n
+      \'Percentage 25% is not a span.\');\n
+\n
+  MT(\'citeBogus\',\n
+      \'Question? is not a citation.\');\n
+\n
+  MT(\'codeBogus\',\n
+      \'user@example.com\');\n
+\n
+  MT(\'subBogus\',\n
+      \'~username\');\n
+\n
+  MT(\'supBogus\',\n
+      \'foo ^ bar\');\n
+\n
+  MT(\'deletionBogus\',\n
+      \'3 - 3 = 0\');\n
+\n
+  MT(\'additionBogus\',\n
+      \'3 + 3 = 6\');\n
+\n
+  MT(\'image\',\n
+      \'An image: [string !http://www.example.com/image.png!]\');\n
+\n
+  MT(\'imageWithAltText\',\n
+      \'An image: [string !http://www.example.com/image.png (Alt Text)!]\');\n
+\n
+  MT(\'imageWithUrl\',\n
+      \'An image: [string !http://www.example.com/image.png!:http://www.example.com/]\');\n
+\n
+  /*\n
+   * Headers\n
+   */\n
+\n
+  MT(\'h1\',\n
+      \'[header&header-1 h1. foo]\');\n
+\n
+  MT(\'h2\',\n
+      \'[header&header-2 h2. foo]\');\n
+\n
+  MT(\'h3\',\n
+      \'[header&header-3 h3. foo]\');\n
+\n
+  MT(\'h4\',\n
+      \'[header&header-4 h4. foo]\');\n
+\n
+  MT(\'h5\',\n
+      \'[header&header-5 h5. foo]\');\n
+\n
+  MT(\'h6\',\n
+      \'[header&header-6 h6. foo]\');\n
+\n
+  MT(\'h7Bogus\',\n
+      \'h7. foo\');\n
+\n
+  MT(\'multipleHeaders\',\n
+      \'[header&header-1 h1. Heading 1]\',\n
+      \'\',\n
+      \'Some text.\',\n
+      \'\',\n
+      \'[header&header-2 h2. Heading 2]\',\n
+      \'\',\n
+      \'More text.\');\n
+\n
+  MT(\'h1inline\',\n
+      \'[header&header-1 h1. foo ][header&header-1&em _bar_][header&header-1  baz]\');\n
+\n
+  /*\n
+   * Lists\n
+   */\n
+\n
+  MT(\'ul\',\n
+      \'foo\',\n
+      \'bar\',\n
+      \'\',\n
+      \'[variable-2 * foo]\',\n
+      \'[variable-2 * bar]\');\n
+\n
+  MT(\'ulNoBlank\',\n
+      \'foo\',\n
+      \'bar\',\n
+      \'[variable-2 * foo]\',\n
+      \'[variable-2 * bar]\');\n
+\n
+  MT(\'ol\',\n
+      \'foo\',\n
+      \'bar\',\n
+      \'\',\n
+      \'[variable-2 # foo]\',\n
+      \'[variable-2 # bar]\');\n
+\n
+  MT(\'olNoBlank\',\n
+      \'foo\',\n
+      \'bar\',\n
+      \'[variable-2 # foo]\',\n
+      \'[variable-2 # bar]\');\n
+\n
+  MT(\'ulFormatting\',\n
+      \'[variable-2 * ][variable-2&em _foo_][variable-2  bar]\',\n
+      \'[variable-2 * ][variable-2&strong *][variable-2&em&strong _foo_]\' +\n
+        \'[variable-2&strong *][variable-2  bar]\',\n
+      \'[variable-2 * ][variable-2&strong *foo*][variable-2  bar]\');\n
+\n
+  MT(\'olFormatting\',\n
+      \'[variable-2 # ][variable-2&em _foo_][variable-2  bar]\',\n
+      \'[variable-2 # ][variable-2&strong *][variable-2&em&strong _foo_]\' +\n
+        \'[variable-2&strong *][variable-2  bar]\',\n
+      \'[variable-2 # ][variable-2&strong *foo*][variable-2  bar]\');\n
+\n
+  MT(\'ulNested\',\n
+      \'[variable-2 * foo]\',\n
+      \'[variable-3 ** bar]\',\n
+      \'[keyword *** bar]\',\n
+      \'[variable-2 **** bar]\',\n
+      \'[variable-3 ** bar]\');\n
+\n
+  MT(\'olNested\',\n
+      \'[variable-2 # foo]\',\n
+      \'[variable-3 ## bar]\',\n
+      \'[keyword ### bar]\',\n
+      \'[variable-2 #### bar]\',\n
+      \'[variable-3 ## bar]\');\n
+\n
+  MT(\'ulNestedWithOl\',\n
+      \'[variable-2 * foo]\',\n
+      \'[variable-3 ## bar]\',\n
+      \'[keyword *** bar]\',\n
+      \'[variable-2 #### bar]\',\n
+      \'[variable-3 ** bar]\');\n
+\n
+  MT(\'olNestedWithUl\',\n
+      \'[variable-2 # foo]\',\n
+      \'[variable-3 ** bar]\',\n
+      \'[keyword ### bar]\',\n
+      \'[variable-2 **** bar]\',\n
+      \'[variable-3 ## bar]\');\n
+\n
+  MT(\'definitionList\',\n
+      \'[number - coffee := Hot ][number&em _and_][number  black]\',\n
+      \'\',\n
+      \'Normal text.\');\n
+\n
+  MT(\'definitionListSpan\',\n
+      \'[number - coffee :=]\',\n
+      \'\',\n
+      \'[number Hot ][number&em _and_][number  black =:]\',\n
+      \'\',\n
+      \'Normal text.\');\n
+\n
+  MT(\'boo\',\n
+      \'[number - dog := woof woof]\',\n
+      \'[number - cat := meow meow]\',\n
+      \'[number - whale :=]\',\n
+      \'[number Whale noises.]\',\n
+      \'\',\n
+      \'[number Also, ][number&em _splashing_][number . =:]\');\n
+\n
+  /*\n
+   * Attributes\n
+   */\n
+\n
+  MT(\'divWithAttribute\',\n
+      \'[punctuation div][punctuation&attribute (#my-id)][punctuation . foo bar]\');\n
+\n
+  MT(\'divWithAttributeAnd2emRightPadding\',\n
+      \'[punctuation div][punctuation&attribute (#my-id)((][punctuation . foo bar]\');\n
+\n
+  MT(\'divWithClassAndId\',\n
+      \'[punctuation div][punctuation&attribute (my-class#my-id)][punctuation . foo bar]\');\n
+\n
+  MT(\'paragraphWithCss\',\n
+      \'p[attribute {color:red;}]. foo bar\');\n
+\n
+  MT(\'paragraphNestedStyles\',\n
+      \'p. [strong *foo ][strong&em _bar_][strong *]\');\n
+\n
+  MT(\'paragraphWithLanguage\',\n
+      \'p[attribute [[fr]]]. Parlez-vous fran莽ais?\');\n
+\n
+  MT(\'paragraphLeftAlign\',\n
+      \'p[attribute <]. Left\');\n
+\n
+  MT(\'paragraphRightAlign\',\n
+      \'p[attribute >]. Right\');\n
+\n
+  MT(\'paragraphRightAlign\',\n
+      \'p[attribute =]. Center\');\n
+\n
+  MT(\'paragraphJustified\',\n
+      \'p[attribute <>]. Justified\');\n
+\n
+  MT(\'paragraphWithLeftIndent1em\',\n
+      \'p[attribute (]. Left\');\n
+\n
+  MT(\'paragraphWithRightIndent1em\',\n
+      \'p[attribute )]. Right\');\n
+\n
+  MT(\'paragraphWithLeftIndent2em\',\n
+      \'p[attribute ((]. Left\');\n
+\n
+  MT(\'paragraphWithRightIndent2em\',\n
+      \'p[attribute ))]. Right\');\n
+\n
+  MT(\'paragraphWithLeftIndent3emRightIndent2em\',\n
+      \'p[attribute ((())]. Right\');\n
+\n
+  MT(\'divFormatting\',\n
+      \'[punctuation div. ][punctuation&strong *foo ]\' +\n
+        \'[punctuation&strong&em _bar_][punctuation&strong *]\');\n
+\n
+  MT(\'phraseModifierAttributes\',\n
+      \'p[attribute (my-class)]. This is a paragraph that has a class and\' +\n
+      \' this [em _][em&attribute (#special-phrase)][em emphasized phrase_]\' +\n
+      \' has an id.\');\n
+\n
+  MT(\'linkWithClass\',\n
+      \'[link "(my-class). This is a link with class":http://redcloth.org]\');\n
+\n
+  /*\n
+   * Layouts\n
+   */\n
+\n
+  MT(\'paragraphLayouts\',\n
+      \'p. This is one paragraph.\',\n
+      \'\',\n
+      \'p. This is another.\');\n
+\n
+  MT(\'div\',\n
+      \'[punctuation div. foo bar]\');\n
+\n
+  MT(\'pre\',\n
+      \'[operator pre. Text]\');\n
+\n
+  MT(\'bq.\',\n
+      \'[bracket bq. foo bar]\',\n
+      \'\',\n
+      \'Normal text.\');\n
+\n
+  MT(\'footnote\',\n
+      \'[variable fn123. foo ][variable&strong *bar*]\');\n
+\n
+  /*\n
+   * Spanning Layouts\n
+   */\n
+\n
+  MT(\'bq..ThenParagraph\',\n
+      \'[bracket bq.. foo bar]\',\n
+      \'\',\n
+      \'[bracket More quote.]\',\n
+      \'p. Normal Text\');\n
+\n
+  MT(\'bq..ThenH1\',\n
+      \'[bracket bq.. foo bar]\',\n
+      \'\',\n
+      \'[bracket More quote.]\',\n
+      \'[header&header-1 h1. Header Text]\');\n
+\n
+  MT(\'bc..ThenParagraph\',\n
+      \'[atom bc.. # Some ruby code]\',\n
+      \'[atom obj = {foo: :bar}]\',\n
+      \'[atom puts obj]\',\n
+      \'\',\n
+      \'[atom obj[[:love]] = "*love*"]\',\n
+      \'[atom puts obj.love.upcase]\',\n
+      \'\',\n
+      \'p. Normal text.\');\n
+\n
+  MT(\'fn1..ThenParagraph\',\n
+      \'[variable fn1.. foo bar]\',\n
+      \'\',\n
+      \'[variable More.]\',\n
+      \'p. Normal Text\');\n
+\n
+  MT(\'pre..ThenParagraph\',\n
+      \'[operator pre.. foo bar]\',\n
+      \'\',\n
+      \'[operator More.]\',\n
+      \'p. Normal Text\');\n
+\n
+  /*\n
+   * Tables\n
+   */\n
+\n
+  MT(\'table\',\n
+      \'[variable-3&operator |_. name |_. age|]\',\n
+      \'[variable-3 |][variable-3&strong *Walter*][variable-3 |   5  |]\',\n
+      \'[variable-3 |Florence|   6  |]\',\n
+      \'\',\n
+      \'p. Normal text.\');\n
+\n
+  MT(\'tableWithAttributes\',\n
+      \'[variable-3&operator |_. name |_. age|]\',\n
+      \'[variable-3 |][variable-3&attribute /2.][variable-3  Jim |]\',\n
+      \'[variable-3 |][variable-3&attribute \\\\2{color: red}.][variable-3  Sam |]\');\n
+\n
+  /*\n
+   * HTML\n
+   */\n
+\n
+  MT(\'html\',\n
+      \'[comment <div id="wrapper">]\',\n
+      \'[comment <section id="introduction">]\',\n
+      \'\',\n
+      \'[header&header-1 h1. Welcome]\',\n
+      \'\',\n
+      \'[variable-2 * Item one]\',\n
+      \'[variable-2 * Item two]\',\n
+      \'\',\n
+      \'[comment <a href="http://example.com">Example</a>]\',\n
+      \'\',\n
+      \'[comment </section>]\',\n
+      \'[comment </div>]\');\n
+\n
+  MT(\'inlineHtml\',\n
+      \'I can use HTML directly in my [comment <span class="youbetcha">Textile</span>].\');\n
+\n
+  /*\n
+   * No-Textile\n
+   */\n
+\n
+  MT(\'notextile\',\n
+    \'[string-2 notextile. *No* formatting]\');\n
+\n
+  MT(\'notextileInline\',\n
+      \'Use [string-2 ==*asterisks*==] for [strong *strong*] text.\');\n
+\n
+  MT(\'notextileWithPre\',\n
+      \'[operator pre. *No* formatting]\');\n
+\n
+  MT(\'notextileWithSpanningPre\',\n
+      \'[operator pre.. *No* formatting]\',\n
+      \'\',\n
+      \'[operator *No* formatting]\');\n
+\n
+  /* Only toggling phrases between non-word chars. */\n
+\n
+  MT(\'phrase-in-word\',\n
+     \'foo_bar_baz\');\n
+\n
+  MT(\'phrase-non-word\',\n
+     \'[negative -x-] aaa-bbb ccc-ddd [negative -eee-] fff [negative -ggg-]\');\n
+\n
+  MT(\'phrase-lone-dash\',\n
+     \'foo - bar - baz\');\n
+})();\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>9437</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile/textile.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile/textile.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f2f6defd10813cf6194e61d266dc2841c2bbee64
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/textile/textile.js.xml
@@ -0,0 +1,513 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897140.94</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>textile.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") { // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  } else if (typeof define == "function" && define.amd) { // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  } else { // Plain browser env\n
+    mod(CodeMirror);\n
+  }\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  var TOKEN_STYLES = {\n
+    addition: "positive",\n
+    attributes: "attribute",\n
+    bold: "strong",\n
+    cite: "keyword",\n
+    code: "atom",\n
+    definitionList: "number",\n
+    deletion: "negative",\n
+    div: "punctuation",\n
+    em: "em",\n
+    footnote: "variable",\n
+    footCite: "qualifier",\n
+    header: "header",\n
+    html: "comment",\n
+    image: "string",\n
+    italic: "em",\n
+    link: "link",\n
+    linkDefinition: "link",\n
+    list1: "variable-2",\n
+    list2: "variable-3",\n
+    list3: "keyword",\n
+    notextile: "string-2",\n
+    pre: "operator",\n
+    p: "property",\n
+    quote: "bracket",\n
+    span: "quote",\n
+    specialChar: "tag",\n
+    strong: "strong",\n
+    sub: "builtin",\n
+    sup: "builtin",\n
+    table: "variable-3",\n
+    tableHeading: "operator"\n
+  };\n
+\n
+  function startNewLine(stream, state) {\n
+    state.mode = Modes.newLayout;\n
+    state.tableHeading = false;\n
+\n
+    if (state.layoutType === "definitionList" && state.spanningLayout &&\n
+        stream.match(RE("definitionListEnd"), false))\n
+      state.spanningLayout = false;\n
+  }\n
+\n
+  function handlePhraseModifier(stream, state, ch) {\n
+    if (ch === "_") {\n
+      if (stream.eat("_"))\n
+        return togglePhraseModifier(stream, state, "italic", /__/, 2);\n
+      else\n
+        return togglePhraseModifier(stream, state, "em", /_/, 1);\n
+    }\n
+\n
+    if (ch === "*") {\n
+      if (stream.eat("*")) {\n
+        return togglePhraseModifier(stream, state, "bold", /\\*\\*/, 2);\n
+      }\n
+      return togglePhraseModifier(stream, state, "strong", /\\*/, 1);\n
+    }\n
+\n
+    if (ch === "[") {\n
+      if (stream.match(/\\d+\\]/)) state.footCite = true;\n
+      return tokenStyles(state);\n
+    }\n
+\n
+    if (ch === "(") {\n
+      var spec = stream.match(/^(r|tm|c)\\)/);\n
+      if (spec)\n
+        return tokenStylesWith(state, TOKEN_STYLES.specialChar);\n
+    }\n
+\n
+    if (ch === "<" && stream.match(/(\\w+)[^>]+>[^<]+<\\/\\1>/))\n
+      return tokenStylesWith(state, TOKEN_STYLES.html);\n
+\n
+    if (ch === "?" && stream.eat("?"))\n
+      return togglePhraseModifier(stream, state, "cite", /\\?\\?/, 2);\n
+\n
+    if (ch === "=" && stream.eat("="))\n
+      return togglePhraseModifier(stream, state, "notextile", /==/, 2);\n
+\n
+    if (ch === "-" && !stream.eat("-"))\n
+      return togglePhraseModifier(stream, state, "deletion", /-/, 1);\n
+\n
+    if (ch === "+")\n
+      return togglePhraseModifier(stream, state, "addition", /\\+/, 1);\n
+\n
+    if (ch === "~")\n
+      return togglePhraseModifier(stream, state, "sub", /~/, 1);\n
+\n
+    if (ch === "^")\n
+      return togglePhraseModifier(stream, state, "sup", /\\^/, 1);\n
+\n
+    if (ch === "%")\n
+      return togglePhraseModifier(stream, state, "span", /%/, 1);\n
+\n
+    if (ch === "@")\n
+      return togglePhraseModifier(stream, state, "code", /@/, 1);\n
+\n
+    if (ch === "!") {\n
+      var type = togglePhraseModifier(stream, state, "image", /(?:\\([^\\)]+\\))?!/, 1);\n
+      stream.match(/^:\\S+/); // optional Url portion\n
+      return type;\n
+    }\n
+    return tokenStyles(state);\n
+  }\n
+\n
+  function togglePhraseModifier(stream, state, phraseModifier, closeRE, openSize) {\n
+    var charBefore = stream.pos > openSize ? stream.string.charAt(stream.pos - openSize - 1) : null;\n
+    var charAfter = stream.peek();\n
+    if (state[phraseModifier]) {\n
+      if ((!charAfter || /\\W/.test(charAfter)) && charBefore && /\\S/.test(charBefore)) {\n
+        var type = tokenStyles(state);\n
+        state[phraseModifier] = false;\n
+        return type;\n
+      }\n
+    } else if ((!charBefore || /\\W/.test(charBefore)) && charAfter && /\\S/.test(charAfter) &&\n
+               stream.match(new RegExp("^.*\\\\S" + closeRE.source + "(?:\\\\W|$)"), false)) {\n
+      state[phraseModifier] = true;\n
+      state.mode = Modes.attributes;\n
+    }\n
+    return tokenStyles(state);\n
+  };\n
+\n
+  function tokenStyles(state) {\n
+    var disabled = textileDisabled(state);\n
+    if (disabled) return disabled;\n
+\n
+    var styles = [];\n
+    if (state.layoutType) styles.push(TOKEN_STYLES[state.layoutType]);\n
+\n
+    styles = styles.concat(activeStyles(\n
+      state, "addition", "bold", "cite", "code", "deletion", "em", "footCite",\n
+      "image", "italic", "link", "span", "strong", "sub", "sup", "table", "tableHeading"));\n
+\n
+    if (state.layoutType === "header")\n
+      styles.push(TOKEN_STYLES.header + "-" + state.header);\n
+\n
+    return styles.length ? styles.join(" ") : null;\n
+  }\n
+\n
+  function textileDisabled(state) {\n
+    var type = state.layoutType;\n
+\n
+    switch(type) {\n
+    case "notextile":\n
+    case "code":\n
+    case "pre":\n
+      return TOKEN_STYLES[type];\n
+    default:\n
+      if (state.notextile)\n
+        return TOKEN_STYLES.notextile + (type ? (" " + TOKEN_STYLES[type]) : "");\n
+      return null;\n
+    }\n
+  }\n
+\n
+  function tokenStylesWith(state, extraStyles) {\n
+    var disabled = textileDisabled(state);\n
+    if (disabled) return disabled;\n
+\n
+    var type = tokenStyles(state);\n
+    if (extraStyles)\n
+      return type ? (type + " " + extraStyles) : extraStyles;\n
+    else\n
+      return type;\n
+  }\n
+\n
+  function activeStyles(state) {\n
+    var styles = [];\n
+    for (var i = 1; i < arguments.length; ++i) {\n
+      if (state[arguments[i]])\n
+        styles.push(TOKEN_STYLES[arguments[i]]);\n
+    }\n
+    return styles;\n
+  }\n
+\n
+  function blankLine(state) {\n
+    var spanningLayout = state.spanningLayout, type = state.layoutType;\n
+\n
+    for (var key in state) if (state.hasOwnProperty(key))\n
+      delete state[key];\n
+\n
+    state.mode = Modes.newLayout;\n
+    if (spanningLayout) {\n
+      state.layoutType = type;\n
+      state.spanningLayout = true;\n
+    }\n
+  }\n
+\n
+  var REs = {\n
+    cache: {},\n
+    single: {\n
+      bc: "bc",\n
+      bq: "bq",\n
+      definitionList: /- [^(?::=)]+:=+/,\n
+      definitionListEnd: /.*=:\\s*$/,\n
+      div: "div",\n
+      drawTable: /\\|.*\\|/,\n
+      foot: /fn\\d+/,\n
+      header: /h[1-6]/,\n
+      html: /\\s*<(?:\\/)?(\\w+)(?:[^>]+)?>(?:[^<]+<\\/\\1>)?/,\n
+      link: /[^"]+":\\S/,\n
+      linkDefinition: /\\[[^\\s\\]]+\\]\\S+/,\n
+      list: /(?:#+|\\*+)/,\n
+      notextile: "notextile",\n
+      para: "p",\n
+      pre: "pre",\n
+      table: "table",\n
+      tableCellAttributes: /[\\/\\\\]\\d+/,\n
+      tableHeading: /\\|_\\./,\n
+      tableText: /[^"_\\*\\[\\(\\?\\+~\\^%@|-]+/,\n
+      text: /[^!"_=\\*\\[\\(<\\?\\+~\\^%@-]+/\n
+    },\n
+    attributes: {\n
+      align: /(?:<>|<|>|=)/,\n
+      selector: /\\([^\\(][^\\)]+\\)/,\n
+      lang: /\\[[^\\[\\]]+\\]/,\n
+      pad: /(?:\\(+|\\)+){1,2}/,\n
+      css: /\\{[^\\}]+\\}/\n
+    },\n
+    createRe: function(name) {\n
+      switch (name) {\n
+      case "drawTable":\n
+        return REs.makeRe("^", REs.single.drawTable, "$");\n
+      case "html":\n
+        return REs.makeRe("^", REs.single.html, "(?:", REs.single.html, ")*", "$");\n
+      case "linkDefinition":\n
+        return REs.makeRe("^", REs.single.linkDefinition, "$");\n
+      case "listLayout":\n
+        return REs.makeRe("^", REs.single.list, RE("allAttributes"), "*\\\\s+");\n
+      case "tableCellAttributes":\n
+        return REs.makeRe("^", REs.choiceRe(REs.single.tableCellAttributes,\n
+                                            RE("allAttributes")), "+\\\\.");\n
+      case "type":\n
+        return REs.makeRe("^", RE("allTypes"));\n
+      case "typeLayout":\n
+        return REs.makeRe("^", RE("allTypes"), RE("allAttributes"),\n
+                          "*\\\\.\\\\.?", "(\\\\s+|$)");\n
+      case "attributes":\n
+        return REs.makeRe("^", RE("allAttributes"), "+");\n
+\n
+      case "allTypes":\n
+        return REs.choiceRe(REs.single.div, REs.single.foot,\n
+                            REs.single.header, REs.single.bc, REs.single.bq,\n
+                            REs.single.notextile, REs.single.pre, REs.single.table,\n
+                            REs.single.para);\n
+\n
+      case "allAttributes":\n
+        return REs.choiceRe(REs.attributes.selector, REs.attributes.css,\n
+                            REs.attributes.lang, REs.attributes.align, REs.attributes.pad);\n
+\n
+      default:\n
+        return REs.makeRe("^", REs.single[name]);\n
+      }\n
+    },\n
+    makeRe: function() {\n
+      var pattern = "";\n
+      for (var i = 0; i < arguments.length; ++i) {\n
+        var arg = arguments[i];\n
+        pattern += (typeof arg === "string") ? arg : arg.source;\n
+      }\n
+      return new RegExp(pattern);\n
+    },\n
+    choiceRe: function() {\n
+      var parts = [arguments[0]];\n
+      for (var i = 1; i < arguments.length; ++i) {\n
+        parts[i * 2 - 1] = "|";\n
+        parts[i * 2] = arguments[i];\n
+      }\n
+\n
+      parts.unshift("(?:");\n
+      parts.push(")");\n
+      return REs.makeRe.apply(null, parts);\n
+    }\n
+  };\n
+\n
+  function RE(name) {\n
+    return (REs.cache[name] || (REs.cache[name] = REs.createRe(name)));\n
+  }\n
+\n
+  var Modes = {\n
+    newLayout: function(stream, state) {\n
+      if (stream.match(RE("typeLayout"), false)) {\n
+        state.spanningLayout = false;\n
+        return (state.mode = Modes.blockType)(stream, state);\n
+      }\n
+      var newMode;\n
+      if (!textileDisabled(state)) {\n
+        if (stream.match(RE("listLayout"), false))\n
+          newMode = Modes.list;\n
+        else if (stream.match(RE("drawTable"), false))\n
+          newMode = Modes.table;\n
+        else if (stream.match(RE("linkDefinition"), false))\n
+          newMode = Modes.linkDefinition;\n
+        else if (stream.match(RE("definitionList")))\n
+          newMode = Modes.definitionList;\n
+        else if (stream.match(RE("html"), false))\n
+          newMode = Modes.html;\n
+      }\n
+      return (state.mode = (newMode || Modes.text))(stream, state);\n
+    },\n
+\n
+    blockType: function(stream, state) {\n
+      var match, type;\n
+      state.layoutType = null;\n
+\n
+      if (match = stream.match(RE("type")))\n
+        type = match[0];\n
+      else\n
+        return (state.mode = Modes.text)(stream, state);\n
+\n
+      if (match = type.match(RE("header"))) {\n
+        state.layoutType = "header";\n
+        state.header = parseInt(match[0][1]);\n
+      } else if (type.match(RE("bq"))) {\n
+        state.layoutType = "quote";\n
+      } else if (type.match(RE("bc"))) {\n
+        state.layoutType = "code";\n
+      } else if (type.match(RE("foot"))) {\n
+        state.layoutType = "footnote";\n
+      } else if (type.match(RE("notextile"))) {\n
+        state.layoutType = "notextile";\n
+      } else if (type.match(RE("pre"))) {\n
+        state.layoutType = "pre";\n
+      } else if (type.match(RE("div"))) {\n
+        state.layoutType = "div";\n
+      } else if (type.match(RE("table"))) {\n
+        state.layoutType = "table";\n
+      }\n
+\n
+      state.mode = Modes.attributes;\n
+      return tokenStyles(state);\n
+    },\n
+\n
+    text: function(stream, state) {\n
+      if (stream.match(RE("text"))) return tokenStyles(state);\n
+\n
+      var ch = stream.next();\n
+      if (ch === \'"\')\n
+        return (state.mode = Modes.link)(stream, state);\n
+      return handlePhraseModifier(stream, state, ch);\n
+    },\n
+\n
+    attributes: function(stream, state) {\n
+      state.mode = Modes.layoutLength;\n
+\n
+      if (stream.match(RE("attributes")))\n
+        return tokenStylesWith(state, TOKEN_STYLES.attributes);\n
+      else\n
+        return tokenStyles(state);\n
+    },\n
+\n
+    layoutLength: function(stream, state) {\n
+      if (stream.eat(".") && stream.eat("."))\n
+        state.spanningLayout = true;\n
+\n
+      state.mode = Modes.text;\n
+      return tokenStyles(state);\n
+    },\n
+\n
+    list: function(stream, state) {\n
+      var match = stream.match(RE("list"));\n
+      state.listDepth = match[0].length;\n
+      var listMod = (state.listDepth - 1) % 3;\n
+      if (!listMod)\n
+        state.layoutType = "list1";\n
+      else if (listMod === 1)\n
+        state.layoutType = "list2";\n
+      else\n
+        state.layoutType = "list3";\n
+\n
+      state.mode = Modes.attributes;\n
+      return tokenStyles(state);\n
+    },\n
+\n
+    link: function(stream, state) {\n
+      state.mode = Modes.text;\n
+      if (stream.match(RE("link"))) {\n
+        stream.match(/\\S+/);\n
+        return tokenStylesWith(state, TOKEN_STYLES.link);\n
+      }\n
+      return tokenStyles(state);\n
+    },\n
+\n
+    linkDefinition: function(stream, state) {\n
+      stream.skipToEnd();\n
+      return tokenStylesWith(state, TOKEN_STYLES.linkDefinition);\n
+    },\n
+\n
+    definitionList: function(stream, state) {\n
+      stream.match(RE("definitionList"));\n
+\n
+      state.layoutType = "definitionList";\n
+\n
+      if (stream.match(/\\s*$/))\n
+        state.spanningLayout = true;\n
+      else\n
+        state.mode = Modes.attributes;\n
+\n
+      return tokenStyles(state);\n
+    },\n
+\n
+    html: function(stream, state) {\n
+      stream.skipToEnd();\n
+      return tokenStylesWith(state, TOKEN_STYLES.html);\n
+    },\n
+\n
+    table: function(stream, state) {\n
+      state.layoutType = "table";\n
+      return (state.mode = Modes.tableCell)(stream, state);\n
+    },\n
+\n
+    tableCell: function(stream, state) {\n
+      if (stream.match(RE("tableHeading")))\n
+        state.tableHeading = true;\n
+      else\n
+        stream.eat("|");\n
+\n
+      state.mode = Modes.tableCellAttributes;\n
+      return tokenStyles(state);\n
+    },\n
+\n
+    tableCellAttributes: function(stream, state) {\n
+      state.mode = Modes.tableText;\n
+\n
+      if (stream.match(RE("tableCellAttributes")))\n
+        return tokenStylesWith(state, TOKEN_STYLES.attributes);\n
+      else\n
+        return tokenStyles(state);\n
+    },\n
+\n
+    tableText: function(stream, state) {\n
+      if (stream.match(RE("tableText")))\n
+        return tokenStyles(state);\n
+\n
+      if (stream.peek() === "|") { // end of cell\n
+        state.mode = Modes.tableCell;\n
+        return tokenStyles(state);\n
+      }\n
+      return handlePhraseModifier(stream, state, stream.next());\n
+    }\n
+  };\n
+\n
+  CodeMirror.defineMode("textile", function() {\n
+    return {\n
+      startState: function() {\n
+        return { mode: Modes.newLayout };\n
+      },\n
+      token: function(stream, state) {\n
+        if (stream.sol()) startNewLine(stream, state);\n
+        return state.mode(stream, state);\n
+      },\n
+      blankLine: blankLine\n
+    };\n
+  });\n
+\n
+  CodeMirror.defineMIME("text/x-textile", "textile");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>13842</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiddlywiki/tiddlywiki.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiddlywiki/tiddlywiki.js.xml
index 7542ecbfb3c1c2aeec36042c1bf1e17abdcc1f15..26effe7966fb4881b15907699baec21b97b6f750 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiddlywiki/tiddlywiki.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiddlywiki/tiddlywiki.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403099.69</string> </value>
+            <value> <string>ts21897134.83</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /***\n
     |\'\'Name\'\'|tiddlywiki.js|\n
     |\'\'Description\'\'|Enables TiddlyWikiy syntax highlighting using CodeMirror|\n
@@ -38,6 +41,17 @@
     CoreVersion parameter is needed for TiddlyWiki only!\n
 ***/\n
 //{{{\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("tiddlywiki", function () {\n
   // Tokenizer\n
   var textwords = {};\n
@@ -374,6 +388,8 @@ CodeMirror.defineMode("tiddlywiki", function () {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");\n
+});\n
+\n
 //}}}\n
 
 
@@ -385,7 +401,7 @@ CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9733</int> </value>
+            <value> <int>10195</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiki/tiki.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiki/tiki.js.xml
index c7f6922e60eb5892600c038ed7aa6f2ce11ee249..aa938a455b669155e05c40a2195ebd5235fa19e9 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiki/tiki.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tiki/tiki.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403092.95</string> </value>
+            <value> <string>ts21897142.34</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode(\'tiki\', function(config) {\n
   function inBlock(style, terminator, returnTokenizer) {\n
     return function(stream, state) {\n
@@ -330,6 +343,8 @@ return {\n
 });\n
 \n
 CodeMirror.defineMIME("text/tiki", "tiki");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -340,7 +355,7 @@ CodeMirror.defineMIME("text/tiki", "tiki");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>8194</int> </value>
+            <value> <int>8655</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/toml/toml.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/toml/toml.js.xml
index c16fdbf660fdf90f0d9930ef0939aac752e3c971..402687047aceccbe4170111e06dfd05a7c56e964 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/toml/toml.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/toml/toml.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403086.82</string> </value>
+            <value> <string>ts21897149.11</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("toml", function () {\n
   return {\n
     startState: function () {\n
@@ -62,6 +75,8 @@ CodeMirror.defineMode("toml", function () {\n
         return \'bracket\';\n
       } else if (state.lhs && stream.peek() === \'[\' && stream.skipTo(\']\')) {\n
         stream.next();//skip closing ]\n
+        // array of objects has an extra open & close []\n
+        if (stream.peek() === \']\') stream.next();\n
         return "atom";\n
       } else if (stream.peek() === "#") {\n
         stream.skipToEnd();\n
@@ -93,6 +108,8 @@ CodeMirror.defineMode("toml", function () {\n
 });\n
 \n
 CodeMirror.defineMIME(\'text/x-toml\', \'toml\');\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -103,7 +120,7 @@ CodeMirror.defineMIME(\'text/x-toml\', \'toml\');\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2329</int> </value>
+            <value> <int>2897</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tornado.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tornado.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2e8295fdaf819d5d0307ac3da2c9b1c5e16872e4
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tornado.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>tornado</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tornado/tornado.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tornado/tornado.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2fb09327c33a1d353f710ece6e214cd7cb02f566
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/tornado/tornado.js.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897140.35</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>tornado.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),\n
+        require("../../addon/mode/overlay"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror", "../htmlmixed/htmlmixed",\n
+            "../../addon/mode/overlay"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+  "use strict";\n
+\n
+  CodeMirror.defineMode("tornado:inner", function() {\n
+    var keywords = ["and","as","assert","autoescape","block","break","class","comment","context",\n
+                    "continue","datetime","def","del","elif","else","end","escape","except",\n
+                    "exec","extends","false","finally","for","from","global","if","import","in",\n
+                    "include","is","json_encode","lambda","length","linkify","load","module",\n
+                    "none","not","or","pass","print","put","raise","raw","return","self","set",\n
+                    "squeeze","super","true","try","url_escape","while","with","without","xhtml_escape","yield"];\n
+    keywords = new RegExp("^((" + keywords.join(")|(") + "))\\\\b");\n
+\n
+    function tokenBase (stream, state) {\n
+      stream.eatWhile(/[^\\{]/);\n
+      var ch = stream.next();\n
+      if (ch == "{") {\n
+        if (ch = stream.eat(/\\{|%|#/)) {\n
+          state.tokenize = inTag(ch);\n
+          return "tag";\n
+        }\n
+      }\n
+    }\n
+    function inTag (close) {\n
+      if (close == "{") {\n
+        close = "}";\n
+      }\n
+      return function (stream, state) {\n
+        var ch = stream.next();\n
+        if ((ch == close) && stream.eat("}")) {\n
+          state.tokenize = tokenBase;\n
+          return "tag";\n
+        }\n
+        if (stream.match(keywords)) {\n
+          return "keyword";\n
+        }\n
+        return close == "#" ? "comment" : "string";\n
+      };\n
+    }\n
+    return {\n
+      startState: function () {\n
+        return {tokenize: tokenBase};\n
+      },\n
+      token: function (stream, state) {\n
+        return state.tokenize(stream, state);\n
+      }\n
+    };\n
+  });\n
+\n
+  CodeMirror.defineMode("tornado", function(config) {\n
+    var htmlBase = CodeMirror.getMode(config, "text/html");\n
+    var tornadoInner = CodeMirror.getMode(config, "tornado:inner");\n
+    return CodeMirror.overlayMode(htmlBase, tornadoInner);\n
+  });\n
+\n
+  CodeMirror.defineMIME("text/x-tornado", "tornado");\n
+});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2496</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/turtle/turtle.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/turtle/turtle.js.xml
index 9a8757466e3211c677bd0c570753d49df54b41ab..c767cdccc156e3461c5a3d9ddb9df64b5c2e4536 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/turtle/turtle.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/turtle/turtle.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403102.45</string> </value>
+            <value> <string>ts21897132.95</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("turtle", function(config) {\n
   var indentUnit = config.indentUnit;\n
   var curPunc;\n
@@ -162,11 +175,15 @@ CodeMirror.defineMode("turtle", function(config) {\n
         return context.col + (closing ? 0 : 1);\n
       else\n
         return context.indent + (closing ? 0 : indentUnit);\n
-    }\n
+    },\n
+\n
+    lineComment: "#"\n
   };\n
 });\n
 \n
 CodeMirror.defineMIME("text/turtle", "turtle");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -177,7 +194,7 @@ CodeMirror.defineMIME("text/turtle", "turtle");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4365</int> </value>
+            <value> <int>4849</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vb/vb.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vb/vb.js.xml
index 6fabe3fd8ede707255509aaabc54e80e29934721..a8ae8dda9234ef168e7ad57a2faeceb592794502 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vb/vb.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vb/vb.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403100.74</string> </value>
+            <value> <string>ts21897134.16</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("vb", function(conf, parserConf) {\n
     var ERRORCLASS = \'error\';\n
 \n
@@ -281,6 +294,8 @@ CodeMirror.defineMode("vb", function(conf, parserConf) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-vb", "vb");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -291,7 +306,7 @@ CodeMirror.defineMIME("text/x-vb", "vb");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>8033</int> </value>
+            <value> <int>8494</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vbscript/vbscript.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vbscript/vbscript.js.xml
index 55195cd87f8d4899dae7efb98e05e7feb84d8f45..9825ba10b6b78b1592612ac07abc8a4dbbc23ac5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vbscript/vbscript.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/vbscript/vbscript.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403099.15</string> </value>
+            <value> <string>ts21897135.33</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 /*\n
 For extra ASP classic objects, initialize CodeMirror instance with this option:\n
     isASP: true\n
@@ -32,6 +35,17 @@ E.G.:\n
         isASP: true\n
       });\n
 */\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("vbscript", function(conf, parserConf) {\n
     var ERRORCLASS = \'error\';\n
 \n
@@ -301,7 +315,7 @@ CodeMirror.defineMode("vbscript", function(conf, parserConf) {\n
             style = state.tokenize(stream, state);\n
 \n
             current = stream.current();\n
-            if (style.substr(0, 8) === \'variable\' || style===\'builtin\' || style===\'keyword\'){//|| knownWords.indexOf(current.substring(1)) > -1) {\n
+            if (style && (style.substr(0, 8) === \'variable\' || style===\'builtin\' || style===\'keyword\')){//|| knownWords.indexOf(current.substring(1)) > -1) {\n
                 if (style === \'builtin\' || style === \'keyword\') style=\'variable\';\n
                 if (knownWords.indexOf(current.substr(1)) > -1) style=\'variable-2\';\n
 \n
@@ -356,6 +370,8 @@ CodeMirror.defineMode("vbscript", function(conf, parserConf) {\n
 });\n
 \n
 CodeMirror.defineMIME("text/vbscript", "vbscript");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -366,7 +382,7 @@ CodeMirror.defineMIME("text/vbscript", "vbscript");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>13320</int> </value>
+            <value> <int>13793</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/velocity/velocity.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/velocity/velocity.js.xml
index 2ef3d20ac881ad9515075386ba9d79544b03d667..1cdd32ba78124310313bb2876981e7116f4216c4 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/velocity/velocity.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/velocity/velocity.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403088.24</string> </value>
+            <value> <string>ts21897147.52</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("velocity", function() {\n
     function parseWords(str) {\n
         var obj = {}, words = str.split(" ");\n
@@ -208,6 +221,8 @@ CodeMirror.defineMode("velocity", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/velocity", "velocity");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -218,7 +233,7 @@ CodeMirror.defineMIME("text/velocity", "velocity");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6618</int> </value>
+            <value> <int>7079</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..119b14f5bad069f1a2f716181b0f4fdd39b17c35
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/test.js.xml
@@ -0,0 +1,313 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897132.59</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
+  var mode = CodeMirror.getMode({indentUnit: 4}, "verilog");\n
+  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }\n
+\n
+  MT("binary_literals",\n
+     "[number 1\'b0]",\n
+     "[number 1\'b1]",\n
+     "[number 1\'bx]",\n
+     "[number 1\'bz]",\n
+     "[number 1\'bX]",\n
+     "[number 1\'bZ]",\n
+     "[number 1\'B0]",\n
+     "[number 1\'B1]",\n
+     "[number 1\'Bx]",\n
+     "[number 1\'Bz]",\n
+     "[number 1\'BX]",\n
+     "[number 1\'BZ]",\n
+     "[number 1\'b0]",\n
+     "[number 1\'b1]",\n
+     "[number 2\'b01]",\n
+     "[number 2\'bxz]",\n
+     "[number 2\'b11]",\n
+     "[number 2\'b10]",\n
+     "[number 2\'b1Z]",\n
+     "[number 12\'b0101_0101_0101]",\n
+     "[number 1\'b 0]",\n
+     "[number \'b0101]"\n
+  );\n
+\n
+  MT("octal_literals",\n
+     "[number 3\'o7]",\n
+     "[number 3\'O7]",\n
+     "[number 3\'so7]",\n
+     "[number 3\'SO7]"\n
+  );\n
+\n
+  MT("decimal_literals",\n
+     "[number 0]",\n
+     "[number 1]",\n
+     "[number 7]",\n
+     "[number 123_456]",\n
+     "[number \'d33]",\n
+     "[number 8\'d255]",\n
+     "[number 8\'D255]",\n
+     "[number 8\'sd255]",\n
+     "[number 8\'SD255]",\n
+     "[number 32\'d123]",\n
+     "[number 32 \'d123]",\n
+     "[number 32 \'d 123]"\n
+  );\n
+\n
+  MT("hex_literals",\n
+     "[number 4\'h0]",\n
+     "[number 4\'ha]",\n
+     "[number 4\'hF]",\n
+     "[number 4\'hx]",\n
+     "[number 4\'hz]",\n
+     "[number 4\'hX]",\n
+     "[number 4\'hZ]",\n
+     "[number 32\'hdc78]",\n
+     "[number 32\'hDC78]",\n
+     "[number 32 \'hDC78]",\n
+     "[number 32\'h DC78]",\n
+     "[number 32 \'h DC78]",\n
+     "[number 32\'h44x7]",\n
+     "[number 32\'hFFF?]"\n
+  );\n
+\n
+  MT("real_number_literals",\n
+     "[number 1.2]",\n
+     "[number 0.1]",\n
+     "[number 2394.26331]",\n
+     "[number 1.2E12]",\n
+     "[number 1.2e12]",\n
+     "[number 1.30e-2]",\n
+     "[number 0.1e-0]",\n
+     "[number 23E10]",\n
+     "[number 29E-2]",\n
+     "[number 236.123_763_e-12]"\n
+  );\n
+\n
+  MT("operators",\n
+     "[meta ^]"\n
+  );\n
+\n
+  MT("keywords",\n
+     "[keyword logic]",\n
+     "[keyword logic] [variable foo]",\n
+     "[keyword reg] [variable abc]"\n
+  );\n
+\n
+  MT("variables",\n
+     "[variable _leading_underscore]",\n
+     "[variable _if]",\n
+     "[number 12] [variable foo]",\n
+     "[variable foo] [number 14]"\n
+  );\n
+\n
+  MT("tick_defines",\n
+     "[def `FOO]",\n
+     "[def `foo]",\n
+     "[def `FOO_bar]"\n
+  );\n
+\n
+  MT("system_calls",\n
+     "[meta $display]",\n
+     "[meta $vpi_printf]"\n
+  );\n
+\n
+  MT("line_comment", "[comment // Hello world]");\n
+\n
+  // Alignment tests\n
+  MT("align_port_map_style1",\n
+     /**\n
+      * mod mod(.a(a),\n
+      *         .b(b)\n
+      *        );\n
+      */\n
+     "[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],",\n
+     "        .[variable b][bracket (][variable b][bracket )]",\n
+     "       [bracket )];",\n
+     ""\n
+  );\n
+\n
+  MT("align_port_map_style2",\n
+     /**\n
+      * mod mod(\n
+      *     .a(a),\n
+      *     .b(b)\n
+      * );\n
+      */\n
+     "[variable mod] [variable mod][bracket (]",\n
+     "    .[variable a][bracket (][variable a][bracket )],",\n
+     "    .[variable b][bracket (][variable b][bracket )]",\n
+     "[bracket )];",\n
+     ""\n
+  );\n
+\n
+  // Indentation tests\n
+  MT("indent_single_statement_if",\n
+      "[keyword if] [bracket (][variable foo][bracket )]",\n
+      "    [keyword break];",\n
+      ""\n
+  );\n
+\n
+  MT("no_indent_after_single_line_if",\n
+      "[keyword if] [bracket (][variable foo][bracket )] [keyword break];",\n
+      ""\n
+  );\n
+\n
+  MT("indent_after_if_begin_same_line",\n
+      "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]",\n
+      "    [keyword break];",\n
+      "    [keyword break];",\n
+      "[keyword end]",\n
+      ""\n
+  );\n
+\n
+  MT("indent_after_if_begin_next_line",\n
+      "[keyword if] [bracket (][variable foo][bracket )]",\n
+      "    [keyword begin]",\n
+      "        [keyword break];",\n
+      "        [keyword break];",\n
+      "    [keyword end]",\n
+      ""\n
+  );\n
+\n
+  MT("indent_single_statement_if_else",\n
+      "[keyword if] [bracket (][variable foo][bracket )]",\n
+      "    [keyword break];",\n
+      "[keyword else]",\n
+      "    [keyword break];",\n
+      ""\n
+  );\n
+\n
+  MT("indent_if_else_begin_same_line",\n
+      "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]",\n
+      "    [keyword break];",\n
+      "    [keyword break];",\n
+      "[keyword end] [keyword else] [keyword begin]",\n
+      "    [keyword break];",\n
+      "    [keyword break];",\n
+      "[keyword end]",\n
+      ""\n
+  );\n
+\n
+  MT("indent_if_else_begin_next_line",\n
+      "[keyword if] [bracket (][variable foo][bracket )]",\n
+      "    [keyword begin]",\n
+      "        [keyword break];",\n
+      "        [keyword break];",\n
+      "    [keyword end]",\n
+      "[keyword else]",\n
+      "    [keyword begin]",\n
+      "        [keyword break];",\n
+      "        [keyword break];",\n
+      "    [keyword end]",\n
+      ""\n
+  );\n
+\n
+  MT("indent_if_nested_without_begin",\n
+      "[keyword if] [bracket (][variable foo][bracket )]",\n
+      "    [keyword if] [bracket (][variable foo][bracket )]",\n
+      "        [keyword if] [bracket (][variable foo][bracket )]",\n
+      "            [keyword break];",\n
+      ""\n
+  );\n
+\n
+  MT("indent_case",\n
+      "[keyword case] [bracket (][variable state][bracket )]",\n
+      "    [variable FOO]:",\n
+      "        [keyword break];",\n
+      "    [variable BAR]:",\n
+      "        [keyword break];",\n
+      "[keyword endcase]",\n
+      ""\n
+  );\n
+\n
+  MT("unindent_after_end_with_preceding_text",\n
+      "[keyword begin]",\n
+      "    [keyword break]; [keyword end]",\n
+      ""\n
+  );\n
+\n
+  MT("export_function_one_line_does_not_indent",\n
+     "[keyword export] [string \\"DPI-C\\"] [keyword function] [variable helloFromSV];",\n
+     ""\n
+  );\n
+\n
+  MT("export_task_one_line_does_not_indent",\n
+     "[keyword export] [string \\"DPI-C\\"] [keyword task] [variable helloFromSV];",\n
+     ""\n
+  );\n
+\n
+  MT("export_function_two_lines_indents_properly",\n
+    "[keyword export]",\n
+    "    [string \\"DPI-C\\"] [keyword function] [variable helloFromSV];",\n
+    ""\n
+  );\n
+\n
+  MT("export_task_two_lines_indents_properly",\n
+    "[keyword export]",\n
+    "    [string \\"DPI-C\\"] [keyword task] [variable helloFromSV];",\n
+    ""\n
+  );\n
+\n
+  MT("import_function_one_line_does_not_indent",\n
+    "[keyword import] [string \\"DPI-C\\"] [keyword function] [variable helloFromC];",\n
+    ""\n
+  );\n
+\n
+  MT("import_task_one_line_does_not_indent",\n
+    "[keyword import] [string \\"DPI-C\\"] [keyword task] [variable helloFromC];",\n
+    ""\n
+  );\n
+\n
+  MT("import_package_single_line_does_not_indent",\n
+    "[keyword import] [variable p]::[variable x];",\n
+    "[keyword import] [variable p]::[variable y];",\n
+    ""\n
+  );\n
+\n
+  MT("covergoup_with_function_indents_properly",\n
+    "[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];",\n
+    "    [variable c] : [keyword coverpoint] [variable c];",\n
+    "[keyword endgroup]: [variable cg]",\n
+    ""\n
+  );\n
+\n
+})();\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>6776</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/verilog.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/verilog.js.xml
index b0b642f6071a3c8305634d69a0cfa76316c0c7af..af9ff915bb97a49cd5fb1cd901ebad2879fe42cb 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/verilog.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/verilog/verilog.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403102.81</string> </value>
+            <value> <string>ts21897132.45</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,36 +22,157 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("verilog", function(config, parserConfig) {\n
+\n
   var indentUnit = config.indentUnit,\n
-      keywords = parserConfig.keywords || {},\n
-      blockKeywords = parserConfig.blockKeywords || {},\n
-      atoms = parserConfig.atoms || {},\n
-      hooks = parserConfig.hooks || {},\n
+      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n
+      dontAlignCalls = parserConfig.dontAlignCalls,\n
+      noIndentKeywords = parserConfig.noIndentKeywords || [],\n
       multiLineStrings = parserConfig.multiLineStrings;\n
-  var isOperatorChar = /[&|~><!\\)\\(*#%@+\\/=?\\:;}{,\\.\\^\\-\\[\\]]/;\n
+\n
+  function words(str) {\n
+    var obj = {}, words = str.split(" ");\n
+    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
+    return obj;\n
+  }\n
+\n
+  /**\n
+   * Keywords from IEEE 1800-2012\n
+   */\n
+  var keywords = words(\n
+    "accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " +\n
+    "bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " +\n
+    "const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " +\n
+    "dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " +\n
+    "endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " +\n
+    "enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " +\n
+    "function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " +\n
+    "incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " +\n
+    "join_none large let liblist library local localparam logic longint macromodule matches medium modport module " +\n
+    "nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " +\n
+    "parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " +\n
+    "pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " +\n
+    "reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " +\n
+    "s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " +\n
+    "specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " +\n
+    "table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " +\n
+    "trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " +\n
+    "wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor");\n
+\n
+  /** Operators from IEEE 1800-2012\n
+     unary_operator ::=\n
+       + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~\n
+     binary_operator ::=\n
+       + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **\n
+       | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<\n
+       | -> | <->\n
+     inc_or_dec_operator ::= ++ | --\n
+     unary_module_path_operator ::=\n
+       ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~\n
+     binary_module_path_operator ::=\n
+       == | != | && | || | & | | | ^ | ^~ | ~^\n
+  */\n
+  var isOperatorChar = /[\\+\\-\\*\\/!~&|^%=?:]/;\n
+  var isBracketChar = /[\\[\\]{}()]/;\n
+\n
+  var unsignedNumber = /\\d[0-9_]*/;\n
+  var decimalLiteral = /\\d*\\s*\'s?d\\s*\\d[0-9_]*/i;\n
+  var binaryLiteral = /\\d*\\s*\'s?b\\s*[xz01][xz01_]*/i;\n
+  var octLiteral = /\\d*\\s*\'s?o\\s*[xz0-7][xz0-7_]*/i;\n
+  var hexLiteral = /\\d*\\s*\'s?h\\s*[0-9a-fxz?][0-9a-fxz?_]*/i;\n
+  var realLiteral = /(\\d[\\d_]*(\\.\\d[\\d_]*)?E-?[\\d_]+)|(\\d[\\d_]*\\.\\d[\\d_]*)/i;\n
+\n
+  var closingBracketOrWord = /^((\\w+)|[)}\\]])/;\n
+  var closingBracket = /[)}\\]]/;\n
 \n
   var curPunc;\n
+  var curKeyword;\n
+\n
+  // Block openings which are closed by a matching keyword in the form of ("end" + keyword)\n
+  // E.g. "task" => "endtask"\n
+  var blockKeywords = words(\n
+    "case checker class clocking config function generate interface module package" +\n
+    "primitive program property specify sequence table task"\n
+  );\n
+\n
+  // Opening/closing pairs\n
+  var openClose = {};\n
+  for (var keyword in blockKeywords) {\n
+    openClose[keyword] = "end" + keyword;\n
+  }\n
+  openClose["begin"] = "end";\n
+  openClose["casex"] = "endcase";\n
+  openClose["casez"] = "endcase";\n
+  openClose["do"   ] = "while";\n
+  openClose["fork" ] = "join;join_any;join_none";\n
+  openClose["covergroup"] = "endgroup";\n
+\n
+  for (var i in noIndentKeywords) {\n
+    var keyword = noIndentKeywords[i];\n
+    if (openClose[keyword]) {\n
+      openClose[keyword] = undefined;\n
+    }\n
+  }\n
+\n
+  // Keywords which open statements that are ended with a semi-colon\n
+  var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while");\n
 \n
   function tokenBase(stream, state) {\n
-    var ch = stream.next();\n
-    if (hooks[ch]) {\n
-      var result = hooks[ch](stream, state);\n
-      if (result !== false) return result;\n
+    var ch = stream.peek();\n
+    if (/[,;:\\.]/.test(ch)) {\n
+      curPunc = stream.next();\n
+      return null;\n
+    }\n
+    if (isBracketChar.test(ch)) {\n
+      curPunc = stream.next();\n
+      return "bracket";\n
+    }\n
+    // Macros (tick-defines)\n
+    if (ch == \'`\') {\n
+      stream.next();\n
+      if (stream.eatWhile(/[\\w\\$_]/)) {\n
+        return "def";\n
+      } else {\n
+        return null;\n
+      }\n
     }\n
+    // System calls\n
+    if (ch == \'$\') {\n
+      stream.next();\n
+      if (stream.eatWhile(/[\\w\\$_]/)) {\n
+        return "meta";\n
+      } else {\n
+        return null;\n
+      }\n
+    }\n
+    // Time literals\n
+    if (ch == \'#\') {\n
+      stream.next();\n
+      stream.eatWhile(/[\\d_.]/);\n
+      return "def";\n
+    }\n
+    // Strings\n
     if (ch == \'"\') {\n
+      stream.next();\n
       state.tokenize = tokenString(ch);\n
       return state.tokenize(stream, state);\n
     }\n
-    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n
-      curPunc = ch;\n
-      return null;\n
-    }\n
-    if (/[\\d\']/.test(ch)) {\n
-      stream.eatWhile(/[\\w\\.\']/);\n
-      return "number";\n
-    }\n
+    // Comments\n
     if (ch == "/") {\n
+      stream.next();\n
       if (stream.eat("*")) {\n
         state.tokenize = tokenComment;\n
         return tokenComment(stream, state);\n
@@ -60,19 +181,43 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {\n
         stream.skipToEnd();\n
         return "comment";\n
       }\n
+      stream.backUp(1);\n
+    }\n
+\n
+    // Numeric literals\n
+    if (stream.match(realLiteral) ||\n
+        stream.match(decimalLiteral) ||\n
+        stream.match(binaryLiteral) ||\n
+        stream.match(octLiteral) ||\n
+        stream.match(hexLiteral) ||\n
+        stream.match(unsignedNumber) ||\n
+        stream.match(realLiteral)) {\n
+      return "number";\n
     }\n
-    if (isOperatorChar.test(ch)) {\n
-      stream.eatWhile(isOperatorChar);\n
-      return "operator";\n
+\n
+    // Operators\n
+    if (stream.eatWhile(isOperatorChar)) {\n
+      return "meta";\n
     }\n
-    stream.eatWhile(/[\\w\\$_]/);\n
-    var cur = stream.current();\n
-    if (keywords.propertyIsEnumerable(cur)) {\n
-      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";\n
-      return "keyword";\n
+\n
+    // Keywords / plain variables\n
+    if (stream.eatWhile(/[\\w\\$_]/)) {\n
+      var cur = stream.current();\n
+      if (keywords[cur]) {\n
+        if (openClose[cur]) {\n
+          curPunc = "newblock";\n
+        }\n
+        if (statementKeywords[cur]) {\n
+          curPunc = "newstatement";\n
+        }\n
+        curKeyword = cur;\n
+        return "keyword";\n
+      }\n
+      return "variable";\n
     }\n
-    if (atoms.propertyIsEnumerable(cur)) return "atom";\n
-    return "variable";\n
+\n
+    stream.next();\n
+    return null;\n
   }\n
 \n
   function tokenString(quote) {\n
@@ -108,18 +253,56 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {\n
     this.prev = prev;\n
   }\n
   function pushContext(state, col, type) {\n
-    return state.context = new Context(state.indented, col, type, null, state.context);\n
+    var indent = state.indented;\n
+    var c = new Context(indent, col, type, null, state.context);\n
+    return state.context = c;\n
   }\n
   function popContext(state) {\n
     var t = state.context.type;\n
-    if (t == ")" || t == "]" || t == "}")\n
+    if (t == ")" || t == "]" || t == "}") {\n
       state.indented = state.context.indented;\n
+    }\n
     return state.context = state.context.prev;\n
   }\n
 \n
-  // Interface\n
+  function isClosing(text, contextClosing) {\n
+    if (text == contextClosing) {\n
+      return true;\n
+    } else {\n
+      // contextClosing may be mulitple keywords separated by ;\n
+      var closingKeywords = contextClosing.split(";");\n
+      for (var i in closingKeywords) {\n
+        if (text == closingKeywords[i]) {\n
+          return true;\n
+        }\n
+      }\n
+      return false;\n
+    }\n
+  }\n
+\n
+  function buildElectricInputRegEx() {\n
+    // Reindentation should occur on any bracket char: {}()[]\n
+    // or on a match of any of the block closing keywords, at\n
+    // the end of a line\n
+    var allClosings = [];\n
+    for (var i in openClose) {\n
+      if (openClose[i]) {\n
+        var closings = openClose[i].split(";");\n
+        for (var j in closings) {\n
+          allClosings.push(closings[j]);\n
+        }\n
+      }\n
+    }\n
+    var re = new RegExp("[{}()\\\\[\\\\]]|(" + allClosings.join("|") + ")$");\n
+    return re;\n
+  }\n
 \n
+  // Interface\n
   return {\n
+\n
+    // Regex to force current line to reindent\n
+    electricInput: buildElectricInputRegEx(),\n
+\n
     startState: function(basecolumn) {\n
       return {\n
         tokenize: null,\n
@@ -138,72 +321,71 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {\n
       }\n
       if (stream.eatSpace()) return null;\n
       curPunc = null;\n
+      curKeyword = null;\n
       var style = (state.tokenize || tokenBase)(stream, state);\n
-      if (style == "comment" || style == "meta") return style;\n
+      if (style == "comment" || style == "meta" || style == "variable") return style;\n
       if (ctx.align == null) ctx.align = true;\n
 \n
-      if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);\n
-      else if (curPunc == "{") pushContext(state, stream.column(), "}");\n
-      else if (curPunc == "[") pushContext(state, stream.column(), "]");\n
-      else if (curPunc == "(") pushContext(state, stream.column(), ")");\n
-      else if (curPunc == "}") {\n
-        while (ctx.type == "statement") ctx = popContext(state);\n
-        if (ctx.type == "}") ctx = popContext(state);\n
-        while (ctx.type == "statement") ctx = popContext(state);\n
+      if (curPunc == ctx.type) {\n
+        popContext(state);\n
       }\n
-      else if (curPunc == ctx.type) popContext(state);\n
-      else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))\n
+      else if ((curPunc == ";" && ctx.type == "statement") ||\n
+               (ctx.type && isClosing(curKeyword, ctx.type))) {\n
+        ctx = popContext(state);\n
+        while (ctx && ctx.type == "statement") ctx = popContext(state);\n
+      }\n
+      else if (curPunc == "{") { pushContext(state, stream.column(), "}"); }\n
+      else if (curPunc == "[") { pushContext(state, stream.column(), "]"); }\n
+      else if (curPunc == "(") { pushContext(state, stream.column(), ")"); }\n
+      else if (ctx && ctx.type == "endcase" && curPunc == ":") { pushContext(state, stream.column(), "statement"); }\n
+      else if (curPunc == "newstatement") {\n
         pushContext(state, stream.column(), "statement");\n
+      } else if (curPunc == "newblock") {\n
+        if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) {\n
+          // The \'function\' keyword can appear in some other contexts where it actually does not\n
+          // indicate a function (import/export DPI and covergroup definitions).\n
+          // Do nothing in this case\n
+        } else if (curKeyword == "task" && ctx && ctx.type == "statement") {\n
+          // Same thing for task\n
+        } else {\n
+          var close = openClose[curKeyword];\n
+          pushContext(state, stream.column(), close);\n
+        }\n
+      }\n
+\n
       state.startOfLine = false;\n
       return style;\n
     },\n
 \n
     indent: function(state, textAfter) {\n
-      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n
-      var firstChar = textAfter && textAfter.charAt(0), ctx = state.context, closing = firstChar == ctx.type;\n
-      if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);\n
-      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n
+      if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;\n
+      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n
+      if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;\n
+      var closing = false;\n
+      var possibleClosing = textAfter.match(closingBracketOrWord);\n
+      if (possibleClosing) {\n
+        closing = isClosing(possibleClosing[0], ctx.type);\n
+      }\n
+      if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);\n
+      else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1);\n
+      else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;\n
       else return ctx.indented + (closing ? 0 : indentUnit);\n
     },\n
 \n
-    electricChars: "{}"\n
+    blockCommentStart: "/*",\n
+    blockCommentEnd: "*/",\n
+    lineComment: "//"\n
   };\n
 });\n
 \n
-(function() {\n
-  function words(str) {\n
-    var obj = {}, words = str.split(" ");\n
-    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n
-    return obj;\n
-  }\n
-\n
-  var verilogKeywords = "always and assign automatic begin buf bufif0 bufif1 case casex casez cell cmos config " +\n
-    "deassign default defparam design disable edge else end endcase endconfig endfunction endgenerate endmodule " +\n
-    "endprimitive endspecify endtable endtask event for force forever fork function generate genvar highz0 " +\n
-    "highz1 if ifnone incdir include initial inout input instance integer join large liblist library localparam " +\n
-    "macromodule medium module nand negedge nmos nor noshowcancelled not notif0 notif1 or output parameter pmos " +\n
-    "posedge primitive pull0 pull1 pulldown pullup pulsestyle_onevent pulsestyle_ondetect rcmos real realtime " +\n
-    "reg release repeat rnmos rpmos rtran rtranif0 rtranif1 scalared showcancelled signed small specify specparam " +\n
-    "strong0 strong1 supply0 supply1 table task time tran tranif0 tranif1 tri tri0 tri1 triand trior trireg " +\n
-    "unsigned use vectored wait wand weak0 weak1 while wire wor xnor xor";\n
-\n
-  var verilogBlockKeywords = "begin bufif0 bufif1 case casex casez config else end endcase endconfig endfunction " +\n
-    "endgenerate endmodule endprimitive endspecify endtable endtask for forever function generate if ifnone " +\n
-    "macromodule module primitive repeat specify table task while";\n
-\n
-  function metaHook(stream) {\n
-    stream.eatWhile(/[\\w\\$_]/);\n
-    return "meta";\n
-  }\n
+CodeMirror.defineMIME("text/x-verilog", {\n
+  name: "verilog"\n
+});\n
+CodeMirror.defineMIME("text/x-systemverilog", {\n
+  name: "systemverilog"\n
+});\n
 \n
-  CodeMirror.defineMIME("text/x-verilog", {\n
-    name: "verilog",\n
-    keywords: words(verilogKeywords),\n
-    blockKeywords: words(verilogBlockKeywords),\n
-    atoms: words("null"),\n
-    hooks: {"`": metaHook, "$": metaHook}\n
-  });\n
-}());\n
+});\n
 
 
 ]]></string> </value>
@@ -214,7 +396,7 @@ CodeMirror.defineMode("verilog", function(config, parserConfig) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>6520</int> </value>
+            <value> <int>12679</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..295462e5cc863ea87ba3a3b7b78f5b78ebb9b366
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/test.js.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897135.48</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function() {\n
+  var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml";\n
+  function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }\n
+\n
+  MT("matching",\n
+     "[tag\046bracket \074][tag top][tag\046bracket \076]",\n
+     "  text",\n
+     "  [tag\046bracket \074][tag inner][tag\046bracket /\076]",\n
+     "[tag\046bracket \074/][tag top][tag\046bracket \076]");\n
+\n
+  MT("nonmatching",\n
+     "[tag\046bracket \074][tag top][tag\046bracket \076]",\n
+     "  [tag\046bracket \074][tag inner][tag\046bracket /\076]",\n
+     "  [tag\046bracket \074/][tag\046error tip][tag\046bracket\046error \076]");\n
+\n
+  MT("doctype",\n
+     "[meta \074!doctype foobar\076]",\n
+     "[tag\046bracket \074][tag top][tag\046bracket /\076]");\n
+\n
+  MT("cdata",\n
+     "[tag\046bracket \074][tag top][tag\046bracket \076]",\n
+     "  [atom \074![CDATA[foo]",\n
+     "[atom barbazguh]]]]\076]",\n
+     "[tag\046bracket \074/][tag top][tag\046bracket \076]");\n
+\n
+  // HTML tests\n
+  mode = CodeMirror.getMode({indentUnit: 2}, "text/html");\n
+\n
+  MT("selfclose",\n
+     "[tag\046bracket \074][tag html][tag\046bracket \076]",\n
+     "  [tag\046bracket \074][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \\"/foobar\\"][tag\046bracket \076]",\n
+     "[tag\046bracket \074/][tag html][tag\046bracket \076]");\n
+\n
+  MT("list",\n
+     "[tag\046bracket \074][tag ol][tag\046bracket \076]",\n
+     "  [tag\046bracket \074][tag li][tag\046bracket \076]one",\n
+     "  [tag\046bracket \074][tag li][tag\046bracket \076]two",\n
+     "[tag\046bracket \074/][tag ol][tag\046bracket \076]");\n
+\n
+  MT("valueless",\n
+     "[tag\046bracket \074][tag input] [attribute type]=[string checkbox] [attribute checked][tag\046bracket /\076]");\n
+\n
+  MT("pThenArticle",\n
+     "[tag\046bracket \074][tag p][tag\046bracket \076]",\n
+     "  foo",\n
+     "[tag\046bracket \074][tag article][tag\046bracket \076]bar");\n
+\n
+})();\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1758</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/xml.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/xml.js.xml
index 12230305795811301543ca2763c2720f9f1c1f2b..8cf100fddd4b19d5a5b87a2efdb8cdb7be86155a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/xml.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xml/xml.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403098.97</string> </value>
+            <value> <string>ts21897135.67</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -20,7 +20,20 @@
         </item>
         <item>
             <key> <string>data</string> </key>
-            <value> <string>CodeMirror.defineMode("xml", function(config, parserConfig) {\n
+            <value> <string>// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" \046\046 typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" \046\046 define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
+CodeMirror.defineMode("xml", function(config, parserConfig) {\n
   var indentUnit = config.indentUnit;\n
   var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;\n
   var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;\n
@@ -30,7 +43,7 @@
     autoSelfClosers: {\'area\': true, \'base\': true, \'br\': true, \'col\': true, \'command\': true,\n
                       \'embed\': true, \'frame\': true, \'hr\': true, \'img\': true, \'input\': true,\n
                       \'keygen\': true, \'link\': true, \'meta\': true, \'param\': true, \'source\': true,\n
-                      \'track\': true, \'wbr\': true},\n
+                      \'track\': true, \'wbr\': true, \'menuitem\': true},\n
     implicitlyClosed: {\'dd\': true, \'li\': true, \'optgroup\': true, \'option\': true, \'p\': true,\n
                        \'rp\': true, \'rt\': true, \'tbody\': true, \'td\': true, \'tfoot\': true,\n
                        \'th\': true, \'tr\': true},\n
@@ -56,19 +69,21 @@
     },\n
     doNotIndent: {"pre": true},\n
     allowUnquoted: true,\n
-    allowMissing: true\n
+    allowMissing: true,\n
+    caseFold: true\n
   } : {\n
     autoSelfClosers: {},\n
     implicitlyClosed: {},\n
     contextGrabbers: {},\n
     doNotIndent: {},\n
     allowUnquoted: false,\n
-    allowMissing: false\n
+    allowMissing: false,\n
+    caseFold: false\n
   };\n
   var alignCDATA = parserConfig.alignCDATA;\n
 \n
   // Return variables for tokenizers\n
-  var tagName, type, setStyle;\n
+  var type, setStyle;\n
 \n
   function inText(stream, state) {\n
     function chain(parser) {\n
@@ -95,14 +110,9 @@
         state.tokenize = inBlock("meta", "?\076");\n
         return "meta";\n
       } else {\n
-        var isClose = stream.eat("/");\n
-        tagName = "";\n
-        var c;\n
-        while ((c = stream.eat(/[^\\s\\u00a0=\074\076\\"\\\'\\/?]/))) tagName += c;\n
-        if (!tagName) return "tag error";\n
-        type = isClose ? "closeTag" : "openTag";\n
+        type = stream.eat("/") ? "closeTag" : "openTag";\n
         state.tokenize = inTag;\n
-        return "tag";\n
+        return "tag bracket";\n
       }\n
     } else if (ch == "\046") {\n
       var ok;\n
@@ -127,7 +137,7 @@
     if (ch == "\076" || (ch == "/" \046\046 stream.eat("\076"))) {\n
       state.tokenize = inText;\n
       type = ch == "\076" ? "endTag" : "selfcloseTag";\n
-      return "tag";\n
+      return "tag bracket";\n
     } else if (ch == "=") {\n
       type = "equals";\n
       return null;\n
@@ -136,13 +146,13 @@
       state.state = baseState;\n
       state.tagName = state.tagStart = null;\n
       var next = state.tokenize(stream, state);\n
-      return next ? next + " error" : "error";\n
+      return next ? next + " tag error" : "tag error";\n
     } else if (/[\\\'\\"]/.test(ch)) {\n
       state.tokenize = inAttribute(ch);\n
       state.stringStartCol = stream.column();\n
       return state.tokenize(stream, state);\n
     } else {\n
-      stream.eatWhile(/[^\\s\\u00a0=\074\076\\"\\\']/);\n
+      stream.match(/^[^\\s\\u00a0=\074\076\\"\\\']*[^\\s\\u00a0=\074\076\\"\\\'\\/]/);\n
       return "word";\n
     }\n
   }\n
@@ -211,7 +221,7 @@
       if (!state.context) {\n
         return;\n
       }\n
-      parentTagName = state.context.tagName.toLowerCase();\n
+      parentTagName = state.context.tagName;\n
       if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||\n
           !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {\n
         return;\n
@@ -222,26 +232,43 @@
 \n
   function baseState(type, stream, state) {\n
     if (type == "openTag") {\n
-      state.tagName = tagName;\n
       state.tagStart = stream.column();\n
-      return attrState;\n
+      return tagNameState;\n
     } else if (type == "closeTag") {\n
-      var err = false;\n
-      if (state.context) {\n
-        if (state.context.tagName != tagName) {\n
-          if (Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName.toLowerCase()))\n
-            popContext(state);\n
-          err = !state.context || state.context.tagName != tagName;\n
-        }\n
+      return closeTagNameState;\n
+    } else {\n
+      return baseState;\n
+    }\n
+  }\n
+  function tagNameState(type, stream, state) {\n
+    if (type == "word") {\n
+      state.tagName = stream.current();\n
+      setStyle = "tag";\n
+      return attrState;\n
+    } else {\n
+      setStyle = "error";\n
+      return tagNameState;\n
+    }\n
+  }\n
+  function closeTagNameState(type, stream, state) {\n
+    if (type == "word") {\n
+      var tagName = stream.current();\n
+      if (state.context \046\046 state.context.tagName != tagName \046\046\n
+          Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))\n
+        popContext(state);\n
+      if (state.context \046\046 state.context.tagName == tagName) {\n
+        setStyle = "tag";\n
+        return closeState;\n
       } else {\n
-        err = true;\n
+        setStyle = "tag error";\n
+        return closeStateErr;\n
       }\n
-      if (err) setStyle = "error";\n
-      return err ? closeStateErr : closeState;\n
     } else {\n
-      return baseState;\n
+      setStyle = "error";\n
+      return closeStateErr;\n
     }\n
   }\n
+\n
   function closeState(type, _stream, state) {\n
     if (type != "endTag") {\n
       setStyle = "error";\n
@@ -263,10 +290,10 @@
       var tagName = state.tagName, tagStart = state.tagStart;\n
       state.tagName = state.tagStart = null;\n
       if (type == "selfcloseTag" ||\n
-          Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase())) {\n
-        maybePopContext(state, tagName.toLowerCase());\n
+          Kludges.autoSelfClosers.hasOwnProperty(tagName)) {\n
+        maybePopContext(state, tagName);\n
       } else {\n
-        maybePopContext(state, tagName.toLowerCase());\n
+        maybePopContext(state, tagName);\n
         state.context = new Context(state, tagName, tagStart == state.indented);\n
       }\n
       return baseState;\n
@@ -304,7 +331,7 @@
         state.indented = stream.indentation();\n
 \n
       if (stream.eatSpace()) return null;\n
-      tagName = type = null;\n
+      type = null;\n
       var style = state.tokenize(stream, state);\n
       if ((style || type) \046\046 style != "comment") {\n
         setStyle = null;\n
@@ -319,7 +346,10 @@
       var context = state.context;\n
       // Indent multi-line strings (e.g. css).\n
       if (state.tokenize.isInAttribute) {\n
-        return state.stringStartCol + 1;\n
+        if (state.tagStart == state.indented)\n
+          return state.stringStartCol + 1;\n
+        else\n
+          return state.indented + indentUnit;\n
       }\n
       if (context \046\046 context.noIndent) return CodeMirror.Pass;\n
       if (state.tokenize != inTag \046\046 state.tokenize != inText)\n
@@ -332,15 +362,34 @@
           return state.tagStart + indentUnit * multilineTagIndentFactor;\n
       }\n
       if (alignCDATA \046\046 /\074!\\[CDATA\\[/.test(textAfter)) return 0;\n
-      if (context \046\046 /^\074\\//.test(textAfter))\n
-        context = context.prev;\n
+      var tagAfter = textAfter \046\046 /^\074(\\/)?([\\w_:\\.-]*)/.exec(textAfter);\n
+      if (tagAfter \046\046 tagAfter[1]) { // Closing tag spotted\n
+        while (context) {\n
+          if (context.tagName == tagAfter[2]) {\n
+            context = context.prev;\n
+            break;\n
+          } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {\n
+            context = context.prev;\n
+          } else {\n
+            break;\n
+          }\n
+        }\n
+      } else if (tagAfter) { // Opening tag spotted\n
+        while (context) {\n
+          var grabbers = Kludges.contextGrabbers[context.tagName];\n
+          if (grabbers \046\046 grabbers.hasOwnProperty(tagAfter[2]))\n
+            context = context.prev;\n
+          else\n
+            break;\n
+        }\n
+      }\n
       while (context \046\046 !context.startOfLine)\n
         context = context.prev;\n
       if (context) return context.indent + indentUnit;\n
       else return 0;\n
     },\n
 \n
-    electricChars: "/",\n
+    electricInput: /\074\\/[\\s\\w:]+\076$/,\n
     blockCommentStart: "\074!--",\n
     blockCommentEnd: "--\076",\n
 \n
@@ -353,6 +402,8 @@ CodeMirror.defineMIME("text/xml", "xml");\n
 CodeMirror.defineMIME("application/xml", "xml");\n
 if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))\n
   CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});\n
+\n
+});\n
 </string> </value>
         </item>
         <item>
@@ -361,7 +412,7 @@ if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>10915</int> </value>
+            <value> <int>12375</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/test.js.xml
index 9ac2508e4e3b494e9389ec81bc4705332b6d6c73..fce72fa386fd6866ffb62f959c7bafb1a5158dac 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403088.09</string> </value>
+            <value> <string>ts21897147.65</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,9 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
 // Don\'t take these too seriously -- the expected results appear to be\n
 // based on the results of actual runs without any serious manual\n
 // verification. If a change you made causes them to fail, the test is\n
@@ -96,7 +99,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4980</int> </value>
+            <value> <int>5108</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/xquery.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/xquery.js.xml
index 7abae82d41d8b739a0373a5057963091fa5f9289..aba2bc690e327bfdbf9c555b93d627f33156f680 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/xquery.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/xquery/xquery.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403087.89</string> </value>
+            <value> <string>ts21897147.84</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("xquery", function() {\n
 \n
   // The keywords object is set to the result of this self executing\n
@@ -454,6 +467,8 @@ CodeMirror.defineMode("xquery", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("application/xquery", "xquery");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -464,7 +479,7 @@ CodeMirror.defineMIME("application/xquery", "xquery");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>14667</int> </value>
+            <value> <int>15128</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/yaml/yaml.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/yaml/yaml.js.xml
index 89968ca10ac259c1f5bef4a791fa69244f978c66..f53bbe8583ee26b6b5e4f603789efd7183bd20ad 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/yaml/yaml.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/yaml/yaml.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403093.51</string> </value>
+            <value> <string>ts21897141.76</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode("yaml", function() {\n
 \n
   var cons = [\'true\', \'false\', \'on\', \'off\', \'yes\', \'no\'];\n
@@ -34,8 +47,13 @@ CodeMirror.defineMode("yaml", function() {\n
       state.escaped = false;\n
       /* comments */\n
       if (ch == "#" && (stream.pos == 0 || /\\s/.test(stream.string.charAt(stream.pos - 1)))) {\n
-        stream.skipToEnd(); return "comment";\n
+        stream.skipToEnd();\n
+        return "comment";\n
       }\n
+\n
+      if (stream.match(/^(\'([^\']|\\\\.)*\'?|"([^"]|\\\\.)*"?)/))\n
+        return "string";\n
+\n
       if (state.literal && stream.indentation() > state.keyCol) {\n
         stream.skipToEnd(); return "string";\n
       } else if (state.literal) { state.literal = false; }\n
@@ -91,7 +109,7 @@ CodeMirror.defineMode("yaml", function() {\n
       }\n
 \n
       /* pairs (associative arrays) -> key */\n
-      if (!state.pair && stream.match(/^\\s*\\S+(?=\\s*:($|\\s))/i)) {\n
+      if (!state.pair && stream.match(/^\\s*(?:[,\\[\\]{}&*!|>\'"%@`][^\\s\'":]|[^,\\[\\]{}#&*!|>\'"%@`])[^#]*?(?=\\s*:($|\\s))/)) {\n
         state.pair = true;\n
         state.keyCol = stream.indentation();\n
         return "atom";\n
@@ -119,6 +137,8 @@ CodeMirror.defineMode("yaml", function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-yaml", "yaml");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -129,7 +149,7 @@ CodeMirror.defineMIME("text/x-yaml", "yaml");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3038</int> </value>
+            <value> <int>3649</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/z80/z80.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/z80/z80.js.xml
index e5eafa1ba229f93ee023aa63f429c3eb58dfa10d..56507a55f4bbd6f213330165f530db114f291b66 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/z80/z80.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/mode/z80/z80.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403090.42</string> </value>
+            <value> <string>ts21897144.88</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -22,6 +22,19 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+// CodeMirror, copyright (c) by Marijn Haverbeke and others\n
+// Distributed under an MIT license: http://codemirror.net/LICENSE\n
+\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") // CommonJS\n
+    mod(require("../../lib/codemirror"));\n
+  else if (typeof define == "function" && define.amd) // AMD\n
+    define(["../../lib/codemirror"], mod);\n
+  else // Plain browser env\n
+    mod(CodeMirror);\n
+})(function(CodeMirror) {\n
+"use strict";\n
+\n
 CodeMirror.defineMode(\'z80\', function() {\n
   var keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\\b/i;\n
   var keywords2 = /^(call|j[pr]|ret[in]?)\\b/i;\n
@@ -107,6 +120,8 @@ CodeMirror.defineMode(\'z80\', function() {\n
 });\n
 \n
 CodeMirror.defineMIME("text/x-z80", "z80");\n
+\n
+});\n
 
 
 ]]></string> </value>
@@ -117,7 +132,7 @@ CodeMirror.defineMIME("text/x-z80", "z80");\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2419</int> </value>
+            <value> <int>2880</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/package.json.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/package.json.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e2e11f7fbdc8b9c961bb9ed9d407c42cbb95927
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/package.json.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897150.22</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>package.json</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/json</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>{\n
+    "name": "codemirror",\n
+    "version":"4.11.0",\n
+    "main": "lib/codemirror.js",\n
+    "description": "In-browser code editing made bearable",\n
+    "licenses": [{"type": "MIT",\n
+                  "url": "http://codemirror.net/LICENSE"}],\n
+    "directories": {"lib": "./lib"},\n
+    "scripts": {"test": "node ./test/run.js"},\n
+    "devDependencies": {"node-static": "0.6.0",\n
+                        "phantomjs": "1.9.2-5"},\n
+    "bugs": "http://github.com/codemirror/CodeMirror/issues",\n
+    "keywords": ["JavaScript", "CodeMirror", "Editor"],\n
+    "homepage": "http://codemirror.net",\n
+    "maintainers":[{"name": "Marijn Haverbeke",\n
+                    "email": "marijnh@gmail.com",\n
+                    "web": "http://marijnhaverbeke.nl"}],\n
+    "repository": {"type": "git",\n
+                   "url": "https://github.com/codemirror/CodeMirror.git"}\n
+}\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>844</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/comment_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/comment_test.js.xml
index 456619c186f0bbb4e4bbe5f0b5e2323f67d1f760..e05661b121a23ab6a50a6ed48468a2a3747c5303 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/comment_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/comment_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403105.36</string> </value>
+            <value> <string>ts21897152.25</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -31,6 +31,9 @@
   }\n
 \n
   var simpleProg = "function foo() {\\n  return bar;\\n}";\n
+  var inlineBlock = "foo(/* bar */ true);";\n
+  var inlineBlocks = "foo(/* bar */ true, /* baz */ false);";\n
+  var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"];\n
 \n
   test("block", "javascript", function(cm) {\n
     cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"});\n
@@ -40,6 +43,17 @@
     cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});\n
     cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});\n
   }, simpleProg, simpleProg);\n
+\n
+  test("blockToggle2", "javascript", function(cm) {\n
+    cm.setCursor({line: 0, ch: 7 /* inside the block comment */});\n
+    cm.execCommand("toggleComment");\n
+  }, inlineBlock, "foo(bar true);");\n
+\n
+  // This test should work but currently fails.\n
+  // test("blockToggle3", "javascript", function(cm) {\n
+  //   cm.setCursor({line: 0, ch: 7 /* inside the first block comment */});\n
+  //   cm.execCommand("toggleComment");\n
+  // }, inlineBlocks, "foo(bar true, /* baz */ false);");\n
 \n
   test("line", "javascript", function(cm) {\n
     cm.lineComment(Pos(1, 1), Pos(1, 1));\n
@@ -57,6 +71,29 @@
   test("fallbackToLine", "ruby", function(cm) {\n
     cm.blockComment(Pos(0, 0), Pos(1));\n
   }, "def blah()\\n  return hah\\n", "# def blah()\\n#   return hah\\n");\n
+\n
+  test("ignoreExternalBlockComments", "javascript", function(cm) {\n
+    cm.execCommand("toggleComment");\n
+  }, inlineBlocks, "// " + inlineBlocks);\n
+\n
+  test("ignoreExternalBlockComments2", "javascript", function(cm) {\n
+    cm.setCursor({line: 0, ch: null /* eol */});\n
+    cm.execCommand("toggleComment");\n
+  }, inlineBlocks, "// " + inlineBlocks);\n
+\n
+  test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) {\n
+    cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1});\n
+    cm.execCommand("toggleComment");\n
+  }, multiLineInlineBlock.join("\\n"), ["// " + multiLineInlineBlock[0],\n
+                                       "// " + multiLineInlineBlock[1],\n
+                                       multiLineInlineBlock[2]].join("\\n"));\n
+\n
+  test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) {\n
+    cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1});\n
+    cm.execCommand("toggleComment");\n
+  }, multiLineInlineBlock.join("\\n"), [multiLineInlineBlock[0],\n
+                                       "// " + multiLineInlineBlock[1],\n
+                                       "// " + multiLineInlineBlock[2]].join("\\n"));\n
 \n
   test("commentRange", "javascript", function(cm) {\n
     cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false});\n
@@ -91,7 +128,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>2320</int> </value>
+            <value> <int>4149</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/doc_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/doc_test.js.xml
index 2fc2346091da18c3dbb00052e1dd779e2f53099d..73cbad2b13bb22505711c52d5c9d823406e97a41 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/doc_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/doc_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.53</string> </value>
+            <value> <string>ts21897151.16</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -343,6 +343,48 @@
     eq(mark.find(), null);\n
     eq(cleared, 1);\n
   });\n
+\n
+  testDoc("sharedMarkerCopy", "A=\'abcde\'", function(a) {\n
+    var shared = a.markText(Pos(0, 1), Pos(0, 3), {shared: true});\n
+    var b = a.linkedDoc();\n
+    var found = b.findMarksAt(Pos(0, 2));\n
+    eq(found.length, 1);\n
+    eq(found[0], shared);\n
+    shared.clear();\n
+    eq(b.findMarksAt(Pos(0, 2)), 0);\n
+  });\n
+\n
+  testDoc("sharedMarkerDetach", "A=\'abcde\' B<A C<B", function(a, b, c) {\n
+    var shared = a.markText(Pos(0, 1), Pos(0, 3), {shared: true});\n
+    a.unlinkDoc(b);\n
+    var inB = b.findMarksAt(Pos(0, 2));\n
+    eq(inB.length, 1);\n
+    is(inB[0] != shared);\n
+    var inC = c.findMarksAt(Pos(0, 2));\n
+    eq(inC.length, 1);\n
+    is(inC[0] != shared);\n
+    inC[0].clear();\n
+    is(shared.find());\n
+  });\n
+\n
+  testDoc("sharedBookmark", "A=\'ab\\ncd\\nef\\ngh\' B<A C<~A/1-2", function(a, b, c) {\n
+    var mark = b.setBookmark(Pos(1, 1), {shared: true});\n
+    var found = a.findMarksAt(Pos(1, 1));\n
+    eq(found.length, 1);\n
+    eq(found[0], mark);\n
+    eq(c.findMarksAt(Pos(1, 1)).length, 1);\n
+    eqPos(mark.find(), Pos(1, 1));\n
+    b.replaceRange("x\\ny\\n", Pos(0, 0));\n
+    eqPos(mark.find(), Pos(3, 1));\n
+    var cleared = 0;\n
+    CodeMirror.on(mark, "clear", function() {++cleared;});\n
+    b.operation(function() {mark.clear();});\n
+    eq(a.findMarks(Pos(0, 0), Pos(5)).length, 0);\n
+    eq(b.findMarks(Pos(0, 0), Pos(5)).length, 0);\n
+    eq(c.findMarks(Pos(0, 0), Pos(5)).length, 0);\n
+    eq(mark.find(), null);\n
+    eq(cleared, 1);\n
+  });\n
 \n
   testDoc("undoInSubview", "A=\'line 0\\nline 1\\nline 2\\nline 3\\nline 4\' B<A/1-4", function(a, b) {\n
     b.replaceRange("x", Pos(2, 0));\n
@@ -361,7 +403,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>9894</int> </value>
+            <value> <int>11305</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/driver.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/driver.js.xml
index 9c4e0d7536fa07f55f1befcb0e6a9ad0ce47a023..9e1fb5ae9a8c45aece959d6d0f5cc583a92ac824 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/driver.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/driver.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403103.74</string> </value>
+            <value> <string>ts21897150.47</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -68,23 +68,25 @@ function testCM(name, run, opts, expectedFail) {\n
 function runTests(callback) {\n
   var totalTime = 0;\n
   function step(i) {\n
-    if (i === tests.length){\n
-      running = false;\n
-      return callback("done");\n
-    } \n
-    var test = tests[i], expFail = test.expectedFail, startTime = +new Date;\n
-    if (filters.length) {\n
-      for (var j = 0; j < filters.length; j++) {\n
-        if (test.name.match(filters[j])) {\n
-          break;\n
-        }\n
+    for (;;) {\n
+      if (i === tests.length) {\n
+        running = false;\n
+        return callback("done");\n
+      }\n
+      var test = tests[i], skip = false;\n
+      if (filters.length) {\n
+        skip = true;\n
+        for (var j = 0; j < filters.length; j++)\n
+          if (test.name.match(filters[j])) skip = false;\n
       }\n
-      if (j == filters.length) {      \n
+      if (skip) {\n
         callback("skipped", test.name, message);\n
-        return step(i + 1);\n
+        i++;\n
+      } else {\n
+        break;\n
       }\n
     }\n
-    var threw = false;\n
+    var expFail = test.expectedFail, startTime = +new Date, threw = false;\n
     try {\n
       var message = test.func();\n
     } catch(e) {\n
@@ -93,6 +95,7 @@ function runTests(callback) {\n
       else if (e instanceof Failure) callback("fail", test.name, e.message);\n
       else {\n
         var pos = /(?:\\bat |@).*?([^\\/:]+):(\\d+)/.exec(e.stack);\n
+        if (pos) console["log"](e.stack);\n
         callback("error", test.name, e.toString() + (pos ? " (" + pos[1] + ":" + pos[2] + ")" : ""));\n
       }\n
     }\n
@@ -123,6 +126,10 @@ function label(str, msg) {\n
 function eq(a, b, msg) {\n
   if (a != b) throw new Failure(label(a + " != " + b, msg));\n
 }\n
+function near(a, b, margin, msg) {\n
+  if (Math.abs(a - b) > margin)\n
+    throw new Failure(label(a + " is not close to " + b + " (" + margin + ")", msg));\n
+}\n
 function eqPos(a, b, msg) {\n
   function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; }\n
   if (a == b) return;\n
@@ -163,7 +170,7 @@ function parseTestFilter(s) {\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>3723</int> </value>
+            <value> <int>3963</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/emacs_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/emacs_test.js.xml
index 2637c40f17e50970579fd9098840fc4e366b8163..95c1320c230aa1e213263841ac402ad2385c58f3 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/emacs_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/emacs_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.07</string> </value>
+            <value> <string>ts21897150.73</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -132,10 +132,10 @@
 \n
   sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\\n bar"))\n
 \n
-  sim("transposeChar", "abcd\\n\\ne",\n
-      "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\\n\\ne"), at(0, 3),\n
-      "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\\n\\ne"), at(0, 4),\n
-      "Ctrl-F", "Ctrl-T", txt("bcd\\na\\ne"), at(1, 1));\n
+  sim("transposeChar", "abcd\\ne",\n
+      "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\\ne"), at(0, 3),\n
+      "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\\ne"), at(0, 4),\n
+      "Ctrl-F", "Ctrl-T", txt("bcde\\na"), at(1, 0));\n
 \n
   sim("manipWordCase", "foo BAR bAZ",\n
       "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"),\n
@@ -151,6 +151,9 @@
 \n
   sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F",\n
       "Ctrl-G", "Ctrl-W", txt("abcde"));\n
+\n
+  sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde"));\n
+  sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde"));\n
 \n
   testCM("save", function(cm) {\n
     var saved = false;\n
@@ -170,7 +173,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5475</int> </value>
+            <value> <int>5647</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/acorn.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/acorn.js.xml
index bce416abe129e0ba25ee327fe6d7db4d2931fe88..f716e4c6956247dea3839f808c4e760277c9a5eb 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/acorn.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/acorn.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403105.26</string> </value>
+            <value> <string>ts21897152.05</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -18,6 +18,33 @@
             <key> <string>content_type</string> </key>
             <value> <string>application/javascript</string> </value>
         </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>69379</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
         <item>
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
@@ -36,13 +63,24 @@
 // Please use the [github bug tracker][ghbt] to report issues.\n
 //\n
 // [ghbt]: https://github.com/marijnh/acorn/issues\n
-\n
-(function(exports) {\n
+//\n
+// This file defines the main parser interface. The library also comes\n
+// with a [error-tolerant parser][dammit] and an\n
+// [abstract syntax tree walker][walk], defined in other files.\n
+//\n
+// [dammit]: acorn_loose.js\n
+// [walk]: util/walk.js\n
+\n
+(function(root, mod) {\n
+  if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS\n
+  if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD\n
+  mod(root.acorn || (root.acorn = {})); // Plain browser env\n
+})(this, function(exports) {\n
   "use strict";\n
 \n
-  exports.version = "0.0.1";\n
+  exports.version = "0.4.1";\n
 \n
-  // The main exported interface (under `window.acorn` when in the\n
+  // The main exported interface (under `self.acorn` when in the\n
   // browser) is a `parse` function that takes a code string and\n
   // returns an abstract syntax tree as specified by [Mozilla parser\n
   // API][api], with the caveat that the SpiderMonkey-specific syntax\n
@@ -54,10 +92,8 @@
 \n
   exports.parse = function(inpt, opts) {\n
     input = String(inpt); inputLen = input.length;\n
-    options = opts || {};\n
-    for (var opt in defaultOptions) if (!options.hasOwnProperty(opt))\n
-      options[opt] = defaultOptions[opt];\n
-    sourceFile = options.sourceFile || null;\n
+    setOptions(opts);\n
+    initTokenState();\n
     return parseTopLevel(options.program);\n
   };\n
 \n
@@ -77,20 +113,29 @@
     // trailing commas in array and object literals.\n
     allowTrailingCommas: true,\n
     // By default, reserved words are not enforced. Enable\n
-    // `forbidReserved` to enforce them.\n
+    // `forbidReserved` to enforce them. When this option has the\n
+    // value "everywhere", reserved words and keywords can also not be\n
+    // used as property names.\n
     forbidReserved: false,\n
-    // When `trackComments` is turned on, the parser will attach\n
-    // `commentsBefore` and `commentsAfter` properties to AST nodes\n
-    // holding arrays of strings. A single comment may appear in both\n
-    // a `commentsBefore` and `commentsAfter` array (of the nodes\n
-    // after and before it), but never twice in the before (or after)\n
-    // array of different nodes.\n
-    trackComments: false,\n
+    // When enabled, a return at the top level is not considered an\n
+    // error.\n
+    allowReturnOutsideFunction: false,\n
     // When `locations` is on, `loc` properties holding objects with\n
     // `start` and `end` properties in `{line, column}` form (with\n
     // line being 1-based and column 0-based) will be attached to the\n
     // nodes.\n
     locations: false,\n
+    // A function can be passed as `onComment` option, which will\n
+    // cause Acorn to call that function with `(block, text, start,\n
+    // end)` parameters whenever a comment is skipped. `block` is a\n
+    // boolean indicating whether this is a block (`/* */`) comment,\n
+    // `text` is the content of the comment, and `start` and `end` are\n
+    // character offsets that denote the start and end of the comment.\n
+    // When the `locations` option is on, two more parameters are\n
+    // passed, the full `{line, column}` locations of the start and\n
+    // end of the comments. Note that you are not allowed to call the\n
+    // parser from the callback鈥攖hat will corrupt its internal state.\n
+    onComment: null,\n
     // Nodes have their start and end characters offsets recorded in\n
     // `start` and `end` properties (directly on the node, rather than\n
     // the `loc` object, which holds line/column data. To also add a\n
@@ -106,10 +151,20 @@
     // toplevel forms of the parsed file to the `Program` (top) node\n
     // of an existing parse tree.\n
     program: null,\n
-    // When `location` is on, you can pass this to record the source\n
+    // When `locations` is on, you can pass this to record the source\n
     // file in every node\'s `loc` object.\n
-    sourceFile: null\n
+    sourceFile: null,\n
+    // This value, if given, is stored in every node, whether\n
+    // `locations` is on or off.\n
+    directSourceFile: null\n
   };\n
+\n
+  function setOptions(opts) {\n
+    options = opts || {};\n
+    for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))\n
+      options[opt] = defaultOptions[opt];\n
+    sourceFile = options.sourceFile || null;\n
+  }\n
 \n
   // The `getLineInfo` function is mostly useful when the\n
   // `locations` option is off (for performance reasons) and you\n
@@ -130,9 +185,45 @@
   };\n
 \n
   // Acorn is organized as a tokenizer and a recursive-descent parser.\n
-  // Both use (closure-)global variables to keep their state and\n
-  // communicate. We already saw the `options`, `input`, and\n
-  // `inputLen` variables above (set in `parse`).\n
+  // The `tokenize` export provides an interface to the tokenizer.\n
+  // Because the tokenizer is optimized for being efficiently used by\n
+  // the Acorn parser itself, this interface is somewhat crude and not\n
+  // very modular. Performing another parse or call to `tokenize` will\n
+  // reset the internal state, and invalidate existing tokenizers.\n
+\n
+  exports.tokenize = function(inpt, opts) {\n
+    input = String(inpt); inputLen = input.length;\n
+    setOptions(opts);\n
+    initTokenState();\n
+\n
+    var t = {};\n
+    function getToken(forceRegexp) {\n
+      lastEnd = tokEnd;\n
+      readToken(forceRegexp);\n
+      t.start = tokStart; t.end = tokEnd;\n
+      t.startLoc = tokStartLoc; t.endLoc = tokEndLoc;\n
+      t.type = tokType; t.value = tokVal;\n
+      return t;\n
+    }\n
+    getToken.jumpTo = function(pos, reAllowed) {\n
+      tokPos = pos;\n
+      if (options.locations) {\n
+        tokCurLine = 1;\n
+        tokLineStart = lineBreak.lastIndex = 0;\n
+        var match;\n
+        while ((match = lineBreak.exec(input)) && match.index < pos) {\n
+          ++tokCurLine;\n
+          tokLineStart = match.index + match[0].length;\n
+        }\n
+      }\n
+      tokRegexpAllowed = reAllowed;\n
+      skipSpace();\n
+    };\n
+    return getToken;\n
+  };\n
+\n
+  // State is kept in (closure-)global variables. We already saw the\n
+  // `options`, `input`, and `inputLen` variables above.\n
 \n
   // The current position of the tokenizer in the input.\n
 \n
@@ -156,11 +247,6 @@
   // for operators, the operator name, and so on.\n
 \n
   var tokType, tokVal;\n
-\n
-  // These are used to hold arrays of comments when\n
-  // `options.trackComments` is true.\n
-\n
-  var tokCommentsBefore, tokCommentsAfter;\n
 \n
   // Interal state for the tokenizer. To distinguish between division\n
   // operators and regular expressions, it remembers whether the last\n
@@ -169,13 +255,13 @@
   // division operator. See the `parseStatement` function for a\n
   // caveat.)\n
 \n
-  var tokRegexpAllowed, tokComments;\n
+  var tokRegexpAllowed;\n
 \n
   // When `options.locations` is true, these are used to keep\n
   // track of the current line, and know when a new line has been\n
-  // entered. See the `curLineLoc` function.\n
+  // entered.\n
 \n
-  var tokCurLine, tokLineStart, tokLineStartNext;\n
+  var tokCurLine, tokLineStart;\n
 \n
   // These store the position of the previous token, which is useful\n
   // when finishing a node and assigning its `end` position.\n
@@ -190,16 +276,22 @@
   var inFunction, labels, strict;\n
 \n
   // This function is used to raise exceptions on parse errors. It\n
-  // takes either a `{line, column}` object or an offset integer (into\n
-  // the current `input`) as `pos` argument. It attaches the position\n
-  // to the end of the error message, and then raises a `SyntaxError`\n
-  // with that message.\n
+  // takes an offset integer (into the current `input`) to indicate\n
+  // the location of the error, attaches the position to the end\n
+  // of the error message, and then raises a `SyntaxError` with that\n
+  // message.\n
 \n
   function raise(pos, message) {\n
-    if (typeof pos == "number") pos = getLineInfo(input, pos);\n
-    message += " (" + pos.line + ":" + pos.column + ")";\n
-    throw new SyntaxError(message);\n
+    var loc = getLineInfo(input, pos);\n
+    message += " (" + loc.line + ":" + loc.column + ")";\n
+    var err = new SyntaxError(message);\n
+    err.pos = pos; err.loc = loc; err.raisedAt = tokPos;\n
+    throw err;\n
   }\n
+\n
+  // Reused empty array added for node fields that are always empty.\n
+\n
+  var empty = [];\n
 \n
   // ## Token types\n
 \n
@@ -257,10 +349,10 @@
                       "function": _function, "if": _if, "return": _return, "switch": _switch,\n
                       "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with,\n
                       "null": _null, "true": _true, "false": _false, "new": _new, "in": _in,\n
-                      "instanceof": {keyword: "instanceof", binop: 7}, "this": _this,\n
-                      "typeof": {keyword: "typeof", prefix: true},\n
-                      "void": {keyword: "void", prefix: true},\n
-                      "delete": {keyword: "delete", prefix: true}};\n
+                      "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this,\n
+                      "typeof": {keyword: "typeof", prefix: true, beforeExpr: true},\n
+                      "void": {keyword: "void", prefix: true, beforeExpr: true},\n
+                      "delete": {keyword: "delete", prefix: true, beforeExpr: true}};\n
 \n
   // Punctuation token types. Again, the `type` property is purely for debugging.\n
 \n
@@ -286,13 +378,27 @@
   // in AssignmentExpression nodes.\n
 \n
   var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};\n
-  var _assign = {isAssign: true, beforeExpr: true}, _plusmin = {binop: 9, prefix: true, beforeExpr: true};\n
-  var _incdec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};\n
-  var _bin1 = {binop: 1, beforeExpr: true}, _bin2 = {binop: 2, beforeExpr: true};\n
-  var _bin3 = {binop: 3, beforeExpr: true}, _bin4 = {binop: 4, beforeExpr: true};\n
-  var _bin5 = {binop: 5, beforeExpr: true}, _bin6 = {binop: 6, beforeExpr: true};\n
-  var _bin7 = {binop: 7, beforeExpr: true}, _bin8 = {binop: 8, beforeExpr: true};\n
-  var _bin10 = {binop: 10, beforeExpr: true};\n
+  var _assign = {isAssign: true, beforeExpr: true};\n
+  var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};\n
+  var _logicalOR = {binop: 1, beforeExpr: true};\n
+  var _logicalAND = {binop: 2, beforeExpr: true};\n
+  var _bitwiseOR = {binop: 3, beforeExpr: true};\n
+  var _bitwiseXOR = {binop: 4, beforeExpr: true};\n
+  var _bitwiseAND = {binop: 5, beforeExpr: true};\n
+  var _equality = {binop: 6, beforeExpr: true};\n
+  var _relational = {binop: 7, beforeExpr: true};\n
+  var _bitShift = {binop: 8, beforeExpr: true};\n
+  var _plusMin = {binop: 9, prefix: true, beforeExpr: true};\n
+  var _multiplyModulo = {binop: 10, beforeExpr: true};\n
+\n
+  // Provide access to the token types for external users of the\n
+  // tokenizer.\n
+\n
+  exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,\n
+                      parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,\n
+                      dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof,\n
+                      num: _num, regexp: _regexp, string: _string};\n
+  for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];\n
 \n
   // This is a trick taken from Esprima. It turns out that, on\n
   // non-Chrome browsers, to check whether a string is in a set, a\n
@@ -369,9 +475,9 @@
   // are only applied when a character is found to actually have a\n
   // code point above 128.\n
 \n
-  var nonASCIIwhitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]/;\n
+  var nonASCIIwhitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]/;\n
   var nonASCIIidentifierStartChars = "\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc";\n
-  var nonASCIIidentifierChars = "\\u0371-\\u0374\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f";\n
+  var nonASCIIidentifierChars = "\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f";\n
   var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");\n
   var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");\n
 \n
@@ -386,17 +492,17 @@
 \n
   // Test whether a given character code starts an identifier.\n
 \n
-  function isIdentifierStart(code) {\n
+  var isIdentifierStart = exports.isIdentifierStart = function(code) {\n
     if (code < 65) return code === 36;\n
     if (code < 91) return true;\n
     if (code < 97) return code === 95;\n
     if (code < 123)return true;\n
     return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));\n
-  }\n
+  };\n
 \n
   // Test whether a given character is part of an identifier.\n
 \n
-  function isIdentifierChar(code) {\n
+  var isIdentifierChar = exports.isIdentifierChar = function(code) {\n
     if (code < 48) return code === 36;\n
     if (code < 58) return true;\n
     if (code < 65) return false;\n
@@ -404,27 +510,16 @@
     if (code < 97) return code === 95;\n
     if (code < 123)return true;\n
     return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));\n
-  }\n
+  };\n
 \n
   // ## Tokenizer\n
 \n
-  // These are used when `options.locations` is on, in order to track\n
-  // the current line number and start of line offset, in order to set\n
-  // `tokStartLoc` and `tokEndLoc`.\n
+  // These are used when `options.locations` is on, for the\n
+  // `tokStartLoc` and `tokEndLoc` properties.\n
 \n
-  function nextLineStart() {\n
-    lineBreak.lastIndex = tokLineStart;\n
-    var match = lineBreak.exec(input);\n
-    return match ? match.index + match[0].length : input.length + 1;\n
-  }\n
-\n
-  function curLineLoc() {\n
-    while (tokLineStartNext <= tokPos) {\n
-      ++tokCurLine;\n
-      tokLineStart = tokLineStartNext;\n
-      tokLineStartNext = nextLineStart();\n
-    }\n
-    return {line: tokCurLine, column: tokPos - tokLineStart};\n
+  function line_loc_t() {\n
+    this.line = tokCurLine;\n
+    this.column = tokPos - tokLineStart;\n
   }\n
 \n
   // Reset the token state. Used at the start of a parse.\n
@@ -432,63 +527,88 @@
   function initTokenState() {\n
     tokCurLine = 1;\n
     tokPos = tokLineStart = 0;\n
-    tokLineStartNext = nextLineStart();\n
     tokRegexpAllowed = true;\n
-    tokComments = null;\n
     skipSpace();\n
   }\n
 \n
-  // Called at the end of every token. Sets `tokEnd`, `tokVal`,\n
-  // `tokCommentsAfter`, and `tokRegexpAllowed`, and skips the space\n
-  // after the token, so that the next one\'s `tokStart` will point at\n
-  // the right position.\n
+  // Called at the end of every token. Sets `tokEnd`, `tokVal`, and\n
+  // `tokRegexpAllowed`, and skips the space after the token, so that\n
+  // the next one\'s `tokStart` will point at the right position.\n
 \n
   function finishToken(type, val) {\n
     tokEnd = tokPos;\n
-    if (options.locations) tokEndLoc = curLineLoc();\n
+    if (options.locations) tokEndLoc = new line_loc_t;\n
     tokType = type;\n
     skipSpace();\n
     tokVal = val;\n
-    tokCommentsAfter = tokComments;\n
     tokRegexpAllowed = type.beforeExpr;\n
   }\n
 \n
   function skipBlockComment() {\n
-    var end = input.indexOf("*/", tokPos += 2);\n
+    var startLoc = options.onComment && options.locations && new line_loc_t;\n
+    var start = tokPos, end = input.indexOf("*/", tokPos += 2);\n
     if (end === -1) raise(tokPos - 2, "Unterminated comment");\n
-    if (options.trackComments)\n
-      (tokComments || (tokComments = [])).push(input.slice(tokPos, end));\n
     tokPos = end + 2;\n
+    if (options.locations) {\n
+      lineBreak.lastIndex = start;\n
+      var match;\n
+      while ((match = lineBreak.exec(input)) && match.index < tokPos) {\n
+        ++tokCurLine;\n
+        tokLineStart = match.index + match[0].length;\n
+      }\n
+    }\n
+    if (options.onComment)\n
+      options.onComment(true, input.slice(start + 2, end), start, tokPos,\n
+                        startLoc, options.locations && new line_loc_t);\n
   }\n
 \n
   function skipLineComment() {\n
     var start = tokPos;\n
+    var startLoc = options.onComment && options.locations && new line_loc_t;\n
     var ch = input.charCodeAt(tokPos+=2);\n
-    while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8329) {\n
+    while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {\n
       ++tokPos;\n
       ch = input.charCodeAt(tokPos);\n
     }\n
-    (tokComments || (tokComments = [])).push(input.slice(start, tokPos));\n
+    if (options.onComment)\n
+      options.onComment(false, input.slice(start + 2, tokPos), start, tokPos,\n
+                        startLoc, options.locations && new line_loc_t);\n
   }\n
 \n
   // Called at the start of the parse and after every token. Skips\n
-  // whitespace and comments, and, if `options.trackComments` is on,\n
-  // will store all skipped comments in `tokComments`.\n
+  // whitespace and comments, and.\n
 \n
   function skipSpace() {\n
-    tokComments = null;\n
     while (tokPos < inputLen) {\n
       var ch = input.charCodeAt(tokPos);\n
-      if (ch === 47) { // \'/\'\n
-        var next = input.charCodeAt(tokPos+1);\n
+      if (ch === 32) { // \' \'\n
+        ++tokPos;\n
+      } else if (ch === 13) {\n
+        ++tokPos;\n
+        var next = input.charCodeAt(tokPos);\n
+        if (next === 10) {\n
+          ++tokPos;\n
+        }\n
+        if (options.locations) {\n
+          ++tokCurLine;\n
+          tokLineStart = tokPos;\n
+        }\n
+      } else if (ch === 10 || ch === 8232 || ch === 8233) {\n
+        ++tokPos;\n
+        if (options.locations) {\n
+          ++tokCurLine;\n
+          tokLineStart = tokPos;\n
+        }\n
+      } else if (ch > 8 && ch < 14) {\n
+        ++tokPos;\n
+      } else if (ch === 47) { // \'/\'\n
+        var next = input.charCodeAt(tokPos + 1);\n
         if (next === 42) { // \'*\'\n
           skipBlockComment();\n
         } else if (next === 47) { // \'/\'\n
           skipLineComment();\n
         } else break;\n
-      } else if (ch < 14 && ch > 8) {\n
-        ++tokPos;\n
-      } else if (ch === 32 || ch === 160) { // \' \', \'\\xa0\'\n
+      } else if (ch === 160) { // \'\\xa0\'\n
         ++tokPos;\n
       } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {\n
         ++tokPos;\n
@@ -510,26 +630,89 @@
   // The `forceRegexp` parameter is used in the one case where the\n
   // `tokRegexpAllowed` trick does not work. See `parseStatement`.\n
 \n
-  function readToken(forceRegexp) {\n
-    tokStart = tokPos;\n
-    if (options.locations) tokStartLoc = curLineLoc();\n
-    tokCommentsBefore = tokComments;\n
-    if (forceRegexp) return readRegexp();\n
-    if (tokPos >= inputLen) return finishToken(_eof);\n
+  function readToken_dot() {\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (next >= 48 && next <= 57) return readNumber(true);\n
+    ++tokPos;\n
+    return finishToken(_dot);\n
+  }\n
 \n
-    var code = input.charCodeAt(tokPos);\n
-    // Identifier or keyword. \'\\uXXXX\' sequences are allowed in\n
-    // identifiers, so \'\\\' also dispatches to that.\n
-    if (isIdentifierStart(code) || code === 92 /* \'\\\' */) return readWord();\n
-    var next = input.charCodeAt(tokPos+1);\n
+  function readToken_slash() { // \'/\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (tokRegexpAllowed) {++tokPos; return readRegexp();}\n
+    if (next === 61) return finishOp(_assign, 2);\n
+    return finishOp(_slash, 1);\n
+  }\n
 \n
+  function readToken_mult_modulo() { // \'%*\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (next === 61) return finishOp(_assign, 2);\n
+    return finishOp(_multiplyModulo, 1);\n
+  }\n
+\n
+  function readToken_pipe_amp(code) { // \'|&\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);\n
+    if (next === 61) return finishOp(_assign, 2);\n
+    return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);\n
+  }\n
+\n
+  function readToken_caret() { // \'^\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (next === 61) return finishOp(_assign, 2);\n
+    return finishOp(_bitwiseXOR, 1);\n
+  }\n
+\n
+  function readToken_plus_min(code) { // \'+-\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (next === code) {\n
+      if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&\n
+          newline.test(input.slice(lastEnd, tokPos))) {\n
+        // A `-->` line comment\n
+        tokPos += 3;\n
+        skipLineComment();\n
+        skipSpace();\n
+        return readToken();\n
+      }\n
+      return finishOp(_incDec, 2);\n
+    }\n
+    if (next === 61) return finishOp(_assign, 2);\n
+    return finishOp(_plusMin, 1);\n
+  }\n
+\n
+  function readToken_lt_gt(code) { // \'<>\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    var size = 1;\n
+    if (next === code) {\n
+      size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;\n
+      if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);\n
+      return finishOp(_bitShift, size);\n
+    }\n
+    if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&\n
+        input.charCodeAt(tokPos + 3) == 45) {\n
+      // `<!--`, an XML-style comment that should be interpreted as a line comment\n
+      tokPos += 4;\n
+      skipLineComment();\n
+      skipSpace();\n
+      return readToken();\n
+    }\n
+    if (next === 61)\n
+      size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;\n
+    return finishOp(_relational, size);\n
+  }\n
+\n
+  function readToken_eq_excl(code) { // \'=!\'\n
+    var next = input.charCodeAt(tokPos + 1);\n
+    if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);\n
+    return finishOp(code === 61 ? _eq : _prefix, 1);\n
+  }\n
+\n
+  function getTokenFromCode(code) {\n
     switch(code) {\n
       // The interpretation of a dot depends on whether it is followed\n
       // by a digit.\n
     case 46: // \'.\'\n
-      if (next >= 48 && next <= 57) return readNumber(String.fromCharCode(code));\n
-      ++tokPos;\n
-      return finishToken(_dot);\n
+      return readToken_dot();\n
 \n
       // Punctuation tokens.\n
     case 40: ++tokPos; return finishToken(_parenL);\n
@@ -545,11 +728,12 @@
 \n
       // \'0x\' is a hexadecimal number.\n
     case 48: // \'0\'\n
+      var next = input.charCodeAt(tokPos + 1);\n
       if (next === 120 || next === 88) return readHexNumber();\n
       // Anything else beginning with a digit is an integer, octal\n
       // number, or float.\n
     case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9\n
-      return readNumber(String.fromCharCode(code));\n
+      return readNumber(false);\n
 \n
       // Quotes produce strings.\n
     case 34: case 39: // \'"\', "\'"\n
@@ -561,52 +745,55 @@
     // of the type given by its first argument.\n
 \n
     case 47: // \'/\'\n
-      if (tokRegexpAllowed) {++tokPos; return readRegexp();}\n
-      if (next === 61) return finishOp(_assign, 2);\n
-      return finishOp(_slash, 1);\n
+      return readToken_slash(code);\n
 \n
     case 37: case 42: // \'%*\'\n
-      if (next === 61) return finishOp(_assign, 2);\n
-      return finishOp(_bin10, 1);\n
+      return readToken_mult_modulo();\n
 \n
     case 124: case 38: // \'|&\'\n
-      if (next === code) return finishOp(code === 124 ? _bin1 : _bin2, 2);\n
-      if (next === 61) return finishOp(_assign, 2);\n
-      return finishOp(code === 124 ? _bin3 : _bin5, 1);\n
+      return readToken_pipe_amp(code);\n
 \n
     case 94: // \'^\'\n
-      if (next === 61) return finishOp(_assign, 2);\n
-      return finishOp(_bin4, 1);\n
+      return readToken_caret();\n
 \n
     case 43: case 45: // \'+-\'\n
-      if (next === code) return finishOp(_incdec, 2);\n
-      if (next === 61) return finishOp(_assign, 2);\n
-      return finishOp(_plusmin, 1);\n
+      return readToken_plus_min(code);\n
 \n
     case 60: case 62: // \'<>\'\n
-      var size = 1;\n
-      if (next === code) {\n
-        size = code === 62 && input.charCodeAt(tokPos+2) === 62 ? 3 : 2;\n
-        if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);\n
-        return finishOp(_bin8, size);\n
-      }\n
-      if (next === 61)\n
-        size = input.charCodeAt(tokPos+2) === 61 ? 3 : 2;\n
-      return finishOp(_bin7, size);\n
+      return readToken_lt_gt(code);\n
 \n
     case 61: case 33: // \'=!\'\n
-      if (next === 61) return finishOp(_bin6, input.charCodeAt(tokPos+2) === 61 ? 3 : 2);\n
-      return finishOp(code === 61 ? _eq : _prefix, 1);\n
+      return readToken_eq_excl(code);\n
 \n
     case 126: // \'~\'\n
       return finishOp(_prefix, 1);\n
     }\n
 \n
-    // If we are here, we either found a non-ASCII identifier\n
-    // character, or something that\'s entirely disallowed.\n
-    var ch = String.fromCharCode(code);\n
-    if (ch === "\\\\" || nonASCIIidentifierStart.test(ch)) return readWord();\n
-    raise(tokPos, "Unexpected character \'" + ch + "\'");\n
+    return false;\n
+  }\n
+\n
+  function readToken(forceRegexp) {\n
+    if (!forceRegexp) tokStart = tokPos;\n
+    else tokPos = tokStart + 1;\n
+    if (options.locations) tokStartLoc = new line_loc_t;\n
+    if (forceRegexp) return readRegexp();\n
+    if (tokPos >= inputLen) return finishToken(_eof);\n
+\n
+    var code = input.charCodeAt(tokPos);\n
+    // Identifier or keyword. \'\\uXXXX\' sequences are allowed in\n
+    // identifiers, so \'\\\' also dispatches to that.\n
+    if (isIdentifierStart(code) || code === 92 /* \'\\\' */) return readWord();\n
+\n
+    var tok = getTokenFromCode(code);\n
+\n
+    if (tok === false) {\n
+      // If we are here, we either found a non-ASCII identifier\n
+      // character, or something that\'s entirely disallowed.\n
+      var ch = String.fromCharCode(code);\n
+      if (ch === "\\\\" || nonASCIIidentifierStart.test(ch)) return readWord();\n
+      raise(tokPos, "Unexpected character \'" + ch + "\'");\n
+    }\n
+    return tok;\n
   }\n
 \n
   function finishOp(type, size) {\n
@@ -638,7 +825,13 @@
     // here (don\'t ask).\n
     var mods = readWord1();\n
     if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regexp flag");\n
-    return finishToken(_regexp, new RegExp(content, mods));\n
+    try {\n
+      var value = new RegExp(content, mods);\n
+    } catch (e) {\n
+      if (e instanceof SyntaxError) raise(start, e.message);\n
+      raise(e);\n
+    }\n
+    return finishToken(_regexp, value);\n
   }\n
 \n
   // Read an integer in the given radix. Return null if zero digits\n
@@ -647,7 +840,7 @@
 \n
   function readInt(radix, len) {\n
     var start = tokPos, total = 0;\n
-    for (;;) {\n
+    for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {\n
       var code = input.charCodeAt(tokPos), val;\n
       if (code >= 97) val = code - 97 + 10; // a\n
       else if (code >= 65) val = code - 65 + 10; // A\n
@@ -671,27 +864,27 @@
   }\n
 \n
   // Read an integer, octal integer, or floating-point number.\n
-  \n
-  function readNumber(ch) {\n
-    var start = tokPos, isFloat = ch === ".";\n
-    if (!isFloat && readInt(10) == null) raise(start, "Invalid number");\n
-    if (isFloat || input.charAt(tokPos) === ".") {\n
-      var next = input.charAt(++tokPos);\n
-      if (next === "-" || next === "+") ++tokPos;\n
-      if (readInt(10) === null && ch === ".") raise(start, "Invalid number");\n
+\n
+  function readNumber(startsWithDot) {\n
+    var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;\n
+    if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number");\n
+    if (input.charCodeAt(tokPos) === 46) {\n
+      ++tokPos;\n
+      readInt(10);\n
       isFloat = true;\n
     }\n
-    if (/e/i.test(input.charAt(tokPos))) {\n
-      var next = input.charAt(++tokPos);\n
-      if (next === "-" || next === "+") ++tokPos;\n
-      if (readInt(10) === null) raise(start, "Invalid number")\n
+    var next = input.charCodeAt(tokPos);\n
+    if (next === 69 || next === 101) { // \'eE\'\n
+      next = input.charCodeAt(++tokPos);\n
+      if (next === 43 || next === 45) ++tokPos; // \'+-\'\n
+      if (readInt(10) === null) raise(start, "Invalid number");\n
       isFloat = true;\n
     }\n
     if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");\n
 \n
     var str = input.slice(start, tokPos), val;\n
     if (isFloat) val = parseFloat(str);\n
-    else if (ch !== "0" || str.length === 1) val = parseInt(str, 10);\n
+    else if (!octal || str.length === 1) val = parseInt(str, 10);\n
     else if (/[89]/.test(str) || strict) raise(start, "Invalid number");\n
     else val = parseInt(str, 8);\n
     return finishToken(_num, val);\n
@@ -701,45 +894,47 @@
 \n
   function readString(quote) {\n
     tokPos++;\n
-    var str = [];\n
+    var out = "";\n
     for (;;) {\n
       if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");\n
       var ch = input.charCodeAt(tokPos);\n
       if (ch === quote) {\n
         ++tokPos;\n
-        return finishToken(_string, String.fromCharCode.apply(null, str));\n
+        return finishToken(_string, out);\n
       }\n
       if (ch === 92) { // \'\\\'\n
         ch = input.charCodeAt(++tokPos);\n
         var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));\n
         if (octal) octal = octal[0];\n
-        while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, octal.length - 1);\n
+        while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);\n
         if (octal === "0") octal = null;\n
         ++tokPos;\n
         if (octal) {\n
           if (strict) raise(tokPos - 2, "Octal literal in strict mode");\n
-          str.push(parseInt(octal, 8));\n
+          out += String.fromCharCode(parseInt(octal, 8));\n
           tokPos += octal.length - 1;\n
         } else {\n
           switch (ch) {\n
-          case 110: str.push(10); break; // \'n\' -> \'\\n\'\n
-          case 114: str.push(13); break; // \'r\' -> \'\\r\'\n
-          case 120: str.push(readHexChar(2)); break; // \'x\'\n
-          case 117: str.push(readHexChar(4)); break; // \'u\'\n
-          case 85: str.push(readHexChar(8)); break; // \'U\'\n
-          case 116: str.push(9); break; // \'t\' -> \'\\t\'\n
-          case 98: str.push(8); break; // \'b\' -> \'\\b\'\n
-          case 118: str.push(11); break; // \'v\' -> \'\\u000b\'\n
-          case 102: str.push(12); break; // \'f\' -> \'\\f\'\n
-          case 48: str.push(0); break; // 0 -> \'\\0\'\n
+          case 110: out += "\\n"; break; // \'n\' -> \'\\n\'\n
+          case 114: out += "\\r"; break; // \'r\' -> \'\\r\'\n
+          case 120: out += String.fromCharCode(readHexChar(2)); break; // \'x\'\n
+          case 117: out += String.fromCharCode(readHexChar(4)); break; // \'u\'\n
+          case 85: out += String.fromCharCode(readHexChar(8)); break; // \'U\'\n
+          case 116: out += "\\t"; break; // \'t\' -> \'\\t\'\n
+          case 98: out += "\\b"; break; // \'b\' -> \'\\b\'\n
+          case 118: out += "\\u000b"; break; // \'v\' -> \'\\u000b\'\n
+          case 102: out += "\\f"; break; // \'f\' -> \'\\f\'\n
+          case 48: out += "\\0"; break; // 0 -> \'\\0\'\n
           case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // \'\\r\\n\'\n
-          case 10: break; // \' \\n\'\n
-          default: str.push(ch); break;\n
+          case 10: // \' \\n\'\n
+            if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }\n
+            break;\n
+          default: out += String.fromCharCode(ch); break;\n
           }\n
         }\n
       } else {\n
-        if (ch === 13 || ch === 10 || ch === 8232 || ch === 8329) raise(tokStart, "Unterminated string constant");\n
-        if (ch !== 92) str.push(ch); // \'\\\'\n
+        if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, "Unterminated string constant");\n
+        out += String.fromCharCode(ch); // \'\\\'\n
         ++tokPos;\n
       }\n
     }\n
@@ -799,13 +994,8 @@
   function readWord() {\n
     var word = readWord1();\n
     var type = _name;\n
-    if (!containsEsc) {\n
-      if (isKeyword(word)) type = keywordTypes[word];\n
-      else if (options.forbidReserved &&\n
-               (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(word) ||\n
-               strict && isStrictReservedWord(word))\n
-        raise(tokStart, "The keyword \'" + word + "\' is reserved");\n
-    }\n
+    if (!containsEsc && isKeyword(word))\n
+      type = keywordTypes[word];\n
     return finishToken(type, word);\n
   }\n
 \n
@@ -832,7 +1022,7 @@
   // ### Parser utilities\n
 \n
   // Continue to the next token.\n
-  \n
+\n
   function next() {\n
     lastStart = tokStart;\n
     lastEnd = tokEnd;\n
@@ -845,69 +1035,64 @@
 \n
   function setStrict(strct) {\n
     strict = strct;\n
-    tokPos = lastEnd;\n
+    tokPos = tokStart;\n
+    if (options.locations) {\n
+      while (tokPos < tokLineStart) {\n
+        tokLineStart = input.lastIndexOf("\\n", tokLineStart - 2) + 1;\n
+        --tokCurLine;\n
+      }\n
+    }\n
     skipSpace();\n
     readToken();\n
   }\n
 \n
-  // Start an AST node, attaching a start offset and optionally a\n
-  // `commentsBefore` property to it.\n
+  // Start an AST node, attaching a start offset.\n
+\n
+  function node_t() {\n
+    this.type = null;\n
+    this.start = tokStart;\n
+    this.end = null;\n
+  }\n
+\n
+  function node_loc_t() {\n
+    this.start = tokStartLoc;\n
+    this.end = null;\n
+    if (sourceFile !== null) this.source = sourceFile;\n
+  }\n
 \n
   function startNode() {\n
-    var node = {type: null, start: tokStart, end: null};\n
-    if (options.trackComments && tokCommentsBefore) {\n
-      node.commentsBefore = tokCommentsBefore;\n
-      tokCommentsBefore = null;\n
-    }\n
+    var node = new node_t();\n
     if (options.locations)\n
-      node.loc = {start: tokStartLoc, end: null, source: sourceFile};\n
+      node.loc = new node_loc_t();\n
+    if (options.directSourceFile)\n
+      node.sourceFile = options.directSourceFile;\n
     if (options.ranges)\n
       node.range = [tokStart, 0];\n
     return node;\n
   }\n
 \n
-  // Start a node whose start offset/comments information should be\n
-  // based on the start of another node. For example, a binary\n
-  // operator node is only started after its left-hand side has\n
-  // already been parsed.\n
+  // Start a node whose start offset information should be based on\n
+  // the start of another node. For example, a binary operator node is\n
+  // only started after its left-hand side has already been parsed.\n
 \n
   function startNodeFrom(other) {\n
-    var node = {type: null, start: other.start};\n
-    if (other.commentsBefore) {\n
-      node.commentsBefore = other.commentsBefore;\n
-      other.commentsBefore = null;\n
+    var node = new node_t();\n
+    node.start = other.start;\n
+    if (options.locations) {\n
+      node.loc = new node_loc_t();\n
+      node.loc.start = other.loc.start;\n
     }\n
-    if (options.locations)\n
-      node.loc = {start: other.loc.start, end: null, source: other.loc.source};\n
     if (options.ranges)\n
       node.range = [other.range[0], 0];\n
 \n
     return node;\n
   }\n
 \n
-  // Finish an AST node, adding `type`, `end`, and `commentsAfter`\n
-  // properties.\n
-  //\n
-  // We keep track of the last node that we finished, in order\n
-  // \'bubble\' `commentsAfter` properties up to the biggest node. I.e.\n
-  // in \'`1 + 1 // foo\', the comment should be attached to the binary\n
-  // operator node, not the second literal node.\n
-\n
-  var lastFinishedNode;\n
+  // Finish an AST node, adding `type` and `end` properties.\n
 \n
   function finishNode(node, type) {\n
     node.type = type;\n
     node.end = lastEnd;\n
-    if (options.trackComments) {\n
-      if (tokCommentsAfter) {\n
-        node.commentsAfter = tokCommentsAfter;\n
-        tokCommentsAfter = null;\n
-      } else if (lastFinishedNode && lastFinishedNode.end === lastEnd) {\n
-        node.commentsAfter = lastFinishedNode.commentsAfter;\n
-        lastFinishedNode.commentsAfter = null;\n
-      }\n
-      lastFinishedNode = node;\n
-    }\n
     if (options.locations)\n
       node.loc.end = lastEndLoc;\n
     if (options.ranges)\n
@@ -978,9 +1163,8 @@
   // to its body instead of creating a new node.\n
 \n
   function parseTopLevel(program) {\n
-    initTokenState();\n
     lastStart = lastEnd = tokPos;\n
-    if (options.locations) lastEndLoc = curLineLoc();\n
+    if (options.locations) lastEndLoc = new line_loc_t;\n
     inFunction = strict = null;\n
     labels = [];\n
     readToken();\n
@@ -994,7 +1178,7 @@
       first = false;\n
     }\n
     return finishNode(node, "Program");\n
-  };\n
+  }\n
 \n
   var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};\n
 \n
@@ -1006,7 +1190,7 @@
   // does not help.\n
 \n
   function parseStatement() {\n
-    if (tokType === _slash)\n
+    if (tokType === _slash || tokType === _assign && tokVal == "/=")\n
       readToken(true);\n
 \n
     var starttype = tokType, node = startNode();\n
@@ -1040,6 +1224,7 @@
 \n
     case _debugger:\n
       next();\n
+      semicolon();\n
       return finishNode(node, "DebuggerStatement");\n
 \n
     case _do:\n
@@ -1069,6 +1254,7 @@
         var init = startNode();\n
         next();\n
         parseVar(init, true);\n
+        finishNode(init, "VariableDeclaration");\n
         if (init.declarations.length === 1 && eat(_in))\n
           return parseForIn(node, init);\n
         return parseFor(node, init);\n
@@ -1089,13 +1275,14 @@
       return finishNode(node, "IfStatement");\n
 \n
     case _return:\n
-      if (!inFunction) raise(tokStart, "\'return\' outside of function");\n
+      if (!inFunction && !options.allowReturnOutsideFunction)\n
+        raise(tokStart, "\'return\' outside of function");\n
       next();\n
 \n
       // In `return` (and `break`/`continue`), the keywords with\n
       // optional arguments, we eagerly look for a semicolon or the\n
       // possibility to insert one.\n
-      \n
+\n
       if (eat(_semi) || canInsertSemicolon()) node.argument = null;\n
       else { node.argument = parseExpression(); semicolon(); }\n
       return finishNode(node, "ReturnStatement");\n
@@ -1110,7 +1297,7 @@
       // Statements under must be grouped (by label) in SwitchCase\n
       // nodes. `cur` is used to keep the node that we are currently\n
       // adding statements to.\n
-      \n
+\n
       for (var cur, sawDefault; tokType != _braceR;) {\n
         if (tokType === _case || tokType === _default) {\n
           var isCase = tokType === _case;\n
@@ -1139,13 +1326,14 @@
       if (newline.test(input.slice(lastEnd, tokStart)))\n
         raise(lastEnd, "Illegal newline after throw");\n
       node.argument = parseExpression();\n
+      semicolon();\n
       return finishNode(node, "ThrowStatement");\n
 \n
     case _try:\n
       next();\n
       node.block = parseBlock();\n
-      node.handlers = [];\n
-      while (tokType === _catch) {\n
+      node.handler = null;\n
+      if (tokType === _catch) {\n
         var clause = startNode();\n
         next();\n
         expect(_parenL);\n
@@ -1155,18 +1343,19 @@
         expect(_parenR);\n
         clause.guard = null;\n
         clause.body = parseBlock();\n
-        node.handlers.push(finishNode(clause, "CatchClause"));\n
+        node.handler = finishNode(clause, "CatchClause");\n
       }\n
+      node.guardedHandlers = empty;\n
       node.finalizer = eat(_finally) ? parseBlock() : null;\n
-      if (!node.handlers.length && !node.finalizer)\n
+      if (!node.handler && !node.finalizer)\n
         raise(node.start, "Missing catch or finally clause");\n
       return finishNode(node, "TryStatement");\n
 \n
     case _var:\n
       next();\n
-      node = parseVar(node);\n
+      parseVar(node);\n
       semicolon();\n
-      return node;\n
+      return finishNode(node, "VariableDeclaration");\n
 \n
     case _while:\n
       next();\n
@@ -1204,6 +1393,7 @@
         var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;\n
         labels.push({name: maybeName, kind: kind});\n
         node.body = parseStatement();\n
+        labels.pop();\n
         node.label = expr;\n
         return finishNode(node, "LabeledStatement");\n
       } else {\n
@@ -1235,11 +1425,11 @@
     while (!eat(_braceR)) {\n
       var stmt = parseStatement();\n
       node.body.push(stmt);\n
-      if (first && isUseStrict(stmt)) {\n
+      if (first && allowStrict && isUseStrict(stmt)) {\n
         oldStrict = strict;\n
         setStrict(strict = true);\n
       }\n
-      first = false\n
+      first = false;\n
     }\n
     if (strict && !oldStrict) setStrict(false);\n
     return finishNode(node, "BlockStatement");\n
@@ -1286,7 +1476,7 @@
       node.declarations.push(finishNode(decl, "VariableDeclarator"));\n
       if (!eat(_comma)) break;\n
     }\n
-    return finishNode(node, "VariableDeclaration");\n
+    return node;\n
   }\n
 \n
   // ### Expression parsing\n
@@ -1347,7 +1537,7 @@
   // Start the precedence parser.\n
 \n
   function parseExprOps(noIn) {\n
-    return parseExprOp(parseMaybeUnary(noIn), -1, noIn);\n
+    return parseExprOp(parseMaybeUnary(), -1, noIn);\n
   }\n
 \n
   // Parse binary operators with the operator precedence parsing\n
@@ -1363,10 +1553,11 @@
         var node = startNodeFrom(left);\n
         node.left = left;\n
         node.operator = tokVal;\n
+        var op = tokType;\n
         next();\n
-        node.right = parseExprOp(parseMaybeUnary(noIn), prec, noIn);\n
-        var node = finishNode(node, /&&|\\|\\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression");\n
-        return parseExprOp(node, minPrec, noIn);\n
+        node.right = parseExprOp(parseMaybeUnary(), prec, noIn);\n
+        var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression");\n
+        return parseExprOp(exprNode, minPrec, noIn);\n
       }\n
     }\n
     return left;\n
@@ -1374,13 +1565,14 @@
 \n
   // Parse unary operators, both prefix and postfix.\n
 \n
-  function parseMaybeUnary(noIn) {\n
+  function parseMaybeUnary() {\n
     if (tokType.prefix) {\n
       var node = startNode(), update = tokType.isUpdate;\n
       node.operator = tokVal;\n
       node.prefix = true;\n
+      tokRegexpAllowed = true;\n
       next();\n
-      node.argument = parseMaybeUnary(noIn);\n
+      node.argument = parseMaybeUnary();\n
       if (update) checkLVal(node.argument);\n
       else if (strict && node.operator === "delete" &&\n
                node.argument.type === "Identifier")\n
@@ -1451,12 +1643,22 @@
     case _null: case _true: case _false:\n
       var node = startNode();\n
       node.value = tokType.atomValue;\n
+      node.raw = tokType.keyword;\n
       next();\n
       return finishNode(node, "Literal");\n
 \n
     case _parenL:\n
+      var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;\n
       next();\n
       var val = parseExpression();\n
+      val.start = tokStart1;\n
+      val.end = tokEnd;\n
+      if (options.locations) {\n
+        val.loc.start = tokStartLoc1;\n
+        val.loc.end = tokEndLoc;\n
+      }\n
+      if (options.ranges)\n
+        val.range = [tokStart1, tokEnd];\n
       expect(_parenR);\n
       return val;\n
 \n
@@ -1484,14 +1686,14 @@
 \n
   // New\'s precedence is slightly tricky. It must allow its argument\n
   // to be a `[]` or dot subscript expression, but not a call 鈥� at\n
-  // least, not without wrapping it in parentheses. Thus, it uses the \n
+  // least, not without wrapping it in parentheses. Thus, it uses the\n
 \n
   function parseNew() {\n
     var node = startNode();\n
     next();\n
-    node.callee = parseSubscripts(parseExprAtom(false), true);\n
+    node.callee = parseSubscripts(parseExprAtom(), true);\n
     if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);\n
-    else node.arguments = [];\n
+    else node.arguments = empty;\n
     return finishNode(node, "NewExpression");\n
   }\n
 \n
@@ -1516,7 +1718,7 @@
         isGetSet = sawGetSet = true;\n
         kind = prop.kind = prop.key.name;\n
         prop.key = parsePropertyName();\n
-        if (!tokType === _parenL) unexpected();\n
+        if (tokType !== _parenL) unexpected();\n
         prop.value = parseFunction(startNode(), false);\n
       } else unexpected();\n
 \n
@@ -1609,28 +1811,30 @@
 \n
   function parseIdent(liberal) {\n
     var node = startNode();\n
-    node.name = tokType === _name ? tokVal : (liberal && !options.forbidReserved && tokType.keyword) || unexpected();\n
+    if (liberal && options.forbidReserved == "everywhere") liberal = false;\n
+    if (tokType === _name) {\n
+      if (!liberal &&\n
+          (options.forbidReserved &&\n
+           (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) ||\n
+           strict && isStrictReservedWord(tokVal)) &&\n
+          input.slice(tokStart, tokEnd).indexOf("\\\\") == -1)\n
+        raise(tokStart, "The keyword \'" + tokVal + "\' is reserved");\n
+      node.name = tokVal;\n
+    } else if (liberal && tokType.keyword) {\n
+      node.name = tokType.keyword;\n
+    } else {\n
+      unexpected();\n
+    }\n
+    tokRegexpAllowed = false;\n
     next();\n
     return finishNode(node, "Identifier");\n
   }\n
 \n
-})(typeof exports === "undefined" ? (window.acorn = {}) : exports);\n
+});\n
 
 
 ]]></string> </value>
         </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>63657</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
       </dictionary>
     </pickle>
   </record>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/lint.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/lint.js.xml
index 9aa442f134a2ba0a2244f13a51ec2aa4a6e91690..0d7c49650b6f6765482fe21d6eb8360d0fc08aed 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/lint.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/lint.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403105.16</string> </value>
+            <value> <string>ts21897151.95</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -43,9 +43,10 @@ var topAllowedGlobals = Object.create(null);\n
 ("Error RegExp Number String Array Function Object Math Date undefined " +\n
  "parseInt parseFloat Infinity NaN isNaN " +\n
  "window document navigator prompt alert confirm console " +\n
- "FileReader Worker postMessage importScripts " +\n
+ "screen FileReader Worker postMessage importScripts " +\n
  "setInterval clearInterval setTimeout clearTimeout " +\n
- "CodeMirror test")\n
+ "CodeMirror " +\n
+ "test exports require module define requirejs")\n
   .split(" ").forEach(function(n) { topAllowedGlobals[n] = true; });\n
 \n
 var fs = require("fs"), acorn = require("./acorn.js"), walk = require("./walk.js");\n
@@ -54,6 +55,8 @@ var scopePasser = walk.make({\n
   ScopeBody: function(node, prev, c) { c(node, node.scope); }\n
 });\n
 \n
+var cBlob = /^\\/\\/ CodeMirror, copyright \\(c\\) by Marijn Haverbeke and others\\n\\/\\/ Distributed under an MIT license: http:\\/\\/codemirror.net\\/LICENSE\\n\\n/;\n
+\n
 function checkFile(fileName) {\n
   var file = fs.readFileSync(fileName, "utf8"), notAllowed;\n
   if (notAllowed = file.match(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x19\\uFEFF\\t]|[ \\t]\\n/)) {\n
@@ -64,6 +67,9 @@ function checkFile(fileName) {\n
     var info = acorn.getLineInfo(file, notAllowed.index);\n
     fail(msg + " at line " + info.line + ", column " + info.column, {source: fileName});\n
   }\n
+\n
+  if (!cBlob.test(file))\n
+    fail("Missing license blob", {source: fileName});\n
   \n
   var globalsSeen = Object.create(null);\n
 \n
@@ -73,7 +79,7 @@ function checkFile(fileName) {\n
       ecmaVersion: 3,\n
       strictSemicolons: true,\n
       allowTrailingCommas: false,\n
-      forbidReserved: true,\n
+      forbidReserved: "everywhere",\n
       sourceFile: fileName\n
     });\n
   } catch (e) {\n
@@ -119,19 +125,40 @@ function checkFile(fileName) {\n
     },\n
     FunctionExpression: function(node) {\n
       if (node.id) fail("Named function expression", node.loc);\n
+    },\n
+    ForStatement: function(node) {\n
+      checkReusedIndex(node);\n
+    },\n
+    MemberExpression: function(node) {\n
+      if (node.object.type == "Identifier" && node.object.name == "console" && !node.computed)\n
+        fail("Found console." + node.property.name, node.loc);\n
+    },\n
+    DebuggerStatement: function(node) {\n
+      fail("Found debugger statement", node.loc);\n
     }\n
   }, scopePasser);\n
 \n
-  if (!globalsSeen.exports) {\n
-    var allowedGlobals = Object.create(topAllowedGlobals), m;\n
-    if (m = file.match(/\\/\\/ declare global:\\s+(.*)/))\n
-      m[1].split(/,\\s*/g).forEach(function(n) { allowedGlobals[n] = true; });\n
-    for (var glob in globalsSeen)\n
-      if (!(glob in allowedGlobals))\n
-        fail("Access to global variable " + glob + ". Add a \'// declare global: " + glob +\n
-             "\' comment or add this variable in test/lint/lint.js.", globalsSeen[glob]);\n
+  function checkReusedIndex(node) {\n
+    if (!node.init || node.init.type != "VariableDeclaration") return;\n
+    var name = node.init.declarations[0].id.name;\n
+    walk.recursive(node.body, null, {\n
+      Function: function() {},\n
+      VariableDeclaration: function(node, st, c) {\n
+        for (var i = 0; i < node.declarations.length; i++)\n
+          if (node.declarations[i].id.name == name)\n
+            fail("redefined loop variable", node.declarations[i].id.loc);\n
+        walk.base.VariableDeclaration(node, st, c);\n
+      }\n
+    });\n
   }\n
 \n
+  var allowedGlobals = Object.create(topAllowedGlobals), m;\n
+  if (m = file.match(/\\/\\/ declare global:\\s+(.*)/))\n
+    m[1].split(/,\\s*/g).forEach(function(n) { allowedGlobals[n] = true; });\n
+  for (var glob in globalsSeen)\n
+    if (!(glob in allowedGlobals))\n
+      fail("Access to global variable " + glob + ". Add a \'// declare global: " + glob +\n
+           "\' comment or add this variable in test/lint/lint.js.", globalsSeen[glob]);\n
 \n
   for (var i = 0; i < scopes.length; ++i) {\n
     var scope = scopes[i];\n
@@ -154,7 +181,7 @@ function checkDir(dir) {\n
   fs.readdirSync(dir).forEach(function(file) {\n
     var fname = dir + "/" + file;\n
     if (/\\.js$/.test(file)) checkFile(fname);\n
-    else if (file != "dep" && fs.lstatSync(fname).isDirectory()) checkDir(fname);\n
+    else if (fs.lstatSync(fname).isDirectory()) checkDir(fname);\n
   });\n
 }\n
 \n
@@ -171,7 +198,7 @@ exports.success = function() { return !failed; };\n
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>4601</int> </value>
+            <value> <int>5742</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/walk.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/walk.js.xml
index 16b46b8b7d93f93970b3d666321320a0a338d630..020f8c5b5f763c6722ff8e8a62ef711fa29b73ef 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/walk.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/lint/walk.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403105.09</string> </value>
+            <value> <string>ts21897151.88</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -24,7 +24,11 @@
 
 // AST walker module for Mozilla Parser API compatible trees\n
 \n
-(function(exports) {\n
+(function(mod) {\n
+  if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS\n
+  if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD\n
+  mod((this.acorn || (this.acorn = {})).walk = {}); // Plain browser env\n
+})(function(exports) {\n
   "use strict";\n
 \n
   // A simple walk is one where you simply specify callbacks to be\n
@@ -43,11 +47,11 @@
   // walker, and state can be used to give this walked an initial\n
   // state.\n
   exports.simple = function(node, visitors, base, state) {\n
-    if (!base) base = exports;\n
+    if (!base) base = exports.base;\n
     function c(node, st, override) {\n
       var type = override || node.type, found = visitors[type];\n
-      if (found) found(node, st);\n
       base[type](node, st, c);\n
+      if (found) found(node, st);\n
     }\n
     c(node, state);\n
   };\n
@@ -58,51 +62,140 @@
   // their child nodes (by calling their third argument on these\n
   // nodes).\n
   exports.recursive = function(node, state, funcs, base) {\n
-    var visitor = exports.make(funcs, base);\n
+    var visitor = funcs ? exports.make(funcs, base) : base;\n
     function c(node, st, override) {\n
       visitor[override || node.type](node, st, c);\n
     }\n
     c(node, state);\n
   };\n
+\n
+  function makeTest(test) {\n
+    if (typeof test == "string")\n
+      return function(type) { return type == test; };\n
+    else if (!test)\n
+      return function() { return true; };\n
+    else\n
+      return test;\n
+  }\n
+\n
+  function Found(node, state) { this.node = node; this.state = state; }\n
+\n
+  // Find a node with a given start, end, and type (all are optional,\n
+  // null can be used as wildcard). Returns a {node, state} object, or\n
+  // undefined when it doesn\'t find a matching node.\n
+  exports.findNodeAt = function(node, start, end, test, base, state) {\n
+    test = makeTest(test);\n
+    try {\n
+      if (!base) base = exports.base;\n
+      var c = function(node, st, override) {\n
+        var type = override || node.type;\n
+        if ((start == null || node.start <= start) &&\n
+            (end == null || node.end >= end))\n
+          base[type](node, st, c);\n
+        if (test(type, node) &&\n
+            (start == null || node.start == start) &&\n
+            (end == null || node.end == end))\n
+          throw new Found(node, st);\n
+      };\n
+      c(node, state);\n
+    } catch (e) {\n
+      if (e instanceof Found) return e;\n
+      throw e;\n
+    }\n
+  };\n
+\n
+  // Find the innermost node of a given type that contains the given\n
+  // position. Interface similar to findNodeAt.\n
+  exports.findNodeAround = function(node, pos, test, base, state) {\n
+    test = makeTest(test);\n
+    try {\n
+      if (!base) base = exports.base;\n
+      var c = function(node, st, override) {\n
+        var type = override || node.type;\n
+        if (node.start > pos || node.end < pos) return;\n
+        base[type](node, st, c);\n
+        if (test(type, node)) throw new Found(node, st);\n
+      };\n
+      c(node, state);\n
+    } catch (e) {\n
+      if (e instanceof Found) return e;\n
+      throw e;\n
+    }\n
+  };\n
+\n
+  // Find the outermost matching node after a given position.\n
+  exports.findNodeAfter = function(node, pos, test, base, state) {\n
+    test = makeTest(test);\n
+    try {\n
+      if (!base) base = exports.base;\n
+      var c = function(node, st, override) {\n
+        if (node.end < pos) return;\n
+        var type = override || node.type;\n
+        if (node.start >= pos && test(type, node)) throw new Found(node, st);\n
+        base[type](node, st, c);\n
+      };\n
+      c(node, state);\n
+    } catch (e) {\n
+      if (e instanceof Found) return e;\n
+      throw e;\n
+    }\n
+  };\n
+\n
+  // Find the outermost matching node before a given position.\n
+  exports.findNodeBefore = function(node, pos, test, base, state) {\n
+    test = makeTest(test);\n
+    if (!base) base = exports.base;\n
+    var max;\n
+    var c = function(node, st, override) {\n
+      if (node.start > pos) return;\n
+      var type = override || node.type;\n
+      if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))\n
+        max = new Found(node, st);\n
+      base[type](node, st, c);\n
+    };\n
+    c(node, state);\n
+    return max;\n
+  };\n
 \n
   // Used to create a custom walker. Will fill in all missing node\n
   // type properties with the defaults.\n
   exports.make = function(funcs, base) {\n
-    if (!base) base = exports;\n
+    if (!base) base = exports.base;\n
     var visitor = {};\n
-    for (var type in base)\n
-      visitor[type] = funcs.hasOwnProperty(type) ? funcs[type] : base[type];\n
+    for (var type in base) visitor[type] = base[type];\n
+    for (var type in funcs) visitor[type] = funcs[type];\n
     return visitor;\n
   };\n
 \n
   function skipThrough(node, st, c) { c(node, st); }\n
-  function ignore(node, st, c) {}\n
+  function ignore(_node, _st, _c) {}\n
 \n
   // Node walkers.\n
 \n
-  exports.Program = exports.BlockStatement = function(node, st, c) {\n
+  var base = exports.base = {};\n
+  base.Program = base.BlockStatement = function(node, st, c) {\n
     for (var i = 0; i < node.body.length; ++i)\n
       c(node.body[i], st, "Statement");\n
   };\n
-  exports.Statement = skipThrough;\n
-  exports.EmptyStatement = ignore;\n
-  exports.ExpressionStatement = function(node, st, c) {\n
+  base.Statement = skipThrough;\n
+  base.EmptyStatement = ignore;\n
+  base.ExpressionStatement = function(node, st, c) {\n
     c(node.expression, st, "Expression");\n
   };\n
-  exports.IfStatement = function(node, st, c) {\n
+  base.IfStatement = function(node, st, c) {\n
     c(node.test, st, "Expression");\n
     c(node.consequent, st, "Statement");\n
     if (node.alternate) c(node.alternate, st, "Statement");\n
   };\n
-  exports.LabeledStatement = function(node, st, c) {\n
+  base.LabeledStatement = function(node, st, c) {\n
     c(node.body, st, "Statement");\n
   };\n
-  exports.BreakStatement = exports.ContinueStatement = ignore;\n
-  exports.WithStatement = function(node, st, c) {\n
+  base.BreakStatement = base.ContinueStatement = ignore;\n
+  base.WithStatement = function(node, st, c) {\n
     c(node.object, st, "Expression");\n
     c(node.body, st, "Statement");\n
   };\n
-  exports.SwitchStatement = function(node, st, c) {\n
+  base.SwitchStatement = function(node, st, c) {\n
     c(node.discriminant, st, "Expression");\n
     for (var i = 0; i < node.cases.length; ++i) {\n
       var cs = node.cases[i];\n
@@ -111,101 +204,104 @@
         c(cs.consequent[j], st, "Statement");\n
     }\n
   };\n
-  exports.ReturnStatement = function(node, st, c) {\n
+  base.ReturnStatement = function(node, st, c) {\n
     if (node.argument) c(node.argument, st, "Expression");\n
   };\n
-  exports.ThrowStatement = function(node, st, c) {\n
+  base.ThrowStatement = function(node, st, c) {\n
     c(node.argument, st, "Expression");\n
   };\n
-  exports.TryStatement = function(node, st, c) {\n
+  base.TryStatement = function(node, st, c) {\n
     c(node.block, st, "Statement");\n
-    for (var i = 0; i < node.handlers.length; ++i)\n
-      c(node.handlers[i].body, st, "ScopeBody");\n
+    if (node.handler) c(node.handler.body, st, "ScopeBody");\n
     if (node.finalizer) c(node.finalizer, st, "Statement");\n
   };\n
-  exports.WhileStatement = function(node, st, c) {\n
+  base.WhileStatement = function(node, st, c) {\n
     c(node.test, st, "Expression");\n
     c(node.body, st, "Statement");\n
   };\n
-  exports.DoWhileStatement = exports.WhileStatement;\n
-  exports.ForStatement = function(node, st, c) {\n
+  base.DoWhileStatement = base.WhileStatement;\n
+  base.ForStatement = function(node, st, c) {\n
     if (node.init) c(node.init, st, "ForInit");\n
     if (node.test) c(node.test, st, "Expression");\n
     if (node.update) c(node.update, st, "Expression");\n
     c(node.body, st, "Statement");\n
   };\n
-  exports.ForInStatement = function(node, st, c) {\n
+  base.ForInStatement = function(node, st, c) {\n
     c(node.left, st, "ForInit");\n
     c(node.right, st, "Expression");\n
     c(node.body, st, "Statement");\n
   };\n
-  exports.ForInit = function(node, st, c) {\n
+  base.ForInit = function(node, st, c) {\n
     if (node.type == "VariableDeclaration") c(node, st);\n
     else c(node, st, "Expression");\n
   };\n
-  exports.DebuggerStatement = ignore;\n
+  base.DebuggerStatement = ignore;\n
 \n
-  exports.FunctionDeclaration = function(node, st, c) {\n
+  base.FunctionDeclaration = function(node, st, c) {\n
     c(node, st, "Function");\n
   };\n
-  exports.VariableDeclaration = function(node, st, c) {\n
+  base.VariableDeclaration = function(node, st, c) {\n
     for (var i = 0; i < node.declarations.length; ++i) {\n
       var decl = node.declarations[i];\n
       if (decl.init) c(decl.init, st, "Expression");\n
     }\n
   };\n
 \n
-  exports.Function = function(node, st, c) {\n
+  base.Function = function(node, st, c) {\n
     c(node.body, st, "ScopeBody");\n
   };\n
-  exports.ScopeBody = function(node, st, c) {\n
+  base.ScopeBody = function(node, st, c) {\n
     c(node, st, "Statement");\n
   };\n
 \n
-  exports.Expression = skipThrough;\n
-  exports.ThisExpression = ignore;\n
-  exports.ArrayExpression = function(node, st, c) {\n
+  base.Expression = skipThrough;\n
+  base.ThisExpression = ignore;\n
+  base.ArrayExpression = function(node, st, c) {\n
     for (var i = 0; i < node.elements.length; ++i) {\n
       var elt = node.elements[i];\n
       if (elt) c(elt, st, "Expression");\n
     }\n
   };\n
-  exports.ObjectExpression = function(node, st, c) {\n
+  base.ObjectExpression = function(node, st, c) {\n
     for (var i = 0; i < node.properties.length; ++i)\n
       c(node.properties[i].value, st, "Expression");\n
   };\n
-  exports.FunctionExpression = exports.FunctionDeclaration;\n
-  exports.SequenceExpression = function(node, st, c) {\n
+  base.FunctionExpression = base.FunctionDeclaration;\n
+  base.SequenceExpression = function(node, st, c) {\n
     for (var i = 0; i < node.expressions.length; ++i)\n
       c(node.expressions[i], st, "Expression");\n
   };\n
-  exports.UnaryExpression = exports.UpdateExpression = function(node, st, c) {\n
+  base.UnaryExpression = base.UpdateExpression = function(node, st, c) {\n
     c(node.argument, st, "Expression");\n
   };\n
-  exports.BinaryExpression = exports.AssignmentExpression = exports.LogicalExpression = function(node, st, c) {\n
+  base.BinaryExpression = base.AssignmentExpression = base.LogicalExpression = function(node, st, c) {\n
     c(node.left, st, "Expression");\n
     c(node.right, st, "Expression");\n
   };\n
-  exports.ConditionalExpression = function(node, st, c) {\n
+  base.ConditionalExpression = function(node, st, c) {\n
     c(node.test, st, "Expression");\n
     c(node.consequent, st, "Expression");\n
     c(node.alternate, st, "Expression");\n
   };\n
-  exports.NewExpression = exports.CallExpression = function(node, st, c) {\n
+  base.NewExpression = base.CallExpression = function(node, st, c) {\n
     c(node.callee, st, "Expression");\n
     if (node.arguments) for (var i = 0; i < node.arguments.length; ++i)\n
       c(node.arguments[i], st, "Expression");\n
   };\n
-  exports.MemberExpression = function(node, st, c) {\n
+  base.MemberExpression = function(node, st, c) {\n
     c(node.object, st, "Expression");\n
     if (node.computed) c(node.property, st, "Expression");\n
   };\n
-  exports.Identifier = exports.Literal = ignore;\n
+  base.Identifier = base.Literal = ignore;\n
 \n
   // A custom walker that keeps track of the scope chain and the\n
   // variables defined in it.\n
-  function makeScope(prev) {\n
-    return {vars: Object.create(null), prev: prev};\n
+  function makeScope(prev, isCatch) {\n
+    return {vars: Object.create(null), prev: prev, isCatch: isCatch};\n
+  }\n
+  function normalScope(scope) {\n
+    while (scope.isCatch) scope = scope.prev;\n
+    return scope;\n
   }\n
   exports.scopeVisitor = exports.make({\n
     Function: function(node, scope, c) {\n
@@ -214,30 +310,31 @@
         inner.vars[node.params[i].name] = {type: "argument", node: node.params[i]};\n
       if (node.id) {\n
         var decl = node.type == "FunctionDeclaration";\n
-        (decl ? scope : inner).vars[node.id.name] =\n
+        (decl ? normalScope(scope) : inner).vars[node.id.name] =\n
           {type: decl ? "function" : "function name", node: node.id};\n
       }\n
       c(node.body, inner, "ScopeBody");\n
     },\n
     TryStatement: function(node, scope, c) {\n
       c(node.block, scope, "Statement");\n
-      for (var i = 0; i < node.handlers.length; ++i) {\n
-        var handler = node.handlers[i], inner = makeScope(scope);\n
-        inner.vars[handler.param.name] = {type: "catch clause", node: handler.param};\n
-        c(handler.body, inner, "ScopeBody");\n
+      if (node.handler) {\n
+        var inner = makeScope(scope, true);\n
+        inner.vars[node.handler.param.name] = {type: "catch clause", node: node.handler.param};\n
+        c(node.handler.body, inner, "ScopeBody");\n
       }\n
       if (node.finalizer) c(node.finalizer, scope, "Statement");\n
     },\n
     VariableDeclaration: function(node, scope, c) {\n
+      var target = normalScope(scope);\n
       for (var i = 0; i < node.declarations.length; ++i) {\n
         var decl = node.declarations[i];\n
-        scope.vars[decl.id.name] = {type: "var", node: decl.id};\n
+        target.vars[decl.id.name] = {type: "var", node: decl.id};\n
         if (decl.init) c(decl.init, scope, "Expression");\n
       }\n
     }\n
   });\n
 \n
-})(typeof exports == "undefined" ? acorn.walk = {} : exports);\n
+});\n
 
 
 ]]></string> </value>
@@ -248,7 +345,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>7837</int> </value>
+            <value> <int>10917</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.css.xml
index 66a6a0ae8a447ea43af4ddb0d5c772805f25bf1c..061a7f427998d9dfcecc2fd30ccc365194240c79 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.css.xml
@@ -34,6 +34,19 @@
 .mt-output .mt-style {\n
   font-size: x-small;\n
 }\n
+\n
+.mt-output .mt-state {\n
+  font-size: x-small;\n
+  vertical-align: top;\n
+}\n
+\n
+.mt-output .mt-state-row {\n
+  display: none;\n
+}\n
+\n
+.mt-state-unhide .mt-output .mt-state-row {\n
+  display: table-row;\n
+}\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.js.xml
index 68d853425789a95e29c606faec627010696f7418..0482748c3fc23dc06772accd9bdb4cb307b9c34a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/mode_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.85</string> </value>
+            <value> <string>ts21897151.44</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -76,7 +76,7 @@
           pos = end;\n
         }\n
         text = text.replace(/\\[\\[|\\]\\]/g, function(s) {return s.charAt(0);});\n
-        tokens.push(style, text);\n
+        tokens.push({style: style, text: text});\n
         plain += text;\n
       }\n
     }\n
@@ -91,16 +91,17 @@
   };\n
 \n
   function esc(str) {\n
-    return str.replace(\'&\', \'&amp;\').replace(\'<\', \'&lt;\');\n
+    return str.replace(\'&\', \'&amp;\').replace(\'<\', \'&lt;\').replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/\'/g, "&#039;");\n
+;\n
   }\n
 \n
   function compare(text, expected, mode) {\n
 \n
     var expectedOutput = [];\n
-    for (var i = 0; i < expected.length; i += 2) {\n
-      var sty = expected[i];\n
+    for (var i = 0; i < expected.length; ++i) {\n
+      var sty = expected[i].style;\n
       if (sty && sty.indexOf(" ")) sty = sty.split(\' \').sort().join(\' \');\n
-      expectedOutput.push(sty, expected[i + 1]);\n
+      expectedOutput.push({style: sty, text: expected[i].text});\n
     }\n
 \n
     var observedOutput = highlight(text, mode);\n
@@ -113,7 +114,7 @@
       s +=   \'<div class="cm-s-default">\';\n
       s += \'expected:\';\n
       s +=   prettyPrintOutputTable(expectedOutput, diff);\n
-      s += \'observed:\';\n
+      s += \'observed: [<a onclick="this.parentElement.className+=\\\' mt-state-unhide\\\'">display states</a>]\';\n
       s +=   prettyPrintOutputTable(observedOutput, diff);\n
       s +=   \'</div>\';\n
       s += \'</div>\';\n
@@ -124,9 +125,22 @@
     }\n
     if (s) throw new Failure(s);\n
   }\n
+\n
+  function stringify(obj) {\n
+    function replacer(key, obj) {\n
+      if (typeof obj == "function") {\n
+        var m = obj.toString().match(/function\\s*[^\\s(]*/);\n
+        return m ? m[0] : "function";\n
+      }\n
+      return obj;\n
+    }\n
+    if (window.JSON && JSON.stringify)\n
+      return JSON.stringify(obj, replacer, 2);\n
+    return "[unsupported]";  // Fail safely if no native JSON.\n
+  }\n
 \n
   function highlight(string, mode) {\n
-    var state = mode.startState()\n
+    var state = mode.startState();\n
 \n
     var lines = string.replace(/\\r\\n/g,\'\\n\').split(\'\\n\');\n
     var st = [], pos = 0;\n
@@ -143,17 +157,21 @@
       if (line == "" && mode.blankLine) mode.blankLine(state);\n
       /* Start copied code from CodeMirror.highlight */\n
       while (!stream.eol()) {\n
-        var compare = mode.token(stream, state), substr = stream.current();\n
+        for (var j = 0; j < 10 && stream.start >= stream.pos; j++)\n
+          var compare = mode.token(stream, state);\n
+        if (j == 10)\n
+          throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos);\n
+        var substr = stream.current();\n
         if (compare && compare.indexOf(" ") > -1) compare = compare.split(\' \').sort().join(\' \');\n
         stream.start = stream.pos;\n
-        if (pos && st[pos-2] == compare && !newLine) {\n
-          st[pos-1] += substr;\n
+        if (pos && st[pos-1].style == compare && !newLine) {\n
+          st[pos-1].text += substr;\n
         } else if (substr) {\n
-          st[pos++] = compare; st[pos++] = substr;\n
+          st[pos++] = {style: compare, text: substr, state: stringify(state)};\n
         }\n
         // Give up when line is ridiculously long\n
         if (stream.pos > 5000) {\n
-          st[pos++] = null; st[pos++] = this.text.slice(stream.pos);\n
+          st[pos++] = {style: null, text: this.text.slice(stream.pos)};\n
           break;\n
         }\n
         newLine = false;\n
@@ -166,27 +184,33 @@
   function highlightOutputsDifferent(o1, o2) {\n
     var minLen = Math.min(o1.length, o2.length);\n
     for (var i = 0; i < minLen; ++i)\n
-      if (o1[i] != o2[i]) return i >> 1;\n
+      if (o1[i].style != o2[i].style || o1[i].text != o2[i].text) return i;\n
     if (o1.length > minLen || o2.length > minLen) return minLen;\n
   }\n
 \n
   function prettyPrintOutputTable(output, diffAt) {\n
     var s = \'<table class="mt-output">\';\n
     s += \'<tr>\';\n
-    for (var i = 0; i < output.length; i += 2) {\n
-      var style = output[i], val = output[i+1];\n
+    for (var i = 0; i < output.length; ++i) {\n
+      var style = output[i].style, val = output[i].text;\n
       s +=\n
       \'<td class="mt-token"\' + (i == diffAt * 2 ? " style=\'background: pink\'" : "") + \'>\' +\n
         \'<span class="cm-\' + esc(String(style)) + \'">\' +\n
-        esc(val.replace(/ /g,\'\\xb7\')) +\n
+        esc(val.replace(/ /g,\'\\xb7\')) +  // 路 MIDDLE DOT\n
         \'</span>\' +\n
         \'</td>\';\n
     }\n
     s += \'</tr><tr>\';\n
-    for (var i = 0; i < output.length; i += 2) {\n
-      s += \'<td class="mt-style"><span>\' + (output[i] || null) + \'</span></td>\';\n
+    for (var i = 0; i < output.length; ++i) {\n
+      s += \'<td class="mt-style"><span>\' + (output[i].style || null) + \'</span></td>\';\n
+    }\n
+    if(output[0].state) {\n
+      s += \'</tr><tr class="mt-state-row" title="State AFTER each token">\';\n
+      for (var i = 0; i < output.length; ++i) {\n
+        s += \'<td class="mt-state"><pre>\' + esc(output[i].state) + \'</pre></td>\';\n
+      }\n
     }\n
-    s += \'</table>\';\n
+    s += \'</tr></table>\';\n
     return s;\n
   }\n
 })();\n
@@ -200,7 +224,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>5891</int> </value>
+            <value> <int>7021</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/multi_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/multi_test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f77f39303d88fe6295ba53371a94f8fec7a608d
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/multi_test.js.xml
@@ -0,0 +1,329 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897150.92</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>multi_test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+(function() {\n
+  namespace = "multi_";\n
+\n
+  function hasSelections(cm) {\n
+    var sels = cm.listSelections();\n
+    var given = (arguments.length - 1) / 4;\n
+    if (sels.length != given)\n
+      throw new Failure("expected " + given + " selections, found " + sels.length);\n
+    for (var i = 0, p = 1; i < given; i++, p += 4) {\n
+      var anchor = Pos(arguments[p], arguments[p + 1]);\n
+      var head = Pos(arguments[p + 2], arguments[p + 3]);\n
+      eqPos(sels[i].anchor, anchor, "anchor of selection " + i);\n
+      eqPos(sels[i].head, head, "head of selection " + i);\n
+    }\n
+  }\n
+  function hasCursors(cm) {\n
+    var sels = cm.listSelections();\n
+    var given = (arguments.length - 1) / 2;\n
+    if (sels.length != given)\n
+      throw new Failure("expected " + given + " selections, found " + sels.length);\n
+    for (var i = 0, p = 1; i < given; i++, p += 2) {\n
+      eqPos(sels[i].anchor, sels[i].head, "something selected for " + i);\n
+      var head = Pos(arguments[p], arguments[p + 1]);\n
+      eqPos(sels[i].head, head, "selection " + i);\n
+    }\n
+  }\n
+\n
+  testCM("getSelection", function(cm) {\n
+    select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, {anchor: Pos(2, 2), head: Pos(2, 0)});\n
+    eq(cm.getSelection(), "1234\\n56\\n90");\n
+    eq(cm.getSelection(false).join("|"), "1234|56|90");\n
+    eq(cm.getSelections().join("|"), "1234\\n56|90");\n
+  }, {value: "1234\\n5678\\n90"});\n
+\n
+  testCM("setSelection", function(cm) {\n
+    select(cm, Pos(3, 0), Pos(0, 0), {anchor: Pos(2, 5), head: Pos(1, 0)});\n
+    hasSelections(cm, 0, 0, 0, 0,\n
+                  2, 5, 1, 0,\n
+                  3, 0, 3, 0);\n
+    cm.setSelection(Pos(1, 2), Pos(1, 1));\n
+    hasSelections(cm, 1, 2, 1, 1);\n
+    select(cm, {anchor: Pos(1, 1), head: Pos(2, 4)},\n
+           {anchor: Pos(0, 0), head: Pos(1, 3)},\n
+           Pos(3, 0), Pos(2, 2));\n
+    hasSelections(cm, 0, 0, 2, 4,\n
+                  3, 0, 3, 0);\n
+    cm.setSelections([{anchor: Pos(0, 1), head: Pos(0, 2)},\n
+                      {anchor: Pos(1, 1), head: Pos(1, 2)},\n
+                      {anchor: Pos(2, 1), head: Pos(2, 2)}], 1);\n
+    eqPos(cm.getCursor("head"), Pos(1, 2));\n
+    eqPos(cm.getCursor("anchor"), Pos(1, 1));\n
+    eqPos(cm.getCursor("from"), Pos(1, 1));\n
+    eqPos(cm.getCursor("to"), Pos(1, 2));\n
+    cm.setCursor(Pos(1, 1));\n
+    hasCursors(cm, 1, 1);\n
+  }, {value: "abcde\\nabcde\\nabcde\\n"});\n
+\n
+  testCM("somethingSelected", function(cm) {\n
+    select(cm, Pos(0, 1), {anchor: Pos(0, 3), head: Pos(0, 5)});\n
+    eq(cm.somethingSelected(), true);\n
+    select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5));\n
+    eq(cm.somethingSelected(), false);\n
+  }, {value: "123456789"});\n
+\n
+  testCM("extendSelection", function(cm) {\n
+    select(cm, Pos(0, 1), Pos(1, 1), Pos(2, 1));\n
+    cm.setExtending(true);\n
+    cm.extendSelections([Pos(0, 2), Pos(1, 0), Pos(2, 3)]);\n
+    hasSelections(cm, 0, 1, 0, 2,\n
+                  1, 1, 1, 0,\n
+                  2, 1, 2, 3);\n
+    cm.extendSelection(Pos(2, 4), Pos(2, 0));\n
+    hasSelections(cm, 2, 4, 2, 0);\n
+  }, {value: "1234\\n1234\\n1234"});\n
+\n
+  testCM("addSelection", function(cm) {\n
+    select(cm, Pos(0, 1), Pos(1, 1));\n
+    cm.addSelection(Pos(0, 0), Pos(0, 4));\n
+    hasSelections(cm, 0, 0, 0, 4,\n
+                  1, 1, 1, 1);\n
+    cm.addSelection(Pos(2, 2));\n
+    hasSelections(cm, 0, 0, 0, 4,\n
+                  1, 1, 1, 1,\n
+                  2, 2, 2, 2);\n
+  }, {value: "1234\\n1234\\n1234"});\n
+\n
+  testCM("replaceSelection", function(cm) {\n
+    var selections = [{anchor: Pos(0, 0), head: Pos(0, 1)},\n
+                      {anchor: Pos(0, 2), head: Pos(0, 3)},\n
+                      {anchor: Pos(0, 4), head: Pos(0, 5)},\n
+                      {anchor: Pos(2, 1), head: Pos(2, 4)},\n
+                      {anchor: Pos(2, 5), head: Pos(2, 6)}];\n
+    var val = "123456\\n123456\\n123456";\n
+    cm.setValue(val);\n
+    cm.setSelections(selections);\n
+    cm.replaceSelection("ab", "around");\n
+    eq(cm.getValue(), "ab2ab4ab6\\n123456\\n1ab5ab");\n
+    hasSelections(cm, 0, 0, 0, 2,\n
+                  0, 3, 0, 5,\n
+                  0, 6, 0, 8,\n
+                  2, 1, 2, 3,\n
+                  2, 4, 2, 6);\n
+    cm.setValue(val);\n
+    cm.setSelections(selections);\n
+    cm.replaceSelection("", "around");\n
+    eq(cm.getValue(), "246\\n123456\\n15");\n
+    hasSelections(cm, 0, 0, 0, 0,\n
+                  0, 1, 0, 1,\n
+                  0, 2, 0, 2,\n
+                  2, 1, 2, 1,\n
+                  2, 2, 2, 2);\n
+    cm.setValue(val);\n
+    cm.setSelections(selections);\n
+    cm.replaceSelection("X\\nY\\nZ", "around");\n
+    hasSelections(cm, 0, 0, 2, 1,\n
+                  2, 2, 4, 1,\n
+                  4, 2, 6, 1,\n
+                  8, 1, 10, 1,\n
+                  10, 2, 12, 1);\n
+    cm.replaceSelection("a", "around");\n
+    hasSelections(cm, 0, 0, 0, 1,\n
+                  0, 2, 0, 3,\n
+                  0, 4, 0, 5,\n
+                  2, 1, 2, 2,\n
+                  2, 3, 2, 4);\n
+    cm.replaceSelection("xy", "start");\n
+    hasSelections(cm, 0, 0, 0, 0,\n
+                  0, 3, 0, 3,\n
+                  0, 6, 0, 6,\n
+                  2, 1, 2, 1,\n
+                  2, 4, 2, 4);\n
+    cm.replaceSelection("z\\nf");\n
+    hasSelections(cm, 1, 1, 1, 1,\n
+                  2, 1, 2, 1,\n
+                  3, 1, 3, 1,\n
+                  6, 1, 6, 1,\n
+                  7, 1, 7, 1);\n
+    eq(cm.getValue(), "z\\nfxy2z\\nfxy4z\\nfxy6\\n123456\\n1z\\nfxy5z\\nfxy");\n
+  });\n
+\n
+  function select(cm) {\n
+    var sels = [];\n
+    for (var i = 1; i < arguments.length; i++) {\n
+      var arg = arguments[i];\n
+      if (arg.head) sels.push(arg);\n
+      else sels.push({head: arg, anchor: arg});\n
+    }\n
+    cm.setSelections(sels, sels.length - 1);\n
+  }\n
+\n
+  testCM("indentSelection", function(cm) {\n
+    select(cm, Pos(0, 1), Pos(1, 1));\n
+    cm.indentSelection(4);\n
+    eq(cm.getValue(), "    foo\\n    bar\\nbaz");\n
+\n
+    select(cm, Pos(0, 2), Pos(0, 3), Pos(0, 4));\n
+    cm.indentSelection(-2);\n
+    eq(cm.getValue(), "  foo\\n    bar\\nbaz");\n
+\n
+    select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)},\n
+           {anchor: Pos(1, 3), head: Pos(2, 0)});\n
+    cm.indentSelection(-2);\n
+    eq(cm.getValue(), "foo\\n  bar\\nbaz");\n
+  }, {value: "foo\\nbar\\nbaz"});\n
+\n
+  testCM("killLine", function(cm) {\n
+    select(cm, Pos(0, 1), Pos(0, 2), Pos(1, 1));\n
+    cm.execCommand("killLine");\n
+    eq(cm.getValue(), "f\\nb\\nbaz");\n
+    cm.execCommand("killLine");\n
+    eq(cm.getValue(), "fbbaz");\n
+    cm.setValue("foo\\nbar\\nbaz");\n
+    select(cm, Pos(0, 1), {anchor: Pos(0, 2), head: Pos(2, 1)});\n
+    cm.execCommand("killLine");\n
+    eq(cm.getValue(), "faz");\n
+  }, {value: "foo\\nbar\\nbaz"});\n
+\n
+  testCM("deleteLine", function(cm) {\n
+    select(cm, Pos(0, 0),\n
+           {head: Pos(0, 1), anchor: Pos(2, 0)},\n
+           Pos(4, 0));\n
+    cm.execCommand("deleteLine");\n
+    eq(cm.getValue(), "4\\n6\\n7");\n
+    select(cm, Pos(2, 1));\n
+    cm.execCommand("deleteLine");\n
+    eq(cm.getValue(), "4\\n6\\n");\n
+  }, {value: "1\\n2\\n3\\n4\\n5\\n6\\n7"});\n
+\n
+  testCM("deleteH", function(cm) {\n
+    select(cm, Pos(0, 4), {anchor: Pos(1, 4), head: Pos(1, 5)});\n
+    cm.execCommand("delWordAfter");\n
+    eq(cm.getValue(), "foo bar baz\\nabc ef ghi\\n");\n
+    cm.execCommand("delWordAfter");\n
+    eq(cm.getValue(), "foo  baz\\nabc  ghi\\n");\n
+    cm.execCommand("delCharBefore");\n
+    cm.execCommand("delCharBefore");\n
+    eq(cm.getValue(), "fo baz\\nab ghi\\n");\n
+    select(cm, Pos(0, 3), Pos(0, 4), Pos(0, 5));\n
+    cm.execCommand("delWordAfter");\n
+    eq(cm.getValue(), "fo \\nab ghi\\n");\n
+  }, {value: "foo bar baz\\nabc def ghi\\n"});\n
+\n
+  testCM("goLineStart", function(cm) {\n
+    select(cm, Pos(0, 2), Pos(0, 3), Pos(1, 1));\n
+    cm.execCommand("goLineStart");\n
+    hasCursors(cm, 0, 0, 1, 0);\n
+    select(cm, Pos(1, 1), Pos(0, 1));\n
+    cm.setExtending(true);\n
+    cm.execCommand("goLineStart");\n
+    hasSelections(cm, 0, 1, 0, 0,\n
+                  1, 1, 1, 0);\n
+  }, {value: "foo\\nbar\\nbaz"});\n
+\n
+  testCM("moveV", function(cm) {\n
+    select(cm, Pos(0, 2), Pos(1, 2));\n
+    cm.execCommand("goLineDown");\n
+    hasCursors(cm, 1, 2, 2, 2);\n
+    cm.execCommand("goLineUp");\n
+    hasCursors(cm, 0, 2, 1, 2);\n
+    cm.execCommand("goLineUp");\n
+    hasCursors(cm, 0, 0, 0, 2);\n
+    cm.execCommand("goLineUp");\n
+    hasCursors(cm, 0, 0);\n
+    select(cm, Pos(0, 2), Pos(1, 2));\n
+    cm.setExtending(true);\n
+    cm.execCommand("goLineDown");\n
+    hasSelections(cm, 0, 2, 2, 2);\n
+  }, {value: "12345\\n12345\\n12345"});\n
+\n
+  testCM("moveH", function(cm) {\n
+    select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5), Pos(2, 3));\n
+    cm.execCommand("goCharRight");\n
+    hasCursors(cm, 0, 2, 0, 4, 1, 0, 2, 4);\n
+    cm.execCommand("goCharLeft");\n
+    hasCursors(cm, 0, 1, 0, 3, 0, 5, 2, 3);\n
+    for (var i = 0; i < 15; i++)\n
+      cm.execCommand("goCharRight");\n
+    hasCursors(cm, 2, 4, 2, 5);\n
+  }, {value: "12345\\n12345\\n12345"});\n
+\n
+  testCM("newlineAndIndent", function(cm) {\n
+    select(cm, Pos(0, 5), Pos(1, 5));\n
+    cm.execCommand("newlineAndIndent");\n
+    hasCursors(cm, 1, 2, 3, 2);\n
+    eq(cm.getValue(), "x = [\\n  1];\\ny = [\\n  2];");\n
+    cm.undo();\n
+    eq(cm.getValue(), "x = [1];\\ny = [2];");\n
+    hasCursors(cm, 0, 5, 1, 5);\n
+    select(cm, Pos(0, 5), Pos(0, 6));\n
+    cm.execCommand("newlineAndIndent");\n
+    hasCursors(cm, 1, 2, 2, 0);\n
+    eq(cm.getValue(), "x = [\\n  1\\n];\\ny = [2];");\n
+  }, {value: "x = [1];\\ny = [2];", mode: "javascript"});\n
+\n
+  testCM("goDocStartEnd", function(cm) {\n
+    select(cm, Pos(0, 1), Pos(1, 1));\n
+    cm.execCommand("goDocStart");\n
+    hasCursors(cm, 0, 0);\n
+    select(cm, Pos(0, 1), Pos(1, 1));\n
+    cm.execCommand("goDocEnd");\n
+    hasCursors(cm, 1, 3);\n
+    select(cm, Pos(0, 1), Pos(1, 1));\n
+    cm.setExtending(true);\n
+    cm.execCommand("goDocEnd");\n
+    hasSelections(cm, 1, 1, 1, 3);\n
+  }, {value: "abc\\ndef"});\n
+\n
+  testCM("selectionHistory", function(cm) {\n
+    for (var i = 0; i < 3; ++i)\n
+      cm.addSelection(Pos(0, i * 2), Pos(0, i * 2 + 1));\n
+    cm.execCommand("undoSelection");\n
+    eq(cm.getSelection(), "1\\n2");\n
+    cm.execCommand("undoSelection");\n
+    eq(cm.getSelection(), "1");\n
+    cm.execCommand("undoSelection");\n
+    eq(cm.getSelection(), "");\n
+    eqPos(cm.getCursor(), Pos(0, 0));\n
+    cm.execCommand("redoSelection");\n
+    eq(cm.getSelection(), "1");\n
+    cm.execCommand("redoSelection");\n
+    eq(cm.getSelection(), "1\\n2");\n
+    cm.execCommand("redoSelection");\n
+    eq(cm.getSelection(), "1\\n2\\n3");\n
+  }, {value: "1 2 3"});\n
+})();\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>10033</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/phantom_driver.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/phantom_driver.js.xml
index bc4aafaab4ee86726376cfb2d6a6996f0ef86c2e..fe69c157f51c05097cfbf0f9b46ab1dd2f65e98c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/phantom_driver.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/phantom_driver.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.71</string> </value>
+            <value> <string>ts21897151.3</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/run.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/run.js.xml
index 70acacc4d1375d2268c47de9e6e2f2fbf20f9e3e..2eafc4705cd952067c4a21a8be65761b9eeffa83 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/run.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/run.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403103.89</string> </value>
+            <value> <string>ts21897150.57</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/scroll_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/scroll_test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a0e224664e874f0841202bb9712a8a0d3c16af1d
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/scroll_test.js.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897151.75</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>scroll_test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+(function() {\n
+  "use strict";\n
+\n
+  namespace = "scroll_";\n
+\n
+  testCM("bars_hidden", function(cm) {\n
+    for (var i = 0;; i++) {\n
+      var wrapBox = cm.getWrapperElement().getBoundingClientRect();\n
+      var scrollBox = cm.getScrollerElement().getBoundingClientRect();\n
+      is(wrapBox.bottom < scrollBox.bottom - 10);\n
+      is(wrapBox.right < scrollBox.right - 10);\n
+      if (i == 1) break;\n
+      cm.getWrapperElement().style.height = "auto";\n
+      cm.refresh();\n
+    }\n
+  });\n
+  \n
+  function barH(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; }\n
+  function barV(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-vscrollbar")[0]; }\n
+\n
+  function displayBottom(cm, scrollbar) {\n
+    if (scrollbar)\n
+      return barH(cm).getBoundingClientRect().top;\n
+    else\n
+      return cm.getWrapperElement().getBoundingClientRect().bottom - 1;\n
+  }\n
+\n
+  function displayRight(cm, scrollbar) {\n
+    if (scrollbar)\n
+      return barV(cm).getBoundingClientRect().left;\n
+    else\n
+      return cm.getWrapperElement().getBoundingClientRect().right - 1;\n
+  }\n
+\n
+  function testMovedownFixed(cm, hScroll) {\n
+    cm.setSize("100px", "100px");\n
+    if (hScroll) cm.setValue(new Array(100).join("x"));\n
+    var bottom = displayBottom(cm, hScroll);\n
+    for (var i = 0; i < 30; i++) {\n
+      cm.replaceSelection("x\\n");\n
+      var cursorBottom = cm.cursorCoords(null, "window").bottom;\n
+      is(cursorBottom <= bottom);\n
+    }\n
+    is(cursorBottom >= bottom - 5);\n
+  }\n
+\n
+  testCM("movedown_fixed", function(cm) {testMovedownFixed(cm, false);});\n
+  testCM("movedown_hscroll_fixed", function(cm) {testMovedownFixed(cm, true);});\n
+\n
+  function testMovedownResize(cm, hScroll) {\n
+    cm.getWrapperElement().style.height = "auto";\n
+    if (hScroll) cm.setValue(new Array(100).join("x"));\n
+    cm.refresh();\n
+    for (var i = 0; i < 30; i++) {\n
+      cm.replaceSelection("x\\n");\n
+      var bottom = displayBottom(cm, hScroll);\n
+      var cursorBottom = cm.cursorCoords(null, "window").bottom;\n
+      is(cursorBottom <= bottom);\n
+      is(cursorBottom >= bottom - 5);\n
+    }\n
+  }\n
+\n
+  testCM("movedown_resize", function(cm) {testMovedownResize(cm, false);});\n
+  testCM("movedown_hscroll_resize", function(cm) {testMovedownResize(cm, true);});\n
+\n
+  function testMoveright(cm, wrap, scroll) {\n
+    cm.setSize("100px", "100px");\n
+    if (wrap) cm.setOption("lineWrapping", true);\n
+    if (scroll) {\n
+      cm.setValue("\\n" + new Array(100).join("x\\n"));\n
+      cm.setCursor(Pos(0, 0));\n
+    }\n
+    var right = displayRight(cm, scroll);\n
+    for (var i = 0; i < 10; i++) {\n
+      cm.replaceSelection("xxxxxxxxxx");\n
+      var cursorRight = cm.cursorCoords(null, "window").right;\n
+      is(cursorRight < right);\n
+    }\n
+    if (!wrap) is(cursorRight > right - 20);\n
+  }\n
+\n
+  testCM("moveright", function(cm) {testMoveright(cm, false, false);});\n
+  testCM("moveright_wrap", function(cm) {testMoveright(cm, true, false);});\n
+  testCM("moveright_scroll", function(cm) {testMoveright(cm, false, true);});\n
+  testCM("moveright_scroll_wrap", function(cm) {testMoveright(cm, true, true);});\n
+\n
+  testCM("suddenly_wide", function(cm) {\n
+    addDoc(cm, 100, 100);\n
+    cm.replaceSelection(new Array(600).join("l ") + "\\n");\n
+    cm.execCommand("goLineUp");\n
+    cm.execCommand("goLineEnd");\n
+    is(barH(cm).scrollLeft > cm.getScrollerElement().scrollLeft - 1);\n
+  });\n
+\n
+  testCM("wrap_changes_height", function(cm) {\n
+    var line = new Array(20).join("a ") + "\\n";\n
+    cm.setValue(new Array(20).join(line));\n
+    var box = cm.getWrapperElement().getBoundingClientRect();\n
+    cm.setSize(cm.cursorCoords(Pos(0), "window").right - box.left + 2,\n
+               cm.cursorCoords(Pos(19, 0), "window").bottom - box.top + 2);\n
+    cm.setCursor(Pos(19, 0));\n
+    cm.replaceSelection("\\n");\n
+    is(cm.cursorCoords(null, "window").bottom < displayBottom(cm, false));\n
+  }, {lineWrapping: true});\n
+})();\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3804</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/search_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/search_test.js.xml
index c90f4ce728bce3d9eb489a68f6b936fd90c53ce7..0457e5c843a7eec89db9d1b2168199895881e64b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/search_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/search_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.17</string> </value>
+            <value> <string>ts21897150.82</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/sublime_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/sublime_test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..301a91453c0f66e730a7656c959d21bb7b8821e8
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/sublime_test.js.xml
@@ -0,0 +1,347 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21897152.14</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>sublime_test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+(function() {\n
+  "use strict";\n
+  \n
+  var Pos = CodeMirror.Pos;\n
+  namespace = "sublime_";\n
+\n
+  function stTest(name) {\n
+    var actions = Array.prototype.slice.call(arguments, 1);\n
+    testCM(name, function(cm) {\n
+      for (var i = 0; i < actions.length; i++) {\n
+        var action = actions[i];\n
+        if (typeof action == "string" && i == 0)\n
+          cm.setValue(action);\n
+        else if (typeof action == "string")\n
+          cm.execCommand(action);\n
+        else if (action instanceof Pos)\n
+          cm.setCursor(action);\n
+        else\n
+          action(cm);\n
+      }\n
+    });\n
+  }\n
+\n
+  function at(line, ch, msg) {\n
+    return function(cm) {\n
+      eq(cm.listSelections().length, 1);\n
+      eqPos(cm.getCursor("head"), Pos(line, ch), msg);\n
+      eqPos(cm.getCursor("anchor"), Pos(line, ch), msg);\n
+    };\n
+  }\n
+\n
+  function val(content, msg) {\n
+    return function(cm) { eq(cm.getValue(), content, msg); };\n
+  }\n
+\n
+  function argsToRanges(args) {\n
+    if (args.length % 4) throw new Error("Wrong number of arguments for ranges.");\n
+    var ranges = [];\n
+    for (var i = 0; i < args.length; i += 4)\n
+      ranges.push({anchor: Pos(args[i], args[i + 1]),\n
+                   head: Pos(args[i + 2], args[i + 3])});\n
+    return ranges;\n
+  }\n
+\n
+  function setSel() {\n
+    var ranges = argsToRanges(arguments);\n
+    return function(cm) { cm.setSelections(ranges, 0); };\n
+  }\n
+\n
+  function hasSel() {\n
+    var ranges = argsToRanges(arguments);\n
+    return function(cm) {\n
+      var sels = cm.listSelections();\n
+      if (sels.length != ranges.length)\n
+        throw new Failure("Expected " + ranges.length + " selections, but found " + sels.length);\n
+      for (var i = 0; i < sels.length; i++) {\n
+        eqPos(sels[i].anchor, ranges[i].anchor, "anchor " + i);\n
+        eqPos(sels[i].head, ranges[i].head, "head " + i);\n
+      }\n
+    };\n
+  }\n
+\n
+  stTest("bySubword", "the foo_bar DooDahBah \\n a",\n
+         "goSubwordLeft", at(0, 0),\n
+         "goSubwordRight", at(0, 3),\n
+         "goSubwordRight", at(0, 7),\n
+         "goSubwordRight", at(0, 11),\n
+         "goSubwordRight", at(0, 15),\n
+         "goSubwordRight", at(0, 18),\n
+         "goSubwordRight", at(0, 21),\n
+         "goSubwordRight", at(0, 22),\n
+         "goSubwordRight", at(1, 0),\n
+         "goSubwordRight", at(1, 2),\n
+         "goSubwordRight", at(1, 2),\n
+         "goSubwordLeft", at(1, 1),\n
+         "goSubwordLeft", at(1, 0),\n
+         "goSubwordLeft", at(0, 22),\n
+         "goSubwordLeft", at(0, 18),\n
+         "goSubwordLeft", at(0, 15),\n
+         "goSubwordLeft", at(0, 12),\n
+         "goSubwordLeft", at(0, 8),\n
+         "goSubwordLeft", at(0, 4),\n
+         "goSubwordLeft", at(0, 0));\n
+\n
+  stTest("splitSelectionByLine", "abc\\ndef\\nghi",\n
+         setSel(0, 1, 2, 2),\n
+         "splitSelectionByLine",\n
+         hasSel(0, 1, 0, 3,\n
+                1, 0, 1, 3,\n
+                2, 0, 2, 2));\n
+\n
+  stTest("splitSelectionByLineMulti", "abc\\ndef\\nghi\\njkl",\n
+         setSel(0, 1, 1, 1,\n
+                1, 2, 3, 2,\n
+                3, 3, 3, 3),\n
+         "splitSelectionByLine",\n
+         hasSel(0, 1, 0, 3,\n
+                1, 0, 1, 1,\n
+                1, 2, 1, 3,\n
+                2, 0, 2, 3,\n
+                3, 0, 3, 2,\n
+                3, 3, 3, 3));\n
+\n
+  stTest("selectLine", "abc\\ndef\\nghi",\n
+         setSel(0, 1, 0, 1,\n
+                2, 0, 2, 1),\n
+         "selectLine",\n
+         hasSel(0, 0, 1, 0,\n
+                2, 0, 2, 3),\n
+         setSel(0, 1, 1, 0),\n
+         "selectLine",\n
+         hasSel(0, 0, 2, 0));\n
+\n
+  stTest("insertLineAfter", "abcde\\nfghijkl\\nmn",\n
+         setSel(0, 1, 0, 1,\n
+                0, 3, 0, 3,\n
+                1, 2, 1, 2,\n
+                1, 3, 1, 5), "insertLineAfter",\n
+         hasSel(1, 0, 1, 0,\n
+                3, 0, 3, 0), val("abcde\\n\\nfghijkl\\n\\nmn"));\n
+\n
+  stTest("insertLineBefore", "abcde\\nfghijkl\\nmn",\n
+         setSel(0, 1, 0, 1,\n
+                0, 3, 0, 3,\n
+                1, 2, 1, 2,\n
+                1, 3, 1, 5), "insertLineBefore",\n
+         hasSel(0, 0, 0, 0,\n
+                2, 0, 2, 0), val("\\nabcde\\n\\nfghijkl\\nmn"));\n
+\n
+  stTest("selectNextOccurrence", "a foo bar\\nfoobar foo",\n
+         setSel(0, 2, 0, 5),\n
+         "selectNextOccurrence", hasSel(0, 2, 0, 5,\n
+                                        1, 0, 1, 3),\n
+         "selectNextOccurrence", hasSel(0, 2, 0, 5,\n
+                                        1, 0, 1, 3,\n
+                                        1, 7, 1, 10),\n
+         "selectNextOccurrence", hasSel(0, 2, 0, 5,\n
+                                        1, 0, 1, 3,\n
+                                        1, 7, 1, 10),\n
+         Pos(0, 3), "selectNextOccurrence", hasSel(0, 2, 0, 5),\n
+        "selectNextOccurrence", hasSel(0, 2, 0, 5,\n
+                                       1, 7, 1, 10),\n
+         setSel(0, 6, 0, 9),\n
+         "selectNextOccurrence", hasSel(0, 6, 0, 9,\n
+                                        1, 3, 1, 6));\n
+\n
+  stTest("selectScope", "foo(a) {\\n  bar[1, 2];\\n}",\n
+         "selectScope", hasSel(0, 0, 2, 1),\n
+         Pos(0, 4), "selectScope", hasSel(0, 4, 0, 5),\n
+         Pos(0, 5), "selectScope", hasSel(0, 4, 0, 5),\n
+         Pos(0, 6), "selectScope", hasSel(0, 0, 2, 1),\n
+         Pos(0, 8), "selectScope", hasSel(0, 8, 2, 0),\n
+         Pos(1, 2), "selectScope", hasSel(0, 8, 2, 0),\n
+         Pos(1, 6), "selectScope", hasSel(1, 6, 1, 10),\n
+         Pos(1, 9), "selectScope", hasSel(1, 6, 1, 10));\n
+\n
+  stTest("goToBracket", "foo(a) {\\n  bar[1, 2];\\n}",\n
+         Pos(0, 0), "goToBracket", at(0, 0),\n
+         Pos(0, 4), "goToBracket", at(0, 5), "goToBracket", at(0, 4),\n
+         Pos(0, 8), "goToBracket", at(2, 0), "goToBracket", at(0, 8),\n
+         Pos(1, 2), "goToBracket", at(2, 0),\n
+         Pos(1, 7), "goToBracket", at(1, 10), "goToBracket", at(1, 6));\n
+\n
+  stTest("swapLine", "1\\n2\\n3---\\n4\\n5",\n
+         "swapLineDown", val("2\\n1\\n3---\\n4\\n5"),\n
+         "swapLineUp", val("1\\n2\\n3---\\n4\\n5"),\n
+         "swapLineUp", val("1\\n2\\n3---\\n4\\n5"),\n
+         Pos(4, 1), "swapLineDown", val("1\\n2\\n3---\\n4\\n5"),\n
+         setSel(0, 1, 0, 1,\n
+                1, 0, 2, 0,\n
+                2, 2, 2, 2),\n
+         "swapLineDown", val("4\\n1\\n2\\n3---\\n5"),\n
+         hasSel(1, 1, 1, 1,\n
+                2, 0, 3, 0,\n
+                3, 2, 3, 2),\n
+         "swapLineUp", val("1\\n2\\n3---\\n4\\n5"),\n
+         hasSel(0, 1, 0, 1,\n
+                1, 0, 2, 0,\n
+                2, 2, 2, 2));\n
+\n
+  stTest("swapLineEmptyBottomSel", "1\\n2\\n3",\n
+         setSel(0, 1, 1, 0),\n
+         "swapLineDown", val("2\\n1\\n3"), hasSel(1, 1, 2, 0),\n
+         "swapLineUp", val("1\\n2\\n3"), hasSel(0, 1, 1, 0),\n
+         "swapLineUp", val("1\\n2\\n3"), hasSel(0, 0, 0, 0));\n
+\n
+  stTest("swapLineUpFromEnd", "a\\nb\\nc",\n
+         Pos(2, 1), "swapLineUp",\n
+         hasSel(1, 1, 1, 1), val("a\\nc\\nb"));\n
+\n
+  stTest("joinLines", "abc\\ndef\\nghi\\njkl",\n
+         "joinLines", val("abc def\\nghi\\njkl"), at(0, 4),\n
+         "undo",\n
+         setSel(0, 2, 1, 1), "joinLines",\n
+         val("abc def ghi\\njkl"), hasSel(0, 2, 0, 8),\n
+         "undo",\n
+         setSel(0, 1, 0, 1,\n
+                1, 1, 1, 1,\n
+                3, 1, 3, 1), "joinLines",\n
+         val("abc def ghi\\njkl"), hasSel(0, 4, 0, 4,\n
+                                         0, 8, 0, 8,\n
+                                         1, 3, 1, 3));\n
+\n
+  stTest("duplicateLine", "abc\\ndef\\nghi",\n
+         Pos(1, 0), "duplicateLine", val("abc\\ndef\\ndef\\nghi"), at(2, 0),\n
+         "undo",\n
+         setSel(0, 1, 0, 1,\n
+                1, 1, 1, 1,\n
+                2, 1, 2, 1), "duplicateLine",\n
+         val("abc\\nabc\\ndef\\ndef\\nghi\\nghi"), hasSel(1, 1, 1, 1,\n
+                                                     3, 1, 3, 1,\n
+                                                     5, 1, 5, 1));\n
+  stTest("duplicateLineSelection", "abcdef",\n
+         setSel(0, 1, 0, 1,\n
+                0, 2, 0, 4,\n
+                0, 5, 0, 5),\n
+         "duplicateLine",\n
+         val("abcdef\\nabcdcdef\\nabcdcdef"), hasSel(2, 1, 2, 1,\n
+                                                   2, 4, 2, 6,\n
+                                                   2, 7, 2, 7));\n
+\n
+  stTest("selectLinesUpward", "123\\n345\\n789\\n012",\n
+         setSel(0, 1, 0, 1,\n
+                1, 1, 1, 3,\n
+                2, 0, 2, 0,\n
+                3, 0, 3, 0),\n
+         "selectLinesUpward",\n
+         hasSel(0, 1, 0, 1,\n
+                0, 3, 0, 3,\n
+                1, 0, 1, 0,\n
+                1, 1, 1, 3,\n
+                2, 0, 2, 0,\n
+                3, 0, 3, 0));\n
+\n
+  stTest("selectLinesDownward", "123\\n345\\n789\\n012",\n
+         setSel(0, 1, 0, 1,\n
+                1, 1, 1, 3,\n
+                2, 0, 2, 0,\n
+                3, 0, 3, 0),\n
+         "selectLinesDownward",\n
+         hasSel(0, 1, 0, 1,\n
+                1, 1, 1, 3,\n
+                2, 0, 2, 0,\n
+                2, 3, 2, 3,\n
+                3, 0, 3, 0));\n
+\n
+  stTest("sortLines", "c\\nb\\na\\nC\\nB\\nA",\n
+         "sortLines", val("A\\nB\\nC\\na\\nb\\nc"),\n
+         "undo",\n
+         setSel(0, 0, 2, 0,\n
+                3, 0, 5, 0),\n
+         "sortLines", val("a\\nb\\nc\\nA\\nB\\nC"),\n
+         hasSel(0, 0, 2, 1,\n
+                3, 0, 5, 1),\n
+         "undo",\n
+         setSel(1, 0, 4, 0), "sortLinesInsensitive", val("c\\na\\nB\\nb\\nC\\nA"));\n
+\n
+  stTest("bookmarks", "abc\\ndef\\nghi\\njkl",\n
+         Pos(0, 1), "toggleBookmark",\n
+         setSel(1, 1, 1, 2), "toggleBookmark",\n
+         setSel(2, 1, 2, 2), "toggleBookmark",\n
+         "nextBookmark", hasSel(0, 1, 0, 1),\n
+         "nextBookmark", hasSel(1, 1, 1, 2),\n
+         "nextBookmark", hasSel(2, 1, 2, 2),\n
+         "prevBookmark", hasSel(1, 1, 1, 2),\n
+         "prevBookmark", hasSel(0, 1, 0, 1),\n
+         "prevBookmark", hasSel(2, 1, 2, 2),\n
+         "prevBookmark", hasSel(1, 1, 1, 2),\n
+         "toggleBookmark",\n
+         "prevBookmark", hasSel(2, 1, 2, 2),\n
+         "prevBookmark", hasSel(0, 1, 0, 1),\n
+         "selectBookmarks", hasSel(0, 1, 0, 1,\n
+                                   2, 1, 2, 2),\n
+         "clearBookmarks",\n
+         Pos(0, 0), "selectBookmarks", at(0, 0));\n
+\n
+  stTest("upAndDowncaseAtCursor", "abc\\ndef  x\\nghI",\n
+         setSel(0, 1, 0, 3,\n
+                1, 1, 1, 1,\n
+                1, 4, 1, 4), "upcaseAtCursor",\n
+         val("aBC\\nDEF  x\\nghI"), hasSel(0, 1, 0, 3,\n
+                                         1, 3, 1, 3,\n
+                                         1, 4, 1, 4),\n
+         "downcaseAtCursor",\n
+         val("abc\\ndef  x\\nghI"), hasSel(0, 1, 0, 3,\n
+                                         1, 3, 1, 3,\n
+                                         1, 4, 1, 4));\n
+\n
+  stTest("mark", "abc\\ndef\\nghi",\n
+         Pos(1, 1), "setSublimeMark",\n
+         Pos(2, 1), "selectToSublimeMark", hasSel(2, 1, 1, 1),\n
+         Pos(0, 1), "swapWithSublimeMark", at(1, 1), "swapWithSublimeMark", at(0, 1),\n
+         "deleteToSublimeMark", val("aef\\nghi"),\n
+         "sublimeYank", val("abc\\ndef\\nghi"), at(1, 1));\n
+\n
+  stTest("findUnder", "foo foobar  a",\n
+         "findUnder", hasSel(0, 4, 0, 7),\n
+         "findUnder", hasSel(0, 0, 0, 3),\n
+         "findUnderPrevious", hasSel(0, 4, 0, 7),\n
+         "findUnderPrevious", hasSel(0, 0, 0, 3),\n
+         Pos(0, 4), "findUnder", hasSel(0, 4, 0, 10),\n
+         Pos(0, 11), "findUnder", hasSel(0, 11, 0, 11));\n
+})();\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>10876</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/test.js.xml
index f7e122d652f214a9680ac9afc8ecd3e7eecc1fb1..341b8b1b66dd21825432cfc2ec0cf1eb109d890f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.33</string> </value>
+            <value> <string>ts21897151.02</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -18,6 +18,33 @@
             <key> <string>content_type</string> </key>
             <value> <string>application/javascript</string> </value>
         </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>74399</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
         <item>
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
@@ -27,7 +54,7 @@ var Pos = CodeMirror.Pos;\n
 CodeMirror.defaults.rtlMoveVisually = true;\n
 \n
 function forEach(arr, f) {\n
-  for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);\n
+  for (var i = 0, e = arr.length; i < e; ++i) f(arr[i], i);\n
 }\n
 \n
 function addDoc(cm, width, height) {\n
@@ -51,6 +78,7 @@ function byClassName(elt, cls) {\n
 }\n
 \n
 var ie_lt8 = /MSIE [1-7]\\b/.test(navigator.userAgent);\n
+var ie_lt9 = /MSIE [1-8]\\b/.test(navigator.userAgent);\n
 var mac = /Mac/.test(navigator.platform);\n
 var phantom = /PhantomJS/.test(navigator.userAgent);\n
 var opera = /Opera\\/\\./.test(navigator.userAgent);\n
@@ -111,7 +139,7 @@ testCM("selection", function(cm) {\n
   is(!cm.somethingSelected());\n
   eq(cm.getSelection(), "");\n
   eqPos(cm.getCursor(true), Pos(1, 0));\n
-  cm.replaceSelection("abc");\n
+  cm.replaceSelection("abc", "around");\n
   eq(cm.getSelection(), "abc");\n
   eq(cm.getValue(), "111111\\nabc222222\\n333333");\n
   cm.replaceSelection("def", "end");\n
@@ -156,16 +184,16 @@ testCM("extendSelection", function(cm) {\n
   eqPos(cm.getCursor("anchor"), Pos(4, 5));\n
   cm.setExtending(false);\n
   cm.extendSelection(Pos(0, 3), Pos(0, 4));\n
-  eqPos(cm.getCursor("head"), Pos(0, 4));\n
-  eqPos(cm.getCursor("anchor"), Pos(0, 3));\n
+  eqPos(cm.getCursor("head"), Pos(0, 3));\n
+  eqPos(cm.getCursor("anchor"), Pos(0, 4));\n
 });\n
 \n
 testCM("lines", function(cm) {\n
   eq(cm.getLine(0), "111111");\n
   eq(cm.getLine(1), "222222");\n
   eq(cm.getLine(-1), null);\n
-  cm.removeLine(1);\n
-  cm.setLine(1, "abc");\n
+  cm.replaceRange("", Pos(1, 0), Pos(2, 0))\n
+  cm.replaceRange("abc", Pos(1, 0), Pos(1));\n
   eq(cm.getValue(), "111111\\nabc");\n
 }, {value: "111111\\n222222\\n333333"});\n
 \n
@@ -288,7 +316,7 @@ testCM("posFromIndex", function(cm) {\n
 });\n
 \n
 testCM("undo", function(cm) {\n
-  cm.setLine(0, "def");\n
+  cm.replaceRange("def", Pos(0, 0), Pos(0));\n
   eq(cm.historySize().undo, 1);\n
   cm.undo();\n
   eq(cm.getValue(), "abc");\n
@@ -318,7 +346,7 @@ testCM("undoDepth", function(cm) {\n
   cm.replaceRange("f", Pos(0));\n
   cm.undo(); cm.undo(); cm.undo();\n
   eq(cm.getValue(), "abcd");\n
-}, {value: "abc", undoDepth: 2});\n
+}, {value: "abc", undoDepth: 4});\n
 \n
 testCM("undoDoesntClearValue", function(cm) {\n
   cm.undo();\n
@@ -375,6 +403,22 @@ testCM("undoSelection", function(cm) {\n
   eqPos(cm.getCursor(false), Pos(0, 2));\n
 }, {value: "abcdefgh\\n"});\n
 \n
+testCM("undoSelectionAsBefore", function(cm) {\n
+  cm.replaceSelection("abc", "around");\n
+  cm.undo();\n
+  cm.redo();\n
+  eq(cm.getSelection(), "abc");\n
+});\n
+\n
+testCM("selectionChangeConfusesHistory", function(cm) {\n
+  cm.replaceSelection("abc", null, "dontmerge");\n
+  cm.operation(function() {\n
+    cm.setCursor(Pos(0, 0));\n
+    cm.replaceSelection("abc", null, "dontmerge");\n
+  });\n
+  eq(cm.historySize().undo, 2);\n
+});\n
+\n
 testCM("markTextSingleLine", function(cm) {\n
   forEach([{a: 0, b: 1, c: "", f: 2, t: 5},\n
            {a: 0, b: 4, c: "", f: 0, t: 2},\n
@@ -523,6 +567,17 @@ testCM("deleteSpanCollapsedInclusiveLeft", function(cm) {\n
   cm.replaceRange("", from, to);\n
 }, {value: "abc\\nX\\ndef"});\n
 \n
+testCM("markTextCSS", function(cm) {\n
+  function present() {\n
+    var spans = cm.display.lineDiv.getElementsByTagName("span");\n
+    for (var i = 0; i < spans.length; i++)\n
+      if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true;\n
+  }\n
+  var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"});\n
+  m.clear();\n
+  is(!present());\n
+}, {value: "abcdefgh"});\n
+\n
 testCM("bookmark", function(cm) {\n
   function p(v) { return v && Pos(v[0], v[1]); }\n
   forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},\n
@@ -565,10 +620,14 @@ testCM("bookmarkCursor", function(cm) {\n
   cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("鈫�")});\n
   var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)),\n
       new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0));\n
-  is(new01.left == pos01.left && new01.top == pos01.top, "at left, middle of line");\n
-  is(new11.left > pos11.left && new11.top == pos11.top, "at right, middle of line");\n
-  is(new20.left == pos20.left && new20.top == pos20.top, "at left, empty line");\n
-  is(new30.left > pos30.left && new30.top == pos30.top, "at right, empty line");\n
+  near(new01.left, pos01.left, 1);\n
+  near(new01.top, pos01.top, 1);\n
+  is(new11.left > pos11.left, "at right, middle of line");\n
+  near(new11.top == pos11.top, 1);\n
+  near(new20.left, pos20.left, 1);\n
+  near(new20.top, pos20.top, 1);\n
+  is(new30.left > pos30.left, "at right, empty line");\n
+  near(new30.top, pos30, 1);\n
   cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("鈫�")});\n
   is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");\n
 }, {value: "foo\\nbar\\n\\n\\nx\\ny"});\n
@@ -585,10 +644,10 @@ testCM("multiBookmarkCursor", function(cm) {\n
   }\n
   var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left;\n
   add(true);\n
-  is(Math.abs(base1 - cm.cursorCoords(Pos(0, 1)).left) < .1);\n
+  near(base1, cm.cursorCoords(Pos(0, 1)).left, 1);\n
   while (m = ms.pop()) m.clear();\n
   add(false);\n
-  is(Math.abs(base4 - cm.cursorCoords(Pos(0, 1)).left) < .1);\n
+  near(base4, cm.cursorCoords(Pos(0, 1)).left, 1);\n
 }, {value: "abcdefg"});\n
 \n
 testCM("getAllMarks", function(cm) {\n
@@ -628,20 +687,40 @@ testCM("scrollSnap", function(cm) {\n
 testCM("scrollIntoView", function(cm) {\n
   if (phantom) return;\n
   var outer = cm.getWrapperElement().getBoundingClientRect();\n
-  function test(line, ch) {\n
+  function test(line, ch, msg) {\n
     var pos = Pos(line, ch);\n
     cm.scrollIntoView(pos);\n
     var box = cm.charCoords(pos, "window");\n
-    is(box.left >= outer.left && box.right <= outer.right &&\n
-       box.top >= outer.top && box.bottom <= outer.bottom);\n
+    is(box.left >= outer.left, msg + " (left)");\n
+    is(box.right <= outer.right, msg + " (right)");\n
+    is(box.top >= outer.top, msg + " (top)");\n
+    is(box.bottom <= outer.bottom, msg + " (bottom)");\n
   }\n
   addDoc(cm, 200, 200);\n
-  test(199, 199);\n
-  test(0, 0);\n
-  test(100, 100);\n
-  test(199, 0);\n
-  test(0, 199);\n
-  test(100, 100);\n
+  test(199, 199, "bottom right");\n
+  test(0, 0, "top left");\n
+  test(100, 100, "center");\n
+  test(199, 0, "bottom left");\n
+  test(0, 199, "top right");\n
+  test(100, 100, "center again");\n
+});\n
+\n
+testCM("scrollBackAndForth", function(cm) {\n
+  addDoc(cm, 1, 200);\n
+  cm.operation(function() {\n
+    cm.scrollIntoView(Pos(199, 0));\n
+    cm.scrollIntoView(Pos(4, 0));\n
+  });\n
+  is(cm.getScrollInfo().top > 0);\n
+});\n
+\n
+testCM("selectAllNoScroll", function(cm) {\n
+  addDoc(cm, 1, 200);\n
+  cm.execCommand("selectAll");\n
+  eq(cm.getScrollInfo().top, 0);\n
+  cm.setCursor(199);\n
+  cm.execCommand("selectAll");\n
+  is(cm.getScrollInfo().top > 0);\n
 });\n
 \n
 testCM("selectionPos", function(cm) {\n
@@ -681,8 +760,8 @@ testCM("selectionPos", function(cm) {\n
 \n
 testCM("restoreHistory", function(cm) {\n
   cm.setValue("abc\\ndef");\n
-  cm.setLine(1, "hello");\n
-  cm.setLine(0, "goop");\n
+  cm.replaceRange("hello", Pos(1, 0), Pos(1));\n
+  cm.replaceRange("goop", Pos(0, 0), Pos(0));\n
   cm.undo();\n
   var storedVal = cm.getValue(), storedHist = cm.getHistory();\n
   if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist));\n
@@ -747,11 +826,11 @@ testCM("collapsedLines", function(cm) {\n
   cm.setCursor(Pos(3, 0));\n
   CodeMirror.commands.goLineDown(cm);\n
   eqPos(cm.getCursor(), Pos(5, 0));\n
-  cm.setLine(3, "abcdefg");\n
+  cm.replaceRange("abcdefg", Pos(3, 0), Pos(3));\n
   cm.setCursor(Pos(3, 6));\n
   CodeMirror.commands.goLineDown(cm);\n
   eqPos(cm.getCursor(), Pos(5, 4));\n
-  cm.setLine(3, "ab");\n
+  cm.replaceRange("ab", Pos(3, 0), Pos(3));\n
   cm.setCursor(Pos(3, 2));\n
   CodeMirror.commands.goLineDown(cm);\n
   eqPos(cm.getCursor(), Pos(5, 2));\n
@@ -774,6 +853,31 @@ testCM("collapsedRangeCoordsChar", function(cm) {\n
   eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));\n
 }, {value: "123456\\nabcdef\\nghijkl\\nmnopqr\\n"});\n
 \n
+testCM("collapsedRangeBetweenLinesSelected", function(cm) {\n
+  var widget = document.createElement("span");\n
+  widget.textContent = "\\u2194";\n
+  cm.markText(Pos(0, 3), Pos(1, 0), {replacedWith: widget});\n
+  cm.setSelection(Pos(0, 3), Pos(1, 0));\n
+  var selElts = byClassName(cm.getWrapperElement(), "CodeMirror-selected");\n
+  for (var i = 0, w = 0; i < selElts.length; i++)\n
+    w += selElts[i].offsetWidth;\n
+  is(w > 0);\n
+}, {value: "one\\ntwo"});\n
+\n
+testCM("randomCollapsedRanges", function(cm) {\n
+  addDoc(cm, 20, 500);\n
+  cm.operation(function() {\n
+    for (var i = 0; i < 200; i++) {\n
+      var start = Pos(Math.floor(Math.random() * 500), Math.floor(Math.random() * 20));\n
+      if (i % 4)\n
+        try { cm.markText(start, Pos(start.line + 2, 1), {collapsed: true}); }\n
+        catch(e) { if (!/overlapping/.test(String(e))) throw e; }\n
+      else\n
+        cm.markText(start, Pos(start.line, start.ch + 4), {"className": "foo"});\n
+    }\n
+  });\n
+});\n
+\n
 testCM("hiddenLinesAutoUnfold", function(cm) {\n
   var range = foldLines(cm, 1, 3, true), cleared = 0;\n
   CodeMirror.on(range, "clear", function() {cleared++;});\n
@@ -912,6 +1016,15 @@ testCM("nestedFoldOnSide", function(cm) {\n
   is(caught && /overlap/i.test(caught.message));\n
 }, {value: "ab\\ncd\\ef"});\n
 \n
+testCM("editInFold", function(cm) {\n
+  addDoc(cm, 4, 6);\n
+  var m = cm.markText(Pos(1, 2), Pos(3, 2), {collapsed: true});\n
+  cm.replaceRange("", Pos(0, 0), Pos(1, 3));\n
+  cm.replaceRange("", Pos(2, 1), Pos(3, 3));\n
+  cm.replaceRange("a\\nb\\nc\\nd", Pos(0, 1), Pos(1, 0));\n
+  cm.cursorCoords(Pos(0, 0));\n
+});\n
+\n
 testCM("wrappingInlineWidget", function(cm) {\n
   cm.setSize("11em");\n
   var w = document.createElement("span");\n
@@ -928,6 +1041,7 @@ testCM("wrappingInlineWidget", function(cm) {\n
   eq(curR.bottom, cur1.bottom);\n
   cm.replaceRange("", Pos(0, 9), Pos(0));\n
   curR = cm.cursorCoords(Pos(0, 9));\n
+  if (phantom) return;\n
   eq(curR.top, cur1.top);\n
   eq(curR.bottom, cur1.bottom);\n
 }, {value: "1 2 3 xxx 4", lineWrapping: true});\n
@@ -1072,15 +1186,15 @@ testCM("verticalScroll", function(cm) {\n
   cm.setSize(100, 200);\n
   cm.setValue("foo\\nbar\\nbaz\\n");\n
   var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth;\n
-  cm.setLine(0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah");\n
+  cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0));\n
   is(sc.scrollWidth > baseWidth, "scrollbar present");\n
-  cm.setLine(0, "foo");\n
+  cm.replaceRange("foo", Pos(0, 0), Pos(0));\n
   if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone");\n
-  cm.setLine(0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah");\n
-  cm.setLine(1, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh");\n
+  cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0));\n
+  cm.replaceRange("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh", Pos(1, 0), Pos(1));\n
   is(sc.scrollWidth > baseWidth, "present again");\n
   var curWidth = sc.scrollWidth;\n
-  cm.setLine(0, "foo");\n
+  cm.replaceRange("foo", Pos(0, 0), Pos(0));\n
   is(sc.scrollWidth < curWidth, "scrollbar smaller");\n
   is(sc.scrollWidth > baseWidth, "but still present");\n
 });\n
@@ -1253,23 +1367,26 @@ testCM("rtlMovement", function(cm) {\n
            "<img src=\\"/讘讚讬拽讛3.jpg\\">"], function(line) {\n
     var inv = line.charAt(0) == "禺";\n
     cm.setValue(line + "\\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");\n
-    var cursor = byClassName(cm.getWrapperElement(), "CodeMirror-cursor")[0];\n
+    var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0];\n
+    var cursor = cursors.firstChild;\n
     var prevX = cursor.offsetLeft, prevY = cursor.offsetTop;\n
     for (var i = 0; i <= line.length; ++i) {\n
       cm.execCommand("goCharRight");\n
+      cursor = cursors.firstChild;\n
       if (i == line.length) is(cursor.offsetTop > prevY, "next line");\n
       else is(cursor.offsetLeft > prevX, "moved right");\n
       prevX = cursor.offsetLeft; prevY = cursor.offsetTop;\n
     }\n
     cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd");\n
-    prevX = cursor.offsetLeft;\n
+    prevX = cursors.firstChild.offsetLeft;\n
     for (var i = 0; i < line.length; ++i) {\n
       cm.execCommand("goCharLeft");\n
+      cursor = cursors.firstChild;\n
       is(cursor.offsetLeft < prevX, "moved left");\n
       prevX = cursor.offsetLeft;\n
     }\n
   });\n
-});\n
+}, null, ie_lt9);\n
 \n
 // Verify that updating a line clears its bidi ordering\n
 testCM("bidiUpdate", function(cm) {\n
@@ -1280,7 +1397,7 @@ testCM("bidiUpdate", function(cm) {\n
 }, {value: "abcd\\n"});\n
 \n
 testCM("movebyTextUnit", function(cm) {\n
-  cm.setValue("讘职旨专值讗砖执\\n虂e虂e虂e\\n");\n
+  cm.setValue("讘职旨专值讗砖执\\ne虂e虂e虂虂\\n");\n
   cm.execCommand("goLineEnd");\n
   for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight");\n
   eqPos(cm.getCursor(), Pos(0, 0));\n
@@ -1288,10 +1405,9 @@ testCM("movebyTextUnit", function(cm) {\n
   eqPos(cm.getCursor(), Pos(1, 0));\n
   cm.execCommand("goCharRight");\n
   cm.execCommand("goCharRight");\n
-  eqPos(cm.getCursor(), Pos(1, 3));\n
-  cm.execCommand("goCharRight");\n
+  eqPos(cm.getCursor(), Pos(1, 4));\n
   cm.execCommand("goCharRight");\n
-  eqPos(cm.getCursor(), Pos(1, 6));\n
+  eqPos(cm.getCursor(), Pos(1, 7));\n
 });\n
 \n
 testCM("lineChangeEvents", function(cm) {\n
@@ -1352,6 +1468,91 @@ testCM("lineWidgetFocus", function(cm) {\n
   }\n
 });\n
 \n
+testCM("lineWidgetCautiousRedraw", function(cm) {\n
+  var node = document.createElement("div");\n
+  node.innerHTML = "hahah";\n
+  var w = cm.addLineWidget(0, node);\n
+  var redrawn = false;\n
+  w.on("redraw", function() { redrawn = true; });\n
+  cm.replaceSelection("0");\n
+  is(!redrawn);\n
+}, {value: "123\\n456"});\n
+\n
+\n
+var knownScrollbarWidth;\n
+function scrollbarWidth(measure) {\n
+  if (knownScrollbarWidth != null) return knownScrollbarWidth;\n
+  var div = document.createElement(\'div\');\n
+  div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll";\n
+  document.body.appendChild(div);\n
+  knownScrollbarWidth = div.offsetHeight - div.clientHeight;\n
+  document.body.removeChild(div);\n
+  return knownScrollbarWidth || 0;\n
+}\n
+\n
+testCM("lineWidgetChanged", function(cm) {\n
+  addDoc(cm, 2, 300);\n
+  var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2;\n
+  cm.setOption(\'lineNumbers\', true);\n
+  cm.setSize(600, cm.defaultTextHeight() * 50);\n
+  cm.scrollTo(null, cm.heightAtLine(125, "local"));\n
+\n
+  var expectedWidgetHeight = 60;\n
+  var expectedLinesInWidget = 3;\n
+  function w() {\n
+    var node = document.createElement("div");\n
+    // we use these children with just under half width of the line to check measurements are made with correct width\n
+    // when placed in the measure div.\n
+    // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test.\n
+    // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test.\n
+    // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right.\n
+    // It may also be worthwhile to check this for non-coverGutter widgets.\n
+    // Visually:\n
+    // Good:\n
+    // | ------------- display width ------------- |\n
+    // | ------- widget-width when measured ------ |\n
+    // | | -- under-half -- | | -- under-half -- | | \n
+    // | | --- over-half --- |                     |\n
+    // | | --- over-half --- |                     |\n
+    // Height: measured as 3 lines, same as it will be when actually displayed\n
+\n
+    // Bad (too narrow):\n
+    // | ------------- display width ------------- |\n
+    // | ------ widget-width when measured ----- |  < -- uh oh\n
+    // | | -- under-half -- |                    |\n
+    // | | -- under-half -- |                    |  < -- when measured, shoved to next line\n
+    // | | --- over-half --- |                   |\n
+    // | | --- over-half --- |                   |\n
+    // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines!\n
+\n
+    // Bad (too wide):\n
+    // | ------------- display width ------------- |\n
+    // | -------- widget-width when measured ------- | < -- uh oh\n
+    // | | -- under-half -- | | -- under-half -- |   | \n
+    // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line\n
+    // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines!\n
+\n
+    var barelyUnderHalfWidthHtml = \'<div style="display: inline-block; height: 1px; width: \'+(285 - halfScrollbarWidth)+\'px;"></div>\';\n
+    var barelyOverHalfWidthHtml = \'<div style="display: inline-block; height: 1px; width: \'+(305 - halfScrollbarWidth)+\'px;"></div>\';\n
+    node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml);\n
+    node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;";\n
+    return node;\n
+  }\n
+  var info0 = cm.getScrollInfo();\n
+  var w0 = cm.addLineWidget(0, w(), { coverGutter: true });\n
+  var w150 = cm.addLineWidget(150, w(), { coverGutter: true });\n
+  var w300 = cm.addLineWidget(300, w(), { coverGutter: true });\n
+  var info1 = cm.getScrollInfo();\n
+  eq(info0.height + (3 * expectedWidgetHeight), info1.height);\n
+  eq(info0.top + expectedWidgetHeight, info1.top);\n
+  expectedWidgetHeight = 12;\n
+  w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px";\n
+  w0.changed(); w150.changed(); w300.changed();\n
+  var info2 = cm.getScrollInfo();\n
+  eq(info0.height + (3 * expectedWidgetHeight), info2.height);\n
+  eq(info0.top + expectedWidgetHeight, info2.top);\n
+});\n
+\n
 testCM("getLineNumber", function(cm) {\n
   addDoc(cm, 2, 20);\n
   var h1 = cm.getLineHandle(1);\n
@@ -1363,9 +1564,10 @@ testCM("getLineNumber", function(cm) {\n
 });\n
 \n
 testCM("jumpTheGap", function(cm) {\n
+  if (phantom) return;\n
   var longLine = "abcdef ghiklmnop qrstuvw xyz ";\n
   longLine += longLine; longLine += longLine; longLine += longLine;\n
-  cm.setLine(2, longLine);\n
+  cm.replaceRange(longLine, Pos(2, 0), Pos(2));\n
   cm.setSize("200px", null);\n
   cm.getWrapperElement().style.lineHeight = 2;\n
   cm.refresh();\n
@@ -1393,33 +1595,48 @@ testCM("jumpTheGap", function(cm) {\n
 }, {lineWrapping: true, value: "abc\\ndef\\nghi\\njkl\\n"});\n
 \n
 testCM("addLineClass", function(cm) {\n
-  function cls(line, text, bg, wrap) {\n
+  function cls(line, text, bg, wrap, gutter) {\n
     var i = cm.lineInfo(line);\n
     eq(i.textClass, text);\n
     eq(i.bgClass, bg);\n
     eq(i.wrapClass, wrap);\n
+    if (typeof i.handle.gutterClass !== \'undefined\') {\n
+        eq(i.handle.gutterClass, gutter);\n
+    }\n
   }\n
   cm.addLineClass(0, "text", "foo");\n
   cm.addLineClass(0, "text", "bar");\n
   cm.addLineClass(1, "background", "baz");\n
   cm.addLineClass(1, "wrap", "foo");\n
-  cls(0, "foo bar", null, null);\n
-  cls(1, null, "baz", "foo");\n
+  cm.addLineClass(1, "gutter", "gutter-class");\n
+  cls(0, "foo bar", null, null, null);\n
+  cls(1, null, "baz", "foo", "gutter-class");\n
   var lines = cm.display.lineDiv;\n
   eq(byClassName(lines, "foo").length, 2);\n
   eq(byClassName(lines, "bar").length, 1);\n
   eq(byClassName(lines, "baz").length, 1);\n
+  eq(byClassName(lines, "gutter-class").length, 1);\n
   cm.removeLineClass(0, "text", "foo");\n
-  cls(0, "bar", null, null);\n
+  cls(0, "bar", null, null, null);\n
   cm.removeLineClass(0, "text", "foo");\n
-  cls(0, "bar", null, null);\n
+  cls(0, "bar", null, null, null);\n
   cm.removeLineClass(0, "text", "bar");\n
   cls(0, null, null, null);\n
+\n
   cm.addLineClass(1, "wrap", "quux");\n
-  cls(1, null, "baz", "foo quux");\n
+  cls(1, null, "baz", "foo quux", "gutter-class");\n
   cm.removeLineClass(1, "wrap");\n
-  cls(1, null, "baz", null);\n
-}, {value: "hohoho\\n"});\n
+  cls(1, null, "baz", null, "gutter-class");\n
+  cm.removeLineClass(1, "gutter", "gutter-class");\n
+  eq(byClassName(lines, "gutter-class").length, 0);\n
+  cls(1, null, "baz", null, null);\n
+\n
+  cm.addLineClass(1, "gutter", "gutter-class");\n
+  cls(1, null, "baz", null, "gutter-class");\n
+  cm.removeLineClass(1, "gutter", "gutter-class");\n
+  cls(1, null, "baz", null, null);\n
+\n
+}, {value: "hohoho\\n", lineNumbers: true});\n
 \n
 testCM("atomicMarker", function(cm) {\n
   addDoc(cm, 10, 10);\n
@@ -1469,6 +1686,29 @@ testCM("atomicMarker", function(cm) {\n
   eq(cm.getValue().length, 53, "del chunk");\n
 });\n
 \n
+testCM("selectionBias", function(cm) {\n
+  cm.markText(Pos(0, 1), Pos(0, 3), {atomic: true});\n
+  cm.setCursor(Pos(0, 2));\n
+  eqPos(cm.getCursor(), Pos(0, 3));\n
+  cm.setCursor(Pos(0, 2));\n
+  eqPos(cm.getCursor(), Pos(0, 1));\n
+  cm.setCursor(Pos(0, 2), null, {bias: -1});\n
+  eqPos(cm.getCursor(), Pos(0, 1));\n
+  cm.setCursor(Pos(0, 4));\n
+  cm.setCursor(Pos(0, 2), null, {bias: 1});\n
+  eqPos(cm.getCursor(), Pos(0, 3));\n
+}, {value: "12345"});\n
+\n
+testCM("selectionHomeEnd", function(cm) {\n
+  cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true});\n
+  cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true});\n
+  cm.setCursor(Pos(1, 2));\n
+  cm.execCommand("goLineStart");\n
+  eqPos(cm.getCursor(), Pos(1, 1));\n
+  cm.execCommand("goLineEnd");\n
+  eqPos(cm.getCursor(), Pos(1, 3));\n
+}, {value: "ab\\ncdef\\ngh"});\n
+\n
 testCM("readOnlyMarker", function(cm) {\n
   function mark(ll, cl, lr, cr, at) {\n
     return cm.markText(Pos(ll, cl), Pos(lr, cr),\n
@@ -1480,14 +1720,14 @@ testCM("readOnlyMarker", function(cm) {\n
   eqPos(cm.getCursor(), Pos(0, 2));\n
   eq(cm.getLine(0), "abcde");\n
   cm.execCommand("selectAll");\n
-  cm.replaceSelection("oops");\n
+  cm.replaceSelection("oops", "around");\n
   eq(cm.getValue(), "oopsbcd");\n
   cm.undo();\n
   eqPos(m.find().from, Pos(0, 1));\n
   eqPos(m.find().to, Pos(0, 4));\n
   m.clear();\n
   cm.setCursor(Pos(0, 2));\n
-  cm.replaceSelection("hi");\n
+  cm.replaceSelection("hi", "around");\n
   eq(cm.getLine(0), "abhicde");\n
   eqPos(cm.getCursor(), Pos(0, 4));\n
   m = mark(0, 2, 2, 2, true);\n
@@ -1499,19 +1739,19 @@ testCM("readOnlyMarker", function(cm) {\n
   cm.execCommand("goCharLeft");\n
   eqPos(cm.getCursor(), Pos(0, 2));\n
   cm.setSelection(Pos(0, 1), Pos(0, 3));\n
-  cm.replaceSelection("xx");\n
+  cm.replaceSelection("xx", "around");\n
   eqPos(cm.getCursor(), Pos(0, 3));\n
   eq(cm.getLine(0), "axxhicde");\n
 }, {value: "abcde\\nfghij\\nklmno\\n"});\n
 \n
 testCM("dirtyBit", function(cm) {\n
   eq(cm.isClean(), true);\n
-  cm.replaceSelection("boo");\n
+  cm.replaceSelection("boo", null, "test");\n
   eq(cm.isClean(), false);\n
   cm.undo();\n
   eq(cm.isClean(), true);\n
-  cm.replaceSelection("boo");\n
-  cm.replaceSelection("baz");\n
+  cm.replaceSelection("boo", null, "test");\n
+  cm.replaceSelection("baz", null, "test");\n
   cm.undo();\n
   eq(cm.isClean(), false);\n
   cm.markClean();\n
@@ -1523,15 +1763,15 @@ testCM("dirtyBit", function(cm) {\n
 });\n
 \n
 testCM("changeGeneration", function(cm) {\n
-  cm.replaceSelection("x", null, "+insert");\n
+  cm.replaceSelection("x");\n
   var softGen = cm.changeGeneration();\n
-  cm.replaceSelection("x", null, "+insert");\n
+  cm.replaceSelection("x");\n
   cm.undo();\n
   eq(cm.getValue(), "");\n
   is(!cm.isClean(softGen));\n
-  cm.replaceSelection("x", null, "+insert");\n
+  cm.replaceSelection("x");\n
   var hardGen = cm.changeGeneration(true);\n
-  cm.replaceSelection("x", null, "+insert");\n
+  cm.replaceSelection("x");\n
   cm.undo();\n
   eq(cm.getValue(), "x");\n
   is(cm.isClean(hardGen));\n
@@ -1609,8 +1849,8 @@ testCM("beforeChange", function(cm) {\n
 }, {value: "abcdefghijk"});\n
 \n
 testCM("beforeChangeUndo", function(cm) {\n
-  cm.setLine(0, "hi");\n
-  cm.setLine(0, "bye");\n
+  cm.replaceRange("hi", Pos(0, 0), Pos(0));\n
+  cm.replaceRange("bye", Pos(0, 0), Pos(0));\n
   eq(cm.historySize().undo, 2);\n
   cm.on("beforeChange", function(cm, change) {\n
     is(!change.update);\n
@@ -1627,9 +1867,9 @@ testCM("beforeSelectionChange", function(cm) {\n
     if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1);\n
     return pos;\n
   }\n
-  cm.on("beforeSelectionChange", function(cm, sel) {\n
-    sel.head = notAtEnd(cm, sel.head);\n
-    sel.anchor = notAtEnd(cm, sel.anchor);\n
+  cm.on("beforeSelectionChange", function(cm, obj) {\n
+    obj.update([{anchor: notAtEnd(cm, obj.ranges[0].anchor),\n
+                 head: notAtEnd(cm, obj.ranges[0].head)}]);\n
   });\n
 \n
   addDoc(cm, 10, 10);\n
@@ -1643,9 +1883,9 @@ testCM("beforeSelectionChange", function(cm) {\n
 testCM("change_removedText", function(cm) {\n
   cm.setValue("abc\\ndef");\n
 \n
-  var removedText;\n
+  var removedText = [];\n
   cm.on("change", function(cm, change) {\n
-    removedText = [change.removed, change.next && change.next.removed];\n
+    removedText.push(change.removed);\n
   });\n
 \n
   cm.operation(function() {\n
@@ -1653,14 +1893,19 @@ testCM("change_removedText", function(cm) {\n
     cm.replaceRange("123", Pos(0,0));\n
   });\n
 \n
+  eq(removedText.length, 2);\n
   eq(removedText[0].join("\\n"), "abc\\nd");\n
   eq(removedText[1].join("\\n"), "");\n
 \n
+  var removedText = [];\n
   cm.undo();\n
+  eq(removedText.length, 2);\n
   eq(removedText[0].join("\\n"), "123");\n
   eq(removedText[1].join("\\n"), "xyz");\n
 \n
+  var removedText = [];\n
   cm.redo();\n
+  eq(removedText.length, 2);\n
   eq(removedText[0].join("\\n"), "abc\\nd");\n
   eq(removedText[1].join("\\n"), "");\n
 });\n
@@ -1676,11 +1921,11 @@ testCM("lineStyleFromMode", function(cm) {\n
   });\n
   cm.setOption("mode", "test_mode");\n
   var bracketElts = byClassName(cm.getWrapperElement(), "brackets");\n
-  eq(bracketElts.length, 1);\n
+  eq(bracketElts.length, 1, "brackets count");\n
   eq(bracketElts[0].nodeName, "PRE");\n
   is(!/brackets.*brackets/.test(bracketElts[0].className));\n
   var parenElts = byClassName(cm.getWrapperElement(), "parens");\n
-  eq(parenElts.length, 1);\n
+  eq(parenElts.length, 1, "parens count");\n
   eq(parenElts[0].nodeName, "DIV");\n
   is(!/parens.*parens/.test(parenElts[0].className));\n
   eq(parenElts[0].parentElement.nodeName, "DIV");\n
@@ -1692,6 +1937,20 @@ testCM("lineStyleFromMode", function(cm) {\n
   is(/^\\s*cm-span\\s*$/.test(spanElts[0].className));\n
 }, {value: "line1: [br] [br]\\nline2: (par) (par)\\nline3: <tag> <tag>"});\n
 \n
+testCM("lineStyleFromBlankLine", function(cm) {\n
+  CodeMirror.defineMode("lineStyleFromBlankLine_mode", function() {\n
+    return {token: function(stream) { stream.skipToEnd(); return "comment"; },\n
+            blankLine: function() { return "line-blank"; }};\n
+  });\n
+  cm.setOption("mode", "lineStyleFromBlankLine_mode");\n
+  var blankElts = byClassName(cm.getWrapperElement(), "blank");\n
+  eq(blankElts.length, 1);\n
+  eq(blankElts[0].nodeName, "PRE");\n
+  cm.replaceRange("x", Pos(1, 0));\n
+  blankElts = byClassName(cm.getWrapperElement(), "blank");\n
+  eq(blankElts.length, 0);\n
+}, {value: "foo\\n\\nbar"});\n
+\n
 CodeMirror.registerHelper("xxx", "a", "A");\n
 CodeMirror.registerHelper("xxx", "b", "B");\n
 CodeMirror.defineMode("yyy", function() {\n
@@ -1710,22 +1969,191 @@ testCM("helpers", function(cm) {\n
   cm.setOption("mode", "javascript");\n
   eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "");\n
 });\n
+\n
+testCM("selectionHistory", function(cm) {\n
+  for (var i = 0; i < 3; i++) {\n
+    cm.setExtending(true);\n
+    cm.execCommand("goCharRight");\n
+    cm.setExtending(false);\n
+    cm.execCommand("goCharRight");\n
+    cm.execCommand("goCharRight");\n
+  }\n
+  cm.execCommand("undoSelection");\n
+  eq(cm.getSelection(), "c");\n
+  cm.execCommand("undoSelection");\n
+  eq(cm.getSelection(), "");\n
+  eqPos(cm.getCursor(), Pos(0, 4));\n
+  cm.execCommand("undoSelection");\n
+  eq(cm.getSelection(), "b");\n
+  cm.execCommand("redoSelection");\n
+  eq(cm.getSelection(), "");\n
+  eqPos(cm.getCursor(), Pos(0, 4));\n
+  cm.execCommand("redoSelection");\n
+  eq(cm.getSelection(), "c");\n
+  cm.execCommand("redoSelection");\n
+  eq(cm.getSelection(), "");\n
+  eqPos(cm.getCursor(), Pos(0, 6));\n
+}, {value: "a b c d"});\n
+\n
+testCM("selectionChangeReducesRedo", function(cm) {\n
+  cm.replaceSelection("X");\n
+  cm.execCommand("goCharRight");\n
+  cm.undoSelection();\n
+  cm.execCommand("selectAll");\n
+  cm.undoSelection();\n
+  eq(cm.getValue(), "Xabc");\n
+  eqPos(cm.getCursor(), Pos(0, 1));\n
+  cm.undoSelection();\n
+  eq(cm.getValue(), "abc");\n
+}, {value: "abc"});\n
+\n
+testCM("selectionHistoryNonOverlapping", function(cm) {\n
+  cm.setSelection(Pos(0, 0), Pos(0, 1));\n
+  cm.setSelection(Pos(0, 2), Pos(0, 3));\n
+  cm.execCommand("undoSelection");\n
+  eqPos(cm.getCursor("anchor"), Pos(0, 0));\n
+  eqPos(cm.getCursor("head"), Pos(0, 1));\n
+}, {value: "1234"});\n
+\n
+testCM("cursorMotionSplitsHistory", function(cm) {\n
+  cm.replaceSelection("a");\n
+  cm.execCommand("goCharRight");\n
+  cm.replaceSelection("b");\n
+  cm.replaceSelection("c");\n
+  cm.undo();\n
+  eq(cm.getValue(), "a1234");\n
+  eqPos(cm.getCursor(), Pos(0, 2));\n
+  cm.undo();\n
+  eq(cm.getValue(), "1234");\n
+  eqPos(cm.getCursor(), Pos(0, 0));\n
+}, {value: "1234"});\n
+\n
+testCM("selChangeInOperationDoesNotSplit", function(cm) {\n
+  for (var i = 0; i < 4; i++) {\n
+    cm.operation(function() {\n
+      cm.replaceSelection("x");\n
+      cm.setCursor(Pos(0, cm.getCursor().ch - 1));\n
+    });\n
+  }\n
+  eqPos(cm.getCursor(), Pos(0, 0));\n
+  eq(cm.getValue(), "xxxxa");\n
+  cm.undo();\n
+  eq(cm.getValue(), "a");\n
+}, {value: "a"});\n
+\n
+testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) {\n
+  cm.replaceSelection("U", null, "foo");\n
+  cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "foo"});\n
+  cm.undoSelection();\n
+  eq(cm.getValue(), "a");\n
+  cm.replaceSelection("V", null, "foo");\n
+  cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "bar"});\n
+  cm.undoSelection();\n
+  eq(cm.getValue(), "Va");\n
+}, {value: "a"});\n
+\n
+testCM("getTokenAt", function(cm) {\n
+  var tokPlus = cm.getTokenAt(Pos(0, 2));\n
+  eq(tokPlus.type, "operator");\n
+  eq(tokPlus.string, "+");\n
+  var toks = cm.getLineTokens(0);\n
+  eq(toks.length, 3);\n
+  forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) {\n
+    eq(toks[i].type, expect[0]);\n
+    eq(toks[i].string, expect[1]);\n
+  });\n
+}, {value: "1+2", mode: "javascript"});\n
+\n
+testCM("getTokenTypeAt", function(cm) {\n
+  eq(cm.getTokenTypeAt(Pos(0, 0)), "number");\n
+  eq(cm.getTokenTypeAt(Pos(0, 6)), "string");\n
+  cm.addOverlay({\n
+    token: function(stream) {\n
+      if (stream.match("foo")) return "foo";\n
+      else stream.next();\n
+    }\n
+  });\n
+  eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1);\n
+  eq(cm.getTokenTypeAt(Pos(0, 6)), "string");\n
+}, {value: "1 + \'foo\'", mode: "javascript"});\n
+\n
+testCM("resizeLineWidget", function(cm) {\n
+  addDoc(cm, 200, 3);\n
+  var widget = document.createElement("pre");\n
+  widget.innerHTML = "imwidget";\n
+  widget.style.background = "yellow";\n
+  cm.addLineWidget(1, widget, {noHScroll: true});\n
+  cm.setSize(40);\n
+  is(widget.parentNode.offsetWidth < 42);\n
+});\n
+\n
+testCM("combinedOperations", function(cm) {\n
+  var place = document.getElementById("testground");\n
+  var other = CodeMirror(place, {value: "123"});\n
+  try {\n
+    cm.operation(function() {\n
+      cm.addLineClass(0, "wrap", "foo");\n
+      other.addLineClass(0, "wrap", "foo");\n
+    });\n
+    eq(byClassName(cm.getWrapperElement(), "foo").length, 1);\n
+    eq(byClassName(other.getWrapperElement(), "foo").length, 1);\n
+    cm.operation(function() {\n
+      cm.removeLineClass(0, "wrap", "foo");\n
+      other.removeLineClass(0, "wrap", "foo");\n
+    });\n
+    eq(byClassName(cm.getWrapperElement(), "foo").length, 0);\n
+    eq(byClassName(other.getWrapperElement(), "foo").length, 0);\n
+  } finally {\n
+    place.removeChild(other.getWrapperElement());\n
+  }\n
+}, {value: "abc"});\n
+\n
+testCM("eventOrder", function(cm) {\n
+  var seen = [];\n
+  cm.on("change", function() {\n
+    if (!seen.length) cm.replaceSelection(".");\n
+    seen.push("change");\n
+  });\n
+  cm.on("cursorActivity", function() {\n
+    cm.replaceSelection("!");\n
+    seen.push("activity");\n
+  });\n
+  cm.replaceSelection("/");\n
+  eq(seen.join(","), "change,change,activity,change");\n
+});\n
+\n
+test("core_rmClass", function() {\n
+  var node = document.createElement("div");\n
+  node.className = "foo-bar baz-quux yadda";\n
+  CodeMirror.rmClass(node, "quux");\n
+  eq(node.className, "foo-bar baz-quux yadda");\n
+  CodeMirror.rmClass(node, "baz-quux");\n
+  eq(node.className, "foo-bar yadda");\n
+  CodeMirror.rmClass(node, "yadda");\n
+  eq(node.className, "foo-bar");\n
+  CodeMirror.rmClass(node, "foo-bar");\n
+  eq(node.className, "");\n
+  node.className = " foo ";\n
+  CodeMirror.rmClass(node, "foo");\n
+  eq(node.className, "");\n
+});\n
+\n
+test("core_addClass", function() {\n
+  var node = document.createElement("div");\n
+  CodeMirror.addClass(node, "a");\n
+  eq(node.className, "a");\n
+  CodeMirror.addClass(node, "a");\n
+  eq(node.className, "a");\n
+  CodeMirror.addClass(node, "b");\n
+  eq(node.className, "a b");\n
+  CodeMirror.addClass(node, "a");\n
+  CodeMirror.addClass(node, "b");\n
+  eq(node.className, "a b");\n
+});\n
 
 
 ]]></string> </value>
         </item>
-        <item>
-            <key> <string>precondition</string> </key>
-            <value> <string></string> </value>
-        </item>
-        <item>
-            <key> <string>size</string> </key>
-            <value> <int>59307</int> </value>
-        </item>
-        <item>
-            <key> <string>title</string> </key>
-            <value> <string></string> </value>
-        </item>
       </dictionary>
     </pickle>
   </record>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/vim_test.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/vim_test.js.xml
index c0158885de54613509710399984c8dcd9e532244..a12de7872bc9db9e495dcef7110e28b09ff61d41 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/vim_test.js.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/test/vim_test.js.xml
@@ -8,7 +8,7 @@
       <dictionary>
         <item>
             <key> <string>_EtagSupport__etag</string> </key>
-            <value> <string>ts93403104.99</string> </value>
+            <value> <string>ts21897151.6</string> </value>
         </item>
         <item>
             <key> <string>__name__</string> </key>
@@ -30,7 +30,7 @@
         </item>
         <item>
             <key> <string>size</string> </key>
-            <value> <int>92482</int> </value>
+            <value> <int>133477</int> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
@@ -49,6 +49,8 @@
             <key> <string>data</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
+CodeMirror.Vim.suppressErrorLogging = true;\n
+\n
 var code = \'\' +\n
 \' wOrd1 (#%\\n\' +\n
 \' word3] \\n\' +\n
@@ -149,7 +151,7 @@ function copyCursor(cur) {\n
 \n
 function forEach(arr, func) {\n
   for (var i = 0; i < arr.length; i++) {\n
-    func(arr[i]);\n
+    func(arr[i], i, arr);\n
   }\n
 }\n
 \n
@@ -194,9 +196,9 @@ function testVim(name, run, opts, expectedFail) {\n
         for (var i = 0; i < arguments.length; i++) {\n
           var key = arguments[i];\n
           // Find key in keymap and handle.\n
-          var handled = CodeMirror.lookupKey(key, [\'vim-insert\'], executeHandler);\n
+          var handled = CodeMirror.lookupKey(key, \'vim-insert\', executeHandler);\n
           // Record for insert mode.\n
-          if (handled === true && cm.state.vim.insertMode && arguments[i] != \'Esc\') {\n
+          if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != \'Esc\') {\n
             var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;\n
             if (lastChange) {\n
               lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));\n
@@ -227,6 +229,11 @@ function testVim(name, run, opts, expectedFail) {\n
         return callback(result);\n
       }\n
     }\n
+    function fakeOpenNotification(matcher) {\n
+      return function(text) {\n
+        matcher(text);\n
+      }\n
+    }\n
     var helpers = {\n
       doKeys: doKeysFn(cm),\n
       // Warning: Only emulates keymap events, not character insertions. Use\n
@@ -236,16 +243,19 @@ function testVim(name, run, opts, expectedFail) {\n
       doEx: doExFn(cm),\n
       assertCursorAt: assertCursorAtFn(cm),\n
       fakeOpenDialog: fakeOpenDialog,\n
+      fakeOpenNotification: fakeOpenNotification,\n
       getRegisterController: function() {\n
         return CodeMirror.Vim.getRegisterController();\n
       }\n
     }\n
     CodeMirror.Vim.resetVimGlobalState_();\n
     var successful = false;\n
+    var savedOpenNotification = cm.openNotification;\n
     try {\n
       run(cm, vim, helpers);\n
       successful = true;\n
     } finally {\n
+      cm.openNotification = savedOpenNotification;\n
       if (!successful || verbose) {\n
         place.style.visibility = "visible";\n
       } else {\n
@@ -301,7 +311,7 @@ testJumplist(\'jumplist_gg\', [\'g\', \'g\', \'<C-o>\'], [5,2], [5,2]);\n
 testJumplist(\'jumplist_%\', [\'%\', \'<C-o>\'], [1,5], [1,5]);\n
 testJumplist(\'jumplist_{\', [\'{\', \'<C-o>\'], [1,5], [1,5]);\n
 testJumplist(\'jumplist_}\', [\'}\', \'<C-o>\'], [1,5], [1,5]);\n
-testJumplist(\'jumplist_\\\'\', [\'m\', \'a\', \'h\', \'\\\'\', \'a\', \'h\', \'<C-i>\'], [1,5], [1,5]);\n
+testJumplist(\'jumplist_\\\'\', [\'m\', \'a\', \'h\', \'\\\'\', \'a\', \'h\', \'<C-i>\'], [1,0], [1,5]);\n
 testJumplist(\'jumplist_`\', [\'m\', \'a\', \'h\', \'`\', \'a\', \'h\', \'<C-i>\'], [1,5], [1,5]);\n
 testJumplist(\'jumplist_*_cachedCursor\', [\'*\', \'<C-o>\'], [1,3], [1,3]);\n
 testJumplist(\'jumplist_#_cachedCursor\', [\'#\', \'<C-o>\'], [1,3], [1,3]);\n
@@ -545,6 +555,80 @@ testVim(\'{\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'6\', \'{\');\n
   helpers.assertCursorAt(0, 0);\n
 }, { value: \'a\\n\\nb\\nc\\n\\nd\' });\n
+testVim(\'paragraph motions\', function(cm, vim, helpers) {\n
+  cm.setCursor(10, 0);\n
+  helpers.doKeys(\'{\');\n
+  helpers.assertCursorAt(4, 0);\n
+  helpers.doKeys(\'{\');\n
+  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'2\', \'}\');\n
+  helpers.assertCursorAt(7, 0);\n
+  helpers.doKeys(\'2\', \'}\');\n
+  helpers.assertCursorAt(16, 0);\n
+\n
+  cm.setCursor(9, 0);\n
+  helpers.doKeys(\'}\');\n
+  helpers.assertCursorAt(14, 0);\n
+\n
+  cm.setCursor(6, 0);\n
+  helpers.doKeys(\'}\');\n
+  helpers.assertCursorAt(7, 0);\n
+\n
+  // ip inside empty space\n
+  cm.setCursor(10, 0);\n
+  helpers.doKeys(\'v\', \'i\', \'p\');\n
+  eqPos(Pos(7, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(12, 0), cm.getCursor(\'head\'));\n
+  helpers.doKeys(\'i\', \'p\');\n
+  eqPos(Pos(7, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(13, 1), cm.getCursor(\'head\'));\n
+  helpers.doKeys(\'2\', \'i\', \'p\');\n
+  eqPos(Pos(7, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(16, 1), cm.getCursor(\'head\'));\n
+\n
+  // should switch to visualLine mode\n
+  cm.setCursor(14, 0);\n
+  helpers.doKeys(\'<Esc>\', \'v\', \'i\', \'p\');\n
+  helpers.assertCursorAt(14, 0);\n
+\n
+  cm.setCursor(14, 0);\n
+  helpers.doKeys(\'<Esc>\', \'V\', \'i\', \'p\');\n
+  eqPos(Pos(16, 1), cm.getCursor(\'head\'));\n
+\n
+  // ap inside empty space\n
+  cm.setCursor(10, 0);\n
+  helpers.doKeys(\'<Esc>\', \'v\', \'a\', \'p\');\n
+  eqPos(Pos(7, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(13, 1), cm.getCursor(\'head\'));\n
+  helpers.doKeys(\'a\', \'p\');\n
+  eqPos(Pos(7, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(16, 1), cm.getCursor(\'head\'));\n
+\n
+  cm.setCursor(13, 0);\n
+  helpers.doKeys(\'v\', \'a\', \'p\');\n
+  eqPos(Pos(13, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(14, 0), cm.getCursor(\'head\'));\n
+\n
+  cm.setCursor(16, 0);\n
+  helpers.doKeys(\'v\', \'a\', \'p\');\n
+  eqPos(Pos(14, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(16, 1), cm.getCursor(\'head\'));\n
+\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'v\', \'a\', \'p\');\n
+  eqPos(Pos(0, 0), cm.getCursor(\'anchor\'));\n
+  eqPos(Pos(4, 0), cm.getCursor(\'head\'));\n
+\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'d\', \'i\', \'p\');\n
+  var register = helpers.getRegisterController().getRegister();\n
+  eq(\'a\\na\\n\', register.toString());\n
+  is(register.linewise);\n
+  helpers.doKeys(\'3\', \'j\', \'p\');\n
+  helpers.doKeys(\'y\', \'i\', \'p\');\n
+  is(register.linewise);\n
+  eq(\'b\\na\\na\\nc\\n\', register.toString());\n
+}, { value: \'a\\na\\n\\n\\n\\nb\\nc\\n\\n\\n\\n\\n\\n\\nd\\n\\ne\\nf\' });\n
 \n
 // Operator tests\n
 testVim(\'dl\', function(cm, vim, helpers) {\n
@@ -553,7 +637,7 @@ testVim(\'dl\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'l\');\n
   eq(\'word1 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\' \', register.text);\n
+  eq(\' \', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1 \' });\n
@@ -562,9 +646,9 @@ testVim(\'dl_eol\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'l\');\n
   eq(\' word1\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\' \', register.text);\n
+  eq(\' \', register.toString());\n
   is(!register.linewise);\n
-  helpers.assertCursorAt(0, 5);\n
+  helpers.assertCursorAt(0, 6);\n
 }, { value: \' word1 \' });\n
 testVim(\'dl_repeat\', function(cm, vim, helpers) {\n
   var curStart = makeCursor(0, 0);\n
@@ -572,7 +656,7 @@ testVim(\'dl_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'d\', \'l\');\n
   eq(\'ord1 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\' w\', register.text);\n
+  eq(\' w\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1 \' });\n
@@ -582,7 +666,7 @@ testVim(\'dh\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'h\');\n
   eq(\' wrd1 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'o\', register.text);\n
+  eq(\'o\', register.toString());\n
   is(!register.linewise);\n
   eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());\n
 }, { value: \' word1 \' });\n
@@ -592,7 +676,7 @@ testVim(\'dj\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'j\');\n
   eq(\' word3\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\' word1\\nword2\\n\', register.text);\n
+  eq(\' word1\\nword2\\n\', register.toString());\n
   is(register.linewise);\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1\\nword2\\n word3\' });\n
@@ -602,7 +686,7 @@ testVim(\'dj_end_of_document\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'j\');\n
   eq(\' word1 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 3);\n
 }, { value: \' word1 \' });\n
@@ -612,7 +696,7 @@ testVim(\'dk\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'k\');\n
   eq(\' word3\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\' word1\\nword2\\n\', register.text);\n
+  eq(\' word1\\nword2\\n\', register.toString());\n
   is(register.linewise);\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1\\nword2\\n word3\' });\n
@@ -622,7 +706,7 @@ testVim(\'dk_start_of_document\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'k\');\n
   eq(\' word1 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 3);\n
 }, { value: \' word1 \' });\n
@@ -632,7 +716,7 @@ testVim(\'dw_space\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'w\');\n
   eq(\'word1 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\' \', register.text);\n
+  eq(\' \', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1 \' });\n
@@ -642,7 +726,7 @@ testVim(\'dw_word\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'w\');\n
   eq(\' word2\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1 \', register.text);\n
+  eq(\'word1 \', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1 word2\' });\n
@@ -653,9 +737,9 @@ testVim(\'dw_only_word\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'w\');\n
   eq(\' \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1 \', register.text);\n
+  eq(\'word1 \', register.toString());\n
   is(!register.linewise);\n
-  helpers.assertCursorAt(0, 0);\n
+  helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1 \' });\n
 testVim(\'dw_eol\', function(cm, vim, helpers) {\n
   // Assert that dw does not delete the newline if last word to delete is at end\n
@@ -664,9 +748,9 @@ testVim(\'dw_eol\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'w\');\n
   eq(\' \\nword2\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\', register.text);\n
+  eq(\'word1\', register.toString());\n
   is(!register.linewise);\n
-  helpers.assertCursorAt(0, 0);\n
+  helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1\\nword2\' });\n
 testVim(\'dw_eol_with_multiple_newlines\', function(cm, vim, helpers) {\n
   // Assert that dw does not delete the newline if last word to delete is at end\n
@@ -675,9 +759,9 @@ testVim(\'dw_eol_with_multiple_newlines\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'w\');\n
   eq(\' \\n\\nword2\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\', register.text);\n
+  eq(\'word1\', register.toString());\n
   is(!register.linewise);\n
-  helpers.assertCursorAt(0, 0);\n
+  helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1\\n\\nword2\' });\n
 testVim(\'dw_empty_line_followed_by_whitespace\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
@@ -721,9 +805,9 @@ testVim(\'dw_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'2\', \'w\');\n
   eq(\' \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\\nword2\', register.text);\n
+  eq(\'word1\\nword2\', register.toString());\n
   is(!register.linewise);\n
-  helpers.assertCursorAt(0, 0);\n
+  helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1\\nword2\' });\n
 testVim(\'de_word_start_and_empty_lines\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
@@ -802,7 +886,7 @@ testVim(\'d_inclusive\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'e\');\n
   eq(\'  \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\', register.text);\n
+  eq(\'word1\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1 \' });\n
@@ -812,7 +896,7 @@ testVim(\'d_reverse\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'b\');\n
   eq(\' word2 \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\\n\', register.text);\n
+  eq(\'word1\\n\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \' word1\\nword2 \' });\n
@@ -824,7 +908,7 @@ testVim(\'dd\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'d\');\n
   eq(expectedLineCount, cm.lineCount());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(expectedBuffer, register.text);\n
+  eq(expectedBuffer, register.toString());\n
   is(register.linewise);\n
   helpers.assertCursorAt(0, lines[1].textStart);\n
 });\n
@@ -836,7 +920,7 @@ testVim(\'dd_prefix_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'d\', \'d\');\n
   eq(expectedLineCount, cm.lineCount());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(expectedBuffer, register.text);\n
+  eq(expectedBuffer, register.toString());\n
   is(register.linewise);\n
   helpers.assertCursorAt(0, lines[2].textStart);\n
 });\n
@@ -848,7 +932,7 @@ testVim(\'dd_motion_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'d\', \'2\', \'d\');\n
   eq(expectedLineCount, cm.lineCount());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(expectedBuffer, register.text);\n
+  eq(expectedBuffer, register.toString());\n
   is(register.linewise);\n
   helpers.assertCursorAt(0, lines[2].textStart);\n
 });\n
@@ -860,7 +944,7 @@ testVim(\'dd_multiply_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'d\', \'3\', \'d\');\n
   eq(expectedLineCount, cm.lineCount());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(expectedBuffer, register.text);\n
+  eq(expectedBuffer, register.toString());\n
   is(register.linewise);\n
   helpers.assertCursorAt(0, lines[6].textStart);\n
 });\n
@@ -871,6 +955,15 @@ testVim(\'dd_lastline\', function(cm, vim, helpers) {\n
   eq(expectedLineCount, cm.lineCount());\n
   helpers.assertCursorAt(cm.lineCount() - 1, 0);\n
 });\n
+testVim(\'dd_only_line\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  var expectedRegister = cm.getValue() + "\\n";\n
+  helpers.doKeys(\'d\',\'d\');\n
+  eq(1, cm.lineCount());\n
+  eq(\'\', cm.getValue());\n
+  var register = helpers.getRegisterController().getRegister();\n
+  eq(expectedRegister, register.toString());\n
+}, { value: "thisistheonlyline" });\n
 // Yank commands should behave the exact same as d commands, expect that nothing\n
 // gets deleted.\n
 testVim(\'yw_repeat\', function(cm, vim, helpers) {\n
@@ -881,7 +974,7 @@ testVim(\'yw_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'y\', \'2\', \'w\');\n
   eq(\' word1\\nword2\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\\nword2\', register.text);\n
+  eq(\'word1\\nword2\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1\\nword2\' });\n
@@ -894,7 +987,7 @@ testVim(\'yy_multiply_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'y\', \'3\', \'y\');\n
   eq(expectedLineCount, cm.lineCount());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(expectedBuffer, register.text);\n
+  eq(expectedBuffer, register.toString());\n
   is(register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 });\n
@@ -915,7 +1008,7 @@ testVim(\'cw_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'c\', \'2\', \'w\');\n
   eq(\' \', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'word1\\nword2\', register.text);\n
+  eq(\'word1\\nword2\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
   eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
@@ -928,16 +1021,59 @@ testVim(\'cc_multiply_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'c\', \'3\', \'c\');\n
   eq(expectedLineCount, cm.lineCount());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(expectedBuffer, register.text);\n
+  eq(expectedBuffer, register.toString());\n
   is(register.linewise);\n
   eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
 });\n
-testVim(\'cc_append\', function(cm, vim, helpers) {\n
+testVim(\'cc_should_not_append_to_document\', function(cm, vim, helpers) {\n
   var expectedLineCount = cm.lineCount();\n
   cm.setCursor(cm.lastLine(), 0);\n
   helpers.doKeys(\'c\', \'c\');\n
   eq(expectedLineCount, cm.lineCount());\n
 });\n
+function fillArray(val, times) {\n
+  var arr = [];\n
+  for (var i = 0; i < times; i++) {\n
+    arr.push(val);\n
+  }\n
+  return arr;\n
+}\n
+testVim(\'c_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'l\', \'l\', \'c\');\n
+  var replacement = fillArray(\'hello\', 3);\n
+  cm.replaceSelections(replacement);\n
+  eq(\'1hello\\n5hello\\nahellofg\', cm.getValue());\n
+  helpers.doKeys(\'<Esc>\');\n
+  cm.setCursor(2, 3);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'k\', \'h\', \'C\');\n
+  replacement = fillArray(\'world\', 3);\n
+  cm.replaceSelections(replacement);\n
+  eq(\'1hworld\\n5hworld\\nahworld\', cm.getValue());\n
+}, {value: \'1234\\n5678\\nabcdefg\'});\n
+testVim(\'c_visual_block_replay\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'c\');\n
+  var replacement = fillArray(\'fo\', 3);\n
+  cm.replaceSelections(replacement);\n
+  eq(\'1fo4\\n5fo8\\nafodefg\', cm.getValue());\n
+  helpers.doKeys(\'<Esc>\');\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'.\');\n
+  eq(\'foo4\\nfoo8\\nfoodefg\', cm.getValue());\n
+}, {value: \'1234\\n5678\\nabcdefg\'});\n
+\n
+testVim(\'d_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'l\', \'l\', \'d\');\n
+  eq(\'1\\n5\\nafg\', cm.getValue());\n
+}, {value: \'1234\\n5678\\nabcdefg\'});\n
+testVim(\'D_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'D\');\n
+  eq(\'1\\n5\\na\', cm.getValue());\n
+}, {value: \'1234\\n5678\\nabcdefg\'});\n
+\n
 // Swapcase commands edit in place and do not modify registers.\n
 testVim(\'g~w_repeat\', function(cm, vim, helpers) {\n
   // Assert that dw does delete newline if it should go to the next line, and\n
@@ -947,7 +1083,7 @@ testVim(\'g~w_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'g\', \'~\', \'2\', \'w\');\n
   eq(\' WORD1\\nWORD2\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1\\nword2\' });\n
@@ -959,10 +1095,62 @@ testVim(\'g~g~\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'g\', \'~\', \'3\', \'g\', \'~\');\n
   eq(expectedValue, cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
 }, { value: \' word1\\nword2\\nword3\\nword4\\nword5\\nword6\' });\n
+testVim(\'gu_and_gU\', function(cm, vim, helpers) {\n
+  var curStart = makeCursor(0, 7);\n
+  var value = cm.getValue();\n
+  cm.setCursor(curStart);\n
+  helpers.doKeys(\'2\', \'g\', \'U\', \'w\');\n
+  eq(cm.getValue(), \'wa wb xX WC wd\');\n
+  eqPos(curStart, cm.getCursor());\n
+  helpers.doKeys(\'2\', \'g\', \'u\', \'w\');\n
+  eq(cm.getValue(), value);\n
+\n
+  helpers.doKeys(\'2\', \'g\', \'U\', \'B\');\n
+  eq(cm.getValue(), \'wa WB Xx wc wd\');\n
+  eqPos(makeCursor(0, 3), cm.getCursor());\n
+\n
+  cm.setCursor(makeCursor(0, 4));\n
+  helpers.doKeys(\'g\', \'u\', \'i\', \'w\');\n
+  eq(cm.getValue(), \'wa wb Xx wc wd\');\n
+  eqPos(makeCursor(0, 3), cm.getCursor());\n
+\n
+  // TODO: support gUgU guu\n
+  // eqPos(makeCursor(0, 0), cm.getCursor());\n
+\n
+  var register = helpers.getRegisterController().getRegister();\n
+  eq(\'\', register.toString());\n
+  is(!register.linewise);\n
+}, { value: \'wa wb xx wc wd\' });\n
+testVim(\'visual_block_~\', function(cm, vim, helpers) {\n
+  cm.setCursor(1, 1);\n
+  helpers.doKeys(\'<C-v>\', \'l\', \'l\', \'j\', \'~\');\n
+  helpers.assertCursorAt(1, 1);\n
+  eq(\'hello\\nwoRLd\\naBCDe\', cm.getValue());\n
+  cm.setCursor(2, 0);\n
+  helpers.doKeys(\'v\', \'l\', \'l\', \'~\');\n
+  helpers.assertCursorAt(2, 0);\n
+  eq(\'hello\\nwoRLd\\nAbcDe\', cm.getValue());\n
+},{value: \'hello\\nwOrld\\nabcde\' });\n
+testVim(\'._swapCase_visualBlock\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'<C-v>\', \'j\', \'j\', \'l\', \'~\');\n
+  cm.setCursor(0, 3);\n
+  helpers.doKeys(\'.\');\n
+  eq(\'HelLO\\nWorLd\\nAbcdE\', cm.getValue());\n
+},{value: \'hEllo\\nwOrlD\\naBcDe\' });\n
+testVim(\'._delete_visualBlock\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'<C-v>\', \'j\', \'x\');\n
+  eq(\'ive\\ne\\nsome\\nsugar\', cm.getValue());\n
+  helpers.doKeys(\'.\');\n
+  eq(\'ve\\n\\nsome\\nsugar\', cm.getValue());\n
+  helpers.doKeys(\'j\', \'j\', \'.\');\n
+  eq(\'ve\\n\\nome\\nugar\', cm.getValue());\n
+  helpers.doKeys(\'u\', \'<C-r>\', \'.\');\n
+  eq(\'ve\\n\\nme\\ngar\', cm.getValue());\n
+},{value: \'give\\nme\\nsome\\nsugar\' });\n
 testVim(\'>{motion}\', function(cm, vim, helpers) {\n
   cm.setCursor(1, 3);\n
   var expectedLineCount = cm.lineCount();\n
@@ -970,7 +1158,7 @@ testVim(\'>{motion}\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'>\', \'k\');\n
   eq(expectedValue, cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 3);\n
 }, { value: \' word1\\nword2\\nword3 \', indentUnit: 2 });\n
@@ -981,7 +1169,7 @@ testVim(\'>>\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'>\', \'>\');\n
   eq(expectedValue, cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 3);\n
 }, { value: \' word1\\nword2\\nword3 \', indentUnit: 2 });\n
@@ -992,7 +1180,7 @@ testVim(\'<{motion}\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'<\', \'k\');\n
   eq(expectedValue, cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \'   word1\\n  word2\\nword3 \', indentUnit: 2 });\n
@@ -1003,7 +1191,7 @@ testVim(\'<<\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'2\', \'<\', \'<\');\n
   eq(expectedValue, cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'\', register.text);\n
+  eq(\'\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \'   word1\\n  word2\\nword3 \', indentUnit: 2 });\n
@@ -1011,7 +1199,12 @@ testVim(\'<<\', function(cm, vim, helpers) {\n
 // Edit tests\n
 function testEdit(name, before, pos, edit, after) {\n
   return testVim(name, function(cm, vim, helpers) {\n
-             cm.setCursor(0, before.search(pos));\n
+             var ch = before.search(pos)\n
+             var line = before.substring(0, ch).split(\'\\n\').length - 1;\n
+             if (line) {\n
+               ch = before.substring(0, ch).split(\'\\n\').pop().length;\n
+             }\n
+             cm.setCursor(line, ch);\n
              helpers.doKeys.apply(this, edit.split(\'\'));\n
              eq(after, cm.getValue());\n
            }, {value: before});\n
@@ -1053,6 +1246,7 @@ testEdit(\'daW_end_punct\', \'foo \\tbAr.\', /A/, \'daW\', \'foo\');\n
 //    Open and close on same line\n
 testEdit(\'di(_open_spc\', \'foo (bAr) baz\', /\\(/, \'di(\', \'foo () baz\');\n
 testEdit(\'di)_open_spc\', \'foo (bAr) baz\', /\\(/, \'di)\', \'foo () baz\');\n
+testEdit(\'dib_open_spc\', \'foo (bAr) baz\', /\\(/, \'dib\', \'foo () baz\');\n
 testEdit(\'da(_open_spc\', \'foo (bAr) baz\', /\\(/, \'da(\', \'foo  baz\');\n
 testEdit(\'da)_open_spc\', \'foo (bAr) baz\', /\\(/, \'da)\', \'foo  baz\');\n
 \n
@@ -1066,11 +1260,26 @@ testEdit(\'di)_close_spc\', \'foo (bAr) baz\', /\\)/, \'di)\', \'foo () baz\');\
 testEdit(\'da(_close_spc\', \'foo (bAr) baz\', /\\)/, \'da(\', \'foo  baz\');\n
 testEdit(\'da)_close_spc\', \'foo (bAr) baz\', /\\)/, \'da)\', \'foo  baz\');\n
 \n
+//  delete around and inner b.\n
+testEdit(\'dab_on_(_should_delete_around_()block\', \'o( in(abc) )\', /\\(a/, \'dab\', \'o( in )\');\n
+\n
+//  delete around and inner B.\n
+testEdit(\'daB_on_{_should_delete_around_{}block\', \'o{ in{abc} }\', /{a/, \'daB\', \'o{ in }\');\n
+testEdit(\'diB_on_{_should_delete_inner_{}block\', \'o{ in{abc} }\', /{a/, \'diB\', \'o{ in{} }\');\n
+\n
+testEdit(\'da{_on_{_should_delete_inner_block\', \'o{ in{abc} }\', /{a/, \'da{\', \'o{ in }\');\n
+testEdit(\'di[_on_(_should_not_delete\', \'foo (bAr) baz\', /\\(/, \'di[\', \'foo (bAr) baz\');\n
+testEdit(\'di[_on_)_should_not_delete\', \'foo (bAr) baz\', /\\)/, \'di[\', \'foo (bAr) baz\');\n
+testEdit(\'da[_on_(_should_not_delete\', \'foo (bAr) baz\', /\\(/, \'da[\', \'foo (bAr) baz\');\n
+testEdit(\'da[_on_)_should_not_delete\', \'foo (bAr) baz\', /\\)/, \'da[\', \'foo (bAr) baz\');\n
+testMotion(\'di(_outside_should_stay\', [\'d\', \'i\', \'(\'], { line: 0, ch: 0}, { line: 0, ch: 0});\n
+\n
 //  Open and close on different lines, equally indented\n
 testEdit(\'di{_middle_spc\', \'a{\\n\\tbar\\n}b\', /r/, \'di{\', \'a{}b\');\n
 testEdit(\'di}_middle_spc\', \'a{\\n\\tbar\\n}b\', /r/, \'di}\', \'a{}b\');\n
 testEdit(\'da{_middle_spc\', \'a{\\n\\tbar\\n}b\', /r/, \'da{\', \'ab\');\n
 testEdit(\'da}_middle_spc\', \'a{\\n\\tbar\\n}b\', /r/, \'da}\', \'ab\');\n
+testEdit(\'daB_middle_spc\', \'a{\\n\\tbar\\n}b\', /r/, \'daB\', \'ab\');\n
 \n
 // open and close on diff lines, open indented less than close\n
 testEdit(\'di{_middle_spc\', \'a{\\n\\tbar\\n\\t}b\', /r/, \'di{\', \'a{}b\');\n
@@ -1084,15 +1293,48 @@ testEdit(\'di]_middle_spc\', \'a\\t[\\n\\tbar\\n]b\', /r/, \'di]\', \'a\\t[]b\')
 testEdit(\'da[_middle_spc\', \'a\\t[\\n\\tbar\\n]b\', /r/, \'da[\', \'a\\tb\');\n
 testEdit(\'da]_middle_spc\', \'a\\t[\\n\\tbar\\n]b\', /r/, \'da]\', \'a\\tb\');\n
 \n
+function testSelection(name, before, pos, keys, sel) {\n
+  return testVim(name, function(cm, vim, helpers) {\n
+             var ch = before.search(pos)\n
+             var line = before.substring(0, ch).split(\'\\n\').length - 1;\n
+             if (line) {\n
+               ch = before.substring(0, ch).split(\'\\n\').pop().length;\n
+             }\n
+             cm.setCursor(line, ch);\n
+             helpers.doKeys.apply(this, keys.split(\'\'));\n
+             eq(sel, cm.getSelection());\n
+           }, {value: before});\n
+}\n
+testSelection(\'viw_middle_spc\', \'foo \\tbAr\\t baz\', /A/, \'viw\', \'bAr\');\n
+testSelection(\'vaw_middle_spc\', \'foo \\tbAr\\t baz\', /A/, \'vaw\', \'bAr\\t \');\n
+testSelection(\'viw_middle_punct\', \'foo \\tbAr,\\t baz\', /A/, \'viw\', \'bAr\');\n
+testSelection(\'vaW_middle_punct\', \'foo \\tbAr,\\t baz\', /A/, \'vaW\', \'bAr,\\t \');\n
+testSelection(\'viw_start_spc\', \'foo \\tbAr\\t baz\', /b/, \'viw\', \'bAr\');\n
+testSelection(\'viw_end_spc\', \'foo \\tbAr\\t baz\', /r/, \'viw\', \'bAr\');\n
+testSelection(\'viw_eol\', \'foo \\tbAr\', /r/, \'viw\', \'bAr\');\n
+testSelection(\'vi{_middle_spc\', \'a{\\n\\tbar\\n\\t}b\', /r/, \'vi{\', \'\\n\\tbar\\n\\t\');\n
+testSelection(\'va{_middle_spc\', \'a{\\n\\tbar\\n\\t}b\', /r/, \'va{\', \'{\\n\\tbar\\n\\t}\');\n
+\n
+testVim(\'mouse_select\', function(cm, vim, helpers) {\n
+  cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: \'*mouse\'});\n
+  is(cm.state.vim.visualMode);\n
+  is(!cm.state.vim.visualLine);\n
+  is(!cm.state.vim.visualBlock);\n
+  helpers.doKeys(\'<Esc>\');\n
+  is(!cm.somethingSelected());\n
+  helpers.doKeys(\'g\', \'v\');\n
+  eq(\'cd\', cm.getSelection());\n
+}, {value: \'abcdef\'});\n
+\n
 // Operator-motion tests\n
 testVim(\'D\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 3);\n
   helpers.doKeys(\'D\');\n
   eq(\' wo\\nword2\\n word3\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'rd1\', register.text);\n
+  eq(\'rd1\', register.toString());\n
   is(!register.linewise);\n
-  helpers.assertCursorAt(0, 2);\n
+  helpers.assertCursorAt(0, 3);\n
 }, { value: \' word1\\nword2\\n word3\' });\n
 testVim(\'C\', function(cm, vim, helpers) {\n
   var curStart = makeCursor(0, 3);\n
@@ -1100,7 +1342,7 @@ testVim(\'C\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'C\');\n
   eq(\' wo\\nword2\\n word3\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'rd1\', register.text);\n
+  eq(\'rd1\', register.toString());\n
   is(!register.linewise);\n
   eqPos(curStart, cm.getCursor());\n
   eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
@@ -1111,7 +1353,7 @@ testVim(\'Y\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'Y\');\n
   eq(\' word1\\nword2\\n word3\', cm.getValue());\n
   var register = helpers.getRegisterController().getRegister();\n
-  eq(\'rd1\', register.text);\n
+  eq(\'rd1\', register.toString());\n
   is(!register.linewise);\n
   helpers.assertCursorAt(0, 3);\n
 }, { value: \' word1\\nword2\\n word3\' });\n
@@ -1163,6 +1405,13 @@ testVim(\'a_eol\', function(cm, vim, helpers) {\n
   helpers.assertCursorAt(0, lines[0].length);\n
   eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
 });\n
+testVim(\'A_endOfSelectedArea\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'v\', \'j\', \'l\');\n
+  helpers.doKeys(\'A\');\n
+  helpers.assertCursorAt(1, 2);\n
+  eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
+}, {value: \'foo\\nbar\'});\n
 testVim(\'i\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'i\');\n
@@ -1172,7 +1421,7 @@ testVim(\'i\', function(cm, vim, helpers) {\n
 testVim(\'i_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'3\', \'i\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   eq(\'testtesttest\', cm.getValue());\n
   helpers.assertCursorAt(0, 11);\n
 }, { value: \'\' });\n
@@ -1180,7 +1429,8 @@ testVim(\'i_repeat_delete\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 4);\n
   helpers.doKeys(\'2\', \'i\');\n
   cm.replaceRange(\'z\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Backspace\', \'Backspace\', \'Esc\');\n
+  helpers.doInsertModeKeys(\'Backspace\', \'Backspace\');\n
+  helpers.doKeys(\'<Esc>\');\n
   eq(\'abe\', cm.getValue());\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \'abcde\' });\n
@@ -1189,6 +1439,19 @@ testVim(\'A\', function(cm, vim, helpers) {\n
   helpers.assertCursorAt(0, lines[0].length);\n
   eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
 });\n
+testVim(\'A_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'l\', \'A\');\n
+  var replacement = new Array(cm.listSelections().length+1).join(\'hello \').split(\' \');\n
+  replacement.pop();\n
+  cm.replaceSelections(replacement);\n
+  eq(\'testhello\\nmehello\\npleahellose\', cm.getValue());\n
+  helpers.doKeys(\'<Esc>\');\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'.\');\n
+  // TODO this doesn\'t work yet\n
+  // eq(\'teshellothello\\nme hello hello\\nplehelloahellose\', cm.getValue());\n
+}, {value: \'test\\nme\\nplease\'});\n
 testVim(\'I\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 4);\n
   helpers.doKeys(\'I\');\n
@@ -1199,10 +1462,18 @@ testVim(\'I_repeat\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'3\', \'I\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   eq(\'testtesttestblah\', cm.getValue());\n
   helpers.assertCursorAt(0, 11);\n
 }, { value: \'blah\' });\n
+testVim(\'I_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'l\', \'I\');\n
+  var replacement = new Array(cm.listSelections().length+1).join(\'hello \').split(\' \');\n
+  replacement.pop();\n
+  cm.replaceSelections(replacement);\n
+  eq(\'hellotest\\nhellome\\nhelloplease\', cm.getValue());\n
+}, {value: \'test\\nme\\nplease\'});\n
 testVim(\'o\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 4);\n
   helpers.doKeys(\'o\');\n
@@ -1214,7 +1485,7 @@ testVim(\'o_repeat\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
   helpers.doKeys(\'3\', \'o\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   eq(\'\\ntest\\ntest\\ntest\', cm.getValue());\n
   helpers.assertCursorAt(3, 3);\n
 }, { value: \'\' });\n
@@ -1248,14 +1519,14 @@ testVim(\'p\', function(cm, vim, helpers) {\n
 }, { value: \'___\' });\n
 testVim(\'p_register\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
-  helpers.getRegisterController().getRegister(\'a\').set(\'abc\\ndef\', false);\n
+  helpers.getRegisterController().getRegister(\'a\').setText(\'abc\\ndef\', false);\n
   helpers.doKeys(\'"\', \'a\', \'p\');\n
   eq(\'__abc\\ndef_\', cm.getValue());\n
   helpers.assertCursorAt(1, 2);\n
 }, { value: \'___\' });\n
 testVim(\'p_wrong_register\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
-  helpers.getRegisterController().getRegister(\'a\').set(\'abc\\ndef\', false);\n
+  helpers.getRegisterController().getRegister(\'a\').setText(\'abc\\ndef\', false);\n
   helpers.doKeys(\'p\');\n
   eq(\'___\', cm.getValue());\n
   helpers.assertCursorAt(0, 1);\n
@@ -1274,6 +1545,31 @@ testVim(\'p_lastline\', function(cm, vim, helpers) {\n
   eq(\'___\\n  a\\nd\\n  a\\nd\', cm.getValue());\n
   helpers.assertCursorAt(1, 2);\n
 }, { value: \'___\' });\n
+testVim(\']p_first_indent_is_smaller\', function(cm, vim, helpers) {\n
+  helpers.getRegisterController().pushText(\'"\', \'yank\', \'  abc\\n    def\\n\', true);\n
+  helpers.doKeys(\']\', \'p\');\n
+  eq(\'  ___\\n  abc\\n    def\', cm.getValue());\n
+}, { value: \'  ___\' });\n
+testVim(\']p_first_indent_is_larger\', function(cm, vim, helpers) {\n
+  helpers.getRegisterController().pushText(\'"\', \'yank\', \'    abc\\n  def\\n\', true);\n
+  helpers.doKeys(\']\', \'p\');\n
+  eq(\'  ___\\n  abc\\ndef\', cm.getValue());\n
+}, { value: \'  ___\' });\n
+testVim(\']p_with_tab_indents\', function(cm, vim, helpers) {\n
+  helpers.getRegisterController().pushText(\'"\', \'yank\', \'\\t\\tabc\\n\\t\\t\\tdef\\n\', true);\n
+  helpers.doKeys(\']\', \'p\');\n
+  eq(\'\\t___\\n\\tabc\\n\\t\\tdef\', cm.getValue());\n
+}, { value: \'\\t___\', indentWithTabs: true});\n
+testVim(\']p_with_spaces_translated_to_tabs\', function(cm, vim, helpers) {\n
+  helpers.getRegisterController().pushText(\'"\', \'yank\', \'  abc\\n    def\\n\', true);\n
+  helpers.doKeys(\']\', \'p\');\n
+  eq(\'\\t___\\n\\tabc\\n\\t\\tdef\', cm.getValue());\n
+}, { value: \'\\t___\', indentWithTabs: true, tabSize: 2 });\n
+testVim(\'[p\', function(cm, vim, helpers) {\n
+  helpers.getRegisterController().pushText(\'"\', \'yank\', \'  abc\\n    def\\n\', true);\n
+  helpers.doKeys(\'[\', \'p\');\n
+  eq(\'  abc\\n    def\\n  ___\', cm.getValue());\n
+}, { value: \'  ___\' });\n
 testVim(\'P\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.getRegisterController().pushText(\'"\', \'yank\', \'abc\\ndef\', false);\n
@@ -1297,6 +1593,19 @@ testVim(\'r\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'v\', \'j\', \'h\', \'r\', \'<Space>\');\n
   eq(\'wuuu  \\n    her\', cm.getValue(),\'Replacing selection by space-characters failed\');\n
 }, { value: \'wordet\\nanother\' });\n
+testVim(\'r_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(2, 3);\n
+  helpers.doKeys(\'<C-v>\', \'k\', \'k\', \'h\', \'h\', \'r\', \'l\');\n
+  eq(\'1lll\\n5lll\\nalllefg\', cm.getValue());\n
+  helpers.doKeys(\'<C-v>\', \'l\', \'j\', \'r\', \'<Space>\');\n
+  eq(\'1  l\\n5  l\\nalllefg\', cm.getValue());\n
+  cm.setCursor(2, 0);\n
+  helpers.doKeys(\'o\');\n
+  helpers.doKeys(\'<Esc>\');\n
+  cm.replaceRange(\'\\t\\t\', cm.getCursor());\n
+  helpers.doKeys(\'<C-v>\', \'h\', \'h\', \'r\', \'r\');\n
+  eq(\'1  l\\n5  l\\nalllefg\\nrrrrrrrr\', cm.getValue());\n
+}, {value: \'1234\\n5678\\nabcdefg\'});\n
 testVim(\'R\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'R\');\n
@@ -1308,11 +1617,13 @@ testVim(\'mark\', function(cm, vim, helpers) {\n
   cm.setCursor(2, 2);\n
   helpers.doKeys(\'m\', \'t\');\n
   cm.setCursor(0, 0);\n
-  helpers.doKeys(\'\\\'\', \'t\');\n
-  helpers.assertCursorAt(2, 2);\n
-  cm.setCursor(0, 0);\n
   helpers.doKeys(\'`\', \'t\');\n
   helpers.assertCursorAt(2, 2);\n
+  cm.setCursor(2, 0);\n
+  cm.replaceRange(\'   h\', cm.getCursor());\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'\\\'\', \'t\');\n
+  helpers.assertCursorAt(2, 3);\n
 });\n
 testVim(\'jumpToMark_next\', function(cm, vim, helpers) {\n
   cm.setCursor(2, 2);\n
@@ -1552,60 +1863,365 @@ testVim(\'delmark_all\', function(cm, vim, helpers) {\n
 });\n
 testVim(\'visual\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'l\', \'v\', \'l\', \'l\');\n
-  helpers.assertCursorAt(0, 3);\n
+  helpers.assertCursorAt(0, 4);\n
   eqPos(makeCursor(0, 1), cm.getCursor(\'anchor\'));\n
   helpers.doKeys(\'d\');\n
   eq(\'15\', cm.getValue());\n
 }, { value: \'12345\' });\n
+testVim(\'visual_yank\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'v\', \'3\', \'l\', \'y\');\n
+  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'p\');\n
+  eq(\'aa te test for yank\', cm.getValue());\n
+}, { value: \'a test for yank\' })\n
+testVim(\'visual_w\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'v\', \'w\');\n
+  eq(cm.getSelection(), \'motion t\');\n
+}, { value: \'motion test\'});\n
+testVim(\'visual_initial_selection\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'v\');\n
+  cm.getSelection(\'n\');\n
+}, { value: \'init\'});\n
+testVim(\'visual_crossover_left\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 2);\n
+  helpers.doKeys(\'v\', \'l\', \'h\', \'h\');\n
+  cm.getSelection(\'ro\');\n
+}, { value: \'cross\'});\n
+testVim(\'visual_crossover_left\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 2);\n
+  helpers.doKeys(\'v\', \'h\', \'l\', \'l\');\n
+  cm.getSelection(\'os\');\n
+}, { value: \'cross\'});\n
+testVim(\'visual_crossover_up\', function(cm, vim, helpers) {\n
+  cm.setCursor(3, 2);\n
+  helpers.doKeys(\'v\', \'j\', \'k\', \'k\');\n
+  eqPos(Pos(2, 2), cm.getCursor(\'head\'));\n
+  eqPos(Pos(3, 3), cm.getCursor(\'anchor\'));\n
+  helpers.doKeys(\'k\');\n
+  eqPos(Pos(1, 2), cm.getCursor(\'head\'));\n
+  eqPos(Pos(3, 3), cm.getCursor(\'anchor\'));\n
+}, { value: \'cross\\ncross\\ncross\\ncross\\ncross\\n\'});\n
+testVim(\'visual_crossover_down\', function(cm, vim, helpers) {\n
+  cm.setCursor(1, 2);\n
+  helpers.doKeys(\'v\', \'k\', \'j\', \'j\');\n
+  eqPos(Pos(2, 3), cm.getCursor(\'head\'));\n
+  eqPos(Pos(1, 2), cm.getCursor(\'anchor\'));\n
+  helpers.doKeys(\'j\');\n
+  eqPos(Pos(3, 3), cm.getCursor(\'head\'));\n
+  eqPos(Pos(1, 2), cm.getCursor(\'anchor\'));\n
+}, { value: \'cross\\ncross\\ncross\\ncross\\ncross\\n\'});\n
+testVim(\'visual_exit\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'<C-v>\', \'l\', \'j\', \'j\', \'<Esc>\');\n
+  eqPos(cm.getCursor(\'anchor\'), cm.getCursor(\'head\'));\n
+  eq(vim.visualMode, false);\n
+}, { value: \'hello\\nworld\\nfoo\' });\n
 testVim(\'visual_line\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'l\', \'V\', \'l\', \'j\', \'j\', \'d\');\n
   eq(\' 4\\n 5\', cm.getValue());\n
 }, { value: \' 1\\n 2\\n 3\\n 4\\n 5\' });\n
+testVim(\'visual_block_move_to_eol\', function(cm, vim, helpers) {\n
+  // moveToEol should move all block cursors to end of line\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'G\', \'$\');\n
+  var selections = cm.getSelections().join();\n
+  eq("123,45,6", selections);\n
+}, {value: \'123\\n45\\n6\'});\n
+testVim(\'visual_block_different_line_lengths\', function(cm, vim, helpers) {\n
+  // test the block selection with lines of different length\n
+  // i.e. extending the selection\n
+  // till the end of the longest line.\n
+  helpers.doKeys(\'<C-v>\', \'l\', \'j\', \'j\', \'6\', \'l\', \'d\');\n
+  helpers.doKeys(\'d\', \'d\', \'d\', \'d\');\n
+  eq(\'\', cm.getValue());\n
+}, {value: \'1234\\n5678\\nabcdefg\'});\n
+testVim(\'visual_block_truncate_on_short_line\', function(cm, vim, helpers) {\n
+  // check for left side selection in case\n
+  // of moving up to a shorter line.\n
+  cm.replaceRange(\'\', cm.getCursor());\n
+  cm.setCursor(3, 4);\n
+  helpers.doKeys(\'<C-v>\', \'l\', \'k\', \'k\', \'d\');\n
+  eq(\'hello world\\n{\\ntis\\nsa!\', cm.getValue());\n
+}, {value: \'hello world\\n{\\nthis is\\nsparta!\'});\n
+testVim(\'visual_block_corners\', function(cm, vim, helpers) {\n
+  cm.setCursor(1, 2);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'l\', \'k\');\n
+  // circle around the anchor\n
+  // and check the selections\n
+  var selections = cm.getSelections();\n
+  eq(\'345891\', selections.join(\'\'));\n
+  helpers.doKeys(\'4\', \'h\');\n
+  selections = cm.getSelections();\n
+  eq(\'123678\', selections.join(\'\'));\n
+  helpers.doKeys(\'j\', \'j\');\n
+  selections = cm.getSelections();\n
+  eq(\'678abc\', selections.join(\'\'));\n
+  helpers.doKeys(\'4\', \'l\');\n
+  selections = cm.getSelections();\n
+  eq(\'891cde\', selections.join(\'\'));\n
+}, {value: \'12345\\n67891\\nabcde\'});\n
+testVim(\'visual_block_mode_switch\', function(cm, vim, helpers) {\n
+  // switch between visual modes\n
+  cm.setCursor(1, 1);\n
+  // blockwise to characterwise visual\n
+  helpers.doKeys(\'<C-v>\', \'j\', \'l\', \'v\');\n
+  selections = cm.getSelections();\n
+  eq(\'7891\\nabc\', selections.join(\'\'));\n
+  // characterwise to blockwise\n
+  helpers.doKeys(\'<C-v>\');\n
+  selections = cm.getSelections();\n
+  eq(\'78bc\', selections.join(\'\'));\n
+  // blockwise to linewise visual\n
+  helpers.doKeys(\'V\');\n
+  selections = cm.getSelections();\n
+  eq(\'67891\\nabcde\', selections.join(\'\'));\n
+}, {value: \'12345\\n67891\\nabcde\'});\n
+testVim(\'visual_block_crossing_short_line\', function(cm, vim, helpers) {\n
+  // visual block with long and short lines\n
+  cm.setCursor(0, 3);\n
+  helpers.doKeys(\'<C-v>\', \'j\', \'j\', \'j\');\n
+  var selections = cm.getSelections().join();\n
+  eq(\'4,,d,b\', selections);\n
+  helpers.doKeys(\'3\', \'k\');\n
+  selections = cm.getSelections().join();\n
+  eq(\'4\', selections);\n
+  helpers.doKeys(\'5\', \'j\', \'k\');\n
+  selections = cm.getSelections().join("");\n
+  eq(10, selections.length);\n
+}, {value: \'123456\\n78\\nabcdefg\\nfoobar\\n}\\n\'});\n
+testVim(\'visual_block_curPos_on_exit\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'3\' , \'l\', \'<Esc>\');\n
+  eqPos(makeCursor(0, 3), cm.getCursor());\n
+  helpers.doKeys(\'h\', \'<C-v>\', \'2\' , \'j\' ,\'3\' , \'l\');\n
+  eq(cm.getSelections().join(), "3456,,cdef");\n
+  helpers.doKeys(\'4\' , \'h\');\n
+  eq(cm.getSelections().join(), "23,8,bc");\n
+  helpers.doKeys(\'2\' , \'l\');\n
+  eq(cm.getSelections().join(), "34,,cd");\n
+}, {value: \'123456\\n78\\nabcdefg\\nfoobar\'});\n
+\n
 testVim(\'visual_marks\', function(cm, vim, helpers) {\n
-  helpers.doKeys(\'l\', \'v\', \'l\', \'l\', \'v\');\n
+  helpers.doKeys(\'l\', \'v\', \'l\', \'l\', \'j\', \'j\', \'v\');\n
   // Test visual mode marks\n
-  cm.setCursor(0, 0);\n
+  cm.setCursor(2, 1);\n
   helpers.doKeys(\'\\\'\', \'<\');\n
   helpers.assertCursorAt(0, 1);\n
   helpers.doKeys(\'\\\'\', \'>\');\n
-  helpers.assertCursorAt(0, 3);\n
+  helpers.assertCursorAt(2, 0);\n
 });\n
 testVim(\'visual_join\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'l\', \'V\', \'l\', \'j\', \'j\', \'J\');\n
   eq(\' 1 2 3\\n 4\\n 5\', cm.getValue());\n
+  is(!vim.visualMode);\n
 }, { value: \' 1\\n 2\\n 3\\n 4\\n 5\' });\n
 testVim(\'visual_blank\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'v\', \'k\');\n
   eq(vim.visualMode, true);\n
 }, { value: \'\\n\' });\n
+testVim(\'reselect_visual\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'l\', \'v\', \'l\', \'l\', \'l\', \'y\', \'g\', \'v\');\n
+  helpers.assertCursorAt(0, 5);\n
+  eqPos(makeCursor(0, 1), cm.getCursor(\'anchor\'));\n
+  helpers.doKeys(\'v\');\n
+  cm.setCursor(1, 0);\n
+  helpers.doKeys(\'v\', \'l\', \'l\', \'p\');\n
+  eq(\'123456\\n2345\\nbar\', cm.getValue());\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'g\', \'v\');\n
+  // here the fake cursor is at (1, 3)\n
+  helpers.assertCursorAt(1, 4);\n
+  eqPos(makeCursor(1, 0), cm.getCursor(\'anchor\'));\n
+  helpers.doKeys(\'v\');\n
+  cm.setCursor(2, 0);\n
+  helpers.doKeys(\'v\', \'l\', \'l\', \'g\', \'v\');\n
+  helpers.assertCursorAt(1, 4);\n
+  eqPos(makeCursor(1, 0), cm.getCursor(\'anchor\'));\n
+  helpers.doKeys(\'g\', \'v\');\n
+  helpers.assertCursorAt(2, 3);\n
+  eqPos(makeCursor(2, 0), cm.getCursor(\'anchor\'));\n
+  eq(\'123456\\n2345\\nbar\', cm.getValue());\n
+}, { value: \'123456\\nfoo\\nbar\' });\n
+testVim(\'reselect_visual_line\', function(cm, vim, helpers) {\n
+  helpers.doKeys(\'l\', \'V\', \'j\', \'j\', \'V\', \'g\', \'v\', \'d\');\n
+  eq(\'foo\\nand\\nbar\', cm.getValue());\n
+  cm.setCursor(1, 0);\n
+  helpers.doKeys(\'V\', \'y\', \'j\');\n
+  helpers.doKeys(\'V\', \'p\' , \'g\', \'v\', \'d\');\n
+  eq(\'foo\\nand\', cm.getValue());\n
+}, { value: \'hello\\nthis\\nis\\nfoo\\nand\\nbar\' });\n
+testVim(\'reselect_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(1, 2);\n
+  helpers.doKeys(\'<C-v>\', \'k\', \'h\', \'<C-v>\');\n
+  cm.setCursor(2, 1);\n
+  helpers.doKeys(\'v\', \'l\', \'g\', \'v\');\n
+  eqPos(Pos(1, 2), vim.sel.anchor);\n
+  eqPos(Pos(0, 1), vim.sel.head);\n
+  // Ensure selection is done with visual block mode rather than one\n
+  // continuous range.\n
+  eq(cm.getSelections().join(\'\'), \'23oo\')\n
+  helpers.doKeys(\'g\', \'v\');\n
+  eqPos(Pos(2, 1), vim.sel.anchor);\n
+  eqPos(Pos(2, 2), vim.sel.head);\n
+  helpers.doKeys(\'<Esc>\');\n
+  // Ensure selection of deleted range\n
+  cm.setCursor(1, 1);\n
+  helpers.doKeys(\'v\', \'<C-v>\', \'j\', \'d\', \'g\', \'v\');\n
+  eq(cm.getSelections().join(\'\'), \'or\');\n
+}, { value: \'123456\\nfoo\\nbar\' });\n
 testVim(\'s_normal\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'s\');\n
-  helpers.doInsertModeKeys(\'Esc\');\n
-  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'<Esc>\');\n
   eq(\'ac\', cm.getValue());\n
 }, { value: \'abc\'});\n
 testVim(\'s_visual\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'v\', \'s\');\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.assertCursorAt(0, 0);\n
   eq(\'ac\', cm.getValue());\n
 }, { value: \'abc\'});\n
+testVim(\'o_visual\', function(cm, vim, helpers) {\n
+  cm.setCursor(0,0);\n
+  helpers.doKeys(\'v\',\'l\',\'l\',\'l\',\'o\');\n
+  helpers.assertCursorAt(0,0);\n
+  helpers.doKeys(\'v\',\'v\',\'j\',\'j\',\'j\',\'o\');\n
+  helpers.assertCursorAt(0,0);\n
+  helpers.doKeys(\'O\');\n
+  helpers.doKeys(\'l\',\'l\')\n
+  helpers.assertCursorAt(3, 3);\n
+  helpers.doKeys(\'d\');\n
+  eq(\'p\',cm.getValue());\n
+}, { value: \'abcd\\nefgh\\nijkl\\nmnop\'});\n
+testVim(\'o_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\',\'3\',\'j\',\'l\',\'l\', \'o\');\n
+  eqPos(Pos(3, 3), vim.sel.anchor);\n
+  eqPos(Pos(0, 1), vim.sel.head);\n
+  helpers.doKeys(\'O\');\n
+  eqPos(Pos(3, 1), vim.sel.anchor);\n
+  eqPos(Pos(0, 3), vim.sel.head);\n
+  helpers.doKeys(\'o\');\n
+  eqPos(Pos(0, 3), vim.sel.anchor);\n
+  eqPos(Pos(3, 1), vim.sel.head);\n
+}, { value: \'abcd\\nefgh\\nijkl\\nmnop\'});\n
+testVim(\'changeCase_visual\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'v\', \'l\', \'l\');\n
+  helpers.doKeys(\'U\');\n
+  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'v\', \'l\', \'l\');\n
+  helpers.doKeys(\'u\');\n
+  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'l\', \'l\', \'l\', \'.\');\n
+  helpers.assertCursorAt(0, 3);\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'v\', \'j\', \'U\', \'q\');\n
+  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'j\', \'@\', \'a\');\n
+  helpers.assertCursorAt(1, 0);\n
+  cm.setCursor(3, 0);\n
+  helpers.doKeys(\'V\', \'U\', \'j\', \'.\');\n
+  eq(\'ABCDEF\\nGHIJKL\\nMnopq\\nSHORT LINE\\nLONG LINE OF TEXT\', cm.getValue());\n
+}, { value: \'abcdef\\nghijkl\\nmnopq\\nshort line\\nlong line of text\'});\n
+testVim(\'changeCase_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(2, 1);\n
+  helpers.doKeys(\'<C-v>\', \'k\', \'k\', \'h\', \'U\');\n
+  eq(\'ABcdef\\nGHijkl\\nMNopq\\nfoo\', cm.getValue());\n
+  cm.setCursor(0, 2);\n
+  helpers.doKeys(\'.\');\n
+  eq(\'ABCDef\\nGHIJkl\\nMNOPq\\nfoo\', cm.getValue());\n
+  // check when last line is shorter.\n
+  cm.setCursor(2, 2);\n
+  helpers.doKeys(\'.\');\n
+  eq(\'ABCDef\\nGHIJkl\\nMNOPq\\nfoO\', cm.getValue());\n
+}, { value: \'abcdef\\nghijkl\\nmnopq\\nfoo\'});\n
+testVim(\'visual_paste\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'v\', \'l\', \'l\', \'y\');\n
+  helpers.assertCursorAt(0, 0);\n
+  helpers.doKeys(\'3\', \'l\', \'j\', \'v\', \'l\', \'p\');\n
+  helpers.assertCursorAt(1, 5);\n
+  eq(\'this is a\\nunithitest for visual paste\', cm.getValue());\n
+  cm.setCursor(0, 0);\n
+  // in case of pasting whole line\n
+  helpers.doKeys(\'y\', \'y\');\n
+  cm.setCursor(1, 6);\n
+  helpers.doKeys(\'v\', \'l\', \'l\', \'l\', \'p\');\n
+  helpers.assertCursorAt(2, 0);\n
+  eq(\'this is a\\nunithi\\nthis is a\\n for visual paste\', cm.getValue());\n
+}, { value: \'this is a\\nunit test for visual paste\'});\n
+\n
+// This checks the contents of the register used to paste the text\n
+testVim(\'v_paste_from_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'"\', \'a\', \'y\', \'w\');\n
+  cm.setCursor(1, 0);\n
+  helpers.doKeys(\'v\', \'p\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+register/.test(text));\n
+  });\n
+}, { value: \'register contents\\nare not erased\'});\n
 testVim(\'S_normal\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'j\', \'S\');\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.assertCursorAt(1, 0);\n
   eq(\'aa\\n\\ncc\', cm.getValue());\n
 }, { value: \'aa\\nbb\\ncc\'});\n
+testVim(\'blockwise_paste\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'3\', \'j\', \'l\', \'y\');\n
+  cm.setCursor(0, 2);\n
+  // paste one char after the current cursor position\n
+  helpers.doKeys(\'p\');\n
+  eq(\'helhelo\\nworwold\\nfoofo\\nbarba\', cm.getValue());\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'v\', \'4\', \'l\', \'y\');\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'3\', \'j\', \'p\');\n
+  eq(\'helheelhelo\\norwold\\noofo\\narba\', cm.getValue());\n
+}, { value: \'hello\\nworld\\nfoo\\nbar\'});\n
+testVim(\'blockwise_paste_long/short_line\', function(cm, vim, helpers) {\n
+  // extend short lines in case of different line lengths.\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'j\', \'j\', \'y\');\n
+  cm.setCursor(0, 3);\n
+  helpers.doKeys(\'p\');\n
+  eq(\'hellho\\nfoo f\\nbar b\', cm.getValue());\n
+}, { value: \'hello\\nfoo\\nbar\'});\n
+testVim(\'blockwise_paste_cut_paste\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'x\');\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'P\');\n
+  eq(\'cut\\nand\\npaste\\nme\', cm.getValue());\n
+}, { value: \'cut\\nand\\npaste\\nme\'});\n
+testVim(\'blockwise_paste_from_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'"\', \'a\', \'y\');\n
+  cm.setCursor(0, 3);\n
+  helpers.doKeys(\'"\', \'a\', \'p\');\n
+  eq(\'foobfar\\nhellho\\nworlwd\', cm.getValue());\n
+}, { value: \'foobar\\nhello\\nworld\'});\n
+testVim(\'blockwise_paste_last_line\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<C-v>\', \'2\', \'j\', \'l\', \'y\');\n
+  cm.setCursor(3, 0);\n
+  helpers.doKeys(\'p\');\n
+  eq(\'cut\\nand\\npaste\\nmcue\\n an\\n pa\', cm.getValue());\n
+}, { value: \'cut\\nand\\npaste\\nme\'});\n
+\n
 testVim(\'S_visual\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 1);\n
   helpers.doKeys(\'v\', \'j\', \'S\');\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.assertCursorAt(0, 0);\n
   eq(\'\\ncc\', cm.getValue());\n
 }, { value: \'aa\\nbb\\ncc\'});\n
+\n
 testVim(\'/ and n/N\', function(cm, vim, helpers) {\n
   cm.openDialog = helpers.fakeOpenDialog(\'match\');\n
   helpers.doKeys(\'/\');\n
@@ -1624,7 +2240,16 @@ testVim(\'/_case\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'/\');\n
   helpers.assertCursorAt(1, 6);\n
 }, { value: \'match nope match \\n nope Match\' });\n
-testVim(\'/_2\', function(cm, vim, helpers) {\n
+testVim(\'/_2_pcre\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.setOption(\'pcre\', true);\n
+  cm.openDialog = helpers.fakeOpenDialog(\'(word){2}\');\n
+  helpers.doKeys(\'/\');\n
+  helpers.assertCursorAt(1, 9);\n
+  helpers.doKeys(\'n\');\n
+  helpers.assertCursorAt(2, 1);\n
+}, { value: \'word\\n another wordword\\n wordwordword\\n\' });\n
+testVim(\'/_2_nopcre\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.setOption(\'pcre\', false);\n
   cm.openDialog = helpers.fakeOpenDialog(\'\\\\(word\\\\)\\\\{2}\');\n
   helpers.doKeys(\'/\');\n
   helpers.assertCursorAt(1, 9);\n
@@ -1754,6 +2379,366 @@ testVim(\'#\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'#\');\n
   helpers.assertCursorAt(1, 8);\n
 }, { value: \'    :=  match nomatch match \\nnomatch Match\' });\n
+testVim(\'g*\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 8);\n
+  helpers.doKeys(\'g\', \'*\');\n
+  helpers.assertCursorAt(0, 18);\n
+  cm.setCursor(0, 8);\n
+  helpers.doKeys(\'3\', \'g\', \'*\');\n
+  helpers.assertCursorAt(1, 8);\n
+}, { value: \'matches match alsoMatch\\nmatchme matching\' });\n
+testVim(\'g#\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 8);\n
+  helpers.doKeys(\'g\', \'#\');\n
+  helpers.assertCursorAt(0, 0);\n
+  cm.setCursor(0, 8);\n
+  helpers.doKeys(\'3\', \'g\', \'#\');\n
+  helpers.assertCursorAt(1, 0);\n
+}, { value: \'matches match alsoMatch\\nmatchme matching\' });\n
+testVim(\'macro_insert\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'0\', \'i\');\n
+  cm.replaceRange(\'foo\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\', \'@\', \'a\');\n
+  eq(\'foofoo\', cm.getValue());\n
+}, { value: \'\'});\n
+testVim(\'macro_insert_repeat\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'$\', \'a\');\n
+  cm.replaceRange(\'larry.\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'a\');\n
+  cm.replaceRange(\'curly.\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\');\n
+  helpers.doKeys(\'a\');\n
+  cm.replaceRange(\'moe.\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'@\', \'a\');\n
+  // At this point, the most recent edit should be the 2nd insert change\n
+  // inside the macro, i.e. "curly.".\n
+  helpers.doKeys(\'.\');\n
+  eq(\'larry.curly.moe.larry.curly.curly.\', cm.getValue());\n
+}, { value: \'\'});\n
+testVim(\'macro_space\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'<Space>\', \'<Space>\');\n
+  helpers.assertCursorAt(0, 2);\n
+  helpers.doKeys(\'q\', \'a\', \'<Space>\', \'<Space>\', \'q\');\n
+  helpers.assertCursorAt(0, 4);\n
+  helpers.doKeys(\'@\', \'a\');\n
+  helpers.assertCursorAt(0, 6);\n
+  helpers.doKeys(\'@\', \'a\');\n
+  helpers.assertCursorAt(0, 8);\n
+}, { value: \'one line of text.\'});\n
+testVim(\'macro_t_search\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'t\', \'e\', \'q\');\n
+  helpers.assertCursorAt(0, 1);\n
+  helpers.doKeys(\'l\', \'@\', \'a\');\n
+  helpers.assertCursorAt(0, 6);\n
+  helpers.doKeys(\'l\', \';\');\n
+  helpers.assertCursorAt(0, 12);\n
+}, { value: \'one line of text.\'});\n
+testVim(\'macro_f_search\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'b\', \'f\', \'e\', \'q\');\n
+  helpers.assertCursorAt(0, 2);\n
+  helpers.doKeys(\'@\', \'b\');\n
+  helpers.assertCursorAt(0, 7);\n
+  helpers.doKeys(\';\');\n
+  helpers.assertCursorAt(0, 13);\n
+}, { value: \'one line of text.\'});\n
+testVim(\'macro_slash_search\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'c\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'e\');\n
+  helpers.doKeys(\'/\', \'q\');\n
+  helpers.assertCursorAt(0, 2);\n
+  helpers.doKeys(\'@\', \'c\');\n
+  helpers.assertCursorAt(0, 7);\n
+  helpers.doKeys(\'n\');\n
+  helpers.assertCursorAt(0, 13);\n
+}, { value: \'one line of text.\'});\n
+testVim(\'macro_multislash_search\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'d\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'e\');\n
+  helpers.doKeys(\'/\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'t\');\n
+  helpers.doKeys(\'/\', \'q\');\n
+  helpers.assertCursorAt(0, 12);\n
+  helpers.doKeys(\'@\', \'d\');\n
+  helpers.assertCursorAt(0, 15);\n
+}, { value: \'one line of text to rule them all.\'});\n
+testVim(\'macro_parens\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'z\', \'i\');\n
+  cm.replaceRange(\'(\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'e\', \'a\');\n
+  cm.replaceRange(\')\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\');\n
+  helpers.doKeys(\'w\', \'@\', \'z\');\n
+  helpers.doKeys(\'w\', \'@\', \'z\');\n
+  eq(\'(see) (spot) (run)\', cm.getValue());\n
+}, { value: \'see spot run\'});\n
+testVim(\'macro_overwrite\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'z\', \'0\', \'i\');\n
+  cm.replaceRange(\'I \', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\');\n
+  helpers.doKeys(\'e\');\n
+  // Now replace the macro with something else.\n
+  helpers.doKeys(\'q\', \'z\', \'a\');\n
+  cm.replaceRange(\'.\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\');\n
+  helpers.doKeys(\'e\', \'@\', \'z\');\n
+  helpers.doKeys(\'e\', \'@\', \'z\');\n
+  eq(\'I see. spot. run.\', cm.getValue());\n
+}, { value: \'see spot run\'});\n
+testVim(\'macro_search_f\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'f\', \' \');\n
+  helpers.assertCursorAt(0,3);\n
+  helpers.doKeys(\'q\', \'0\');\n
+  helpers.assertCursorAt(0,0);\n
+  helpers.doKeys(\'@\', \'a\');\n
+  helpers.assertCursorAt(0,3);\n
+}, { value: \'The quick brown fox jumped over the lazy dog.\'});\n
+testVim(\'macro_search_2f\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'2\', \'f\', \' \');\n
+  helpers.assertCursorAt(0,9);\n
+  helpers.doKeys(\'q\', \'0\');\n
+  helpers.assertCursorAt(0,0);\n
+  helpers.doKeys(\'@\', \'a\');\n
+  helpers.assertCursorAt(0,9);\n
+}, { value: \'The quick brown fox jumped over the lazy dog.\'});\n
+testVim(\'yank_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'"\', \'a\', \'y\', \'y\');\n
+  helpers.doKeys(\'j\', \'"\', \'b\', \'y\', \'y\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+foo/.test(text));\n
+    is(/b\\s+bar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'foo\\nbar\'});\n
+testVim(\'yank_visual_block\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 1);\n
+  helpers.doKeys(\'<C-v>\', \'l\', \'j\', \'"\', \'a\', \'y\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+oo\\nar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'foo\\nbar\'});\n
+testVim(\'yank_append_line_to_line_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'"\', \'a\', \'y\', \'y\');\n
+  helpers.doKeys(\'j\', \'"\', \'A\', \'y\', \'y\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+foo\\nbar/.test(text));\n
+    is(/"\\s+foo\\nbar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'foo\\nbar\'});\n
+testVim(\'yank_append_word_to_word_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'"\', \'a\', \'y\', \'w\');\n
+  helpers.doKeys(\'j\', \'"\', \'A\', \'y\', \'w\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+foobar/.test(text));\n
+    is(/"\\s+foobar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'foo\\nbar\'});\n
+testVim(\'yank_append_line_to_word_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'"\', \'a\', \'y\', \'w\');\n
+  helpers.doKeys(\'j\', \'"\', \'A\', \'y\', \'y\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+foo\\nbar/.test(text));\n
+    is(/"\\s+foo\\nbar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'foo\\nbar\'});\n
+testVim(\'yank_append_word_to_line_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'"\', \'a\', \'y\', \'y\');\n
+  helpers.doKeys(\'j\', \'"\', \'A\', \'y\', \'w\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+foo\\nbar/.test(text));\n
+    is(/"\\s+foo\\nbar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'foo\\nbar\'});\n
+testVim(\'macro_register\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'q\', \'a\', \'i\');\n
+  cm.replaceRange(\'gangnam\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\');\n
+  helpers.doKeys(\'q\', \'b\', \'o\');\n
+  cm.replaceRange(\'style\', cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  helpers.doKeys(\'q\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/a\\s+i/.test(text));\n
+    is(/b\\s+o/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, { value: \'\'});\n
+testVim(\'._register\', function(cm,vim,helpers) {\n
+  cm.setCursor(0,0);\n
+  helpers.doKeys(\'i\');\n
+  cm.replaceRange(\'foo\',cm.getCursor());\n
+  helpers.doKeys(\'<Esc>\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/\\.\\s+foo/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, {value: \'\'});\n
+testVim(\':_register\', function(cm,vim,helpers) {\n
+  helpers.doEx(\'bar\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/:\\s+bar/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, {value: \'\'});\n
+testVim(\'search_register_escape\', function(cm, vim, helpers) {\n
+  // Check that the register is restored if the user escapes rather than confirms.\n
+  cm.openDialog = helpers.fakeOpenDialog(\'waldo\');\n
+  helpers.doKeys(\'/\');\n
+  var onKeyDown;\n
+  var onKeyUp;\n
+  var KEYCODES = {\n
+    f: 70,\n
+    o: 79,\n
+    Esc: 27\n
+  };\n
+  cm.openDialog = function(template, callback, options) {\n
+    onKeyDown = options.onKeyDown;\n
+    onKeyUp = options.onKeyUp;\n
+  };\n
+  var close = function() {};\n
+  helpers.doKeys(\'/\');\n
+  // Fake some keyboard events coming in.\n
+  onKeyDown({keyCode: KEYCODES.f}, \'\', close);\n
+  onKeyUp({keyCode: KEYCODES.f}, \'\', close);\n
+  onKeyDown({keyCode: KEYCODES.o}, \'f\', close);\n
+  onKeyUp({keyCode: KEYCODES.o}, \'f\', close);\n
+  onKeyDown({keyCode: KEYCODES.o}, \'fo\', close);\n
+  onKeyUp({keyCode: KEYCODES.o}, \'fo\', close);\n
+  onKeyDown({keyCode: KEYCODES.Esc}, \'foo\', close);\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/waldo/.test(text));\n
+    is(!/foo/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, {value: \'\'});\n
+testVim(\'search_register\', function(cm, vim, helpers) {\n
+  cm.openDialog = helpers.fakeOpenDialog(\'foo\');\n
+  helpers.doKeys(\'/\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  cm.openNotification = helpers.fakeOpenNotification(function(text) {\n
+    is(/\\/\\s+foo/.test(text));\n
+  });\n
+  helpers.doKeys(\':\');\n
+}, {value: \'\'});\n
+testVim(\'search_history\', function(cm, vim, helpers) {\n
+  cm.openDialog = helpers.fakeOpenDialog(\'this\');\n
+  helpers.doKeys(\'/\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'checks\');\n
+  helpers.doKeys(\'/\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'search\');\n
+  helpers.doKeys(\'/\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'history\');\n
+  helpers.doKeys(\'/\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'checks\');\n
+  helpers.doKeys(\'/\');\n
+  var onKeyDown;\n
+  var onKeyUp;\n
+  var query = \'\';\n
+  var keyCodes = {\n
+    Up: 38,\n
+    Down: 40\n
+  };\n
+  cm.openDialog = function(template, callback, options) {\n
+    onKeyUp = options.onKeyUp;\n
+    onKeyDown = options.onKeyDown;\n
+  };\n
+  var close = function(newVal) {\n
+    if (typeof newVal == \'string\') query = newVal;\n
+  }\n
+  helpers.doKeys(\'/\');\n
+  onKeyDown({keyCode: keyCodes.Up}, query, close);\n
+  onKeyUp({keyCode: keyCodes.Up}, query, close);\n
+  eq(query, \'checks\');\n
+  onKeyDown({keyCode: keyCodes.Up}, query, close);\n
+  onKeyUp({keyCode: keyCodes.Up}, query, close);\n
+  eq(query, \'history\');\n
+  onKeyDown({keyCode: keyCodes.Up}, query, close);\n
+  onKeyUp({keyCode: keyCodes.Up}, query, close);\n
+  eq(query, \'search\');\n
+  onKeyDown({keyCode: keyCodes.Up}, query, close);\n
+  onKeyUp({keyCode: keyCodes.Up}, query, close);\n
+  eq(query, \'this\');\n
+  onKeyDown({keyCode: keyCodes.Down}, query, close);\n
+  onKeyUp({keyCode: keyCodes.Down}, query, close);\n
+  eq(query, \'search\');\n
+}, {value: \'\'});\n
+testVim(\'exCommand_history\', function(cm, vim, helpers) {\n
+  cm.openDialog = helpers.fakeOpenDialog(\'registers\');\n
+  helpers.doKeys(\':\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'sort\');\n
+  helpers.doKeys(\':\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'map\');\n
+  helpers.doKeys(\':\');\n
+  cm.openDialog = helpers.fakeOpenDialog(\'invalid\');\n
+  helpers.doKeys(\':\');\n
+  var onKeyDown;\n
+  var onKeyUp;\n
+  var input = \'\';\n
+  var keyCodes = {\n
+    Up: 38,\n
+    Down: 40,\n
+    s: 115\n
+  };\n
+  cm.openDialog = function(template, callback, options) {\n
+    onKeyUp = options.onKeyUp;\n
+    onKeyDown = options.onKeyDown;\n
+  };\n
+  var close = function(newVal) {\n
+    if (typeof newVal == \'string\') input = newVal;\n
+  }\n
+  helpers.doKeys(\':\');\n
+  onKeyDown({keyCode: keyCodes.Up}, input, close);\n
+  eq(input, \'invalid\');\n
+  onKeyDown({keyCode: keyCodes.Up}, input, close);\n
+  eq(input, \'map\');\n
+  onKeyDown({keyCode: keyCodes.Up}, input, close);\n
+  eq(input, \'sort\');\n
+  onKeyDown({keyCode: keyCodes.Up}, input, close);\n
+  eq(input, \'registers\');\n
+  onKeyDown({keyCode: keyCodes.s}, \'\', close);\n
+  input = \'s\';\n
+  onKeyDown({keyCode: keyCodes.Up}, input, close);\n
+  eq(input, \'sort\');\n
+}, {value: \'\'});\n
 testVim(\'.\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
   helpers.doKeys(\'2\', \'d\', \'w\');\n
@@ -1769,7 +2754,7 @@ testVim(\'._repeat\', function(cm, vim, helpers) {\n
 testVim(\'._insert\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'i\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.doKeys(\'.\');\n
   eq(\'testestt\', cm.getValue());\n
   helpers.assertCursorAt(0, 6);\n
@@ -1778,7 +2763,7 @@ testVim(\'._insert_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'i\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
   cm.setCursor(0, 4);\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.doKeys(\'2\', \'.\');\n
   eq(\'testesttestt\', cm.getValue());\n
   helpers.assertCursorAt(0, 10);\n
@@ -1787,7 +2772,7 @@ testVim(\'._repeat_insert\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'3\', \'i\');\n
   cm.replaceRange(\'te\', cm.getCursor());\n
   cm.setCursor(0, 2);\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.doKeys(\'.\');\n
   eq(\'tetettetetee\', cm.getValue());\n
   helpers.assertCursorAt(0, 10);\n
@@ -1796,7 +2781,7 @@ testVim(\'._insert_o\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'o\');\n
   cm.replaceRange(\'z\', cm.getCursor());\n
   cm.setCursor(1, 1);\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.doKeys(\'.\');\n
   eq(\'\\nz\\nz\', cm.getValue());\n
   helpers.assertCursorAt(2, 0);\n
@@ -1804,7 +2789,7 @@ testVim(\'._insert_o\', function(cm, vim, helpers) {\n
 testVim(\'._insert_o_repeat\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'o\');\n
   cm.replaceRange(\'z\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   cm.setCursor(1, 0);\n
   helpers.doKeys(\'2\', \'.\');\n
   eq(\'\\nz\\nz\\nz\', cm.getValue());\n
@@ -1813,7 +2798,7 @@ testVim(\'._insert_o_repeat\', function(cm, vim, helpers) {\n
 testVim(\'._insert_o_indent\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'o\');\n
   cm.replaceRange(\'z\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   cm.setCursor(1, 2);\n
   helpers.doKeys(\'.\');\n
   eq(\'{\\n  z\\n  z\', cm.getValue());\n
@@ -1822,7 +2807,7 @@ testVim(\'._insert_o_indent\', function(cm, vim, helpers) {\n
 testVim(\'._insert_cw\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'c\', \'w\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   cm.setCursor(0, 3);\n
   helpers.doKeys(\'2\', \'l\');\n
   helpers.doKeys(\'.\');\n
@@ -1834,7 +2819,7 @@ testVim(\'._insert_cw_repeat\', function(cm, vim, helpers) {\n
   // changes. Will conform to that behavior.\n
   helpers.doKeys(\'c\', \'w\');\n
   cm.replaceRange(\'test\', cm.getCursor());\n
-  helpers.doInsertModeKeys(\'Esc\');\n
+  helpers.doKeys(\'<Esc>\');\n
   cm.setCursor(0, 4);\n
   helpers.doKeys(\'l\');\n
   helpers.doKeys(\'2\', \'.\');\n
@@ -1844,7 +2829,8 @@ testVim(\'._insert_cw_repeat\', function(cm, vim, helpers) {\n
 testVim(\'._delete\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 5);\n
   helpers.doKeys(\'i\');\n
-  helpers.doInsertModeKeys(\'Backspace\', \'Esc\');\n
+  helpers.doInsertModeKeys(\'Backspace\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.doKeys(\'.\');\n
   eq(\'zace\', cm.getValue());\n
   helpers.assertCursorAt(0, 1);\n
@@ -1852,11 +2838,20 @@ testVim(\'._delete\', function(cm, vim, helpers) {\n
 testVim(\'._delete_repeat\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 6);\n
   helpers.doKeys(\'i\');\n
-  helpers.doInsertModeKeys(\'Backspace\', \'Esc\');\n
+  helpers.doInsertModeKeys(\'Backspace\');\n
+  helpers.doKeys(\'<Esc>\');\n
   helpers.doKeys(\'2\', \'.\');\n
   eq(\'zzce\', cm.getValue());\n
   helpers.assertCursorAt(0, 1);\n
 }, { value: \'zzabcde\'});\n
+testVim(\'._visual_>\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doKeys(\'V\', \'j\', \'>\');\n
+  cm.setCursor(2, 0)\n
+  helpers.doKeys(\'.\');\n
+  eq(\'  1\\n  2\\n  3\\n  4\', cm.getValue());\n
+  helpers.assertCursorAt(2, 2);\n
+}, { value: \'1\\n2\\n3\\n4\'});\n
 testVim(\'f;\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
   helpers.doKeys(\'f\', \'x\');\n
@@ -1961,7 +2956,7 @@ testVim(\'fc,;\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
   helpers.doKeys(\'f\', \'4\');\n
   cm.setCursor(0, 0);\n
-  helpers.doKeys(\'c\', \';\', \'Esc\');\n
+  helpers.doKeys(\'c\', \';\', \'<Esc>\');\n
   eq(\'56789\', cm.getValue());\n
   helpers.doKeys(\'u\');\n
   cm.setCursor(0, 9);\n
@@ -1972,7 +2967,7 @@ testVim(\'Fc,;\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 9);\n
   helpers.doKeys(\'F\', \'4\');\n
   cm.setCursor(0, 9);\n
-  helpers.doKeys(\'c\', \';\', \'Esc\');\n
+  helpers.doKeys(\'c\', \';\', \'<Esc>\');\n
   eq(\'01239\', cm.getValue());\n
   helpers.doKeys(\'u\');\n
   cm.setCursor(0, 0);\n
@@ -1983,7 +2978,7 @@ testVim(\'tc,;\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 0);\n
   helpers.doKeys(\'t\', \'4\');\n
   cm.setCursor(0, 0);\n
-  helpers.doKeys(\'c\', \';\', \'Esc\');\n
+  helpers.doKeys(\'c\', \';\', \'<Esc>\');\n
   eq(\'456789\', cm.getValue());\n
   helpers.doKeys(\'u\');\n
   cm.setCursor(0, 9);\n
@@ -1994,7 +2989,7 @@ testVim(\'Tc,;\', function(cm, vim, helpers) {\n
   cm.setCursor(0, 9);\n
   helpers.doKeys(\'T\', \'4\');\n
   cm.setCursor(0, 9);\n
-  helpers.doKeys(\'c\', \';\', \'Esc\');\n
+  helpers.doKeys(\'c\', \';\', \'<Esc>\');\n
   eq(\'012349\', cm.getValue());\n
   helpers.doKeys(\'u\');\n
   cm.setCursor(0, 0);\n
@@ -2065,7 +3060,8 @@ testVim(\'HML\', function(cm, vim, helpers) {\n
   return upper + lower;\n
 })()});\n
 \n
-var zVals = [\'zb\',\'zz\',\'zt\',\'z-\',\'z.\',\'z<CR>\'].map(function(e, idx){\n
+var zVals = [];\n
+forEach([\'zb\',\'zz\',\'zt\',\'z-\',\'z.\',\'z<CR>\'], function(e, idx){\n
   var lineNum = 250;\n
   var lines = 35;\n
   testVim(e, function(cm, vim, helpers) {\n
@@ -2135,6 +3131,7 @@ testVim(\'moveTillCharacter\', function(cm, vim, helpers){\n
   eq(4, cm.getCursor().ch);\n
 }, { value: moveTillCharacterSandbox});\n
 testVim(\'searchForPipe\', function(cm, vim, helpers){\n
+  CodeMirror.Vim.setOption(\'pcre\', false);\n
   cm.setCursor(0, 0);\n
   // Search for the \'|\'.\n
   cm.openDialog = helpers.fakeOpenDialog(\'|\');\n
@@ -2157,7 +3154,7 @@ testVim(\'scrollMotion\', function(cm, vim, helpers){\n
   prevScrollInfo = cm.getScrollInfo();\n
   helpers.doKeys(\'<C-e>\');\n
   eq(1, cm.getCursor().line);\n
-  eq(true, prevScrollInfo.top < cm.getScrollInfo().top);\n
+  is(prevScrollInfo.top < cm.getScrollInfo().top);\n
   // Jump to the end of the sandbox.\n
   cm.setCursor(1000, 0);\n
   prevCursor = cm.getCursor();\n
@@ -2166,8 +3163,8 @@ testVim(\'scrollMotion\', function(cm, vim, helpers){\n
   eq(prevCursor.line, cm.getCursor().line);\n
   prevScrollInfo = cm.getScrollInfo();\n
   helpers.doKeys(\'<C-y>\');\n
-  eq(prevCursor.line - 1, cm.getCursor().line);\n
-  eq(true, prevScrollInfo.top > cm.getScrollInfo().top);\n
+  eq(prevCursor.line - 1, cm.getCursor().line, "Y");\n
+  is(prevScrollInfo.top > cm.getScrollInfo().top);\n
 }, { value: scrollMotionSandbox});\n
 \n
 var squareBracketMotionSandbox = \'\'+\n
@@ -2365,142 +3362,204 @@ testVim(\'ex_sort_decimal_mixed_reverse\', function(cm, vim, helpers) {\n
   helpers.doEx(\'sort! d\');\n
   eq(\'a3\\nb2\\nc1\\nz\\ny\', cm.getValue());\n
 }, { value: \'a3\\nz\\nc1\\ny\\nb2\'});\n
-\n
-\n
+// test for :global command\n
+testVim(\'ex_global\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doEx(\'g/one/s//two\');\n
+  eq(\'two two\\n two two\\n two two\', cm.getValue());\n
+  helpers.doEx(\'1,2g/two/s//one\');\n
+  eq(\'one one\\n one one\\n two two\', cm.getValue());\n
+}, {value: \'one one\\n one one\\n one one\'});\n
+testVim(\'ex_global_confirm\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 0);\n
+  var onKeyDown;\n
+  var openDialogSave = cm.openDialog;\n
+  var KEYCODES = {\n
+    a: 65,\n
+    n: 78,\n
+    q: 81,\n
+    y: 89\n
+  };\n
+  // Intercept the ex command, \'global\'\n
+  cm.openDialog = function(template, callback, options) {\n
+    // Intercept the prompt for the embedded ex command, \'substitute\'\n
+    cm.openDialog = function(template, callback, options) {\n
+      onKeyDown = options.onKeyDown;\n
+    };\n
+    callback(\'g/one/s//two/gc\');\n
+  };\n
+  helpers.doKeys(\':\');\n
+  var close = function() {};\n
+  onKeyDown({keyCode: KEYCODES.n}, \'\', close);\n
+  onKeyDown({keyCode: KEYCODES.y}, \'\', close);\n
+  onKeyDown({keyCode: KEYCODES.a}, \'\', close);\n
+  onKeyDown({keyCode: KEYCODES.q}, \'\', close);\n
+  onKeyDown({keyCode: KEYCODES.y}, \'\', close);\n
+  eq(\'one two\\n two two\\n one one\\n two one\\n one one\', cm.getValue());\n
+}, {value: \'one one\\n one one\\n one one\\n one one\\n one one\'});\n
+// Basic substitute tests.\n
 testVim(\'ex_substitute_same_line\', function(cm, vim, helpers) {\n
   cm.setCursor(1, 0);\n
-  helpers.doEx(\'s/one/two\');\n
+  helpers.doEx(\'s/one/two/g\');\n
   eq(\'one one\\n two two\', cm.getValue());\n
 }, { value: \'one one\\n one one\'});\n
-testVim(\'ex_substitute_global\', function(cm, vim, helpers) {\n
+testVim(\'ex_substitute_full_file\', function(cm, vim, helpers) {\n
   cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/one/two\');\n
+  helpers.doEx(\'%s/one/two/g\');\n
   eq(\'two two\\n two two\', cm.getValue());\n
 }, { value: \'one one\\n one one\'});\n
 testVim(\'ex_substitute_input_range\', function(cm, vim, helpers) {\n
   cm.setCursor(1, 0);\n
-  helpers.doEx(\'1,3s/\\\\d/0\');\n
+  helpers.doEx(\'1,3s/\\\\d/0/g\');\n
   eq(\'0\\n0\\n0\\n4\', cm.getValue());\n
 }, { value: \'1\\n2\\n3\\n4\' });\n
 testVim(\'ex_substitute_visual_range\', function(cm, vim, helpers) {\n
   cm.setCursor(1, 0);\n
   // Set last visual mode selection marks \'< and \'> at lines 2 and 4\n
   helpers.doKeys(\'V\', \'2\', \'j\', \'v\');\n
-  helpers.doEx(\'\\\'<,\\\'>s/\\\\d/0\');\n
+  helpers.doEx(\'\\\'<,\\\'>s/\\\\d/0/g\');\n
   eq(\'1\\n0\\n0\\n0\\n5\', cm.getValue());\n
 }, { value: \'1\\n2\\n3\\n4\\n5\' });\n
-testVim(\'ex_substitute_capture\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  // \\n should be a backreference.\n
-  helpers.doEx(\'s/\\\\(\\\\d+\\\\)/\\\\1\\\\1/\')\n
-  eq(\'a1111 a1212 a1313\', cm.getValue());\n
-}, { value: \'a11 a12 a13\' });\n
-testVim(\'ex_substitute_capture2\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  // \\n should be a backreference, even if followed by \'$\'\n
-  helpers.doEx(\'s/\\\\(\\\\d+\\\\)/$\\\\1\\\\1/\')\n
-  eq(\'a $00 b\', cm.getValue());\n
-}, { value: \'a 0 b\' });\n
-testVim(\'ex_substitute_javascript\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  // Throw all the things that javascript likes to treat as special values\n
-  // into the replace part. All should be literal (this is VIM).\n
-  helpers.doEx(\'s/\\\\(\\\\d+\\\\)/$$ $\\\' $` $& \\\\1/\')\n
-  eq(\'a $$ $\\\' $` $& 0 b\', cm.getValue());\n
-}, { value: \'a 0 b\' });\n
-testVim(\'ex_substitute_nocapture\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  // $n should be literal, since that is the javascript form, not VIM.\n
-  helpers.doEx(\'s/\\\\(\\\\d+\\\\)/$1$1/\')\n
-  eq(\'a$1$1 a$1$1 a$1$1\', cm.getValue());\n
-}, { value: \'a11 a12 a13\' });\n
-testVim(\'ex_substitute_nocapture2\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  // \\$n should be literal, since that is the javascript form, not VIM. \n
-  helpers.doEx(\'s/\\\\(\\\\d+\\\\)/\\\\$1\\\\1/\')\n
-  eq(\'a $10 b\', cm.getValue());\n
-}, { value: \'a 0 b\' });\n
-testVim(\'ex_substitute_nocapture\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'s/b/$/\')\n
-  eq(\'a $ c\', cm.getValue());\n
-}, { value: \'a b c\' });\n
 testVim(\'ex_substitute_empty_query\', function(cm, vim, helpers) {\n
   // If the query is empty, use last query.\n
   cm.setCursor(1, 0);\n
   cm.openDialog = helpers.fakeOpenDialog(\'1\');\n
   helpers.doKeys(\'/\');\n
-  helpers.doEx(\'s//b\');\n
+  helpers.doEx(\'s//b/g\');\n
   eq(\'abb ab2 ab3\', cm.getValue());\n
 }, { value: \'a11 a12 a13\' });\n
-testVim(\'ex_substitute_slash_regex\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/\\\\//|\');\n
-  eq(\'one|two \\n three|four\', cm.getValue());\n
-}, { value: \'one/two \\n three/four\'});\n
-testVim(\'ex_substitute_pipe_regex\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/|/,\');\n
-  eq(\'one,two \\n three,four\', cm.getValue());\n
-}, { value: \'one|two \\n three|four\'});\n
-testVim(\'ex_substitute_or_regex\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/o\\\\|e\\\\|u/a\');\n
-  eq(\'ana|twa \\n thraa|faar\', cm.getValue());\n
-}, { value: \'one|two \\n three|four\'});\n
-testVim(\'ex_substitute_or_word_regex\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/\\\\(one\\\\|two\\\\)/five\');\n
-  eq(\'five|five \\n three|four\', cm.getValue());\n
-}, { value: \'one|two \\n three|four\'});\n
-testVim(\'ex_substitute_backslashslash_regex\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/\\\\\\\\/,\');\n
-  eq(\'one,two \\n three,four\', cm.getValue());\n
-}, { value: \'one\\\\two \\n three\\\\four\'});\n
-testVim(\'ex_substitute_slash_replacement\', function(cm, vim, helpers) {\n
-  cm.setCursor(1, 0);\n
-  helpers.doEx(\'%s/,/\\\\/\');\n
-  eq(\'one/two \\n three/four\', cm.getValue());\n
-}, { value: \'one,two \\n three,four\'});\n
-testVim(\'ex_substitute_backslash_replacement\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/,/\\\\\\\\/g\');\n
-  eq(\'one\\\\two \\n three\\\\four\', cm.getValue());\n
-}, { value: \'one,two \\n three,four\'});\n
-testVim(\'ex_substitute_multibackslash_replacement\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/,/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/g\'); // 16 backslashes.\n
-  eq(\'one\\\\\\\\\\\\\\\\two \\n three\\\\\\\\\\\\\\\\four\', cm.getValue()); // 2*8 backslashes.\n
-}, { value: \'one,two \\n three,four\'});\n
-testVim(\'ex_substitute_braces_word\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/\\\\(ab\\\\)\\\\{2\\\\}//g\');\n
-  eq(\'ab abb ab{2}\', cm.getValue());\n
-}, { value: \'ababab abb ab{2}\'});\n
-testVim(\'ex_substitute_braces_range\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/a\\\\{2,3\\\\}//g\');\n
-  eq(\'a   a\', cm.getValue());\n
-}, { value: \'a aa aaa aaaa\'});\n
-testVim(\'ex_substitute_braces_literal\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/ab{2}//g\');\n
-  eq(\'ababab abb \', cm.getValue());\n
-}, { value: \'ababab abb ab{2}\'});\n
-testVim(\'ex_substitute_braces_char\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/ab\\\\{2\\\\}//g\');\n
-  eq(\'ababab  ab{2}\', cm.getValue());\n
-}, { value: \'ababab abb ab{2}\'});\n
-testVim(\'ex_substitute_braces_no_escape\', function(cm, vim, helpers) {\n
-  helpers.doEx(\'%s/ab\\\\{2}//g\');\n
-  eq(\'ababab  ab{2}\', cm.getValue());\n
-}, { value: \'ababab abb ab{2}\'});\n
-testVim(\'ex_substitute_count\', function(cm, vim, helpers) {\n
+testVim(\'ex_substitute_javascript\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.setOption(\'pcre\', false);\n
   cm.setCursor(1, 0);\n
-  helpers.doEx(\'s/\\\\d/0/i 2\');\n
-  eq(\'1\\n0\\n0\\n4\', cm.getValue());\n
-}, { value: \'1\\n2\\n3\\n4\' });\n
-testVim(\'ex_substitute_count_with_range\', function(cm, vim, helpers) {\n
+  // Throw all the things that javascript likes to treat as special values\n
+  // into the replace part. All should be literal (this is VIM).\n
+  helpers.doEx(\'s/\\\\(\\\\d+\\\\)/$$ $\\\' $` $& \\\\1/g\')\n
+  eq(\'a $$ $\\\' $` $& 0 b\', cm.getValue());\n
+}, { value: \'a 0 b\' });\n
+testVim(\'ex_substitute_empty_arguments\', function(cm,vim,helpers) {\n
+  cm.setCursor(0, 0);\n
+  helpers.doEx(\'s/a/b/g\');\n
   cm.setCursor(1, 0);\n
-  helpers.doEx(\'1,3s/\\\\d/0/ 3\');\n
-  eq(\'1\\n2\\n0\\n0\', cm.getValue());\n
-}, { value: \'1\\n2\\n3\\n4\' });\n
+  helpers.doEx(\'s\');\n
+  eq(\'b b\\nb a\', cm.getValue());\n
+}, {value: \'a a\\na a\'});\n
+\n
+// More complex substitute tests that test both pcre and nopcre options.\n
+function testSubstitute(name, options) {\n
+  testVim(name + \'_pcre\', function(cm, vim, helpers) {\n
+    cm.setCursor(1, 0);\n
+    CodeMirror.Vim.setOption(\'pcre\', true);\n
+    helpers.doEx(options.expr);\n
+    eq(options.expectedValue, cm.getValue());\n
+  }, options);\n
+  // If no noPcreExpr is defined, assume that it\'s the same as the expr.\n
+  var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr;\n
+  testVim(name + \'_nopcre\', function(cm, vim, helpers) {\n
+    cm.setCursor(1, 0);\n
+    CodeMirror.Vim.setOption(\'pcre\', false);\n
+    helpers.doEx(noPcreExpr);\n
+    eq(options.expectedValue, cm.getValue());\n
+  }, options);\n
+}\n
+testSubstitute(\'ex_substitute_capture\', {\n
+  value: \'a11 a12 a13\',\n
+  expectedValue: \'a1111 a1212 a1313\',\n
+  // $n is a backreference\n
+  expr: \'s/(\\\\d+)/$1$1/g\',\n
+  // \\n is a backreference.\n
+  noPcreExpr: \'s/\\\\(\\\\d+\\\\)/\\\\1\\\\1/g\'});\n
+testSubstitute(\'ex_substitute_capture2\', {\n
+  value: \'a 0 b\',\n
+  expectedValue: \'a $00 b\',\n
+  expr: \'s/(\\\\d+)/$$$1$1/g\',\n
+  noPcreExpr: \'s/\\\\(\\\\d+\\\\)/$\\\\1\\\\1/g\'});\n
+testSubstitute(\'ex_substitute_nocapture\', {\n
+  value: \'a11 a12 a13\',\n
+  expectedValue: \'a$1$1 a$1$1 a$1$1\',\n
+  expr: \'s/(\\\\d+)/$$1$$1/g\',\n
+  noPcreExpr: \'s/\\\\(\\\\d+\\\\)/$1$1/g\'});\n
+testSubstitute(\'ex_substitute_nocapture2\', {\n
+  value: \'a 0 b\',\n
+  expectedValue: \'a $10 b\',\n
+  expr: \'s/(\\\\d+)/$$1$1/g\',\n
+  noPcreExpr: \'s/\\\\(\\\\d+\\\\)/\\\\$1\\\\1/g\'});\n
+testSubstitute(\'ex_substitute_nocapture\', {\n
+  value: \'a b c\',\n
+  expectedValue: \'a $ c\',\n
+  expr: \'s/b/$$/\',\n
+  noPcreExpr: \'s/b/$/\'});\n
+testSubstitute(\'ex_substitute_slash_regex\', {\n
+  value: \'one/two \\n three/four\',\n
+  expectedValue: \'one|two \\n three|four\',\n
+  expr: \'%s/\\\\//|\'});\n
+testSubstitute(\'ex_substitute_pipe_regex\', {\n
+  value: \'one|two \\n three|four\',\n
+  expectedValue: \'one,two \\n three,four\',\n
+  expr: \'%s/\\\\|/,/\',\n
+  noPcreExpr: \'%s/|/,/\'});\n
+testSubstitute(\'ex_substitute_or_regex\', {\n
+  value: \'one|two \\n three|four\',\n
+  expectedValue: \'ana|twa \\n thraa|faar\',\n
+  expr: \'%s/o|e|u/a/g\',\n
+  noPcreExpr: \'%s/o\\\\|e\\\\|u/a/g\'});\n
+testSubstitute(\'ex_substitute_or_word_regex\', {\n
+  value: \'one|two \\n three|four\',\n
+  expectedValue: \'five|five \\n three|four\',\n
+  expr: \'%s/(one|two)/five/g\',\n
+  noPcreExpr: \'%s/\\\\(one\\\\|two\\\\)/five/g\'});\n
+testSubstitute(\'ex_substitute_backslashslash_regex\', {\n
+  value: \'one\\\\two \\n three\\\\four\',\n
+  expectedValue: \'one,two \\n three,four\',\n
+  expr: \'%s/\\\\\\\\/,\'});\n
+testSubstitute(\'ex_substitute_slash_replacement\', {\n
+  value: \'one,two \\n three,four\',\n
+  expectedValue: \'one/two \\n three/four\',\n
+  expr: \'%s/,/\\\\/\'});\n
+testSubstitute(\'ex_substitute_backslash_replacement\', {\n
+  value: \'one,two \\n three,four\',\n
+  expectedValue: \'one\\\\two \\n three\\\\four\',\n
+  expr: \'%s/,/\\\\\\\\/g\'});\n
+testSubstitute(\'ex_substitute_multibackslash_replacement\', {\n
+  value: \'one,two \\n three,four\',\n
+  expectedValue: \'one\\\\\\\\\\\\\\\\two \\n three\\\\\\\\\\\\\\\\four\', // 2*8 backslashes.\n
+  expr: \'%s/,/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/g\'}); // 16 backslashes.\n
+testSubstitute(\'ex_substitute_braces_word\', {\n
+  value: \'ababab abb ab{2}\',\n
+  expectedValue: \'ab abb ab{2}\',\n
+  expr: \'%s/(ab){2}//g\',\n
+  noPcreExpr: \'%s/\\\\(ab\\\\)\\\\{2\\\\}//g\'});\n
+testSubstitute(\'ex_substitute_braces_range\', {\n
+  value: \'a aa aaa aaaa\',\n
+  expectedValue: \'a   a\',\n
+  expr: \'%s/a{2,3}//g\',\n
+  noPcreExpr: \'%s/a\\\\{2,3\\\\}//g\'});\n
+testSubstitute(\'ex_substitute_braces_literal\', {\n
+  value: \'ababab abb ab{2}\',\n
+  expectedValue: \'ababab abb \',\n
+  expr: \'%s/ab\\\\{2\\\\}//g\',\n
+  noPcreExpr: \'%s/ab{2}//g\'});\n
+testSubstitute(\'ex_substitute_braces_char\', {\n
+  value: \'ababab abb ab{2}\',\n
+  expectedValue: \'ababab  ab{2}\',\n
+  expr: \'%s/ab{2}//g\',\n
+  noPcreExpr: \'%s/ab\\\\{2\\\\}//g\'});\n
+testSubstitute(\'ex_substitute_braces_no_escape\', {\n
+  value: \'ababab abb ab{2}\',\n
+  expectedValue: \'ababab  ab{2}\',\n
+  expr: \'%s/ab{2}//g\',\n
+  noPcreExpr: \'%s/ab\\\\{2}//g\'});\n
+testSubstitute(\'ex_substitute_count\', {\n
+  value: \'1\\n2\\n3\\n4\',\n
+  expectedValue: \'1\\n0\\n0\\n4\',\n
+  expr: \'s/\\\\d/0/i 2\'});\n
+testSubstitute(\'ex_substitute_count_with_range\', {\n
+  value: \'1\\n2\\n3\\n4\',\n
+  expectedValue: \'1\\n2\\n0\\n0\',\n
+  expr: \'1,3s/\\\\d/0/ 3\'});\n
+testSubstitute(\'ex_substitute_not_global\', {\n
+  value: \'aaa\\nbaa\\ncaa\',\n
+  expectedValue: \'xaa\\nbxa\\ncxa\',\n
+  expr: \'%s/a/x/\'});\n
 function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {\n
   testVim(name, function(cm, vim, helpers) {\n
     var savedOpenDialog = cm.openDialog;\n
@@ -2550,29 +3609,29 @@ testSubstituteConfirm(\'ex_substitute_confirm_emptydoc\',\n
 testSubstituteConfirm(\'ex_substitute_confirm_nomatch\',\n
     \'%s/x/b/c\', \'ba a\\nbab\', \'ba a\\nbab\', \'\', makeCursor(0, 0));\n
 testSubstituteConfirm(\'ex_substitute_confirm_accept\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb b\\nbbb\', \'yyy\', makeCursor(1, 1));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb b\\nbbb\', \'yyy\', makeCursor(1, 1));\n
 testSubstituteConfirm(\'ex_substitute_confirm_random_keys\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb b\\nbbb\', \'ysdkywerty\', makeCursor(1, 1));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb b\\nbbb\', \'ysdkywerty\', makeCursor(1, 1));\n
 testSubstituteConfirm(\'ex_substitute_confirm_some\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb a\\nbbb\', \'yny\', makeCursor(1, 1));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb a\\nbbb\', \'yny\', makeCursor(1, 1));\n
 testSubstituteConfirm(\'ex_substitute_confirm_all\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb b\\nbbb\', \'a\', makeCursor(1, 1));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb b\\nbbb\', \'a\', makeCursor(1, 1));\n
 testSubstituteConfirm(\'ex_substitute_confirm_accept_then_all\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb b\\nbbb\', \'ya\', makeCursor(1, 1));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb b\\nbbb\', \'ya\', makeCursor(1, 1));\n
 testSubstituteConfirm(\'ex_substitute_confirm_quit\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb a\\nbab\', \'yq\', makeCursor(0, 3));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb a\\nbab\', \'yq\', makeCursor(0, 3));\n
 testSubstituteConfirm(\'ex_substitute_confirm_last\',\n
-    \'%s/a/b/c\', \'ba a\\nbab\', \'bb b\\nbab\', \'yl\', makeCursor(0, 3));\n
+    \'%s/a/b/cg\', \'ba a\\nbab\', \'bb b\\nbab\', \'yl\', makeCursor(0, 3));\n
 testSubstituteConfirm(\'ex_substitute_confirm_oneline\',\n
-    \'1s/a/b/c\', \'ba a\\nbab\', \'bb b\\nbab\', \'yl\', makeCursor(0, 3));\n
+    \'1s/a/b/cg\', \'ba a\\nbab\', \'bb b\\nbab\', \'yl\', makeCursor(0, 3));\n
 testSubstituteConfirm(\'ex_substitute_confirm_range_accept\',\n
-    \'1,2s/a/b/c\', \'aa\\na \\na\\na\', \'bb\\nb \\na\\na\', \'yyy\', makeCursor(1, 0));\n
+    \'1,2s/a/b/cg\', \'aa\\na \\na\\na\', \'bb\\nb \\na\\na\', \'yyy\', makeCursor(1, 0));\n
 testSubstituteConfirm(\'ex_substitute_confirm_range_some\',\n
-    \'1,3s/a/b/c\', \'aa\\na \\na\\na\', \'ba\\nb \\nb\\na\', \'ynyy\', makeCursor(2, 0));\n
+    \'1,3s/a/b/cg\', \'aa\\na \\na\\na\', \'ba\\nb \\nb\\na\', \'ynyy\', makeCursor(2, 0));\n
 testSubstituteConfirm(\'ex_substitute_confirm_range_all\',\n
-    \'1,3s/a/b/c\', \'aa\\na \\na\\na\', \'bb\\nb \\nb\\na\', \'a\', makeCursor(2, 0));\n
+    \'1,3s/a/b/cg\', \'aa\\na \\na\\na\', \'bb\\nb \\nb\\na\', \'a\', makeCursor(2, 0));\n
 testSubstituteConfirm(\'ex_substitute_confirm_range_last\',\n
-    \'1,3s/a/b/c\', \'aa\\na \\na\\na\', \'bb\\nb \\na\\na\', \'yyl\', makeCursor(1, 0));\n
+    \'1,3s/a/b/cg\', \'aa\\na \\na\\na\', \'bb\\nb \\na\\na\', \'yyl\', makeCursor(1, 0));\n
 //:noh should clear highlighting of search-results but allow to resume search through n\n
 testVim(\'ex_noh_clearSearchHighlight\', function(cm, vim, helpers) {\n
   cm.openDialog = helpers.fakeOpenDialog(\'match\');\n
@@ -2582,6 +3641,63 @@ testVim(\'ex_noh_clearSearchHighlight\', function(cm, vim, helpers) {\n
   helpers.doKeys(\'n\');\n
   helpers.assertCursorAt(0, 11,\'can\\\'t resume search after clearing highlighting\');\n
 }, { value: \'match nope match \\n nope Match\' });\n
+testVim(\'set_boolean\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.defineOption(\'testoption\', true, \'boolean\');\n
+  // Test default value is set.\n
+  is(CodeMirror.Vim.getOption(\'testoption\'));\n
+  try {\n
+    // Test fail to set to non-boolean\n
+    CodeMirror.Vim.setOption(\'testoption\', \'5\');\n
+    fail();\n
+  } catch (expected) {};\n
+  // Test setOption\n
+  CodeMirror.Vim.setOption(\'testoption\', false);\n
+  is(!CodeMirror.Vim.getOption(\'testoption\'));\n
+});\n
+testVim(\'ex_set_boolean\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.defineOption(\'testoption\', true, \'boolean\');\n
+  // Test default value is set.\n
+  is(CodeMirror.Vim.getOption(\'testoption\'));\n
+  try {\n
+    // Test fail to set to non-boolean\n
+    helpers.doEx(\'set testoption=22\');\n
+    fail();\n
+  } catch (expected) {};\n
+  // Test setOption\n
+  helpers.doEx(\'set notestoption\');\n
+  is(!CodeMirror.Vim.getOption(\'testoption\'));\n
+});\n
+testVim(\'set_string\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.defineOption(\'testoption\', \'a\', \'string\');\n
+  // Test default value is set.\n
+  eq(\'a\', CodeMirror.Vim.getOption(\'testoption\'));\n
+  try {\n
+    // Test fail to set non-string.\n
+    CodeMirror.Vim.setOption(\'testoption\', true);\n
+    fail();\n
+  } catch (expected) {};\n
+  try {\n
+    // Test fail to set \'notestoption\'\n
+    CodeMirror.Vim.setOption(\'notestoption\', \'b\');\n
+    fail();\n
+  } catch (expected) {};\n
+  // Test setOption\n
+  CodeMirror.Vim.setOption(\'testoption\', \'c\');\n
+  eq(\'c\', CodeMirror.Vim.getOption(\'testoption\'));\n
+});\n
+testVim(\'ex_set_string\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.defineOption(\'testoption\', \'a\', \'string\');\n
+  // Test default value is set.\n
+  eq(\'a\', CodeMirror.Vim.getOption(\'testoption\'));\n
+  try {\n
+    // Test fail to set \'notestoption\'\n
+    helpers.doEx(\'set notestoption=b\');\n
+    fail();\n
+  } catch (expected) {};\n
+  // Test setOption\n
+  helpers.doEx(\'set testoption=c\')\n
+  eq(\'c\', CodeMirror.Vim.getOption(\'testoption\'));\n
+});\n
 // TODO: Reset key maps after each test.\n
 testVim(\'ex_map_key2key\', function(cm, vim, helpers) {\n
   helpers.doEx(\'map a x\');\n
@@ -2589,6 +3705,19 @@ testVim(\'ex_map_key2key\', function(cm, vim, helpers) {\n
   helpers.assertCursorAt(0, 0);\n
   eq(\'bc\', cm.getValue());\n
 }, { value: \'abc\' });\n
+testVim(\'ex_unmap_key2key\', function(cm, vim, helpers) {\n
+  helpers.doEx(\'unmap a\');\n
+  helpers.doKeys(\'a\');\n
+  eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
+}, { value: \'abc\' });\n
+testVim(\'ex_unmap_key2key_does_not_remove_default\', function(cm, vim, helpers) {\n
+  try {\n
+    helpers.doEx(\'unmap a\');\n
+    fail();\n
+  } catch (expected) {}\n
+  helpers.doKeys(\'a\');\n
+  eq(\'vim-insert\', cm.getOption(\'keyMap\'));\n
+}, { value: \'abc\' });\n
 testVim(\'ex_map_key2key_to_colon\', function(cm, vim, helpers) {\n
   helpers.doEx(\'map ; :\');\n
   var dialogOpened = false;\n
@@ -2651,6 +3780,13 @@ testVim(\'ex_map_key2key_visual_api\', function(cm, vim, helpers) {\n
 \n
   CodeMirror.commands.save = tmp;\n
 });\n
+testVim(\'ex_imap\', function(cm, vim, helpers) {\n
+  CodeMirror.Vim.map(\'jk\', \'<Esc>\', \'insert\');\n
+  helpers.doKeys(\'i\');\n
+  is(vim.insertMode);\n
+  helpers.doKeys(\'j\', \'k\');\n
+  is(!vim.insertMode);\n
+})\n
 \n
 // Testing registration of functions as ex-commands and mapping to <Key>-keys\n
 testVim(\'ex_api_test\', function(cm, vim, helpers) {\n
@@ -2673,6 +3809,14 @@ testVim(\'ex_map_key2key_from_colon\', function(cm, vim, helpers) {\n
   helpers.assertCursorAt(0, 0);\n
   eq(\'bc\', cm.getValue());\n
 }, { value: \'abc\' });\n
+\n
+// Test event handlers\n
+testVim(\'beforeSelectionChange\', function(cm, vim, helpers) {\n
+  cm.setCursor(0, 100);\n
+  eqPos(cm.getCursor(\'head\'), cm.getCursor(\'anchor\'));\n
+}, { value: \'abc\' });\n
+\n
+\n
 
 
 ]]></string> </value>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-day.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-day.css.xml
index c4d86c8b94e3a35c3a5053eb34c51d3e30a09033..96477467418d4952ebc17b6d84496ff5ca42b678 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-day.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-day.css.xml
@@ -36,8 +36,12 @@
 \n
 .cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;}\n
 .cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;}\n
+\n
 .cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;}\n
+.cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; }\n
+.cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; }\n
 .cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;}\n
+\n
 .cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;}\n
 \n
 .cm-s-3024-day span.cm-comment {color: #cdab53;}\n
@@ -57,7 +61,7 @@
 .cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;}\n
 \n
 .cm-s-3024-day .CodeMirror-activeline-background {background: #e8f2ff !important;}\n
-.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}\n
+.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important;}\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-night.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-night.css.xml
index b65f36d10f05a4ed8bffe690d8b2db36be05f84d..e2d7303943c42ef174b112ae544418eff615dc0a 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-night.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/3024-night.css.xml
@@ -37,7 +37,10 @@
 .cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;}\n
 .cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;}\n
 .cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;}\n
+.cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; }\n
+.cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; }\n
 .cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;}\n
+\n
 .cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;}\n
 \n
 .cm-s-3024-night span.cm-comment {color: #cdab53;}\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/ambiance.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/ambiance.css.xml
index 459f4df67e94a0a42c6ca76de42550effc4ba253..781673f66dc1c16915fc982aa06d54149a8a0db2 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/ambiance.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/ambiance.css.xml
@@ -67,7 +67,6 @@
 \n
 .cm-s-ambiance.CodeMirror {\n
   line-height: 1.40em;\n
-  font-family: Monaco, Menlo,"Andale Mono","lucida console","Courier New",monospace !important;\n
   color: #E6E1DC;\n
   background-color: #202020;\n
   -webkit-box-shadow: inset 0 0 10px black;\n
@@ -83,10 +82,13 @@
 \n
 .cm-s-ambiance .CodeMirror-linenumber {\n
   text-shadow: 0px 1px 1px #4d4d4d;\n
-  color: #222;\n
+  color: #111;\n
   padding: 0 5px;\n
 }\n
 \n
+.cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; }\n
+.cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; }\n
+\n
 .cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor {\n
   border-left: 1px solid #7991E8;\n
 }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-dark.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-dark.css.xml
index 26cf7467a8f54f528dd54d3734c6d089840bad94..095fc42504081b50cd12ae17e53fd1e8abe8ae4b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-dark.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-dark.css.xml
@@ -35,8 +35,10 @@
 */\n
 \n
 .cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;}\n
-.cm-s-base16-dark div.CodeMirror-selected {background: #202020 !important;}\n
+.cm-s-base16-dark div.CodeMirror-selected {background: #303030 !important;}\n
 .cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;}\n
+.cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; }\n
+.cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; }\n
 .cm-s-base16-dark .CodeMirror-linenumber {color: #505050;}\n
 .cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;}\n
 \n
@@ -56,7 +58,7 @@
 .cm-s-base16-dark span.cm-link {color: #aa759f;}\n
 .cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;}\n
 \n
-.cm-s-base16-dark .CodeMirror-activeline-background {background: #2F2F2F !important;}\n
+.cm-s-base16-dark .CodeMirror-activeline-background {background: #202020 !important;}\n
 .cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}\n
 </string> </value>
         </item>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-light.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-light.css.xml
index 97108348421b36ea6711f3fc056da2c2dd4f0361..1ec0ef0ec6567cb41142828563bcbd664d88e1e5 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-light.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/base16-light.css.xml
@@ -37,6 +37,8 @@
 .cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;}\n
 .cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;}\n
 .cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;}\n
+.cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; }\n
+.cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; }\n
 .cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;}\n
 .cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;}\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/blackboard.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/blackboard.css.xml
index dcc9dde0cee2881f78811d07fafb14bfbf4c98b3..bbc95c0e0a3a12b4aa8673a6beffb2b16ed99ed8 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/blackboard.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/blackboard.css.xml
@@ -29,6 +29,8 @@
 .cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; }\n
 .cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }\n
 .cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; }\n
+.cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; }\n
+.cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; }\n
 .cm-s-blackboard .CodeMirror-linenumber { color: #888; }\n
 .cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/cobalt.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/cobalt.css.xml
index 0d5c8d78d4aaa1a1bdfbd5e5bdd7113e1936f631..eb3606eefb279258d32769b438594511b17e22ad 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/cobalt.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/cobalt.css.xml
@@ -27,6 +27,8 @@
             <value> <string>.cm-s-cobalt.CodeMirror { background: #002240; color: white; }\n
 .cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }\n
 .cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }\n
+.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; }\n
+.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n
 .cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; }\n
 .cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/erlang-dark.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/erlang-dark.css.xml
index a000016b5bca340f7844f3a1a881e6150129189e..405b2a6bdbb49f1e054baedb5a3875ffb3c05b33 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/erlang-dark.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/erlang-dark.css.xml
@@ -27,6 +27,8 @@
             <value> <string>.cm-s-erlang-dark.CodeMirror { background: #002240; color: white; }\n
 .cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }\n
 .cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }\n
+.cm-s-erlang-dark .CodeMirror-guttermarker { color: white; }\n
+.cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n
 .cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; }\n
 .cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/lesser-dark.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/lesser-dark.css.xml
index 45bd11e01860ccd8d6685d7da0214ecc9679dfbb..922a406540d8553162c30800d5f77fbb90e1abb7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/lesser-dark.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/lesser-dark.css.xml
@@ -31,10 +31,6 @@ Ported to CodeMirror by Peter Kroon\n
 .cm-s-lesser-dark {\n
   line-height: 1.3em;\n
 }\n
-.cm-s-lesser-dark {\n
-  font-family: \'Bitstream Vera Sans Mono\', \'DejaVu Sans Mono\', \'Monaco\', Courier, monospace !important;\n
-}\n
-\n
 .cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }\n
 .cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/\n
 .cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }\n
@@ -43,6 +39,8 @@ Ported to CodeMirror by Peter Kroon\n
 .cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/\n
 \n
 .cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; }\n
+.cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; }\n
+.cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; }\n
 .cm-s-lesser-dark .CodeMirror-linenumber { color: #777; }\n
 \n
 .cm-s-lesser-dark span.cm-keyword { color: #599eff; }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mbo.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mbo.css.xml
index beed37da96762d9563bb5e80531da378ff91de65..6564ca724f41f56822951fd5392c409bad8bdb2b 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mbo.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mbo.css.xml
@@ -24,11 +24,17 @@
         </item>
         <item>
             <key> <string>raw</string> </key>
-            <value> <string>/* Based on mbonaci\'s Brackets mbo theme */\n
+            <value> <string>/****************************************************************/\n
+/*   Based on mbonaci\'s Brackets mbo theme                      */\n
+/*   https://github.com/mbonaci/global/blob/master/Mbo.tmTheme  */\n
+/*   Create your own: http://tmtheme-editor.herokuapp.com       */\n
+/****************************************************************/\n
 \n
-.cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffe9;}\n
+.cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffec;}\n
 .cm-s-mbo div.CodeMirror-selected {background: #716C62 !important;}\n
 .cm-s-mbo .CodeMirror-gutters {background: #4e4e4e; border-right: 0px;}\n
+.cm-s-mbo .CodeMirror-guttermarker { color: white; }\n
+.cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; }\n
 .cm-s-mbo .CodeMirror-linenumber {color: #dadada;}\n
 .cm-s-mbo .CodeMirror-cursor {border-left: 1px solid #ffffec !important;}\n
 \n
@@ -39,6 +45,7 @@
 .cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute {color: #9ddfe9;}\n
 .cm-s-mbo span.cm-keyword {color: #ffb928;}\n
 .cm-s-mbo span.cm-string {color: #ffcf6c;}\n
+.cm-s-mbo span.cm-string.cm-property {color: #ffffec;}\n
 \n
 .cm-s-mbo span.cm-variable {color: #ffffec;}\n
 .cm-s-mbo span.cm-variable-2 {color: #00a8c6;}\n
@@ -46,21 +53,12 @@
 .cm-s-mbo span.cm-bracket {color: #fffffc; font-weight: bold;}\n
 .cm-s-mbo span.cm-tag {color: #9ddfe9;}\n
 .cm-s-mbo span.cm-link {color: #f54b07;}\n
-.cm-s-mbo span.cm-error {background: #636363; color: #ffffec;}\n
+.cm-s-mbo span.cm-error {border-bottom: #636363; color: #ffffec;}\n
+.cm-s-mbo span.cm-qualifier {color: #ffffec;}\n
 \n
 .cm-s-mbo .CodeMirror-activeline-background {background: #494b41 !important;}\n
-.cm-s-mbo .CodeMirror-matchingbracket {\n
-  text-decoration: underline;\n
-  color: #f5e107 !important;\n
- }\n
- \n
-.cm-s-mbo .CodeMirror-matchingtag {background: #4e4e4e;}\n
-\n
-.cm-s-mbo span.cm-searching {\n
-  background-color: none;\n
-  background: none;\n
-  box-shadow: 0 0 0 1px #ffffec;\n
-}\n
+.cm-s-mbo .CodeMirror-matchingbracket {color: #222 !important;}\n
+.cm-s-mbo .CodeMirror-matchingtag {background: rgba(255, 255, 255, .37);}\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mdn-like.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mdn-like.css.xml
index 734dc2c1179e2259a9bc408d6abc4c3ad90a1ad5..8584ff95255f1a3b6385e6549b510e96cea8cfb7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mdn-like.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/mdn-like.css.xml
@@ -29,13 +29,13 @@
 /*\n
   MDN-LIKE Theme - Mozilla\n
   Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>\n
-  Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues\n
+  Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues\n
   GitHub: @peterkroon\n
 \n
   The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation\n
 \n
 */\n
-.cm-s-mdn-like.CodeMirror { color: #999; font-family: monospace; background-color: #fff; }\n
+.cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; }\n
 .cm-s-mdn-like .CodeMirror-selected { background: #cfc !important; }\n
 \n
 .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/midnight.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/midnight.css.xml
index 50e0c81fca5e82e27f3ea2649a33c93d1288f9af..ad3e02b1287adc138b52a8a58eb91181c42dd623 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/midnight.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/midnight.css.xml
@@ -44,6 +44,8 @@
 \n
 .cm-s-midnight div.CodeMirror-selected {background: #314D67 !important;}\n
 .cm-s-midnight .CodeMirror-gutters {background: #0F192A; border-right: 1px solid;}\n
+.cm-s-midnight .CodeMirror-guttermarker { color: white; }\n
+.cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n
 .cm-s-midnight .CodeMirror-linenumber {color: #D0D0D0;}\n
 .cm-s-midnight .CodeMirror-cursor {\n
     border-left: 1px solid #F8F8F0 !important;\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/monokai.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/monokai.css.xml
index 3f3eb22395a1f5a1dc73766cae43993dbdb9c3af..ba6425ebe332d296a03d171c83d6c85a2300a8e7 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/monokai.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/monokai.css.xml
@@ -29,6 +29,8 @@
 .cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2;}\n
 .cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}\n
 .cm-s-monokai .CodeMirror-gutters {background: #272822; border-right: 0px;}\n
+.cm-s-monokai .CodeMirror-guttermarker { color: white; }\n
+.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n
 .cm-s-monokai .CodeMirror-linenumber {color: #d0d0d0;}\n
 .cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/neo.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/neo.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..61926a621100cf7d9a3cd36b4a8999026e8a94be
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/neo.css.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>neo.css</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>/* neo theme for codemirror */\n
+\n
+/* Color scheme */\n
+\n
+.cm-s-neo.CodeMirror {\n
+  background-color:#ffffff;\n
+  color:#2e383c;\n
+  line-height:1.4375;\n
+}\n
+.cm-s-neo .cm-comment {color:#75787b}\n
+.cm-s-neo .cm-keyword, .cm-s-neo .cm-property {color:#1d75b3}\n
+.cm-s-neo .cm-atom,.cm-s-neo .cm-number {color:#75438a}\n
+.cm-s-neo .cm-node,.cm-s-neo .cm-tag {color:#9c3328}\n
+.cm-s-neo .cm-string {color:#b35e14}\n
+.cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier {color:#047d65}\n
+\n
+\n
+/* Editor styling */\n
+\n
+.cm-s-neo pre {\n
+  padding:0;\n
+}\n
+\n
+.cm-s-neo .CodeMirror-gutters {\n
+  border:none;\n
+  border-right:10px solid transparent;\n
+  background-color:transparent;\n
+}\n
+\n
+.cm-s-neo .CodeMirror-linenumber {\n
+  padding:0;\n
+  color:#e0e2e5;\n
+}\n
+\n
+.cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; }\n
+.cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; }\n
+\n
+.cm-s-neo div.CodeMirror-cursor {\n
+  width: auto;\n
+  border: 0;\n
+  background: rgba(155,157,162,0.37);\n
+  z-index: 1;\n
+}\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/night.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/night.css.xml
index 6aff244114f5eb37d011f4d69e9694df60ec0d8b..38e02619d650b34e57f5ae7201c34b23dda7f53f 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/night.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/night.css.xml
@@ -29,6 +29,8 @@
 .cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; }\n
 .cm-s-night div.CodeMirror-selected { background: #447 !important; }\n
 .cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }\n
+.cm-s-night .CodeMirror-guttermarker { color: white; }\n
+.cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; }\n
 .cm-s-night .CodeMirror-linenumber { color: #f8f8f8; }\n
 .cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-dark.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-dark.css.xml
index a34720f29ba2f5d42ab2ba3d1e77b2f79e5103ad..c4e5343db95da24715af6be1af572931499069de 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-dark.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-dark.css.xml
@@ -37,6 +37,8 @@
 .cm-s-paraiso-dark.CodeMirror {background: #2f1e2e; color: #b9b6b0;}\n
 .cm-s-paraiso-dark div.CodeMirror-selected {background: #41323f !important;}\n
 .cm-s-paraiso-dark .CodeMirror-gutters {background: #2f1e2e; border-right: 0px;}\n
+.cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; }\n
+.cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; }\n
 .cm-s-paraiso-dark .CodeMirror-linenumber {color: #776e71;}\n
 .cm-s-paraiso-dark .CodeMirror-cursor {border-left: 1px solid #8d8687 !important;}\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-light.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-light.css.xml
index 28ed424b1db094e1024d331e342ed5683b8d2df5..b2c1dc60aced4365dc16e56d650d583ce17e8698 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-light.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/paraiso-light.css.xml
@@ -37,6 +37,8 @@
 .cm-s-paraiso-light.CodeMirror {background: #e7e9db; color: #41323f;}\n
 .cm-s-paraiso-light div.CodeMirror-selected {background: #b9b6b0 !important;}\n
 .cm-s-paraiso-light .CodeMirror-gutters {background: #e7e9db; border-right: 0px;}\n
+.cm-s-paraiso-light .CodeMirror-guttermarker { color: black; }\n
+.cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; }\n
 .cm-s-paraiso-light .CodeMirror-linenumber {color: #8d8687;}\n
 .cm-s-paraiso-light .CodeMirror-cursor {border-left: 1px solid #776e71 !important;}\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/pastel-on-dark.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/pastel-on-dark.css.xml
index f85a0e0d3deacd35a2faa555831f4129aaa1a100..a1504e7c674a48fc8b83e49788e2013e8f7132d8 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/pastel-on-dark.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/pastel-on-dark.css.xml
@@ -37,7 +37,6 @@
 \tbackground: #2c2827;\n
 \tcolor: #8F938F;\n
 \tline-height: 1.5;\n
-\tfont-family: consolas, Courier, monospace;\n
 \tfont-size: 14px;\n
 }\n
 .cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2) !important; }\n
@@ -46,6 +45,8 @@
 \tborder-right: 0px;\n
 \tpadding: 0 3px;\n
 }\n
+.cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; }\n
+.cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; }\n
 .cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; }\n
 .cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }\n
 .cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; }\n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/rubyblue.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/rubyblue.css.xml
index 86c5d0e5758cc662d06e533bf82d7b3a6c1bc726..d1dd43885ba763c690349f2818b825da2869246c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/rubyblue.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/rubyblue.css.xml
@@ -24,11 +24,11 @@
         </item>
         <item>
             <key> <string>raw</string> </key>
-            <value> <string>.cm-s-rubyblue { font-family: Trebuchet, Verdana, sans-serif; }\t/* - customized editor font - */\n
-\n
-.cm-s-rubyblue.CodeMirror { background: #112435; color: white; }\n
+            <value> <string>.cm-s-rubyblue.CodeMirror { background: #112435; color: white; }\n
 .cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }\n
 .cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; }\n
+.cm-s-rubyblue .CodeMirror-guttermarker { color: white; }\n
+.cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; }\n
 .cm-s-rubyblue .CodeMirror-linenumber { color: white; }\n
 .cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/solarized.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/solarized.css.xml
index 128cd4a4e53211764b7d34cabc1a0af8087740b0..88115ab67bb437a4cc8c35045d9a881c98207290 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/solarized.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/solarized.css.xml
@@ -55,7 +55,6 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png\n
 \n
 .cm-s-solarized {\n
   line-height: 1.45em;\n
-  font-family: Menlo,Monaco,"Andale Mono","lucida console","Courier New",monospace !important;\n
   color-profile: sRGB;\n
   rendering-intent: auto;\n
 }\n
@@ -115,11 +114,6 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png\n
   text-decoration-style: dotted;\n
 }\n
 .cm-s-solarized .cm-strong { color: #eee; }\n
-.cm-s-solarized .cm-tab:before {\n
-  content: "鉃�";   /*visualize tab character*/\n
-  color: #586e75;\n
-  position:absolute;\n
-}\n
 .cm-s-solarized .cm-error,\n
 .cm-s-solarized .cm-invalidchar {\n
   color: #586e75;\n
@@ -147,8 +141,6 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png\n
 \n
 /* Gutter border and some shadow from it  */\n
 .cm-s-solarized .CodeMirror-gutters {\n
-  padding: 0 15px 0 10px;\n
-  box-shadow: 0 10px 20px black;\n
   border-right: 1px solid;\n
 }\n
 \n
@@ -156,7 +148,7 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png\n
 \n
 /* Dark */\n
 .cm-s-solarized.cm-s-dark .CodeMirror-gutters {\n
-  background-color: #073642;\n
+  background-color:  #002b36;\n
   border-color: #00232c;\n
 }\n
 \n
@@ -166,23 +158,23 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png\n
 \n
 /* Light */\n
 .cm-s-solarized.cm-s-light .CodeMirror-gutters {\n
-  background-color: #eee8d5;\n
+  background-color: #fdf6e3;\n
   border-color: #eee8d5;\n
 }\n
 \n
 /* Common */\n
 .cm-s-solarized .CodeMirror-linenumber {\n
   color: #586e75;\n
+  padding: 0 5px;\n
 }\n
+.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }\n
+.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }\n
+.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }\n
 \n
 .cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {\n
   color: #586e75;\n
 }\n
 \n
-.cm-s-solarized .CodeMirror-lines {\n
-  padding-left: 5px;\n
-}\n
-\n
 .cm-s-solarized .CodeMirror-lines .CodeMirror-cursor {\n
   border-left: 1px solid #819090;\n
 }\n
@@ -197,14 +189,6 @@ view-port\n
 .cm-s-solarized.cm-s-light .CodeMirror-activeline-background {\n
   background: rgba(0, 0, 0, 0.10);\n
 }\n
-\n
-/*\n
-View-port and gutter both get little noise background to give it a real feel.\n
-*/\n
-.cm-s-solarized.CodeMirror,\n
-.cm-s-solarized .CodeMirror-gutters {\n
-  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC");\n
-}\n
 </string> </value>
         </item>
       </dictionary>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/the-matrix.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/the-matrix.css.xml
index a67a05fc26535f1ebaeafcbcc8d61bb581b9b0db..3787e95321e6377001795dd2cd56bcc2d85b14aa 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/the-matrix.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/the-matrix.css.xml
@@ -27,6 +27,8 @@
             <value> <string>.cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; }\n
 .cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D !important; }\n
 .cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; }\n
+.cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; }\n
+.cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; }\n
 .cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; }\n
 .cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00 !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-bright.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-bright.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9fb203b6059dc333a3f51d83fefa115060335bac
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-bright.css.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>tomorrow-night-bright.css</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*\n
+\n
+    Name:       Tomorrow Night - Bright\n
+    Author:     Chris Kempson\n
+\n
+    Port done by Gerard Braad <me@gbraad.nl>\n
+\n
+*/\n
+\n
+.cm-s-tomorrow-night-bright.CodeMirror {background: #000000; color: #eaeaea;}\n
+.cm-s-tomorrow-night-bright div.CodeMirror-selected {background: #424242 !important;}\n
+.cm-s-tomorrow-night-bright .CodeMirror-gutters {background: #000000; border-right: 0px;}\n
+.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }\n
+.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }\n
+.cm-s-tomorrow-night-bright .CodeMirror-linenumber {color: #424242;}\n
+.cm-s-tomorrow-night-bright .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}\n
+\n
+.cm-s-tomorrow-night-bright span.cm-comment {color: #d27b53;}\n
+.cm-s-tomorrow-night-bright span.cm-atom {color: #a16a94;}\n
+.cm-s-tomorrow-night-bright span.cm-number {color: #a16a94;}\n
+\n
+.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute {color: #99cc99;}\n
+.cm-s-tomorrow-night-bright span.cm-keyword {color: #d54e53;}\n
+.cm-s-tomorrow-night-bright span.cm-string {color: #e7c547;}\n
+\n
+.cm-s-tomorrow-night-bright span.cm-variable {color: #b9ca4a;}\n
+.cm-s-tomorrow-night-bright span.cm-variable-2 {color: #7aa6da;}\n
+.cm-s-tomorrow-night-bright span.cm-def {color: #e78c45;}\n
+.cm-s-tomorrow-night-bright span.cm-bracket {color: #eaeaea;}\n
+.cm-s-tomorrow-night-bright span.cm-tag {color: #d54e53;}\n
+.cm-s-tomorrow-night-bright span.cm-link {color: #a16a94;}\n
+.cm-s-tomorrow-night-bright span.cm-error {background: #d54e53; color: #6A6A6A;}\n
+\n
+.cm-s-tomorrow-night-bright .CodeMirror-activeline-background {background: #2a2a2a !important;}\n
+.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-eighties.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-eighties.css.xml
index 62533307d097c19798ee753ad97e71caa91fa1a3..42d2b6ef7af2451ad87570a1e3c446c46f5a3300 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-eighties.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/tomorrow-night-eighties.css.xml
@@ -37,6 +37,8 @@
 .cm-s-tomorrow-night-eighties.CodeMirror {background: #000000; color: #CCCCCC;}\n
 .cm-s-tomorrow-night-eighties div.CodeMirror-selected {background: #2D2D2D !important;}\n
 .cm-s-tomorrow-night-eighties .CodeMirror-gutters {background: #000000; border-right: 0px;}\n
+.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }\n
+.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }\n
 .cm-s-tomorrow-night-eighties .CodeMirror-linenumber {color: #515151;}\n
 .cm-s-tomorrow-night-eighties .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/twilight.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/twilight.css.xml
index e3e1d245a895e2be144b145f657c3889926c737f..e349e35ea8405d72eaae2a6e8bd5b0ae937a489e 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/twilight.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/twilight.css.xml
@@ -28,6 +28,8 @@
 .cm-s-twilight .CodeMirror-selected { background: #323232 !important; } /**/\n
 \n
 .cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; }\n
+.cm-s-twilight .CodeMirror-guttermarker { color: white; }\n
+.cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; }\n
 .cm-s-twilight .CodeMirror-linenumber { color: #aaa; }\n
 .cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/vibrant-ink.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/vibrant-ink.css.xml
index 464a4ee22ed2470f98917cab3f4b481948cd45d9..1614152f2a4f82e96a2125129464625fe7c92a5c 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/vibrant-ink.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/vibrant-ink.css.xml
@@ -30,6 +30,8 @@
 .cm-s-vibrant-ink .CodeMirror-selected { background: #35493c !important; }\n
 \n
 .cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }\n
+.cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; }\n
+.cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n
 .cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; }\n
 .cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/xq-dark.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/xq-dark.css.xml
index b39393ad1b9aa70a4b0fb2c6bdf3d1bcd43e644b..b8d28149dc9375ce73482e5a48d12bb077247d82 100644
--- a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/xq-dark.css.xml
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/xq-dark.css.xml
@@ -51,6 +51,8 @@ THE SOFTWARE.\n
 .cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; }\n
 .cm-s-xq-dark .CodeMirror-selected { background: #27007A !important; }\n
 .cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }\n
+.cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; }\n
+.cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; }\n
 .cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; }\n
 .cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }\n
 \n
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/zenburn.css.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/zenburn.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fbd2c53f8bdabc5e2ab237f968446896a976ebec
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/codemirror/theme/zenburn.css.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>zenburn.css</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>/**\n
+ * "\n
+ *  Using Zenburn color palette from the Emacs Zenburn Theme\n
+ *  https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el\n
+ *\n
+ *  Also using parts of https://github.com/xavi/coderay-lighttable-theme\n
+ * "\n
+ * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css\n
+ */\n
+\n
+.cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; }\n
+.cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; }\n
+.cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white !important; }\n
+.cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; }\n
+.cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; }\n
+.cm-s-zenburn span.cm-comment { color: #7f9f7f; }\n
+.cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; }\n
+.cm-s-zenburn span.cm-atom { color: #bfebbf; }\n
+.cm-s-zenburn span.cm-def { color: #dcdccc; }\n
+.cm-s-zenburn span.cm-variable { color: #dfaf8f; }\n
+.cm-s-zenburn span.cm-variable-2 { color: #dcdccc; }\n
+.cm-s-zenburn span.cm-string { color: #cc9393; }\n
+.cm-s-zenburn span.cm-string-2 { color: #cc9393; }\n
+.cm-s-zenburn span.cm-number { color: #dcdccc; }\n
+.cm-s-zenburn span.cm-tag { color: #93e0e3; }\n
+.cm-s-zenburn span.cm-property { color: #dfaf8f; }\n
+.cm-s-zenburn span.cm-attribute { color: #dfaf8f; }\n
+.cm-s-zenburn span.cm-qualifier { color: #7cb8bb; }\n
+.cm-s-zenburn span.cm-meta { color: #f0dfaf; }\n
+.cm-s-zenburn span.cm-header { color: #f0efd0; }\n
+.cm-s-zenburn span.cm-operator { color: #f0efd0; }\n
+.cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; }\n
+.cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; }\n
+.cm-s-zenburn .CodeMirror-activeline { background: #000000; }\n
+.cm-s-zenburn .CodeMirror-activeline-background { background: #000000; }\n
+.cm-s-zenburn .CodeMirror-selected { background: #545454; }\n
+.cm-s-zenburn .CodeMirror-focused .CodeMirror-selected { background: #4f4f4f; }\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c441fda612439b8cc9c464af02ddd292b6968ee3
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>diff_match_patch</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/COPYING.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/COPYING.xml
new file mode 100644
index 0000000000000000000000000000000000000000..56f35ea2bbd3842367ae9164ff93171d2fcbd08c
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/COPYING.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>COPYING</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>\n
+                                 Apache License\n
+                           Version 2.0, January 2004\n
+                        http://www.apache.org/licenses/\n
+\n
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n
+\n
+   1. Definitions.\n
+\n
+      "License" shall mean the terms and conditions for use, reproduction,\n
+      and distribution as defined by Sections 1 through 9 of this document.\n
+\n
+      "Licensor" shall mean the copyright owner or entity authorized by\n
+      the copyright owner that is granting the License.\n
+\n
+      "Legal Entity" shall mean the union of the acting entity and all\n
+      other entities that control, are controlled by, or are under common\n
+      control with that entity. For the purposes of this definition,\n
+      "control" means (i) the power, direct or indirect, to cause the\n
+      direction or management of such entity, whether by contract or\n
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n
+      outstanding shares, or (iii) beneficial ownership of such entity.\n
+\n
+      "You" (or "Your") shall mean an individual or Legal Entity\n
+      exercising permissions granted by this License.\n
+\n
+      "Source" form shall mean the preferred form for making modifications,\n
+      including but not limited to software source code, documentation\n
+      source, and configuration files.\n
+\n
+      "Object" form shall mean any form resulting from mechanical\n
+      transformation or translation of a Source form, including but\n
+      not limited to compiled object code, generated documentation,\n
+      and conversions to other media types.\n
+\n
+      "Work" shall mean the work of authorship, whether in Source or\n
+      Object form, made available under the License, as indicated by a\n
+      copyright notice that is included in or attached to the work\n
+      (an example is provided in the Appendix below).\n
+\n
+      "Derivative Works" shall mean any work, whether in Source or Object\n
+      form, that is based on (or derived from) the Work and for which the\n
+      editorial revisions, annotations, elaborations, or other modifications\n
+      represent, as a whole, an original work of authorship. For the purposes\n
+      of this License, Derivative Works shall not include works that remain\n
+      separable from, or merely link (or bind by name) to the interfaces of,\n
+      the Work and Derivative Works thereof.\n
+\n
+      "Contribution" shall mean any work of authorship, including\n
+      the original version of the Work and any modifications or additions\n
+      to that Work or Derivative Works thereof, that is intentionally\n
+      submitted to Licensor for inclusion in the Work by the copyright owner\n
+      or by an individual or Legal Entity authorized to submit on behalf of\n
+      the copyright owner. For the purposes of this definition, "submitted"\n
+      means any form of electronic, verbal, or written communication sent\n
+      to the Licensor or its representatives, including but not limited to\n
+      communication on electronic mailing lists, source code control systems,\n
+      and issue tracking systems that are managed by, or on behalf of, the\n
+      Licensor for the purpose of discussing and improving the Work, but\n
+      excluding communication that is conspicuously marked or otherwise\n
+      designated in writing by the copyright owner as "Not a Contribution."\n
+\n
+      "Contributor" shall mean Licensor and any individual or Legal Entity\n
+      on behalf of whom a Contribution has been received by Licensor and\n
+      subsequently incorporated within the Work.\n
+\n
+   2. Grant of Copyright License. Subject to the terms and conditions of\n
+      this License, each Contributor hereby grants to You a perpetual,\n
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n
+      copyright license to reproduce, prepare Derivative Works of,\n
+      publicly display, publicly perform, sublicense, and distribute the\n
+      Work and such Derivative Works in Source or Object form.\n
+\n
+   3. Grant of Patent License. Subject to the terms and conditions of\n
+      this License, each Contributor hereby grants to You a perpetual,\n
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n
+      (except as stated in this section) patent license to make, have made,\n
+      use, offer to sell, sell, import, and otherwise transfer the Work,\n
+      where such license applies only to those patent claims licensable\n
+      by such Contributor that are necessarily infringed by their\n
+      Contribution(s) alone or by combination of their Contribution(s)\n
+      with the Work to which such Contribution(s) was submitted. If You\n
+      institute patent litigation against any entity (including a\n
+      cross-claim or counterclaim in a lawsuit) alleging that the Work\n
+      or a Contribution incorporated within the Work constitutes direct\n
+      or contributory patent infringement, then any patent licenses\n
+      granted to You under this License for that Work shall terminate\n
+      as of the date such litigation is filed.\n
+\n
+   4. Redistribution. You may reproduce and distribute copies of the\n
+      Work or Derivative Works thereof in any medium, with or without\n
+      modifications, and in Source or Object form, provided that You\n
+      meet the following conditions:\n
+\n
+      (a) You must give any other recipients of the Work or\n
+          Derivative Works a copy of this License; and\n
+\n
+      (b) You must cause any modified files to carry prominent notices\n
+          stating that You changed the files; and\n
+\n
+      (c) You must retain, in the Source form of any Derivative Works\n
+          that You distribute, all copyright, patent, trademark, and\n
+          attribution notices from the Source form of the Work,\n
+          excluding those notices that do not pertain to any part of\n
+          the Derivative Works; and\n
+\n
+      (d) If the Work includes a "NOTICE" text file as part of its\n
+          distribution, then any Derivative Works that You distribute must\n
+          include a readable copy of the attribution notices contained\n
+          within such NOTICE file, excluding those notices that do not\n
+          pertain to any part of the Derivative Works, in at least one\n
+          of the following places: within a NOTICE text file distributed\n
+          as part of the Derivative Works; within the Source form or\n
+          documentation, if provided along with the Derivative Works; or,\n
+          within a display generated by the Derivative Works, if and\n
+          wherever such third-party notices normally appear. The contents\n
+          of the NOTICE file are for informational purposes only and\n
+          do not modify the License. You may add Your own attribution\n
+          notices within Derivative Works that You distribute, alongside\n
+          or as an addendum to the NOTICE text from the Work, provided\n
+          that such additional attribution notices cannot be construed\n
+          as modifying the License.\n
+\n
+      You may add Your own copyright statement to Your modifications and\n
+      may provide additional or different license terms and conditions\n
+      for use, reproduction, or distribution of Your modifications, or\n
+      for any such Derivative Works as a whole, provided Your use,\n
+      reproduction, and distribution of the Work otherwise complies with\n
+      the conditions stated in this License.\n
+\n
+   5. Submission of Contributions. Unless You explicitly state otherwise,\n
+      any Contribution intentionally submitted for inclusion in the Work\n
+      by You to the Licensor shall be under the terms and conditions of\n
+      this License, without any additional terms or conditions.\n
+      Notwithstanding the above, nothing herein shall supersede or modify\n
+      the terms of any separate license agreement you may have executed\n
+      with Licensor regarding such Contributions.\n
+\n
+   6. Trademarks. This License does not grant permission to use the trade\n
+      names, trademarks, service marks, or product names of the Licensor,\n
+      except as required for reasonable and customary use in describing the\n
+      origin of the Work and reproducing the content of the NOTICE file.\n
+\n
+   7. Disclaimer of Warranty. Unless required by applicable law or\n
+      agreed to in writing, Licensor provides the Work (and each\n
+      Contributor provides its Contributions) on an "AS IS" BASIS,\n
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n
+      implied, including, without limitation, any warranties or conditions\n
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n
+      PARTICULAR PURPOSE. You are solely responsible for determining the\n
+      appropriateness of using or redistributing the Work and assume any\n
+      risks associated with Your exercise of permissions under this License.\n
+\n
+   8. Limitation of Liability. In no event and under no legal theory,\n
+      whether in tort (including negligence), contract, or otherwise,\n
+      unless required by applicable law (such as deliberate and grossly\n
+      negligent acts) or agreed to in writing, shall any Contributor be\n
+      liable to You for damages, including any direct, indirect, special,\n
+      incidental, or consequential damages of any character arising as a\n
+      result of this License or out of the use or inability to use the\n
+      Work (including but not limited to damages for loss of goodwill,\n
+      work stoppage, computer failure or malfunction, or any and all\n
+      other commercial damages or losses), even if such Contributor\n
+      has been advised of the possibility of such damages.\n
+\n
+   9. Accepting Warranty or Additional Liability. While redistributing\n
+      the Work or Derivative Works thereof, You may choose to offer,\n
+      and charge a fee for, acceptance of support, warranty, indemnity,\n
+      or other liability obligations and/or rights consistent with this\n
+      License. However, in accepting such obligations, You may act only\n
+      on Your own behalf and on Your sole responsibility, not on behalf\n
+      of any other Contributor, and only if You agree to indemnify,\n
+      defend, and hold each Contributor harmless for any liability\n
+      incurred by, or claims asserted against, such Contributor by reason\n
+      of your accepting any such warranty or additional liability.\n
+\n
+   END OF TERMS AND CONDITIONS\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/README.txt.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/README.txt.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5770442074dc12b04a596f7641c3344a39472aa2
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/README.txt.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="DTMLMethod" module="OFS.DTMLMethod"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>README.txt</string> </value>
+        </item>
+        <item>
+            <key> <string>_vars</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>globals</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>raw</string> </key>
+            <value> <string>Diff, Match and Patch Library\n
+http://code.google.com/p/google-diff-match-patch/\n
+Neil Fraser\n
+\n
+This library is currently available in seven different ports, all using the same API.\n
+Every version includes a full set of unit tests.\n
+\n
+C++:\n
+* Ported by Mike Slemmer.\n
+* Currently requires the Qt library.\n
+\n
+C#:\n
+* Ported by Matthaeus G. Chajdas.\n
+\n
+Dart:\n
+* The Dart language is still growing and evolving, so this port is only as\n
+  stable as the underlying language.\n
+\n
+Java:\n
+* Included is both the source and a Maven package.\n
+\n
+JavaScript:\n
+* diff_match_patch_uncompressed.js is the human-readable version.\n
+  Users of node.js should \'require\' this uncompressed version since the\n
+  compressed version is not guaranteed to work outside of a web browser.\n
+* diff_match_patch.js has been compressed using Google\'s internal JavaScript compressor.\n
+  Non-Google hackers who wish to recompress the source can use:\n
+  http://dean.edwards.name/packer/\n
+\n
+Lua:\n
+* Ported by Duncan Cross.\n
+* Does not support line-mode speedup.\n
+\n
+Objective C:\n
+* Ported by Jan Weiss.\n
+* Includes speed test (this is a separate bundle for other languages).\n
+\n
+Python:\n
+* Two versions, one for Python 2.x, the other for Python 3.x.\n
+* Runs 10x faster under PyPy than CPython.\n
+\n
+Demos:\n
+* Separate demos for Diff, Match and Patch in JavaScript.\n
+</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/javascript.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/javascript.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b684bea4d6f2fdb9317952bdee01e9c478b31885
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/javascript.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/javascript/diff_match_patch_uncompressed.js.xml b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/javascript/diff_match_patch_uncompressed.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d9d0d9f28ccad47674630605d3d09e5665651136
--- /dev/null
+++ b/bt5/erp5_code_mirror/SkinTemplateItem/portal_skins/erp5_code_mirror/diff_match_patch/javascript/diff_match_patch_uncompressed.js.xml
@@ -0,0 +1,2252 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts21898048.7</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>diff_match_patch_uncompressed.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>76493</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/**\n
+ * Diff Match and Patch\n
+ *\n
+ * Copyright 2006 Google Inc.\n
+ * http://code.google.com/p/google-diff-match-patch/\n
+ *\n
+ * Licensed under the Apache License, Version 2.0 (the "License");\n
+ * you may not use this file except in compliance with the License.\n
+ * You may obtain a copy of the License at\n
+ *\n
+ *   http://www.apache.org/licenses/LICENSE-2.0\n
+ *\n
+ * Unless required by applicable law or agreed to in writing, software\n
+ * distributed under the License is distributed on an "AS IS" BASIS,\n
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n
+ * See the License for the specific language governing permissions and\n
+ * limitations under the License.\n
+ */\n
+\n
+/**\n
+ * @fileoverview Computes the difference between two texts to create a patch.\n
+ * Applies the patch onto another text, allowing for errors.\n
+ * @author fraser@google.com (Neil Fraser)\n
+ */\n
+\n
+/**\n
+ * Class containing the diff, match and patch methods.\n
+ * @constructor\n
+ */\n
+function diff_match_patch() {\n
+\n
+  // Defaults.\n
+  // Redefine these in your program to override the defaults.\n
+\n
+  // Number of seconds to map a diff before giving up (0 for infinity).\n
+  this.Diff_Timeout = 1.0;\n
+  // Cost of an empty edit operation in terms of edit characters.\n
+  this.Diff_EditCost = 4;\n
+  // At what point is no match declared (0.0 = perfection, 1.0 = very loose).\n
+  this.Match_Threshold = 0.5;\n
+  // How far to search for a match (0 = exact location, 1000+ = broad match).\n
+  // A match this many characters away from the expected location will add\n
+  // 1.0 to the score (0.0 is a perfect match).\n
+  this.Match_Distance = 1000;\n
+  // When deleting a large block of text (over ~64 characters), how close do\n
+  // the contents have to be to match the expected contents. (0.0 = perfection,\n
+  // 1.0 = very loose).  Note that Match_Threshold controls how closely the\n
+  // end points of a delete need to match.\n
+  this.Patch_DeleteThreshold = 0.5;\n
+  // Chunk size for context length.\n
+  this.Patch_Margin = 4;\n
+\n
+  // The number of bits in an int.\n
+  this.Match_MaxBits = 32;\n
+}\n
+\n
+\n
+//  DIFF FUNCTIONS\n
+\n
+\n
+/**\n
+ * The data structure representing a diff is an array of tuples:\n
+ * [[DIFF_DELETE, \'Hello\'], [DIFF_INSERT, \'Goodbye\'], [DIFF_EQUAL, \' world.\']]\n
+ * which means: delete \'Hello\', add \'Goodbye\' and keep \' world.\'\n
+ */\n
+var DIFF_DELETE = -1;\n
+var DIFF_INSERT = 1;\n
+var DIFF_EQUAL = 0;\n
+\n
+/** @typedef {{0: number, 1: string}} */\n
+diff_match_patch.Diff;\n
+\n
+\n
+/**\n
+ * Find the differences between two texts.  Simplifies the problem by stripping\n
+ * any common prefix or suffix off the texts before diffing.\n
+ * @param {string} text1 Old string to be diffed.\n
+ * @param {string} text2 New string to be diffed.\n
+ * @param {boolean=} opt_checklines Optional speedup flag. If present and false,\n
+ *     then don\'t run a line-level diff first to identify the changed areas.\n
+ *     Defaults to true, which does a faster, slightly less optimal diff.\n
+ * @param {number} opt_deadline Optional time when the diff should be complete\n
+ *     by.  Used internally for recursive calls.  Users should set DiffTimeout\n
+ *     instead.\n
+ * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n
+ */\n
+diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines,\n
+    opt_deadline) {\n
+  // Set a deadline by which time the diff must be complete.\n
+  if (typeof opt_deadline == \'undefined\') {\n
+    if (this.Diff_Timeout <= 0) {\n
+      opt_deadline = Number.MAX_VALUE;\n
+    } else {\n
+      opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000;\n
+    }\n
+  }\n
+  var deadline = opt_deadline;\n
+\n
+  // Check for null inputs.\n
+  if (text1 == null || text2 == null) {\n
+    throw new Error(\'Null input. (diff_main)\');\n
+  }\n
+\n
+  // Check for equality (speedup).\n
+  if (text1 == text2) {\n
+    if (text1) {\n
+      return [[DIFF_EQUAL, text1]];\n
+    }\n
+    return [];\n
+  }\n
+\n
+  if (typeof opt_checklines == \'undefined\') {\n
+    opt_checklines = true;\n
+  }\n
+  var checklines = opt_checklines;\n
+\n
+  // Trim off common prefix (speedup).\n
+  var commonlength = this.diff_commonPrefix(text1, text2);\n
+  var commonprefix = text1.substring(0, commonlength);\n
+  text1 = text1.substring(commonlength);\n
+  text2 = text2.substring(commonlength);\n
+\n
+  // Trim off common suffix (speedup).\n
+  commonlength = this.diff_commonSuffix(text1, text2);\n
+  var commonsuffix = text1.substring(text1.length - commonlength);\n
+  text1 = text1.substring(0, text1.length - commonlength);\n
+  text2 = text2.substring(0, text2.length - commonlength);\n
+\n
+  // Compute the diff on the middle block.\n
+  var diffs = this.diff_compute_(text1, text2, checklines, deadline);\n
+\n
+  // Restore the prefix and suffix.\n
+  if (commonprefix) {\n
+    diffs.unshift([DIFF_EQUAL, commonprefix]);\n
+  }\n
+  if (commonsuffix) {\n
+    diffs.push([DIFF_EQUAL, commonsuffix]);\n
+  }\n
+  this.diff_cleanupMerge(diffs);\n
+  return diffs;\n
+};\n
+\n
+\n
+/**\n
+ * Find the differences between two texts.  Assumes that the texts do not\n
+ * have any common prefix or suffix.\n
+ * @param {string} text1 Old string to be diffed.\n
+ * @param {string} text2 New string to be diffed.\n
+ * @param {boolean} checklines Speedup flag.  If false, then don\'t run a\n
+ *     line-level diff first to identify the changed areas.\n
+ *     If true, then run a faster, slightly less optimal diff.\n
+ * @param {number} deadline Time when the diff should be complete by.\n
+ * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines,\n
+    deadline) {\n
+  var diffs;\n
+\n
+  if (!text1) {\n
+    // Just add some text (speedup).\n
+    return [[DIFF_INSERT, text2]];\n
+  }\n
+\n
+  if (!text2) {\n
+    // Just delete some text (speedup).\n
+    return [[DIFF_DELETE, text1]];\n
+  }\n
+\n
+  var longtext = text1.length > text2.length ? text1 : text2;\n
+  var shorttext = text1.length > text2.length ? text2 : text1;\n
+  var i = longtext.indexOf(shorttext);\n
+  if (i != -1) {\n
+    // Shorter text is inside the longer text (speedup).\n
+    diffs = [[DIFF_INSERT, longtext.substring(0, i)],\n
+             [DIFF_EQUAL, shorttext],\n
+             [DIFF_INSERT, longtext.substring(i + shorttext.length)]];\n
+    // Swap insertions for deletions if diff is reversed.\n
+    if (text1.length > text2.length) {\n
+      diffs[0][0] = diffs[2][0] = DIFF_DELETE;\n
+    }\n
+    return diffs;\n
+  }\n
+\n
+  if (shorttext.length == 1) {\n
+    // Single character string.\n
+    // After the previous speedup, the character can\'t be an equality.\n
+    return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];\n
+  }\n
+\n
+  // Check to see if the problem can be split in two.\n
+  var hm = this.diff_halfMatch_(text1, text2);\n
+  if (hm) {\n
+    // A half-match was found, sort out the return data.\n
+    var text1_a = hm[0];\n
+    var text1_b = hm[1];\n
+    var text2_a = hm[2];\n
+    var text2_b = hm[3];\n
+    var mid_common = hm[4];\n
+    // Send both pairs off for separate processing.\n
+    var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline);\n
+    var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline);\n
+    // Merge the results.\n
+    return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b);\n
+  }\n
+\n
+  if (checklines && text1.length > 100 && text2.length > 100) {\n
+    return this.diff_lineMode_(text1, text2, deadline);\n
+  }\n
+\n
+  return this.diff_bisect_(text1, text2, deadline);\n
+};\n
+\n
+\n
+/**\n
+ * Do a quick line-level diff on both strings, then rediff the parts for\n
+ * greater accuracy.\n
+ * This speedup can produce non-minimal diffs.\n
+ * @param {string} text1 Old string to be diffed.\n
+ * @param {string} text2 New string to be diffed.\n
+ * @param {number} deadline Time when the diff should be complete by.\n
+ * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) {\n
+  // Scan the text on a line-by-line basis first.\n
+  var a = this.diff_linesToChars_(text1, text2);\n
+  text1 = a.chars1;\n
+  text2 = a.chars2;\n
+  var linearray = a.lineArray;\n
+\n
+  var diffs = this.diff_main(text1, text2, false, deadline);\n
+\n
+  // Convert the diff back to original text.\n
+  this.diff_charsToLines_(diffs, linearray);\n
+  // Eliminate freak matches (e.g. blank lines)\n
+  this.diff_cleanupSemantic(diffs);\n
+\n
+  // Rediff any replacement blocks, this time character-by-character.\n
+  // Add a dummy entry at the end.\n
+  diffs.push([DIFF_EQUAL, \'\']);\n
+  var pointer = 0;\n
+  var count_delete = 0;\n
+  var count_insert = 0;\n
+  var text_delete = \'\';\n
+  var text_insert = \'\';\n
+  while (pointer < diffs.length) {\n
+    switch (diffs[pointer][0]) {\n
+      case DIFF_INSERT:\n
+        count_insert++;\n
+        text_insert += diffs[pointer][1];\n
+        break;\n
+      case DIFF_DELETE:\n
+        count_delete++;\n
+        text_delete += diffs[pointer][1];\n
+        break;\n
+      case DIFF_EQUAL:\n
+        // Upon reaching an equality, check for prior redundancies.\n
+        if (count_delete >= 1 && count_insert >= 1) {\n
+          // Delete the offending records and add the merged ones.\n
+          diffs.splice(pointer - count_delete - count_insert,\n
+                       count_delete + count_insert);\n
+          pointer = pointer - count_delete - count_insert;\n
+          var a = this.diff_main(text_delete, text_insert, false, deadline);\n
+          for (var j = a.length - 1; j >= 0; j--) {\n
+            diffs.splice(pointer, 0, a[j]);\n
+          }\n
+          pointer = pointer + a.length;\n
+        }\n
+        count_insert = 0;\n
+        count_delete = 0;\n
+        text_delete = \'\';\n
+        text_insert = \'\';\n
+        break;\n
+    }\n
+    pointer++;\n
+  }\n
+  diffs.pop();  // Remove the dummy entry at the end.\n
+\n
+  return diffs;\n
+};\n
+\n
+\n
+/**\n
+ * Find the \'middle snake\' of a diff, split the problem in two\n
+ * and return the recursively constructed diff.\n
+ * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.\n
+ * @param {string} text1 Old string to be diffed.\n
+ * @param {string} text2 New string to be diffed.\n
+ * @param {number} deadline Time at which to bail if not yet complete.\n
+ * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) {\n
+  // Cache the text lengths to prevent multiple calls.\n
+  var text1_length = text1.length;\n
+  var text2_length = text2.length;\n
+  var max_d = Math.ceil((text1_length + text2_length) / 2);\n
+  var v_offset = max_d;\n
+  var v_length = 2 * max_d;\n
+  var v1 = new Array(v_length);\n
+  var v2 = new Array(v_length);\n
+  // Setting all elements to -1 is faster in Chrome & Firefox than mixing\n
+  // integers and undefined.\n
+  for (var x = 0; x < v_length; x++) {\n
+    v1[x] = -1;\n
+    v2[x] = -1;\n
+  }\n
+  v1[v_offset + 1] = 0;\n
+  v2[v_offset + 1] = 0;\n
+  var delta = text1_length - text2_length;\n
+  // If the total number of characters is odd, then the front path will collide\n
+  // with the reverse path.\n
+  var front = (delta % 2 != 0);\n
+  // Offsets for start and end of k loop.\n
+  // Prevents mapping of space beyond the grid.\n
+  var k1start = 0;\n
+  var k1end = 0;\n
+  var k2start = 0;\n
+  var k2end = 0;\n
+  for (var d = 0; d < max_d; d++) {\n
+    // Bail out if deadline is reached.\n
+    if ((new Date()).getTime() > deadline) {\n
+      break;\n
+    }\n
+\n
+    // Walk the front path one step.\n
+    for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {\n
+      var k1_offset = v_offset + k1;\n
+      var x1;\n
+      if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) {\n
+        x1 = v1[k1_offset + 1];\n
+      } else {\n
+        x1 = v1[k1_offset - 1] + 1;\n
+      }\n
+      var y1 = x1 - k1;\n
+      while (x1 < text1_length && y1 < text2_length &&\n
+             text1.charAt(x1) == text2.charAt(y1)) {\n
+        x1++;\n
+        y1++;\n
+      }\n
+      v1[k1_offset] = x1;\n
+      if (x1 > text1_length) {\n
+        // Ran off the right of the graph.\n
+        k1end += 2;\n
+      } else if (y1 > text2_length) {\n
+        // Ran off the bottom of the graph.\n
+        k1start += 2;\n
+      } else if (front) {\n
+        var k2_offset = v_offset + delta - k1;\n
+        if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) {\n
+          // Mirror x2 onto top-left coordinate system.\n
+          var x2 = text1_length - v2[k2_offset];\n
+          if (x1 >= x2) {\n
+            // Overlap detected.\n
+            return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n
+          }\n
+        }\n
+      }\n
+    }\n
+\n
+    // Walk the reverse path one step.\n
+    for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {\n
+      var k2_offset = v_offset + k2;\n
+      var x2;\n
+      if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) {\n
+        x2 = v2[k2_offset + 1];\n
+      } else {\n
+        x2 = v2[k2_offset - 1] + 1;\n
+      }\n
+      var y2 = x2 - k2;\n
+      while (x2 < text1_length && y2 < text2_length &&\n
+             text1.charAt(text1_length - x2 - 1) ==\n
+             text2.charAt(text2_length - y2 - 1)) {\n
+        x2++;\n
+        y2++;\n
+      }\n
+      v2[k2_offset] = x2;\n
+      if (x2 > text1_length) {\n
+        // Ran off the left of the graph.\n
+        k2end += 2;\n
+      } else if (y2 > text2_length) {\n
+        // Ran off the top of the graph.\n
+        k2start += 2;\n
+      } else if (!front) {\n
+        var k1_offset = v_offset + delta - k2;\n
+        if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) {\n
+          var x1 = v1[k1_offset];\n
+          var y1 = v_offset + x1 - k1_offset;\n
+          // Mirror x2 onto top-left coordinate system.\n
+          x2 = text1_length - x2;\n
+          if (x1 >= x2) {\n
+            // Overlap detected.\n
+            return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n
+          }\n
+        }\n
+      }\n
+    }\n
+  }\n
+  // Diff took too long and hit the deadline or\n
+  // number of diffs equals number of characters, no commonality at all.\n
+  return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];\n
+};\n
+\n
+\n
+/**\n
+ * Given the location of the \'middle snake\', split the diff in two parts\n
+ * and recurse.\n
+ * @param {string} text1 Old string to be diffed.\n
+ * @param {string} text2 New string to be diffed.\n
+ * @param {number} x Index of split point in text1.\n
+ * @param {number} y Index of split point in text2.\n
+ * @param {number} deadline Time at which to bail if not yet complete.\n
+ * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y,\n
+    deadline) {\n
+  var text1a = text1.substring(0, x);\n
+  var text2a = text2.substring(0, y);\n
+  var text1b = text1.substring(x);\n
+  var text2b = text2.substring(y);\n
+\n
+  // Compute both diffs serially.\n
+  var diffs = this.diff_main(text1a, text2a, false, deadline);\n
+  var diffsb = this.diff_main(text1b, text2b, false, deadline);\n
+\n
+  return diffs.concat(diffsb);\n
+};\n
+\n
+\n
+/**\n
+ * Split two texts into an array of strings.  Reduce the texts to a string of\n
+ * hashes where each Unicode character represents one line.\n
+ * @param {string} text1 First string.\n
+ * @param {string} text2 Second string.\n
+ * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}\n
+ *     An object containing the encoded text1, the encoded text2 and\n
+ *     the array of unique strings.\n
+ *     The zeroth element of the array of unique strings is intentionally blank.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) {\n
+  var lineArray = [];  // e.g. lineArray[4] == \'Hello\\n\'\n
+  var lineHash = {};   // e.g. lineHash[\'Hello\\n\'] == 4\n
+\n
+  // \'\\x00\' is a valid character, but various debuggers don\'t like it.\n
+  // So we\'ll insert a junk entry to avoid generating a null character.\n
+  lineArray[0] = \'\';\n
+\n
+  /**\n
+   * Split a text into an array of strings.  Reduce the texts to a string of\n
+   * hashes where each Unicode character represents one line.\n
+   * Modifies linearray and linehash through being a closure.\n
+   * @param {string} text String to encode.\n
+   * @return {string} Encoded string.\n
+   * @private\n
+   */\n
+  function diff_linesToCharsMunge_(text) {\n
+    var chars = \'\';\n
+    // Walk the text, pulling out a substring for each line.\n
+    // text.split(\'\\n\') would would temporarily double our memory footprint.\n
+    // Modifying text would create many large strings to garbage collect.\n
+    var lineStart = 0;\n
+    var lineEnd = -1;\n
+    // Keeping our own length variable is faster than looking it up.\n
+    var lineArrayLength = lineArray.length;\n
+    while (lineEnd < text.length - 1) {\n
+      lineEnd = text.indexOf(\'\\n\', lineStart);\n
+      if (lineEnd == -1) {\n
+        lineEnd = text.length - 1;\n
+      }\n
+      var line = text.substring(lineStart, lineEnd + 1);\n
+      lineStart = lineEnd + 1;\n
+\n
+      if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :\n
+          (lineHash[line] !== undefined)) {\n
+        chars += String.fromCharCode(lineHash[line]);\n
+      } else {\n
+        chars += String.fromCharCode(lineArrayLength);\n
+        lineHash[line] = lineArrayLength;\n
+        lineArray[lineArrayLength++] = line;\n
+      }\n
+    }\n
+    return chars;\n
+  }\n
+\n
+  var chars1 = diff_linesToCharsMunge_(text1);\n
+  var chars2 = diff_linesToCharsMunge_(text2);\n
+  return {chars1: chars1, chars2: chars2, lineArray: lineArray};\n
+};\n
+\n
+\n
+/**\n
+ * Rehydrate the text in a diff from a string of line hashes to real lines of\n
+ * text.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @param {!Array.<string>} lineArray Array of unique strings.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) {\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    var chars = diffs[x][1];\n
+    var text = [];\n
+    for (var y = 0; y < chars.length; y++) {\n
+      text[y] = lineArray[chars.charCodeAt(y)];\n
+    }\n
+    diffs[x][1] = text.join(\'\');\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * Determine the common prefix of two strings.\n
+ * @param {string} text1 First string.\n
+ * @param {string} text2 Second string.\n
+ * @return {number} The number of characters common to the start of each\n
+ *     string.\n
+ */\n
+diff_match_patch.prototype.diff_commonPrefix = function(text1, text2) {\n
+  // Quick check for common null cases.\n
+  if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {\n
+    return 0;\n
+  }\n
+  // Binary search.\n
+  // Performance analysis: http://neil.fraser.name/news/2007/10/09/\n
+  var pointermin = 0;\n
+  var pointermax = Math.min(text1.length, text2.length);\n
+  var pointermid = pointermax;\n
+  var pointerstart = 0;\n
+  while (pointermin < pointermid) {\n
+    if (text1.substring(pointerstart, pointermid) ==\n
+        text2.substring(pointerstart, pointermid)) {\n
+      pointermin = pointermid;\n
+      pointerstart = pointermin;\n
+    } else {\n
+      pointermax = pointermid;\n
+    }\n
+    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n
+  }\n
+  return pointermid;\n
+};\n
+\n
+\n
+/**\n
+ * Determine the common suffix of two strings.\n
+ * @param {string} text1 First string.\n
+ * @param {string} text2 Second string.\n
+ * @return {number} The number of characters common to the end of each string.\n
+ */\n
+diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) {\n
+  // Quick check for common null cases.\n
+  if (!text1 || !text2 ||\n
+      text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {\n
+    return 0;\n
+  }\n
+  // Binary search.\n
+  // Performance analysis: http://neil.fraser.name/news/2007/10/09/\n
+  var pointermin = 0;\n
+  var pointermax = Math.min(text1.length, text2.length);\n
+  var pointermid = pointermax;\n
+  var pointerend = 0;\n
+  while (pointermin < pointermid) {\n
+    if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==\n
+        text2.substring(text2.length - pointermid, text2.length - pointerend)) {\n
+      pointermin = pointermid;\n
+      pointerend = pointermin;\n
+    } else {\n
+      pointermax = pointermid;\n
+    }\n
+    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n
+  }\n
+  return pointermid;\n
+};\n
+\n
+\n
+/**\n
+ * Determine if the suffix of one string is the prefix of another.\n
+ * @param {string} text1 First string.\n
+ * @param {string} text2 Second string.\n
+ * @return {number} The number of characters common to the end of the first\n
+ *     string and the start of the second string.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) {\n
+  // Cache the text lengths to prevent multiple calls.\n
+  var text1_length = text1.length;\n
+  var text2_length = text2.length;\n
+  // Eliminate the null case.\n
+  if (text1_length == 0 || text2_length == 0) {\n
+    return 0;\n
+  }\n
+  // Truncate the longer string.\n
+  if (text1_length > text2_length) {\n
+    text1 = text1.substring(text1_length - text2_length);\n
+  } else if (text1_length < text2_length) {\n
+    text2 = text2.substring(0, text1_length);\n
+  }\n
+  var text_length = Math.min(text1_length, text2_length);\n
+  // Quick check for the worst case.\n
+  if (text1 == text2) {\n
+    return text_length;\n
+  }\n
+\n
+  // Start by looking for a single character match\n
+  // and increase length until no match is found.\n
+  // Performance analysis: http://neil.fraser.name/news/2010/11/04/\n
+  var best = 0;\n
+  var length = 1;\n
+  while (true) {\n
+    var pattern = text1.substring(text_length - length);\n
+    var found = text2.indexOf(pattern);\n
+    if (found == -1) {\n
+      return best;\n
+    }\n
+    length += found;\n
+    if (found == 0 || text1.substring(text_length - length) ==\n
+        text2.substring(0, length)) {\n
+      best = length;\n
+      length++;\n
+    }\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * Do the two texts share a substring which is at least half the length of the\n
+ * longer text?\n
+ * This speedup can produce non-minimal diffs.\n
+ * @param {string} text1 First string.\n
+ * @param {string} text2 Second string.\n
+ * @return {Array.<string>} Five element Array, containing the prefix of\n
+ *     text1, the suffix of text1, the prefix of text2, the suffix of\n
+ *     text2 and the common middle.  Or null if there was no match.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) {\n
+  if (this.Diff_Timeout <= 0) {\n
+    // Don\'t risk returning a non-optimal diff if we have unlimited time.\n
+    return null;\n
+  }\n
+  var longtext = text1.length > text2.length ? text1 : text2;\n
+  var shorttext = text1.length > text2.length ? text2 : text1;\n
+  if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {\n
+    return null;  // Pointless.\n
+  }\n
+  var dmp = this;  // \'this\' becomes \'window\' in a closure.\n
+\n
+  /**\n
+   * Does a substring of shorttext exist within longtext such that the substring\n
+   * is at least half the length of longtext?\n
+   * Closure, but does not reference any external variables.\n
+   * @param {string} longtext Longer string.\n
+   * @param {string} shorttext Shorter string.\n
+   * @param {number} i Start index of quarter length substring within longtext.\n
+   * @return {Array.<string>} Five element Array, containing the prefix of\n
+   *     longtext, the suffix of longtext, the prefix of shorttext, the suffix\n
+   *     of shorttext and the common middle.  Or null if there was no match.\n
+   * @private\n
+   */\n
+  function diff_halfMatchI_(longtext, shorttext, i) {\n
+    // Start with a 1/4 length substring at position i as a seed.\n
+    var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));\n
+    var j = -1;\n
+    var best_common = \'\';\n
+    var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;\n
+    while ((j = shorttext.indexOf(seed, j + 1)) != -1) {\n
+      var prefixLength = dmp.diff_commonPrefix(longtext.substring(i),\n
+                                               shorttext.substring(j));\n
+      var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i),\n
+                                               shorttext.substring(0, j));\n
+      if (best_common.length < suffixLength + prefixLength) {\n
+        best_common = shorttext.substring(j - suffixLength, j) +\n
+            shorttext.substring(j, j + prefixLength);\n
+        best_longtext_a = longtext.substring(0, i - suffixLength);\n
+        best_longtext_b = longtext.substring(i + prefixLength);\n
+        best_shorttext_a = shorttext.substring(0, j - suffixLength);\n
+        best_shorttext_b = shorttext.substring(j + prefixLength);\n
+      }\n
+    }\n
+    if (best_common.length * 2 >= longtext.length) {\n
+      return [best_longtext_a, best_longtext_b,\n
+              best_shorttext_a, best_shorttext_b, best_common];\n
+    } else {\n
+      return null;\n
+    }\n
+  }\n
+\n
+  // First check if the second quarter is the seed for a half-match.\n
+  var hm1 = diff_halfMatchI_(longtext, shorttext,\n
+                             Math.ceil(longtext.length / 4));\n
+  // Check again based on the third quarter.\n
+  var hm2 = diff_halfMatchI_(longtext, shorttext,\n
+                             Math.ceil(longtext.length / 2));\n
+  var hm;\n
+  if (!hm1 && !hm2) {\n
+    return null;\n
+  } else if (!hm2) {\n
+    hm = hm1;\n
+  } else if (!hm1) {\n
+    hm = hm2;\n
+  } else {\n
+    // Both matched.  Select the longest.\n
+    hm = hm1[4].length > hm2[4].length ? hm1 : hm2;\n
+  }\n
+\n
+  // A half-match was found, sort out the return data.\n
+  var text1_a, text1_b, text2_a, text2_b;\n
+  if (text1.length > text2.length) {\n
+    text1_a = hm[0];\n
+    text1_b = hm[1];\n
+    text2_a = hm[2];\n
+    text2_b = hm[3];\n
+  } else {\n
+    text2_a = hm[0];\n
+    text2_b = hm[1];\n
+    text1_a = hm[2];\n
+    text1_b = hm[3];\n
+  }\n
+  var mid_common = hm[4];\n
+  return [text1_a, text1_b, text2_a, text2_b, mid_common];\n
+};\n
+\n
+\n
+/**\n
+ * Reduce the number of edits by eliminating semantically trivial equalities.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ */\n
+diff_match_patch.prototype.diff_cleanupSemantic = function(diffs) {\n
+  var changes = false;\n
+  var equalities = [];  // Stack of indices where equalities are found.\n
+  var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n
+  /** @type {?string} */\n
+  var lastequality = null;\n
+  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n
+  var pointer = 0;  // Index of current position.\n
+  // Number of characters that changed prior to the equality.\n
+  var length_insertions1 = 0;\n
+  var length_deletions1 = 0;\n
+  // Number of characters that changed after the equality.\n
+  var length_insertions2 = 0;\n
+  var length_deletions2 = 0;\n
+  while (pointer < diffs.length) {\n
+    if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n
+      equalities[equalitiesLength++] = pointer;\n
+      length_insertions1 = length_insertions2;\n
+      length_deletions1 = length_deletions2;\n
+      length_insertions2 = 0;\n
+      length_deletions2 = 0;\n
+      lastequality = diffs[pointer][1];\n
+    } else {  // An insertion or deletion.\n
+      if (diffs[pointer][0] == DIFF_INSERT) {\n
+        length_insertions2 += diffs[pointer][1].length;\n
+      } else {\n
+        length_deletions2 += diffs[pointer][1].length;\n
+      }\n
+      // Eliminate an equality that is smaller or equal to the edits on both\n
+      // sides of it.\n
+      if (lastequality && (lastequality.length <=\n
+          Math.max(length_insertions1, length_deletions1)) &&\n
+          (lastequality.length <= Math.max(length_insertions2,\n
+                                           length_deletions2))) {\n
+        // Duplicate record.\n
+        diffs.splice(equalities[equalitiesLength - 1], 0,\n
+                     [DIFF_DELETE, lastequality]);\n
+        // Change second copy to insert.\n
+        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n
+        // Throw away the equality we just deleted.\n
+        equalitiesLength--;\n
+        // Throw away the previous equality (it needs to be reevaluated).\n
+        equalitiesLength--;\n
+        pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;\n
+        length_insertions1 = 0;  // Reset the counters.\n
+        length_deletions1 = 0;\n
+        length_insertions2 = 0;\n
+        length_deletions2 = 0;\n
+        lastequality = null;\n
+        changes = true;\n
+      }\n
+    }\n
+    pointer++;\n
+  }\n
+\n
+  // Normalize the diff.\n
+  if (changes) {\n
+    this.diff_cleanupMerge(diffs);\n
+  }\n
+  this.diff_cleanupSemanticLossless(diffs);\n
+\n
+  // Find any overlaps between deletions and insertions.\n
+  // e.g: <del>abcxxx</del><ins>xxxdef</ins>\n
+  //   -> <del>abc</del>xxx<ins>def</ins>\n
+  // e.g: <del>xxxabc</del><ins>defxxx</ins>\n
+  //   -> <ins>def</ins>xxx<del>abc</del>\n
+  // Only extract an overlap if it is as big as the edit ahead or behind it.\n
+  pointer = 1;\n
+  while (pointer < diffs.length) {\n
+    if (diffs[pointer - 1][0] == DIFF_DELETE &&\n
+        diffs[pointer][0] == DIFF_INSERT) {\n
+      var deletion = diffs[pointer - 1][1];\n
+      var insertion = diffs[pointer][1];\n
+      var overlap_length1 = this.diff_commonOverlap_(deletion, insertion);\n
+      var overlap_length2 = this.diff_commonOverlap_(insertion, deletion);\n
+      if (overlap_length1 >= overlap_length2) {\n
+        if (overlap_length1 >= deletion.length / 2 ||\n
+            overlap_length1 >= insertion.length / 2) {\n
+          // Overlap found.  Insert an equality and trim the surrounding edits.\n
+          diffs.splice(pointer, 0,\n
+              [DIFF_EQUAL, insertion.substring(0, overlap_length1)]);\n
+          diffs[pointer - 1][1] =\n
+              deletion.substring(0, deletion.length - overlap_length1);\n
+          diffs[pointer + 1][1] = insertion.substring(overlap_length1);\n
+          pointer++;\n
+        }\n
+      } else {\n
+        if (overlap_length2 >= deletion.length / 2 ||\n
+            overlap_length2 >= insertion.length / 2) {\n
+          // Reverse overlap found.\n
+          // Insert an equality and swap and trim the surrounding edits.\n
+          diffs.splice(pointer, 0,\n
+              [DIFF_EQUAL, deletion.substring(0, overlap_length2)]);\n
+          diffs[pointer - 1][0] = DIFF_INSERT;\n
+          diffs[pointer - 1][1] =\n
+              insertion.substring(0, insertion.length - overlap_length2);\n
+          diffs[pointer + 1][0] = DIFF_DELETE;\n
+          diffs[pointer + 1][1] =\n
+              deletion.substring(overlap_length2);\n
+          pointer++;\n
+        }\n
+      }\n
+      pointer++;\n
+    }\n
+    pointer++;\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * Look for single edits surrounded on both sides by equalities\n
+ * which can be shifted sideways to align the edit to a word boundary.\n
+ * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ */\n
+diff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) {\n
+  /**\n
+   * Given two strings, compute a score representing whether the internal\n
+   * boundary falls on logical boundaries.\n
+   * Scores range from 6 (best) to 0 (worst).\n
+   * Closure, but does not reference any external variables.\n
+   * @param {string} one First string.\n
+   * @param {string} two Second string.\n
+   * @return {number} The score.\n
+   * @private\n
+   */\n
+  function diff_cleanupSemanticScore_(one, two) {\n
+    if (!one || !two) {\n
+      // Edges are the best.\n
+      return 6;\n
+    }\n
+\n
+    // Each port of this function behaves slightly differently due to\n
+    // subtle differences in each language\'s definition of things like\n
+    // \'whitespace\'.  Since this function\'s purpose is largely cosmetic,\n
+    // the choice has been made to use each language\'s native features\n
+    // rather than force total conformity.\n
+    var char1 = one.charAt(one.length - 1);\n
+    var char2 = two.charAt(0);\n
+    var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_);\n
+    var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_);\n
+    var whitespace1 = nonAlphaNumeric1 &&\n
+        char1.match(diff_match_patch.whitespaceRegex_);\n
+    var whitespace2 = nonAlphaNumeric2 &&\n
+        char2.match(diff_match_patch.whitespaceRegex_);\n
+    var lineBreak1 = whitespace1 &&\n
+        char1.match(diff_match_patch.linebreakRegex_);\n
+    var lineBreak2 = whitespace2 &&\n
+        char2.match(diff_match_patch.linebreakRegex_);\n
+    var blankLine1 = lineBreak1 &&\n
+        one.match(diff_match_patch.blanklineEndRegex_);\n
+    var blankLine2 = lineBreak2 &&\n
+        two.match(diff_match_patch.blanklineStartRegex_);\n
+\n
+    if (blankLine1 || blankLine2) {\n
+      // Five points for blank lines.\n
+      return 5;\n
+    } else if (lineBreak1 || lineBreak2) {\n
+      // Four points for line breaks.\n
+      return 4;\n
+    } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {\n
+      // Three points for end of sentences.\n
+      return 3;\n
+    } else if (whitespace1 || whitespace2) {\n
+      // Two points for whitespace.\n
+      return 2;\n
+    } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {\n
+      // One point for non-alphanumeric.\n
+      return 1;\n
+    }\n
+    return 0;\n
+  }\n
+\n
+  var pointer = 1;\n
+  // Intentionally ignore the first and last element (don\'t need checking).\n
+  while (pointer < diffs.length - 1) {\n
+    if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n
+        diffs[pointer + 1][0] == DIFF_EQUAL) {\n
+      // This is a single edit surrounded by equalities.\n
+      var equality1 = diffs[pointer - 1][1];\n
+      var edit = diffs[pointer][1];\n
+      var equality2 = diffs[pointer + 1][1];\n
+\n
+      // First, shift the edit as far left as possible.\n
+      var commonOffset = this.diff_commonSuffix(equality1, edit);\n
+      if (commonOffset) {\n
+        var commonString = edit.substring(edit.length - commonOffset);\n
+        equality1 = equality1.substring(0, equality1.length - commonOffset);\n
+        edit = commonString + edit.substring(0, edit.length - commonOffset);\n
+        equality2 = commonString + equality2;\n
+      }\n
+\n
+      // Second, step character by character right, looking for the best fit.\n
+      var bestEquality1 = equality1;\n
+      var bestEdit = edit;\n
+      var bestEquality2 = equality2;\n
+      var bestScore = diff_cleanupSemanticScore_(equality1, edit) +\n
+          diff_cleanupSemanticScore_(edit, equality2);\n
+      while (edit.charAt(0) === equality2.charAt(0)) {\n
+        equality1 += edit.charAt(0);\n
+        edit = edit.substring(1) + equality2.charAt(0);\n
+        equality2 = equality2.substring(1);\n
+        var score = diff_cleanupSemanticScore_(equality1, edit) +\n
+            diff_cleanupSemanticScore_(edit, equality2);\n
+        // The >= encourages trailing rather than leading whitespace on edits.\n
+        if (score >= bestScore) {\n
+          bestScore = score;\n
+          bestEquality1 = equality1;\n
+          bestEdit = edit;\n
+          bestEquality2 = equality2;\n
+        }\n
+      }\n
+\n
+      if (diffs[pointer - 1][1] != bestEquality1) {\n
+        // We have an improvement, save it back to the diff.\n
+        if (bestEquality1) {\n
+          diffs[pointer - 1][1] = bestEquality1;\n
+        } else {\n
+          diffs.splice(pointer - 1, 1);\n
+          pointer--;\n
+        }\n
+        diffs[pointer][1] = bestEdit;\n
+        if (bestEquality2) {\n
+          diffs[pointer + 1][1] = bestEquality2;\n
+        } else {\n
+          diffs.splice(pointer + 1, 1);\n
+          pointer--;\n
+        }\n
+      }\n
+    }\n
+    pointer++;\n
+  }\n
+};\n
+\n
+// Define some regex patterns for matching boundaries.\n
+diff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;\n
+diff_match_patch.whitespaceRegex_ = /\\s/;\n
+diff_match_patch.linebreakRegex_ = /[\\r\\n]/;\n
+diff_match_patch.blanklineEndRegex_ = /\\n\\r?\\n$/;\n
+diff_match_patch.blanklineStartRegex_ = /^\\r?\\n\\r?\\n/;\n
+\n
+/**\n
+ * Reduce the number of edits by eliminating operationally trivial equalities.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ */\n
+diff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) {\n
+  var changes = false;\n
+  var equalities = [];  // Stack of indices where equalities are found.\n
+  var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n
+  /** @type {?string} */\n
+  var lastequality = null;\n
+  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n
+  var pointer = 0;  // Index of current position.\n
+  // Is there an insertion operation before the last equality.\n
+  var pre_ins = false;\n
+  // Is there a deletion operation before the last equality.\n
+  var pre_del = false;\n
+  // Is there an insertion operation after the last equality.\n
+  var post_ins = false;\n
+  // Is there a deletion operation after the last equality.\n
+  var post_del = false;\n
+  while (pointer < diffs.length) {\n
+    if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n
+      if (diffs[pointer][1].length < this.Diff_EditCost &&\n
+          (post_ins || post_del)) {\n
+        // Candidate found.\n
+        equalities[equalitiesLength++] = pointer;\n
+        pre_ins = post_ins;\n
+        pre_del = post_del;\n
+        lastequality = diffs[pointer][1];\n
+      } else {\n
+        // Not a candidate, and can never become one.\n
+        equalitiesLength = 0;\n
+        lastequality = null;\n
+      }\n
+      post_ins = post_del = false;\n
+    } else {  // An insertion or deletion.\n
+      if (diffs[pointer][0] == DIFF_DELETE) {\n
+        post_del = true;\n
+      } else {\n
+        post_ins = true;\n
+      }\n
+      /*\n
+       * Five types to be split:\n
+       * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>\n
+       * <ins>A</ins>X<ins>C</ins><del>D</del>\n
+       * <ins>A</ins><del>B</del>X<ins>C</ins>\n
+       * <ins>A</del>X<ins>C</ins><del>D</del>\n
+       * <ins>A</ins><del>B</del>X<del>C</del>\n
+       */\n
+      if (lastequality && ((pre_ins && pre_del && post_ins && post_del) ||\n
+                           ((lastequality.length < this.Diff_EditCost / 2) &&\n
+                            (pre_ins + pre_del + post_ins + post_del) == 3))) {\n
+        // Duplicate record.\n
+        diffs.splice(equalities[equalitiesLength - 1], 0,\n
+                     [DIFF_DELETE, lastequality]);\n
+        // Change second copy to insert.\n
+        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n
+        equalitiesLength--;  // Throw away the equality we just deleted;\n
+        lastequality = null;\n
+        if (pre_ins && pre_del) {\n
+          // No changes made which could affect previous entry, keep going.\n
+          post_ins = post_del = true;\n
+          equalitiesLength = 0;\n
+        } else {\n
+          equalitiesLength--;  // Throw away the previous equality.\n
+          pointer = equalitiesLength > 0 ?\n
+              equalities[equalitiesLength - 1] : -1;\n
+          post_ins = post_del = false;\n
+        }\n
+        changes = true;\n
+      }\n
+    }\n
+    pointer++;\n
+  }\n
+\n
+  if (changes) {\n
+    this.diff_cleanupMerge(diffs);\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * Reorder and merge like edit sections.  Merge equalities.\n
+ * Any edit section can move as long as it doesn\'t cross an equality.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ */\n
+diff_match_patch.prototype.diff_cleanupMerge = function(diffs) {\n
+  diffs.push([DIFF_EQUAL, \'\']);  // Add a dummy entry at the end.\n
+  var pointer = 0;\n
+  var count_delete = 0;\n
+  var count_insert = 0;\n
+  var text_delete = \'\';\n
+  var text_insert = \'\';\n
+  var commonlength;\n
+  while (pointer < diffs.length) {\n
+    switch (diffs[pointer][0]) {\n
+      case DIFF_INSERT:\n
+        count_insert++;\n
+        text_insert += diffs[pointer][1];\n
+        pointer++;\n
+        break;\n
+      case DIFF_DELETE:\n
+        count_delete++;\n
+        text_delete += diffs[pointer][1];\n
+        pointer++;\n
+        break;\n
+      case DIFF_EQUAL:\n
+        // Upon reaching an equality, check for prior redundancies.\n
+        if (count_delete + count_insert > 1) {\n
+          if (count_delete !== 0 && count_insert !== 0) {\n
+            // Factor out any common prefixies.\n
+            commonlength = this.diff_commonPrefix(text_insert, text_delete);\n
+            if (commonlength !== 0) {\n
+              if ((pointer - count_delete - count_insert) > 0 &&\n
+                  diffs[pointer - count_delete - count_insert - 1][0] ==\n
+                  DIFF_EQUAL) {\n
+                diffs[pointer - count_delete - count_insert - 1][1] +=\n
+                    text_insert.substring(0, commonlength);\n
+              } else {\n
+                diffs.splice(0, 0, [DIFF_EQUAL,\n
+                                    text_insert.substring(0, commonlength)]);\n
+                pointer++;\n
+              }\n
+              text_insert = text_insert.substring(commonlength);\n
+              text_delete = text_delete.substring(commonlength);\n
+            }\n
+            // Factor out any common suffixies.\n
+            commonlength = this.diff_commonSuffix(text_insert, text_delete);\n
+            if (commonlength !== 0) {\n
+              diffs[pointer][1] = text_insert.substring(text_insert.length -\n
+                  commonlength) + diffs[pointer][1];\n
+              text_insert = text_insert.substring(0, text_insert.length -\n
+                  commonlength);\n
+              text_delete = text_delete.substring(0, text_delete.length -\n
+                  commonlength);\n
+            }\n
+          }\n
+          // Delete the offending records and add the merged ones.\n
+          if (count_delete === 0) {\n
+            diffs.splice(pointer - count_insert,\n
+                count_delete + count_insert, [DIFF_INSERT, text_insert]);\n
+          } else if (count_insert === 0) {\n
+            diffs.splice(pointer - count_delete,\n
+                count_delete + count_insert, [DIFF_DELETE, text_delete]);\n
+          } else {\n
+            diffs.splice(pointer - count_delete - count_insert,\n
+                count_delete + count_insert, [DIFF_DELETE, text_delete],\n
+                [DIFF_INSERT, text_insert]);\n
+          }\n
+          pointer = pointer - count_delete - count_insert +\n
+                    (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;\n
+        } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {\n
+          // Merge this equality with the previous one.\n
+          diffs[pointer - 1][1] += diffs[pointer][1];\n
+          diffs.splice(pointer, 1);\n
+        } else {\n
+          pointer++;\n
+        }\n
+        count_insert = 0;\n
+        count_delete = 0;\n
+        text_delete = \'\';\n
+        text_insert = \'\';\n
+        break;\n
+    }\n
+  }\n
+  if (diffs[diffs.length - 1][1] === \'\') {\n
+    diffs.pop();  // Remove the dummy entry at the end.\n
+  }\n
+\n
+  // Second pass: look for single edits surrounded on both sides by equalities\n
+  // which can be shifted sideways to eliminate an equality.\n
+  // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC\n
+  var changes = false;\n
+  pointer = 1;\n
+  // Intentionally ignore the first and last element (don\'t need checking).\n
+  while (pointer < diffs.length - 1) {\n
+    if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n
+        diffs[pointer + 1][0] == DIFF_EQUAL) {\n
+      // This is a single edit surrounded by equalities.\n
+      if (diffs[pointer][1].substring(diffs[pointer][1].length -\n
+          diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {\n
+        // Shift the edit over the previous equality.\n
+        diffs[pointer][1] = diffs[pointer - 1][1] +\n
+            diffs[pointer][1].substring(0, diffs[pointer][1].length -\n
+                                        diffs[pointer - 1][1].length);\n
+        diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];\n
+        diffs.splice(pointer - 1, 1);\n
+        changes = true;\n
+      } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==\n
+          diffs[pointer + 1][1]) {\n
+        // Shift the edit over the next equality.\n
+        diffs[pointer - 1][1] += diffs[pointer + 1][1];\n
+        diffs[pointer][1] =\n
+            diffs[pointer][1].substring(diffs[pointer + 1][1].length) +\n
+            diffs[pointer + 1][1];\n
+        diffs.splice(pointer + 1, 1);\n
+        changes = true;\n
+      }\n
+    }\n
+    pointer++;\n
+  }\n
+  // If shifts were made, the diff needs reordering and another shift sweep.\n
+  if (changes) {\n
+    this.diff_cleanupMerge(diffs);\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * loc is a location in text1, compute and return the equivalent location in\n
+ * text2.\n
+ * e.g. \'The cat\' vs \'The big cat\', 1->1, 5->8\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @param {number} loc Location within text1.\n
+ * @return {number} Location within text2.\n
+ */\n
+diff_match_patch.prototype.diff_xIndex = function(diffs, loc) {\n
+  var chars1 = 0;\n
+  var chars2 = 0;\n
+  var last_chars1 = 0;\n
+  var last_chars2 = 0;\n
+  var x;\n
+  for (x = 0; x < diffs.length; x++) {\n
+    if (diffs[x][0] !== DIFF_INSERT) {  // Equality or deletion.\n
+      chars1 += diffs[x][1].length;\n
+    }\n
+    if (diffs[x][0] !== DIFF_DELETE) {  // Equality or insertion.\n
+      chars2 += diffs[x][1].length;\n
+    }\n
+    if (chars1 > loc) {  // Overshot the location.\n
+      break;\n
+    }\n
+    last_chars1 = chars1;\n
+    last_chars2 = chars2;\n
+  }\n
+  // Was the location was deleted?\n
+  if (diffs.length != x && diffs[x][0] === DIFF_DELETE) {\n
+    return last_chars2;\n
+  }\n
+  // Add the remaining character length.\n
+  return last_chars2 + (loc - last_chars1);\n
+};\n
+\n
+\n
+/**\n
+ * Convert a diff array into a pretty HTML report.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @return {string} HTML representation.\n
+ */\n
+diff_match_patch.prototype.diff_prettyHtml = function(diffs) {\n
+  var html = [];\n
+  var pattern_amp = /&/g;\n
+  var pattern_lt = /</g;\n
+  var pattern_gt = />/g;\n
+  var pattern_para = /\\n/g;\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    var op = diffs[x][0];    // Operation (insert, delete, equal)\n
+    var data = diffs[x][1];  // Text of change.\n
+    var text = data.replace(pattern_amp, \'&amp;\').replace(pattern_lt, \'&lt;\')\n
+        .replace(pattern_gt, \'&gt;\').replace(pattern_para, \'&para;<br>\');\n
+    switch (op) {\n
+      case DIFF_INSERT:\n
+        html[x] = \'<ins style="background:#e6ffe6;">\' + text + \'</ins>\';\n
+        break;\n
+      case DIFF_DELETE:\n
+        html[x] = \'<del style="background:#ffe6e6;">\' + text + \'</del>\';\n
+        break;\n
+      case DIFF_EQUAL:\n
+        html[x] = \'<span>\' + text + \'</span>\';\n
+        break;\n
+    }\n
+  }\n
+  return html.join(\'\');\n
+};\n
+\n
+\n
+/**\n
+ * Compute and return the source text (all equalities and deletions).\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @return {string} Source text.\n
+ */\n
+diff_match_patch.prototype.diff_text1 = function(diffs) {\n
+  var text = [];\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    if (diffs[x][0] !== DIFF_INSERT) {\n
+      text[x] = diffs[x][1];\n
+    }\n
+  }\n
+  return text.join(\'\');\n
+};\n
+\n
+\n
+/**\n
+ * Compute and return the destination text (all equalities and insertions).\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @return {string} Destination text.\n
+ */\n
+diff_match_patch.prototype.diff_text2 = function(diffs) {\n
+  var text = [];\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    if (diffs[x][0] !== DIFF_DELETE) {\n
+      text[x] = diffs[x][1];\n
+    }\n
+  }\n
+  return text.join(\'\');\n
+};\n
+\n
+\n
+/**\n
+ * Compute the Levenshtein distance; the number of inserted, deleted or\n
+ * substituted characters.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @return {number} Number of changes.\n
+ */\n
+diff_match_patch.prototype.diff_levenshtein = function(diffs) {\n
+  var levenshtein = 0;\n
+  var insertions = 0;\n
+  var deletions = 0;\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    var op = diffs[x][0];\n
+    var data = diffs[x][1];\n
+    switch (op) {\n
+      case DIFF_INSERT:\n
+        insertions += data.length;\n
+        break;\n
+      case DIFF_DELETE:\n
+        deletions += data.length;\n
+        break;\n
+      case DIFF_EQUAL:\n
+        // A deletion and an insertion is one substitution.\n
+        levenshtein += Math.max(insertions, deletions);\n
+        insertions = 0;\n
+        deletions = 0;\n
+        break;\n
+    }\n
+  }\n
+  levenshtein += Math.max(insertions, deletions);\n
+  return levenshtein;\n
+};\n
+\n
+\n
+/**\n
+ * Crush the diff into an encoded string which describes the operations\n
+ * required to transform text1 into text2.\n
+ * E.g. =3\\t-2\\t+ing  -> Keep 3 chars, delete 2 chars, insert \'ing\'.\n
+ * Operations are tab-separated.  Inserted text is escaped using %xx notation.\n
+ * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n
+ * @return {string} Delta text.\n
+ */\n
+diff_match_patch.prototype.diff_toDelta = function(diffs) {\n
+  var text = [];\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    switch (diffs[x][0]) {\n
+      case DIFF_INSERT:\n
+        text[x] = \'+\' + encodeURI(diffs[x][1]);\n
+        break;\n
+      case DIFF_DELETE:\n
+        text[x] = \'-\' + diffs[x][1].length;\n
+        break;\n
+      case DIFF_EQUAL:\n
+        text[x] = \'=\' + diffs[x][1].length;\n
+        break;\n
+    }\n
+  }\n
+  return text.join(\'\\t\').replace(/%20/g, \' \');\n
+};\n
+\n
+\n
+/**\n
+ * Given the original text1, and an encoded string which describes the\n
+ * operations required to transform text1 into text2, compute the full diff.\n
+ * @param {string} text1 Source string for the diff.\n
+ * @param {string} delta Delta text.\n
+ * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n
+ * @throws {!Error} If invalid input.\n
+ */\n
+diff_match_patch.prototype.diff_fromDelta = function(text1, delta) {\n
+  var diffs = [];\n
+  var diffsLength = 0;  // Keeping our own length var is faster in JS.\n
+  var pointer = 0;  // Cursor in text1\n
+  var tokens = delta.split(/\\t/g);\n
+  for (var x = 0; x < tokens.length; x++) {\n
+    // Each token begins with a one character parameter which specifies the\n
+    // operation of this token (delete, insert, equality).\n
+    var param = tokens[x].substring(1);\n
+    switch (tokens[x].charAt(0)) {\n
+      case \'+\':\n
+        try {\n
+          diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)];\n
+        } catch (ex) {\n
+          // Malformed URI sequence.\n
+          throw new Error(\'Illegal escape in diff_fromDelta: \' + param);\n
+        }\n
+        break;\n
+      case \'-\':\n
+        // Fall through.\n
+      case \'=\':\n
+        var n = parseInt(param, 10);\n
+        if (isNaN(n) || n < 0) {\n
+          throw new Error(\'Invalid number in diff_fromDelta: \' + param);\n
+        }\n
+        var text = text1.substring(pointer, pointer += n);\n
+        if (tokens[x].charAt(0) == \'=\') {\n
+          diffs[diffsLength++] = [DIFF_EQUAL, text];\n
+        } else {\n
+          diffs[diffsLength++] = [DIFF_DELETE, text];\n
+        }\n
+        break;\n
+      default:\n
+        // Blank tokens are ok (from a trailing \\t).\n
+        // Anything else is an error.\n
+        if (tokens[x]) {\n
+          throw new Error(\'Invalid diff operation in diff_fromDelta: \' +\n
+                          tokens[x]);\n
+        }\n
+    }\n
+  }\n
+  if (pointer != text1.length) {\n
+    throw new Error(\'Delta length (\' + pointer +\n
+        \') does not equal source text length (\' + text1.length + \').\');\n
+  }\n
+  return diffs;\n
+};\n
+\n
+\n
+//  MATCH FUNCTIONS\n
+\n
+\n
+/**\n
+ * Locate the best instance of \'pattern\' in \'text\' near \'loc\'.\n
+ * @param {string} text The text to search.\n
+ * @param {string} pattern The pattern to search for.\n
+ * @param {number} loc The location to search around.\n
+ * @return {number} Best match index or -1.\n
+ */\n
+diff_match_patch.prototype.match_main = function(text, pattern, loc) {\n
+  // Check for null inputs.\n
+  if (text == null || pattern == null || loc == null) {\n
+    throw new Error(\'Null input. (match_main)\');\n
+  }\n
+\n
+  loc = Math.max(0, Math.min(loc, text.length));\n
+  if (text == pattern) {\n
+    // Shortcut (potentially not guaranteed by the algorithm)\n
+    return 0;\n
+  } else if (!text.length) {\n
+    // Nothing to match.\n
+    return -1;\n
+  } else if (text.substring(loc, loc + pattern.length) == pattern) {\n
+    // Perfect match at the perfect spot!  (Includes case of null pattern)\n
+    return loc;\n
+  } else {\n
+    // Do a fuzzy compare.\n
+    return this.match_bitap_(text, pattern, loc);\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * Locate the best instance of \'pattern\' in \'text\' near \'loc\' using the\n
+ * Bitap algorithm.\n
+ * @param {string} text The text to search.\n
+ * @param {string} pattern The pattern to search for.\n
+ * @param {number} loc The location to search around.\n
+ * @return {number} Best match index or -1.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) {\n
+  if (pattern.length > this.Match_MaxBits) {\n
+    throw new Error(\'Pattern too long for this browser.\');\n
+  }\n
+\n
+  // Initialise the alphabet.\n
+  var s = this.match_alphabet_(pattern);\n
+\n
+  var dmp = this;  // \'this\' becomes \'window\' in a closure.\n
+\n
+  /**\n
+   * Compute and return the score for a match with e errors and x location.\n
+   * Accesses loc and pattern through being a closure.\n
+   * @param {number} e Number of errors in match.\n
+   * @param {number} x Location of match.\n
+   * @return {number} Overall score for match (0.0 = good, 1.0 = bad).\n
+   * @private\n
+   */\n
+  function match_bitapScore_(e, x) {\n
+    var accuracy = e / pattern.length;\n
+    var proximity = Math.abs(loc - x);\n
+    if (!dmp.Match_Distance) {\n
+      // Dodge divide by zero error.\n
+      return proximity ? 1.0 : accuracy;\n
+    }\n
+    return accuracy + (proximity / dmp.Match_Distance);\n
+  }\n
+\n
+  // Highest score beyond which we give up.\n
+  var score_threshold = this.Match_Threshold;\n
+  // Is there a nearby exact match? (speedup)\n
+  var best_loc = text.indexOf(pattern, loc);\n
+  if (best_loc != -1) {\n
+    score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);\n
+    // What about in the other direction? (speedup)\n
+    best_loc = text.lastIndexOf(pattern, loc + pattern.length);\n
+    if (best_loc != -1) {\n
+      score_threshold =\n
+          Math.min(match_bitapScore_(0, best_loc), score_threshold);\n
+    }\n
+  }\n
+\n
+  // Initialise the bit arrays.\n
+  var matchmask = 1 << (pattern.length - 1);\n
+  best_loc = -1;\n
+\n
+  var bin_min, bin_mid;\n
+  var bin_max = pattern.length + text.length;\n
+  var last_rd;\n
+  for (var d = 0; d < pattern.length; d++) {\n
+    // Scan for the best match; each iteration allows for one more error.\n
+    // Run a binary search to determine how far from \'loc\' we can stray at this\n
+    // error level.\n
+    bin_min = 0;\n
+    bin_mid = bin_max;\n
+    while (bin_min < bin_mid) {\n
+      if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {\n
+        bin_min = bin_mid;\n
+      } else {\n
+        bin_max = bin_mid;\n
+      }\n
+      bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);\n
+    }\n
+    // Use the result from this iteration as the maximum for the next.\n
+    bin_max = bin_mid;\n
+    var start = Math.max(1, loc - bin_mid + 1);\n
+    var finish = Math.min(loc + bin_mid, text.length) + pattern.length;\n
+\n
+    var rd = Array(finish + 2);\n
+    rd[finish + 1] = (1 << d) - 1;\n
+    for (var j = finish; j >= start; j--) {\n
+      // The alphabet (s) is a sparse hash, so the following line generates\n
+      // warnings.\n
+      var charMatch = s[text.charAt(j - 1)];\n
+      if (d === 0) {  // First pass: exact match.\n
+        rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;\n
+      } else {  // Subsequent passes: fuzzy match.\n
+        rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) |\n
+                (((last_rd[j + 1] | last_rd[j]) << 1) | 1) |\n
+                last_rd[j + 1];\n
+      }\n
+      if (rd[j] & matchmask) {\n
+        var score = match_bitapScore_(d, j - 1);\n
+        // This match will almost certainly be better than any existing match.\n
+        // But check anyway.\n
+        if (score <= score_threshold) {\n
+          // Told you so.\n
+          score_threshold = score;\n
+          best_loc = j - 1;\n
+          if (best_loc > loc) {\n
+            // When passing loc, don\'t exceed our current distance from loc.\n
+            start = Math.max(1, 2 * loc - best_loc);\n
+          } else {\n
+            // Already passed loc, downhill from here on in.\n
+            break;\n
+          }\n
+        }\n
+      }\n
+    }\n
+    // No hope for a (better) match at greater error levels.\n
+    if (match_bitapScore_(d + 1, loc) > score_threshold) {\n
+      break;\n
+    }\n
+    last_rd = rd;\n
+  }\n
+  return best_loc;\n
+};\n
+\n
+\n
+/**\n
+ * Initialise the alphabet for the Bitap algorithm.\n
+ * @param {string} pattern The text to encode.\n
+ * @return {!Object} Hash of character locations.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.match_alphabet_ = function(pattern) {\n
+  var s = {};\n
+  for (var i = 0; i < pattern.length; i++) {\n
+    s[pattern.charAt(i)] = 0;\n
+  }\n
+  for (var i = 0; i < pattern.length; i++) {\n
+    s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1);\n
+  }\n
+  return s;\n
+};\n
+\n
+\n
+//  PATCH FUNCTIONS\n
+\n
+\n
+/**\n
+ * Increase the context until it is unique,\n
+ * but don\'t let the pattern expand beyond Match_MaxBits.\n
+ * @param {!diff_match_patch.patch_obj} patch The patch to grow.\n
+ * @param {string} text Source text.\n
+ * @private\n
+ */\n
+diff_match_patch.prototype.patch_addContext_ = function(patch, text) {\n
+  if (text.length == 0) {\n
+    return;\n
+  }\n
+  var pattern = text.substring(patch.start2, patch.start2 + patch.length1);\n
+  var padding = 0;\n
+\n
+  // Look for the first and last matches of pattern in text.  If two different\n
+  // matches are found, increase the pattern length.\n
+  while (text.indexOf(pattern) != text.lastIndexOf(pattern) &&\n
+         pattern.length < this.Match_MaxBits - this.Patch_Margin -\n
+         this.Patch_Margin) {\n
+    padding += this.Patch_Margin;\n
+    pattern = text.substring(patch.start2 - padding,\n
+                             patch.start2 + patch.length1 + padding);\n
+  }\n
+  // Add one chunk for good luck.\n
+  padding += this.Patch_Margin;\n
+\n
+  // Add the prefix.\n
+  var prefix = text.substring(patch.start2 - padding, patch.start2);\n
+  if (prefix) {\n
+    patch.diffs.unshift([DIFF_EQUAL, prefix]);\n
+  }\n
+  // Add the suffix.\n
+  var suffix = text.substring(patch.start2 + patch.length1,\n
+                              patch.start2 + patch.length1 + padding);\n
+  if (suffix) {\n
+    patch.diffs.push([DIFF_EQUAL, suffix]);\n
+  }\n
+\n
+  // Roll back the start points.\n
+  patch.start1 -= prefix.length;\n
+  patch.start2 -= prefix.length;\n
+  // Extend the lengths.\n
+  patch.length1 += prefix.length + suffix.length;\n
+  patch.length2 += prefix.length + suffix.length;\n
+};\n
+\n
+\n
+/**\n
+ * Compute a list of patches to turn text1 into text2.\n
+ * Use diffs if provided, otherwise compute it ourselves.\n
+ * There are four ways to call this function, depending on what data is\n
+ * available to the caller:\n
+ * Method 1:\n
+ * a = text1, b = text2\n
+ * Method 2:\n
+ * a = diffs\n
+ * Method 3 (optimal):\n
+ * a = text1, b = diffs\n
+ * Method 4 (deprecated, use method 3):\n
+ * a = text1, b = text2, c = diffs\n
+ *\n
+ * @param {string|!Array.<!diff_match_patch.Diff>} a text1 (methods 1,3,4) or\n
+ * Array of diff tuples for text1 to text2 (method 2).\n
+ * @param {string|!Array.<!diff_match_patch.Diff>} opt_b text2 (methods 1,4) or\n
+ * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2).\n
+ * @param {string|!Array.<!diff_match_patch.Diff>} opt_c Array of diff tuples\n
+ * for text1 to text2 (method 4) or undefined (methods 1,2,3).\n
+ * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n
+ */\n
+diff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) {\n
+  var text1, diffs;\n
+  if (typeof a == \'string\' && typeof opt_b == \'string\' &&\n
+      typeof opt_c == \'undefined\') {\n
+    // Method 1: text1, text2\n
+    // Compute diffs from text1 and text2.\n
+    text1 = /** @type {string} */(a);\n
+    diffs = this.diff_main(text1, /** @type {string} */(opt_b), true);\n
+    if (diffs.length > 2) {\n
+      this.diff_cleanupSemantic(diffs);\n
+      this.diff_cleanupEfficiency(diffs);\n
+    }\n
+  } else if (a && typeof a == \'object\' && typeof opt_b == \'undefined\' &&\n
+      typeof opt_c == \'undefined\') {\n
+    // Method 2: diffs\n
+    // Compute text1 from diffs.\n
+    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(a);\n
+    text1 = this.diff_text1(diffs);\n
+  } else if (typeof a == \'string\' && opt_b && typeof opt_b == \'object\' &&\n
+      typeof opt_c == \'undefined\') {\n
+    // Method 3: text1, diffs\n
+    text1 = /** @type {string} */(a);\n
+    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_b);\n
+  } else if (typeof a == \'string\' && typeof opt_b == \'string\' &&\n
+      opt_c && typeof opt_c == \'object\') {\n
+    // Method 4: text1, text2, diffs\n
+    // text2 is not used.\n
+    text1 = /** @type {string} */(a);\n
+    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_c);\n
+  } else {\n
+    throw new Error(\'Unknown call format to patch_make.\');\n
+  }\n
+\n
+  if (diffs.length === 0) {\n
+    return [];  // Get rid of the null case.\n
+  }\n
+  var patches = [];\n
+  var patch = new diff_match_patch.patch_obj();\n
+  var patchDiffLength = 0;  // Keeping our own length var is faster in JS.\n
+  var char_count1 = 0;  // Number of characters into the text1 string.\n
+  var char_count2 = 0;  // Number of characters into the text2 string.\n
+  // Start with text1 (prepatch_text) and apply the diffs until we arrive at\n
+  // text2 (postpatch_text).  We recreate the patches one by one to determine\n
+  // context info.\n
+  var prepatch_text = text1;\n
+  var postpatch_text = text1;\n
+  for (var x = 0; x < diffs.length; x++) {\n
+    var diff_type = diffs[x][0];\n
+    var diff_text = diffs[x][1];\n
+\n
+    if (!patchDiffLength && diff_type !== DIFF_EQUAL) {\n
+      // A new patch starts here.\n
+      patch.start1 = char_count1;\n
+      patch.start2 = char_count2;\n
+    }\n
+\n
+    switch (diff_type) {\n
+      case DIFF_INSERT:\n
+        patch.diffs[patchDiffLength++] = diffs[x];\n
+        patch.length2 += diff_text.length;\n
+        postpatch_text = postpatch_text.substring(0, char_count2) + diff_text +\n
+                         postpatch_text.substring(char_count2);\n
+        break;\n
+      case DIFF_DELETE:\n
+        patch.length1 += diff_text.length;\n
+        patch.diffs[patchDiffLength++] = diffs[x];\n
+        postpatch_text = postpatch_text.substring(0, char_count2) +\n
+                         postpatch_text.substring(char_count2 +\n
+                             diff_text.length);\n
+        break;\n
+      case DIFF_EQUAL:\n
+        if (diff_text.length <= 2 * this.Patch_Margin &&\n
+            patchDiffLength && diffs.length != x + 1) {\n
+          // Small equality inside a patch.\n
+          patch.diffs[patchDiffLength++] = diffs[x];\n
+          patch.length1 += diff_text.length;\n
+          patch.length2 += diff_text.length;\n
+        } else if (diff_text.length >= 2 * this.Patch_Margin) {\n
+          // Time for a new patch.\n
+          if (patchDiffLength) {\n
+            this.patch_addContext_(patch, prepatch_text);\n
+            patches.push(patch);\n
+            patch = new diff_match_patch.patch_obj();\n
+            patchDiffLength = 0;\n
+            // Unlike Unidiff, our patch lists have a rolling context.\n
+            // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff\n
+            // Update prepatch text & pos to reflect the application of the\n
+            // just completed patch.\n
+            prepatch_text = postpatch_text;\n
+            char_count1 = char_count2;\n
+          }\n
+        }\n
+        break;\n
+    }\n
+\n
+    // Update the current character count.\n
+    if (diff_type !== DIFF_INSERT) {\n
+      char_count1 += diff_text.length;\n
+    }\n
+    if (diff_type !== DIFF_DELETE) {\n
+      char_count2 += diff_text.length;\n
+    }\n
+  }\n
+  // Pick up the leftover patch if not empty.\n
+  if (patchDiffLength) {\n
+    this.patch_addContext_(patch, prepatch_text);\n
+    patches.push(patch);\n
+  }\n
+\n
+  return patches;\n
+};\n
+\n
+\n
+/**\n
+ * Given an array of patches, return another array that is identical.\n
+ * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n
+ * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n
+ */\n
+diff_match_patch.prototype.patch_deepCopy = function(patches) {\n
+  // Making deep copies is hard in JavaScript.\n
+  var patchesCopy = [];\n
+  for (var x = 0; x < patches.length; x++) {\n
+    var patch = patches[x];\n
+    var patchCopy = new diff_match_patch.patch_obj();\n
+    patchCopy.diffs = [];\n
+    for (var y = 0; y < patch.diffs.length; y++) {\n
+      patchCopy.diffs[y] = patch.diffs[y].slice();\n
+    }\n
+    patchCopy.start1 = patch.start1;\n
+    patchCopy.start2 = patch.start2;\n
+    patchCopy.length1 = patch.length1;\n
+    patchCopy.length2 = patch.length2;\n
+    patchesCopy[x] = patchCopy;\n
+  }\n
+  return patchesCopy;\n
+};\n
+\n
+\n
+/**\n
+ * Merge a set of patches onto the text.  Return a patched text, as well\n
+ * as a list of true/false values indicating which patches were applied.\n
+ * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n
+ * @param {string} text Old text.\n
+ * @return {!Array.<string|!Array.<boolean>>} Two element Array, containing the\n
+ *      new text and an array of boolean values.\n
+ */\n
+diff_match_patch.prototype.patch_apply = function(patches, text) {\n
+  if (patches.length == 0) {\n
+    return [text, []];\n
+  }\n
+\n
+  // Deep copy the patches so that no changes are made to originals.\n
+  patches = this.patch_deepCopy(patches);\n
+\n
+  var nullPadding = this.patch_addPadding(patches);\n
+  text = nullPadding + text + nullPadding;\n
+\n
+  this.patch_splitMax(patches);\n
+  // delta keeps track of the offset between the expected and actual location\n
+  // of the previous patch.  If there are patches expected at positions 10 and\n
+  // 20, but the first patch was found at 12, delta is 2 and the second patch\n
+  // has an effective expected position of 22.\n
+  var delta = 0;\n
+  var results = [];\n
+  for (var x = 0; x < patches.length; x++) {\n
+    var expected_loc = patches[x].start2 + delta;\n
+    var text1 = this.diff_text1(patches[x].diffs);\n
+    var start_loc;\n
+    var end_loc = -1;\n
+    if (text1.length > this.Match_MaxBits) {\n
+      // patch_splitMax will only provide an oversized pattern in the case of\n
+      // a monster delete.\n
+      start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits),\n
+                                  expected_loc);\n
+      if (start_loc != -1) {\n
+        end_loc = this.match_main(text,\n
+            text1.substring(text1.length - this.Match_MaxBits),\n
+            expected_loc + text1.length - this.Match_MaxBits);\n
+        if (end_loc == -1 || start_loc >= end_loc) {\n
+          // Can\'t find valid trailing context.  Drop this patch.\n
+          start_loc = -1;\n
+        }\n
+      }\n
+    } else {\n
+      start_loc = this.match_main(text, text1, expected_loc);\n
+    }\n
+    if (start_loc == -1) {\n
+      // No match found.  :(\n
+      results[x] = false;\n
+      // Subtract the delta for this failed patch from subsequent patches.\n
+      delta -= patches[x].length2 - patches[x].length1;\n
+    } else {\n
+      // Found a match.  :)\n
+      results[x] = true;\n
+      delta = start_loc - expected_loc;\n
+      var text2;\n
+      if (end_loc == -1) {\n
+        text2 = text.substring(start_loc, start_loc + text1.length);\n
+      } else {\n
+        text2 = text.substring(start_loc, end_loc + this.Match_MaxBits);\n
+      }\n
+      if (text1 == text2) {\n
+        // Perfect match, just shove the replacement text in.\n
+        text = text.substring(0, start_loc) +\n
+               this.diff_text2(patches[x].diffs) +\n
+               text.substring(start_loc + text1.length);\n
+      } else {\n
+        // Imperfect match.  Run a diff to get a framework of equivalent\n
+        // indices.\n
+        var diffs = this.diff_main(text1, text2, false);\n
+        if (text1.length > this.Match_MaxBits &&\n
+            this.diff_levenshtein(diffs) / text1.length >\n
+            this.Patch_DeleteThreshold) {\n
+          // The end points match, but the content is unacceptably bad.\n
+          results[x] = false;\n
+        } else {\n
+          this.diff_cleanupSemanticLossless(diffs);\n
+          var index1 = 0;\n
+          var index2;\n
+          for (var y = 0; y < patches[x].diffs.length; y++) {\n
+            var mod = patches[x].diffs[y];\n
+            if (mod[0] !== DIFF_EQUAL) {\n
+              index2 = this.diff_xIndex(diffs, index1);\n
+            }\n
+            if (mod[0] === DIFF_INSERT) {  // Insertion\n
+              text = text.substring(0, start_loc + index2) + mod[1] +\n
+                     text.substring(start_loc + index2);\n
+            } else if (mod[0] === DIFF_DELETE) {  // Deletion\n
+              text = text.substring(0, start_loc + index2) +\n
+                     text.substring(start_loc + this.diff_xIndex(diffs,\n
+                         index1 + mod[1].length));\n
+            }\n
+            if (mod[0] !== DIFF_DELETE) {\n
+              index1 += mod[1].length;\n
+            }\n
+          }\n
+        }\n
+      }\n
+    }\n
+  }\n
+  // Strip the padding off.\n
+  text = text.substring(nullPadding.length, text.length - nullPadding.length);\n
+  return [text, results];\n
+};\n
+\n
+\n
+/**\n
+ * Add some padding on text start and end so that edges can match something.\n
+ * Intended to be called only from within patch_apply.\n
+ * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n
+ * @return {string} The padding string added to each side.\n
+ */\n
+diff_match_patch.prototype.patch_addPadding = function(patches) {\n
+  var paddingLength = this.Patch_Margin;\n
+  var nullPadding = \'\';\n
+  for (var x = 1; x <= paddingLength; x++) {\n
+    nullPadding += String.fromCharCode(x);\n
+  }\n
+\n
+  // Bump all the patches forward.\n
+  for (var x = 0; x < patches.length; x++) {\n
+    patches[x].start1 += paddingLength;\n
+    patches[x].start2 += paddingLength;\n
+  }\n
+\n
+  // Add some padding on start of first diff.\n
+  var patch = patches[0];\n
+  var diffs = patch.diffs;\n
+  if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) {\n
+    // Add nullPadding equality.\n
+    diffs.unshift([DIFF_EQUAL, nullPadding]);\n
+    patch.start1 -= paddingLength;  // Should be 0.\n
+    patch.start2 -= paddingLength;  // Should be 0.\n
+    patch.length1 += paddingLength;\n
+    patch.length2 += paddingLength;\n
+  } else if (paddingLength > diffs[0][1].length) {\n
+    // Grow first equality.\n
+    var extraLength = paddingLength - diffs[0][1].length;\n
+    diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1];\n
+    patch.start1 -= extraLength;\n
+    patch.start2 -= extraLength;\n
+    patch.length1 += extraLength;\n
+    patch.length2 += extraLength;\n
+  }\n
+\n
+  // Add some padding on end of last diff.\n
+  patch = patches[patches.length - 1];\n
+  diffs = patch.diffs;\n
+  if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) {\n
+    // Add nullPadding equality.\n
+    diffs.push([DIFF_EQUAL, nullPadding]);\n
+    patch.length1 += paddingLength;\n
+    patch.length2 += paddingLength;\n
+  } else if (paddingLength > diffs[diffs.length - 1][1].length) {\n
+    // Grow last equality.\n
+    var extraLength = paddingLength - diffs[diffs.length - 1][1].length;\n
+    diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength);\n
+    patch.length1 += extraLength;\n
+    patch.length2 += extraLength;\n
+  }\n
+\n
+  return nullPadding;\n
+};\n
+\n
+\n
+/**\n
+ * Look through the patches and break up any which are longer than the maximum\n
+ * limit of the match algorithm.\n
+ * Intended to be called only from within patch_apply.\n
+ * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n
+ */\n
+diff_match_patch.prototype.patch_splitMax = function(patches) {\n
+  var patch_size = this.Match_MaxBits;\n
+  for (var x = 0; x < patches.length; x++) {\n
+    if (patches[x].length1 <= patch_size) {\n
+      continue;\n
+    }\n
+    var bigpatch = patches[x];\n
+    // Remove the big old patch.\n
+    patches.splice(x--, 1);\n
+    var start1 = bigpatch.start1;\n
+    var start2 = bigpatch.start2;\n
+    var precontext = \'\';\n
+    while (bigpatch.diffs.length !== 0) {\n
+      // Create one of several smaller patches.\n
+      var patch = new diff_match_patch.patch_obj();\n
+      var empty = true;\n
+      patch.start1 = start1 - precontext.length;\n
+      patch.start2 = start2 - precontext.length;\n
+      if (precontext !== \'\') {\n
+        patch.length1 = patch.length2 = precontext.length;\n
+        patch.diffs.push([DIFF_EQUAL, precontext]);\n
+      }\n
+      while (bigpatch.diffs.length !== 0 &&\n
+             patch.length1 < patch_size - this.Patch_Margin) {\n
+        var diff_type = bigpatch.diffs[0][0];\n
+        var diff_text = bigpatch.diffs[0][1];\n
+        if (diff_type === DIFF_INSERT) {\n
+          // Insertions are harmless.\n
+          patch.length2 += diff_text.length;\n
+          start2 += diff_text.length;\n
+          patch.diffs.push(bigpatch.diffs.shift());\n
+          empty = false;\n
+        } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 &&\n
+                   patch.diffs[0][0] == DIFF_EQUAL &&\n
+                   diff_text.length > 2 * patch_size) {\n
+          // This is a large deletion.  Let it pass in one chunk.\n
+          patch.length1 += diff_text.length;\n
+          start1 += diff_text.length;\n
+          empty = false;\n
+          patch.diffs.push([diff_type, diff_text]);\n
+          bigpatch.diffs.shift();\n
+        } else {\n
+          // Deletion or equality.  Only take as much as we can stomach.\n
+          diff_text = diff_text.substring(0,\n
+              patch_size - patch.length1 - this.Patch_Margin);\n
+          patch.length1 += diff_text.length;\n
+          start1 += diff_text.length;\n
+          if (diff_type === DIFF_EQUAL) {\n
+            patch.length2 += diff_text.length;\n
+            start2 += diff_text.length;\n
+          } else {\n
+            empty = false;\n
+          }\n
+          patch.diffs.push([diff_type, diff_text]);\n
+          if (diff_text == bigpatch.diffs[0][1]) {\n
+            bigpatch.diffs.shift();\n
+          } else {\n
+            bigpatch.diffs[0][1] =\n
+                bigpatch.diffs[0][1].substring(diff_text.length);\n
+          }\n
+        }\n
+      }\n
+      // Compute the head context for the next patch.\n
+      precontext = this.diff_text2(patch.diffs);\n
+      precontext =\n
+          precontext.substring(precontext.length - this.Patch_Margin);\n
+      // Append the end context for this patch.\n
+      var postcontext = this.diff_text1(bigpatch.diffs)\n
+                            .substring(0, this.Patch_Margin);\n
+      if (postcontext !== \'\') {\n
+        patch.length1 += postcontext.length;\n
+        patch.length2 += postcontext.length;\n
+        if (patch.diffs.length !== 0 &&\n
+            patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) {\n
+          patch.diffs[patch.diffs.length - 1][1] += postcontext;\n
+        } else {\n
+          patch.diffs.push([DIFF_EQUAL, postcontext]);\n
+        }\n
+      }\n
+      if (!empty) {\n
+        patches.splice(++x, 0, patch);\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * Take a list of patches and return a textual representation.\n
+ * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n
+ * @return {string} Text representation of patches.\n
+ */\n
+diff_match_patch.prototype.patch_toText = function(patches) {\n
+  var text = [];\n
+  for (var x = 0; x < patches.length; x++) {\n
+    text[x] = patches[x];\n
+  }\n
+  return text.join(\'\');\n
+};\n
+\n
+\n
+/**\n
+ * Parse a textual representation of patches and return a list of Patch objects.\n
+ * @param {string} textline Text representation of patches.\n
+ * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n
+ * @throws {!Error} If invalid input.\n
+ */\n
+diff_match_patch.prototype.patch_fromText = function(textline) {\n
+  var patches = [];\n
+  if (!textline) {\n
+    return patches;\n
+  }\n
+  var text = textline.split(\'\\n\');\n
+  var textPointer = 0;\n
+  var patchHeader = /^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;\n
+  while (textPointer < text.length) {\n
+    var m = text[textPointer].match(patchHeader);\n
+    if (!m) {\n
+      throw new Error(\'Invalid patch string: \' + text[textPointer]);\n
+    }\n
+    var patch = new diff_match_patch.patch_obj();\n
+    patches.push(patch);\n
+    patch.start1 = parseInt(m[1], 10);\n
+    if (m[2] === \'\') {\n
+      patch.start1--;\n
+      patch.length1 = 1;\n
+    } else if (m[2] == \'0\') {\n
+      patch.length1 = 0;\n
+    } else {\n
+      patch.start1--;\n
+      patch.length1 = parseInt(m[2], 10);\n
+    }\n
+\n
+    patch.start2 = parseInt(m[3], 10);\n
+    if (m[4] === \'\') {\n
+      patch.start2--;\n
+      patch.length2 = 1;\n
+    } else if (m[4] == \'0\') {\n
+      patch.length2 = 0;\n
+    } else {\n
+      patch.start2--;\n
+      patch.length2 = parseInt(m[4], 10);\n
+    }\n
+    textPointer++;\n
+\n
+    while (textPointer < text.length) {\n
+      var sign = text[textPointer].charAt(0);\n
+      try {\n
+        var line = decodeURI(text[textPointer].substring(1));\n
+      } catch (ex) {\n
+        // Malformed URI sequence.\n
+        throw new Error(\'Illegal escape in patch_fromText: \' + line);\n
+      }\n
+      if (sign == \'-\') {\n
+        // Deletion.\n
+        patch.diffs.push([DIFF_DELETE, line]);\n
+      } else if (sign == \'+\') {\n
+        // Insertion.\n
+        patch.diffs.push([DIFF_INSERT, line]);\n
+      } else if (sign == \' \') {\n
+        // Minor equality.\n
+        patch.diffs.push([DIFF_EQUAL, line]);\n
+      } else if (sign == \'@\') {\n
+        // Start of next patch.\n
+        break;\n
+      } else if (sign === \'\') {\n
+        // Blank line?  Whatever.\n
+      } else {\n
+        // WTF?\n
+        throw new Error(\'Invalid patch mode "\' + sign + \'" in: \' + line);\n
+      }\n
+      textPointer++;\n
+    }\n
+  }\n
+  return patches;\n
+};\n
+\n
+\n
+/**\n
+ * Class representing one patch operation.\n
+ * @constructor\n
+ */\n
+diff_match_patch.patch_obj = function() {\n
+  /** @type {!Array.<!diff_match_patch.Diff>} */\n
+  this.diffs = [];\n
+  /** @type {?number} */\n
+  this.start1 = null;\n
+  /** @type {?number} */\n
+  this.start2 = null;\n
+  /** @type {number} */\n
+  this.length1 = 0;\n
+  /** @type {number} */\n
+  this.length2 = 0;\n
+};\n
+\n
+\n
+/**\n
+ * Emmulate GNU diff\'s format.\n
+ * Header: @@ -382,8 +481,9 @@\n
+ * Indicies are printed as 1-based, not 0-based.\n
+ * @return {string} The GNU diff string.\n
+ */\n
+diff_match_patch.patch_obj.prototype.toString = function() {\n
+  var coords1, coords2;\n
+  if (this.length1 === 0) {\n
+    coords1 = this.start1 + \',0\';\n
+  } else if (this.length1 == 1) {\n
+    coords1 = this.start1 + 1;\n
+  } else {\n
+    coords1 = (this.start1 + 1) + \',\' + this.length1;\n
+  }\n
+  if (this.length2 === 0) {\n
+    coords2 = this.start2 + \',0\';\n
+  } else if (this.length2 == 1) {\n
+    coords2 = this.start2 + 1;\n
+  } else {\n
+    coords2 = (this.start2 + 1) + \',\' + this.length2;\n
+  }\n
+  var text = [\'@@ -\' + coords1 + \' +\' + coords2 + \' @@\\n\'];\n
+  var op;\n
+  // Escape the body of the patch with %xx notation.\n
+  for (var x = 0; x < this.diffs.length; x++) {\n
+    switch (this.diffs[x][0]) {\n
+      case DIFF_INSERT:\n
+        op = \'+\';\n
+        break;\n
+      case DIFF_DELETE:\n
+        op = \'-\';\n
+        break;\n
+      case DIFF_EQUAL:\n
+        op = \' \';\n
+        break;\n
+    }\n
+    text[x + 1] = op + encodeURI(this.diffs[x][1]) + \'\\n\';\n
+  }\n
+  return text.join(\'\').replace(/%20/g, \' \');\n
+};\n
+\n
+\n
+// Export these global variables so that they survive Google\'s JS compiler.\n
+// In a browser, \'this\' will be \'window\'.\n
+// Users of node.js should \'require\' the uncompressed version since Google\'s\n
+// JS compiler may break the following exports for non-browser environments.\n
+this[\'diff_match_patch\'] = diff_match_patch;\n
+this[\'DIFF_DELETE\'] = DIFF_DELETE;\n
+this[\'DIFF_INSERT\'] = DIFF_INSERT;\n
+this[\'DIFF_EQUAL\'] = DIFF_EQUAL;\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_code_mirror/bt/change_log b/bt5/erp5_code_mirror/bt/change_log
index a92f68ef1a2afdb110dbb9fc4180495e7aaac4a9..db5b273fd227e16e6223ac1dde7c66c744e8bf4a 100644
--- a/bt5/erp5_code_mirror/bt/change_log
+++ b/bt5/erp5_code_mirror/bt/change_log
@@ -1,3 +1,6 @@
+2015-01-22 arnaud.fontaine
+* Update CodeMirror to 4.11.
+
 2015-01-16 arnaud.fontaine
 * Add linter to check Python syntax in real time and display warnings/errors icons next to the line number (likewise Ace Editor implementation).
 
diff --git a/bt5/erp5_code_mirror/bt/comment b/bt5/erp5_code_mirror/bt/comment
new file mode 100644
index 0000000000000000000000000000000000000000..766ff76161cace6e6817450bac45669a33645f39
--- /dev/null
+++ b/bt5/erp5_code_mirror/bt/comment
@@ -0,0 +1,5 @@
+CodeMirror is available at:
+http://codemirror.net
+
+diff_match_patch (used by CodeMirror Merge addon):
+https://code.google.com/p/google-diff-match-patch
\ No newline at end of file
diff --git a/bt5/erp5_code_mirror/bt/copyright_list b/bt5/erp5_code_mirror/bt/copyright_list
index 7c84e6aa072dd68bc324b3b57b5817d895a14e5b..51cd3130bd0da6e346997b136ca058396374fa55 100644
--- a/bt5/erp5_code_mirror/bt/copyright_list
+++ b/bt5/erp5_code_mirror/bt/copyright_list
@@ -1 +1,8 @@
-Copyright (c) 2011 Nexedi SA
\ No newline at end of file
+code_mirror_support:
+Copyright (c) 2011-2014 Nexedi SA
+
+CodeMirror (under MIT license):
+Copyright (c) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
+
+diff_match_patch (under Apache 2.0 license)
+Copyright (c) 2006 Google Inc.
\ No newline at end of file
diff --git a/bt5/erp5_code_mirror/bt/license b/bt5/erp5_code_mirror/bt/license
deleted file mode 100644
index c241a790285090d03185aef52317717bc1285a85..0000000000000000000000000000000000000000
--- a/bt5/erp5_code_mirror/bt/license
+++ /dev/null
@@ -1 +0,0 @@
-zlib-style License
\ No newline at end of file
diff --git a/bt5/erp5_code_mirror/bt/maintainer_list b/bt5/erp5_code_mirror/bt/maintainer_list
index d4596cc42ae7ac2a518c354d890d38edbe46ef5f..3e5e9dc2248e6a816185adbf3f1fb828eb35ea6a 100644
--- a/bt5/erp5_code_mirror/bt/maintainer_list
+++ b/bt5/erp5_code_mirror/bt/maintainer_list
@@ -1 +1,2 @@
-seb
\ No newline at end of file
+seb
+arnaud.fontaine
\ No newline at end of file