[pytango] 98/483: added notebook example

Sandor Bodo-Merle sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:14:28 UTC 2017


This is an automated email from the git hooks/post-receive script.

sbodomerle-guest pushed a commit to annotated tag bliss_8.10
in repository pytango.

commit d8b36f3e26c24c5bdcb045603395c911eb9f8636
Author: tiagocoutinho <tiagocoutinho at 4e9c00fd-8f2e-0410-aa12-93ce3db5e235>
Date:   Mon Feb 13 09:12:55 2012 +0000

    added notebook example
    
    git-svn-id: http://svn.code.sf.net/p/tango-cs/code/bindings/PyTango/trunk@19269 4e9c00fd-8f2e-0410-aa12-93ce3db5e235
---
 .../examples/notebooks/notebook_launcher.py        |  288 ++
 .../notebooks/static/IPy_Notebook_logo.svg         |  305 +++
 .../examples/notebooks/static/ace/ace.js           |    1 +
 .../examples/notebooks/static/ace/mode-html.js     |    1 +
 .../examples/notebooks/static/ace/mode-markdown.js |    1 +
 .../examples/notebooks/static/ace/mode-python.js   |    1 +
 .../notebooks/static/ace/theme-textmate.js         |    1 +
 .../examples/notebooks/static/codemirror/LICENSE   |   19 +
 .../notebooks/static/codemirror/README-IPython.rst |   33 +
 .../examples/notebooks/static/codemirror/README.md |    6 +
 .../notebooks/static/codemirror/lib/codemirror.css |  104 +
 .../notebooks/static/codemirror/lib/codemirror.js  | 2761 ++++++++++++++++++++
 .../static/codemirror/lib/util/dialog.css          |   23 +
 .../notebooks/static/codemirror/lib/util/dialog.js |   63 +
 .../static/codemirror/lib/util/foldcode.js         |   66 +
 .../static/codemirror/lib/util/formatting.js       |  291 +++
 .../static/codemirror/lib/util/javascript-hint.js  |   83 +
 .../static/codemirror/lib/util/overlay.js          |   51 +
 .../static/codemirror/lib/util/runmode.js          |   27 +
 .../notebooks/static/codemirror/lib/util/search.js |  114 +
 .../static/codemirror/lib/util/searchcursor.js     |  117 +
 .../static/codemirror/lib/util/simple-hint.css     |   16 +
 .../static/codemirror/lib/util/simple-hint.js      |   66 +
 .../notebooks/static/codemirror/mode/css/css.js    |  124 +
 .../static/codemirror/mode/css/index.html          |   55 +
 .../static/codemirror/mode/htmlmixed/htmlmixed.js  |   83 +
 .../static/codemirror/mode/htmlmixed/index.html    |   51 +
 .../static/codemirror/mode/javascript/index.html   |   77 +
 .../codemirror/mode/javascript/javascript.js       |  360 +++
 .../static/codemirror/mode/markdown/index.html     |  339 +++
 .../static/codemirror/mode/markdown/markdown.js    |  242 ++
 .../static/codemirror/mode/python/LICENSE.txt      |   21 +
 .../static/codemirror/mode/python/index.html       |  122 +
 .../static/codemirror/mode/python/python.js        |  333 +++
 .../static/codemirror/mode/rst/index.html          |  525 ++++
 .../notebooks/static/codemirror/mode/rst/rst.js    |  326 +++
 .../static/codemirror/mode/xml/index.html          |   44 +
 .../notebooks/static/codemirror/mode/xml/xml.js    |  252 ++
 .../notebooks/static/codemirror/theme/cobalt.css   |   18 +
 .../notebooks/static/codemirror/theme/eclipse.css  |   25 +
 .../notebooks/static/codemirror/theme/elegant.css  |   10 +
 .../notebooks/static/codemirror/theme/ipython.css  |   40 +
 .../notebooks/static/codemirror/theme/monokai.css  |   28 +
 .../notebooks/static/codemirror/theme/neat.css     |    9 +
 .../notebooks/static/codemirror/theme/night.css    |   21 +
 .../notebooks/static/codemirror/theme/rubyblue.css |   21 +
 .../examples/notebooks/static/css/base.css         |   73 +
 .../examples/notebooks/static/css/boilerplate.css  |   73 +
 .../examples/notebooks/static/css/layout.css       |  130 +
 .../examples/notebooks/static/css/notebook.css     |  399 +++
 .../notebooks/static/css/printnotebook.css         |    5 +
 .../notebooks/static/css/projectdashboard.css      |   82 +
 .../examples/notebooks/static/css/renderedhtml.css |   63 +
 .../notebooks/static/dateformat/date.format.js     |  125 +
 .../examples/notebooks/static/favicon.ico          |  Bin 0 -> 1226 bytes
 .../examples/notebooks/static/ipynblogo.png        |  Bin 0 -> 7152 bytes
 .../base/images/ui-bg_flat_0_aaaaaa_40x100.png     |  Bin 0 -> 180 bytes
 .../base/images/ui-bg_flat_75_ffffff_40x100.png    |  Bin 0 -> 178 bytes
 .../base/images/ui-bg_glass_55_fbf9ee_1x400.png    |  Bin 0 -> 120 bytes
 .../base/images/ui-bg_glass_65_ffffff_1x400.png    |  Bin 0 -> 105 bytes
 .../base/images/ui-bg_glass_75_dadada_1x400.png    |  Bin 0 -> 111 bytes
 .../base/images/ui-bg_glass_75_e6e6e6_1x400.png    |  Bin 0 -> 110 bytes
 .../base/images/ui-bg_glass_95_fef1ec_1x400.png    |  Bin 0 -> 119 bytes
 .../ui-bg_highlight-soft_75_cccccc_1x100.png       |  Bin 0 -> 101 bytes
 .../themes/base/images/ui-icons_222222_256x240.png |  Bin 0 -> 4369 bytes
 .../themes/base/images/ui-icons_2e83ff_256x240.png |  Bin 0 -> 4369 bytes
 .../themes/base/images/ui-icons_454545_256x240.png |  Bin 0 -> 4369 bytes
 .../themes/base/images/ui-icons_888888_256x240.png |  Bin 0 -> 4369 bytes
 .../themes/base/images/ui-icons_cd0a0a_256x240.png |  Bin 0 -> 4369 bytes
 .../jquery/css/themes/base/jquery-ui.min.css       |    1 +
 .../notebooks/static/jquery/js/jquery-1.7.1.min.js |    4 +
 .../notebooks/static/jquery/js/jquery-ui.min.js    |   16 +
 .../notebooks/static/jquery/js/jquery.autogrow.js  |   42 +
 .../examples/notebooks/static/js/cell.js           |  150 ++
 .../examples/notebooks/static/js/codecell.js       |  850 ++++++
 .../examples/notebooks/static/js/fulleditwidget.js |  119 +
 .../examples/notebooks/static/js/kernel.js         |  235 ++
 .../examples/notebooks/static/js/kernelstatus.js   |   65 +
 .../examples/notebooks/static/js/layout.js         |   48 +
 .../examples/notebooks/static/js/loginmain.js      |   30 +
 .../examples/notebooks/static/js/loginwidget.js    |   42 +
 .../examples/notebooks/static/js/menubar.js        |  151 ++
 .../examples/notebooks/static/js/namespace.js      |   30 +
 .../examples/notebooks/static/js/notebook.js       | 1172 +++++++++
 .../examples/notebooks/static/js/notebooklist.js   |  251 ++
 .../examples/notebooks/static/js/notebookmain.js   |  116 +
 .../examples/notebooks/static/js/pager.js          |  102 +
 .../notebooks/static/js/printnotebookmain.js       |   94 +
 .../notebooks/static/js/projectdashboardmain.js    |   42 +
 .../examples/notebooks/static/js/quickhelp.js      |   69 +
 .../examples/notebooks/static/js/savewidget.js     |  179 ++
 .../examples/notebooks/static/js/textcell.js       |  290 ++
 .../examples/notebooks/static/js/utils.js          |  101 +
 .../examples/notebooks/static/pagedown/LICENSE.txt |   32 +
 .../static/pagedown/Markdown.Converter.js          | 1318 ++++++++++
 .../examples/notebooks/static/prettify/COPYING     |  202 ++
 .../notebooks/static/prettify/prettify.css         |   48 +
 .../examples/notebooks/static/prettify/prettify.js |   28 +
 .../examples/notebooks/static/pytangologo.png      |  Bin 0 -> 60409 bytes
 .../notebooks/static/pytangologo_original.png      |  Bin 0 -> 1206330 bytes
 .../examples/notebooks/templates/layout.html       |   86 +
 .../examples/notebooks/templates/login.html        |   26 +
 .../examples/notebooks/templates/logout.html       |   28 +
 .../examples/notebooks/templates/notebook.html     |  207 ++
 .../notebooks/templates/printnotebook.html         |  104 +
 .../notebooks/templates/projectdashboard.html      |   43 +
 106 files changed, 14835 insertions(+)

diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/notebook_launcher.py b/PyTango/ipython/ipython_00_12/examples/notebooks/notebook_launcher.py
new file mode 100644
index 0000000..94e80c8
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/notebook_launcher.py
@@ -0,0 +1,288 @@
+"""==============================
+Branded IPython Notebook Launcher
+=================================
+
+Executing this module will create an overlay over ipython notebooks own static
+files and templates and overrides static files and templates and copies over all
+example notebooks into a temporary folder and launches the ipython notebook server.
+
+You can use this to offer an interactive tutorial for your library/framework/...
+
+
+To use this script properly, create three folders in the same folder this script
+resides in:
+
+    parent
+    |
+    +- this_script.py
+    |
+    +- templates/
+    |  |
+    |  ...
+    |
+    +- static/
+    |  |
+    |  ...
+    |
+    |+ notebooks/
+    |  |
+    |  ...
+
+
+The folders templates and static may be empty, but must exist. Read the
+docstring of merge_dirs to find out how these folders are treated.
+
+If you put those folders anywhere else, change the variables in the
+Configuration section below.
+
+In your setup.py you can add the following to your entry_points:
+
+      [console_scripts]
+      my_framework_tutorial = framework.examples.notebooks.this_script:launch_notebook_server
+
+and a binary will be created for the user's system that launches this script.
+
+Additionally, add these package_data entries, so that the static files
+get installed, too:
+
+      package_data = {
+          'framework.examples.notebooks':
+              ['notebooks/*', 'static/**/*', 'templates/*'],
+          }
+
+
+License
+-------
+
+Copyright (c) 2011, Timo Paulssen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * The name of the author may not be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL TIMO PAULSSEN BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Revision History
+----------------
+
+   1.0 2011-12-19
+        First release.
+
+   1.1 2011-12-20
+        Don't use os.system for starting the notebook.
+        Cleaner clean-up.
+"""
+
+import os
+import shutil
+import tempfile
+from itertools import izip
+
+try:
+    from IPython.frontend.html.notebook import notebookapp
+except ImportError:
+    print "You don't seem to have IPython installed, or the dependencies of "
+    print "ipython notebook are not met."
+
+    raise
+
+"""==================
+Configuration section
+=====================
+"""
+
+"""This is the base path in which the modified templates/, static/ and the
+example notebooks can be found:"""
+BASE_PATH = os.path.dirname(__file__)
+
+
+"""By default, the template, static and notebooks folder will be assumed inside
+BASE_PATH:"""
+TEMPLATE_PATH = os.path.join(BASE_PATH, "templates")
+STATIC_PATH = os.path.join(BASE_PATH, "static")
+EXAMPLES_PATH = os.path.join(BASE_PATH, "notebooks")
+
+
+"""These are the folders from which the original templates and static files are
+taken. You should not have to change this. It will usually be correct."""
+NOTEBOOK_BASE_PATH = os.path.dirname(notebookapp.__file__)
+NOTEBOOK_TEMPLATE_PATH = os.path.join(NOTEBOOK_BASE_PATH, "templates")
+NOTEBOOK_STATIC_PATH = os.path.join(NOTEBOOK_BASE_PATH, "static")
+
+"""This name will be the prefix for the temporary folder"""
+PROJECT_NAME = "ITango"
+
+
+
+"""These extra arguments go directly between the tornado arguments and the
+arguments passed to this script on the commandline:"""
+#notebook_extra_args = ["--gui=qt"] # for example
+notebook_extra_args = ["--pylab=inline"]
+
+
+"""=========
+Code section
+============
+"""
+
+def merge_dirs(base, overlay, target, preserve_originals=False):
+    """This function merges a base and an overlay folder into a target folder.
+
+    If a folder exists in base or overlay only, it will be symlinked
+    into the target.
+
+    If a folder exists in both, the folder is created in the target and
+    merging continues with the contents of both folders.
+
+    If a file exists in base or overlay only, it will be symlinked from base.
+
+    If a file exists in both and preserve_originals is True, the file from
+    base will be symlinked here with a original_ prefix. The file from the
+    overlay will be symlinked into the target.
+    """
+
+    def replace_prefix(prefix, path, new_prefix):
+        assert path.startswith(prefix)
+        if path.startswith("/"):
+            path = path[1:]
+        return os.path.join(new_prefix, path[len(prefix):])
+
+    base_w = os.walk(base, followlinks=True)
+    overlay_w = os.walk(overlay, followlinks=True)
+
+    from_base_dirs = []
+    from_over_dirs = []
+    from_base_files = []
+    from_over_files = []
+    preserved_originals = []
+
+    # walk the base and overlay trees in parallel
+    for (base_t, over_t) in izip(base_w, overlay_w):
+        (base_path, base_dirs, base_files) = base_t
+        (over_path, over_dirs, over_files) = over_t
+
+        # don't recurse into dirs that are only in base or only in overlay.
+        # instead, just symlink them.
+        # this keeps both walkers in sync.
+        for subdir in set(base_dirs[:] + over_dirs[:]):
+            if subdir not in over_dirs:
+                base_dirs.remove(subdir)
+                from_base_dirs.append(os.path.join(base_path, subdir))
+            elif subdir not in base_dirs:
+                over_dirs.remove(subdir)
+                from_over_dirs.append(os.path.join(base_path, subdir))
+
+        for fn in set(base_files[:] + over_files[:]):
+            if fn in over_files and fn in base_files and preserve_originals:
+                preserved_originals.append(os.path.join(base_path, fn))
+            if fn not in over_files:
+                from_base_files.append(os.path.join(base_path, fn))
+            else:
+                from_over_files.append(os.path.join(over_path, fn))
+
+    # link full directories over
+    for source, dirlist in ((base, from_base_dirs), (overlay, from_over_dirs)):
+        for dir_link in dirlist:
+            os.symlink(dir_link, replace_prefix(source, dir_link, target))
+
+    # link files over.
+    for source, filelist in ((base, from_base_files),
+                             (overlay, from_over_files),
+                             (base, preserved_originals)):
+        for file_link in filelist:
+            target_file = replace_prefix(source, file_link, target)
+
+            # preserved originals get an original_ prefix
+            if filelist is preserved_originals:
+                tfp, tfn = os.path.dirname(target_file), os.path.basename(target_file)
+                target_file = os.path.join(tfp, "original_" + tfn)
+
+            parent_dir = os.path.dirname(target_file)
+            if not os.path.exists(parent_dir):
+                os.makedirs(parent_dir)
+            try:
+                os.symlink(file_link, target_file)
+            except:
+                print "failed to make simbolic link", file_link, "to", target_file
+                print source, parent_dir, target
+
+def create_overlay():
+    """This function copies all files from the source to the target and then
+    links all missing files from IPython itself to the target.
+
+    Templates that are overrided will be linked to orig_{filename}, so that
+    changes to templates can just use tornadowebs own template extension scheme.
+
+    It returns a tuple with the temporary path as well as a dictionary with keys
+    'template_path' and 'static_path', which are absolute paths to the merged
+    templates and static files."""
+
+    # create the temporary folder where overlay and base are merged
+    path = tempfile.mkdtemp(prefix=PROJECT_NAME + "_tutorial")
+
+    template_path = os.path.join(path, "templates")
+    static_path = os.path.join(path, "static")
+    os.mkdir(template_path)
+    os.mkdir(static_path)
+
+    merge_dirs(NOTEBOOK_TEMPLATE_PATH, TEMPLATE_PATH, template_path, True)
+    merge_dirs(NOTEBOOK_STATIC_PATH, STATIC_PATH, static_path)
+
+    return path, {'template_path': template_path, 'static_path': static_path}
+
+def copy_example_notebooks(target_path):
+    shutil.copytree(EXAMPLES_PATH, os.path.join(target_path, "notebooks"))
+
+def launch_notebook_server():
+    import sys
+    import signal
+    base_path, settings = create_overlay()
+    copy_example_notebooks(base_path)
+
+    print
+    print "running notebook overlay from", base_path
+    print
+    print "hit ctrl-c to exit the tutorial"
+    print
+
+    app = notebookapp.NotebookApp()
+    app.initialize(argv=[
+              '''--NotebookApp.webapp_settings=%s''' % (settings),
+              '''--NotebookManager.notebook_dir="%s"''' % (os.path.join(base_path, "notebooks"))] +
+              notebook_extra_args +
+              sys.argv[1:])
+
+    # somewhere in initialize, the SIGINT handler gets set to be ignored.
+    # we have to undo that
+    signal.signal(signal.SIGINT, signal.default_int_handler)
+
+    try:
+        app.start()
+    except KeyboardInterrupt:
+        pass
+    finally:
+        print
+        print "deleting", base_path
+        shutil.rmtree(base_path)
+
+    print "goodbye"
+
+if __name__ == "__main__":
+    launch_notebook_server()
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/IPy_Notebook_logo.svg b/PyTango/ipython/ipython_00_12/examples/notebooks/static/IPy_Notebook_logo.svg
new file mode 100644
index 0000000..7aa11b4
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/IPy_Notebook_logo.svg
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xml:space="preserve"
+   width="1100"
+   height="160"
+   style="fill-rule:evenodd"
+   viewBox="0 0 1100 159.9984"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="IPy_Notebook_logo.svg"
+   inkscape:export-filename="ipynblogo.png"
+   inkscape:export-xdpi="39.83239"
+   inkscape:export-ydpi="39.83239"><metadata
+   id="metadata121"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1843"
+   inkscape:window-height="1176"
+   id="namedview119"
+   showgrid="false"
+   showguides="true"
+   inkscape:guide-bbox="true"
+   inkscape:zoom="1.4837597"
+   inkscape:cx="535.88673"
+   inkscape:cy="66.092696"
+   inkscape:window-x="77"
+   inkscape:window-y="0"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="svg2"><sodipodi:guide
+     orientation="0,1"
+     position="338.089,21.683168"
+     id="guide3042" /><sodipodi:guide
+     orientation="0,1"
+     position="-40.48922,128.61282"
+     id="guide3815" /><sodipodi:guide
+     orientation="1,0"
+     position="0,292.95141"
+     id="guide3817" /></sodipodi:namedview>
+ <defs
+   id="defs4">
+  <font
+   id="FontID0"
+   font-variant="normal"
+   font-weight="400"
+   horiz-origin-x="0"
+   horiz-origin-y="0"
+   horiz-adv-x="90"
+   vert-origin-x="45"
+   vert-origin-y="90"
+   vert-adv-y="90"
+   style="font-variant:normal;font-weight:400">
+	<font-face
+   font-family="Droid Sans Mono"
+   id="font-face7">
+	</font-face>
+   <missing-glyph
+   id="missing-glyph9"><path
+     d="M0 0z"
+     id="path11" /></missing-glyph>
+   <glyph
+   unicode=" "
+   horiz-adv-x="600"
+   id="glyph13" />
+   <glyph
+   unicode=":"
+   horiz-adv-x="600"
+   id="glyph15"><path
+     d="M299.831 549.838c41.3387,0 62.0033,-22.6678 62.0033,-67.8333 0,-45.3356 -20.6646,-68.0034 -62.0033,-68.0034 -41.3293,0 -61.9939,22.6678 -61.9939,68.0034 0,45.1655 20.6646,67.8333 61.9939,67.8333zm0 -427.834c41.3387,0 62.0033,-22.5072 62.0033,-67.8333 0,-45.5057 -20.6646,-68.3341 -62.0033,-68.3341 -41.3293,0 -61.9939,22.8284 -61.9939,68.3341 0,45.3261 20.6646,67.8333 61.9939,67.8333z"
+     id="path17" /></glyph>
+   <glyph
+   unicode="C"
+   horiz-adv-x="600"
+   id="glyph19"><path
+     d="M548.841 98.1632l0 -79.1712c-47.5084,-19.1621 -105.845,-28.8282 -174.84,-28.8282 -100.488,0 -177.504,32.0029 -230.994,95.8388 -53.3477,63.6657 -79.9932,154.317 -79.9932,271.841 0,112.648 29.14,201.826 87.3065,267.646 58.3366,65.6783 138.018,98.6734 238.846,98.6734 71.6594,0 133.993,-14.0031 187,-42.0092l-38.0124 -76.1664c-50.1446,25.3416 -99.8072,38.0124 -148.988,38.0124 -69.987,0 -125.829,-25.8235 -167.498,-77.3286 -41.669,-51.6753 -62.5035,-121.492 -62.5035,-209.677 0,-93.486 1 [...]
+     id="path21" /></glyph>
+   <glyph
+   unicode="I"
+   horiz-adv-x="600"
+   id="glyph23"><path
+     d="M488.838 0l-379.013 0 0 60.0064 144.001 9.83275 0 574.162 -144.001 9.83275 0 60.0064 379.013 0 0 -60.0064 -143.665 -9.83275 0 -574.162 143.665 -9.83275 0 -60.0064z"
+     id="path25" /></glyph>
+   <glyph
+   unicode="]"
+   horiz-adv-x="600"
+   id="glyph27"><path
+     d="M141.166 -85.0018l168.832 0 0 726.172 -168.832 0 0 72.6616 257.831 0 0 -871.996 -257.831 0 0 73.1624z"
+     id="path29" /></glyph>
+   <glyph
+   unicode="["
+   horiz-adv-x="600"
+   id="glyph31"><path
+     d="M458.997 -158.164l-257.831 0 0 871.996 257.831 0 0 -72.6616 -168.993 0 0 -726.172 168.993 0 0 -73.1624z"
+     id="path33" /></glyph>
+   <glyph
+   unicode="P"
+   horiz-adv-x="600"
+   id="glyph35"><path
+     d="M176.83 277.833l0 -277.833 -90.8334 0 0 713.84 197.169 0c167.334,0 251.01,-69.6797 251.01,-209.004 0,-71.1679 -22.5002,-126.834 -67.6777,-166.997 -45.0004,-40.0043 -110.499,-60.0064 -196.496,-60.0064l-93.172 0zm0 77.1738l83.0026 0c64.3292,0 110.499,11.6576 138.332,35.1676 27.8329,23.3329 41.8291,59.9887 41.8291,109.826 0,90.8334 -54.9926,136.17 -165.155,136.17l-98.0086 0 0 -281.164z"
+     id="path37" /></glyph>
+   <glyph
+   unicode="g"
+   horiz-adv-x="600"
+   id="glyph39"><path
+     d="M549.833 536.17l0 -55.1619 -95.6687 -13.181c21.1747,-27.666 31.6628,-62.3335 31.6628,-104.002 0,-52.4973 -17.3196,-94.1663 -51.9871,-125.319 -34.6675,-31.0108 -82.9979,-46.6863 -144.849,-46.6863 -17.8298,0 -31.8329,1.02047 -41.9808,3.00471 -32.5132,-18.17 -48.8406,-39.8265 -48.8406,-64.998 0,-27.3258 26.3337,-40.9887 78.6609,-40.9887l91.3317 0c56.6642,0 100.006,-12.5007 129.826,-37.5021 30.0187,-25.1715 45.0139,-61.0012 45.0139,-107.489 0,-122.683 -92.012,-184.024 -275.838,-184.0 [...]
+     id="path41" /></glyph>
+   <glyph
+   unicode="m"
+   horiz-adv-x="600"
+   id="glyph43"><path
+     d="M477.011 0l0 345.173c0,47.48 -4.33698,80.6735 -12.8409,99.1553 -8.67396,18.5101 -23.1589,27.836 -43.3415,27.836 -28.3179,0 -48.8406,-13.4928 -61.6532,-40.5068 -12.8409,-26.9857 -19.3322,-72.3114 -19.3322,-135.835l0 -295.822 -78.6893 0 0 345.173c0,84.6703 -20.3243,126.991 -61.0012,126.991 -27.3258,0 -46.8281,-13.0109 -58.4784,-38.8344 -11.8487,-25.8235 -17.6881,-77.6688 -17.6881,-155.508l0 -277.822 -78.9727 0 0 536.17 61.9933 0 13.1527 -72.3397 4.84721 0c21.8266,54.68 54.4815,82.0 [...]
+     id="path45" /></glyph>
+   <glyph
+   unicode="i"
+   horiz-adv-x="600"
+   id="glyph47"><path
+     d="M309.173 756.846c34.4974,0 51.6469,-18.5101 51.6469,-55.6721 0,-18.8503 -5.15902,-32.9951 -15.307,-42.1793 -10.3464,-9.32593 -22.5069,-14.0031 -36.3399,-14.0031 -34.8376,0 -52.3272,18.6802 -52.3272,56.1823 0,37.162 17.4897,55.6721 52.3272,55.6721zm-45.0139 -291.003l-131.328 10.148 0 60.1791 220.166 0 0 -466.325 171.835 -9.83616 0 -60.0091 -428.652 0 0 60.0091 167.98 9.83616 0 395.998z"
+     id="path49" /></glyph>
+   <glyph
+   unicode="c"
+   horiz-adv-x="600"
+   id="glyph51"><path
+     d="M518 517.178l-30.1604 -77.1869c-48.8406,18.5101 -92.4939,27.836 -130.846,27.836 -120.84,0 -181.161,-67.3224 -181.161,-201.655 0,-132.179 58.6768,-198.339 176.172,-198.339 51.165,0 103.322,10.1763 156.84,30.3305l0 -78.1507c-43.6816,-19.8424 -97.171,-29.8486 -160.667,-29.8486 -83.6782,0 -148.676,23.6691 -194.852,71.1775 -46.1477,47.3383 -69.335,115.313 -69.335,203.838 0,91.4734 23.6691,161.149 70.8373,208.997 47.1682,47.8202 113.498,71.6594 199.161,71.6594 58.0248,0 112.676,-9.496  [...]
+     id="path53" /></glyph>
+   <glyph
+   unicode="a"
+   horiz-adv-x="600"
+   id="glyph55"><path
+     d="M436.986 0l-17.9999 74.1539 -3.99683 0c-25.0014,-31.4927 -50.6548,-53.3193 -77.1586,-65.65 -26.3337,-12.1606 -60.3209,-18.34 -101.99,-18.34 -53.0075,0 -94.6766,14.0031 -124.667,42.0092 -30.1604,28.0061 -45.184,67.3224 -45.184,117.665 0,108.169 82.9979,164.834 249.022,169.993l98.9852 3.34486 0 33.8171c0,76.8468 -39.6564,115.171 -118.998,115.171 -47.9902,0 -101.338,-13.3228 -160.156,-39.9966l-30.8408 66.8405c63.8358,31.3226 126.169,46.8281 187,46.8281 73.8421,0 127.331,-14.1731 160 [...]
+     id="path57" /></glyph>
+   <glyph
+   unicode="e"
+   horiz-adv-x="600"
+   id="glyph59"><path
+     d="M535.178 251.006l-377.998 0c2.66455,-122.172 58.6484,-183.174 167.98,-183.174 63.4957,0 123.675,12.3306 180.679,37.162l0 -78.1507c-53.9997,-24.3495 -113.328,-36.6801 -177.674,-36.6801 -79.8231,0 -143.659,24.3495 -191.507,72.9917 -47.8202,48.6706 -71.6594,115.681 -71.6594,201.003 0,86.6829 21.9967,155.168 66.1602,205.851 44.0218,50.6548 103.01,75.8263 177.023,75.8263 68.9948,0 123.987,-21.6566 165.145,-65.3382 41.1871,-43.6533 61.8516,-101.82 61.8516,-174.33l0 -55.1619zm-376.013 7 [...]
+     id="path61" /></glyph>
+   <glyph
+   unicode="n"
+   horiz-adv-x="600"
+   id="glyph63"><path
+     d="M433.173 0l0 345.174c0,84.668 -38.835,126.993 -116.345,126.993 -99.8335,0 -149.83,-64.8253 -149.83,-194.334l0 -277.833 -88.8314 0 0 536.16 71.664 0 13.3407 -72.3195 4.83665 0c33.4845,54.6559 88.1582,81.9928 163.986,81.9928 126.674,0 190.011,-65.1619 190.011,-195.663l0 -350.17 -88.8314 0z"
+     id="path65" /></glyph>
+   <glyph
+   unicode="o"
+   horiz-adv-x="600"
+   id="glyph67"><path
+     d="M297.835 -9.83275c-70.3352,0 -128.162,25.3348 -173.499,76.0045 -45.4964,50.6697 -68.1738,118.17 -68.1738,202.82 0,85.6778 22.0041,153.178 66.1718,202.679 44.1677,49.5004 103.501,74.162 178.495,74.162 70.8313,0 129.013,-25.1577 174.332,-75.6679 45.1775,-50.3331 67.8371,-117.497 67.8371,-201.173 0,-86.1562 -22.323,-154.33 -67.0045,-203.99 -44.4866,-49.837 -103.997,-74.8352 -178.159,-74.8352zm2.00198 73.8254c100.826,0 151.336,68.3332 151.336,205 0,135.515 -50.8469,203.175 -152.346,2 [...]
+     id="path69" /></glyph>
+   <glyph
+   unicode="h"
+   horiz-adv-x="600"
+   id="glyph71"><path
+     d="M433.173 0l0 345.174c0,84.668 -38.835,126.993 -116.345,126.993 -99.8335,0 -149.83,-64.8253 -149.83,-194.334l0 -277.833 -88.8314 0 0 759.833 88.8314 0 0 -225.657 -3.8268 -70.3352 4.83665 0c33.4845,54.6559 88.1582,81.9928 163.986,81.9928 126.674,0 190.011,-65.1619 190.011,-195.663l0 -350.17 -88.8314 0z"
+     id="path73" /></glyph>
+   <glyph
+   unicode="u"
+   horiz-adv-x="600"
+   id="glyph75"><path
+     d="M450.167 0l-13.181 71.8295 -4.81887 0c-34.1573,-54.5099 -88.4971,-81.6656 -163.161,-81.6656 -127.161,0 -190.827,65.3382 -190.827,195.844l0 350.162 88.8089 0 0 -345.173c0,-84.6703 38.3525,-126.991 115.171,-126.991 52.4973,0 90.6797,14.9952 114.831,45.1556 24.0093,30.0187 36.1699,79.6814 36.1699,148.676l0 278.332 88.8372 0 0 -536.17 -71.8295 0z"
+     id="path77" /></glyph>
+   <glyph
+   unicode="p"
+   horiz-adv-x="600"
+   id="glyph79"><path
+     d="M165.996 67.8326l-5.83933 0c3.85509,-42.0092 5.83933,-68.3429 5.83933,-79.0011l0 -229.01 -88.8372 0 0 776.348 71.8295 0 13.181 -72.3397 3.82675 0c35.8297,54.68 88.1569,82.0058 157.18,82.0058 65.4799,0 116.815,-24.3495 154.147,-72.9917 37.1903,-48.6706 55.8422,-116.503 55.8422,-203.838 0,-87.8451 -18.6519,-156.33 -56.154,-205.34 -37.332,-49.0107 -88.6672,-73.5019 -153.835,-73.5019 -67.3508,0 -119.678,25.9935 -157.18,77.6688zm0 221.158l0 -19.9841c0,-73.8421 11.3385,-126.509 34.0155 [...]
+     id="path81" /></glyph>
+   <glyph
+   unicode="v"
+   horiz-adv-x="600"
+   id="glyph83"><path
+     d="M243.154 0l-203.158 536.17 91.8419 0 117.155 -318.329c27.666,-75.3444 43.9934,-128.182 48.8406,-158.682l3.00471 0c2.15432,14.1731 18.6519,67.1807 49.3225,158.682l116.673 318.329 92.3238 0 -203.158 -536.17 -112.847 0z"
+     id="path85" /></glyph>
+   <glyph
+   unicode="r"
+   horiz-adv-x="600"
+   id="glyph87"><path
+     d="M517.178 524.009l-24.0093 -81.1837c-39.9966,14.6834 -76.5066,21.9967 -109.332,21.9967 -53.1776,0 -93.9963,-14.9952 -122.824,-45.1556 -28.8565,-30.1604 -43.1714,-73.672 -43.1714,-130.676l0 -288.99 -89.0073 0 0 536.17 72.3397 0 10.6582 -98.1632 3.99683 0c24.6613,38.6643 51.3351,66.3303 79.5113,82.9979 28.3179,16.6676 63.1555,24.8313 104.484,24.8313 38.5226,0 77.4987,-7.34169 117.354,-21.8266z"
+     id="path89" /></glyph>
+   <glyph
+   unicode="t"
+   horiz-adv-x="600"
+   id="glyph91"><path
+     d="M497.998 73.1699l0 -67.3411c-42.3251,-10.3288 -83.3392,-15.6615 -122.989,-15.6615 -117.834,0 -176.848,56.0024 -176.848,168.007l0 310.999 -130.324 0 0 45.9925 130.324 23.8289 37.6657 140.174 51.3429 0 0 -143.009 213.823 0 0 -66.9867 -213.823 0 0 -310.999c0,-63.5143 31.1636,-95.174 93.6681,-95.174 30.3309,0 69.3253,3.33073 117.16,10.1694z"
+     id="path93" /></glyph>
+   <glyph
+   unicode="y"
+   horiz-adv-x="600"
+   id="glyph95"><path
+     d="M40.0043 536.16l91.8255 0 128.003 -319.325c26.6636,-66.8273 41.1736,-114.007 43.335,-141.663l2.99412 0c7.51187,36.4964 22.1636,83.9948 44.0082,142.655l116.664 318.333 92.3393 0 -232 -605.999c-21.8447,-56.6579 -47.1795,-99.1602 -76.1817,-127.666 -28.9845,-28.4884 -68.9887,-42.6618 -120.154,-42.6618 -28.0101,0 -55.3292,2.67522 -82.0105,8.16739l0 70.8313c20.1793,-3.8268 42.3429,-5.82879 66.3312,-5.82879 31.3408,0 55.6835,6.66147 73.0104,20.0021 17.5041,13.3229 33.0062,36.3369 46.665 [...]
+     id="path97" /></glyph>
+  </font>
+  <style
+   type="text/css"
+   id="style99">
+   
+    @font-face { font-family:"Droid Sans Mono";src:url("#FontID0") format(svg)}
+    .fil2 {fill:black}
+    .fil0 {fill:#2B2828}
+    .fil1 {fill:#3465A4}
+    .fnt1 {font-weight:normal;font-size:41.6669;font-family:'Droid Sans Mono'}
+    .fnt0 {font-weight:normal;font-size:66.6661;font-family:'Droid Sans Mono'}
+    .fnt3 {font-weight:normal;font-size:125;font-family:'Droid Sans Mono'}
+    .fnt2 {font-weight:normal;font-size:150;font-family:'Droid Sans Mono'}
+   
+  </style>
+ 
+  
+  
+  
+  
+  
+  
+  
+  
+ 
+   
+
+
+
+  
+</defs>
+ <g
+   id="g3107"
+   transform="translate(-164.37718,0.077996)"><text
+   x="569.31348"
+   y="138.23804"
+   id="text3840"
+   class="fil0 fnt0"
+   style="font-size:140.73484802px;font-weight:normal;fill:#3465a4;fill-opacity:1;font-family:Droid Sans Mono">Notebook</text>
+
+
+</g><text
+   style="font-size:150px;font-weight:normal;fill:#000000;font-family:Droid Sans Mono"
+   id="text109"
+   class="fil2 fnt2"
+   y="138.31602"
+   x="6.9652257">IP</text>
+
+
+
+
+
+<g
+   id="g3115"
+   transform="translate(-80.389077,-3.6045988)"><text
+   x="261.15134"
+   y="124.71784"
+   class="fil1 fnt3"
+   id="text111"
+   style="font-size:108.73868561px;font-weight:normal;fill:#3465a4;font-family:Droid Sans Mono">[</text>
+
+
+
+
+
+<text
+   x="356.85321"
+   y="124.71784"
+   class="fil1 fnt3"
+   id="text113"
+   style="font-size:108.73868561px;font-weight:normal;fill:#3465a4;font-family:Droid Sans Mono">]</text>
+
+
+
+
+
+<text
+   x="395.29062"
+   y="123.62939"
+   class="fil1 fnt3"
+   id="text115"
+   style="font-size:108.73868561px;font-weight:normal;fill:#3465a4;font-family:Droid Sans Mono">:</text>
+
+
+
+
+
+<text
+   x="315.31311"
+   y="118.70238"
+   class="fil2 fnt3"
+   id="text117"
+   style="font-size:96.64835358px;font-weight:normal;fill:#000000;font-family:Droid Sans Mono">y</text>
+
+
+
+
+
+</g>
+</svg>
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/ace.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/ace.js
new file mode 100755
index 0000000..f6a6161
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/ace.js
@@ -0,0 +1 @@
+(function(){function g(a){var e=function(a,b){return d("",a,b)};e.packaged=!0;var f=b;a&&(b[a]||(b[a]={}),f=b[a]),f.define&&(c.original=f.define),f.define=c,f.require&&(d.original=f.require),f.require=e}var a="",b=function(){return this}();if(typeof requirejs!="undefined")return;var c=function(a,b,d){if(typeof a!="string"){c.original?c.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(d=b),c.mo [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-html.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-html.js
new file mode 100755
index 0000000..f4f8060
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-html.js
@@ -0,0 +1 @@
+define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./html_highlight_rules").HtmlHighlightRules,j=a("./behaviour/xml").XmlBehaviour,k=a("./folding/html").FoldMode,l=function(){va [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-markdown.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-markdown.js
new file mode 100755
index 0000000..4cf7a4a
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-markdown.js
@@ -0,0 +1 @@
+define("ace/mode/markdown",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/xml","ace/mode/html","ace/tokenizer","ace/mode/markdown_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./xml").Mode,h=a("./html").Mode,i=a("../tokenizer").Tokenizer,j=a("./markdown_highlight_rules").MarkdownHighlightRules,k=function(){var a=new j;this.$tokenizer=new i(a.getRules()),this.$embeds=a.getE [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-python.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-python.js
new file mode 100755
index 0000000..116f838
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/mode-python.js
@@ -0,0 +1 @@
+define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./python_highlight_rules").PythonHighlightRules,h=a("./folding/pythonic").FoldMode,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.foldingRules=new h("\\:")};d.inherits(j,e),fun [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/theme-textmate.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/theme-textmate.js
new file mode 100755
index 0000000..a2d3af3
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ace/theme-textmate.js
@@ -0,0 +1 @@
+define("ace/theme/textmate",["require","exports","module"],function(a,b,c){"use strict",b.isDark=!1,b.cssClass="ace-tm",b.cssText=".ace-tm .ace_editor {  border: 2px solid rgb(159, 159, 159);}.ace-tm .ace_editor.ace_focus {  border: 2px solid #327fbd;}.ace-tm .ace_gutter {  background: #e8e8e8;  color: #333;}.ace-tm .ace_print_margin {  width: 1px;  background: #e8e8e8;}.ace-tm .ace_fold {    background-color: #0000A2;}.ace-tm .ace_text-layer {  cursor: text;}.ace-tm .ace_cursor {  borde [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/LICENSE b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/LICENSE
new file mode 100644
index 0000000..3f7c0bb
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2011 by Marijn Haverbeke <marijnh at gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/README-IPython.rst b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/README-IPython.rst
new file mode 100644
index 0000000..ff61963
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/README-IPython.rst
@@ -0,0 +1,33 @@
+=======================
+ CodeMirror in IPython
+=======================
+
+We carry a mostly unmodified copy of CodeMirror.  The current version we use
+is (*please update this information when updating versions*)::
+
+  CodeMirror 2.2
+
+The only changes we've applied so far are these::
+
+    diff --git a/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js b/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js
+    index ca94e7a..fc9a503 100644
+    --- a/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js
+    +++ b/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js
+    @@ -5,7 +5,11 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
+	     return new RegExp("^((" + words.join(")|(") + "))\\b");
+	 }
+
+    -    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
+    +    // IPython-specific changes: add '?' as recognized character.
+    +    //var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
+    +    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
+    +    // End IPython changes.
+    +    
+	 var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
+	 var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
+	 var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
+
+
+In practice it's just a one-line change, adding `\\?` to singleOperators,
+surrounded by a comment.  We'll turn this into a proper patchset if it ever
+gets more complicated than this, but for now this note should be enough.
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/README.md b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/README.md
new file mode 100644
index 0000000..09e6760
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/README.md
@@ -0,0 +1,6 @@
+# CodeMirror 2
+
+CodeMirror 2 is a rewrite of [CodeMirror
+1](http://github.com/marijnh/CodeMirror). The docs live
+[here](http://codemirror.net/doc/manual.html), and the project page is
+[http://codemirror.net/](http://codemirror.net/).
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/codemirror.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/codemirror.css
new file mode 100644
index 0000000..1161425
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/codemirror.css
@@ -0,0 +1,104 @@
+.CodeMirror {
+  line-height: 1em;
+  font-family: monospace;
+}
+
+.CodeMirror-scroll {
+  overflow: auto;
+  height: 300px;
+  /* This is needed to prevent an IE[67] bug where the scrolled content
+     is visible outside of the scrolling box. */
+  position: relative;
+}
+
+.CodeMirror-gutter {
+  position: absolute; left: 0; top: 0;
+  z-index: 10;
+  background-color: #f7f7f7;
+  border-right: 1px solid #eee;
+  min-width: 2em;
+  height: 100%;
+}
+.CodeMirror-gutter-text {
+  color: #aaa;
+  text-align: right;
+  padding: .4em .2em .4em .4em;
+  white-space: pre !important;
+}
+.CodeMirror-lines {
+  padding: .4em;
+}
+
+.CodeMirror pre {
+  -moz-border-radius: 0;
+  -webkit-border-radius: 0;
+  -o-border-radius: 0;
+  border-radius: 0;
+  border-width: 0; margin: 0; padding: 0; background: transparent;
+  font-family: inherit;
+  font-size: inherit;
+  padding: 0; margin: 0;
+  white-space: pre;
+  word-wrap: normal;
+}
+
+.CodeMirror-wrap pre {
+  word-wrap: break-word;
+  white-space: pre-wrap;
+}
+.CodeMirror-wrap .CodeMirror-scroll {
+  overflow-x: hidden;
+}
+
+.CodeMirror textarea {
+  outline: none !important;
+}
+
+.CodeMirror pre.CodeMirror-cursor {
+  z-index: 10;
+  position: absolute;
+  visibility: hidden;
+  border-left: 1px solid black;
+}
+.CodeMirror-focused pre.CodeMirror-cursor {
+  visibility: visible;
+}
+
+span.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused span.CodeMirror-selected { background: #d2dcf8; }
+
+.CodeMirror-searching {background: #ffa;}
+
+/* Default theme */
+
+.cm-s-default span.cm-keyword {color: #708;}
+.cm-s-default span.cm-atom {color: #219;}
+.cm-s-default span.cm-number {color: #164;}
+.cm-s-default span.cm-def {color: #00f;}
+.cm-s-default span.cm-variable {color: black;}
+.cm-s-default span.cm-variable-2 {color: #05a;}
+.cm-s-default span.cm-variable-3 {color: #085;}
+.cm-s-default span.cm-property {color: black;}
+.cm-s-default span.cm-operator {color: black;}
+.cm-s-default span.cm-comment {color: #a50;}
+.cm-s-default span.cm-string {color: #a11;}
+.cm-s-default span.cm-string-2 {color: #f50;}
+.cm-s-default span.cm-meta {color: #555;}
+.cm-s-default span.cm-error {color: #f00;}
+.cm-s-default span.cm-qualifier {color: #555;}
+.cm-s-default span.cm-builtin {color: #30a;}
+.cm-s-default span.cm-bracket {color: #cc7;}
+.cm-s-default span.cm-tag {color: #170;}
+.cm-s-default span.cm-attribute {color: #00c;}
+.cm-s-default span.cm-header {color: #a0a;}
+.cm-s-default span.cm-quote {color: #090;}
+.cm-s-default span.cm-hr {color: #999;}
+.cm-s-default span.cm-link {color: #00c;}
+
+span.cm-header, span.cm-strong {font-weight: bold;}
+span.cm-em {font-style: italic;}
+span.cm-emstrong {font-style: italic; font-weight: bold;}
+span.cm-link {text-decoration: underline;}
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/codemirror.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/codemirror.js
new file mode 100644
index 0000000..79eb457
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/codemirror.js
@@ -0,0 +1,2761 @@
+// CodeMirror version 2.2
+//
+// All functions that need access to the editor's state live inside
+// the CodeMirror function. Below that, at the bottom of the file,
+// some utilities are defined.
+
+// CodeMirror is the only global var we claim
+var CodeMirror = (function() {
+  // This is the function that produces an editor instance. It's
+  // closure is used to store the editor state.
+  function CodeMirror(place, givenOptions) {
+    // Determine effective options based on given values and defaults.
+    var options = {}, defaults = CodeMirror.defaults;
+    for (var opt in defaults)
+      if (defaults.hasOwnProperty(opt))
+        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
+
+    var targetDocument = options["document"];
+    // The element in which the editor lives.
+    var wrapper = targetDocument.createElement("div");
+    wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
+    // This mess creates the base DOM structure for the editor.
+    wrapper.innerHTML =
+      '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
+        '<textarea style="position: absolute; padding: 0; width: 1px;" wrap="off" ' +
+          'autocorrect="off" autocapitalize="off"></textarea></div>' +
+      '<div class="CodeMirror-scroll" tabindex="-1">' +
+        '<div style="position: relative">' + // Set to the height of the text, causes scrolling
+          '<div style="position: relative">' + // Moved around its parent to cover visible view
+            '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
+            // Provides positioning relative to (visible) text origin
+            '<div class="CodeMirror-lines"><div style="position: relative">' +
+              '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden"></div>' +
+              '<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor
+              '<div></div>' + // This DIV contains the actual code
+            '</div></div></div></div></div>';
+    if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
+    // I've never seen more elegant code in my life.
+    var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,
+        scroller = wrapper.lastChild, code = scroller.firstChild,
+        mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
+        lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
+        cursor = measure.nextSibling, lineDiv = cursor.nextSibling;
+    themeChanged();
+    // Needed to hide big blue blinking cursor on Mobile Safari
+    if (/AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent)) input.style.width = "0px";
+    if (!webkit) lineSpace.draggable = true;
+    if (options.tabindex != null) input.tabIndex = options.tabindex;
+    if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
+
+    // Check for problem with IE innerHTML not working when we have a
+    // P (or similar) parent node.
+    try { stringWidth("x"); }
+    catch (e) {
+      if (e.message.match(/runtime/i))
+        e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)");
+      throw e;
+    }
+
+    // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
+    var poll = new Delayed(), highlight = new Delayed(), blinker;
+
+    // mode holds a mode API object. doc is the tree of Line objects,
+    // work an array of lines that should be parsed, and history the
+    // undo history (instance of History constructor).
+    var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), work, focused;
+    loadMode();
+    // The selection. These are always maintained to point at valid
+    // positions. Inverted is used to remember that the user is
+    // selecting bottom-to-top.
+    var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
+    // Selection-related flags. shiftSelecting obviously tracks
+    // whether the user is holding shift.
+    var shiftSelecting, lastClick, lastDoubleClick, draggingText, overwrite = false;
+    // Variables used by startOperation/endOperation to track what
+    // happened during the operation.
+    var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
+        gutterDirty, callbacks;
+    // Current visible range (may be bigger than the view window).
+    var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
+    // bracketHighlighted is used to remember that a backet has been
+    // marked.
+    var bracketHighlighted;
+    // Tracks the maximum line length so that the horizontal scrollbar
+    // can be kept static when scrolling.
+    var maxLine = "", maxWidth, tabText = computeTabText();
+
+    // Initialize the content.
+    operation(function(){setValue(options.value || ""); updateInput = false;})();
+    var history = new History();
+
+    // Register our event handlers.
+    connect(scroller, "mousedown", operation(onMouseDown));
+    connect(scroller, "dblclick", operation(onDoubleClick));
+    connect(lineSpace, "dragstart", onDragStart);
+    connect(lineSpace, "selectstart", e_preventDefault);
+    // Gecko browsers fire contextmenu *after* opening the menu, at
+    // which point we can't mess with it anymore. Context menu is
+    // handled in onMouseDown for Gecko.
+    if (!gecko) connect(scroller, "contextmenu", onContextMenu);
+    connect(scroller, "scroll", function() {
+      updateDisplay([]);
+      if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
+      if (options.onScroll) options.onScroll(instance);
+    });
+    connect(window, "resize", function() {updateDisplay(true);});
+    connect(input, "keyup", operation(onKeyUp));
+    connect(input, "input", fastPoll);
+    connect(input, "keydown", operation(onKeyDown));
+    connect(input, "keypress", operation(onKeyPress));
+    connect(input, "focus", onFocus);
+    connect(input, "blur", onBlur);
+
+    connect(scroller, "dragenter", e_stop);
+    connect(scroller, "dragover", e_stop);
+    connect(scroller, "drop", operation(onDrop));
+    connect(scroller, "paste", function(){focusInput(); fastPoll();});
+    connect(input, "paste", fastPoll);
+    connect(input, "cut", operation(function(){replaceSelection("");}));
+
+    // IE throws unspecified error in certain cases, when
+    // trying to access activeElement before onload
+    var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
+    if (hasFocus) setTimeout(onFocus, 20);
+    else onBlur();
+
+    function isLine(l) {return l >= 0 && l < doc.size;}
+    // The instance object that we'll return. Mostly calls out to
+    // local functions in the CodeMirror function. Some do some extra
+    // range checking and/or clipping. operation is used to wrap the
+    // call so that changes it makes are tracked, and the display is
+    // updated afterwards.
+    var instance = wrapper.CodeMirror = {
+      getValue: getValue,
+      setValue: operation(setValue),
+      getSelection: getSelection,
+      replaceSelection: operation(replaceSelection),
+      focus: function(){focusInput(); onFocus(); fastPoll();},
+      setOption: function(option, value) {
+        var oldVal = options[option];
+        options[option] = value;
+        if (option == "mode" || option == "indentUnit") loadMode();
+        else if (option == "readOnly" && value) {onBlur(); input.blur();}
+        else if (option == "theme") themeChanged();
+        else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
+        else if (option == "tabSize") operation(tabsChanged)();
+        if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme")
+          operation(gutterChanged)();
+      },
+      getOption: function(option) {return options[option];},
+      undo: operation(undo),
+      redo: operation(redo),
+      indentLine: operation(function(n, dir) {
+        if (isLine(n)) indentLine(n, dir == null ? "smart" : dir ? "add" : "subtract");
+      }),
+      indentSelection: operation(indentSelected),
+      historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
+      clearHistory: function() {history = new History();},
+      matchBrackets: operation(function(){matchBrackets(true);}),
+      getTokenAt: operation(function(pos) {
+        pos = clipPos(pos);
+        return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);
+      }),
+      getStateAfter: function(line) {
+        line = clipLine(line == null ? doc.size - 1: line);
+        return getStateBefore(line + 1);
+      },
+      cursorCoords: function(start){
+        if (start == null) start = sel.inverted;
+        return pageCoords(start ? sel.from : sel.to);
+      },
+      charCoords: function(pos){return pageCoords(clipPos(pos));},
+      coordsChar: function(coords) {
+        var off = eltOffset(lineSpace);
+        return coordsChar(coords.x - off.left, coords.y - off.top);
+      },
+      markText: operation(markText),
+      setBookmark: setBookmark,
+      setMarker: operation(addGutterMarker),
+      clearMarker: operation(removeGutterMarker),
+      setLineClass: operation(setLineClass),
+      hideLine: operation(function(h) {return setLineHidden(h, true);}),
+      showLine: operation(function(h) {return setLineHidden(h, false);}),
+      onDeleteLine: function(line, f) {
+        if (typeof line == "number") {
+          if (!isLine(line)) return null;
+          line = getLine(line);
+        }
+        (line.handlers || (line.handlers = [])).push(f);
+        return line;
+      },
+      lineInfo: lineInfo,
+      addWidget: function(pos, node, scroll, vert, horiz) {
+        pos = localCoords(clipPos(pos));
+        var top = pos.yBot, left = pos.x;
+        node.style.position = "absolute";
+        code.appendChild(node);
+        if (vert == "over") top = pos.y;
+        else if (vert == "near") {
+          var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),
+              hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
+          if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
+            top = pos.y - node.offsetHeight;
+          if (left + node.offsetWidth > hspace)
+            left = hspace - node.offsetWidth;
+        }
+        node.style.top = (top + paddingTop()) + "px";
+        node.style.left = node.style.right = "";
+        if (horiz == "right") {
+          left = code.clientWidth - node.offsetWidth;
+          node.style.right = "0px";
+        } else {
+          if (horiz == "left") left = 0;
+          else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2;
+          node.style.left = (left + paddingLeft()) + "px";
+        }
+        if (scroll)
+          scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
+      },
+
+      lineCount: function() {return doc.size;},
+      clipPos: clipPos,
+      getCursor: function(start) {
+        if (start == null) start = sel.inverted;
+        return copyPos(start ? sel.from : sel.to);
+      },
+      somethingSelected: function() {return !posEq(sel.from, sel.to);},
+      setCursor: operation(function(line, ch, user) {
+        if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user);
+        else setCursor(line, ch, user);
+      }),
+      setSelection: operation(function(from, to, user) {
+        (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from));
+      }),
+      getLine: function(line) {if (isLine(line)) return getLine(line).text;},
+      getLineHandle: function(line) {if (isLine(line)) return getLine(line);},
+      setLine: operation(function(line, text) {
+        if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
+      }),
+      removeLine: operation(function(line) {
+        if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
+      }),
+      replaceRange: operation(replaceRange),
+      getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
+
+      execCommand: function(cmd) {return commands[cmd](instance);},
+      // Stuff used by commands, probably not much use to outside code.
+      moveH: operation(moveH),
+      deleteH: operation(deleteH),
+      moveV: operation(moveV),
+      toggleOverwrite: function() {overwrite = !overwrite;},
+
+      posFromIndex: function(off) {
+        var lineNo = 0, ch;
+        doc.iter(0, doc.size, function(line) {
+          var sz = line.text.length + 1;
+          if (sz > off) { ch = off; return true; }
+          off -= sz;
+          ++lineNo;
+        });
+        return clipPos({line: lineNo, ch: ch});
+      },
+      indexFromPos: function (coords) {
+        if (coords.line < 0 || coords.ch < 0) return 0;
+        var index = coords.ch;
+        doc.iter(0, coords.line, function (line) {
+          index += line.text.length + 1;
+        });
+        return index;
+      },
+
+      operation: function(f){return operation(f)();},
+      refresh: function(){updateDisplay(true);},
+      getInputField: function(){return input;},
+      getWrapperElement: function(){return wrapper;},
+      getScrollerElement: function(){return scroller;},
+      getGutterElement: function(){return gutter;}
+    };
+
+    function getLine(n) { return getLineAt(doc, n); }
+    function updateLineHeight(line, height) {
+      gutterDirty = true;
+      var diff = height - line.height;
+      for (var n = line; n; n = n.parent) n.height += diff;
+    }
+
+    function setValue(code) {
+      var top = {line: 0, ch: 0};
+      updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},
+                  splitLines(code), top, top);
+      updateInput = true;
+    }
+    function getValue(code) {
+      var text = [];
+      doc.iter(0, doc.size, function(line) { text.push(line.text); });
+      return text.join("\n");
+    }
+
+    function onMouseDown(e) {
+      setShift(e.shiftKey);
+      // Check whether this is a click in a widget
+      for (var n = e_target(e); n != wrapper; n = n.parentNode)
+        if (n.parentNode == code && n != mover) return;
+
+      // See if this is a click in the gutter
+      for (var n = e_target(e); n != wrapper; n = n.parentNode)
+        if (n.parentNode == gutterText) {
+          if (options.onGutterClick)
+            options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);
+          return e_preventDefault(e);
+        }
+
+      var start = posFromMouse(e);
+
+      switch (e_button(e)) {
+      case 3:
+        if (gecko && !mac) onContextMenu(e);
+        return;
+      case 2:
+        if (start) setCursor(start.line, start.ch, true);
+        return;
+      }
+      // For button 1, if it was clicked inside the editor
+      // (posFromMouse returning non-null), we have to adjust the
+      // selection.
+      if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
+
+      if (!focused) onFocus();
+
+      var now = +new Date;
+      if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
+        e_preventDefault(e);
+        setTimeout(focusInput, 20);
+        return selectLine(start.line);
+      } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
+        lastDoubleClick = {time: now, pos: start};
+        e_preventDefault(e);
+        return selectWordAt(start);
+      } else { lastClick = {time: now, pos: start}; }
+
+      var last = start, going;
+      if (dragAndDrop && !posEq(sel.from, sel.to) &&
+          !posLess(start, sel.from) && !posLess(sel.to, start)) {
+        // Let the drag handler handle this.
+        if (webkit) lineSpace.draggable = true;
+        var up = connect(targetDocument, "mouseup", operation(function(e2) {
+          if (webkit) lineSpace.draggable = false;
+          draggingText = false;
+          up();
+          if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
+            e_preventDefault(e2);
+            setCursor(start.line, start.ch, true);
+            focusInput();
+          }
+        }), true);
+        draggingText = true;
+        return;
+      }
+      e_preventDefault(e);
+      setCursor(start.line, start.ch, true);
+
+      function extend(e) {
+        var cur = posFromMouse(e, true);
+        if (cur && !posEq(cur, last)) {
+          if (!focused) onFocus();
+          last = cur;
+          setSelectionUser(start, cur);
+          updateInput = false;
+          var visible = visibleLines();
+          if (cur.line >= visible.to || cur.line < visible.from)
+            going = setTimeout(operation(function(){extend(e);}), 150);
+        }
+      }
+
+      var move = connect(targetDocument, "mousemove", operation(function(e) {
+        clearTimeout(going);
+        e_preventDefault(e);
+        extend(e);
+      }), true);
+      var up = connect(targetDocument, "mouseup", operation(function(e) {
+        clearTimeout(going);
+        var cur = posFromMouse(e);
+        if (cur) setSelectionUser(start, cur);
+        e_preventDefault(e);
+        focusInput();
+        updateInput = true;
+        move(); up();
+      }), true);
+    }
+    function onDoubleClick(e) {
+      for (var n = e_target(e); n != wrapper; n = n.parentNode)
+        if (n.parentNode == gutterText) return e_preventDefault(e);
+      var start = posFromMouse(e);
+      if (!start) return;
+      lastDoubleClick = {time: +new Date, pos: start};
+      e_preventDefault(e);
+      selectWordAt(start);
+    }
+    function onDrop(e) {
+      e.preventDefault();
+      var pos = posFromMouse(e, true), files = e.dataTransfer.files;
+      if (!pos || options.readOnly) return;
+      if (files && files.length && window.FileReader && window.File) {
+        function loadFile(file, i) {
+          var reader = new FileReader;
+          reader.onload = function() {
+            text[i] = reader.result;
+            if (++read == n) {
+	      pos = clipPos(pos);
+	      operation(function() {
+                var end = replaceRange(text.join(""), pos, pos);
+                setSelectionUser(pos, end);
+              })();
+	    }
+          };
+          reader.readAsText(file);
+        }
+        var n = files.length, text = Array(n), read = 0;
+        for (var i = 0; i < n; ++i) loadFile(files[i], i);
+      }
+      else {
+        try {
+          var text = e.dataTransfer.getData("Text");
+          if (text) {
+	    var end = replaceRange(text, pos, pos);
+	    var curFrom = sel.from, curTo = sel.to;
+	    setSelectionUser(pos, end);
+            if (draggingText) replaceRange("", curFrom, curTo);
+	    focusInput();
+	  }
+        }
+        catch(e){}
+      }
+    }
+    function onDragStart(e) {
+      var txt = getSelection();
+      // This will reset escapeElement
+      htmlEscape(txt);
+      e.dataTransfer.setDragImage(escapeElement, 0, 0);
+      e.dataTransfer.setData("Text", txt);
+    }
+    function handleKeyBinding(e) {
+      var name = keyNames[e.keyCode], next = keyMap[options.keyMap].auto, bound, dropShift;
+      if (name == null || e.altGraphKey) {
+        if (next) options.keyMap = next;
+        return null;
+      }
+      if (e.altKey) name = "Alt-" + name;
+      if (e.ctrlKey) name = "Ctrl-" + name;
+      if (e.metaKey) name = "Cmd-" + name;
+      if (e.shiftKey && (bound = lookupKey("Shift-" + name, options.extraKeys, options.keyMap))) {
+        dropShift = true;
+      } else {
+        bound = lookupKey(name, options.extraKeys, options.keyMap);
+      }
+      if (typeof bound == "string") {
+        if (commands.propertyIsEnumerable(bound)) bound = commands[bound];
+        else bound = null;
+      }
+      if (next && (bound || !isModifierKey(e))) options.keyMap = next;
+      if (!bound) return false;
+      if (dropShift) {
+        var prevShift = shiftSelecting;
+        shiftSelecting = null;
+        bound(instance);
+        shiftSelecting = prevShift;
+      } else bound(instance);
+      e_preventDefault(e);
+      return true;
+    }
+    var lastStoppedKey = null;
+    function onKeyDown(e) {
+      if (!focused) onFocus();
+      var code = e.keyCode;
+      // IE does strange things with escape.
+      if (ie && code == 27) { e.returnValue = false; }
+      setShift(code == 16 || e.shiftKey);
+      // First give onKeyEvent option a chance to handle this.
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
+      var handled = handleKeyBinding(e);
+      if (window.opera) {
+        lastStoppedKey = handled ? e.keyCode : null;
+        // Opera has no cut event... we try to at least catch the key combo
+        if (!handled && (mac ? e.metaKey : e.ctrlKey) && e.keyCode == 88)
+          replaceSelection("");
+      }
+    }
+    function onKeyPress(e) {
+      if (window.opera && e.keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
+      if (window.opera && !e.which && handleKeyBinding(e)) return;
+      if (options.electricChars && mode.electricChars) {
+        var ch = String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode);
+        if (mode.electricChars.indexOf(ch) > -1)
+          setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
+      }
+      fastPoll();
+    }
+    function onKeyUp(e) {
+      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
+      if (e.keyCode == 16) shiftSelecting = null;
+    }
+
+    function onFocus() {
+      if (options.readOnly) return;
+      if (!focused) {
+        if (options.onFocus) options.onFocus(instance);
+        focused = true;
+        if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
+          wrapper.className += " CodeMirror-focused";
+        if (!leaveInputAlone) resetInput(true);
+      }
+      slowPoll();
+      restartBlink();
+    }
+    function onBlur() {
+      if (focused) {
+        if (options.onBlur) options.onBlur(instance);
+        focused = false;
+        wrapper.className = wrapper.className.replace(" CodeMirror-focused", "");
+      }
+      clearInterval(blinker);
+      setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
+    }
+
+    // Replace the range from from to to by the strings in newText.
+    // Afterwards, set the selection to selFrom, selTo.
+    function updateLines(from, to, newText, selFrom, selTo) {
+      if (history) {
+        var old = [];
+        doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });
+        history.addChange(from.line, newText.length, old);
+        while (history.done.length > options.undoDepth) history.done.shift();
+      }
+      updateLinesNoUndo(from, to, newText, selFrom, selTo);
+    }
+    function unredoHelper(from, to) {
+      var change = from.pop();
+      if (change) {
+        var replaced = [], end = change.start + change.added;
+        doc.iter(change.start, end, function(line) { replaced.push(line.text); });
+        to.push({start: change.start, added: change.old.length, old: replaced});
+        var pos = clipPos({line: change.start + change.old.length - 1,
+                           ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});
+        updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
+        updateInput = true;
+      }
+    }
+    function undo() {unredoHelper(history.done, history.undone);}
+    function redo() {unredoHelper(history.undone, history.done);}
+
+    function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
+      var recomputeMaxLength = false, maxLineLength = maxLine.length;
+      if (!options.lineWrapping)
+        doc.iter(from.line, to.line, function(line) {
+          if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
+        });
+      if (from.line != to.line || newText.length > 1) gutterDirty = true;
+
+      var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);
+      // First adjust the line structure, taking some care to leave highlighting intact.
+      if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == "") {
+        // This is a whole-line replace. Treated specially to make
+        // sure line objects move the way they are supposed to.
+        var added = [], prevLine = null;
+        if (from.line) {
+          prevLine = getLine(from.line - 1);
+          prevLine.fixMarkEnds(lastLine);
+        } else lastLine.fixMarkStarts();
+        for (var i = 0, e = newText.length - 1; i < e; ++i)
+          added.push(Line.inheritMarks(newText[i], prevLine));
+        if (nlines) doc.remove(from.line, nlines, callbacks);
+        if (added.length) doc.insert(from.line, added);
+      } else if (firstLine == lastLine) {
+        if (newText.length == 1)
+          firstLine.replace(from.ch, to.ch, newText[0]);
+        else {
+          lastLine = firstLine.split(to.ch, newText[newText.length-1]);
+          firstLine.replace(from.ch, null, newText[0]);
+          firstLine.fixMarkEnds(lastLine);
+          var added = [];
+          for (var i = 1, e = newText.length - 1; i < e; ++i)
+            added.push(Line.inheritMarks(newText[i], firstLine));
+          added.push(lastLine);
+          doc.insert(from.line + 1, added);
+        }
+      } else if (newText.length == 1) {
+        firstLine.replace(from.ch, null, newText[0]);
+        lastLine.replace(null, to.ch, "");
+        firstLine.append(lastLine);
+        doc.remove(from.line + 1, nlines, callbacks);
+      } else {
+        var added = [];
+        firstLine.replace(from.ch, null, newText[0]);
+        lastLine.replace(null, to.ch, newText[newText.length-1]);
+        firstLine.fixMarkEnds(lastLine);
+        for (var i = 1, e = newText.length - 1; i < e; ++i)
+          added.push(Line.inheritMarks(newText[i], firstLine));
+        if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);
+        doc.insert(from.line + 1, added);
+      }
+      if (options.lineWrapping) {
+        var perLine = scroller.clientWidth / charWidth() - 3;
+        doc.iter(from.line, from.line + newText.length, function(line) {
+          if (line.hidden) return;
+          var guess = Math.ceil(line.text.length / perLine) || 1;
+          if (guess != line.height) updateLineHeight(line, guess);
+        });
+      } else {
+        doc.iter(from.line, i + newText.length, function(line) {
+          var l = line.text;
+          if (l.length > maxLineLength) {
+            maxLine = l; maxLineLength = l.length; maxWidth = null;
+            recomputeMaxLength = false;
+          }
+        });
+        if (recomputeMaxLength) {
+          maxLineLength = 0; maxLine = ""; maxWidth = null;
+          doc.iter(0, doc.size, function(line) {
+            var l = line.text;
+            if (l.length > maxLineLength) {
+              maxLineLength = l.length; maxLine = l;
+            }
+          });
+        }
+      }
+
+      // Add these lines to the work array, so that they will be
+      // highlighted. Adjust work lines if lines were added/removed.
+      var newWork = [], lendiff = newText.length - nlines - 1;
+      for (var i = 0, l = work.length; i < l; ++i) {
+        var task = work[i];
+        if (task < from.line) newWork.push(task);
+        else if (task > to.line) newWork.push(task + lendiff);
+      }
+      var hlEnd = from.line + Math.min(newText.length, 500);
+      highlightLines(from.line, hlEnd);
+      newWork.push(hlEnd);
+      work = newWork;
+      startWorker(100);
+      // Remember that these lines changed, for updating the display
+      changes.push({from: from.line, to: to.line + 1, diff: lendiff});
+      var changeObj = {from: from, to: to, text: newText};
+      if (textChanged) {
+        for (var cur = textChanged; cur.next; cur = cur.next) {}
+        cur.next = changeObj;
+      } else textChanged = changeObj;
+
+      // Update the selection
+      function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
+      setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));
+
+      // Make sure the scroll-size div has the correct height.
+      code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px";
+    }
+
+    function replaceRange(code, from, to) {
+      from = clipPos(from);
+      if (!to) to = from; else to = clipPos(to);
+      code = splitLines(code);
+      function adjustPos(pos) {
+        if (posLess(pos, from)) return pos;
+        if (!posLess(to, pos)) return end;
+        var line = pos.line + code.length - (to.line - from.line) - 1;
+        var ch = pos.ch;
+        if (pos.line == to.line)
+          ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0));
+        return {line: line, ch: ch};
+      }
+      var end;
+      replaceRange1(code, from, to, function(end1) {
+        end = end1;
+        return {from: adjustPos(sel.from), to: adjustPos(sel.to)};
+      });
+      return end;
+    }
+    function replaceSelection(code, collapse) {
+      replaceRange1(splitLines(code), sel.from, sel.to, function(end) {
+        if (collapse == "end") return {from: end, to: end};
+        else if (collapse == "start") return {from: sel.from, to: sel.from};
+        else return {from: sel.from, to: end};
+      });
+    }
+    function replaceRange1(code, from, to, computeSel) {
+      var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length;
+      var newSel = computeSel({line: from.line + code.length - 1, ch: endch});
+      updateLines(from, to, code, newSel.from, newSel.to);
+    }
+
+    function getRange(from, to) {
+      var l1 = from.line, l2 = to.line;
+      if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
+      var code = [getLine(l1).text.slice(from.ch)];
+      doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
+      code.push(getLine(l2).text.slice(0, to.ch));
+      return code.join("\n");
+    }
+    function getSelection() {
+      return getRange(sel.from, sel.to);
+    }
+
+    var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
+    function slowPoll() {
+      if (pollingFast) return;
+      poll.set(options.pollInterval, function() {
+        startOperation();
+        readInput();
+        if (focused) slowPoll();
+        endOperation();
+      });
+    }
+    function fastPoll() {
+      var missed = false;
+      pollingFast = true;
+      function p() {
+        startOperation();
+        var changed = readInput();
+        if (!changed && !missed) {missed = true; poll.set(60, p);}
+        else {pollingFast = false; slowPoll();}
+        endOperation();
+      }
+      poll.set(20, p);
+    }
+
+    // Previnput is a hack to work with IME. If we reset the textarea
+    // on every change, that breaks IME. So we look for changes
+    // compared to the previous content instead. (Modern browsers have
+    // events that indicate IME taking place, but these are not widely
+    // supported or compatible enough yet to rely on.)
+    var prevInput = "";
+    function readInput() {
+      if (leaveInputAlone || !focused || hasSelection(input)) return false;
+      var text = input.value;
+      if (text == prevInput) return false;
+      shiftSelecting = null;
+      var same = 0, l = Math.min(prevInput.length, text.length);
+      while (same < l && prevInput[same] == text[same]) ++same;
+      if (same < prevInput.length)
+        sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};
+      else if (overwrite && posEq(sel.from, sel.to))
+        sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
+      replaceSelection(text.slice(same), "end");
+      prevInput = text;
+      return true;
+    }
+    function resetInput(user) {
+      if (!posEq(sel.from, sel.to)) {
+        prevInput = "";
+        input.value = getSelection();
+        input.select();
+      } else if (user) prevInput = input.value = "";
+    }
+
+    function focusInput() {
+      if (!options.readOnly) input.focus();
+    }
+
+    function scrollEditorIntoView() {
+      if (!cursor.getBoundingClientRect) return;
+      var rect = cursor.getBoundingClientRect();
+      // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
+      if (ie && rect.top == rect.bottom) return;
+      var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
+      if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();
+    }
+    function scrollCursorIntoView() {
+      var cursor = localCoords(sel.inverted ? sel.from : sel.to);
+      var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
+      return scrollIntoView(x, cursor.y, x, cursor.yBot);
+    }
+    function scrollIntoView(x1, y1, x2, y2) {
+      var pl = paddingLeft(), pt = paddingTop(), lh = textHeight();
+      y1 += pt; y2 += pt; x1 += pl; x2 += pl;
+      var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;
+      if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;}
+      else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;}
+
+      var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
+      var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
+      if (x1 < screenleft + gutterw) {
+        if (x1 < 50) x1 = 0;
+        scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);
+        scrolled = true;
+      }
+      else if (x2 > screenw + screenleft - 3) {
+        scroller.scrollLeft = x2 + 10 - screenw;
+        scrolled = true;
+        if (x2 > code.clientWidth) result = false;
+      }
+      if (scrolled && options.onScroll) options.onScroll(instance);
+      return result;
+    }
+
+    function visibleLines() {
+      var lh = textHeight(), top = scroller.scrollTop - paddingTop();
+      var from_height = Math.max(0, Math.floor(top / lh));
+      var to_height = Math.ceil((top + scroller.clientHeight) / lh);
+      return {from: lineAtHeight(doc, from_height),
+              to: lineAtHeight(doc, to_height)};
+    }
+    // Uses a set of changes plus the current scroll position to
+    // determine which DOM updates have to be made, and makes the
+    // updates.
+    function updateDisplay(changes, suppressCallback) {
+      if (!scroller.clientWidth) {
+        showingFrom = showingTo = displayOffset = 0;
+        return;
+      }
+      // Compute the new visible window
+      var visible = visibleLines();
+      // Bail out if the visible area is already rendered and nothing changed.
+      if (changes !== true && changes.length == 0 && visible.from >= showingFrom && visible.to <= showingTo) return;
+      var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
+      if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
+      if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
+
+      // Create a range of theoretically intact lines, and punch holes
+      // in that using the change info.
+      var intact = changes === true ? [] :
+        computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);
+      // Clip off the parts that won't be visible
+      var intactLines = 0;
+      for (var i = 0; i < intact.length; ++i) {
+        var range = intact[i];
+        if (range.from < from) {range.domStart += (from - range.from); range.from = from;}
+        if (range.to > to) range.to = to;
+        if (range.from >= range.to) intact.splice(i--, 1);
+        else intactLines += range.to - range.from;
+      }
+      if (intactLines == to - from) return;
+      intact.sort(function(a, b) {return a.domStart - b.domStart;});
+
+      var th = textHeight(), gutterDisplay = gutter.style.display;
+      lineDiv.style.display = gutter.style.display = "none";
+      patchDisplay(from, to, intact);
+      lineDiv.style.display = "";
+
+      // Position the mover div to align with the lines it's supposed
+      // to be showing (which will cover the visible display)
+      var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
+      // This is just a bogus formula that detects when the editor is
+      // resized or the font size changes.
+      if (different) lastSizeC = scroller.clientHeight + th;
+      showingFrom = from; showingTo = to;
+      displayOffset = heightAtLine(doc, from);
+      mover.style.top = (displayOffset * th) + "px";
+      code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
+
+      // Since this is all rather error prone, it is honoured with the
+      // only assertion in the whole file.
+      if (lineDiv.childNodes.length != showingTo - showingFrom)
+        throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
+                        " nodes=" + lineDiv.childNodes.length);
+
+      if (options.lineWrapping) {
+        maxWidth = scroller.clientWidth;
+        var curNode = lineDiv.firstChild;
+        doc.iter(showingFrom, showingTo, function(line) {
+          if (!line.hidden) {
+            var height = Math.round(curNode.offsetHeight / th) || 1;
+            if (line.height != height) {updateLineHeight(line, height); gutterDirty = true;}
+          }
+          curNode = curNode.nextSibling;
+        });
+      } else {
+        if (maxWidth == null) maxWidth = stringWidth(maxLine);
+        if (maxWidth > scroller.clientWidth) {
+          lineSpace.style.width = maxWidth + "px";
+          // Needed to prevent odd wrapping/hiding of widgets placed in here.
+          code.style.width = "";
+          code.style.width = scroller.scrollWidth + "px";
+        } else {
+          lineSpace.style.width = code.style.width = "";
+        }
+      }
+      gutter.style.display = gutterDisplay;
+      if (different || gutterDirty) updateGutter();
+      updateCursor();
+      if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
+      return true;
+    }
+
+    function computeIntact(intact, changes) {
+      for (var i = 0, l = changes.length || 0; i < l; ++i) {
+        var change = changes[i], intact2 = [], diff = change.diff || 0;
+        for (var j = 0, l2 = intact.length; j < l2; ++j) {
+          var range = intact[j];
+          if (change.to <= range.from && change.diff)
+            intact2.push({from: range.from + diff, to: range.to + diff,
+                          domStart: range.domStart});
+          else if (change.to <= range.from || change.from >= range.to)
+            intact2.push(range);
+          else {
+            if (change.from > range.from)
+              intact2.push({from: range.from, to: change.from, domStart: range.domStart});
+            if (change.to < range.to)
+              intact2.push({from: change.to + diff, to: range.to + diff,
+                            domStart: range.domStart + (change.to - range.from)});
+          }
+        }
+        intact = intact2;
+      }
+      return intact;
+    }
+
+    function patchDisplay(from, to, intact) {
+      // The first pass removes the DOM nodes that aren't intact.
+      if (!intact.length) lineDiv.innerHTML = "";
+      else {
+        function killNode(node) {
+          var tmp = node.nextSibling;
+          node.parentNode.removeChild(node);
+          return tmp;
+        }
+        var domPos = 0, curNode = lineDiv.firstChild, n;
+        for (var i = 0; i < intact.length; ++i) {
+          var cur = intact[i];
+          while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}
+          for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}
+        }
+        while (curNode) curNode = killNode(curNode);
+      }
+      // This pass fills in the lines that actually changed.
+      var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
+      var sfrom = sel.from.line, sto = sel.to.line, inSel = sfrom < from && sto >= from;
+      var scratch = targetDocument.createElement("div"), newElt;
+      doc.iter(from, to, function(line) {
+        var ch1 = null, ch2 = null;
+        if (inSel) {
+          ch1 = 0;
+          if (sto == j) {inSel = false; ch2 = sel.to.ch;}
+        } else if (sfrom == j) {
+          if (sto == j) {ch1 = sel.from.ch; ch2 = sel.to.ch;}
+          else {inSel = true; ch1 = sel.from.ch;}
+        }
+        if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
+        if (!nextIntact || nextIntact.from > j) {
+          if (line.hidden) scratch.innerHTML = "<pre></pre>";
+          else scratch.innerHTML = line.getHTML(ch1, ch2, true, tabText);
+          lineDiv.insertBefore(scratch.firstChild, curNode);
+        } else {
+          curNode = curNode.nextSibling;
+        }
+        ++j;
+      });
+    }
+
+    function updateGutter() {
+      if (!options.gutter && !options.lineNumbers) return;
+      var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
+      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
+      var html = [], i = showingFrom;
+      doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
+        if (line.hidden) {
+          html.push("<pre></pre>");
+        } else {
+          var marker = line.gutterMarker;
+          var text = options.lineNumbers ? i + options.firstLineNumber : null;
+          if (marker && marker.text)
+            text = marker.text.replace("%N%", text != null ? text : "");
+          else if (text == null)
+            text = "\u00a0";
+          html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
+          for (var j = 1; j < line.height; ++j) html.push("<br/> ");
+          html.push("</pre>");
+        }
+        ++i;
+      });
+      gutter.style.display = "none";
+      gutterText.innerHTML = html.join("");
+      var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = "";
+      while (val.length + pad.length < minwidth) pad += "\u00a0";
+      if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild);
+      gutter.style.display = "";
+      lineSpace.style.marginLeft = gutter.offsetWidth + "px";
+      gutterDirty = false;
+    }
+    function updateCursor() {
+      var head = sel.inverted ? sel.from : sel.to, lh = textHeight();
+      var pos = localCoords(head, true);
+      var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);
+      inputDiv.style.top = (pos.y + lineOff.top - wrapOff.top) + "px";
+      inputDiv.style.left = (pos.x + lineOff.left - wrapOff.left) + "px";
+      if (posEq(sel.from, sel.to)) {
+        cursor.style.top = pos.y + "px";
+        cursor.style.left = (options.lineWrapping ? Math.min(pos.x, lineSpace.offsetWidth) : pos.x) + "px";
+        cursor.style.display = "";
+      }
+      else cursor.style.display = "none";
+    }
+
+    function setShift(val) {
+      if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);
+      else shiftSelecting = null;
+    }
+    function setSelectionUser(from, to) {
+      var sh = shiftSelecting && clipPos(shiftSelecting);
+      if (sh) {
+        if (posLess(sh, from)) from = sh;
+        else if (posLess(to, sh)) to = sh;
+      }
+      setSelection(from, to);
+      userSelChange = true;
+    }
+    // Update the selection. Last two args are only used by
+    // updateLines, since they have to be expressed in the line
+    // numbers before the update.
+    function setSelection(from, to, oldFrom, oldTo) {
+      goalColumn = null;
+      if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}
+      if (posEq(sel.from, from) && posEq(sel.to, to)) return;
+      if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
+
+      // Skip over hidden lines.
+      if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch);
+      if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
+
+      if (posEq(from, to)) sel.inverted = false;
+      else if (posEq(from, sel.to)) sel.inverted = false;
+      else if (posEq(to, sel.from)) sel.inverted = true;
+
+      // Some ugly logic used to only mark the lines that actually did
+      // see a change in selection as changed, rather than the whole
+      // selected range.
+      if (posEq(from, to)) {
+        if (!posEq(sel.from, sel.to))
+          changes.push({from: oldFrom, to: oldTo + 1});
+      }
+      else if (posEq(sel.from, sel.to)) {
+        changes.push({from: from.line, to: to.line + 1});
+      }
+      else {
+        if (!posEq(from, sel.from)) {
+          if (from.line < oldFrom)
+            changes.push({from: from.line, to: Math.min(to.line, oldFrom) + 1});
+          else
+            changes.push({from: oldFrom, to: Math.min(oldTo, from.line) + 1});
+        }
+        if (!posEq(to, sel.to)) {
+          if (to.line < oldTo)
+            changes.push({from: Math.max(oldFrom, from.line), to: oldTo + 1});
+          else
+            changes.push({from: Math.max(from.line, oldTo), to: to.line + 1});
+        }
+      }
+      sel.from = from; sel.to = to;
+      selectionChanged = true;
+    }
+    function skipHidden(pos, oldLine, oldCh) {
+      function getNonHidden(dir) {
+        var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;
+        while (lNo != end) {
+          var line = getLine(lNo);
+          if (!line.hidden) {
+            var ch = pos.ch;
+            if (ch > oldCh || ch > line.text.length) ch = line.text.length;
+            return {line: lNo, ch: ch};
+          }
+          lNo += dir;
+        }
+      }
+      var line = getLine(pos.line);
+      if (!line.hidden) return pos;
+      if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
+      else return getNonHidden(-1) || getNonHidden(1);
+    }
+    function setCursor(line, ch, user) {
+      var pos = clipPos({line: line, ch: ch || 0});
+      (user ? setSelectionUser : setSelection)(pos, pos);
+    }
+
+    function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}
+    function clipPos(pos) {
+      if (pos.line < 0) return {line: 0, ch: 0};
+      if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};
+      var ch = pos.ch, linelen = getLine(pos.line).text.length;
+      if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
+      else if (ch < 0) return {line: pos.line, ch: 0};
+      else return pos;
+    }
+
+    function findPosH(dir, unit) {
+      var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch;
+      var lineObj = getLine(line);
+      function findNextLine() {
+        for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) {
+          var lo = getLine(l);
+          if (!lo.hidden) { line = l; lineObj = lo; return true; }
+        }
+      }
+      function moveOnce(boundToLine) {
+        if (ch == (dir < 0 ? 0 : lineObj.text.length)) {
+          if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0;
+          else return false;
+        } else ch += dir;
+        return true;
+      }
+      if (unit == "char") moveOnce();
+      else if (unit == "column") moveOnce(true);
+      else if (unit == "word") {
+        var sawWord = false;
+        for (;;) {
+          if (dir < 0) if (!moveOnce()) break;
+          if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
+          else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
+          if (dir > 0) if (!moveOnce()) break;
+        }
+      }
+      return {line: line, ch: ch};
+    }
+    function moveH(dir, unit) {
+      var pos = dir < 0 ? sel.from : sel.to;
+      if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit);
+      setCursor(pos.line, pos.ch, true);
+    }
+    function deleteH(dir, unit) {
+      if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to);
+      else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to);
+      else replaceRange("", sel.from, findPosH(dir, unit));
+      userSelChange = true;
+    }
+    var goalColumn = null;
+    function moveV(dir, unit) {
+      var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);
+      if (goalColumn != null) pos.x = goalColumn;
+      if (unit == "page") dist = scroller.clientHeight;
+      else if (unit == "line") dist = textHeight();
+      var target = coordsChar(pos.x, pos.y + dist * dir + 2);
+      setCursor(target.line, target.ch, true);
+      goalColumn = pos.x;
+    }
+
+    function selectWordAt(pos) {
+      var line = getLine(pos.line).text;
+      var start = pos.ch, end = pos.ch;
+      while (start > 0 && isWordChar(line.charAt(start - 1))) --start;
+      while (end < line.length && isWordChar(line.charAt(end))) ++end;
+      setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});
+    }
+    function selectLine(line) {
+      setSelectionUser({line: line, ch: 0}, {line: line, ch: getLine(line).text.length});
+    }
+    function indentSelected(mode) {
+      if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
+      var e = sel.to.line - (sel.to.ch ? 0 : 1);
+      for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);
+    }
+
+    function indentLine(n, how) {
+      if (!how) how = "add";
+      if (how == "smart") {
+        if (!mode.indent) how = "prev";
+        else var state = getStateBefore(n);
+      }
+
+      var line = getLine(n), curSpace = line.indentation(options.tabSize),
+          curSpaceString = line.text.match(/^\s*/)[0], indentation;
+      if (how == "prev") {
+        if (n) indentation = getLine(n-1).indentation(options.tabSize);
+        else indentation = 0;
+      }
+      else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
+      else if (how == "add") indentation = curSpace + options.indentUnit;
+      else if (how == "subtract") indentation = curSpace - options.indentUnit;
+      indentation = Math.max(0, indentation);
+      var diff = indentation - curSpace;
+
+      if (!diff) {
+        if (sel.from.line != n && sel.to.line != n) return;
+        var indentString = curSpaceString;
+      }
+      else {
+        var indentString = "", pos = 0;
+        if (options.indentWithTabs)
+          for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
+        while (pos < indentation) {++pos; indentString += " ";}
+      }
+
+      replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
+    }
+
+    function loadMode() {
+      mode = CodeMirror.getMode(options, options.mode);
+      doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
+      work = [0];
+      startWorker();
+    }
+    function gutterChanged() {
+      var visible = options.gutter || options.lineNumbers;
+      gutter.style.display = visible ? "" : "none";
+      if (visible) gutterDirty = true;
+      else lineDiv.parentNode.style.marginLeft = 0;
+    }
+    function wrappingChanged(from, to) {
+      if (options.lineWrapping) {
+        wrapper.className += " CodeMirror-wrap";
+        var perLine = scroller.clientWidth / charWidth() - 3;
+        doc.iter(0, doc.size, function(line) {
+          if (line.hidden) return;
+          var guess = Math.ceil(line.text.length / perLine) || 1;
+          if (guess != 1) updateLineHeight(line, guess);
+        });
+        lineSpace.style.width = code.style.width = "";
+      } else {
+        wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
+        maxWidth = null; maxLine = "";
+        doc.iter(0, doc.size, function(line) {
+          if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
+          if (line.text.length > maxLine.length) maxLine = line.text;
+        });
+      }
+      changes.push({from: 0, to: doc.size});
+    }
+    function computeTabText() {
+      for (var str = '<span class="cm-tab">', i = 0; i < options.tabSize; ++i) str += " ";
+      return str + "</span>";
+    }
+    function tabsChanged() {
+      tabText = computeTabText();
+      updateDisplay(true);
+    }
+    function themeChanged() {
+      scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
+        options.theme.replace(/(^|\s)\s*/g, " cm-s-");
+    }
+
+    function TextMarker() { this.set = []; }
+    TextMarker.prototype.clear = operation(function() {
+      var min = Infinity, max = -Infinity;
+      for (var i = 0, e = this.set.length; i < e; ++i) {
+        var line = this.set[i], mk = line.marked;
+        if (!mk || !line.parent) continue;
+        var lineN = lineNo(line);
+        min = Math.min(min, lineN); max = Math.max(max, lineN);
+        for (var j = 0; j < mk.length; ++j)
+          if (mk[j].set == this.set) mk.splice(j--, 1);
+      }
+      if (min != Infinity)
+        changes.push({from: min, to: max + 1});
+    });
+    TextMarker.prototype.find = function() {
+      var from, to;
+      for (var i = 0, e = this.set.length; i < e; ++i) {
+        var line = this.set[i], mk = line.marked;
+        for (var j = 0; j < mk.length; ++j) {
+          var mark = mk[j];
+          if (mark.set == this.set) {
+            if (mark.from != null || mark.to != null) {
+              var found = lineNo(line);
+              if (found != null) {
+                if (mark.from != null) from = {line: found, ch: mark.from};
+                if (mark.to != null) to = {line: found, ch: mark.to};
+              }
+            }
+          }
+        }
+      }
+      return {from: from, to: to};
+    };
+
+    function markText(from, to, className) {
+      from = clipPos(from); to = clipPos(to);
+      var tm = new TextMarker();
+      function add(line, from, to, className) {
+        getLine(line).addMark(new MarkedText(from, to, className, tm.set));
+      }
+      if (from.line == to.line) add(from.line, from.ch, to.ch, className);
+      else {
+        add(from.line, from.ch, null, className);
+        for (var i = from.line + 1, e = to.line; i < e; ++i)
+          add(i, null, null, className);
+        add(to.line, null, to.ch, className);
+      }
+      changes.push({from: from.line, to: to.line + 1});
+      return tm;
+    }
+
+    function setBookmark(pos) {
+      pos = clipPos(pos);
+      var bm = new Bookmark(pos.ch);
+      getLine(pos.line).addMark(bm);
+      return bm;
+    }
+
+    function addGutterMarker(line, text, className) {
+      if (typeof line == "number") line = getLine(clipLine(line));
+      line.gutterMarker = {text: text, style: className};
+      gutterDirty = true;
+      return line;
+    }
+    function removeGutterMarker(line) {
+      if (typeof line == "number") line = getLine(clipLine(line));
+      line.gutterMarker = null;
+      gutterDirty = true;
+    }
+
+    function changeLine(handle, op) {
+      var no = handle, line = handle;
+      if (typeof handle == "number") line = getLine(clipLine(handle));
+      else no = lineNo(handle);
+      if (no == null) return null;
+      if (op(line, no)) changes.push({from: no, to: no + 1});
+      else return null;
+      return line;
+    }
+    function setLineClass(handle, className) {
+      return changeLine(handle, function(line) {
+        if (line.className != className) {
+          line.className = className;
+          return true;
+        }
+      });
+    }
+    function setLineHidden(handle, hidden) {
+      return changeLine(handle, function(line, no) {
+        if (line.hidden != hidden) {
+          line.hidden = hidden;
+          updateLineHeight(line, hidden ? 0 : 1);
+          if (hidden && (sel.from.line == no || sel.to.line == no))
+            setSelection(skipHidden(sel.from, sel.from.line, sel.from.ch),
+                         skipHidden(sel.to, sel.to.line, sel.to.ch));
+          return (gutterDirty = true);
+        }
+      });
+    }
+
+    function lineInfo(line) {
+      if (typeof line == "number") {
+        if (!isLine(line)) return null;
+        var n = line;
+        line = getLine(line);
+        if (!line) return null;
+      }
+      else {
+        var n = lineNo(line);
+        if (n == null) return null;
+      }
+      var marker = line.gutterMarker;
+      return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
+              markerClass: marker && marker.style, lineClass: line.className};
+    }
+
+    function stringWidth(str) {
+      measure.innerHTML = "<pre><span>x</span></pre>";
+      measure.firstChild.firstChild.firstChild.nodeValue = str;
+      return measure.firstChild.firstChild.offsetWidth || 10;
+    }
+    // These are used to go from pixel positions to character
+    // positions, taking varying character widths into account.
+    function charFromX(line, x) {
+      if (x <= 0) return 0;
+      var lineObj = getLine(line), text = lineObj.text;
+      function getX(len) {
+        measure.innerHTML = "<pre><span>" + lineObj.getHTML(null, null, false, tabText, len) + "</span></pre>";
+        return measure.firstChild.firstChild.offsetWidth;
+      }
+      var from = 0, fromX = 0, to = text.length, toX;
+      // Guess a suitable upper bound for our search.
+      var estimated = Math.min(to, Math.ceil(x / charWidth()));
+      for (;;) {
+        var estX = getX(estimated);
+        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
+        else {toX = estX; to = estimated; break;}
+      }
+      if (x > toX) return to;
+      // Try to guess a suitable lower bound as well.
+      estimated = Math.floor(to * 0.8); estX = getX(estimated);
+      if (estX < x) {from = estimated; fromX = estX;}
+      // Do a binary search between these bounds.
+      for (;;) {
+        if (to - from <= 1) return (toX - x > x - fromX) ? from : to;
+        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
+        if (middleX > x) {to = middle; toX = middleX;}
+        else {from = middle; fromX = middleX;}
+      }
+    }
+
+    var tempId = Math.floor(Math.random() * 0xffffff).toString(16);
+    function measureLine(line, ch) {
+      var extra = "";
+      // Include extra text at the end to make sure the measured line is wrapped in the right way.
+      if (options.lineWrapping) {
+        var end = line.text.indexOf(" ", ch + 2);
+        extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
+      }
+      measure.innerHTML = "<pre>" + line.getHTML(null, null, false, tabText, ch) +
+        '<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
+        extra + "</pre>";
+      var elt = document.getElementById("CodeMirror-temp-" + tempId);
+      var top = elt.offsetTop, left = elt.offsetLeft;
+      // Older IEs report zero offsets for spans directly after a wrap
+      if (ie && ch && top == 0 && left == 0) {
+        var backup = document.createElement("span");
+        backup.innerHTML = "x";
+        elt.parentNode.insertBefore(backup, elt.nextSibling);
+        top = backup.offsetTop;
+      }
+      return {top: top, left: left};
+    }
+    function localCoords(pos, inLineWrap) {
+      var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));
+      if (pos.ch == 0) x = 0;
+      else {
+        var sp = measureLine(getLine(pos.line), pos.ch);
+        x = sp.left;
+        if (options.lineWrapping) y += Math.max(0, sp.top);
+      }
+      return {x: x, y: y, yBot: y + lh};
+    }
+    // Coords must be lineSpace-local
+    function coordsChar(x, y) {
+      if (y < 0) y = 0;
+      var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);
+      var lineNo = lineAtHeight(doc, heightPos);
+      if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};
+      var lineObj = getLine(lineNo), text = lineObj.text;
+      var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;
+      if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};
+      function getX(len) {
+        var sp = measureLine(lineObj, len);
+        if (tw) {
+          var off = Math.round(sp.top / th);
+          return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);
+        }
+        return sp.left;
+      }
+      var from = 0, fromX = 0, to = text.length, toX;
+      // Guess a suitable upper bound for our search.
+      var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));
+      for (;;) {
+        var estX = getX(estimated);
+        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));
+        else {toX = estX; to = estimated; break;}
+      }
+      if (x > toX) return {line: lineNo, ch: to};
+      // Try to guess a suitable lower bound as well.
+      estimated = Math.floor(to * 0.8); estX = getX(estimated);
+      if (estX < x) {from = estimated; fromX = estX;}
+      // Do a binary search between these bounds.
+      for (;;) {
+        if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to};
+        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
+        if (middleX > x) {to = middle; toX = middleX;}
+        else {from = middle; fromX = middleX;}
+      }
+    }
+    function pageCoords(pos) {
+      var local = localCoords(pos, true), off = eltOffset(lineSpace);
+      return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};
+    }
+
+    var cachedHeight, cachedHeightFor, measureText;
+    function textHeight() {
+      if (measureText == null) {
+        measureText = "<pre>";
+        for (var i = 0; i < 49; ++i) measureText += "x<br/>";
+        measureText += "x</pre>";
+      }
+      var offsetHeight = lineDiv.clientHeight;
+      if (offsetHeight == cachedHeightFor) return cachedHeight;
+      cachedHeightFor = offsetHeight;
+      measure.innerHTML = measureText;
+      cachedHeight = measure.firstChild.offsetHeight / 50 || 1;
+      measure.innerHTML = "";
+      return cachedHeight;
+    }
+    var cachedWidth, cachedWidthFor = 0;
+    function charWidth() {
+      if (scroller.clientWidth == cachedWidthFor) return cachedWidth;
+      cachedWidthFor = scroller.clientWidth;
+      return (cachedWidth = stringWidth("x"));
+    }
+    function paddingTop() {return lineSpace.offsetTop;}
+    function paddingLeft() {return lineSpace.offsetLeft;}
+
+    function posFromMouse(e, liberal) {
+      var offW = eltOffset(scroller, true), x, y;
+      // Fails unpredictably on IE[67] when mouse is dragged around quickly.
+      try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
+      // This is a mess of a heuristic to try and determine whether a
+      // scroll-bar was clicked or not, and to return null if one was
+      // (and !liberal).
+      if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))
+        return null;
+      var offL = eltOffset(lineSpace, true);
+      return coordsChar(x - offL.left, y - offL.top);
+    }
+    function onContextMenu(e) {
+      var pos = posFromMouse(e);
+      if (!pos || window.opera) return; // Opera is difficult.
+      if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
+        operation(setCursor)(pos.line, pos.ch);
+
+      var oldCSS = input.style.cssText;
+      inputDiv.style.position = "absolute";
+      input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
+        "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " +
+        "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
+      leaveInputAlone = true;
+      var val = input.value = getSelection();
+      focusInput();
+      input.select();
+      function rehide() {
+        var newVal = splitLines(input.value).join("\n");
+        if (newVal != val) operation(replaceSelection)(newVal, "end");
+        inputDiv.style.position = "relative";
+        input.style.cssText = oldCSS;
+        leaveInputAlone = false;
+        resetInput(true);
+        slowPoll();
+      }
+
+      if (gecko) {
+        e_stop(e);
+        var mouseup = connect(window, "mouseup", function() {
+          mouseup();
+          setTimeout(rehide, 20);
+        }, true);
+      }
+      else {
+        setTimeout(rehide, 50);
+      }
+    }
+
+    // Cursor-blinking
+    function restartBlink() {
+      clearInterval(blinker);
+      var on = true;
+      cursor.style.visibility = "";
+      blinker = setInterval(function() {
+        cursor.style.visibility = (on = !on) ? "" : "hidden";
+      }, 650);
+    }
+
+    var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
+    function matchBrackets(autoclear) {
+      var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;
+      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
+      if (!match) return;
+      var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles;
+      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)
+        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}
+
+      var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
+      function scan(line, from, to) {
+        if (!line.text) return;
+        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
+        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
+          var text = st[i];
+          if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}
+          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
+            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
+              var match = matching[cur];
+              if (match.charAt(1) == ">" == forward) stack.push(cur);
+              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
+              else if (!stack.length) return {pos: pos, match: true};
+            }
+          }
+        }
+      }
+      for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {
+        var line = getLine(i), first = i == head.line;
+        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
+        if (found) break;
+      }
+      if (!found) found = {pos: null, match: false};
+      var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
+      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
+          two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
+      var clear = operation(function(){one.clear(); two && two.clear();});
+      if (autoclear) setTimeout(clear, 800);
+      else bracketHighlighted = clear;
+    }
+
+    // Finds the line to start with when starting a parse. Tries to
+    // find a line with a stateAfter, so that it can start with a
+    // valid state. If that fails, it returns the line with the
+    // smallest indentation, which tends to need the least context to
+    // parse correctly.
+    function findStartLine(n) {
+      var minindent, minline;
+      for (var search = n, lim = n - 40; search > lim; --search) {
+        if (search == 0) return 0;
+        var line = getLine(search-1);
+        if (line.stateAfter) return search;
+        var indented = line.indentation(options.tabSize);
+        if (minline == null || minindent > indented) {
+          minline = search - 1;
+          minindent = indented;
+        }
+      }
+      return minline;
+    }
+    function getStateBefore(n) {
+      var start = findStartLine(n), state = start && getLine(start-1).stateAfter;
+      if (!state) state = startState(mode);
+      else state = copyState(mode, state);
+      doc.iter(start, n, function(line) {
+        line.highlight(mode, state, options.tabSize);
+        line.stateAfter = copyState(mode, state);
+      });
+      if (start < n) changes.push({from: start, to: n});
+      if (n < doc.size && !getLine(n).stateAfter) work.push(n);
+      return state;
+    }
+    function highlightLines(start, end) {
+      var state = getStateBefore(start);
+      doc.iter(start, end, function(line) {
+        line.highlight(mode, state, options.tabSize);
+        line.stateAfter = copyState(mode, state);
+      });
+    }
+    function highlightWorker() {
+      var end = +new Date + options.workTime;
+      var foundWork = work.length;
+      while (work.length) {
+        if (!getLine(showingFrom).stateAfter) var task = showingFrom;
+        else var task = work.pop();
+        if (task >= doc.size) continue;
+        var start = findStartLine(task), state = start && getLine(start-1).stateAfter;
+        if (state) state = copyState(mode, state);
+        else state = startState(mode);
+
+        var unchanged = 0, compare = mode.compareStates, realChange = false,
+            i = start, bail = false;
+        doc.iter(i, doc.size, function(line) {
+          var hadState = line.stateAfter;
+          if (+new Date > end) {
+            work.push(i);
+            startWorker(options.workDelay);
+            if (realChange) changes.push({from: task, to: i + 1});
+            return (bail = true);
+          }
+          var changed = line.highlight(mode, state, options.tabSize);
+          if (changed) realChange = true;
+          line.stateAfter = copyState(mode, state);
+          if (compare) {
+            if (hadState && compare(hadState, state)) return true;
+          } else {
+            if (changed !== false || !hadState) unchanged = 0;
+            else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
+              return true;
+          }
+          ++i;
+        });
+        if (bail) return;
+        if (realChange) changes.push({from: task, to: i + 1});
+      }
+      if (foundWork && options.onHighlightComplete)
+        options.onHighlightComplete(instance);
+    }
+    function startWorker(time) {
+      if (!work.length) return;
+      highlight.set(time, operation(highlightWorker));
+    }
+
+    // Operations are used to wrap changes in such a way that each
+    // change won't have to update the cursor and display (which would
+    // be awkward, slow, and error-prone), but instead updates are
+    // batched and then all combined and executed at once.
+    function startOperation() {
+      updateInput = userSelChange = textChanged = null;
+      changes = []; selectionChanged = false; callbacks = [];
+    }
+    function endOperation() {
+      var reScroll = false, updated;
+      if (selectionChanged) reScroll = !scrollCursorIntoView();
+      if (changes.length) updated = updateDisplay(changes, true);
+      else {
+        if (selectionChanged) updateCursor();
+        if (gutterDirty) updateGutter();
+      }
+      if (reScroll) scrollCursorIntoView();
+      if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
+
+      if (focused && !leaveInputAlone &&
+          (updateInput === true || (updateInput !== false && selectionChanged)))
+        resetInput(userSelChange);
+
+      if (selectionChanged && options.matchBrackets)
+        setTimeout(operation(function() {
+          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
+          if (posEq(sel.from, sel.to)) matchBrackets(false);
+        }), 20);
+      var tc = textChanged, cbs = callbacks; // these can be reset by callbacks
+      if (selectionChanged && options.onCursorActivity)
+        options.onCursorActivity(instance);
+      if (tc && options.onChange && instance)
+        options.onChange(instance, tc);
+      for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
+      if (updated && options.onUpdate) options.onUpdate(instance);
+    }
+    var nestedOperation = 0;
+    function operation(f) {
+      return function() {
+        if (!nestedOperation++) startOperation();
+        try {var result = f.apply(this, arguments);}
+        finally {if (!--nestedOperation) endOperation();}
+        return result;
+      };
+    }
+
+    for (var ext in extensions)
+      if (extensions.propertyIsEnumerable(ext) &&
+          !instance.propertyIsEnumerable(ext))
+        instance[ext] = extensions[ext];
+    return instance;
+  } // (end of function CodeMirror)
+
+  // The default configuration options.
+  CodeMirror.defaults = {
+    value: "",
+    mode: null,
+    theme: "default",
+    indentUnit: 2,
+    indentWithTabs: false,
+    tabSize: 4,
+    keyMap: "default",
+    extraKeys: null,
+    electricChars: true,
+    onKeyEvent: null,
+    lineWrapping: false,
+    lineNumbers: false,
+    gutter: false,
+    fixedGutter: false,
+    firstLineNumber: 1,
+    readOnly: false,
+    onChange: null,
+    onCursorActivity: null,
+    onGutterClick: null,
+    onHighlightComplete: null,
+    onUpdate: null,
+    onFocus: null, onBlur: null, onScroll: null,
+    matchBrackets: false,
+    workTime: 100,
+    workDelay: 200,
+    pollInterval: 100,
+    undoDepth: 40,
+    tabindex: null,
+    document: window.document
+  };
+
+  var mac = /Mac/.test(navigator.platform);
+  var win = /Win/.test(navigator.platform);
+
+  // Known modes, by name and by MIME
+  var modes = {}, mimeModes = {};
+  CodeMirror.defineMode = function(name, mode) {
+    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
+    modes[name] = mode;
+  };
+  CodeMirror.defineMIME = function(mime, spec) {
+    mimeModes[mime] = spec;
+  };
+  CodeMirror.getMode = function(options, spec) {
+    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
+      spec = mimeModes[spec];
+    if (typeof spec == "string")
+      var mname = spec, config = {};
+    else if (spec != null)
+      var mname = spec.name, config = spec;
+    var mfactory = modes[mname];
+    if (!mfactory) {
+      if (window.console) console.warn("No mode " + mname + " found, falling back to plain text.");
+      return CodeMirror.getMode(options, "text/plain");
+    }
+    return mfactory(options, config || {});
+  };
+  CodeMirror.listModes = function() {
+    var list = [];
+    for (var m in modes)
+      if (modes.propertyIsEnumerable(m)) list.push(m);
+    return list;
+  };
+  CodeMirror.listMIMEs = function() {
+    var list = [];
+    for (var m in mimeModes)
+      if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});
+    return list;
+  };
+
+  var extensions = CodeMirror.extensions = {};
+  CodeMirror.defineExtension = function(name, func) {
+    extensions[name] = func;
+  };
+
+  var commands = CodeMirror.commands = {
+    selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
+    killLine: function(cm) {
+      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
+      if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0});
+      else cm.replaceRange("", from, sel ? to : {line: from.line});
+    },
+    deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});},
+    undo: function(cm) {cm.undo();},
+    redo: function(cm) {cm.redo();},
+    goDocStart: function(cm) {cm.setCursor(0, 0, true);},
+    goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);},
+    goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);},
+    goLineStartSmart: function(cm) {
+      var cur = cm.getCursor();
+      var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/));
+      cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true);
+    },
+    goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);},
+    goLineUp: function(cm) {cm.moveV(-1, "line");},
+    goLineDown: function(cm) {cm.moveV(1, "line");},
+    goPageUp: function(cm) {cm.moveV(-1, "page");},
+    goPageDown: function(cm) {cm.moveV(1, "page");},
+    goCharLeft: function(cm) {cm.moveH(-1, "char");},
+    goCharRight: function(cm) {cm.moveH(1, "char");},
+    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
+    goColumnRight: function(cm) {cm.moveH(1, "column");},
+    goWordLeft: function(cm) {cm.moveH(-1, "word");},
+    goWordRight: function(cm) {cm.moveH(1, "word");},
+    delCharLeft: function(cm) {cm.deleteH(-1, "char");},
+    delCharRight: function(cm) {cm.deleteH(1, "char");},
+    delWordLeft: function(cm) {cm.deleteH(-1, "word");},
+    delWordRight: function(cm) {cm.deleteH(1, "word");},
+    indentAuto: function(cm) {cm.indentSelection("smart");},
+    indentMore: function(cm) {cm.indentSelection("add");},
+    indentLess: function(cm) {cm.indentSelection("subtract");},
+    insertTab: function(cm) {cm.replaceSelection("\t", "end");},
+    transposeChars: function(cm) {
+      var cur = cm.getCursor(), line = cm.getLine(cur.line);
+      if (cur.ch > 0 && cur.ch < line.length - 1)
+        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
+                        {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});
+    },
+    newlineAndIndent: function(cm) {
+      cm.replaceSelection("\n", "end");
+      cm.indentLine(cm.getCursor().line);
+    },
+    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
+  };
+
+  var keyMap = CodeMirror.keyMap = {};
+  keyMap.basic = {
+    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
+    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
+    "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "indentMore", "Shift-Tab": "indentLess",
+    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
+  };
+  // Note that the save and find-related commands aren't defined by
+  // default. Unknown commands are simply ignored.
+  keyMap.pcDefault = {
+    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
+    "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
+    "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
+    "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
+    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
+    fallthrough: "basic"
+  };
+  keyMap.macDefault = {
+    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
+    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
+    "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
+    "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
+    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
+    fallthrough: ["basic", "emacsy"]
+  };
+  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
+  keyMap.emacsy = {
+    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
+    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
+    "Ctrl-V": "goPageUp", "Shift-Ctrl-V": "goPageDown", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft",
+    "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
+  };
+
+  function lookupKey(name, extraMap, map) {
+    function lookup(name, map, ft) {
+      var found = map[name];
+      if (found != null) return found;
+      if (ft == null) ft = map.fallthrough;
+      if (ft == null) return map.catchall;
+      if (typeof ft == "string") return lookup(name, keyMap[ft]);
+      for (var i = 0, e = ft.length; i < e; ++i) {
+        found = lookup(name, keyMap[ft[i]]);
+        if (found != null) return found;
+      }
+      return null;
+    }
+    return extraMap ? lookup(name, extraMap, map) : lookup(name, keyMap[map]);
+  }
+  function isModifierKey(event) {
+    var name = keyNames[event.keyCode];
+    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
+  }
+
+  CodeMirror.fromTextArea = function(textarea, options) {
+    if (!options) options = {};
+    options.value = textarea.value;
+    if (!options.tabindex && textarea.tabindex)
+      options.tabindex = textarea.tabindex;
+
+    function save() {textarea.value = instance.getValue();}
+    if (textarea.form) {
+      // Deplorable hack to make the submit method do the right thing.
+      var rmSubmit = connect(textarea.form, "submit", save, true);
+      if (typeof textarea.form.submit == "function") {
+        var realSubmit = textarea.form.submit;
+        function wrappedSubmit() {
+          save();
+          textarea.form.submit = realSubmit;
+          textarea.form.submit();
+          textarea.form.submit = wrappedSubmit;
+        }
+        textarea.form.submit = wrappedSubmit;
+      }
+    }
+
+    textarea.style.display = "none";
+    var instance = CodeMirror(function(node) {
+      textarea.parentNode.insertBefore(node, textarea.nextSibling);
+    }, options);
+    instance.save = save;
+    instance.getTextArea = function() { return textarea; };
+    instance.toTextArea = function() {
+      save();
+      textarea.parentNode.removeChild(instance.getWrapperElement());
+      textarea.style.display = "";
+      if (textarea.form) {
+        rmSubmit();
+        if (typeof textarea.form.submit == "function")
+          textarea.form.submit = realSubmit;
+      }
+    };
+    return instance;
+  };
+
+  // Utility functions for working with state. Exported because modes
+  // sometimes need to do this.
+  function copyState(mode, state) {
+    if (state === true) return state;
+    if (mode.copyState) return mode.copyState(state);
+    var nstate = {};
+    for (var n in state) {
+      var val = state[n];
+      if (val instanceof Array) val = val.concat([]);
+      nstate[n] = val;
+    }
+    return nstate;
+  }
+  CodeMirror.copyState = copyState;
+  function startState(mode, a1, a2) {
+    return mode.startState ? mode.startState(a1, a2) : true;
+  }
+  CodeMirror.startState = startState;
+
+  // The character stream used by a mode's parser.
+  function StringStream(string, tabSize) {
+    this.pos = this.start = 0;
+    this.string = string;
+    this.tabSize = tabSize || 8;
+  }
+  StringStream.prototype = {
+    eol: function() {return this.pos >= this.string.length;},
+    sol: function() {return this.pos == 0;},
+    peek: function() {return this.string.charAt(this.pos);},
+    next: function() {
+      if (this.pos < this.string.length)
+        return this.string.charAt(this.pos++);
+    },
+    eat: function(match) {
+      var ch = this.string.charAt(this.pos);
+      if (typeof match == "string") var ok = ch == match;
+      else var ok = ch && (match.test ? match.test(ch) : match(ch));
+      if (ok) {++this.pos; return ch;}
+    },
+    eatWhile: function(match) {
+      var start = this.pos;
+      while (this.eat(match)){}
+      return this.pos > start;
+    },
+    eatSpace: function() {
+      var start = this.pos;
+      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+      return this.pos > start;
+    },
+    skipToEnd: function() {this.pos = this.string.length;},
+    skipTo: function(ch) {
+      var found = this.string.indexOf(ch, this.pos);
+      if (found > -1) {this.pos = found; return true;}
+    },
+    backUp: function(n) {this.pos -= n;},
+    column: function() {return countColumn(this.string, this.start, this.tabSize);},
+    indentation: function() {return countColumn(this.string, null, this.tabSize);},
+    match: function(pattern, consume, caseInsensitive) {
+      if (typeof pattern == "string") {
+        function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
+        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+          if (consume !== false) this.pos += pattern.length;
+          return true;
+        }
+      }
+      else {
+        var match = this.string.slice(this.pos).match(pattern);
+        if (match && consume !== false) this.pos += match[0].length;
+        return match;
+      }
+    },
+    current: function(){return this.string.slice(this.start, this.pos);}
+  };
+  CodeMirror.StringStream = StringStream;
+
+  function MarkedText(from, to, className, set) {
+    this.from = from; this.to = to; this.style = className; this.set = set;
+  }
+  MarkedText.prototype = {
+    attach: function(line) { this.set.push(line); },
+    detach: function(line) {
+      var ix = indexOf(this.set, line);
+      if (ix > -1) this.set.splice(ix, 1);
+    },
+    split: function(pos, lenBefore) {
+      if (this.to <= pos && this.to != null) return null;
+      var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
+      var to = this.to == null ? null : this.to - pos + lenBefore;
+      return new MarkedText(from, to, this.style, this.set);
+    },
+    dup: function() { return new MarkedText(null, null, this.style, this.set); },
+    clipTo: function(fromOpen, from, toOpen, to, diff) {
+      if (this.from != null && this.from >= from)
+        this.from = Math.max(to, this.from) + diff;
+      if (this.to != null && this.to > from)
+        this.to = to < this.to ? this.to + diff : from;
+      if (fromOpen && to > this.from && (to < this.to || this.to == null))
+        this.from = null;
+      if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
+        this.to = null;
+    },
+    isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
+    sameSet: function(x) { return this.set == x.set; }
+  };
+
+  function Bookmark(pos) {
+    this.from = pos; this.to = pos; this.line = null;
+  }
+  Bookmark.prototype = {
+    attach: function(line) { this.line = line; },
+    detach: function(line) { if (this.line == line) this.line = null; },
+    split: function(pos, lenBefore) {
+      if (pos < this.from) {
+        this.from = this.to = (this.from - pos) + lenBefore;
+        return this;
+      }
+    },
+    isDead: function() { return this.from > this.to; },
+    clipTo: function(fromOpen, from, toOpen, to, diff) {
+      if ((fromOpen || from < this.from) && (toOpen || to > this.to)) {
+        this.from = 0; this.to = -1;
+      } else if (this.from > from) {
+        this.from = this.to = Math.max(to, this.from) + diff;
+      }
+    },
+    sameSet: function(x) { return false; },
+    find: function() {
+      if (!this.line || !this.line.parent) return null;
+      return {line: lineNo(this.line), ch: this.from};
+    },
+    clear: function() {
+      if (this.line) {
+        var found = indexOf(this.line.marked, this);
+        if (found != -1) this.line.marked.splice(found, 1);
+        this.line = null;
+      }
+    }
+  };
+
+  // Line objects. These hold state related to a line, including
+  // highlighting info (the styles array).
+  function Line(text, styles) {
+    this.styles = styles || [text, null];
+    this.text = text;
+    this.height = 1;
+    this.marked = this.gutterMarker = this.className = this.handlers = null;
+    this.stateAfter = this.parent = this.hidden = null;
+  }
+  Line.inheritMarks = function(text, orig) {
+    var ln = new Line(text), mk = orig && orig.marked;
+    if (mk) {
+      for (var i = 0; i < mk.length; ++i) {
+        if (mk[i].to == null && mk[i].style) {
+          var newmk = ln.marked || (ln.marked = []), mark = mk[i];
+          var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);
+        }
+      }
+    }
+    return ln;
+  }
+  Line.prototype = {
+    // Replace a piece of a line, keeping the styles around it intact.
+    replace: function(from, to_, text) {
+      var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_;
+      copyStyles(0, from, this.styles, st);
+      if (text) st.push(text, null);
+      copyStyles(to, this.text.length, this.styles, st);
+      this.styles = st;
+      this.text = this.text.slice(0, from) + text + this.text.slice(to);
+      this.stateAfter = null;
+      if (mk) {
+        var diff = text.length - (to - from);
+        for (var i = 0, mark = mk[i]; i < mk.length; ++i) {
+          mark.clipTo(from == null, from || 0, to_ == null, to, diff);
+          if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}
+        }
+      }
+    },
+    // Split a part off a line, keeping styles and markers intact.
+    split: function(pos, textBefore) {
+      var st = [textBefore, null], mk = this.marked;
+      copyStyles(pos, this.text.length, this.styles, st);
+      var taken = new Line(textBefore + this.text.slice(pos), st);
+      if (mk) {
+        for (var i = 0; i < mk.length; ++i) {
+          var mark = mk[i];
+          var newmark = mark.split(pos, textBefore.length);
+          if (newmark) {
+            if (!taken.marked) taken.marked = [];
+            taken.marked.push(newmark); newmark.attach(taken);
+          }
+        }
+      }
+      return taken;
+    },
+    append: function(line) {
+      var mylen = this.text.length, mk = line.marked, mymk = this.marked;
+      this.text += line.text;
+      copyStyles(0, line.text.length, line.styles, this.styles);
+      if (mymk) {
+        for (var i = 0; i < mymk.length; ++i)
+          if (mymk[i].to == null) mymk[i].to = mylen;
+      }
+      if (mk && mk.length) {
+        if (!mymk) this.marked = mymk = [];
+        outer: for (var i = 0; i < mk.length; ++i) {
+          var mark = mk[i];
+          if (!mark.from) {
+            for (var j = 0; j < mymk.length; ++j) {
+              var mymark = mymk[j];
+              if (mymark.to == mylen && mymark.sameSet(mark)) {
+                mymark.to = mark.to == null ? null : mark.to + mylen;
+                if (mymark.isDead()) {
+                  mymark.detach(this);
+                  mk.splice(i--, 1);
+                }
+                continue outer;
+              }
+            }
+          }
+          mymk.push(mark);
+          mark.attach(this);
+          mark.from += mylen;
+          if (mark.to != null) mark.to += mylen;
+        }
+      }
+    },
+    fixMarkEnds: function(other) {
+      var mk = this.marked, omk = other.marked;
+      if (!mk) return;
+      for (var i = 0; i < mk.length; ++i) {
+        var mark = mk[i], close = mark.to == null;
+        if (close && omk) {
+          for (var j = 0; j < omk.length; ++j)
+            if (omk[j].sameSet(mark)) {close = false; break;}
+        }
+        if (close) mark.to = this.text.length;
+      }
+    },
+    fixMarkStarts: function() {
+      var mk = this.marked;
+      if (!mk) return;
+      for (var i = 0; i < mk.length; ++i)
+        if (mk[i].from == null) mk[i].from = 0;
+    },
+    addMark: function(mark) {
+      mark.attach(this);
+      if (this.marked == null) this.marked = [];
+      this.marked.push(mark);
+      this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});
+    },
+    // Run the given mode's parser over a line, update the styles
+    // array, which contains alternating fragments of text and CSS
+    // classes.
+    highlight: function(mode, state, tabSize) {
+      var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0;
+      var changed = false, curWord = st[0], prevWord;
+      if (this.text == "" && mode.blankLine) mode.blankLine(state);
+      while (!stream.eol()) {
+        var style = mode.token(stream, state);
+        var substr = this.text.slice(stream.start, stream.pos);
+        stream.start = stream.pos;
+        if (pos && st[pos-1] == style)
+          st[pos-2] += substr;
+        else if (substr) {
+          if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true;
+          st[pos++] = substr; st[pos++] = style;
+          prevWord = curWord; curWord = st[pos];
+        }
+        // Give up when line is ridiculously long
+        if (stream.pos > 5000) {
+          st[pos++] = this.text.slice(stream.pos); st[pos++] = null;
+          break;
+        }
+      }
+      if (st.length != pos) {st.length = pos; changed = true;}
+      if (pos && st[pos-2] != prevWord) changed = true;
+      // Short lines with simple highlights return null, and are
+      // counted as changed by the driver because they are likely to
+      // highlight the same way in various contexts.
+      return changed || (st.length < 5 && this.text.length < 10 ? null : false);
+    },
+    // Fetch the parser token for a given character. Useful for hacks
+    // that want to inspect the mode state (say, for completion).
+    getTokenAt: function(mode, state, ch) {
+      var txt = this.text, stream = new StringStream(txt);
+      while (stream.pos < ch && !stream.eol()) {
+        stream.start = stream.pos;
+        var style = mode.token(stream, state);
+      }
+      return {start: stream.start,
+              end: stream.pos,
+              string: stream.current(),
+              className: style || null,
+              state: state};
+    },
+    indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
+    // Produces an HTML fragment for the line, taking selection,
+    // marking, and highlighting into account.
+    getHTML: function(sfrom, sto, includePre, tabText, endAt) {
+      var html = [], first = true;
+      if (includePre)
+        html.push(this.className ? '<pre class="' + this.className + '">': "<pre>");
+      function span(text, style) {
+        if (!text) return;
+        // Work around a bug where, in some compat modes, IE ignores leading spaces
+        if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
+        first = false;
+        if (style) html.push('<span class="', style, '">', htmlEscape(text).replace(/\t/g, tabText), "</span>");
+        else html.push(htmlEscape(text).replace(/\t/g, tabText));
+      }
+      var st = this.styles, allText = this.text, marked = this.marked;
+      if (sfrom == sto) sfrom = null;
+      var len = allText.length;
+      if (endAt != null) len = Math.min(endAt, len);
+
+      if (!allText && endAt == null)
+        span(" ", sfrom != null && sto == null ? "CodeMirror-selected" : null);
+      else if (!marked && sfrom == null)
+        for (var i = 0, ch = 0; ch < len; i+=2) {
+          var str = st[i], style = st[i+1], l = str.length;
+          if (ch + l > len) str = str.slice(0, len - ch);
+          ch += l;
+          span(str, style && "cm-" + style);
+        }
+      else {
+        var pos = 0, i = 0, text = "", style, sg = 0;
+        var markpos = -1, mark = null;
+        function nextMark() {
+          if (marked) {
+            markpos += 1;
+            mark = (markpos < marked.length) ? marked[markpos] : null;
+          }
+        }
+        nextMark();
+        while (pos < len) {
+          var upto = len;
+          var extraStyle = "";
+          if (sfrom != null) {
+            if (sfrom > pos) upto = sfrom;
+            else if (sto == null || sto > pos) {
+              extraStyle = " CodeMirror-selected";
+              if (sto != null) upto = Math.min(upto, sto);
+            }
+          }
+          while (mark && mark.to != null && mark.to <= pos) nextMark();
+          if (mark) {
+            if (mark.from > pos) upto = Math.min(upto, mark.from);
+            else {
+              extraStyle += " " + mark.style;
+              if (mark.to != null) upto = Math.min(upto, mark.to);
+            }
+          }
+          for (;;) {
+            var end = pos + text.length;
+            var appliedStyle = style;
+            if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;
+            span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
+            if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
+            pos = end;
+            text = st[i++]; style = "cm-" + st[i++];
+          }
+        }
+        if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
+      }
+      if (includePre) html.push("</pre>");
+      return html.join("");
+    },
+    cleanUp: function() {
+      this.parent = null;
+      if (this.marked)
+        for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);
+    }
+  };
+  // Utility used by replace and split above
+  function copyStyles(from, to, source, dest) {
+    for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {
+      var part = source[i], end = pos + part.length;
+      if (state == 0) {
+        if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
+        if (end >= from) state = 1;
+      }
+      else if (state == 1) {
+        if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
+        else dest.push(part, source[i+1]);
+      }
+      pos = end;
+    }
+  }
+
+  // Data structure that holds the sequence of lines.
+  function LeafChunk(lines) {
+    this.lines = lines;
+    this.parent = null;
+    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
+      lines[i].parent = this;
+      height += lines[i].height;
+    }
+    this.height = height;
+  }
+  LeafChunk.prototype = {
+    chunkSize: function() { return this.lines.length; },
+    remove: function(at, n, callbacks) {
+      for (var i = at, e = at + n; i < e; ++i) {
+        var line = this.lines[i];
+        this.height -= line.height;
+        line.cleanUp();
+        if (line.handlers)
+          for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]);
+      }
+      this.lines.splice(at, n);
+    },
+    collapse: function(lines) {
+      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
+    },
+    insertHeight: function(at, lines, height) {
+      this.height += height;
+      this.lines.splice.apply(this.lines, [at, 0].concat(lines));
+      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
+    },
+    iterN: function(at, n, op) {
+      for (var e = at + n; at < e; ++at)
+        if (op(this.lines[at])) return true;
+    }
+  };
+  function BranchChunk(children) {
+    this.children = children;
+    var size = 0, height = 0;
+    for (var i = 0, e = children.length; i < e; ++i) {
+      var ch = children[i];
+      size += ch.chunkSize(); height += ch.height;
+      ch.parent = this;
+    }
+    this.size = size;
+    this.height = height;
+    this.parent = null;
+  }
+  BranchChunk.prototype = {
+    chunkSize: function() { return this.size; },
+    remove: function(at, n, callbacks) {
+      this.size -= n;
+      for (var i = 0; i < this.children.length; ++i) {
+        var child = this.children[i], sz = child.chunkSize();
+        if (at < sz) {
+          var rm = Math.min(n, sz - at), oldHeight = child.height;
+          child.remove(at, rm, callbacks);
+          this.height -= oldHeight - child.height;
+          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
+          if ((n -= rm) == 0) break;
+          at = 0;
+        } else at -= sz;
+      }
+      if (this.size - n < 25) {
+        var lines = [];
+        this.collapse(lines);
+        this.children = [new LeafChunk(lines)];
+      }
+    },
+    collapse: function(lines) {
+      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
+    },
+    insert: function(at, lines) {
+      var height = 0;
+      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
+      this.insertHeight(at, lines, height);
+    },
+    insertHeight: function(at, lines, height) {
+      this.size += lines.length;
+      this.height += height;
+      for (var i = 0, e = this.children.length; i < e; ++i) {
+        var child = this.children[i], sz = child.chunkSize();
+        if (at <= sz) {
+          child.insertHeight(at, lines, height);
+          if (child.lines && child.lines.length > 50) {
+            while (child.lines.length > 50) {
+              var spilled = child.lines.splice(child.lines.length - 25, 25);
+              var newleaf = new LeafChunk(spilled);
+              child.height -= newleaf.height;
+              this.children.splice(i + 1, 0, newleaf);
+              newleaf.parent = this;
+            }
+            this.maybeSpill();
+          }
+          break;
+        }
+        at -= sz;
+      }
+    },
+    maybeSpill: function() {
+      if (this.children.length <= 10) return;
+      var me = this;
+      do {
+        var spilled = me.children.splice(me.children.length - 5, 5);
+        var sibling = new BranchChunk(spilled);
+        if (!me.parent) { // Become the parent node
+          var copy = new BranchChunk(me.children);
+          copy.parent = me;
+          me.children = [copy, sibling];
+          me = copy;
+        } else {
+          me.size -= sibling.size;
+          me.height -= sibling.height;
+          var myIndex = indexOf(me.parent.children, me);
+          me.parent.children.splice(myIndex + 1, 0, sibling);
+        }
+        sibling.parent = me.parent;
+      } while (me.children.length > 10);
+      me.parent.maybeSpill();
+    },
+    iter: function(from, to, op) { this.iterN(from, to - from, op); },
+    iterN: function(at, n, op) {
+      for (var i = 0, e = this.children.length; i < e; ++i) {
+        var child = this.children[i], sz = child.chunkSize();
+        if (at < sz) {
+          var used = Math.min(n, sz - at);
+          if (child.iterN(at, used, op)) return true;
+          if ((n -= used) == 0) break;
+          at = 0;
+        } else at -= sz;
+      }
+    }
+  };
+
+  function getLineAt(chunk, n) {
+    while (!chunk.lines) {
+      for (var i = 0;; ++i) {
+        var child = chunk.children[i], sz = child.chunkSize();
+        if (n < sz) { chunk = child; break; }
+        n -= sz;
+      }
+    }
+    return chunk.lines[n];
+  }
+  function lineNo(line) {
+    if (line.parent == null) return null;
+    var cur = line.parent, no = indexOf(cur.lines, line);
+    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
+      for (var i = 0, e = chunk.children.length; ; ++i) {
+        if (chunk.children[i] == cur) break;
+        no += chunk.children[i].chunkSize();
+      }
+    }
+    return no;
+  }
+  function lineAtHeight(chunk, h) {
+    var n = 0;
+    outer: do {
+      for (var i = 0, e = chunk.children.length; i < e; ++i) {
+        var child = chunk.children[i], ch = child.height;
+        if (h < ch) { chunk = child; continue outer; }
+        h -= ch;
+        n += child.chunkSize();
+      }
+      return n;
+    } while (!chunk.lines);
+    for (var i = 0, e = chunk.lines.length; i < e; ++i) {
+      var line = chunk.lines[i], lh = line.height;
+      if (h < lh) break;
+      h -= lh;
+    }
+    return n + i;
+  }
+  function heightAtLine(chunk, n) {
+    var h = 0;
+    outer: do {
+      for (var i = 0, e = chunk.children.length; i < e; ++i) {
+        var child = chunk.children[i], sz = child.chunkSize();
+        if (n < sz) { chunk = child; continue outer; }
+        n -= sz;
+        h += child.height;
+      }
+      return h;
+    } while (!chunk.lines);
+    for (var i = 0; i < n; ++i) h += chunk.lines[i].height;
+    return h;
+  }
+
+  // The history object 'chunks' changes that are made close together
+  // and at almost the same time into bigger undoable units.
+  function History() {
+    this.time = 0;
+    this.done = []; this.undone = [];
+  }
+  History.prototype = {
+    addChange: function(start, added, old) {
+      this.undone.length = 0;
+      var time = +new Date, last = this.done[this.done.length - 1];
+      if (time - this.time > 400 || !last ||
+          last.start > start + added || last.start + last.added < start - last.added + last.old.length)
+        this.done.push({start: start, added: added, old: old});
+      else {
+        var oldoff = 0;
+        if (start < last.start) {
+          for (var i = last.start - start - 1; i >= 0; --i)
+            last.old.unshift(old[i]);
+          last.added += last.start - start;
+          last.start = start;
+        }
+        else if (last.start < start) {
+          oldoff = start - last.start;
+          added += oldoff;
+        }
+        for (var i = last.added - oldoff, e = old.length; i < e; ++i)
+          last.old.push(old[i]);
+        if (last.added < added) last.added = added;
+      }
+      this.time = time;
+    }
+  };
+
+  function stopMethod() {e_stop(this);}
+  // Ensure an event has a stop method.
+  function addStop(event) {
+    if (!event.stop) event.stop = stopMethod;
+    return event;
+  }
+
+  function e_preventDefault(e) {
+    if (e.preventDefault) e.preventDefault();
+    else e.returnValue = false;
+  }
+  function e_stopPropagation(e) {
+    if (e.stopPropagation) e.stopPropagation();
+    else e.cancelBubble = true;
+  }
+  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
+  CodeMirror.e_stop = e_stop;
+  CodeMirror.e_preventDefault = e_preventDefault;
+  CodeMirror.e_stopPropagation = e_stopPropagation;
+
+  function e_target(e) {return e.target || e.srcElement;}
+  function e_button(e) {
+    if (e.which) return e.which;
+    else if (e.button & 1) return 1;
+    else if (e.button & 2) return 3;
+    else if (e.button & 4) return 2;
+  }
+
+  // Event handler registration. If disconnect is true, it'll return a
+  // function that unregisters the handler.
+  function connect(node, type, handler, disconnect) {
+    if (typeof node.addEventListener == "function") {
+      node.addEventListener(type, handler, false);
+      if (disconnect) return function() {node.removeEventListener(type, handler, false);};
+    }
+    else {
+      var wrapHandler = function(event) {handler(event || window.event);};
+      node.attachEvent("on" + type, wrapHandler);
+      if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
+    }
+  }
+  CodeMirror.connect = connect;
+
+  function Delayed() {this.id = null;}
+  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
+
+  // Detect drag-and-drop
+  var dragAndDrop = function() {
+    // IE8 has ondragstart and ondrop properties, but doesn't seem to
+    // actually support ondragstart the way it's supposed to work.
+    if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
+    var div = document.createElement('div');
+    return "draggable" in div;
+  }();
+
+  var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
+  var ie = /MSIE \d/.test(navigator.userAgent);
+  var webkit = /WebKit\//.test(navigator.userAgent);
+
+  var lineSep = "\n";
+  // Feature-detect whether newlines in textareas are converted to \r\n
+  (function () {
+    var te = document.createElement("textarea");
+    te.value = "foo\nbar";
+    if (te.value.indexOf("\r") > -1) lineSep = "\r\n";
+  }());
+
+  // Counts the column offset in a string, taking tabs into account.
+  // Used mostly to find indentation.
+  function countColumn(string, end, tabSize) {
+    if (end == null) {
+      end = string.search(/[^\s\u00a0]/);
+      if (end == -1) end = string.length;
+    }
+    for (var i = 0, n = 0; i < end; ++i) {
+      if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
+      else ++n;
+    }
+    return n;
+  }
+
+  function computedStyle(elt) {
+    if (elt.currentStyle) return elt.currentStyle;
+    return window.getComputedStyle(elt, null);
+  }
+
+  // Find the position of an element by following the offsetParent chain.
+  // If screen==true, it returns screen (rather than page) coordinates.
+  function eltOffset(node, screen) {
+    var bod = node.ownerDocument.body;
+    var x = 0, y = 0, skipBody = false;
+    for (var n = node; n; n = n.offsetParent) {
+      var ol = n.offsetLeft, ot = n.offsetTop;
+      // Firefox reports weird inverted offsets when the body has a border.
+      if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }
+      else { x += ol, y += ot; }
+      if (screen && computedStyle(n).position == "fixed")
+        skipBody = true;
+    }
+    var e = screen && !skipBody ? null : bod;
+    for (var n = node.parentNode; n != e; n = n.parentNode)
+      if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}
+    return {left: x, top: y};
+  }
+  // Use the faster and saner getBoundingClientRect method when possible.
+  if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {
+    // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
+    // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
+    try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
+    catch(e) { box = {top: 0, left: 0}; }
+    if (!screen) {
+      // Get the toplevel scroll, working around browser differences.
+      if (window.pageYOffset == null) {
+        var t = document.documentElement || document.body.parentNode;
+        if (t.scrollTop == null) t = document.body;
+        box.top += t.scrollTop; box.left += t.scrollLeft;
+      } else {
+        box.top += window.pageYOffset; box.left += window.pageXOffset;
+      }
+    }
+    return box;
+  };
+
+  // Get a node's text content.
+  function eltText(node) {
+    return node.textContent || node.innerText || node.nodeValue || "";
+  }
+
+  // Operations on {line, ch} objects.
+  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
+  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
+  function copyPos(x) {return {line: x.line, ch: x.ch};}
+
+  var escapeElement = document.createElement("pre");
+  function htmlEscape(str) {
+    escapeElement.textContent = str;
+    return escapeElement.innerHTML;
+  }
+  // Recent (late 2011) Opera betas insert bogus newlines at the start
+  // of the textContent, so we strip those.
+  if (htmlEscape("a") == "\na")
+    htmlEscape = function(str) {
+      escapeElement.textContent = str;
+      return escapeElement.innerHTML.slice(1);
+    };
+  // Some IEs don't preserve tabs through innerHTML
+  else if (htmlEscape("\t") != "\t")
+    htmlEscape = function(str) {
+      escapeElement.innerHTML = "";
+      escapeElement.appendChild(document.createTextNode(str));
+      return escapeElement.innerHTML;
+    };
+  CodeMirror.htmlEscape = htmlEscape;
+
+  // Used to position the cursor after an undo/redo by finding the
+  // last edited character.
+  function editEnd(from, to) {
+    if (!to) return from ? from.length : 0;
+    if (!from) return to.length;
+    for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)
+      if (from.charAt(i) != to.charAt(j)) break;
+    return j + 1;
+  }
+
+  function indexOf(collection, elt) {
+    if (collection.indexOf) return collection.indexOf(elt);
+    for (var i = 0, e = collection.length; i < e; ++i)
+      if (collection[i] == elt) return i;
+    return -1;
+  }
+  function isWordChar(ch) {
+    return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase();
+  }
+
+  // See if "".split is the broken IE version, if so, provide an
+  // alternative way to split lines.
+  var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
+    var pos = 0, nl, result = [];
+    while ((nl = string.indexOf("\n", pos)) > -1) {
+      result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl));
+      pos = nl + 1;
+    }
+    result.push(string.slice(pos));
+    return result;
+  } : function(string){return string.split(/\r?\n/);};
+  CodeMirror.splitLines = splitLines;
+
+  var hasSelection = window.getSelection ? function(te) {
+    try { return te.selectionStart != te.selectionEnd; }
+    catch(e) { return false; }
+  } : function(te) {
+    try {var range = te.ownerDocument.selection.createRange();}
+    catch(e) {}
+    if (!range || range.parentElement() != te) return false;
+    return range.compareEndPoints("StartToEnd", range) != 0;
+  };
+
+  CodeMirror.defineMode("null", function() {
+    return {token: function(stream) {stream.skipToEnd();}};
+  });
+  CodeMirror.defineMIME("text/plain", "null");
+
+  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
+                  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
+                  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
+                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 186: ";", 187: "=", 188: ",",
+                  189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp",
+                  63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right",
+                  63233: "Down", 63302: "Insert", 63272: "Delete"};
+  CodeMirror.keyNames = keyNames;
+  (function() {
+    // Number keys
+    for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
+    // Alphabetic keys
+    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
+    // Function keys
+    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
+  })();
+
+  return CodeMirror;
+})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/dialog.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/dialog.css
new file mode 100644
index 0000000..4cb467e
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/dialog.css
@@ -0,0 +1,23 @@
+.CodeMirror-dialog {
+  position: relative;
+}
+
+.CodeMirror-dialog > div {
+  position: absolute;
+  top: 0; left: 0; right: 0;
+  background: white;
+  border-bottom: 1px solid #eee;
+  z-index: 15;
+  padding: .1em .8em;
+  overflow: hidden;
+  color: #333;
+}
+
+.CodeMirror-dialog input {
+  border: none;
+  outline: none;
+  background: transparent;
+  width: 20em;
+  color: inherit;
+  font-family: monospace;
+}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/dialog.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/dialog.js
new file mode 100644
index 0000000..8950bf0
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/dialog.js
@@ -0,0 +1,63 @@
+// Open simple dialogs on top of an editor. Relies on dialog.css.
+
+(function() {
+  function dialogDiv(cm, template) {
+    var wrap = cm.getWrapperElement();
+    var dialog = wrap.insertBefore(document.createElement("div"), wrap.firstChild);
+    dialog.className = "CodeMirror-dialog";
+    dialog.innerHTML = '<div>' + template + '</div>';
+    return dialog;
+  }
+
+  CodeMirror.defineExtension("openDialog", function(template, callback) {
+    var dialog = dialogDiv(this, template);
+    var closed = false, me = this;
+    function close() {
+      if (closed) return;
+      closed = true;
+      dialog.parentNode.removeChild(dialog);
+    }
+    var inp = dialog.getElementsByTagName("input")[0];
+    if (inp) {
+      CodeMirror.connect(inp, "keydown", function(e) {
+        if (e.keyCode == 13 || e.keyCode == 27) {
+          CodeMirror.e_stop(e);
+          close();
+          me.focus();
+          if (e.keyCode == 13) callback(inp.value);
+        }
+      });
+      inp.focus();
+      CodeMirror.connect(inp, "blur", close);
+    }
+    return close;
+  });
+
+  CodeMirror.defineExtension("openConfirm", function(template, callbacks) {
+    var dialog = dialogDiv(this, template);
+    var buttons = dialog.getElementsByTagName("button");
+    var closed = false, me = this, blurring = 1;
+    function close() {
+      if (closed) return;
+      closed = true;
+      dialog.parentNode.removeChild(dialog);
+      me.focus();
+    }
+    buttons[0].focus();
+    for (var i = 0; i < buttons.length; ++i) {
+      var b = buttons[i];
+      (function(callback) {
+        CodeMirror.connect(b, "click", function(e) {
+          CodeMirror.e_preventDefault(e);
+          close();
+          if (callback) callback(me);
+        });
+      })(callbacks[i]);
+      CodeMirror.connect(b, "blur", function() {
+        --blurring;
+        setTimeout(function() { if (blurring <= 0) close(); }, 200);
+      });
+      CodeMirror.connect(b, "focus", function() { ++blurring; });
+    }
+  });
+})();
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/foldcode.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/foldcode.js
new file mode 100644
index 0000000..1895779
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/foldcode.js
@@ -0,0 +1,66 @@
+CodeMirror.braceRangeFinder = function(cm, line) {
+  var lineText = cm.getLine(line);
+  var startChar = lineText.lastIndexOf("{");
+  if (startChar < 0 || lineText.lastIndexOf("}") > startChar) return;
+  var tokenType = cm.getTokenAt({line: line, ch: startChar}).className;
+  var count = 1, lastLine = cm.lineCount(), end;
+  outer: for (var i = line + 1; i < lastLine; ++i) {
+    var text = cm.getLine(i), pos = 0;
+    for (;;) {
+      var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos);
+      if (nextOpen < 0) nextOpen = text.length;
+      if (nextClose < 0) nextClose = text.length;
+      pos = Math.min(nextOpen, nextClose);
+      if (pos == text.length) break;
+      if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
+        if (pos == nextOpen) ++count;
+        else if (!--count) { end = i; break outer; }
+      }
+      ++pos;
+    }
+  }
+  if (end == null || end == line + 1) return;
+  return end;
+};
+
+
+CodeMirror.newFoldFunction = function(rangeFinder, markText) {
+  var folded = [];
+  if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
+
+  function isFolded(cm, n) {
+    for (var i = 0; i < folded.length; ++i) {
+      var start = cm.lineInfo(folded[i].start);
+      if (!start) folded.splice(i--, 1);
+      else if (start.line == n) return {pos: i, region: folded[i]};
+    }
+  }
+
+  function expand(cm, region) {
+    cm.clearMarker(region.start);
+    for (var i = 0; i < region.hidden.length; ++i)
+      cm.showLine(region.hidden[i]);
+  }
+
+  return function(cm, line) {
+    cm.operation(function() {
+      var known = isFolded(cm, line);
+      if (known) {
+        folded.splice(known.pos, 1);
+        expand(cm, known.region);
+      } else {
+        var end = rangeFinder(cm, line);
+        if (end == null) return;
+        var hidden = [];
+        for (var i = line + 1; i < end; ++i) {
+          var handle = cm.hideLine(i);
+          if (handle) hidden.push(handle);
+        }
+        var first = cm.setMarker(line, markText);
+        var region = {start: first, hidden: hidden};
+        cm.onDeleteLine(first, function() { expand(cm, region); });
+        folded.push(region);
+      }
+    });
+  };
+};
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/formatting.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/formatting.js
new file mode 100644
index 0000000..986bcb8
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/formatting.js
@@ -0,0 +1,291 @@
+// ============== Formatting extensions ============================
+// A common storage for all mode-specific formatting features
+if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};
+
+// Returns the extension of the editor's current mode
+CodeMirror.defineExtension("getModeExt", function () {
+  return CodeMirror.modeExtensions[this.getOption("mode")];
+});
+
+// If the current mode is 'htmlmixed', returns the extension of a mode located at
+// the specified position (can be htmlmixed, css or javascript). Otherwise, simply
+// returns the extension of the editor's current mode.
+CodeMirror.defineExtension("getModeExtAtPos", function (pos) {
+  var token = this.getTokenAt(pos);
+  if (token && token.state && token.state.mode)
+    return CodeMirror.modeExtensions[token.state.mode == "html" ? "htmlmixed" : token.state.mode];
+  else
+    return this.getModeExt();
+});
+
+// Comment/uncomment the specified range
+CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
+  var curMode = this.getModeExtAtPos(this.getCursor());
+  if (isComment) { // Comment range
+    var commentedText = this.getRange(from, to);
+    this.replaceRange(curMode.commentStart + this.getRange(from, to) + curMode.commentEnd
+      , from, to);
+    if (from.line == to.line && from.ch == to.ch) { // An empty comment inserted - put cursor inside
+      this.setCursor(from.line, from.ch + curMode.commentStart.length);
+    }
+  }
+  else { // Uncomment range
+    var selText = this.getRange(from, to);
+    var startIndex = selText.indexOf(curMode.commentStart);
+    var endIndex = selText.lastIndexOf(curMode.commentEnd);
+    if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
+      // Take string till comment start
+      selText = selText.substr(0, startIndex)
+      // From comment start till comment end
+        + selText.substring(startIndex + curMode.commentStart.length, endIndex)
+      // From comment end till string end
+        + selText.substr(endIndex + curMode.commentEnd.length);
+    }
+    this.replaceRange(selText, from, to);
+  }
+});
+
+// Applies automatic mode-aware indentation to the specified range
+CodeMirror.defineExtension("autoIndentRange", function (from, to) {
+  var cmInstance = this;
+  this.operation(function () {
+    for (var i = from.line; i <= to.line; i++) {
+      cmInstance.indentLine(i);
+    }
+  });
+});
+
+// Applies automatic formatting to the specified range
+CodeMirror.defineExtension("autoFormatRange", function (from, to) {
+  var absStart = this.indexFromPos(from);
+  var absEnd = this.indexFromPos(to);
+  // Insert additional line breaks where necessary according to the
+  // mode's syntax
+  var res = this.getModeExt().autoFormatLineBreaks(this.getValue(), absStart, absEnd);
+  var cmInstance = this;
+
+  // Replace and auto-indent the range
+  this.operation(function () {
+    cmInstance.replaceRange(res, from, to);
+    var startLine = cmInstance.posFromIndex(absStart).line;
+    var endLine = cmInstance.posFromIndex(absStart + res.length).line;
+    for (var i = startLine; i <= endLine; i++) {
+      cmInstance.indentLine(i);
+    }
+  });
+});
+
+// Define extensions for a few modes
+
+CodeMirror.modeExtensions["css"] = {
+  commentStart: "/*",
+  commentEnd: "*/",
+  wordWrapChars: [";", "\\{", "\\}"],
+  autoFormatLineBreaks: function (text) {
+    return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2");
+  }
+};
+
+CodeMirror.modeExtensions["javascript"] = {
+  commentStart: "/*",
+  commentEnd: "*/",
+  wordWrapChars: [";", "\\{", "\\}"],
+
+  getNonBreakableBlocks: function (text) {
+    var nonBreakableRegexes = [
+        new RegExp("for\\s*?\\(([\\s\\S]*?)\\)"),
+        new RegExp("'([\\s\\S]*?)('|$)"),
+        new RegExp("\"([\\s\\S]*?)(\"|$)"),
+        new RegExp("//.*([\r\n]|$)")
+      ];
+    var nonBreakableBlocks = new Array();
+    for (var i = 0; i < nonBreakableRegexes.length; i++) {
+      var curPos = 0;
+      while (curPos < text.length) {
+        var m = text.substr(curPos).match(nonBreakableRegexes[i]);
+        if (m != null) {
+          nonBreakableBlocks.push({
+            start: curPos + m.index,
+            end: curPos + m.index + m[0].length
+          });
+          curPos += m.index + Math.max(1, m[0].length);
+        }
+        else { // No more matches
+          break;
+        }
+      }
+    }
+    nonBreakableBlocks.sort(function (a, b) {
+      return a.start - b.start;
+    });
+
+    return nonBreakableBlocks;
+  },
+
+  autoFormatLineBreaks: function (text) {
+    var curPos = 0;
+    var reLinesSplitter = new RegExp("(;|\\{|\\})([^\r\n])", "g");
+    var nonBreakableBlocks = this.getNonBreakableBlocks(text);
+    if (nonBreakableBlocks != null) {
+      var res = "";
+      for (var i = 0; i < nonBreakableBlocks.length; i++) {
+        if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block
+          res += text.substring(curPos, nonBreakableBlocks[i].start).replace(reLinesSplitter, "$1\n$2");
+          curPos = nonBreakableBlocks[i].start;
+        }
+        if (nonBreakableBlocks[i].start <= curPos
+          && nonBreakableBlocks[i].end >= curPos) { // Skip non-breakable block
+          res += text.substring(curPos, nonBreakableBlocks[i].end);
+          curPos = nonBreakableBlocks[i].end;
+        }
+      }
+      if (curPos < text.length - 1) {
+        res += text.substr(curPos).replace(reLinesSplitter, "$1\n$2");
+      }
+      return res;
+    }
+    else {
+      return text.replace(reLinesSplitter, "$1\n$2");
+    }
+  }
+};
+
+CodeMirror.modeExtensions["xml"] = {
+  commentStart: "<!--",
+  commentEnd: "-->",
+  wordWrapChars: [">"],
+
+  autoFormatLineBreaks: function (text) {
+    var lines = text.split("\n");
+    var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)");
+    var reOpenBrackets = new RegExp("<", "g");
+    var reCloseBrackets = new RegExp("(>)([^\r\n])", "g");
+    for (var i = 0; i < lines.length; i++) {
+      var mToProcess = lines[i].match(reProcessedPortion);
+      if (mToProcess != null && mToProcess.length > 3) { // The line starts with whitespaces and ends with whitespaces
+        lines[i] = mToProcess[1]
+            + mToProcess[2].replace(reOpenBrackets, "\n$&").replace(reCloseBrackets, "$1\n$2")
+            + mToProcess[3];
+        continue;
+      }
+    }
+
+    return lines.join("\n");
+  }
+};
+
+CodeMirror.modeExtensions["htmlmixed"] = {
+  commentStart: "<!--",
+  commentEnd: "-->",
+  wordWrapChars: [">", ";", "\\{", "\\}"],
+
+  getModeInfos: function (text, absPos) {
+    var modeInfos = new Array();
+    modeInfos[0] =
+      {
+        pos: 0,
+        modeExt: CodeMirror.modeExtensions["xml"],
+        modeName: "xml"
+      };
+
+    var modeMatchers = new Array();
+    modeMatchers[0] =
+      {
+        regex: new RegExp("<style[^>]*>([\\s\\S]*?)(</style[^>]*>|$)", "i"),
+        modeExt: CodeMirror.modeExtensions["css"],
+        modeName: "css"
+      };
+    modeMatchers[1] =
+      {
+        regex: new RegExp("<script[^>]*>([\\s\\S]*?)(</script[^>]*>|$)", "i"),
+        modeExt: CodeMirror.modeExtensions["javascript"],
+        modeName: "javascript"
+      };
+
+    var lastCharPos = (typeof (absPos) !== "undefined" ? absPos : text.length - 1);
+    // Detect modes for the entire text
+    for (var i = 0; i < modeMatchers.length; i++) {
+      var curPos = 0;
+      while (curPos <= lastCharPos) {
+        var m = text.substr(curPos).match(modeMatchers[i].regex);
+        if (m != null) {
+          if (m.length > 1 && m[1].length > 0) {
+            // Push block begin pos
+            var blockBegin = curPos + m.index + m[0].indexOf(m[1]);
+            modeInfos.push(
+              {
+                pos: blockBegin,
+                modeExt: modeMatchers[i].modeExt,
+                modeName: modeMatchers[i].modeName
+              });
+            // Push block end pos
+            modeInfos.push(
+              {
+                pos: blockBegin + m[1].length,
+                modeExt: modeInfos[0].modeExt,
+                modeName: modeInfos[0].modeName
+              });
+            curPos += m.index + m[0].length;
+            continue;
+          }
+          else {
+            curPos += m.index + Math.max(m[0].length, 1);
+          }
+        }
+        else { // No more matches
+          break;
+        }
+      }
+    }
+    // Sort mode infos
+    modeInfos.sort(function sortModeInfo(a, b) {
+      return a.pos - b.pos;
+    });
+
+    return modeInfos;
+  },
+
+  autoFormatLineBreaks: function (text, startPos, endPos) {
+    var modeInfos = this.getModeInfos(text);
+    var reBlockStartsWithNewline = new RegExp("^\\s*?\n");
+    var reBlockEndsWithNewline = new RegExp("\n\\s*?$");
+    var res = "";
+    // Use modes info to break lines correspondingly
+    if (modeInfos.length > 1) { // Deal with multi-mode text
+      for (var i = 1; i <= modeInfos.length; i++) {
+        var selStart = modeInfos[i - 1].pos;
+        var selEnd = (i < modeInfos.length ? modeInfos[i].pos : endPos);
+
+        if (selStart >= endPos) { // The block starts later than the needed fragment
+          break;
+        }
+        if (selStart < startPos) {
+          if (selEnd <= startPos) { // The block starts earlier than the needed fragment
+            continue;
+          }
+          selStart = startPos;
+        }
+        if (selEnd > endPos) {
+          selEnd = endPos;
+        }
+        var textPortion = text.substring(selStart, selEnd);
+        if (modeInfos[i - 1].modeName != "xml") { // Starting a CSS or JavaScript block
+          if (!reBlockStartsWithNewline.test(textPortion)
+              && selStart > 0) { // The block does not start with a line break
+            textPortion = "\n" + textPortion;
+          }
+          if (!reBlockEndsWithNewline.test(textPortion)
+              && selEnd < text.length - 1) { // The block does not end with a line break
+            textPortion += "\n";
+          }
+        }
+        res += modeInfos[i - 1].modeExt.autoFormatLineBreaks(textPortion);
+      }
+    }
+    else { // Single-mode text
+      res = modeInfos[0].modeExt.autoFormatLineBreaks(text.substring(startPos, endPos));
+    }
+
+    return res;
+  }
+};
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/javascript-hint.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/javascript-hint.js
new file mode 100644
index 0000000..4e88a7e
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/javascript-hint.js
@@ -0,0 +1,83 @@
+(function () {
+  function forEach(arr, f) {
+    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
+  }
+  
+  function arrayContains(arr, item) {
+    if (!Array.prototype.indexOf) {
+      var i = arr.length;
+      while (i--) {
+        if (arr[i] === item) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return arr.indexOf(item) != -1;
+  }
+  
+  CodeMirror.javascriptHint = function(editor) {
+    // Find the token at the cursor
+    var cur = editor.getCursor(), token = editor.getTokenAt(cur), tprop = token;
+    // If it's not a 'word-style' token, ignore the token.
+    if (!/^[\w$_]*$/.test(token.string)) {
+      token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
+                       className: token.string == "." ? "property" : null};
+    }
+    // If it is a property, find out what it is a property of.
+    while (tprop.className == "property") {
+      tprop = editor.getTokenAt({line: cur.line, ch: tprop.start});
+      if (tprop.string != ".") return;
+      tprop = editor.getTokenAt({line: cur.line, ch: tprop.start});
+      if (!context) var context = [];
+      context.push(tprop);
+    }
+    return {list: getCompletions(token, context),
+            from: {line: cur.line, ch: token.start},
+            to: {line: cur.line, ch: token.end}};
+  }
+
+  var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
+                     "toUpperCase toLowerCase split concat match replace search").split(" ");
+  var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
+                    "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
+  var funcProps = "prototype apply call bind".split(" ");
+  var keywords = ("break case catch continue debugger default delete do else false finally for function " +
+                  "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
+
+  function getCompletions(token, context) {
+    var found = [], start = token.string;
+    function maybeAdd(str) {
+      if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
+    }
+    function gatherCompletions(obj) {
+      if (typeof obj == "string") forEach(stringProps, maybeAdd);
+      else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
+      else if (obj instanceof Function) forEach(funcProps, maybeAdd);
+      for (var name in obj) maybeAdd(name);
+    }
+
+    if (context) {
+      // If this is a property, see if it belongs to some object we can
+      // find in the current environment.
+      var obj = context.pop(), base;
+      if (obj.className == "variable")
+        base = window[obj.string];
+      else if (obj.className == "string")
+        base = "";
+      else if (obj.className == "atom")
+        base = 1;
+      while (base != null && context.length)
+        base = base[context.pop().string];
+      if (base != null) gatherCompletions(base);
+    }
+    else {
+      // If not, just look in the window object and any local scope
+      // (reading into JS mode internals to get at the local variables)
+      for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
+      gatherCompletions(window);
+      forEach(keywords, maybeAdd);
+    }
+    return found;
+  }
+})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/overlay.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/overlay.js
new file mode 100644
index 0000000..c4cdf9f
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/overlay.js
@@ -0,0 +1,51 @@
+// Utility function that allows modes to be combined. The mode given
+// as the base argument takes care of most of the normal mode
+// functionality, but a second (typically simple) mode is used, which
+// can override the style of text. Both modes get to parse all of the
+// text, but when both assign a non-null style to a piece of code, the
+// overlay wins, unless the combine argument was true, in which case
+// the styles are combined.
+
+CodeMirror.overlayParser = function(base, overlay, combine) {
+  return {
+    startState: function() {
+      return {
+        base: CodeMirror.startState(base),
+        overlay: CodeMirror.startState(overlay),
+        basePos: 0, baseCur: null,
+        overlayPos: 0, overlayCur: null
+      };
+    },
+    copyState: function(state) {
+      return {
+        base: CodeMirror.copyState(base, state.base),
+        overlay: CodeMirror.copyState(overlay, state.overlay),
+        basePos: state.basePos, baseCur: null,
+        overlayPos: state.overlayPos, overlayCur: null
+      };
+    },
+
+    token: function(stream, state) {
+      if (stream.start == state.basePos) {
+        state.baseCur = base.token(stream, state.base);
+        state.basePos = stream.pos;
+      }
+      if (stream.start == state.overlayPos) {
+        stream.pos = stream.start;
+        state.overlayCur = overlay.token(stream, state.overlay);
+        state.overlayPos = stream.pos;
+      }
+      stream.pos = Math.min(state.basePos, state.overlayPos);
+      if (stream.eol()) state.basePos = state.overlayPos = 0;
+
+      if (state.overlayCur == null) return state.baseCur;
+      if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
+      else return state.overlayCur;
+    },
+    
+    indent: function(state, textAfter) {
+      return base.indent(state.base, textAfter);
+    },
+    electricChars: base.electricChars
+  };
+};
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/runmode.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/runmode.js
new file mode 100644
index 0000000..de4a760
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/runmode.js
@@ -0,0 +1,27 @@
+CodeMirror.runMode = function(string, modespec, callback) {
+  var mode = CodeMirror.getMode({indentUnit: 2}, modespec);
+  var isNode = callback.nodeType == 1;
+  if (isNode) {
+    var node = callback, accum = [];
+    callback = function(string, style) {
+      if (string == "\n")
+        accum.push("<br>");
+      else if (style)
+        accum.push("<span class=\"cm-" + CodeMirror.htmlEscape(style) + "\">" + CodeMirror.htmlEscape(string) + "</span>");
+      else
+        accum.push(CodeMirror.htmlEscape(string));
+    }
+  }
+  var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
+  for (var i = 0, e = lines.length; i < e; ++i) {
+    if (i) callback("\n");
+    var stream = new CodeMirror.StringStream(lines[i]);
+    while (!stream.eol()) {
+      var style = mode.token(stream, state);
+      callback(stream.current(), style, i, stream.start);
+      stream.start = stream.pos;
+    }
+  }
+  if (isNode)
+    node.innerHTML = accum.join("");
+};
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/search.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/search.js
new file mode 100644
index 0000000..63ebca9
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/search.js
@@ -0,0 +1,114 @@
+// Define search commands. Depends on dialog.js or another
+// implementation of the openDialog method.
+
+// Replace works a little oddly -- it will do the replace on the next
+// Ctrl-G (or whatever is bound to findNext) press. You prevent a
+// replace by making sure the match is no longer selected when hitting
+// Ctrl-G.
+
+(function() {
+  function SearchState() {
+    this.posFrom = this.posTo = this.query = null;
+    this.marked = [];
+  }
+  function getSearchState(cm) {
+    return cm._searchState || (cm._searchState = new SearchState());
+  }
+  function dialog(cm, text, shortText, f) {
+    if (cm.openDialog) cm.openDialog(text, f);
+    else f(prompt(shortText, ""));
+  }
+  function confirmDialog(cm, text, shortText, fs) {
+    if (cm.openConfirm) cm.openConfirm(text, fs);
+    else if (confirm(shortText)) fs[0]();
+  }
+  function parseQuery(query) {
+    var isRE = query.match(/^\/(.*)\/$/);
+    return isRE ? new RegExp(isRE[1]) : query;
+  }
+  var queryDialog =
+    'Search: <input type="text" style="width: 10em"> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
+  function doSearch(cm, rev) {
+    var state = getSearchState(cm);
+    if (state.query) return findNext(cm, rev);
+    dialog(cm, queryDialog, "Search for:", function(query) {
+      cm.operation(function() {
+        if (!query || state.query) return;
+        state.query = parseQuery(query);
+        if (cm.lineCount() < 2000) { // This is too expensive on big documents.
+          for (var cursor = cm.getSearchCursor(query); cursor.findNext();)
+            state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
+        }
+        state.posFrom = state.posTo = cm.getCursor();
+        findNext(cm, rev);
+      });
+    });
+  }
+  function findNext(cm, rev) {cm.operation(function() {
+    var state = getSearchState(cm);
+    var cursor = cm.getSearchCursor(state.query, rev ? state.posFrom : state.posTo);
+    if (!cursor.find(rev)) {
+      cursor = cm.getSearchCursor(state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});
+      if (!cursor.find(rev)) return;
+    }
+    cm.setSelection(cursor.from(), cursor.to());
+    state.posFrom = cursor.from(); state.posTo = cursor.to();
+  })}
+  function clearSearch(cm) {cm.operation(function() {
+    var state = getSearchState(cm);
+    if (!state.query) return;
+    state.query = null;
+    for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear();
+    state.marked.length = 0;
+  })}
+
+  var replaceQueryDialog =
+    'Replace: <input type="text" style="width: 10em"> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
+  var replacementQueryDialog = 'With: <input type="text" style="width: 10em">';
+  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
+  function replace(cm, all) {
+    dialog(cm, replaceQueryDialog, "Replace:", function(query) {
+      if (!query) return;
+      query = parseQuery(query);
+      dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
+        if (all) {
+          cm.operation(function() {
+            for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
+              if (typeof query != "string") {
+                var match = cm.getRange(cursor.from(), cursor.to()).match(query);
+                cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
+              } else cursor.replace(text);
+            }
+          });
+        } else {
+          clearSearch(cm);
+          var cursor = cm.getSearchCursor(query, cm.getCursor());
+          function advance() {
+            var start = cursor.from(), match;
+            if (!(match = cursor.findNext())) {
+              cursor = cm.getSearchCursor(query);
+              if (!(match = cursor.findNext()) ||
+                  (cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
+            }
+            cm.setSelection(cursor.from(), cursor.to());
+            confirmDialog(cm, doReplaceConfirm, "Replace?",
+                          [function() {doReplace(match);}, advance]);
+          }
+          function doReplace(match) {
+            cursor.replace(typeof query == "string" ? text :
+                           text.replace(/\$(\d)/, function(w, i) {return match[i];}));
+            advance();
+          }
+          advance();
+        }
+      });
+    });
+  }
+
+  CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
+  CodeMirror.commands.findNext = doSearch;
+  CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
+  CodeMirror.commands.clearSearch = clearSearch;
+  CodeMirror.commands.replace = replace;
+  CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
+})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/searchcursor.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/searchcursor.js
new file mode 100644
index 0000000..3b77829
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/searchcursor.js
@@ -0,0 +1,117 @@
+(function(){
+  function SearchCursor(cm, query, pos, caseFold) {
+    this.atOccurrence = false; this.cm = cm;
+    if (caseFold == null) caseFold = typeof query == "string" && query == query.toLowerCase();
+
+    pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};
+    this.pos = {from: pos, to: pos};
+
+    // The matches method is filled in based on the type of query.
+    // It takes a position and a direction, and returns an object
+    // describing the next occurrence of the query, or null if no
+    // more matches were found.
+    if (typeof query != "string") // Regexp match
+      this.matches = function(reverse, pos) {
+        if (reverse) {
+          var line = cm.getLine(pos.line).slice(0, pos.ch), match = line.match(query), start = 0;
+          while (match) {
+            var ind = line.indexOf(match[0]);
+            start += ind;
+            line = line.slice(ind + 1);
+            var newmatch = line.match(query);
+            if (newmatch) match = newmatch;
+            else break;
+            start++;
+          }
+        }
+        else {
+          var line = cm.getLine(pos.line).slice(pos.ch), match = line.match(query),
+          start = match && pos.ch + line.indexOf(match[0]);
+        }
+        if (match)
+          return {from: {line: pos.line, ch: start},
+                  to: {line: pos.line, ch: start + match[0].length},
+                  match: match};
+      };
+    else { // String query
+      if (caseFold) query = query.toLowerCase();
+      var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
+      var target = query.split("\n");
+      // Different methods for single-line and multi-line queries
+      if (target.length == 1)
+        this.matches = function(reverse, pos) {
+          var line = fold(cm.getLine(pos.line)), len = query.length, match;
+          if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
+              : (match = line.indexOf(query, pos.ch)) != -1)
+            return {from: {line: pos.line, ch: match},
+                    to: {line: pos.line, ch: match + len}};
+        };
+      else
+        this.matches = function(reverse, pos) {
+          var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
+          var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
+          if (reverse ? offsetA >= pos.ch || offsetA != match.length
+              : offsetA <= pos.ch || offsetA != line.length - match.length)
+            return;
+          for (;;) {
+            if (reverse ? !ln : ln == cm.lineCount() - 1) return;
+            line = fold(cm.getLine(ln += reverse ? -1 : 1));
+            match = target[reverse ? --idx : ++idx];
+            if (idx > 0 && idx < target.length - 1) {
+              if (line != match) return;
+              else continue;
+            }
+            var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
+            if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
+              return;
+            var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};
+            return {from: reverse ? end : start, to: reverse ? start : end};
+          }
+        };
+    }
+  }
+
+  SearchCursor.prototype = {
+    findNext: function() {return this.find(false);},
+    findPrevious: function() {return this.find(true);},
+
+    find: function(reverse) {
+      var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
+      function savePosAndFail(line) {
+        var pos = {line: line, ch: 0};
+        self.pos = {from: pos, to: pos};
+        self.atOccurrence = false;
+        return false;
+      }
+
+      for (;;) {
+        if (this.pos = this.matches(reverse, pos)) {
+          this.atOccurrence = true;
+          return this.pos.match || true;
+        }
+        if (reverse) {
+          if (!pos.line) return savePosAndFail(0);
+          pos = {line: pos.line-1, ch: this.cm.getLine(pos.line-1).length};
+        }
+        else {
+          var maxLine = this.cm.lineCount();
+          if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
+          pos = {line: pos.line+1, ch: 0};
+        }
+      }
+    },
+
+    from: function() {if (this.atOccurrence) return this.pos.from;},
+    to: function() {if (this.atOccurrence) return this.pos.to;},
+
+    replace: function(newText) {
+      var self = this;
+      if (this.atOccurrence)
+        self.pos.to = this.cm.replaceRange(newText, self.pos.from, self.pos.to);
+    }
+  };
+
+  CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
+    return new SearchCursor(this, query, pos, caseFold);
+  });
+})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/simple-hint.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/simple-hint.css
new file mode 100644
index 0000000..4387cb9
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/simple-hint.css
@@ -0,0 +1,16 @@
+.CodeMirror-completions {
+  position: absolute;
+  z-index: 10;
+  overflow: hidden;
+  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+}
+.CodeMirror-completions select {
+  background: #fafafa;
+  outline: none;
+  border: none;
+  padding: 0;
+  margin: 0;
+  font-family: monospace;
+}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/simple-hint.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/simple-hint.js
new file mode 100644
index 0000000..b38f389
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/lib/util/simple-hint.js
@@ -0,0 +1,66 @@
+(function() {
+  CodeMirror.simpleHint = function(editor, getHints) {
+    // We want a single cursor position.
+    if (editor.somethingSelected()) return;
+    var result = getHints(editor);
+    if (!result || !result.list.length) return;
+    var completions = result.list;
+    function insert(str) {
+      editor.replaceRange(str, result.from, result.to);
+    }
+    // When there is only one completion, use it directly.
+    if (completions.length == 1) {insert(completions[0]); return true;}
+
+    // Build the select widget
+    var complete = document.createElement("div");
+    complete.className = "CodeMirror-completions";
+    var sel = complete.appendChild(document.createElement("select"));
+    // Opera doesn't move the selection when pressing up/down in a
+    // multi-select, but it does properly support the size property on
+    // single-selects, so no multi-select is necessary.
+    if (!window.opera) sel.multiple = true;
+    for (var i = 0; i < completions.length; ++i) {
+      var opt = sel.appendChild(document.createElement("option"));
+      opt.appendChild(document.createTextNode(completions[i]));
+    }
+    sel.firstChild.selected = true;
+    sel.size = Math.min(10, completions.length);
+    var pos = editor.cursorCoords();
+    complete.style.left = pos.x + "px";
+    complete.style.top = pos.yBot + "px";
+    document.body.appendChild(complete);
+    // Hack to hide the scrollbar.
+    if (completions.length <= 10)
+      complete.style.width = (sel.clientWidth - 1) + "px";
+
+    var done = false;
+    function close() {
+      if (done) return;
+      done = true;
+      complete.parentNode.removeChild(complete);
+    }
+    function pick() {
+      insert(completions[sel.selectedIndex]);
+      close();
+      setTimeout(function(){editor.focus();}, 50);
+    }
+    CodeMirror.connect(sel, "blur", close);
+    CodeMirror.connect(sel, "keydown", function(event) {
+      var code = event.keyCode;
+      // Enter
+      if (code == 13) {CodeMirror.e_stop(event); pick();}
+      // Escape
+      else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
+      else if (code != 38 && code != 40) {
+        close(); editor.focus();
+        setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
+      }
+    });
+    CodeMirror.connect(sel, "dblclick", pick);
+
+    sel.focus();
+    // Opera sometimes ignores focusing a freshly created node
+    if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
+    return true;
+  };
+})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/css/css.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/css/css.js
new file mode 100644
index 0000000..45170a3
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/css/css.js
@@ -0,0 +1,124 @@
+CodeMirror.defineMode("css", function(config) {
+  var indentUnit = config.indentUnit, type;
+  function ret(style, tp) {type = tp; return style;}
+
+  function tokenBase(stream, state) {
+    var ch = stream.next();
+    if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
+    else if (ch == "/" && stream.eat("*")) {
+      state.tokenize = tokenCComment;
+      return tokenCComment(stream, state);
+    }
+    else if (ch == "<" && stream.eat("!")) {
+      state.tokenize = tokenSGMLComment;
+      return tokenSGMLComment(stream, state);
+    }
+    else if (ch == "=") ret(null, "compare");
+    else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
+    else if (ch == "\"" || ch == "'") {
+      state.tokenize = tokenString(ch);
+      return state.tokenize(stream, state);
+    }
+    else if (ch == "#") {
+      stream.eatWhile(/[\w\\\-]/);
+      return ret("atom", "hash");
+    }
+    else if (ch == "!") {
+      stream.match(/^\s*\w*/);
+      return ret("keyword", "important");
+    }
+    else if (/\d/.test(ch)) {
+      stream.eatWhile(/[\w.%]/);
+      return ret("number", "unit");
+    }
+    else if (/[,.+>*\/]/.test(ch)) {
+      return ret(null, "select-op");
+    }
+    else if (/[;{}:\[\]]/.test(ch)) {
+      return ret(null, ch);
+    }
+    else {
+      stream.eatWhile(/[\w\\\-]/);
+      return ret("variable", "variable");
+    }
+  }
+
+  function tokenCComment(stream, state) {
+    var maybeEnd = false, ch;
+    while ((ch = stream.next()) != null) {
+      if (maybeEnd && ch == "/") {
+        state.tokenize = tokenBase;
+        break;
+      }
+      maybeEnd = (ch == "*");
+    }
+    return ret("comment", "comment");
+  }
+
+  function tokenSGMLComment(stream, state) {
+    var dashes = 0, ch;
+    while ((ch = stream.next()) != null) {
+      if (dashes >= 2 && ch == ">") {
+        state.tokenize = tokenBase;
+        break;
+      }
+      dashes = (ch == "-") ? dashes + 1 : 0;
+    }
+    return ret("comment", "comment");
+  }
+
+  function tokenString(quote) {
+    return function(stream, state) {
+      var escaped = false, ch;
+      while ((ch = stream.next()) != null) {
+        if (ch == quote && !escaped)
+          break;
+        escaped = !escaped && ch == "\\";
+      }
+      if (!escaped) state.tokenize = tokenBase;
+      return ret("string", "string");
+    };
+  }
+
+  return {
+    startState: function(base) {
+      return {tokenize: tokenBase,
+              baseIndent: base || 0,
+              stack: []};
+    },
+
+    token: function(stream, state) {
+      if (stream.eatSpace()) return null;
+      var style = state.tokenize(stream, state);
+
+      var context = state.stack[state.stack.length-1];
+      if (type == "hash" && context == "rule") style = "atom";
+      else if (style == "variable") {
+        if (context == "rule") style = "number";
+        else if (!context || context == "@media{") style = "tag";
+      }
+
+      if (context == "rule" && /^[\{\};]$/.test(type))
+        state.stack.pop();
+      if (type == "{") {
+        if (context == "@media") state.stack[state.stack.length-1] = "@media{";
+        else state.stack.push("{");
+      }
+      else if (type == "}") state.stack.pop();
+      else if (type == "@media") state.stack.push("@media");
+      else if (context == "{" && type != "comment") state.stack.push("rule");
+      return style;
+    },
+
+    indent: function(state, textAfter) {
+      var n = state.stack.length;
+      if (/^\}/.test(textAfter))
+        n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
+      return state.baseIndent + n * indentUnit;
+    },
+
+    electricChars: "}"
+  };
+});
+
+CodeMirror.defineMIME("text/css", "css");
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/css/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/css/index.html
new file mode 100644
index 0000000..4993434
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/css/index.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: CSS mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="css.js"></script>
+    <style>.CodeMirror {background: #f8f8f8;}</style>
+    <link rel="stylesheet" href="../../doc/docs.css">
+  </head>
+  <body>
+    <h1>CodeMirror: CSS mode</h1>
+    <form><textarea id="code" name="code">
+/* Some example CSS */
+
+ at import url("something.css");
+
+body {
+  margin: 0;
+  padding: 3em 6em;
+  font-family: tahoma, arial, sans-serif;
+  color: #000;
+}
+
+#navigation a {
+  font-weight: bold;
+  text-decoration: none !important;
+}
+
+h1 {
+  font-size: 2.5em;
+}
+
+h2 {
+  font-size: 1.7em;
+}
+
+h1:before, h2:before {
+  content: "::";
+}
+
+code {
+  font-family: courier, monospace;
+  font-size: 80%;
+  color: #418A8A;
+}
+</textarea></form>
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
+    </script>
+
+    <p><strong>MIME types defined:</strong> <code>text/css</code>.</p>
+
+  </body>
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/htmlmixed/htmlmixed.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/htmlmixed/htmlmixed.js
new file mode 100644
index 0000000..a94dc45
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/htmlmixed/htmlmixed.js
@@ -0,0 +1,83 @@
+CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
+  var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
+  var jsMode = CodeMirror.getMode(config, "javascript");
+  var cssMode = CodeMirror.getMode(config, "css");
+
+  function html(stream, state) {
+    var style = htmlMode.token(stream, state.htmlState);
+    if (style == "tag" && stream.current() == ">" && state.htmlState.context) {
+      if (/^script$/i.test(state.htmlState.context.tagName)) {
+        state.token = javascript;
+        state.localState = jsMode.startState(htmlMode.indent(state.htmlState, ""));
+        state.mode = "javascript";
+      }
+      else if (/^style$/i.test(state.htmlState.context.tagName)) {
+        state.token = css;
+        state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
+        state.mode = "css";
+      }
+    }
+    return style;
+  }
+  function maybeBackup(stream, pat, style) {
+    var cur = stream.current();
+    var close = cur.search(pat);
+    if (close > -1) stream.backUp(cur.length - close);
+    return style;
+  }
+  function javascript(stream, state) {
+    if (stream.match(/^<\/\s*script\s*>/i, false)) {
+      state.token = html;
+      state.curState = null;
+      state.mode = "html";
+      return html(stream, state);
+    }
+    return maybeBackup(stream, /<\/\s*script\s*>/,
+                       jsMode.token(stream, state.localState));
+  }
+  function css(stream, state) {
+    if (stream.match(/^<\/\s*style\s*>/i, false)) {
+      state.token = html;
+      state.localState = null;
+      state.mode = "html";
+      return html(stream, state);
+    }
+    return maybeBackup(stream, /<\/\s*style\s*>/,
+                       cssMode.token(stream, state.localState));
+  }
+
+  return {
+    startState: function() {
+      var state = htmlMode.startState();
+      return {token: html, localState: null, mode: "html", htmlState: state};
+    },
+
+    copyState: function(state) {
+      if (state.localState)
+        var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);
+      return {token: state.token, localState: local, mode: state.mode,
+              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
+    },
+
+    token: function(stream, state) {
+      return state.token(stream, state);
+    },
+
+    indent: function(state, textAfter) {
+      if (state.token == html || /^\s*<\//.test(textAfter))
+        return htmlMode.indent(state.htmlState, textAfter);
+      else if (state.token == javascript)
+        return jsMode.indent(state.localState, textAfter);
+      else
+        return cssMode.indent(state.localState, textAfter);
+    },
+
+    compareStates: function(a, b) {
+      return htmlMode.compareStates(a.htmlState, b.htmlState);
+    },
+
+    electricChars: "/{}:"
+  }
+});
+
+CodeMirror.defineMIME("text/html", "htmlmixed");
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/htmlmixed/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/htmlmixed/index.html
new file mode 100644
index 0000000..63fc412
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/htmlmixed/index.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: HTML mixed mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="../xml/xml.js"></script>
+    <script src="../javascript/javascript.js"></script>
+    <script src="../css/css.js"></script>
+    <script src="htmlmixed.js"></script>
+    <link rel="stylesheet" href="../../doc/docs.css">
+    <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+  </head>
+  <body>
+    <h1>CodeMirror: HTML mixed mode</h1>
+    <form><textarea id="code" name="code">
+<html style="color: green">
+  <!-- this is a comment -->
+  <head>
+    <title>Mixed HTML Example</title>
+    <style type="text/css">
+      h1 {font-family: comic sans; color: #f0f;}
+      div {background: yellow !important;}
+      body {
+        max-width: 50em;
+        margin: 1em 2em 1em 5em;
+      }
+    </style>
+  </head>
+  <body>
+    <h1>Mixed HTML Example</h1>
+    <script>
+      function jsFunc(arg1, arg2) {
+        if (arg1 && arg2) document.body.innerHTML = "achoo";
+      }
+    </script>
+  </body>
+</html>
+</textarea></form>
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "text/html", tabMode: "indent"});
+    </script>
+
+    <p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>
+
+    <p><strong>MIME types defined:</strong> <code>text/html</code>
+    (redefined, only takes effect if you load this parser after the
+    XML parser).</p>
+
+  </body>
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/javascript/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/javascript/index.html
new file mode 100644
index 0000000..c3ab91d
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/javascript/index.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: JavaScript mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="javascript.js"></script>
+    <link rel="stylesheet" href="../../doc/docs.css">
+    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+  </head>
+  <body>
+    <h1>CodeMirror: JavaScript mode</h1>
+
+<div><textarea id="code" name="code">
+// Demo code (the actual new parser character stream implementation)
+
+function StringStream(string) {
+  this.pos = 0;
+  this.string = string;
+}
+
+StringStream.prototype = {
+  done: function() {return this.pos >= this.string.length;},
+  peek: function() {return this.string.charAt(this.pos);},
+  next: function() {
+    if (this.pos < this.string.length)
+      return this.string.charAt(this.pos++);
+  },
+  eat: function(match) {
+    var ch = this.string.charAt(this.pos);
+    if (typeof match == "string") var ok = ch == match;
+    else var ok = ch && match.test ? match.test(ch) : match(ch);
+    if (ok) {this.pos++; return ch;}
+  },
+  eatWhile: function(match) {
+    var start = this.pos;
+    while (this.eat(match));
+    if (this.pos > start) return this.string.slice(start, this.pos);
+  },
+  backUp: function(n) {this.pos -= n;},
+  column: function() {return this.pos;},
+  eatSpace: function() {
+    var start = this.pos;
+    while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
+    return this.pos - start;
+  },
+  match: function(pattern, consume, caseInsensitive) {
+    if (typeof pattern == "string") {
+      function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
+      if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+        if (consume !== false) this.pos += str.length;
+        return true;
+      }
+    }
+    else {
+      var match = this.string.slice(this.pos).match(pattern);
+      if (match && consume !== false) this.pos += match[0].length;
+      return match;
+    }
+  }
+};
+</textarea></div>
+
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        lineNumbers: true,
+        matchBrackets: true
+      });
+    </script>
+
+    <p>JavaScript mode supports a single configuration
+    option, <code>json</code>, which will set the mode to expect JSON
+    data rather than a JavaScript program.</p>
+
+    <p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>.</p>
+  </body>
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/javascript/javascript.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/javascript/javascript.js
new file mode 100644
index 0000000..be2a069
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/javascript/javascript.js
@@ -0,0 +1,360 @@
+CodeMirror.defineMode("javascript", function(config, parserConfig) {
+  var indentUnit = config.indentUnit;
+  var jsonMode = parserConfig.json;
+
+  // Tokenizer
+
+  var keywords = function(){
+    function kw(type) {return {type: type, style: "keyword"};}
+    var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
+    var operator = kw("operator"), atom = {type: "atom", style: "atom"};
+    return {
+      "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
+      "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
+      "var": kw("var"), "const": kw("var"), "let": kw("var"),
+      "function": kw("function"), "catch": kw("catch"),
+      "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
+      "in": operator, "typeof": operator, "instanceof": operator,
+      "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
+    };
+  }();
+
+  var isOperatorChar = /[+\-*&%=<>!?|]/;
+
+  function chain(stream, state, f) {
+    state.tokenize = f;
+    return f(stream, state);
+  }
+
+  function nextUntilUnescaped(stream, end) {
+    var escaped = false, next;
+    while ((next = stream.next()) != null) {
+      if (next == end && !escaped)
+        return false;
+      escaped = !escaped && next == "\\";
+    }
+    return escaped;
+  }
+
+  // Used as scratch variables to communicate multiple values without
+  // consing up tons of objects.
+  var type, content;
+  function ret(tp, style, cont) {
+    type = tp; content = cont;
+    return style;
+  }
+
+  function jsTokenBase(stream, state) {
+    var ch = stream.next();
+    if (ch == '"' || ch == "'")
+      return chain(stream, state, jsTokenString(ch));
+    else if (/[\[\]{}\(\),;\:\.]/.test(ch))
+      return ret(ch);
+    else if (ch == "0" && stream.eat(/x/i)) {
+      stream.eatWhile(/[\da-f]/i);
+      return ret("number", "number");
+    }      
+    else if (/\d/.test(ch)) {
+      stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
+      return ret("number", "number");
+    }
+    else if (ch == "/") {
+      if (stream.eat("*")) {
+        return chain(stream, state, jsTokenComment);
+      }
+      else if (stream.eat("/")) {
+        stream.skipToEnd();
+        return ret("comment", "comment");
+      }
+      else if (state.reAllowed) {
+        nextUntilUnescaped(stream, "/");
+        stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
+        return ret("regexp", "string");
+      }
+      else {
+        stream.eatWhile(isOperatorChar);
+        return ret("operator", null, stream.current());
+      }
+    }
+    else if (ch == "#") {
+        stream.skipToEnd();
+        return ret("error", "error");
+    }
+    else if (isOperatorChar.test(ch)) {
+      stream.eatWhile(isOperatorChar);
+      return ret("operator", null, stream.current());
+    }
+    else {
+      stream.eatWhile(/[\w\$_]/);
+      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
+      return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
+                     ret("variable", "variable", word);
+    }
+  }
+
+  function jsTokenString(quote) {
+    return function(stream, state) {
+      if (!nextUntilUnescaped(stream, quote))
+        state.tokenize = jsTokenBase;
+      return ret("string", "string");
+    };
+  }
+
+  function jsTokenComment(stream, state) {
+    var maybeEnd = false, ch;
+    while (ch = stream.next()) {
+      if (ch == "/" && maybeEnd) {
+        state.tokenize = jsTokenBase;
+        break;
+      }
+      maybeEnd = (ch == "*");
+    }
+    return ret("comment", "comment");
+  }
+
+  // Parser
+
+  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
+
+  function JSLexical(indented, column, type, align, prev, info) {
+    this.indented = indented;
+    this.column = column;
+    this.type = type;
+    this.prev = prev;
+    this.info = info;
+    if (align != null) this.align = align;
+  }
+
+  function inScope(state, varname) {
+    for (var v = state.localVars; v; v = v.next)
+      if (v.name == varname) return true;
+  }
+
+  function parseJS(state, style, type, content, stream) {
+    var cc = state.cc;
+    // Communicate our context to the combinators.
+    // (Less wasteful than consing up a hundred closures on every call.)
+    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
+  
+    if (!state.lexical.hasOwnProperty("align"))
+      state.lexical.align = true;
+
+    while(true) {
+      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
+      if (combinator(type, content)) {
+        while(cc.length && cc[cc.length - 1].lex)
+          cc.pop()();
+        if (cx.marked) return cx.marked;
+        if (type == "variable" && inScope(state, content)) return "variable-2";
+        return style;
+      }
+    }
+  }
+
+  // Combinator utils
+
+  var cx = {state: null, column: null, marked: null, cc: null};
+  function pass() {
+    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
+  }
+  function cont() {
+    pass.apply(null, arguments);
+    return true;
+  }
+  function register(varname) {
+    var state = cx.state;
+    if (state.context) {
+      cx.marked = "def";
+      for (var v = state.localVars; v; v = v.next)
+        if (v.name == varname) return;
+      state.localVars = {name: varname, next: state.localVars};
+    }
+  }
+
+  // Combinators
+
+  var defaultVars = {name: "this", next: {name: "arguments"}};
+  function pushcontext() {
+    if (!cx.state.context) cx.state.localVars = defaultVars;
+    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
+  }
+  function popcontext() {
+    cx.state.localVars = cx.state.context.vars;
+    cx.state.context = cx.state.context.prev;
+  }
+  function pushlex(type, info) {
+    var result = function() {
+      var state = cx.state;
+      state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)
+    };
+    result.lex = true;
+    return result;
+  }
+  function poplex() {
+    var state = cx.state;
+    if (state.lexical.prev) {
+      if (state.lexical.type == ")")
+        state.indented = state.lexical.indented;
+      state.lexical = state.lexical.prev;
+    }
+  }
+  poplex.lex = true;
+
+  function expect(wanted) {
+    return function expecting(type) {
+      if (type == wanted) return cont();
+      else if (wanted == ";") return pass();
+      else return cont(arguments.callee);
+    };
+  }
+
+  function statement(type) {
+    if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
+    if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
+    if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
+    if (type == "{") return cont(pushlex("}"), block, poplex);
+    if (type == ";") return cont();
+    if (type == "function") return cont(functiondef);
+    if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
+                                      poplex, statement, poplex);
+    if (type == "variable") return cont(pushlex("stat"), maybelabel);
+    if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
+                                         block, poplex, poplex);
+    if (type == "case") return cont(expression, expect(":"));
+    if (type == "default") return cont(expect(":"));
+    if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
+                                        statement, poplex, popcontext);
+    return pass(pushlex("stat"), expression, expect(";"), poplex);
+  }
+  function expression(type) {
+    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
+    if (type == "function") return cont(functiondef);
+    if (type == "keyword c") return cont(maybeexpression);
+    if (type == "(") return cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator);
+    if (type == "operator") return cont(expression);
+    if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
+    if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
+    return cont();
+  }
+  function maybeexpression(type) {
+    if (type.match(/[;\}\)\],]/)) return pass();
+    return pass(expression);
+  }
+    
+  function maybeoperator(type, value) {
+    if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
+    if (type == "operator") return cont(expression);
+    if (type == ";") return;
+    if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
+    if (type == ".") return cont(property, maybeoperator);
+    if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
+  }
+  function maybelabel(type) {
+    if (type == ":") return cont(poplex, statement);
+    return pass(maybeoperator, expect(";"), poplex);
+  }
+  function property(type) {
+    if (type == "variable") {cx.marked = "property"; return cont();}
+  }
+  function objprop(type) {
+    if (type == "variable") cx.marked = "property";
+    if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
+  }
+  function commasep(what, end) {
+    function proceed(type) {
+      if (type == ",") return cont(what, proceed);
+      if (type == end) return cont();
+      return cont(expect(end));
+    }
+    return function commaSeparated(type) {
+      if (type == end) return cont();
+      else return pass(what, proceed);
+    };
+  }
+  function block(type) {
+    if (type == "}") return cont();
+    return pass(statement, block);
+  }
+  function vardef1(type, value) {
+    if (type == "variable"){register(value); return cont(vardef2);}
+    return cont();
+  }
+  function vardef2(type, value) {
+    if (value == "=") return cont(expression, vardef2);
+    if (type == ",") return cont(vardef1);
+  }
+  function forspec1(type) {
+    if (type == "var") return cont(vardef1, forspec2);
+    if (type == ";") return pass(forspec2);
+    if (type == "variable") return cont(formaybein);
+    return pass(forspec2);
+  }
+  function formaybein(type, value) {
+    if (value == "in") return cont(expression);
+    return cont(maybeoperator, forspec2);
+  }
+  function forspec2(type, value) {
+    if (type == ";") return cont(forspec3);
+    if (value == "in") return cont(expression);
+    return cont(expression, expect(";"), forspec3);
+  }
+  function forspec3(type) {
+    if (type != ")") cont(expression);
+  }
+  function functiondef(type, value) {
+    if (type == "variable") {register(value); return cont(functiondef);}
+    if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
+  }
+  function funarg(type, value) {
+    if (type == "variable") {register(value); return cont();}
+  }
+
+  // Interface
+
+  return {
+    startState: function(basecolumn) {
+      return {
+        tokenize: jsTokenBase,
+        reAllowed: true,
+        kwAllowed: true,
+        cc: [],
+        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
+        localVars: null,
+        context: null,
+        indented: 0
+      };
+    },
+
+    token: function(stream, state) {
+      if (stream.sol()) {
+        if (!state.lexical.hasOwnProperty("align"))
+          state.lexical.align = false;
+        state.indented = stream.indentation();
+      }
+      if (stream.eatSpace()) return null;
+      var style = state.tokenize(stream, state);
+      if (type == "comment") return style;
+      state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
+      state.kwAllowed = type != '.';
+      return parseJS(state, style, type, content, stream);
+    },
+
+    indent: function(state, textAfter) {
+      if (state.tokenize != jsTokenBase) return 0;
+      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
+          type = lexical.type, closing = firstChar == type;
+      if (type == "vardef") return lexical.indented + 4;
+      else if (type == "form" && firstChar == "{") return lexical.indented;
+      else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
+      else if (lexical.info == "switch" && !closing)
+        return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
+      else if (lexical.align) return lexical.column + (closing ? 0 : 1);
+      else return lexical.indented + (closing ? 0 : indentUnit);
+    },
+
+    electricChars: ":{}"
+  };
+});
+
+CodeMirror.defineMIME("text/javascript", "javascript");
+CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/markdown/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/markdown/index.html
new file mode 100644
index 0000000..3a60c03
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/markdown/index.html
@@ -0,0 +1,339 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: Markdown mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="../xml/xml.js"></script>
+    <script src="markdown.js"></script>
+    <link rel="stylesheet" href="markdown.css">
+    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+    <link rel="stylesheet" href="../../doc/docs.css">
+  </head>
+  <body>
+    <h1>CodeMirror: Markdown mode</h1>
+
+<!-- source: http://daringfireball.net/projects/markdown/basics.text -->
+<form><textarea id="code" name="code">
+Markdown: Basics
+================
+
+<ul id="ProjectSubmenu">
+    <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
+    <li><a class="selected" title="Markdown Basics">Basics</a></li>
+    <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
+    <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
+    <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
+</ul>
+
+
+Getting the Gist of Markdown's Formatting Syntax
+------------------------------------------------
+
+This page offers a brief overview of what it's like to use Markdown.
+The [syntax page] [s] provides complete, detailed documentation for
+every feature, but Markdown should be very easy to pick up simply by
+looking at a few examples of it in action. The examples on this page
+are written in a before/after style, showing example syntax and the
+HTML output produced by Markdown.
+
+It's also helpful to simply try Markdown out; the [Dingus] [d] is a
+web application that allows you type your own Markdown-formatted text
+and translate it to XHTML.
+
+**Note:** This document is itself written using Markdown; you
+can [see the source for it by adding '.text' to the URL] [src].
+
+  [s]: /projects/markdown/syntax  "Markdown Syntax"
+  [d]: /projects/markdown/dingus  "Markdown Dingus"
+  [src]: /projects/markdown/basics.text
+
+
+## Paragraphs, Headers, Blockquotes ##
+
+A paragraph is simply one or more consecutive lines of text, separated
+by one or more blank lines. (A blank line is any line that looks like
+a blank line -- a line containing nothing but spaces or tabs is
+considered blank.) Normal paragraphs should not be indented with
+spaces or tabs.
+
+Markdown offers two styles of headers: *Setext* and *atx*.
+Setext-style headers for `<h1>` and `<h2>` are created by
+"underlining" with equal signs (`=`) and hyphens (`-`), respectively.
+To create an atx-style header, you put 1-6 hash marks (`#`) at the
+beginning of the line -- the number of hashes equals the resulting
+HTML header level.
+
+Blockquotes are indicated using email-style '`>`' angle brackets.
+
+Markdown:
+
+    A First Level Header
+    ====================
+    
+    A Second Level Header
+    ---------------------
+
+    Now is the time for all good men to come to
+    the aid of their country. This is just a
+    regular paragraph.
+
+    The quick brown fox jumped over the lazy
+    dog's back.
+    
+    ### Header 3
+
+    > This is a blockquote.
+    > 
+    > This is the second paragraph in the blockquote.
+    >
+    > ## This is an H2 in a blockquote
+
+
+Output:
+
+    <h1>A First Level Header</h1>
+    
+    <h2>A Second Level Header</h2>
+    
+    <p>Now is the time for all good men to come to
+    the aid of their country. This is just a
+    regular paragraph.</p>
+    
+    <p>The quick brown fox jumped over the lazy
+    dog's back.</p>
+    
+    <h3>Header 3</h3>
+    
+    <blockquote>
+        <p>This is a blockquote.</p>
+        
+        <p>This is the second paragraph in the blockquote.</p>
+        
+        <h2>This is an H2 in a blockquote</h2>
+    </blockquote>
+
+
+
+### Phrase Emphasis ###
+
+Markdown uses asterisks and underscores to indicate spans of emphasis.
+
+Markdown:
+
+    Some of these words *are emphasized*.
+    Some of these words _are emphasized also_.
+    
+    Use two asterisks for **strong emphasis**.
+    Or, if you prefer, __use two underscores instead__.
+
+Output:
+
+    <p>Some of these words <em>are emphasized</em>.
+    Some of these words <em>are emphasized also</em>.</p>
+    
+    <p>Use two asterisks for <strong>strong emphasis</strong>.
+    Or, if you prefer, <strong>use two underscores instead</strong>.</p>
+   
+
+
+## Lists ##
+
+Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
+`+`, and `-`) as list markers. These three markers are
+interchangable; this:
+
+    *   Candy.
+    *   Gum.
+    *   Booze.
+
+this:
+
+    +   Candy.
+    +   Gum.
+    +   Booze.
+
+and this:
+
+    -   Candy.
+    -   Gum.
+    -   Booze.
+
+all produce the same output:
+
+    <ul>
+    <li>Candy.</li>
+    <li>Gum.</li>
+    <li>Booze.</li>
+    </ul>
+
+Ordered (numbered) lists use regular numbers, followed by periods, as
+list markers:
+
+    1.  Red
+    2.  Green
+    3.  Blue
+
+Output:
+
+    <ol>
+    <li>Red</li>
+    <li>Green</li>
+    <li>Blue</li>
+    </ol>
+
+If you put blank lines between items, you'll get `<p>` tags for the
+list item text. You can create multi-paragraph list items by indenting
+the paragraphs by 4 spaces or 1 tab:
+
+    *   A list item.
+    
+        With multiple paragraphs.
+
+    *   Another item in the list.
+
+Output:
+
+    <ul>
+    <li><p>A list item.</p>
+    <p>With multiple paragraphs.</p></li>
+    <li><p>Another item in the list.</p></li>
+    </ul>
+    
+
+
+### Links ###
+
+Markdown supports two styles for creating links: *inline* and
+*reference*. With both styles, you use square brackets to delimit the
+text you want to turn into a link.
+
+Inline-style links use parentheses immediately after the link text.
+For example:
+
+    This is an [example link](http://example.com/).
+
+Output:
+
+    <p>This is an <a href="http://example.com/">
+    example link</a>.</p>
+
+Optionally, you may include a title attribute in the parentheses:
+
+    This is an [example link](http://example.com/ "With a Title").
+
+Output:
+
+    <p>This is an <a href="http://example.com/" title="With a Title">
+    example link</a>.</p>
+
+Reference-style links allow you to refer to your links by names, which
+you define elsewhere in your document:
+
+    I get 10 times more traffic from [Google][1] than from
+    [Yahoo][2] or [MSN][3].
+
+    [1]: http://google.com/        "Google"
+    [2]: http://search.yahoo.com/  "Yahoo Search"
+    [3]: http://search.msn.com/    "MSN Search"
+
+Output:
+
+    <p>I get 10 times more traffic from <a href="http://google.com/"
+    title="Google">Google</a> than from <a href="http://search.yahoo.com/"
+    title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
+    title="MSN Search">MSN</a>.</p>
+
+The title attribute is optional. Link names may contain letters,
+numbers and spaces, but are *not* case sensitive:
+
+    I start my morning with a cup of coffee and
+    [The New York Times][NY Times].
+
+    [ny times]: http://www.nytimes.com/
+
+Output:
+
+    <p>I start my morning with a cup of coffee and
+    <a href="http://www.nytimes.com/">The New York Times</a>.</p>
+
+
+### Images ###
+
+Image syntax is very much like link syntax.
+
+Inline (titles are optional):
+
+    ![alt text](/path/to/img.jpg "Title")
+
+Reference-style:
+
+    ![alt text][id]
+
+    [id]: /path/to/img.jpg "Title"
+
+Both of the above examples produce the same output:
+
+    <img src="/path/to/img.jpg" alt="alt text" title="Title" />
+
+
+
+### Code ###
+
+In a regular paragraph, you can create code span by wrapping text in
+backtick quotes. Any ampersands (`&`) and angle brackets (`<` or
+`>`) will automatically be translated into HTML entities. This makes
+it easy to use Markdown to write about HTML example code:
+
+    I strongly recommend against using any `<blink>` tags.
+
+    I wish SmartyPants used named entities like `&mdash;`
+    instead of decimal-encoded entites like `&#8212;`.
+
+Output:
+
+    <p>I strongly recommend against using any
+    <code>&lt;blink&gt;</code> tags.</p>
+    
+    <p>I wish SmartyPants used named entities like
+    <code>&amp;mdash;</code> instead of decimal-encoded
+    entites like <code>&amp;#8212;</code>.</p>
+
+
+To specify an entire block of pre-formatted code, indent every line of
+the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,
+and `>` characters will be escaped automatically.
+
+Markdown:
+
+    If you want your page to validate under XHTML 1.0 Strict,
+    you've got to put paragraph tags in your blockquotes:
+
+        <blockquote>
+            <p>For example.</p>
+        </blockquote>
+
+Output:
+
+    <p>If you want your page to validate under XHTML 1.0 Strict,
+    you've got to put paragraph tags in your blockquotes:</p>
+    
+    <pre><code>&lt;blockquote&gt;
+        &lt;p&gt;For example.&lt;/p&gt;
+    &lt;/blockquote&gt;
+    </code></pre>
+</textarea></form>
+
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        mode: 'markdown',
+        lineNumbers: true,
+        matchBrackets: true,
+        theme: "default"
+      });
+    </script>
+
+    <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
+
+  </body>
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/markdown/markdown.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/markdown/markdown.js
new file mode 100644
index 0000000..455bb43
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/markdown/markdown.js
@@ -0,0 +1,242 @@
+CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
+
+  var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });
+
+  var header   = 'header'
+  ,   code     = 'comment'
+  ,   quote    = 'quote'
+  ,   list     = 'string'
+  ,   hr       = 'hr'
+  ,   linktext = 'link'
+  ,   linkhref = 'string'
+  ,   em       = 'em'
+  ,   strong   = 'strong'
+  ,   emstrong = 'emstrong';
+
+  var hrRE = /^[*-=_]/
+  ,   ulRE = /^[*-+]\s+/
+  ,   olRE = /^[0-9]\.\s+/
+  ,   headerRE = /^(?:\={3,}|-{3,})$/
+  ,   codeRE = /^(k:\t|\s{4,})/
+  ,   textRE = /^[^\[*_\\<>`]+/;
+
+  function switchInline(stream, state, f) {
+    state.f = state.inline = f;
+    return f(stream, state);
+  }
+
+  function switchBlock(stream, state, f) {
+    state.f = state.block = f;
+    return f(stream, state);
+  }
+
+
+  // Blocks
+
+  function blockNormal(stream, state) {
+    if (stream.match(codeRE)) {
+      stream.skipToEnd();
+      return code;
+    }
+    
+    if (stream.eatSpace()) {
+      return null;
+    }
+    
+    if (stream.peek() === '#' || stream.match(headerRE)) {
+      stream.skipToEnd();
+      return header;
+    }
+    if (stream.eat('>')) {
+      state.indentation++;
+      return quote;
+    }
+    if (stream.peek() === '[') {
+      return switchInline(stream, state, footnoteLink);
+    }
+    if (hrRE.test(stream.peek())) {
+      var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$');
+      if (stream.match(re, true)) {
+        return hr;
+      }
+    }
+    
+    var match;
+    if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
+      state.indentation += match[0].length;
+      return list;
+    }
+    
+    return switchInline(stream, state, state.inline);
+  }
+
+  function htmlBlock(stream, state) {
+    var style = htmlMode.token(stream, state.htmlState);
+    if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
+      state.f = inlineNormal;
+      state.block = blockNormal;
+    }
+    return style;
+  }
+
+
+  // Inline
+  function getType(state) {
+    return state.strong ? (state.em ? emstrong : strong)
+                        : (state.em ? em       : null);
+  }
+
+  function handleText(stream, state) {
+    if (stream.match(textRE, true)) {
+      return getType(state);
+    }
+    return undefined;        
+  }
+
+  function inlineNormal(stream, state) {
+    var style = state.text(stream, state)
+    if (typeof style !== 'undefined')
+      return style;
+    
+    var ch = stream.next();
+    
+    if (ch === '\\') {
+      stream.next();
+      return getType(state);
+    }
+    if (ch === '`') {
+      return switchInline(stream, state, inlineElement(code, '`'));
+    }
+    if (ch === '[') {
+      return switchInline(stream, state, linkText);
+    }
+    if (ch === '<' && stream.match(/^\w/, false)) {
+      stream.backUp(1);
+      return switchBlock(stream, state, htmlBlock);
+    }
+
+    var t = getType(state);
+    if (ch === '*' || ch === '_') {
+      if (stream.eat(ch)) {
+        return (state.strong = !state.strong) ? getType(state) : t;
+      }
+      return (state.em = !state.em) ? getType(state) : t;
+    }
+    
+    return getType(state);
+  }
+
+  function linkText(stream, state) {
+    while (!stream.eol()) {
+      var ch = stream.next();
+      if (ch === '\\') stream.next();
+      if (ch === ']') {
+        state.inline = state.f = linkHref;
+        return linktext;
+      }
+    }
+    return linktext;
+  }
+
+  function linkHref(stream, state) {
+    stream.eatSpace();
+    var ch = stream.next();
+    if (ch === '(' || ch === '[') {
+      return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));
+    }
+    return 'error';
+  }
+
+  function footnoteLink(stream, state) {
+    if (stream.match(/^[^\]]*\]:/, true)) {
+      state.f = footnoteUrl;
+      return linktext;
+    }
+    return switchInline(stream, state, inlineNormal);
+  }
+
+  function footnoteUrl(stream, state) {
+    stream.eatSpace();
+    stream.match(/^[^\s]+/, true);
+    state.f = state.inline = inlineNormal;
+    return linkhref;
+  }
+
+  function inlineRE(endChar) {
+    if (!inlineRE[endChar]) {
+      // match any not-escaped-non-endChar and any escaped char
+      // then match endChar or eol
+      inlineRE[endChar] = new RegExp('^(?:[^\\\\\\' + endChar + ']|\\\\.)*(?:\\' + endChar + '|$)');
+    }
+    return inlineRE[endChar];
+  }
+
+  function inlineElement(type, endChar, next) {
+    next = next || inlineNormal;
+    return function(stream, state) {
+      stream.match(inlineRE(endChar));
+      state.inline = state.f = next;
+      return type;
+    };
+  }
+
+  return {
+    startState: function() {
+      return {
+        f: blockNormal,
+        
+        block: blockNormal,
+        htmlState: htmlMode.startState(),
+        indentation: 0,
+        
+        inline: inlineNormal,
+        text: handleText,
+        em: false,
+        strong: false
+      };
+    },
+
+    copyState: function(s) {
+      return {
+        f: s.f,
+        
+        block: s.block,
+        htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
+        indentation: s.indentation,
+        
+        inline: s.inline,
+        text: s.text,
+        em: s.em,
+        strong: s.strong
+      };
+    },
+
+    token: function(stream, state) {
+      if (stream.sol()) {
+        state.f = state.block;
+        var previousIndentation = state.indentation
+        ,   currentIndentation = 0;
+        while (previousIndentation > 0) {
+          if (stream.eat(' ')) {
+            previousIndentation--;
+            currentIndentation++;
+          } else if (previousIndentation >= 4 && stream.eat('\t')) {
+            previousIndentation -= 4;
+            currentIndentation += 4;
+          } else {
+            break;
+          }
+        }
+        state.indentation = currentIndentation;
+        
+        if (currentIndentation > 0) return null;
+      }
+      return state.f(stream, state);
+    },
+
+    getType: getType
+  };
+
+});
+
+CodeMirror.defineMIME("text/x-markdown", "markdown");
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/LICENSE.txt b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/LICENSE.txt
new file mode 100644
index 0000000..918866b
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2010 Timothy Farrell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/index.html
new file mode 100644
index 0000000..47e0e9d
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/index.html
@@ -0,0 +1,122 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: Python mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="python.js"></script>
+    <link rel="stylesheet" href="../../doc/docs.css">
+    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+  </head>
+  <body>
+    <h1>CodeMirror: Python mode</h1>
+    
+    <div><textarea id="code" name="code">
+# Literals
+1234
+0.0e101
+.123
+0b01010011100
+0o01234567
+0x0987654321abcdef
+7
+2147483647
+3L
+79228162514264337593543950336L
+0x100000000L
+79228162514264337593543950336
+0xdeadbeef
+3.14j
+10.j
+10j
+.001j
+1e100j
+3.14e-10j
+
+
+# String Literals
+'For\''
+"God\""
+"""so loved
+the world"""
+'''that he gave
+his only begotten\' '''
+'that whosoever believeth \
+in him'
+''
+
+# Identifiers
+__a__
+a.b
+a.b.c
+
+# Operators
++ - * / % & | ^ ~ < >
+== != <= >= <> << >> // **
+and or not in is
+
+# Delimiters
+() [] {} , : ` = ; @ .  # Note that @ and . require the proper context.
++= -= *= /= %= &= |= ^=
+//= >>= <<= **=
+
+# Keywords
+as assert break class continue def del elif else except
+finally for from global if import lambda pass raise
+return try while with yield
+
+# Python 2 Keywords (otherwise Identifiers)
+exec print
+
+# Python 3 Keywords (otherwise Identifiers)
+nonlocal
+
+# Types
+bool classmethod complex dict enumerate float frozenset int list object
+property reversed set slice staticmethod str super tuple type
+
+# Python 2 Types (otherwise Identifiers)
+basestring buffer file long unicode xrange
+
+# Python 3 Types (otherwise Identifiers)
+bytearray bytes filter map memoryview open range zip
+
+# Some Example code
+import os
+from package import ParentClass
+
+ at nonsenseDecorator
+def doesNothing():
+    pass
+
+class ExampleClass(ParentClass):
+    @staticmethod
+    def example(inputStr):
+        a = list(inputStr)
+        a.reverse()
+        return ''.join(a)
+
+    def __init__(self, mixin = 'Hello'):
+        self.mixin = mixin
+
+</textarea></div>
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        mode: {name: "python",
+               version: 2,
+               singleLineStringErrors: false},
+        lineNumbers: true,
+        indentUnit: 4,
+        tabMode: "shift",
+        matchBrackets: true
+      });
+    </script>
+    <h2>Configuration Options:</h2>
+    <ul>
+      <li>version - 2/3 - The version of Python to recognize.  Default is 2.</li>
+      <li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>
+    </ul>
+
+    <p><strong>MIME types defined:</strong> <code>text/x-python</code>.</p>
+  </body>
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/python.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/python.js
new file mode 100644
index 0000000..7d6a559
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/python/python.js
@@ -0,0 +1,333 @@
+CodeMirror.defineMode("python", function(conf, parserConf) {
+    var ERRORCLASS = 'error';
+    
+    function wordRegexp(words) {
+        return new RegExp("^((" + words.join(")|(") + "))\\b");
+    }
+    
+    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
+    var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
+    var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
+    var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
+    var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
+    var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
+
+    var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);
+    var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',
+                          'def', 'del', 'elif', 'else', 'except', 'finally',
+                          'for', 'from', 'global', 'if', 'import',
+                          'lambda', 'pass', 'raise', 'return',
+                          'try', 'while', 'with', 'yield'];
+    var commontypes = ['bool', 'classmethod', 'complex', 'dict', 'enumerate',
+                       'float', 'frozenset', 'int', 'list', 'object',
+                       'property', 'reversed', 'set', 'slice', 'staticmethod',
+                       'str', 'super', 'tuple', 'type'];
+    var py2 = {'types': ['basestring', 'buffer', 'file', 'long', 'unicode',
+                         'xrange'],
+               'keywords': ['exec', 'print']};
+    var py3 = {'types': ['bytearray', 'bytes', 'filter', 'map', 'memoryview',
+                         'open', 'range', 'zip'],
+               'keywords': ['nonlocal']};
+
+    if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) {
+        commonkeywords = commonkeywords.concat(py3.keywords);
+        commontypes = commontypes.concat(py3.types);
+        var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
+    } else {
+        commonkeywords = commonkeywords.concat(py2.keywords);
+        commontypes = commontypes.concat(py2.types);
+        var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
+    }
+    var keywords = wordRegexp(commonkeywords);
+    var types = wordRegexp(commontypes);
+
+    var indentInfo = null;
+
+    // tokenizers
+    function tokenBase(stream, state) {
+        // Handle scope changes
+        if (stream.sol()) {
+            var scopeOffset = state.scopes[0].offset;
+            if (stream.eatSpace()) {
+                var lineOffset = stream.indentation();
+                if (lineOffset > scopeOffset) {
+                    indentInfo = 'indent';
+                } else if (lineOffset < scopeOffset) {
+                    indentInfo = 'dedent';
+                }
+                return null;
+            } else {
+                if (scopeOffset > 0) {
+                    dedent(stream, state);
+                }
+            }
+        }
+        if (stream.eatSpace()) {
+            return null;
+        }
+        
+        var ch = stream.peek();
+        
+        // Handle Comments
+        if (ch === '#') {
+            stream.skipToEnd();
+            return 'comment';
+        }
+        
+        // Handle Number Literals
+        if (stream.match(/^[0-9\.]/, false)) {
+            var floatLiteral = false;
+            // Floats
+            if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
+            if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
+            if (stream.match(/^\.\d+/)) { floatLiteral = true; }
+            if (floatLiteral) {
+                // Float literals may be "imaginary"
+                stream.eat(/J/i);
+                return 'number';
+            }
+            // Integers
+            var intLiteral = false;
+            // Hex
+            if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }
+            // Binary
+            if (stream.match(/^0b[01]+/i)) { intLiteral = true; }
+            // Octal
+            if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }
+            // Decimal
+            if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) {
+                // Decimal literals may be "imaginary"
+                stream.eat(/J/i);
+                // TODO - Can you have imaginary longs?
+                intLiteral = true;
+            }
+            // Zero by itself with no other piece of number.
+            if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
+            if (intLiteral) {
+                // Integer literals may be "long"
+                stream.eat(/L/i);
+                return 'number';
+            }
+        }
+        
+        // Handle Strings
+        if (stream.match(stringPrefixes)) {
+            state.tokenize = tokenStringFactory(stream.current());
+            return state.tokenize(stream, state);
+        }
+        
+        // Handle operators and Delimiters
+        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
+            return null;
+        }
+        if (stream.match(doubleOperators)
+            || stream.match(singleOperators)
+            || stream.match(wordOperators)) {
+            return 'operator';
+        }
+        if (stream.match(singleDelimiters)) {
+            return null;
+        }
+        
+        if (stream.match(types)) {
+            return 'builtin';
+        }
+        
+        if (stream.match(keywords)) {
+            return 'keyword';
+        }
+        
+        if (stream.match(identifiers)) {
+            return 'variable';
+        }
+        
+        // Handle non-detected items
+        stream.next();
+        return ERRORCLASS;
+    }
+    
+    function tokenStringFactory(delimiter) {
+        while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
+            delimiter = delimiter.substr(1);
+        }
+        var singleline = delimiter.length == 1;
+        var OUTCLASS = 'string';
+        
+        return function tokenString(stream, state) {
+            while (!stream.eol()) {
+                stream.eatWhile(/[^'"\\]/);
+                if (stream.eat('\\')) {
+                    stream.next();
+                    if (singleline && stream.eol()) {
+                        return OUTCLASS;
+                    }
+                } else if (stream.match(delimiter)) {
+                    state.tokenize = tokenBase;
+                    return OUTCLASS;
+                } else {
+                    stream.eat(/['"]/);
+                }
+            }
+            if (singleline) {
+                if (parserConf.singleLineStringErrors) {
+                    return ERRORCLASS;
+                } else {
+                    state.tokenize = tokenBase;
+                }
+            }
+            return OUTCLASS;
+        };
+    }
+    
+    function indent(stream, state, type) {
+        type = type || 'py';
+        var indentUnit = 0;
+        if (type === 'py') {
+            if (state.scopes[0].type !== 'py') {
+                state.scopes[0].offset = stream.indentation();
+                return;
+            }
+            for (var i = 0; i < state.scopes.length; ++i) {
+                if (state.scopes[i].type === 'py') {
+                    indentUnit = state.scopes[i].offset + conf.indentUnit;
+                    break;
+                }
+            }
+        } else {
+            indentUnit = stream.column() + stream.current().length;
+        }
+        state.scopes.unshift({
+            offset: indentUnit,
+            type: type
+        });
+    }
+    
+    function dedent(stream, state, type) {
+        type = type || 'py';
+        if (state.scopes.length == 1) return;
+        if (state.scopes[0].type === 'py') {
+            var _indent = stream.indentation();
+            var _indent_index = -1;
+            for (var i = 0; i < state.scopes.length; ++i) {
+                if (_indent === state.scopes[i].offset) {
+                    _indent_index = i;
+                    break;
+                }
+            }
+            if (_indent_index === -1) {
+                return true;
+            }
+            while (state.scopes[0].offset !== _indent) {
+                state.scopes.shift();
+            }
+            return false
+        } else {
+            if (type === 'py') {
+                state.scopes[0].offset = stream.indentation();
+                return false;
+            } else {
+                if (state.scopes[0].type != type) {
+                    return true;
+                }
+                state.scopes.shift();
+                return false;
+            }
+        }
+    }
+
+    function tokenLexer(stream, state) {
+        indentInfo = null;
+        var style = state.tokenize(stream, state);
+        var current = stream.current();
+
+        // Handle '.' connected identifiers
+        if (current === '.') {
+            style = state.tokenize(stream, state);
+            current = stream.current();
+            if (style === 'variable') {
+                return 'variable';
+            } else {
+                return ERRORCLASS;
+            }
+        }
+        
+        // Handle decorators
+        if (current === '@') {
+            style = state.tokenize(stream, state);
+            current = stream.current();
+            if (style === 'variable'
+                || current === '@staticmethod'
+                || current === '@classmethod') {
+                return 'meta';
+            } else {
+                return ERRORCLASS;
+            }
+        }
+        
+        // Handle scope changes.
+        if (current === 'pass' || current === 'return') {
+            state.dedent += 1;
+        }
+        if ((current === ':' && !state.lambda && state.scopes[0].type == 'py')
+            || indentInfo === 'indent') {
+            indent(stream, state);
+        }
+        var delimiter_index = '[({'.indexOf(current);
+        if (delimiter_index !== -1) {
+            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
+        }
+        if (indentInfo === 'dedent') {
+            if (dedent(stream, state)) {
+                return ERRORCLASS;
+            }
+        }
+        delimiter_index = '])}'.indexOf(current);
+        if (delimiter_index !== -1) {
+            if (dedent(stream, state, current)) {
+                return ERRORCLASS;
+            }
+        }
+        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'py') {
+            if (state.scopes.length > 1) state.scopes.shift();
+            state.dedent -= 1;
+        }
+        
+        return style;
+    }
+
+    var external = {
+        startState: function(basecolumn) {
+            return {
+              tokenize: tokenBase,
+              scopes: [{offset:basecolumn || 0, type:'py'}],
+              lastToken: null,
+              lambda: false,
+              dedent: 0
+          };
+        },
+        
+        token: function(stream, state) {
+            var style = tokenLexer(stream, state);
+            
+            state.lastToken = {style:style, content: stream.current()};
+            
+            if (stream.eol() && stream.lambda) {
+                state.lambda = false;
+            }
+            
+            return style;
+        },
+        
+        indent: function(state, textAfter) {
+            if (state.tokenize != tokenBase) {
+                return 0;
+            }
+            
+            return state.scopes[0].offset;
+        }
+        
+    };
+    return external;
+});
+
+CodeMirror.defineMIME("text/x-python", "python");
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/rst/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/rst/index.html
new file mode 100644
index 0000000..fd75a28
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/rst/index.html
@@ -0,0 +1,525 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: reStructuredText mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="rst.js"></script>
+    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+    <link rel="stylesheet" href="../../doc/docs.css">
+  </head>
+  <body>
+    <h1>CodeMirror: reStructuredText mode</h1>
+
+<form><textarea id="code" name="code">
+.. This is an excerpt from Sphinx documentation: http://sphinx.pocoo.org/_sources/rest.txt
+
+.. highlightlang:: rest
+
+.. _rst-primer:
+
+reStructuredText Primer
+=======================
+
+This section is a brief introduction to reStructuredText (reST) concepts and
+syntax, intended to provide authors with enough information to author documents
+productively.  Since reST was designed to be a simple, unobtrusive markup
+language, this will not take too long.
+
+.. seealso::
+
+   The authoritative `reStructuredText User Documentation
+   <http://docutils.sourceforge.net/rst.html>`_.  The "ref" links in this
+   document link to the description of the individual constructs in the reST
+   reference.
+
+
+Paragraphs
+----------
+
+The paragraph (:duref:`ref <paragraphs>`) is the most basic block in a reST
+document.  Paragraphs are simply chunks of text separated by one or more blank
+lines.  As in Python, indentation is significant in reST, so all lines of the
+same paragraph must be left-aligned to the same level of indentation.
+
+
+.. _inlinemarkup:
+
+Inline markup
+-------------
+
+The standard reST inline markup is quite simple: use
+
+* one asterisk: ``*text*`` for emphasis (italics),
+* two asterisks: ``**text**`` for strong emphasis (boldface), and
+* backquotes: ````text```` for code samples.
+
+If asterisks or backquotes appear in running text and could be confused with
+inline markup delimiters, they have to be escaped with a backslash.
+
+Be aware of some restrictions of this markup:
+
+* it may not be nested,
+* content may not start or end with whitespace: ``* text*`` is wrong,
+* it must be separated from surrounding text by non-word characters.  Use a
+  backslash escaped space to work around that: ``thisis\ *one*\ word``.
+
+These restrictions may be lifted in future versions of the docutils.
+
+reST also allows for custom "interpreted text roles"', which signify that the
+enclosed text should be interpreted in a specific way.  Sphinx uses this to
+provide semantic markup and cross-referencing of identifiers, as described in
+the appropriate section.  The general syntax is ``:rolename:`content```.
+
+Standard reST provides the following roles:
+
+* :durole:`emphasis` -- alternate spelling for ``*emphasis*``
+* :durole:`strong` -- alternate spelling for ``**strong**``
+* :durole:`literal` -- alternate spelling for ````literal````
+* :durole:`subscript` -- subscript text
+* :durole:`superscript` -- superscript text
+* :durole:`title-reference` -- for titles of books, periodicals, and other
+  materials
+
+See :ref:`inline-markup` for roles added by Sphinx.
+
+
+Lists and Quote-like blocks
+---------------------------
+
+List markup (:duref:`ref <bullet-lists>`) is natural: just place an asterisk at
+the start of a paragraph and indent properly.  The same goes for numbered lists;
+they can also be autonumbered using a ``#`` sign::
+
+   * This is a bulleted list.
+   * It has two items, the second
+     item uses two lines.
+
+   1. This is a numbered list.
+   2. It has two items too.
+
+   #. This is a numbered list.
+   #. It has two items too.
+
+
+Nested lists are possible, but be aware that they must be separated from the
+parent list items by blank lines::
+
+   * this is
+   * a list
+
+     * with a nested list
+     * and some subitems
+
+   * and here the parent list continues
+
+Definition lists (:duref:`ref <definition-lists>`) are created as follows::
+
+   term (up to a line of text)
+      Definition of the term, which must be indented
+
+      and can even consist of multiple paragraphs
+
+   next term
+      Description.
+
+Note that the term cannot have more than one line of text.
+
+Quoted paragraphs (:duref:`ref <block-quotes>`) are created by just indenting
+them more than the surrounding paragraphs.
+
+Line blocks (:duref:`ref <line-blocks>`) are a way of preserving line breaks::
+
+   | These lines are
+   | broken exactly like in
+   | the source file.
+
+There are also several more special blocks available:
+
+* field lists (:duref:`ref <field-lists>`)
+* option lists (:duref:`ref <option-lists>`)
+* quoted literal blocks (:duref:`ref <quoted-literal-blocks>`)
+* doctest blocks (:duref:`ref <doctest-blocks>`)
+
+
+Source Code
+-----------
+
+Literal code blocks (:duref:`ref <literal-blocks>`) are introduced by ending a
+paragraph with the special marker ``::``.  The literal block must be indented
+(and, like all paragraphs, separated from the surrounding ones by blank lines)::
+
+   This is a normal text paragraph. The next paragraph is a code sample::
+
+      It is not processed in any way, except
+      that the indentation is removed.
+
+      It can span multiple lines.
+
+   This is a normal text paragraph again.
+
+The handling of the ``::`` marker is smart:
+
+* If it occurs as a paragraph of its own, that paragraph is completely left
+  out of the document.
+* If it is preceded by whitespace, the marker is removed.
+* If it is preceded by non-whitespace, the marker is replaced by a single
+  colon.
+
+That way, the second sentence in the above example's first paragraph would be
+rendered as "The next paragraph is a code sample:".
+
+
+.. _rst-tables:
+
+Tables
+------
+
+Two forms of tables are supported.  For *grid tables* (:duref:`ref
+<grid-tables>`), you have to "paint" the cell grid yourself.  They look like
+this::
+
+   +------------------------+------------+----------+----------+
+   | Header row, column 1   | Header 2   | Header 3 | Header 4 |
+   | (header rows optional) |            |          |          |
+   +========================+============+==========+==========+
+   | body row 1, column 1   | column 2   | column 3 | column 4 |
+   +------------------------+------------+----------+----------+
+   | body row 2             | ...        | ...      |          |
+   +------------------------+------------+----------+----------+
+
+*Simple tables* (:duref:`ref <simple-tables>`) are easier to write, but
+limited: they must contain more than one row, and the first column cannot
+contain multiple lines.  They look like this::
+
+   =====  =====  =======
+   A      B      A and B
+   =====  =====  =======
+   False  False  False
+   True   False  False
+   False  True   False
+   True   True   True
+   =====  =====  =======
+
+
+Hyperlinks
+----------
+
+External links
+^^^^^^^^^^^^^^
+
+Use ```Link text <http://example.com/>`_`` for inline web links.  If the link
+text should be the web address, you don't need special markup at all, the parser
+finds links and mail addresses in ordinary text.
+
+You can also separate the link and the target definition (:duref:`ref
+<hyperlink-targets>`), like this::
+
+   This is a paragraph that contains `a link`_.
+
+   .. _a link: http://example.com/
+
+
+Internal links
+^^^^^^^^^^^^^^
+
+Internal linking is done via a special reST role provided by Sphinx, see the
+section on specific markup, :ref:`ref-role`.
+
+
+Sections
+--------
+
+Section headers (:duref:`ref <sections>`) are created by underlining (and
+optionally overlining) the section title with a punctuation character, at least
+as long as the text::
+
+   =================
+   This is a heading
+   =================
+
+Normally, there are no heading levels assigned to certain characters as the
+structure is determined from the succession of headings.  However, for the
+Python documentation, this convention is used which you may follow:
+
+* ``#`` with overline, for parts
+* ``*`` with overline, for chapters
+* ``=``, for sections
+* ``-``, for subsections
+* ``^``, for subsubsections
+* ``"``, for paragraphs
+
+Of course, you are free to use your own marker characters (see the reST
+documentation), and use a deeper nesting level, but keep in mind that most
+target formats (HTML, LaTeX) have a limited supported nesting depth.
+
+
+Explicit Markup
+---------------
+
+"Explicit markup" (:duref:`ref <explicit-markup-blocks>`) is used in reST for
+most constructs that need special handling, such as footnotes,
+specially-highlighted paragraphs, comments, and generic directives.
+
+An explicit markup block begins with a line starting with ``..`` followed by
+whitespace and is terminated by the next paragraph at the same level of
+indentation.  (There needs to be a blank line between explicit markup and normal
+paragraphs.  This may all sound a bit complicated, but it is intuitive enough
+when you write it.)
+
+
+.. _directives:
+
+Directives
+----------
+
+A directive (:duref:`ref <directives>`) is a generic block of explicit markup.
+Besides roles, it is one of the extension mechanisms of reST, and Sphinx makes
+heavy use of it.
+
+Docutils supports the following directives:
+
+* Admonitions: :dudir:`attention`, :dudir:`caution`, :dudir:`danger`,
+  :dudir:`error`, :dudir:`hint`, :dudir:`important`, :dudir:`note`,
+  :dudir:`tip`, :dudir:`warning` and the generic :dudir:`admonition`.
+  (Most themes style only "note" and "warning" specially.)
+
+* Images:
+
+  - :dudir:`image` (see also Images_ below)
+  - :dudir:`figure` (an image with caption and optional legend)
+
+* Additional body elements:
+
+  - :dudir:`contents` (a local, i.e. for the current file only, table of
+    contents)
+  - :dudir:`container` (a container with a custom class, useful to generate an
+    outer ``<div>`` in HTML)
+  - :dudir:`rubric` (a heading without relation to the document sectioning)
+  - :dudir:`topic`, :dudir:`sidebar` (special highlighted body elements)
+  - :dudir:`parsed-literal` (literal block that supports inline markup)
+  - :dudir:`epigraph` (a block quote with optional attribution line)
+  - :dudir:`highlights`, :dudir:`pull-quote` (block quotes with their own
+    class attribute)
+  - :dudir:`compound` (a compound paragraph)
+
+* Special tables:
+
+  - :dudir:`table` (a table with title)
+  - :dudir:`csv-table` (a table generated from comma-separated values)
+  - :dudir:`list-table` (a table generated from a list of lists)
+
+* Special directives:
+
+  - :dudir:`raw` (include raw target-format markup)
+  - :dudir:`include` (include reStructuredText from another file)
+    -- in Sphinx, when given an absolute include file path, this directive takes
+    it as relative to the source directory
+  - :dudir:`class` (assign a class attribute to the next element) [1]_
+
+* HTML specifics:
+
+  - :dudir:`meta` (generation of HTML ``<meta>`` tags)
+  - :dudir:`title` (override document title)
+
+* Influencing markup:
+
+  - :dudir:`default-role` (set a new default role)
+  - :dudir:`role` (create a new role)
+
+  Since these are only per-file, better use Sphinx' facilities for setting the
+  :confval:`default_role`.
+
+Do *not* use the directives :dudir:`sectnum`, :dudir:`header` and
+:dudir:`footer`.
+
+Directives added by Sphinx are described in :ref:`sphinxmarkup`.
+
+Basically, a directive consists of a name, arguments, options and content. (Keep
+this terminology in mind, it is used in the next chapter describing custom
+directives.)  Looking at this example, ::
+
+   .. function:: foo(x)
+                 foo(y, z)
+      :module: some.module.name
+
+      Return a line of text input from the user.
+
+``function`` is the directive name.  It is given two arguments here, the
+remainder of the first line and the second line, as well as one option
+``module`` (as you can see, options are given in the lines immediately following
+the arguments and indicated by the colons).  Options must be indented to the
+same level as the directive content.
+
+The directive content follows after a blank line and is indented relative to the
+directive start.
+
+
+Images
+------
+
+reST supports an image directive (:dudir:`ref <image>`), used like so::
+
+   .. image:: gnu.png
+      (options)
+
+When used within Sphinx, the file name given (here ``gnu.png``) must either be
+relative to the source file, or absolute which means that they are relative to
+the top source directory.  For example, the file ``sketch/spam.rst`` could refer
+to the image ``images/spam.png`` as ``../images/spam.png`` or
+``/images/spam.png``.
+
+Sphinx will automatically copy image files over to a subdirectory of the output
+directory on building (e.g. the ``_static`` directory for HTML output.)
+
+Interpretation of image size options (``width`` and ``height``) is as follows:
+if the size has no unit or the unit is pixels, the given size will only be
+respected for output channels that support pixels (i.e. not in LaTeX output).
+Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
+
+Sphinx extends the standard docutils behavior by allowing an asterisk for the
+extension::
+
+   .. image:: gnu.*
+
+Sphinx then searches for all images matching the provided pattern and determines
+their type.  Each builder then chooses the best image out of these candidates.
+For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
+and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
+the former, while the HTML builder would prefer the latter.
+
+.. versionchanged:: 0.4
+   Added the support for file names ending in an asterisk.
+
+.. versionchanged:: 0.6
+   Image paths can now be absolute.
+
+
+Footnotes
+---------
+
+For footnotes (:duref:`ref <footnotes>`), use ``[#name]_`` to mark the footnote
+location, and add the footnote body at the bottom of the document after a
+"Footnotes" rubric heading, like so::
+
+   Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
+
+   .. rubric:: Footnotes
+
+   .. [#f1] Text of the first footnote.
+   .. [#f2] Text of the second footnote.
+
+You can also explicitly number the footnotes (``[1]_``) or use auto-numbered
+footnotes without names (``[#]_``).
+
+
+Citations
+---------
+
+Standard reST citations (:duref:`ref <citations>`) are supported, with the
+additional feature that they are "global", i.e. all citations can be referenced
+from all files.  Use them like so::
+
+   Lorem ipsum [Ref]_ dolor sit amet.
+
+   .. [Ref] Book or article reference, URL or whatever.
+
+Citation usage is similar to footnote usage, but with a label that is not
+numeric or begins with ``#``.
+
+
+Substitutions
+-------------
+
+reST supports "substitutions" (:duref:`ref <substitution-definitions>`), which
+are pieces of text and/or markup referred to in the text by ``|name|``.  They
+are defined like footnotes with explicit markup blocks, like this::
+
+   .. |name| replace:: replacement *text*
+
+or this::
+
+   .. |caution| image:: warning.png
+                :alt: Warning!
+
+See the :duref:`reST reference for substitutions <substitution-definitions>`
+for details.
+
+If you want to use some substitutions for all documents, put them into
+:confval:`rst_prolog` or put them into a separate file and include it into all
+documents you want to use them in, using the :rst:dir:`include` directive.  (Be
+sure to give the include file a file name extension differing from that of other
+source files, to avoid Sphinx finding it as a standalone document.)
+
+Sphinx defines some default substitutions, see :ref:`default-substitutions`.
+
+
+Comments
+--------
+
+Every explicit markup block which isn't a valid markup construct (like the
+footnotes above) is regarded as a comment (:duref:`ref <comments>`).  For
+example::
+
+   .. This is a comment.
+
+You can indent text after a comment start to form multiline comments::
+
+   ..
+      This whole indented block
+      is a comment.
+
+      Still in the comment.
+
+
+Source encoding
+---------------
+
+Since the easiest way to include special characters like em dashes or copyright
+signs in reST is to directly write them as Unicode characters, one has to
+specify an encoding.  Sphinx assumes source files to be encoded in UTF-8 by
+default; you can change this with the :confval:`source_encoding` config value.
+
+
+Gotchas
+-------
+
+There are some problems one commonly runs into while authoring reST documents:
+
+* **Separation of inline markup:** As said above, inline markup spans must be
+  separated from the surrounding text by non-word characters, you have to use a
+  backslash-escaped space to get around that.  See `the reference
+  <http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup>`_
+  for the details.
+
+* **No nested inline markup:** Something like ``*see :func:`foo`*`` is not
+  possible.
+
+
+.. rubric:: Footnotes
+
+.. [1] When the default domain contains a :rst:dir:`class` directive, this directive
+       will be shadowed.  Therefore, Sphinx re-exports it as :rst:dir:`rst-class`.
+</textarea></form>
+
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        lineNumbers: true,
+      });
+    </script>
+    <p>The reStructuredText mode supports one configuration parameter:</p>
+    <dl>
+      <dt><code>verbatim (string)</code></dt>
+      <dd>A name or MIME type of a mode that will be used for highlighting
+      verbatim blocks. By default, reStructuredText mode uses uniform color
+      for whole block of verbatim text if no mode is given.</dd>
+    </dl>
+    <p>If <code>python</code> mode is available,
+    it will be used for highlighting blocks containing Python/IPython terminal
+    sessions (blocks starting with <code>>>></code> (for Python) or
+    <code>In [num]:</code> (for IPython).
+
+    <p><strong>MIME types defined:</strong> <code>text/x-rst</code>.</p>
+  </body>
+</html>
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/rst/rst.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/rst/rst.js
new file mode 100644
index 0000000..411bac5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/rst/rst.js
@@ -0,0 +1,326 @@
+CodeMirror.defineMode('rst', function(config, options) {
+    function setState(state, fn, ctx) {
+        state.fn = fn;
+        setCtx(state, ctx);
+    }
+
+    function setCtx(state, ctx) {
+        state.ctx = ctx || {};
+    }
+
+    function setNormal(state, ch) {
+        if (ch && (typeof ch !== 'string')) {
+            var str = ch.current();
+            ch = str[str.length-1];
+        }
+
+        setState(state, normal, {back: ch});
+    }
+
+    function hasMode(mode) {
+        if (mode) {
+            var modes = CodeMirror.listModes();
+
+            for (var i in modes) {
+                if (modes[i] == mode) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    function getMode(mode) {
+        if (hasMode(mode)) {
+            return CodeMirror.getMode(config, mode);
+        } else {
+            return null;
+        }
+    }
+
+    var verbatimMode = getMode(options.verbatim);
+    var pythonMode = getMode('python');
+
+    var reSection = /^[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]/;
+    var reDirective = /^\s*\w([-:.\w]*\w)?::(\s|$)/;
+    var reHyperlink = /^\s*_[\w-]+:(\s|$)/;
+    var reFootnote = /^\s*\[(\d+|#)\](\s|$)/;
+    var reCitation = /^\s*\[[A-Za-z][\w-]*\](\s|$)/;
+    var reFootnoteRef = /^\[(\d+|#)\]_/;
+    var reCitationRef = /^\[[A-Za-z][\w-]*\]_/;
+    var reDirectiveMarker = /^\.\.(\s|$)/;
+    var reVerbatimMarker = /^::\s*$/;
+    var rePreInline = /^[-\s"([{</:]/;
+    var rePostInline = /^[-\s`'")\]}>/:.,;!?\\_]/;
+    var reEnumeratedList = /^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/;
+    var reBulletedList = /^\s*[-\+\*]\s/;
+    var reExamples = /^\s+(>>>|In \[\d+\]:)\s/;
+
+    function normal(stream, state) {
+        var ch, sol, i;
+
+        if (stream.eat(/\\/)) {
+            ch = stream.next();
+            setNormal(state, ch);
+            return null;
+        }
+
+        sol = stream.sol();
+
+        if (sol && (ch = stream.eat(reSection))) {
+            for (i = 0; stream.eat(ch); i++);
+
+            if (i >= 3 && stream.match(/^\s*$/)) {
+                setNormal(state, null);
+                return 'header';
+            } else {
+                stream.backUp(i + 1);
+            }
+        }
+
+        if (sol && stream.match(reDirectiveMarker)) {
+            if (!stream.eol()) {
+                setState(state, directive);
+            }
+            return 'meta';
+        }
+
+        if (stream.match(reVerbatimMarker)) {
+            if (!verbatimMode) {
+                setState(state, verbatim);
+            } else {
+                var mode = verbatimMode;
+
+                setState(state, verbatim, {
+                    mode: mode,
+                    local: mode.startState()
+                });
+            }
+            return 'meta';
+        }
+
+        if (sol && stream.match(reExamples, false)) {
+            if (!pythonMode) {
+                setState(state, verbatim);
+                return 'meta';
+            } else {
+                var mode = pythonMode;
+
+                setState(state, verbatim, {
+                    mode: mode,
+                    local: mode.startState()
+                });
+
+                return null;
+            }
+        }
+
+        function testBackward(re) {
+            return sol || !state.ctx.back || re.test(state.ctx.back);
+        }
+
+        function testForward(re) {
+            return stream.eol() || stream.match(re, false);
+        }
+
+        function testInline(re) {
+            return stream.match(re) && testBackward(/\W/) && testForward(/\W/);
+        }
+
+        if (testInline(reFootnoteRef)) {
+            setNormal(state, stream);
+            return 'footnote';
+        }
+
+        if (testInline(reCitationRef)) {
+            setNormal(state, stream);
+            return 'citation';
+        }
+
+        ch = stream.next();
+
+        if (testBackward(rePreInline)) {
+            if ((ch === ':' || ch === '|') && stream.eat(/\S/)) {
+                var token;
+
+                if (ch === ':') {
+                    token = 'builtin';
+                } else {
+                    token = 'atom';
+                }
+
+                setState(state, inline, {
+                    ch: ch,
+                    wide: false,
+                    prev: null,
+                    token: token
+                });
+
+                return token;
+            }
+
+            if (ch === '*' || ch === '`') {
+                var orig = ch,
+                    wide = false;
+
+                ch = stream.next();
+
+                if (ch == orig) {
+                    wide = true;
+                    ch = stream.next();
+                }
+
+                if (ch && !/\s/.test(ch)) {
+                    var token;
+
+                    if (orig === '*') {
+                        token = wide ? 'strong' : 'em';
+                    } else {
+                        token = wide ? 'string' : 'string-2';
+                    }
+
+                    setState(state, inline, {
+                        ch: orig,               // inline() has to know what to search for
+                        wide: wide,             // are we looking for `ch` or `chch`
+                        prev: null,             // terminator must not be preceeded with whitespace
+                        token: token            // I don't want to recompute this all the time
+                    });
+
+                    return token;
+                }
+            }
+        }
+
+        setNormal(state, ch);
+        return null;
+    }
+
+    function inline(stream, state) {
+        var ch = stream.next(),
+            token = state.ctx.token;
+
+        function finish(ch) {
+            state.ctx.prev = ch;
+            return token;
+        }
+
+        if (ch != state.ctx.ch) {
+            return finish(ch);
+        }
+
+        if (/\s/.test(state.ctx.prev)) {
+            return finish(ch);
+        }
+
+        if (state.ctx.wide) {
+            ch = stream.next();
+
+            if (ch != state.ctx.ch) {
+                return finish(ch);
+            }
+        }
+
+        if (!stream.eol() && !rePostInline.test(stream.peek())) {
+            if (state.ctx.wide) {
+                stream.backUp(1);
+            }
+
+            return finish(ch);
+        }
+
+        setState(state, normal);
+        setNormal(state, ch);
+
+        return token;
+    }
+
+    function directive(stream, state) {
+        var token = null;
+
+        if (stream.match(reDirective)) {
+            token = 'attribute';
+        } else if (stream.match(reHyperlink)) {
+            token = 'link';
+        } else if (stream.match(reFootnote)) {
+            token = 'quote';
+        } else if (stream.match(reCitation)) {
+            token = 'quote';
+        } else {
+            stream.eatSpace();
+
+            if (stream.eol()) {
+                setNormal(state, stream);
+                return null;
+            } else {
+                stream.skipToEnd();
+                setState(state, comment);
+                return 'comment';
+            }
+        }
+
+        // FIXME this is unreachable
+        setState(state, body, {start: true});
+        return token;
+    }
+
+    function body(stream, state) {
+        var token = 'body';
+
+        if (!state.ctx.start || stream.sol()) {
+            return block(stream, state, token);
+        }
+
+        stream.skipToEnd();
+        setCtx(state);
+
+        return token;
+    }
+
+    function comment(stream, state) {
+        return block(stream, state, 'comment');
+    }
+
+    function verbatim(stream, state) {
+        if (!verbatimMode) {
+            return block(stream, state, 'meta');
+        } else {
+            if (stream.sol()) {
+                if (!stream.eatSpace()) {
+                    setNormal(state, stream);
+                }
+
+                return null;
+            }
+
+            return verbatimMode.token(stream, state.ctx.local);
+        }
+    }
+
+    function block(stream, state, token) {
+        if (stream.eol() || stream.eatSpace()) {
+            stream.skipToEnd();
+            return token;
+        } else {
+            setNormal(state, stream);
+            return null;
+        }
+    }
+
+    return {
+        startState: function() {
+            return {fn: normal, ctx: {}};
+        },
+
+        copyState: function(state) {
+            return {fn: state.fn, ctx: state.ctx};
+        },
+
+        token: function(stream, state) {
+            var token = state.fn(stream, state);
+            return token;
+        }
+    };
+});
+
+CodeMirror.defineMIME("text/x-rst", "rst");
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/xml/index.html b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/xml/index.html
new file mode 100644
index 0000000..3b6d6af
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/xml/index.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+  <head>
+    <title>CodeMirror: XML mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="xml.js"></script>
+    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+    <link rel="stylesheet" href="../../doc/docs.css">
+  </head>
+  <body>
+    <h1>CodeMirror: XML mode</h1>
+    <form><textarea id="code" name="code">
+<html style="color: green">
+  <!-- this is a comment -->
+  <head>
+    <title>HTML Example</title>
+  </head>
+  <body>
+    The indentation tries to be <em>somewhat &quot;do what
+    I mean&quot;</em>... but might not match your style.
+  </body>
+</html>
+</textarea></form>
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        mode: {name: "xml", alignCDATA: true},
+        lineNumbers: true
+      });
+    </script>
+    <p>The XML mode supports two configuration parameters:</p>
+    <dl>
+      <dt><code>htmlMode (boolean)</code></dt>
+      <dd>This switches the mode to parse HTML instead of XML. This
+      means attributes do not have to be quoted, and some elements
+      (such as <code>br</code>) do not require a closing tag.</dd>
+      <dt><code>alignCDATA (boolean)</code></dt>
+      <dd>Setting this to true will force the opening tag of CDATA
+      blocks to not be indented.</dd>
+    </dl>
+
+    <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
+  </body>
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/xml/xml.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/xml/xml.js
new file mode 100644
index 0000000..71e0e2b
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/mode/xml/xml.js
@@ -0,0 +1,252 @@
+CodeMirror.defineMode("xml", function(config, parserConfig) {
+  var indentUnit = config.indentUnit;
+  var Kludges = parserConfig.htmlMode ? {
+    autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
+                      "meta": true, "col": true, "frame": true, "base": true, "area": true},
+    doNotIndent: {"pre": true},
+    allowUnquoted: true
+  } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false};
+  var alignCDATA = parserConfig.alignCDATA;
+
+  // Return variables for tokenizers
+  var tagName, type;
+
+  function inText(stream, state) {
+    function chain(parser) {
+      state.tokenize = parser;
+      return parser(stream, state);
+    }
+
+    var ch = stream.next();
+    if (ch == "<") {
+      if (stream.eat("!")) {
+        if (stream.eat("[")) {
+          if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
+          else return null;
+        }
+        else if (stream.match("--")) return chain(inBlock("comment", "-->"));
+        else if (stream.match("DOCTYPE", true, true)) {
+          stream.eatWhile(/[\w\._\-]/);
+          return chain(doctype(1));
+        }
+        else return null;
+      }
+      else if (stream.eat("?")) {
+        stream.eatWhile(/[\w\._\-]/);
+        state.tokenize = inBlock("meta", "?>");
+        return "meta";
+      }
+      else {
+        type = stream.eat("/") ? "closeTag" : "openTag";
+        stream.eatSpace();
+        tagName = "";
+        var c;
+        while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
+        state.tokenize = inTag;
+        return "tag";
+      }
+    }
+    else if (ch == "&") {
+      stream.eatWhile(/[^;]/);
+      stream.eat(";");
+      return "atom";
+    }
+    else {
+      stream.eatWhile(/[^&<]/);
+      return null;
+    }
+  }
+
+  function inTag(stream, state) {
+    var ch = stream.next();
+    if (ch == ">" || (ch == "/" && stream.eat(">"))) {
+      state.tokenize = inText;
+      type = ch == ">" ? "endTag" : "selfcloseTag";
+      return "tag";
+    }
+    else if (ch == "=") {
+      type = "equals";
+      return null;
+    }
+    else if (/[\'\"]/.test(ch)) {
+      state.tokenize = inAttribute(ch);
+      return state.tokenize(stream, state);
+    }
+    else {
+      stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);
+      return "word";
+    }
+  }
+
+  function inAttribute(quote) {
+    return function(stream, state) {
+      while (!stream.eol()) {
+        if (stream.next() == quote) {
+          state.tokenize = inTag;
+          break;
+        }
+      }
+      return "string";
+    };
+  }
+
+  function inBlock(style, terminator) {
+    return function(stream, state) {
+      while (!stream.eol()) {
+        if (stream.match(terminator)) {
+          state.tokenize = inText;
+          break;
+        }
+        stream.next();
+      }
+      return style;
+    };
+  }
+  function doctype(depth) {
+    return function(stream, state) {
+      var ch;
+      while ((ch = stream.next()) != null) {
+        if (ch == "<") {
+          state.tokenize = doctype(depth + 1);
+          return state.tokenize(stream, state);
+        } else if (ch == ">") {
+          if (depth == 1) {
+            state.tokenize = inText;
+            break;
+          } else {
+            state.tokenize = doctype(depth - 1);
+            return state.tokenize(stream, state);
+          }
+        }
+      }
+      return "meta";
+    };
+  }
+
+  var curState, setStyle;
+  function pass() {
+    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
+  }
+  function cont() {
+    pass.apply(null, arguments);
+    return true;
+  }
+
+  function pushContext(tagName, startOfLine) {
+    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
+    curState.context = {
+      prev: curState.context,
+      tagName: tagName,
+      indent: curState.indented,
+      startOfLine: startOfLine,
+      noIndent: noIndent
+    };
+  }
+  function popContext() {
+    if (curState.context) curState.context = curState.context.prev;
+  }
+
+  function element(type) {
+    if (type == "openTag") {
+      curState.tagName = tagName;
+      return cont(attributes, endtag(curState.startOfLine));
+    } else if (type == "closeTag") {
+      var err = false;
+      if (curState.context) {
+        err = curState.context.tagName != tagName;
+      } else {
+        err = true;
+      }
+      if (err) setStyle = "error";
+      return cont(endclosetag(err));
+    }
+    return cont();
+  }
+  function endtag(startOfLine) {
+    return function(type) {
+      if (type == "selfcloseTag" ||
+          (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))
+        return cont();
+      if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();}
+      return cont();
+    };
+  }
+  function endclosetag(err) {
+    return function(type) {
+      if (err) setStyle = "error";
+      if (type == "endTag") { popContext(); return cont(); }
+      setStyle = "error";
+      return cont(arguments.callee);
+    }
+  }
+
+  function attributes(type) {
+    if (type == "word") {setStyle = "attribute"; return cont(attributes);}
+    if (type == "equals") return cont(attvalue, attributes);
+    if (type == "string") {setStyle = "error"; return cont(attributes);}
+    return pass();
+  }
+  function attvalue(type) {
+    if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
+    if (type == "string") return cont(attvaluemaybe);
+    return pass();
+  }
+  function attvaluemaybe(type) {
+    if (type == "string") return cont(attvaluemaybe);
+    else return pass();
+  }
+
+  return {
+    startState: function() {
+      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};
+    },
+
+    token: function(stream, state) {
+      if (stream.sol()) {
+        state.startOfLine = true;
+        state.indented = stream.indentation();
+      }
+      if (stream.eatSpace()) return null;
+
+      setStyle = type = tagName = null;
+      var style = state.tokenize(stream, state);
+      state.type = type;
+      if ((style || type) && style != "comment") {
+        curState = state;
+        while (true) {
+          var comb = state.cc.pop() || element;
+          if (comb(type || style)) break;
+        }
+      }
+      state.startOfLine = false;
+      return setStyle || style;
+    },
+
+    indent: function(state, textAfter, fullLine) {
+      var context = state.context;
+      if ((state.tokenize != inTag && state.tokenize != inText) ||
+          context && context.noIndent)
+        return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
+      if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
+      if (context && /^<\//.test(textAfter))
+        context = context.prev;
+      while (context && !context.startOfLine)
+        context = context.prev;
+      if (context) return context.indent + indentUnit;
+      else return 0;
+    },
+
+    compareStates: function(a, b) {
+      if (a.indented != b.indented || a.tokenize != b.tokenize) return false;
+      for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
+        if (!ca || !cb) return ca == cb;
+        if (ca.tagName != cb.tagName) return false;
+      }
+    },
+
+    electricChars: "/"
+  };
+});
+
+CodeMirror.defineMIME("application/xml", "xml");
+CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/cobalt.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/cobalt.css
new file mode 100644
index 0000000..a6842a4
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/cobalt.css
@@ -0,0 +1,18 @@
+.cm-s-cobalt { background: #002240; color: white; }
+.cm-s-cobalt span.CodeMirror-selected { background: #b36539 !important; }
+.cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
+.cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; }
+.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
+
+.cm-s-cobalt span.cm-comment { color: #08f; }
+.cm-s-cobalt span.cm-atom { color: #845dc4; }
+.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
+.cm-s-cobalt span.cm-keyword { color: #ffee80; }
+.cm-s-cobalt span.cm-string { color: #3ad900; }
+.cm-s-cobalt span.cm-meta { color: #ff9d00; }
+.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
+.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
+.cm-s-cobalt span.cm-error { color: #9d1e15; }
+.cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
+.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
+.cm-s-cobalt span.cm-link { color: #845dc4; }
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/eclipse.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/eclipse.css
new file mode 100644
index 0000000..41f6fcb
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/eclipse.css
@@ -0,0 +1,25 @@
+.cm-s-eclipse span.cm-meta {color: #FF1717;}
+.cm-s-eclipse span.cm-keyword { font-weight: bold; color: #7F0055; }
+.cm-s-eclipse span.cm-atom {color: #219;}
+.cm-s-eclipse span.cm-number {color: #164;}
+.cm-s-eclipse span.cm-def {color: #00f;}
+.cm-s-eclipse span.cm-variable {color: black;}
+.cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
+.cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
+.cm-s-eclipse span.cm-property {color: black;}
+.cm-s-eclipse span.cm-operator {color: black;}
+.cm-s-eclipse span.cm-comment {color: #3F7F5F;}
+.cm-s-eclipse span.cm-string {color: #2A00FF;}
+.cm-s-eclipse span.cm-string-2 {color: #f50;}
+.cm-s-eclipse span.cm-error {color: #f00;}
+.cm-s-eclipse span.cm-qualifier {color: #555;}
+.cm-s-eclipse span.cm-builtin {color: #30a;}
+.cm-s-eclipse span.cm-bracket {color: #cc7;}
+.cm-s-eclipse span.cm-tag {color: #170;}
+.cm-s-eclipse span.cm-attribute {color: #00c;}
+.cm-s-eclipse span.cm-link {color: #219;}
+
+.cm-s-eclipse .CodeMirror-matchingbracket {
+	border:1px solid grey;
+	color:black !important;;
+}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/elegant.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/elegant.css
new file mode 100644
index 0000000..29afa98
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/elegant.css
@@ -0,0 +1,10 @@
+.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
+.cm-s-elegant span.cm-comment {color: #262;font-style: italic;}
+.cm-s-elegant span.cm-meta {color: #555;font-style: italic;}
+.cm-s-elegant span.cm-variable {color: black;}
+.cm-s-elegant span.cm-variable-2 {color: #b11;}
+.cm-s-elegant span.cm-qualifier {color: #555;}
+.cm-s-elegant span.cm-keyword {color: #730;}
+.cm-s-elegant span.cm-builtin {color: #30a;}
+.cm-s-elegant span.cm-error {background-color: #fdd;}
+.cm-s-elegant span.cm-link {color: #762;}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/ipython.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/ipython.css
new file mode 100644
index 0000000..c8caa24
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/ipython.css
@@ -0,0 +1,40 @@
+
+
+.cm-s-ipython span.cm-keyword {color: #008000; font-weight: bold;}
+.cm-s-ipython span.cm-number {color: #000080;}
+.cm-s-ipython span.cm-operator {color: #AA22FF; font-weight: bold;}
+.cm-s-ipython span.cm-meta {color: #AA22FF;}
+.cm-s-ipython span.cm-comment {color: #408080; font-style: italic;}
+.cm-s-ipython span.cm-string {color: #BA2121;}
+.cm-s-ipython span.cm-error {color: #f00;}
+.cm-s-ipython span.cm-builtin {color: #008000;}
+.cm-s-ipython span.cm-variable {color: #000000;}
+
+/* These classes are not currently used in the python.js mode */
+
+/*.cm-s-ipython span.cm-atom {color: #219;}*/
+/*.cm-s-ipython span.cm-def {color: #00f;}*/
+/*.cm-s-ipython span.cm-variable-2 {color: #05a;}*/
+/*.cm-s-ipython span.cm-variable-3 {color: #0a5;}*/
+/*.cm-s-ipython span.cm-property {color: black;}*/
+/*.cm-s-ipython span.cm-qualifier {color: #555;}*/
+/*.cm-s-ipython span.cm-bracket {color: #cc7;}*/
+/*.cm-s-ipython span.cm-tag {color: #170;}*/
+/*.cm-s-ipython span.cm-attribute {color: #00c;}*/
+
+/* These are the old styles for our pre-themed version */
+
+/*span.py-delimiter {color: #666666;}*/
+/*span.py-special {color: #666666;}*/
+/*span.py-operator {color: #AA22FF; font-weight: bold;}*/
+/*span.py-keyword {color: #008000; font-weight: bold;}*/
+/*span.py-number {color: #666666;}*/
+/*span.py-identifier {color: #000000;}*/
+/*span.py-func {color: #000000;}*/
+/*span.py-type {color: #008000;}*/
+/*span.py-decorator {color: #AA22FF;}*/
+/*span.py-comment {color: #408080; font-style: italic;}*/
+/*span.py-string {color: #BA2121;}*/
+/*span.py-bytes {color: #BA2121;}*/
+/*span.py-raw {color: #BA2121;}*/
+/*span.py-unicode {color: #BA2121;}*/
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/monokai.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/monokai.css
new file mode 100644
index 0000000..470d4c5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/monokai.css
@@ -0,0 +1,28 @@
+/* Based on Sublime Text's Monokai theme */
+
+.cm-s-monokai {background: #272822; color: #f8f8f2;}
+.cm-s-monokai span.CodeMirror-selected {background: #ffe792 !important;}
+.cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;}
+.cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}
+.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
+
+.cm-s-monokai span.cm-comment {color: #75715e;}
+.cm-s-monokai span.cm-atom {color: #ae81ff;}
+.cm-s-monokai span.cm-number {color: #ae81ff;}
+
+.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
+.cm-s-monokai span.cm-keyword {color: #f92672;}
+.cm-s-monokai span.cm-string {color: #e6db74;}
+
+.cm-s-monokai span.cm-variable {color: #a6e22e;}
+.cm-s-monokai span.cm-variable-2 {color: #9effff;}
+.cm-s-monokai span.cm-def {color: #fd971f;}
+.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
+.cm-s-monokai span.cm-bracket {color: #f8f8f2;}
+.cm-s-monokai span.cm-tag {color: #f92672;}
+.cm-s-monokai span.cm-link {color: #ae81ff;}
+
+.cm-s-monokai .CodeMirror-matchingbracket {
+  text-decoration: underline;
+  color: white !important;
+}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/neat.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/neat.css
new file mode 100644
index 0000000..6d2dbf5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/neat.css
@@ -0,0 +1,9 @@
+.cm-s-neat span.cm-comment { color: #a86; }
+.cm-s-neat span.cm-keyword { font-weight: bold; color: blue; }
+.cm-s-neat span.cm-string { color: #a22; }
+.cm-s-neat span.cm-builtin { font-weight: bold; color: #077; }
+.cm-s-neat span.cm-special { font-weight: bold; color: #0aa; }
+.cm-s-neat span.cm-variable { color: black; }
+.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
+.cm-s-neat span.cm-meta {color: #555;}
+.cm-s-neat span.cm-link { color: #3a3; }
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/night.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/night.css
new file mode 100644
index 0000000..f86c70e
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/night.css
@@ -0,0 +1,21 @@
+/* Loosely based on the Midnight Textmate theme */
+
+.cm-s-night { background: #0a001f; color: #f8f8f8; }
+.cm-s-night span.CodeMirror-selected { background: #a8f !important; }
+.cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
+.cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
+.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
+
+.cm-s-night span.cm-comment { color: #6900a1; }
+.cm-s-night span.cm-atom { color: #845dc4; }
+.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
+.cm-s-night span.cm-keyword { color: #599eff; }
+.cm-s-night span.cm-string { color: #37f14a; }
+.cm-s-night span.cm-meta { color: #7678e2; }
+.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
+.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
+.cm-s-night span.cm-error { color: #9d1e15; }
+.cm-s-night span.cm-bracket { color: #8da6ce; }
+.cm-s-night span.cm-comment { color: #6900a1; }
+.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
+.cm-s-night span.cm-link { color: #845dc4; }
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/rubyblue.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/rubyblue.css
new file mode 100644
index 0000000..c712755
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/codemirror/theme/rubyblue.css
@@ -0,0 +1,21 @@
+.cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; }	/* - customized editor font - */
+
+.cm-s-rubyblue { background: #112435; color: white; }
+.cm-s-rubyblue span.CodeMirror-selected { background: #0000FF !important; }
+.cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; }
+.cm-s-rubyblue .CodeMirror-gutter-text { color: white; }
+.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
+
+.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; }
+.cm-s-rubyblue span.cm-atom { color: #F4C20B; }
+.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
+.cm-s-rubyblue span.cm-keyword { color: #F0F; }
+.cm-s-rubyblue span.cm-string { color: #F08047; }
+.cm-s-rubyblue span.cm-meta { color: #F0F; }
+.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }
+.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }
+.cm-s-rubyblue span.cm-error { color: #AF2018; }
+.cm-s-rubyblue span.cm-bracket { color: #F0F; }
+.cm-s-rubyblue span.cm-link { color: #F4C20B; }
+.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }
+.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/base.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/base.css
new file mode 100644
index 0000000..5088bfb
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/base.css
@@ -0,0 +1,73 @@
+/**
+ * Primary styles
+ *
+ * Author: IPython Development Team
+ */
+
+
+body {
+    background-color: white;
+    /* This makes sure that the body covers the entire window and needs to
+       be in a different element than the display: box in wrapper below */
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 0px;
+    bottom: 0px;
+    overflow: hidden;
+}
+
+
+div#header {
+    /* Initially hidden to prevent FLOUC */
+    display: none;
+    position: relative;
+    height: 40px;
+    padding: 5px;
+    margin: 0px;
+    width: 100%;
+}
+
+span#ipython_notebook {
+    position: absolute;
+    padding: 2px 2px 2px 5px;
+}
+
+span#ipython_notebook h1 img {
+    font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
+    height: 24px;
+    text-decoration:none;
+    display: inline;
+    color: black;
+}
+
+div#main_app {
+    /* Initially hidden to prevent FLOUC */
+    display: none;
+    width: 100%;
+    position: relative;
+}
+
+/* We set the fonts by hand here to override the values in the theme */
+.ui-widget {
+    font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
+}
+
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button {
+    font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
+}
+
+/* Smaller buttons */
+.ui-button .ui-button-text {
+    padding: 0.2em 0.8em;
+    font-size: 77%;
+}
+
+span#login_widget {
+    float: right;
+}
+
+/* generic class for hidden objects */
+.hidden {
+    display: none;
+}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/boilerplate.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/boilerplate.css
new file mode 100644
index 0000000..9fa1ee5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/boilerplate.css
@@ -0,0 +1,73 @@
+/**
+ * HTML5 ✰ Boilerplate
+ *
+ * style.css contains a reset, font normalization and some base styles.
+ *
+ * Credit is left where credit is due.
+ * Much inspiration was taken from these projects:
+ * - yui.yahooapis.com/2.8.1/build/base/base.css
+ * - camendesign.com/design/
+ * - praegnanz.de/weblog/htmlcssjs-kickstart
+ */
+
+
+/**
+ * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
+ * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark
+ * html5doctor.com/html-5-reset-stylesheet/
+ */
+
+html, body, div, span, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
+small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section, summary,
+time, mark, audio, video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
+}
+
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+  display: block;
+}
+
+blockquote, q { quotes: none; }
+
+blockquote:before, blockquote:after,
+q:before, q:after { content: ""; content: none; }
+
+ins { background-color: #ff9; color: #000; text-decoration: none; }
+
+mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
+
+del { text-decoration: line-through; }
+
+abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
+
+table { border-collapse: collapse; border-spacing: 0; }
+
+hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
+
+input, select { vertical-align: middle; }
+
+
+/**
+ * Font normalization inspired by YUI Library's fonts.css: developer.yahoo.com/yui/
+ */
+
+body { font:13px/1.231 sans-serif; *font-size:small; } /* Hack retained to preserve specificity */
+select, input, textarea, button { font:99% sans-serif; }
+
+/* Normalize monospace sizing:
+   en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */
+pre, code, kbd, samp { font-family: monospace, sans-serif; }
+
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/layout.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/layout.css
new file mode 100644
index 0000000..d8bec47
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/layout.css
@@ -0,0 +1,130 @@
+
+.border-box-sizing {
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+}
+
+/* Flexible box model classes */
+/* Taken from Alex Russell http://infrequently.org/2009/08/css-3-progress/ */
+ 
+.hbox {
+	display: -webkit-box;
+	-webkit-box-orient: horizontal;
+	-webkit-box-align: stretch;
+ 
+	display: -moz-box;
+	-moz-box-orient: horizontal;
+	-moz-box-align: stretch;
+ 
+	display: box;
+	box-orient: horizontal;
+	box-align: stretch;
+}
+ 
+.hbox > * {
+	-webkit-box-flex: 0;
+	-moz-box-flex: 0;
+	box-flex: 0;
+}
+ 
+.vbox {
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	-webkit-box-align: stretch;
+ 
+	display: -moz-box;
+	-moz-box-orient: vertical;
+	-moz-box-align: stretch;
+ 
+	display: box;
+	box-orient: vertical;
+	box-align: stretch;
+}
+ 
+.vbox > * {
+	-webkit-box-flex: 0;
+	-moz-box-flex: 0;
+	box-flex: 0;
+}
+  
+.reverse {
+	-webkit-box-direction: reverse;
+	-moz-box-direction: reverse;
+	box-direction: reverse;
+}
+ 
+.box-flex0 {
+	-webkit-box-flex: 0;
+	-moz-box-flex: 0;
+	box-flex: 0;
+}
+ 
+.box-flex1, .box-flex {
+	-webkit-box-flex: 1;
+	-moz-box-flex: 1;
+	box-flex: 1;
+}
+ 
+.box-flex2 {
+	-webkit-box-flex: 2;
+	-moz-box-flex: 2;
+	box-flex: 2;
+}
+ 
+.box-group1 {
+	-webkit-box-flex-group: 1;
+	-moz-box-flex-group: 1;
+	box-flex-group: 1;
+}
+ 
+.box-group2 {
+	-webkit-box-flex-group: 2;
+	-moz-box-flex-group: 2;
+	box-flex-group: 2;
+}
+ 
+.start {
+	-webkit-box-pack: start;
+	-moz-box-pack: start;
+	box-pack: start;
+}
+ 
+.end {
+	-webkit-box-pack: end;
+	-moz-box-pack: end;
+	box-pack: end;
+}
+ 
+.center {
+	-webkit-box-pack: center;
+	-moz-box-pack: center;
+	box-pack: center;
+}
+
+.message {
+    border-width: 1px;
+    border-style: solid;
+    text-align: center;
+    padding: 0.5em;
+    margin: 0.5em 0;
+}
+
+.message.error {
+    background-color: #FFD3D1;
+    border-color: red;
+}
+
+.message.warning {
+    background-color: #FFD09E;
+    border-color: orange;
+}
+
+.message.info {
+    background-color: #CBFFBA;
+    border-color: green;
+}
+
+#content_panel {
+    margin: 0.5em;
+}
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/notebook.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/notebook.css
new file mode 100644
index 0000000..6b79133
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/notebook.css
@@ -0,0 +1,399 @@
+/**
+ * Primary styles
+ *
+ * Author: IPython Development Team
+ */
+
+
+body {
+    background-color: white;
+    /* This makes sure that the body covers the entire window and needs to
+       be in a different element than the display: box in wrapper below */
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 0px;
+    bottom: 0px;
+    overflow: hidden;
+}
+
+span#save_widget {
+    padding: 5px;
+    margin: 0px 0px 0px 300px;
+    display:inline-block;
+}
+
+span#notebook_name {
+    height: 1em;
+    line-height: 1em;
+    padding: 3px;
+    border: none;
+    font-size: 146.5%;
+}
+
+#menubar {
+    /* Initially hidden to prevent FLOUC */
+    display: none;
+}
+
+.ui-menubar-item .ui-button .ui-button-text {
+    padding: 0.4em 1.0em;
+    font-size: 100%;
+}
+
+.ui-menu {
+  -moz-box-shadow:    0px 6px 10px -1px #adadad;
+  -webkit-box-shadow: 0px 6px 10px -1px #adadad;
+  box-shadow:         0px 6px 10px -1px #adadad;
+}
+
+.ui-menu .ui-menu-item a {
+    padding: 2px 1.6em;
+}
+
+.ui-menu hr {
+    margin: 0.3em 0;
+}
+
+#fulledit_widget {
+    /* Initially hidden to prevent FLOUC */
+    display: none;
+    width: 920px;
+    margin: 0px auto;
+}
+
+#fulledit_editor {
+    height: 577px;
+    width: 920px;
+}
+
+#fulledit_header {
+    width: 920px;
+}
+
+span#quick_help_area {
+    position: static;
+    padding: 5px 0px;
+    margin: 0px 0px 0px 0px;
+}
+
+span#kernel_status {
+    position: absolute;
+    padding: 8px 5px 5px 5px;
+    right: 10px;
+    font-weight: bold;
+}
+
+
+.status_idle {
+    color: gray;
+    visibility: hidden;
+}
+
+.status_busy {
+    color: red;
+}
+
+.status_restarting {
+    color: black;
+}
+
+#kernel_persist {
+    float: right;
+}
+
+.help_string {
+    float: right;
+    width: 170px;
+    padding: 0px 5px;
+    text-align: left;
+    font-size: 85%;
+}
+
+.help_string_label {
+    float: right;
+    font-size: 85%;
+}
+
+div#notebook_panel {
+    margin: 0px 0px 0px 0px;
+    padding: 0px;
+}
+
+div#notebook {
+    overflow-y: scroll;
+    overflow-x: auto;
+    width: 100%;
+    /* This spaces the cell away from the edge of the notebook area */
+    padding: 5px 5px 15px 5px;
+    margin: 0px
+    background-color: white;
+}
+
+div#pager_splitter {
+    height: 8px;
+}
+
+div#pager {
+    padding: 15px;
+    overflow: auto;
+    display: none;
+}
+
+div.cell {
+    width: 100%;
+    padding: 5px 5px 5px 0px;
+    /* This acts as a spacer between cells, that is outside the border */
+    margin: 2px 0px 2px 0px;
+}
+
+div.code_cell {
+    background-color: white;
+}
+/* any special styling for code cells that are currently running goes here */
+div.code_cell.running {
+}
+
+div.prompt {
+    /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
+    width: 11ex;
+    /* This 0.4em is tuned to match the padding on the CodeMirror editor. */
+    padding: 0.4em;
+    margin: 0px;
+    font-family: monospace;
+    text-align:right;
+}
+
+div.input {
+    page-break-inside: avoid;
+}
+
+/* input_area and input_prompt must match in top border and margin for alignment */
+div.input_area {
+    color: black;
+    border: 1px solid #ddd;
+    border-radius: 3px;
+    background: #f7f7f7;
+}
+
+div.input_prompt {
+    color: navy;
+    border-top: 1px solid transparent;
+}
+
+div.output {
+    /* This is a spacer between the input and output of each cell */
+    margin-top: 5px;
+}
+
+div.output_prompt {
+    color: darkred;
+}
+
+/* This class is the outer container of all output sections. */
+div.output_area {
+    padding: 0px;
+    page-break-inside: avoid;
+}
+
+/* This class is for the output subarea inside the output_area and after
+   the prompt div. */
+div.output_subarea {
+    padding: 0.4em 6.1em 0.4em 0.4em;
+}
+
+/* The rest of the output_* classes are for special styling of the different
+   output types */
+
+/* all text output has this class: */
+div.output_text {
+    text-align: left;
+    color: black;
+    font-family: monospace;
+}
+
+/* stdout/stderr are 'text' as well as 'stream', but pyout/pyerr are *not* streams */
+div.output_stream {
+    padding-top: 0.0em;
+    padding-bottom: 0.0em;
+}
+div.output_stdout {
+}
+div.output_stderr {
+    background: #fdd; /* very light red background for stderr */
+}
+
+div.output_latex {
+    text-align: left;
+    color: black;
+}
+
+div.output_html {
+}
+
+div.output_png {
+}
+
+div.output_jpeg {
+}
+
+div.text_cell {
+    background-color: white;
+    padding: 5px 5px 5px 5px;
+}
+
+div.text_cell_input {
+    color: black;
+    border: 1px solid #ddd;
+    border-radius: 3px;
+    background: #f7f7f7;
+}
+
+div.text_cell_render {
+    font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
+    outline: none;
+    resize: none;
+    width:  inherit;
+    border-style: none;
+    padding: 5px;
+    color: black;
+}
+
+.CodeMirror {
+    line-height: 1.231;  /* Changed from 1em to our global default */
+}
+
+.CodeMirror-scroll {
+    height: auto;     /* Changed to auto to autogrow */
+    /*  The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/
+    /*  We have found that if it is visible, vertical scrollbars appear with font size changes.*/
+    overflow-y: hidden;
+    overflow-x: auto; /* Changed from auto to remove scrollbar */
+}
+
+/* CSS font colors for translated ANSI colors. */
+
+
+.ansiblack {color: black;}
+.ansired {color: darkred;}
+.ansigreen {color: darkgreen;}
+.ansiyellow {color: brown;}
+.ansiblue {color: darkblue;}
+.ansipurple {color: darkviolet;}
+.ansicyan {color: steelblue;}
+.ansigrey {color: grey;}
+.ansibold {font-weight: bold;}
+
+.completions , .tooltip {
+    position: absolute;
+    z-index: 10;
+    overflow: auto;
+    border: 1px solid black;
+}
+
+.completions select {
+    background: white;
+    outline: none;
+    border: none;
+    padding: 0px;
+    margin: 0px;
+    font-family: monospace;
+}
+
+ at -moz-keyframes fadeIn {
+    from {opacity:0;}
+    to {opacity:1;}
+}
+
+ at -webkit-keyframes fadeIn {
+    from {opacity:0;}
+    to {opacity:1;}
+}
+
+ at keyframes fadeIn {
+    from {opacity:0;}
+    to {opacity:1;}
+}
+
+/*"close" "expand" and "Open in pager button" of
+/* the tooltip*/
+.tooltip a {
+    float:right;
+}
+
+/*properties of tooltip after "expand"*/
+.bigtooltip {
+    height:30%;
+}
+
+/*properties of tooltip before "expand"*/
+.smalltooltip {
+    text-overflow: ellipsis;
+    overflow: hidden;
+    height:15%;
+}
+
+.tooltip {
+    /*transition when "expand"ing tooltip */
+    -webkit-transition-property: height;
+    -webkit-transition-duration: 1s;
+    -moz-transition-property: height;
+    -moz-transition-duration: 1s;
+    transition-property: height;
+    transition-duration: 1s;
+    max-width:700px;
+    border-radius: 0px 10px 10px 10px;
+    box-shadow: 3px 3px 5px #999;
+    /*fade-in animation when inserted*/
+    -webkit-animation: fadeIn 200ms;
+    -moz-animation: fadeIn 200ms;
+    animation: fadeIn 200ms;
+    vertical-align: middle;
+    background: #FDFDD8;
+    outline: none;
+    padding: 3px;
+    margin: 0px;
+    font-family: monospace;
+    min-height:50px;
+}
+
+/*fixed part of the completion*/
+.completions p b {
+    font-weight:bold;
+}
+
+.completions p {
+    background: #DDF;
+    /*outline: none;
+    padding: 0px;*/
+    border-bottom: black solid 1px;
+    padding: 1px;
+    font-family: monospace;
+}
+
+pre.dialog {
+    background-color: #f7f7f7;
+    border: 1px solid #ddd;
+    border-radius: 3px;
+    padding: 0.4em;
+    padding-left: 2em;
+}
+
+p.dialog {
+    padding : 0.2em;
+}
+
+.shortcut_key {
+    display: inline-block;
+    width: 15ex;
+    text-align: right;
+    font-family: monospace;
+}
+
+.shortcut_descr {
+}
+
+/* Word-wrap output correctly.  This is the CSS3 spelling, though Firefox seems
+   to not honor it correctly.  Webkit browsers (Chrome, rekonq, Safari) do.
+ */
+pre, code, kbd, samp { white-space: pre-wrap; }
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/printnotebook.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/printnotebook.css
new file mode 100644
index 0000000..71bb5a4
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/printnotebook.css
@@ -0,0 +1,5 @@
+body { overflow: visible !important; }
+div#notebook { overflow: visible !important; }
+.ui-widget-content { border: 0px; }
+#save_widget {margin: 0px !important;}
+#header {display: none !important;}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/projectdashboard.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/projectdashboard.css
new file mode 100644
index 0000000..0ca7484
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/projectdashboard.css
@@ -0,0 +1,82 @@
+
+/**
+ * Primary styles
+ *
+ * Author: IPython Development Team
+ */
+
+
+body {
+    background-color: white;
+    /* This makes sure that the body covers the entire window and needs to
+       be in a different element than the display: box in wrapper below */
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 0px;
+    bottom: 0px;
+    overflow: auto;
+}
+
+#left_panel {
+}
+
+#drop_zone {
+    height: 200px;
+    width: 200px
+}
+
+#content_panel {
+    width: 600px;
+}
+
+#content_toolbar {
+    padding: 5px;
+    height: 25px;
+    line-height: 25px;
+}
+
+#header_border {
+    width: 100%;
+    height: 2px;
+}
+
+#app_hbox {
+    width: 100%;
+}
+
+#drag_info {
+    float: left;
+}
+
+#notebooks_buttons {
+    float: right;
+}
+
+#project_name {
+    height: 25px;
+    line-height: 25px;
+    padding: 3px;
+}
+
+.notebook_item {
+    height: 25px;
+    line-height: 25px;
+    padding: 3px;
+}
+
+.notebook_item a {
+    text-decoration: none;
+}
+
+.item_buttons {
+    float: right;
+}
+
+.item_buttons .upload_button {
+    color: darkred;
+}
+
+.highlight_text {
+    color: blue;
+}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/renderedhtml.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/renderedhtml.css
new file mode 100644
index 0000000..e84beb3
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/css/renderedhtml.css
@@ -0,0 +1,63 @@
+.rendered_html {color: black;}
+.rendered_html em {font-style: italic;}
+.rendered_html strong {font-weight: bold;}
+.rendered_html u {text-decoration: underline;}
+.rendered_html :link { text-decoration: underline }
+.rendered_html :visited { text-decoration: underline }
+.rendered_html h1 {font-size: 197%; margin: .65em 0; font-weight: bold;}
+.rendered_html h2 {font-size: 153.9%; margin: .75em 0; font-weight: bold;}
+.rendered_html h3 {font-size: 123.1%; margin: .85em 0; font-weight: bold;}
+.rendered_html h4 {font-size: 100% margin: 0.95em 0; font-weight: bold;}
+.rendered_html h5 {font-size: 85%; margin: 1.5em 0; font-weight: bold;}
+.rendered_html h6 {font-size: 77%; margin: 1.65em 0; font-weight: bold;}
+.rendered_html ul {list-style:disc; margin: 1em 2em;}
+.rendered_html ul ul {list-style:square; margin: 0em 2em;}
+.rendered_html ul ul ul {list-style:circle; margin-left: 0em 2em;}
+.rendered_html ol {list-style:upper-roman; margin: 1em 2em;}
+.rendered_html ol ol {list-style:upper-alpha; margin: 0em 2em;}
+.rendered_html ol ol ol {list-style:decimal; margin: 0em 2em;}
+.rendered_html ol ol ol ol {list-style:lower-alpha; margin 0em 2em;}
+.rendered_html ol ol ol ol ol {list-style:lower-roman; 0em 2em;}
+
+.rendered_html hr {
+    color: black;
+    background-color: black;
+}
+
+.rendered_html pre {
+    margin: 1em 2em;
+}
+
+.rendered_html blockquote {
+    margin: 1em 2em;
+}
+
+.rendered_html table {
+    border: 1px solid black;
+    border-collapse: collapse;
+    margin: 1em 2em;
+}
+
+.rendered_html td {
+    border: 1px solid black;
+    text-align: left;
+    vertical-align: middle;
+    padding: 4px;
+}
+
+.rendered_html th {
+    border: 1px solid black;
+    text-align: left;
+    vertical-align: middle;
+    padding: 4px;
+    font-weight: bold;
+}
+
+.rendered_html tr {
+    border: 1px solid black;
+}    
+
+.rendered_html p + p {
+    margin-top: 1em;
+}
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/dateformat/date.format.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/dateformat/date.format.js
new file mode 100644
index 0000000..25daaa5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/dateformat/date.format.js
@@ -0,0 +1,125 @@
+/*
+ * Date Format 1.2.3
+ * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
+ * MIT license
+ *
+ * Includes enhancements by Scott Trenda <scott.trenda.net>
+ * and Kris Kowal <cixar.com/~kris.kowal/>
+ *
+ * Accepts a date, a mask, or a date and a mask.
+ * Returns a formatted version of the given date.
+ * The date defaults to the current date/time.
+ * The mask defaults to dateFormat.masks.default.
+ */
+
+var dateFormat = function () {
+    var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
+        timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
+        timezoneClip = /[^-+\dA-Z]/g,
+        pad = function (val, len) {
+            val = String(val);
+            len = len || 2;
+            while (val.length < len) val = "0" + val;
+            return val;
+        };
+
+    // Regexes and supporting functions are cached through closure
+    return function (date, mask, utc) {
+        var dF = dateFormat;
+
+        // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
+        if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
+            mask = date;
+            date = undefined;
+        }
+
+        // Passing date through Date applies Date.parse, if necessary
+        date = date ? new Date(date) : new Date;
+        if (isNaN(date)) throw SyntaxError("invalid date");
+
+        mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+
+        // Allow setting the utc argument via the mask
+        if (mask.slice(0, 4) == "UTC:") {
+            mask = mask.slice(4);
+            utc = true;
+        }
+
+        var _ = utc ? "getUTC" : "get",
+            d = date[_ + "Date"](),
+            D = date[_ + "Day"](),
+            m = date[_ + "Month"](),
+            y = date[_ + "FullYear"](),
+            H = date[_ + "Hours"](),
+            M = date[_ + "Minutes"](),
+            s = date[_ + "Seconds"](),
+            L = date[_ + "Milliseconds"](),
+            o = utc ? 0 : date.getTimezoneOffset(),
+            flags = {
+                d:    d,
+                dd:   pad(d),
+                ddd:  dF.i18n.dayNames[D],
+                dddd: dF.i18n.dayNames[D + 7],
+                m:    m + 1,
+                mm:   pad(m + 1),
+                mmm:  dF.i18n.monthNames[m],
+                mmmm: dF.i18n.monthNames[m + 12],
+                yy:   String(y).slice(2),
+                yyyy: y,
+                h:    H % 12 || 12,
+                hh:   pad(H % 12 || 12),
+                H:    H,
+                HH:   pad(H),
+                M:    M,
+                MM:   pad(M),
+                s:    s,
+                ss:   pad(s),
+                l:    pad(L, 3),
+                L:    pad(L > 99 ? Math.round(L / 10) : L),
+                t:    H < 12 ? "a"  : "p",
+                tt:   H < 12 ? "am" : "pm",
+                T:    H < 12 ? "A"  : "P",
+                TT:   H < 12 ? "AM" : "PM",
+                Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
+                o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+                S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+            };
+
+        return mask.replace(token, function ($0) {
+            return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+        });
+    };
+}();
+
+// Some common format strings
+dateFormat.masks = {
+    "default":      "ddd mmm dd yyyy HH:MM:ss",
+    shortDate:      "m/d/yy",
+    mediumDate:     "mmm d, yyyy",
+    longDate:       "mmmm d, yyyy",
+    fullDate:       "dddd, mmmm d, yyyy",
+    shortTime:      "h:MM TT",
+    mediumTime:     "h:MM:ss TT",
+    longTime:       "h:MM:ss TT Z",
+    isoDate:        "yyyy-mm-dd",
+    isoTime:        "HH:MM:ss",
+    isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
+    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
+};
+
+// Internationalization strings
+dateFormat.i18n = {
+    dayNames: [
+        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+    ],
+    monthNames: [
+        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+        "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+    ]
+};
+
+// For convenience...
+Date.prototype.format = function (mask, utc) {
+    return dateFormat(this, mask, utc);
+};
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/favicon.ico b/PyTango/ipython/ipython_00_12/examples/notebooks/static/favicon.ico
new file mode 100644
index 0000000..7793294
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/favicon.ico differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/ipynblogo.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ipynblogo.png
new file mode 100644
index 0000000..f7c7dd4
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/ipynblogo.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000..5b5dab2
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_flat_75_ffffff_40x100.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000..ac8b229
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 0000000..ad3d634
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000..42ccba2
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000..5a46b47
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 0000000..86c2baa
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000..4443fdc
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 0000000..7c9fa6c
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_222222_256x240.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_222222_256x240.png
new file mode 100644
index 0000000..ee039dc
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_222222_256x240.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_2e83ff_256x240.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000..45e8928
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_2e83ff_256x240.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_454545_256x240.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_454545_256x240.png
new file mode 100644
index 0000000..7ec70d1
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_454545_256x240.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_888888_256x240.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_888888_256x240.png
new file mode 100644
index 0000000..5ba708c
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_888888_256x240.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_cd0a0a_256x240.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000..7930a55
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/jquery-ui.min.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/jquery-ui.min.css
new file mode 100644
index 0000000..82752b5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/css/themes/base/jquery-ui.min.css
@@ -0,0 +1 @@
+.ui-helper-hidden{display:none;}.ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none;}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;}.ui-helper-clearfix:after{clear:both;}.ui-helper-clearfix{zoom:1;}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0 [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery-1.7.1.min.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery-1.7.1.min.js
new file mode 100644
index 0000000..198b3ff
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery-1.7.1.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.1 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement( [...]
+f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]| [...]
+{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replac [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery-ui.min.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery-ui.min.js
new file mode 100644
index 0000000..1365ee1
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery-ui.min.js
@@ -0,0 +1,16 @@
+/*!
+ * jQuery UI @VERSION
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI
+ */(function(a,b){function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;if(!b.href||!g||f.nodeName.toLowerCase()!=="map")return!1;h=a("img[usemap=#"+g+"]")[0];return!!h&&d(h)}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}a.ui=a.ui||{};a.ui.version||(a.extend(a. [...]
+[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&& [...]
+[c].containerCache.over=0)}this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem));return this},serialize:function(b){var c=this._getItemsAsjQ [...]
+a.effects.setMode(d,b.mode||"show"),g={backgroundColor:d.css("backgroundColor")};f==="hide"&&(g.opacity=0),a.effects.save(d,e),d.show().css({backgroundImage:"none",backgroundColor:b.color||"#ffff99"}).animate(g,{queue:!1,duration:b.duration,easing:b.easing,complete:function(){f==="hide"&&d.hide(),a.effects.restore(d,e),c()}})}}(jQuery),function(a,b){a.effects.effect.pulsate=function(b,c){var d=a(this),e=a.effects.setMode(d,b.mode||"show"),f=e==="show",g=e==="hide",h=f||e==="hide",i=(b.ti [...]
+))}$.extend($.ui,{datepicker:{version:"@VERSION"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){extendRemove(this._defaults,a||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=tar [...]
+,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototyp [...]
+(),i=b.top-c.collisionPosition.marginTop,j=g-i,k=i+c.collisionHeight-h-g,l,m;c.collisionHeight>h?j>0&&k<=0?(m=b.top+j+c.collisionHeight-h-g,b.top+=j-m):k>0&&j<=0?b.top=g:j>k?b.top=g+h-c.collisionHeight:b.top=g:j>0?b.top+=j:k>0?b.top-=k:b.top=Math.max(b.top-i,b.top)}},flip:{left:function(b,c){if(c.at[0]!==h){c.elem.removeClass("ui-flipped-left ui-flipped-right");var d=c.within,e=a(window),f=a.isWindow(c.within[0]),g=(f?0:d.offset().left)+d.scrollLeft(),i=f?d.width():d.outerWidth(),j=b.lef [...]
+.options.selected;else return;this.anchors.eq(a).trigger(this.options.event+".tabs")}}(jQuery,jQuery.ui.tabs.prototype);var f=0;function g(){return++f}a.widget("ui.tabs",a.ui.tabs,{options:{cookie:null},_create:function(){var a=this.options,b;a.active==null&&a.cookie&&(b=parseInt(this._cookie(),10),b===-1&&(b=!1),a.active=b),this._super()},_cookie:function(b){var c=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+g())];arguments.length&&(c.push(b===!1?-1:b),c.push(this.opt [...]
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery.autogrow.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery.autogrow.js
new file mode 100644
index 0000000..15f0d35
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/jquery/js/jquery.autogrow.js
@@ -0,0 +1,42 @@
+/*
+ * Auto Grow Textarea Plugin
+ * by Jevin 5/11/2010
+ * http://www.technoreply.com/autogrow-textarea-plugin/
+ *
+ * Modified by Rob G (aka Fudgey/Mottie)
+ *  - Converted into a plugin
+ *  - Added ability to calculate approximate # cols when textarea is set to 100%
+ *
+ * Simplified by Brian Granger on 5/2/2011
+ */
+
+(function($) {
+    $.fn.autogrow = function() {
+
+    var grow = function(d) {
+        var linesCount = 0;
+        // modified split rule from
+        // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
+        var lines = d.txt.value.split(/\r|\r\n|\n/);
+        linesCount = lines.length;
+        if (linesCount >= d.rowsDefault) {
+            d.txt.rows = linesCount;
+        } else {
+            d.txt.rows = d.rowsDefault;
+        }
+    };
+
+    return this.each(function() {
+        var d = {
+            colsDefault : 0,
+            rowsDefault : 1,
+            txt         : this,
+            $txt        : $(this)
+        };
+        d.txt.onkeyup = function() {
+            grow(d);
+        };
+        grow(d);
+    });
+};
+})(jQuery);
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/cell.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/cell.js
new file mode 100644
index 0000000..e24be0e
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/cell.js
@@ -0,0 +1,150 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Cell
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+
+    var Cell = function (notebook) {
+        this.placeholder = this.placeholder || '';
+        this.notebook = notebook;
+        this.read_only = false;
+        if (notebook){
+            this.read_only = notebook.read_only;
+        }
+        this.selected = false;
+        this.element = null;
+        this.create_element();
+        if (this.element !== null) {
+            this.element.data("cell", this);
+            this.bind_events();
+        }
+        this.cell_id = utils.uuid();
+    };
+
+
+    // Subclasses must implement create_element.
+    Cell.prototype.create_element = function () {};
+
+
+    Cell.prototype.bind_events = function () {
+        var that = this;
+        var nb = that.notebook;
+        that.element.click(function (event) {
+            if (that.selected === false) {
+                nb.select(nb.find_cell_index(that));
+            }
+        });
+        that.element.focusin(function (event) {
+            if (that.selected === false) {
+                nb.select(nb.find_cell_index(that));
+            }
+        });
+    };
+
+
+    // typeset with MathJax if MathJax is available
+    Cell.prototype.typeset = function () {
+        if (window.MathJax){
+            MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
+        }
+    };
+
+
+    Cell.prototype.select = function () {
+        this.element.addClass('ui-widget-content ui-corner-all');
+        this.selected = true;
+    };
+
+
+    Cell.prototype.unselect = function () {
+        this.element.removeClass('ui-widget-content ui-corner-all');
+        this.selected = false;
+    };
+
+
+    Cell.prototype.get_text = function () {
+    };
+
+
+    Cell.prototype.set_text = function (text) {
+    };
+
+
+    Cell.prototype.refresh = function () {
+        this.code_mirror.refresh();
+    };
+
+
+    Cell.prototype.edit = function () {
+    };
+
+
+    Cell.prototype.render = function () {
+    };
+
+
+    Cell.prototype.toJSON = function () {
+    };
+
+
+    Cell.prototype.fromJSON = function (data) {
+    };
+
+
+    Cell.prototype.is_splittable = function () {
+        return true;
+    };
+
+
+    Cell.prototype.get_pre_cursor = function () {
+        var cursor = this.code_mirror.getCursor();
+        var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
+        text = text.replace(/^\n+/, '').replace(/\n+$/, '');
+        return text;
+    }
+
+
+    Cell.prototype.get_post_cursor = function () {
+        var cursor = this.code_mirror.getCursor();
+        var last_line_num = this.code_mirror.lineCount()-1;
+        var last_line_len = this.code_mirror.getLine(last_line_num).length;
+        var end = {line:last_line_num, ch:last_line_len}
+        var text = this.code_mirror.getRange(cursor, end);
+        text = text.replace(/^\n+/, '').replace(/\n+$/, '');
+        return text;
+    };
+
+
+    Cell.prototype.grow = function(element) {
+        // Grow the cell by hand. This is used upon reloading from JSON, when the
+        // autogrow handler is not called.
+        var dom = element.get(0);
+        var lines_count = 0;
+        // modified split rule from
+        // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
+        var lines = dom.value.split(/\r|\r\n|\n/);
+        lines_count = lines.length;
+        if (lines_count >= 1) {
+            dom.rows = lines_count;
+        } else {
+            dom.rows = 1;
+        }
+    };
+
+
+    IPython.Cell = Cell;
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/codecell.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/codecell.js
new file mode 100644
index 0000000..55ecda5
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/codecell.js
@@ -0,0 +1,850 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// CodeCell
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+    var CodeCell = function (notebook) {
+        this.code_mirror = null;
+        this.input_prompt_number = ' ';
+        this.is_completing = false;
+        this.completion_cursor = null;
+        this.outputs = [];
+        this.collapsed = false;
+        this.tooltip_timeout = null;
+        IPython.Cell.apply(this, arguments);
+    };
+
+
+    CodeCell.prototype = new IPython.Cell();
+
+
+    CodeCell.prototype.create_element = function () {
+        var cell =  $('<div></div>').addClass('cell border-box-sizing code_cell vbox');
+        cell.attr('tabindex','2');
+        var input = $('<div></div>').addClass('input hbox');
+        input.append($('<div/>').addClass('prompt input_prompt'));
+        var input_area = $('<div/>').addClass('input_area box-flex1');
+        this.code_mirror = CodeMirror(input_area.get(0), {
+            indentUnit : 4,
+            mode: 'python',
+            theme: 'ipython',
+            readOnly: this.read_only,
+            onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
+        });
+        input.append(input_area);
+        var output = $('<div></div>').addClass('output vbox');
+        cell.append(input).append(output);
+        this.element = cell;
+        this.collapse();
+    };
+
+    //TODO, try to diminish the number of parameters.
+    CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time){
+        var that = this;
+        if (pre_cursor === "" || pre_cursor === "(" ) {
+            // don't do anything if line beggin with '(' or is empty
+        } else {
+            // Will set a timer to request tooltip in `time`
+            that.tooltip_timeout = setTimeout(function(){
+                    IPython.notebook.request_tool_tip(that, pre_cursor)
+                },time);
+        }
+    };
+
+    CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) {
+        // This method gets called in CodeMirror's onKeyDown/onKeyPress
+        // handlers and is used to provide custom key handling. Its return
+        // value is used to determine if CodeMirror should ignore the event:
+        // true = ignore, false = don't ignore.
+        
+        if (this.read_only){
+            return false;
+        }
+
+        // note that we are comparing and setting the time to wait at each key press.
+        // a better wqy might be to generate a new function on each time change and
+        // assign it to CodeCell.prototype.request_tooltip_after_time
+        tooltip_wait_time = this.notebook.time_before_tooltip;
+        tooltip_on_tab    = this.notebook.tooltip_on_tab;
+        var that = this;
+        // whatever key is pressed, first, cancel the tooltip request before
+        // they are sent, and remove tooltip if any
+        if(event.type === 'keydown' ){
+            that.remove_and_cancel_tooltip();
+        }
+
+        if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
+            // Always ignore shift-enter in CodeMirror as we handle it.
+            return true;
+        } else if (event.which === 40 && event.type === 'keypress' && tooltip_wait_time >= 0) {
+            // triger aon keypress (!) otherwise inconsistent event.which depending on plateform
+            // browser and keyboard layout !
+            // Pressing '(' , request tooltip, don't forget to reappend it
+            var cursor = editor.getCursor();
+            var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'(';
+            that.request_tooltip_after_time(pre_cursor,tooltip_wait_time);
+        } else if (event.which === 38) {
+            // If we are not at the top, let CM handle the up arrow and
+            // prevent the global keydown handler from handling it.
+            if (!that.at_top()) {
+                event.stop();
+                return false;
+            } else {
+                return true; 
+            };
+        } else if (event.which === 40) {
+            // If we are not at the bottom, let CM handle the down arrow and
+            // prevent the global keydown handler from handling it.
+            if (!that.at_bottom()) {
+                event.stop();
+                return false;
+            } else {
+                return true; 
+            };
+        } else if (event.keyCode === 9 && event.type == 'keydown') {
+            // Tab completion.
+            var cur = editor.getCursor();
+            //Do not trim here because of tooltip
+            var pre_cursor = editor.getRange({line:cur.line,ch:0},cur);
+            if (pre_cursor.trim() === "") {
+                // Don't autocomplete if the part of the line before the cursor
+                // is empty.  In this case, let CodeMirror handle indentation.
+                return false;
+            } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) {
+                that.request_tooltip_after_time(pre_cursor,0);
+            } else {
+                pre_cursor.trim();
+                // Autocomplete the current line.
+                event.stop();
+                var line = editor.getLine(cur.line);
+                this.is_completing = true;
+                this.completion_cursor = cur;
+                IPython.notebook.complete_cell(this, line, cur.ch);
+                return true;
+            }
+        } else if (event.keyCode === 8 && event.type == 'keydown') {
+            // If backspace and the line ends with 4 spaces, remove them.
+            var cur = editor.getCursor();
+            var line = editor.getLine(cur.line);
+            var ending = line.slice(-4);
+            if (ending === '    ') {
+                editor.replaceRange('',
+                    {line: cur.line, ch: cur.ch-4},
+                    {line: cur.line, ch: cur.ch}
+                );
+                event.stop();
+                return true;
+            } else {
+                return false;
+            }
+        } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey
+                   && event.type == 'keydown') {
+            // toggle line numbers with Ctrl-Shift-L
+            this.toggle_line_numbers();
+        }
+        else {
+            // keypress/keyup also trigger on TAB press, and we don't want to
+            // use those to disable tab completion.
+            if (this.is_completing && event.keyCode !== 9) {
+                var ed_cur = editor.getCursor();
+                var cc_cur = this.completion_cursor;
+                if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) {
+                    this.is_completing = false;
+                    this.completion_cursor = null;
+                }
+            }
+            return false;
+        };
+        return false;
+    };
+
+    CodeCell.prototype.remove_and_cancel_tooltip = function() {
+        // note that we don't handle closing directly inside the calltip
+        // as in the completer, because it is not focusable, so won't
+        // get the event.
+        if (this.tooltip_timeout != null){
+            clearTimeout(this.tooltip_timeout);
+            $('#tooltip').remove();
+            this.tooltip_timeout = null;
+        }
+    }
+
+    CodeCell.prototype.finish_tooltip = function (reply) {
+        // Extract call tip data; the priority is call, init, main.
+        defstring = reply.call_def;
+        if (defstring == null) { defstring = reply.init_definition; }
+        if (defstring == null) { defstring = reply.definition; }
+
+        docstring = reply.call_docstring;
+        if (docstring == null) { docstring = reply.init_docstring; }
+        if (docstring == null) { docstring = reply.docstring; }
+        if (docstring == null) { docstring = "<empty docstring>"; }
+
+        name=reply.name;
+
+        var that = this;
+        var tooltip = $('<div/>').attr('id', 'tooltip').addClass('tooltip');
+        // remove to have the tooltip not Limited in X and Y
+        tooltip.addClass('smalltooltip');
+        var pre=$('<pre/>').html(utils.fixConsole(docstring));
+        var expandlink=$('<a/>').attr('href',"#");
+            expandlink.addClass("ui-corner-all"); //rounded corner
+            expandlink.attr('role',"button");
+            //expandlink.addClass('ui-button');
+            //expandlink.addClass('ui-state-default');
+        var expandspan=$('<span/>').text('Expand');
+            expandspan.addClass('ui-icon');
+            expandspan.addClass('ui-icon-plus');
+        expandlink.append(expandspan);
+        expandlink.attr('id','expanbutton');
+        expandlink.click(function(){
+            tooltip.removeClass('smalltooltip');
+            tooltip.addClass('bigtooltip');
+            $('#expanbutton').remove();
+            setTimeout(function(){that.code_mirror.focus();}, 50);
+        });
+        var morelink=$('<a/>').attr('href',"#");
+            morelink.attr('role',"button");
+            morelink.addClass('ui-button');
+            //morelink.addClass("ui-corner-all"); //rounded corner
+            //morelink.addClass('ui-state-default');
+        var morespan=$('<span/>').text('Open in Pager');
+            morespan.addClass('ui-icon');
+            morespan.addClass('ui-icon-arrowstop-l-n');
+        morelink.append(morespan);
+        morelink.click(function(){
+            var msg_id = IPython.notebook.kernel.execute(name+"?");
+            IPython.notebook.msg_cell_map[msg_id] = IPython.notebook.selected_cell().cell_id;
+            that.remove_and_cancel_tooltip();
+            setTimeout(function(){that.code_mirror.focus();}, 50);
+        });
+
+        var closelink=$('<a/>').attr('href',"#");
+            closelink.attr('role',"button");
+            closelink.addClass('ui-button');
+            //closelink.addClass("ui-corner-all"); //rounded corner
+            //closelink.adClass('ui-state-default'); // grey background and blue cross
+        var closespan=$('<span/>').text('Close');
+            closespan.addClass('ui-icon');
+            closespan.addClass('ui-icon-close');
+        closelink.append(closespan);
+        closelink.click(function(){
+            that.remove_and_cancel_tooltip();
+            setTimeout(function(){that.code_mirror.focus();}, 50);
+            });
+        //construct the tooltip
+        tooltip.append(closelink);
+        tooltip.append(expandlink);
+        tooltip.append(morelink);
+        if(defstring){
+            defstring_html = $('<pre/>').html(utils.fixConsole(defstring));
+            tooltip.append(defstring_html);
+        }
+        tooltip.append(pre);
+        var pos = this.code_mirror.cursorCoords();
+        tooltip.css('left',pos.x+'px');
+        tooltip.css('top',pos.yBot+'px');
+        $('body').append(tooltip);
+
+        // issues with cross-closing if multiple tooltip in less than 5sec
+        // keep it comented for now
+        // setTimeout(that.remove_and_cancel_tooltip, 5000);
+    };
+
+    // As you type completer
+    CodeCell.prototype.finish_completing = function (matched_text, matches) {
+        //return if not completing or nothing to complete
+        if (!this.is_completing || matches.length === 0) {return;}
+
+        // for later readability
+        var key = { tab:9,
+                    esc:27,
+                    backspace:8,
+                    space:32,
+                    shift:16,
+                    enter:13,
+                    // _ is 95
+                    isCompSymbol : function (code)
+                        {
+                        return (code > 64 && code <= 90)
+                            || (code >= 97 && code <= 122)
+                            || (code == 95)
+                        },
+                    dismissAndAppend : function (code)
+                        {
+                        chararr = '()[]+-/\\. ,=*'.split("");
+                        codearr = chararr.map(function(x){return x.charCodeAt(0)});
+                        return jQuery.inArray(code, codearr) != -1;
+                        }
+
+                    }
+
+        // smart completion, sort kwarg ending with '='
+        var newm = new Array();
+        if(this.notebook.smart_completer)
+        {
+            kwargs = new Array();
+            other = new Array();
+            for(var i = 0 ; i<matches.length ; ++i){
+                if(matches[i].substr(-1) === '='){
+                    kwargs.push(matches[i]);
+                }else{other.push(matches[i]);}
+            }
+            newm = kwargs.concat(other);
+            matches = newm;
+        }
+        // end sort kwargs
+
+        // give common prefix of a array of string
+        function sharedStart(A){
+            if(A.length == 1){return A[0]}
+            if(A.length > 1 ){
+                var tem1, tem2, s, A = A.slice(0).sort();
+                tem1 = A[0];
+                s = tem1.length;
+                tem2 = A.pop();
+                while(s && tem2.indexOf(tem1) == -1){
+                    tem1 = tem1.substring(0, --s);
+                }
+                return tem1;
+            }
+            return "";
+        }
+
+
+        //try to check if the user is typing tab at least twice after a word
+        // and completion is "done"
+        fallback_on_tooltip_after = 2
+        if(matches.length == 1 && matched_text === matches[0])
+        {
+            if(this.npressed >fallback_on_tooltip_after  && this.prevmatch==matched_text)
+            {
+                this.request_tooltip_after_time(matched_text+'(',0);
+                return;
+            }
+            this.prevmatch = matched_text
+            this.npressed = this.npressed+1;
+        }
+        else
+        {
+            this.prevmatch = "";
+            this.npressed = 0;
+        }
+        // end fallback on tooltip
+        //==================================
+        // Real completion logic start here
+        var that = this;
+        var cur = this.completion_cursor;
+        var done = false;
+
+        // call to dismmiss the completer
+        var close = function () {
+            if (done) return;
+            done = true;
+            if (complete != undefined)
+            {complete.remove();}
+            that.is_completing = false;
+            that.completion_cursor = null;
+        };
+
+        // update codemirror with the typed text
+        prev = matched_text
+        var update = function (inserted_text, event) {
+            that.code_mirror.replaceRange(
+                inserted_text,
+                {line: cur.line, ch: (cur.ch-matched_text.length)},
+                {line: cur.line, ch: (cur.ch+prev.length-matched_text.length)}
+            );
+            prev = inserted_text
+            if(event != null){
+                event.stopPropagation();
+                event.preventDefault();
+            }
+        };
+        // insert the given text and exit the completer
+        var insert = function (selected_text, event) {
+            update(selected_text)
+            close();
+            setTimeout(function(){that.code_mirror.focus();}, 50);
+        };
+
+        // insert the curent highlited selection and exit
+        var pick = function () {
+            insert(select.val()[0],null);
+        };
+
+
+        // Define function to clear the completer, refill it with the new
+        // matches, update the pseuso typing field. autopick insert match if
+        // only one left, in no matches (anymore) dismiss itself by pasting
+        // what the user have typed until then
+        var complete_with = function(matches,typed_text,autopick,event)
+        {
+            // If autopick an only one match, past.
+            // Used to 'pick' when pressing tab
+            if (matches.length < 1) {
+                insert(typed_text,event);
+                if(event != null){
+                event.stopPropagation();
+                event.preventDefault();
+                }
+            } else if (autopick && matches.length == 1) {
+                insert(matches[0],event);
+                if(event != null){
+                event.stopPropagation();
+                event.preventDefault();
+                }
+            }
+            //clear the previous completion if any
+            update(typed_text,event);
+            complete.children().children().remove();
+            $('#asyoutype').html("<b>"+matched_text+"</b>"+typed_text.substr(matched_text.length));
+            select = $('#asyoutypeselect');
+            for (var i = 0; i<matches.length; ++i) {
+                    select.append($('<option/>').html(matches[i]));
+            }
+            select.children().first().attr('selected','true');
+        }
+
+        // create html for completer
+        var complete = $('<div/>').addClass('completions');
+            complete.attr('id','complete');
+        complete.append($('<p/>').attr('id', 'asyoutype').html('<b>fixed part</b>user part'));//pseudo input field
+
+        var select = $('<select/>').attr('multiple','true');
+            select.attr('id', 'asyoutypeselect')
+            select.attr('size',Math.min(10,matches.length));
+        var pos = this.code_mirror.cursorCoords();
+
+        // TODO: I propose to remove enough horizontal pixel
+        // to align the text later
+        complete.css('left',pos.x+'px');
+        complete.css('top',pos.yBot+'px');
+        complete.append(select);
+
+        $('body').append(complete);
+
+        // So a first actual completion.  see if all the completion start wit
+        // the same letter and complete if necessary
+        fastForward = sharedStart(matches)
+        typed_characters = fastForward.substr(matched_text.length);
+        complete_with(matches,matched_text+typed_characters,true,null);
+        filterd = matches;
+        // Give focus to select, and make it filter the match as the user type
+        // by filtering the previous matches. Called by .keypress and .keydown
+        var downandpress = function (event,press_or_down) {
+            var code = event.which;
+            var autopick = false; // auto 'pick' if only one match
+            if (press_or_down === 0){
+                press = true; down = false; //Are we called from keypress or keydown
+            } else if (press_or_down == 1){
+                press = false; down = true;
+            }
+            if (code === key.shift) {
+                // nothing on Shift
+                return;
+            }
+            if (key.dismissAndAppend(code) && press) {
+                var newchar = String.fromCharCode(code);
+                typed_characters = typed_characters+newchar;
+                insert(matched_text+typed_characters,event);
+                return
+            }
+            if (code === key.enter) {
+                // Pressing ENTER will cause a pick
+                event.stopPropagation();
+                event.preventDefault();
+                pick();
+            } else if (code === 38 || code === 40) {
+                // We don't want the document keydown handler to handle UP/DOWN,
+                // but we want the default action.
+                event.stopPropagation();
+            } else if ( (code == key.backspace)||(code == key.tab && down) || press  || key.isCompSymbol(code)){
+                if( key.isCompSymbol(code) && press)
+                {
+                    var newchar = String.fromCharCode(code);
+                    typed_characters = typed_characters+newchar;
+                } else if (code == key.tab) {
+                    fastForward = sharedStart(filterd)
+                    ffsub = fastForward.substr(matched_text.length+typed_characters.length);
+                    typed_characters = typed_characters+ffsub;
+                    autopick = true;
+                } else if (code == key.backspace && down) {
+                    // cancel if user have erase everything, otherwise decrease
+                    // what we filter with
+                    event.preventDefault();
+                    if (typed_characters.length <= 0)
+                    {
+                        insert(matched_text,event)
+                        return
+                    }
+                    typed_characters = typed_characters.substr(0,typed_characters.length-1);
+                } else if (press && code != key.backspace && code != key.tab && code != 0){
+                    insert(matched_text+typed_characters,event);
+                    return
+                } else {
+                    return
+                }
+                re = new RegExp("^"+"\%?"+matched_text+typed_characters,"");
+                filterd = matches.filter(function(x){return re.test(x)});
+                complete_with(filterd,matched_text+typed_characters,autopick,event);
+            } else if (code == key.esc) {
+                // dismiss the completer and go back to before invoking it
+                insert(matched_text,event);
+            } else if (press) { // abort only on .keypress or esc
+            }
+        }
+        select.keydown(function (event) {
+            downandpress(event,1)
+        });
+        select.keypress(function (event) {
+            downandpress(event,0)
+        });
+        // Double click also causes a pick.
+        // and bind the last actions.
+        select.dblclick(pick);
+        select.blur(close);
+        select.focus();
+    };
+
+
+    CodeCell.prototype.toggle_line_numbers = function () {
+        if (this.code_mirror.getOption('lineNumbers') == false) {
+            this.code_mirror.setOption('lineNumbers', true);
+        } else {
+            this.code_mirror.setOption('lineNumbers', false);
+        }
+        this.code_mirror.refresh();
+    };
+
+
+    CodeCell.prototype.select = function () {
+        IPython.Cell.prototype.select.apply(this);
+        // In some cases (inserting a new cell) we need a refresh before and
+        // after the focus. Not sure why this is the case.
+        this.code_mirror.refresh();
+        this.code_mirror.focus();
+        this.code_mirror.refresh();
+    };
+
+
+    CodeCell.prototype.select_all = function () {
+        var start = {line: 0, ch: 0};
+        var nlines = this.code_mirror.lineCount();
+        var last_line = this.code_mirror.getLine(nlines-1);
+        var end = {line: nlines-1, ch: last_line.length};
+        this.code_mirror.setSelection(start, end);
+    };
+
+
+    CodeCell.prototype.append_output = function (json) {
+        this.expand();
+        if (json.output_type === 'pyout') {
+            this.append_pyout(json);
+        } else if (json.output_type === 'pyerr') {
+            this.append_pyerr(json);
+        } else if (json.output_type === 'display_data') {
+            this.append_display_data(json);
+        } else if (json.output_type === 'stream') {
+            this.append_stream(json);
+        };
+        this.outputs.push(json);
+    };
+
+
+    CodeCell.prototype.create_output_area = function () {
+        var oa = $("<div/>").addClass("hbox output_area");
+        oa.append($('<div/>').addClass('prompt'));
+        return oa;
+    };
+
+
+    CodeCell.prototype.append_pyout = function (json) {
+        n = json.prompt_number || ' ';
+        var toinsert = this.create_output_area();
+        toinsert.find('div.prompt').addClass('output_prompt').html('Out[' + n + ']:');
+        this.append_mime_type(json, toinsert);
+        this.element.find('div.output').append(toinsert);
+        // If we just output latex, typeset it.
+        if ((json.latex !== undefined) || (json.html !== undefined)) {
+            this.typeset();
+        };
+    };
+
+
+    CodeCell.prototype.append_pyerr = function (json) {
+        var tb = json.traceback;
+        if (tb !== undefined && tb.length > 0) {
+            var s = '';
+            var len = tb.length;
+            for (var i=0; i<len; i++) {
+                s = s + tb[i] + '\n';
+            }
+            s = s + '\n';
+            var toinsert = this.create_output_area();
+            this.append_text(s, toinsert);
+            this.element.find('div.output').append(toinsert);
+        };
+    };
+
+
+    CodeCell.prototype.append_stream = function (json) {
+        // temporary fix: if stream undefined (json file written prior to this patch),
+        // default to most likely stdout:
+        if (json.stream == undefined){
+            json.stream = 'stdout';
+        }
+        var subclass = "output_"+json.stream;
+        if (this.outputs.length > 0){
+            // have at least one output to consider
+            var last = this.outputs[this.outputs.length-1];
+            if (last.output_type == 'stream' && json.stream == last.stream){
+                // latest output was in the same stream,
+                // so append directly into its pre tag
+                this.element.find('div.'+subclass).last().find('pre').append(json.text);
+                return;
+            }
+        }
+        
+        // If we got here, attach a new div
+        var toinsert = this.create_output_area();
+        this.append_text(json.text, toinsert, "output_stream "+subclass);
+        this.element.find('div.output').append(toinsert);
+    };
+
+
+    CodeCell.prototype.append_display_data = function (json) {
+        var toinsert = this.create_output_area();
+        this.append_mime_type(json, toinsert);
+        this.element.find('div.output').append(toinsert);
+        // If we just output latex, typeset it.
+        if ( (json.latex !== undefined) || (json.html !== undefined) ) {
+            this.typeset();
+        };
+    };
+
+
+    CodeCell.prototype.append_mime_type = function (json, element) {
+        if (json.html !== undefined) {
+            this.append_html(json.html, element);
+        } else if (json.latex !== undefined) {
+            this.append_latex(json.latex, element);
+        } else if (json.svg !== undefined) {
+            this.append_svg(json.svg, element);
+        } else if (json.png !== undefined) {
+            this.append_png(json.png, element);
+        } else if (json.jpeg !== undefined) {
+            this.append_jpeg(json.jpeg, element);
+        } else if (json.text !== undefined) {
+            this.append_text(json.text, element);
+        };
+    };
+
+
+    CodeCell.prototype.append_html = function (html, element) {
+        var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_html rendered_html");
+        toinsert.append(html);
+        element.append(toinsert);
+    };
+
+
+    CodeCell.prototype.append_text = function (data, element, extra_class) {
+        var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_text");
+        if (extra_class){
+            toinsert.addClass(extra_class);
+        }
+        toinsert.append($("<pre/>").html(data));
+        element.append(toinsert);
+    };
+
+
+    CodeCell.prototype.append_svg = function (svg, element) {
+        var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_svg");
+        toinsert.append(svg);
+        element.append(toinsert);
+    };
+
+
+    CodeCell.prototype.append_png = function (png, element) {
+        var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_png");
+        toinsert.append($("<img/>").attr('src','data:image/png;base64,'+png));
+        element.append(toinsert);
+    };
+
+
+    CodeCell.prototype.append_jpeg = function (jpeg, element) {
+        var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_jpeg");
+        toinsert.append($("<img/>").attr('src','data:image/jpeg;base64,'+jpeg));
+        element.append(toinsert);
+    };
+
+
+    CodeCell.prototype.append_latex = function (latex, element) {
+        // This method cannot do the typesetting because the latex first has to
+        // be on the page.
+        var toinsert = $("<div/>").addClass("box_flex1 output_subarea output_latex");
+        toinsert.append(latex);
+        element.append(toinsert);
+    };
+
+
+    CodeCell.prototype.clear_output = function (stdout, stderr, other) {
+        var output_div = this.element.find("div.output");
+        if (stdout && stderr && other){
+            // clear all, no need for logic
+            output_div.html("");
+            this.outputs = [];
+            return;
+        }
+        // remove html output
+        // each output_subarea that has an identifying class is in an output_area
+        // which is the element to be removed.
+        if (stdout){
+            output_div.find("div.output_stdout").parent().remove();
+        }
+        if (stderr){
+            output_div.find("div.output_stderr").parent().remove();
+        }
+        if (other){
+            output_div.find("div.output_subarea").not("div.output_stderr").not("div.output_stdout").parent().remove();
+        }
+        
+        // remove cleared outputs from JSON list:
+        for (var i = this.outputs.length - 1; i >= 0; i--){
+            var out = this.outputs[i];
+            var output_type = out.output_type;
+            if (output_type == "display_data" && other){
+                this.outputs.splice(i,1);
+            }else if (output_type == "stream"){
+                if (stdout && out.stream == "stdout"){
+                    this.outputs.splice(i,1);
+                }else if (stderr && out.stream == "stderr"){
+                    this.outputs.splice(i,1);
+                }
+            }
+        }
+    };
+
+
+    CodeCell.prototype.clear_input = function () {
+        this.code_mirror.setValue('');
+    };
+
+
+    CodeCell.prototype.collapse = function () {
+        if (!this.collapsed) {
+            this.element.find('div.output').hide();
+            this.collapsed = true;
+        };
+    };
+
+
+    CodeCell.prototype.expand = function () {
+        if (this.collapsed) {
+            this.element.find('div.output').show();
+            this.collapsed = false;
+        };
+    };
+
+
+    CodeCell.prototype.toggle_output = function () {
+        if (this.collapsed) {
+            this.expand();
+        } else {
+            this.collapse();
+        };
+    };
+
+    CodeCell.prototype.set_input_prompt = function (number) {
+        var n = number || ' ';
+        this.input_prompt_number = n;
+        this.element.find('div.input_prompt').html('In [' + n + ']:');
+    };
+
+
+    CodeCell.prototype.get_text = function () {
+        return this.code_mirror.getValue();
+    };
+
+
+    CodeCell.prototype.set_text = function (code) {
+        return this.code_mirror.setValue(code);
+    };
+
+
+    CodeCell.prototype.at_top = function () {
+        var cursor = this.code_mirror.getCursor();
+        if (cursor.line === 0) {
+            return true;
+        } else {
+            return false;
+        }
+    };
+
+
+    CodeCell.prototype.at_bottom = function () {
+        var cursor = this.code_mirror.getCursor();
+        if (cursor.line === (this.code_mirror.lineCount()-1)) {
+            return true;
+        } else {
+            return false;
+        }
+    };
+
+
+    CodeCell.prototype.fromJSON = function (data) {
+        if (data.cell_type === 'code') {
+            if (data.input !== undefined) {
+                this.set_text(data.input);
+            }
+            if (data.prompt_number !== undefined) {
+                this.set_input_prompt(data.prompt_number);
+            } else {
+                this.set_input_prompt();
+            };
+            var len = data.outputs.length;
+            for (var i=0; i<len; i++) {
+                this.append_output(data.outputs[i]);
+            };
+            if (data.collapsed !== undefined) {
+                if (data.collapsed) {
+                    this.collapse();
+                };
+            };
+        };
+    };
+
+
+    CodeCell.prototype.toJSON = function () {
+        var data = {};
+        data.input = this.get_text();
+        data.cell_type = 'code';
+        if (this.input_prompt_number !== ' ') {
+            data.prompt_number = this.input_prompt_number;
+        };
+        var outputs = [];
+        var len = this.outputs.length;
+        for (var i=0; i<len; i++) {
+            outputs[i] = this.outputs[i];
+        };
+        data.outputs = outputs;
+        data.language = 'python';
+        data.collapsed = this.collapsed;
+        return data;
+    };
+
+
+    IPython.CodeCell = CodeCell;
+
+    return IPython;
+}(IPython));
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/fulleditwidget.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/fulleditwidget.js
new file mode 100644
index 0000000..546f849
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/fulleditwidget.js
@@ -0,0 +1,119 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// MenuBar
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var FullEditWidget = function (selector) {
+        this.selector = selector;
+        this.opened = false;
+        if (this.selector !== undefined) {
+            this.element = $(selector);
+            this.style();
+            this.bind_events();
+        }
+    };
+
+
+    FullEditWidget.prototype.style = function () {
+        var that = this;
+        this.element.find('#close_fulledit').button().on('click', function (){
+            that.close();
+        })
+        this.element.find('#fulledit_header').addClass('ui-widget ui-widget-header');
+        this.element.find('#fulledit_editor').addClass('ui-widget ui-widget-content');
+        this.ace_editor = ace.edit("fulledit_editor");
+        this.ace_editor.setTheme("ace/theme/textmate");
+        var PythonMode = require("ace/mode/python").Mode;
+        this.ace_editor.getSession().setMode(new PythonMode());
+        this.ace_editor.getSession().setTabSize(4);
+        this.ace_editor.getSession().setUseSoftTabs(true);
+        this.ace_editor.setHighlightActiveLine(false);
+        // Ace sets its css dynamically, so we need to do this here. These
+        // values are chosen to match those of our CodeMirror editors.
+        $('.ace_editor').css({fontFamily: 'monospace', fontSize: '110%',
+        lineHeight: '1.231'});
+    };
+
+
+    FullEditWidget.prototype.bind_events = function () {
+
+    };
+
+
+    FullEditWidget.prototype.open = function () {
+        var cell = IPython.notebook.get_selected_cell();
+        if (!this.opened) {
+            $('#fulledit_widget').show();
+            $('#main_app').hide();
+            $('#menubar').hide();
+            $('body').css({overflow : 'auto'});
+            var code = cell.get_text();
+            this.ace_editor.getSession().setValue(code);
+            if (cell instanceof IPython.CodeCell) {
+                var PythonMode = require("ace/mode/python").Mode;
+                this.ace_editor.getSession().setMode(new PythonMode());
+            } else if (cell instanceof IPython.MarkdownCell) {
+                var MarkdownMode = require("ace/mode/markdown").Mode;
+                this.ace_editor.getSession().setMode(new MarkdownMode());
+            } else if (cell instanceof IPython.HTMLCell) {
+                var HTMLMode = require("ace/mode/html").Mode;
+                this.ace_editor.getSession().setMode(new HTMLMode());
+            };
+            this.ace_editor.focus();
+            // On Safari (and Chrome/FF on Linux) the editor doesn't get
+            // focus unless there is a window resize. For now, we trigger it
+            // by hand until the bug is fixed upstream.
+            window.resizeBy(0,1);
+            window.resizeBy(0,-1);
+            this.opened = true;
+        };
+    };
+
+
+    FullEditWidget.prototype.close = function () {
+        if (this.opened) {
+            $('#fulledit_widget').hide();
+            $('#main_app').show();
+            //  We may need to add a refresh to all CM based cells after
+            // showing them.
+            $('#menubar').show();
+            $('body').css({overflow : 'hidden'});
+            var code = this.ace_editor.getSession().getValue();
+            var cell = IPython.notebook.get_selected_cell();
+            if (cell instanceof IPython.CodeCell) {
+                cell.code_mirror.refresh();
+                cell.set_text(code);                
+            } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
+                cell.edit();
+                // If the cell was already in edit mode, we need to refresh/focus.
+                cell.code_mirror.refresh();
+                cell.code_mirror.focus();
+                cell.set_text(code);
+            };
+            this.opened = false;
+        };
+    };
+
+
+    FullEditWidget.prototype.toggle = function () {
+        if (this.opened) {
+            this.close();
+        } else {
+            this.open();
+        };
+    };
+
+
+    IPython.FullEditWidget = FullEditWidget;
+
+    return IPython;
+
+}(IPython));
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/kernel.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/kernel.js
new file mode 100644
index 0000000..6f00922
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/kernel.js
@@ -0,0 +1,235 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Kernel
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+    var Kernel = function () {
+        this.kernel_id = null;
+        this.shell_channel = null;
+        this.iopub_channel = null;
+        this.base_url = $('body').data('baseKernelUrl') + "kernels";
+        this.running = false;
+        this.username = "username";
+        this.session_id = utils.uuid();
+        
+        if (typeof(WebSocket) !== 'undefined') {
+            this.WebSocket = WebSocket;
+        } else if (typeof(MozWebSocket) !== 'undefined') {
+            this.WebSocket = MozWebSocket;
+        } else {
+            alert('Your browser does not have WebSocket support, please try Chrome, Safari or Firefox ≥ 6. Firefox 4 and 5 are also supported by you have to enable WebSockets in about:config.');
+        };
+    };
+
+
+    Kernel.prototype.get_msg = function (msg_type, content) {
+        var msg = {
+            header : {
+                msg_id : utils.uuid(),
+                username : this.username,
+                session : this.session_id,
+                msg_type : msg_type
+            },
+            content : content,
+            parent_header : {}
+        };
+        return msg;
+    };
+
+    Kernel.prototype.start = function (notebook_id, callback) {
+        var that = this;
+        if (!this.running) {
+            var qs = $.param({notebook:notebook_id});
+            var url = this.base_url + '?' + qs;
+            $.post(url,
+                function (kernel_id) {
+                    that._handle_start_kernel(kernel_id, callback);
+                }, 
+                'json'
+            );
+        };
+    };
+
+
+    Kernel.prototype.restart = function (callback) {
+        IPython.kernel_status_widget.status_restarting();
+        var url = this.kernel_url + "/restart";
+        var that = this;
+        if (this.running) {
+            this.stop_channels();
+            $.post(url,
+                function (kernel_id) {
+                    that._handle_start_kernel(kernel_id, callback);
+                },
+                'json'
+            );
+        };
+    };
+
+
+    Kernel.prototype._handle_start_kernel = function (json, callback) {
+        this.running = true;
+        this.kernel_id = json.kernel_id;
+        this.ws_url = json.ws_url;
+        this.kernel_url = this.base_url + "/" + this.kernel_id;
+        this.start_channels();
+        callback();
+        IPython.kernel_status_widget.status_idle();
+    };
+
+    Kernel.prototype._websocket_closed = function(ws_url, early){
+        var msg;
+        var parent_item = $('body');
+        if (early) {
+            msg = "Websocket connection to " + ws_url + " could not be established.<br/>" +
+            " You will NOT be able to run code.<br/>" +
+            " Your browser may not be compatible with the websocket version in the server," +
+            " or if the url does not look right, there could be an error in the" +
+            " server's configuration.";
+        } else {
+            msg = "Websocket connection closed unexpectedly.<br/>" +
+            " The kernel will no longer be responsive.";
+        }
+        var dialog = $('<div/>');
+        dialog.html(msg);
+        parent_item.append(dialog);
+        dialog.dialog({
+            resizable: false,
+            modal: true,
+            title: "Websocket closed",
+            buttons : {
+                "Okay": function () {
+                    $(this).dialog('close');
+                }
+            }
+        });
+        
+    };
+
+    Kernel.prototype.start_channels = function () {
+        var that = this;
+        this.stop_channels();
+        var ws_url = this.ws_url + this.kernel_url;
+        console.log("Starting WS:", ws_url);
+        this.shell_channel = new this.WebSocket(ws_url + "/shell");
+        this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
+        send_cookie = function(){
+            this.send(document.cookie);
+        };
+        var already_called_onclose = false; // only alert once
+        ws_closed_early = function(evt){
+            if (already_called_onclose){
+                return;
+            }
+            already_called_onclose = true;
+            if ( ! evt.wasClean ){
+                that._websocket_closed(ws_url, true);
+            }
+        };
+        ws_closed_late = function(evt){
+            if (already_called_onclose){
+                return;
+            }
+            already_called_onclose = true;
+            if ( ! evt.wasClean ){
+                that._websocket_closed(ws_url, false);
+            }
+        };
+        this.shell_channel.onopen = send_cookie;
+        this.shell_channel.onclose = ws_closed_early;
+        this.iopub_channel.onopen = send_cookie;
+        this.iopub_channel.onclose = ws_closed_early;
+        // switch from early-close to late-close message after 1s
+        setTimeout(function(){
+            that.shell_channel.onclose = ws_closed_late;
+            that.iopub_channel.onclose = ws_closed_late;
+        }, 1000);
+    };
+
+
+    Kernel.prototype.stop_channels = function () {
+        if (this.shell_channel !== null) {
+            this.shell_channel.onclose = function (evt) {};
+            this.shell_channel.close();
+            this.shell_channel = null;
+        };
+        if (this.iopub_channel !== null) {
+            this.iopub_channel.onclose = function (evt) {};
+            this.iopub_channel.close();
+            this.iopub_channel = null;
+        };
+    };
+
+    Kernel.prototype.object_info_request = function (objname) {
+        if(typeof(objname)!=null && objname!=null)
+        {
+            var content = {
+                oname : objname.toString(),
+            };
+            var msg = this.get_msg("object_info_request", content);
+            this.shell_channel.send(JSON.stringify(msg));
+            return msg.header.msg_id;
+        }
+        return;
+    }
+
+    Kernel.prototype.execute = function (code) {
+        var content = {
+            code : code,
+            silent : false,
+            user_variables : [],
+            user_expressions : {},
+            allow_stdin : false
+        };
+        var msg = this.get_msg("execute_request", content);
+        this.shell_channel.send(JSON.stringify(msg));
+        return msg.header.msg_id;
+    };
+
+
+    Kernel.prototype.complete = function (line, cursor_pos) {
+        var content = {
+            text : '',
+            line : line,
+            cursor_pos : cursor_pos
+        };
+        var msg = this.get_msg("complete_request", content);
+        this.shell_channel.send(JSON.stringify(msg));
+        return msg.header.msg_id;
+    };
+
+
+    Kernel.prototype.interrupt = function () {
+        if (this.running) {
+            $.post(this.kernel_url + "/interrupt");
+        };
+    };
+
+
+    Kernel.prototype.kill = function () {
+        if (this.running) {
+            this.running = false;
+            var settings = {
+                cache : false,
+                type : "DELETE"
+            };
+            $.ajax(this.kernel_url, settings);
+        };
+    };
+
+    IPython.Kernel = Kernel;
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/kernelstatus.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/kernelstatus.js
new file mode 100644
index 0000000..5b61157
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/kernelstatus.js
@@ -0,0 +1,65 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Kernel Status widget
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+    var KernelStatusWidget = function (selector) {
+        this.selector = selector;
+        if (this.selector !== undefined) {
+            this.element = $(selector);
+            this.style();
+        }
+    };
+
+
+    KernelStatusWidget.prototype.style = function () {
+        this.element.addClass('ui-widget');
+        this.element.attr('title', "The kernel execution status." +
+        " If 'Busy', the kernel is currently running code." +
+        " If 'Idle', it is available for execution.");
+    };
+
+
+    KernelStatusWidget.prototype.status_busy = function () {
+        this.element.removeClass("status_idle");
+        this.element.removeClass("status_restarting");
+        this.element.addClass("status_busy");
+        window.document.title='(Busy) '+window.document.title;
+        this.element.text("Busy");
+    };
+
+
+    KernelStatusWidget.prototype.status_idle = function () {
+        this.element.removeClass("status_busy");
+        this.element.removeClass("status_restarting");
+        this.element.addClass("status_idle");
+        IPython.save_widget.set_document_title();
+        this.element.text("Idle");
+    };
+
+    KernelStatusWidget.prototype.status_restarting = function () {
+        this.element.removeClass("status_busy");
+        this.element.removeClass("status_idle");
+        this.element.addClass("status_restarting");
+        this.element.text("Restarting");
+    };
+
+
+
+
+    IPython.KernelStatusWidget = KernelStatusWidget;
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/layout.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/layout.js
new file mode 100644
index 0000000..ad59393
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/layout.js
@@ -0,0 +1,48 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Layout
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var LayoutManager = function () {
+        this.bind_events();
+    };
+
+
+    LayoutManager.prototype.bind_events = function () {
+        $(window).resize($.proxy(this.do_resize,this));
+    };
+
+
+    LayoutManager.prototype.do_resize = function () {
+        var win = $(window);
+        var w = win.width();
+        var h = win.height();
+        var header_height = $('div#header').outerHeight(true);
+        var menubar_height = $('div#menubar').outerHeight(true);
+        var app_height = h-header_height-menubar_height-2;  // content height
+
+        $('div#main_app').height(app_height + 2);  // content+padding+border height
+
+        var pager_height = IPython.pager.percentage_height*app_height;
+        var pager_splitter_height = $('div#pager_splitter').outerHeight(true);
+        $('div#pager').height(pager_height);
+        if (IPython.pager.expanded) {
+            $('div#notebook').height(app_height-pager_height-pager_splitter_height);
+        } else {
+            $('div#notebook').height(app_height-pager_splitter_height);
+        }
+    };
+
+    IPython.LayoutManager = LayoutManager;
+
+    return IPython;
+
+}(IPython));
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/loginmain.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/loginmain.js
new file mode 100644
index 0000000..684d3e0
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/loginmain.js
@@ -0,0 +1,30 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// On document ready
+//============================================================================
+
+
+$(document).ready(function () {
+
+    $('div#header').addClass('border-box-sizing');
+    $('div#header_border').addClass('border-box-sizing ui-widget ui-widget-content');
+
+    $('div#main_app').addClass('border-box-sizing ui-widget');
+    $('div#app_hbox').addClass('hbox');
+
+    $('div#left_panel').addClass('box-flex');
+    $('div#right_panel').addClass('box-flex');
+    $('input#signin').button();
+
+    // These have display: none in the css file and are made visible here to prevent FLOUC.
+    $('div#header').css('display','block');
+    $('div#main_app').css('display','block');
+
+});
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/loginwidget.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/loginwidget.js
new file mode 100644
index 0000000..763118e
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/loginwidget.js
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Login button
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var LoginWidget = function (selector) {
+        this.selector = selector;
+        if (this.selector !== undefined) {
+            this.element = $(selector);
+            this.style();
+            this.bind_events();
+        }
+    };
+
+    LoginWidget.prototype.style = function () {
+        this.element.find('button#logout').button();
+        this.element.find('button#login').button();
+    };
+    LoginWidget.prototype.bind_events = function () {
+        var that = this;
+        this.element.find("button#logout").click(function () {
+            window.location = "/logout";
+        });
+        this.element.find("button#login").click(function () {
+            window.location = "/login";
+        });
+    };
+
+    // Set module variables
+    IPython.LoginWidget = LoginWidget;
+
+    return IPython;
+
+}(IPython));
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/menubar.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/menubar.js
new file mode 100644
index 0000000..0eb989f
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/menubar.js
@@ -0,0 +1,151 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// MenuBar
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var MenuBar = function (selector) {
+        this.selector = selector;
+        if (this.selector !== undefined) {
+            this.element = $(selector);
+            this.style();
+            this.bind_events();
+        }
+    };
+
+
+    MenuBar.prototype.style = function () {
+        $('ul#menus').menubar({
+            select : function (event, ui) {
+                // The selected cell loses focus when the menu is entered, so we
+                // re-select it upon selection.
+                var i = IPython.notebook.get_selected_index();
+                IPython.notebook.select(i);
+            }
+        });
+    };
+
+
+    MenuBar.prototype.bind_events = function () {
+        //  File
+        this.element.find('#new_notebook').click(function () {
+            window.open($('body').data('baseProjectUrl')+'new');
+        });
+        this.element.find('#open_notebook').click(function () {
+            window.open($('body').data('baseProjectUrl'));
+        });
+        this.element.find('#rename_notebook').click(function () {
+            IPython.save_widget.rename_notebook();
+        });
+        this.element.find('#copy_notebook').click(function () {
+            var notebook_id = IPython.save_widget.get_notebook_id();
+            var url = $('body').data('baseProjectUrl') + notebook_id + '/copy';
+            window.open(url,'_newtab');
+        });
+        this.element.find('#save_notebook').click(function () {
+            IPython.save_widget.save_notebook();
+        });
+        this.element.find('#download_ipynb').click(function () {
+            var notebook_id = IPython.save_widget.get_notebook_id();
+            var url = $('body').data('baseProjectUrl') + 'notebooks/' +
+                      notebook_id + '?format=json';
+            window.open(url,'_newtab');
+        });
+        this.element.find('#download_py').click(function () {
+            var notebook_id = IPython.save_widget.get_notebook_id();
+            var url = $('body').data('baseProjectUrl') + 'notebooks/' +
+                      notebook_id + '?format=py';
+            window.open(url,'_newtab');
+        });
+        this.element.find('button#print_notebook').click(function () {
+            IPython.print_widget.print_notebook();
+        });
+        // Edit
+        this.element.find('#cut_cell').click(function () {
+            IPython.notebook.cut_cell();
+        });
+        this.element.find('#copy_cell').click(function () {
+            IPython.notebook.copy_cell();
+        });
+        this.element.find('#delete_cell').click(function () {
+            IPython.notebook.delete_cell();
+        });
+        this.element.find('#split_cell').click(function () {
+            IPython.notebook.split_cell();
+        });
+        this.element.find('#merge_cell_above').click(function () {
+            IPython.notebook.merge_cell_above();
+        });
+        this.element.find('#merge_cell_below').click(function () {
+            IPython.notebook.merge_cell_below();
+        });
+        this.element.find('#move_cell_up').click(function () {
+            IPython.notebook.move_cell_up();
+        });
+        this.element.find('#move_cell_down').click(function () {
+            IPython.notebook.move_cell_down();
+        });
+        this.element.find('#select_previous').click(function () {
+            IPython.notebook.select_prev();
+        });
+        this.element.find('#select_next').click(function () {
+            IPython.notebook.select_next();
+        });
+        // Insert
+        this.element.find('#insert_cell_above').click(function () {
+            IPython.notebook.insert_cell_above('code');
+        });
+        this.element.find('#insert_cell_below').click(function () {
+            IPython.notebook.insert_cell_below('code');
+        });
+        // Cell
+        this.element.find('#full_edit_cell').click(function () {
+            IPython.fulledit_widget.open();
+        });
+        this.element.find('#run_cell').click(function () {
+            IPython.notebook.execute_selected_cell();
+        });
+        this.element.find('#run_cell_in_place').click(function () {
+            IPython.notebook.execute_selected_cell({terminal:true});
+        });
+        this.element.find('#run_all_cells').click(function () {
+            IPython.notebook.execute_all_cells();
+        });
+        this.element.find('#to_code').click(function () {
+            IPython.notebook.to_code();
+        });
+        this.element.find('#to_markdown').click(function () {
+            IPython.notebook.to_markdown();
+        });
+        this.element.find('#toggle_output').click(function () {
+            IPython.notebook.toggle_output();
+        });
+        this.element.find('#clear_all_output').click(function () {
+            IPython.notebook.clear_all_output();
+        });
+        // Kernel
+        this.element.find('#int_kernel').click(function () {
+            IPython.notebook.kernel.interrupt();
+        });
+        this.element.find('#restart_kernel').click(function () {
+            IPython.notebook.restart_kernel();
+        });
+        // Help
+        this.element.find('#keyboard_shortcuts').click(function () {
+            IPython.quick_help.show_keyboard_shortcuts();
+        });
+    };
+
+
+    IPython.MenuBar = MenuBar;
+
+    return IPython;
+
+}(IPython));
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/namespace.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/namespace.js
new file mode 100644
index 0000000..9c17386
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/namespace.js
@@ -0,0 +1,30 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+var IPython = IPython || {};
+
+IPython.namespace = function (ns_string) {
+    var parts = ns_string.split('.'),
+        parent = IPython,
+        i;
+
+    // String redundant leading global
+    if (parts[0] === "IPython") {
+        parts = parts.slice(1);
+    }
+
+    for (i=0; i<parts.length; i+=1) {
+        // Create property if it doesn't exist
+        if (typeof parent[parts[i]] === "undefined") {
+            parent[parts[i]] = {};
+        }
+    }
+    return parent;
+};
+
+
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebook.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebook.js
new file mode 100644
index 0000000..031d46a
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebook.js
@@ -0,0 +1,1172 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Notebook
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+    var Notebook = function (selector) {
+        this.read_only = IPython.read_only;
+        this.element = $(selector);
+        this.element.scroll();
+        this.element.data("notebook", this);
+        this.next_prompt_number = 1;
+        this.kernel = null;
+        this.clipboard = null;
+        this.paste_enabled = false;
+        this.dirty = false;
+        this.msg_cell_map = {};
+        this.metadata = {};
+        this.control_key_active = false;
+        this.style();
+        this.create_elements();
+        this.bind_events();
+        this.set_tooltipontab(true);
+        this.set_smartcompleter(true);
+        this.set_timebeforetooltip(1200);
+    };
+
+
+    Notebook.prototype.style = function () {
+        $('div#notebook').addClass('border-box-sizing');
+    };
+
+
+    Notebook.prototype.create_elements = function () {
+        // We add this end_space div to the end of the notebook div to:
+        // i) provide a margin between the last cell and the end of the notebook
+        // ii) to prevent the div from scrolling up when the last cell is being
+        // edited, but is too low on the page, which browsers will do automatically.
+        var that = this;
+        var end_space = $('<div/>').addClass('end_space').height("30%");
+        end_space.dblclick(function (e) {
+            if (that.read_only) return;
+            var ncells = that.ncells();
+            that.insert_cell_below('code',ncells-1);
+        });
+        this.element.append(end_space);
+        $('div#notebook').addClass('border-box-sizing');
+    };
+
+
+    Notebook.prototype.bind_events = function () {
+        var that = this;
+        $(document).keydown(function (event) {
+            // console.log(event);
+            if (that.read_only) return true;
+            if (event.which === 27) {
+                // Intercept escape at highest level to avoid closing 
+                // websocket connection with firefox
+                event.preventDefault();
+            }
+            if (event.which === 38 && !event.shiftKey) {
+                var cell = that.get_selected_cell();
+                if (cell.at_top()) {
+                    event.preventDefault();
+                    that.select_prev();
+                };
+            } else if (event.which === 40 && !event.shiftKey) {
+                var cell = that.get_selected_cell();
+                if (cell.at_bottom()) {
+                    event.preventDefault();
+                    that.select_next();
+                };
+            } else if (event.which === 13 && event.shiftKey) {
+                that.execute_selected_cell();
+                return false;
+            } else if (event.which === 13 && event.ctrlKey) {
+                that.execute_selected_cell({terminal:true});
+                return false;
+            } else if (event.which === 77 && event.ctrlKey) {
+                that.control_key_active = true;
+                return false;
+            } else if (event.which === 88 && that.control_key_active) {
+                // Cut selected cell = x
+                that.cut_cell();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 67 && that.control_key_active) {
+                // Copy selected cell = c
+                that.copy_cell();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 86 && that.control_key_active) {
+                // Paste selected cell = v
+                that.paste_cell();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 68 && that.control_key_active) {
+                // Delete selected cell = d
+                that.delete_cell();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 65 && that.control_key_active) {
+                // Insert code cell above selected = a
+                that.insert_cell_above('code');
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 66 && that.control_key_active) {
+                // Insert code cell below selected = b
+                that.insert_cell_below('code');
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 89 && that.control_key_active) {
+                // To code = y
+                that.to_code();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 77 && that.control_key_active) {
+                // To markdown = m
+                that.to_markdown();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 84 && that.control_key_active) {
+                // Toggle output = t
+                that.toggle_output();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 83 && that.control_key_active) {
+                // Save notebook = s
+                IPython.save_widget.save_notebook();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 74 && that.control_key_active) {
+                // Move cell down = j
+                that.move_cell_down();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 75 && that.control_key_active) {
+                // Move cell up = k
+                that.move_cell_up();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 80 && that.control_key_active) {
+                // Select previous = p
+                that.select_prev();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 78 && that.control_key_active) {
+                // Select next = n
+                that.select_next();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 76 && that.control_key_active) {
+                // Toggle line numbers = l
+                that.cell_toggle_line_numbers();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 73 && that.control_key_active) {
+                // Interrupt kernel = i
+                IPython.notebook.kernel.interrupt();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 190 && that.control_key_active) {
+                // Restart kernel = .  # matches qt console
+                IPython.notebook.restart_kernel();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 72 && that.control_key_active) {
+                // Show keyboard shortcuts = h
+                IPython.quick_help.show_keyboard_shortcuts();
+                that.control_key_active = false;
+                return false;
+            } else if (event.which === 69 && that.control_key_active) {
+                // Edit in Ace = e
+                IPython.fulledit_widget.toggle();
+                that.control_key_active = false;
+                return false;
+            } else if (that.control_key_active) {
+                that.control_key_active = false;
+                return true;
+            };
+            return true;
+        });
+
+        this.element.bind('collapse_pager', function () {
+            var app_height = $('div#main_app').height(); // content height
+            var splitter_height = $('div#pager_splitter').outerHeight(true);
+            var new_height = app_height - splitter_height;
+            that.element.animate({height : new_height + 'px'}, 'fast');
+        });
+
+        this.element.bind('expand_pager', function () {
+            var app_height = $('div#main_app').height(); // content height
+            var splitter_height = $('div#pager_splitter').outerHeight(true);
+            var pager_height = $('div#pager').outerHeight(true);
+            var new_height = app_height - pager_height - splitter_height; 
+            that.element.animate({height : new_height + 'px'}, 'fast');
+        });
+
+        $(window).bind('beforeunload', function () {
+            // TODO: Make killing the kernel configurable.
+            var kill_kernel = false;
+            if (kill_kernel) {
+                that.kernel.kill();
+            }
+            if (that.dirty && ! that.read_only) {
+                return "You have unsaved changes that will be lost if you leave this page.";
+            };
+            // Null is the *only* return value that will make the browser not
+            // pop up the "don't leave" dialog.
+            return null;
+        });
+    };
+
+
+    Notebook.prototype.scroll_to_bottom = function () {
+        this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0);
+    };
+
+
+    Notebook.prototype.scroll_to_top = function () {
+        this.element.animate({scrollTop:0}, 0);
+    };
+
+
+    // Cell indexing, retrieval, etc.
+
+    Notebook.prototype.get_cell_elements = function () {
+        return this.element.children("div.cell");
+    };
+
+
+    Notebook.prototype.get_cell_element = function (index) {
+        var result = null;
+        var e = this.get_cell_elements().eq(index);
+        if (e.length !== 0) {
+            result = e;
+        }
+        return result;
+    };
+
+
+    Notebook.prototype.ncells = function (cell) {
+        return this.get_cell_elements().length;
+    };
+
+
+    // TODO: we are often calling cells as cells()[i], which we should optimize
+    // to cells(i) or a new method.
+    Notebook.prototype.get_cells = function () {
+        return this.get_cell_elements().toArray().map(function (e) {
+            return $(e).data("cell");
+        });
+    };
+
+
+    Notebook.prototype.get_cell = function (index) {
+        var result = null;
+        var ce = this.get_cell_element(index);
+        if (ce !== null) {
+            result = ce.data('cell');
+        }
+        return result;
+    }
+
+
+    Notebook.prototype.get_next_cell = function (cell) {
+        var result = null;
+        var index = this.find_cell_index(cell);
+        if (index !== null && index < this.ncells()) {
+            result = this.get_cell(index+1);
+        }
+        return result;
+    }
+
+
+    Notebook.prototype.get_prev_cell = function (cell) {
+        var result = null;
+        var index = this.find_cell_index(cell);
+        if (index !== null && index > 1) {
+            result = this.get_cell(index-1);
+        }
+        return result;
+    }
+
+    Notebook.prototype.find_cell_index = function (cell) {
+        var result = null;
+        this.get_cell_elements().filter(function (index) {
+            if ($(this).data("cell") === cell) {
+                result = index;
+            };
+        });
+        return result;
+    };
+
+
+    Notebook.prototype.index_or_selected = function (index) {
+        var i;
+        if (index === undefined || index === null) {
+            i = this.get_selected_index();
+            if (i === null) {
+                i = 0;
+            }
+        } else {
+            i = index;
+        }
+        return i;
+    };
+
+
+    Notebook.prototype.get_selected_cell = function () {
+        var index = this.get_selected_index();
+        return this.get_cell(index);
+    };
+
+
+    Notebook.prototype.is_valid_cell_index = function (index) {
+        if (index !== null && index >= 0 && index < this.ncells()) {
+            return true;
+        } else {
+            return false;
+        };
+    }
+
+    Notebook.prototype.get_selected_index = function () {
+        var result = null;
+        this.get_cell_elements().filter(function (index) {
+            if ($(this).data("cell").selected === true) {
+                result = index;
+            };
+        });
+        return result;
+    };
+
+
+    Notebook.prototype.cell_for_msg = function (msg_id) {
+        var cell_id = this.msg_cell_map[msg_id];
+        var result = null;
+        this.get_cell_elements().filter(function (index) {
+            cell = $(this).data("cell");
+            if (cell.cell_id === cell_id) {
+                result = cell;
+            };
+        });
+        return result;
+    };
+
+
+    // Cell selection.
+
+    Notebook.prototype.select = function (index) {
+        if (index !== undefined && index >= 0 && index < this.ncells()) {
+            sindex = this.get_selected_index()
+            if (sindex !== null && index !== sindex) {
+                this.get_cell(sindex).unselect();
+            };
+            this.get_cell(index).select();
+        };
+        return this;
+    };
+
+
+    Notebook.prototype.select_next = function () {
+        var index = this.get_selected_index();
+        if (index !== null && index >= 0 && (index+1) < this.ncells()) {
+            this.select(index+1);
+        };
+        return this;
+    };
+
+
+    Notebook.prototype.select_prev = function () {
+        var index = this.get_selected_index();
+        if (index !== null && index >= 0 && (index-1) < this.ncells()) {
+            this.select(index-1);
+        };
+        return this;
+    };
+
+
+    // Cell movement
+
+    Notebook.prototype.move_cell_up = function (index) {
+        var i = this.index_or_selected();
+        if (i !== null && i < this.ncells() && i > 0) {
+            var pivot = this.get_cell_element(i-1);
+            var tomove = this.get_cell_element(i);
+            if (pivot !== null && tomove !== null) {
+                tomove.detach();
+                pivot.before(tomove);
+                this.select(i-1);
+            };
+        };
+        this.dirty = true;
+        return this;
+    };
+
+
+    Notebook.prototype.move_cell_down = function (index) {
+        var i = this.index_or_selected();
+        if (i !== null && i < (this.ncells()-1) && i >= 0) {
+            var pivot = this.get_cell_element(i+1);
+            var tomove = this.get_cell_element(i);
+            if (pivot !== null && tomove !== null) {
+                tomove.detach();
+                pivot.after(tomove);
+                this.select(i+1);
+            };
+        };
+        this.dirty = true;
+        return this;
+    };
+
+
+    Notebook.prototype.sort_cells = function () {
+        // This is not working right now. Calling this will actually crash
+        // the browser. I think there is an infinite loop in here...
+        var ncells = this.ncells();
+        var sindex = this.get_selected_index();
+        var swapped;
+        do {
+            swapped = false;
+            for (var i=1; i<ncells; i++) {
+                current = this.get_cell(i);
+                previous = this.get_cell(i-1);
+                if (previous.input_prompt_number > current.input_prompt_number) {
+                    this.move_cell_up(i);
+                    swapped = true;
+                };
+            };
+        } while (swapped);
+        this.select(sindex);
+        return this;
+    };
+
+    // Insertion, deletion.
+
+    Notebook.prototype.delete_cell = function (index) {
+        var i = this.index_or_selected(index);
+        if (this.is_valid_cell_index(i)) {
+            var ce = this.get_cell_element(i);
+            ce.remove();
+            if (i === (this.ncells())) {
+                this.select(i-1);
+            } else {
+                this.select(i);
+            };
+            this.dirty = true;
+        };
+        return this;
+    };
+
+
+    Notebook.prototype.insert_cell_below = function (type, index) {
+        // type = ('code','html','markdown')
+        // index = cell index or undefined to insert below selected
+        index = this.index_or_selected(index);
+        if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
+            var cell = null;
+            if (type === 'code') {
+                var cell = new IPython.CodeCell(this);
+                cell.set_input_prompt();
+            } else if (type === 'markdown') {
+                var cell = new IPython.MarkdownCell(this);
+            } else if (type === 'html') {
+                var cell = new IPython.HTMLCell(this);
+            };
+            if (cell !== null) {
+                if (this.ncells() === 0) {
+                    this.element.find('div.end_space').before(cell.element);
+                } else if (this.is_valid_cell_index(index)) {
+                    this.get_cell_element(index).after(cell.element);
+                };
+                cell.render();
+                this.select(this.find_cell_index(cell));
+                this.dirty = true;
+                return cell;
+            };
+        };
+    };
+
+
+    Notebook.prototype.insert_cell_above = function (type, index) {
+        // type = ('code','html','markdown')
+        // index = cell index or undefined to insert above selected
+        index = this.index_or_selected(index);
+        if (this.ncells() === 0 || this.is_valid_cell_index(index)) {
+            var cell = null;
+            if (type === 'code') {
+                var cell = new IPython.CodeCell(this);
+                cell.set_input_prompt();
+            } else if (type === 'markdown') {
+                var cell = new IPython.MarkdownCell(this);
+            } else if (type === 'html') {
+                var cell = new IPython.HTMLCell(this);
+            };
+            if (cell !== null) {
+                if (this.ncells() === 0) {
+                    this.element.find('div.end_space').before(cell.element);
+                } else if (this.is_valid_cell_index(index)) {
+                    this.get_cell_element(index).before(cell.element);
+                };
+                cell.render();
+                this.select(this.find_cell_index(cell));
+                this.dirty = true;
+                return cell;
+            };
+        };
+    };
+
+
+    Notebook.prototype.to_code = function (index) {
+        var i = this.index_or_selected(index);
+        if (this.is_valid_cell_index(i)) {
+            var source_element = this.get_cell_element(i);
+            var source_cell = source_element.data("cell");
+            if (!(source_cell instanceof IPython.CodeCell)) {
+                target_cell = this.insert_cell_below('code',i);
+                var text = source_cell.get_text();
+                if (text === source_cell.placeholder) {
+                    text = '';
+                }
+                target_cell.set_text(text);
+                source_element.remove();
+            };
+            this.dirty = true;
+        };
+    };
+
+
+    Notebook.prototype.to_markdown = function (index) {
+        var i = this.index_or_selected(index);
+        if (this.is_valid_cell_index(i)) {
+            var source_element = this.get_cell_element(i);
+            var source_cell = source_element.data("cell");
+            var target_cell = null;
+            if (!(source_cell instanceof IPython.MarkdownCell)) {
+                target_cell = this.insert_cell_below('markdown',i);
+                var text = source_cell.get_text();
+                if (text === source_cell.placeholder) {
+                    text = '';
+                };
+                if (target_cell !== null) {
+                    // The edit must come before the set_text.
+                    target_cell.edit();
+                    target_cell.set_text(text);
+                    source_element.remove();
+                }
+                this.dirty = true;
+            };
+        };
+    };
+
+
+    Notebook.prototype.to_html = function (index) {
+        var i = this.index_or_selected(index);
+        if (this.is_valid_cell_index(i)) {
+            var source_element = this.get_cell_element(i);
+            var source_cell = source_element.data("cell");
+            var target_cell = null;
+            if (!(source_cell instanceof IPython.HTMLCell)) {
+                target_cell = this.insert_cell_below('html',i);
+                var text = source_cell.get_text();
+                if (text === source_cell.placeholder) {
+                    text = '';
+                };
+                if (target_cell !== null) {
+                    // The edit must come before the set_text.
+                    target_cell.edit();
+                    target_cell.set_text(text);
+                    source_element.remove();
+                }
+                this.dirty = true;
+            };
+        };
+    };
+
+
+    // Cut/Copy/Paste
+
+    Notebook.prototype.enable_paste = function () {
+        var that = this;
+        if (!this.paste_enabled) {
+            $('#paste_cell').removeClass('ui-state-disabled')
+                .on('click', function () {that.paste_cell();});
+            $('#paste_cell_above').removeClass('ui-state-disabled')
+                .on('click', function () {that.paste_cell_above();});
+            $('#paste_cell_below').removeClass('ui-state-disabled')
+                .on('click', function () {that.paste_cell_below();});
+            this.paste_enabled = true;
+        };
+    };
+
+
+    Notebook.prototype.disable_paste = function () {
+        if (this.paste_enabled) {
+            $('#paste_cell').addClass('ui-state-disabled').off('click');
+            $('#paste_cell_above').addClass('ui-state-disabled').off('click');
+            $('#paste_cell_below').addClass('ui-state-disabled').off('click');
+            this.paste_enabled = false;
+        };
+    };
+
+
+    Notebook.prototype.cut_cell = function () {
+        this.copy_cell();
+        this.delete_cell();
+    }
+
+    Notebook.prototype.copy_cell = function () {
+        var cell = this.get_selected_cell();
+        this.clipboard = cell.toJSON();
+        this.enable_paste();
+    };
+
+
+    Notebook.prototype.paste_cell = function () {
+        if (this.clipboard !== null && this.paste_enabled) {
+            var cell_data = this.clipboard;
+            var new_cell = this.insert_cell_above(cell_data.cell_type);
+            new_cell.fromJSON(cell_data);
+            old_cell = this.get_next_cell(new_cell);
+            this.delete_cell(this.find_cell_index(old_cell));
+            this.select(this.find_cell_index(new_cell));
+        };
+    };
+
+
+    Notebook.prototype.paste_cell_above = function () {
+        if (this.clipboard !== null && this.paste_enabled) {
+            var cell_data = this.clipboard;
+            var new_cell = this.insert_cell_above(cell_data.cell_type);
+            new_cell.fromJSON(cell_data);
+        };
+    };
+
+
+    Notebook.prototype.paste_cell_below = function () {
+        if (this.clipboard !== null && this.paste_enabled) {
+            var cell_data = this.clipboard;
+            var new_cell = this.insert_cell_below(cell_data.cell_type);
+            new_cell.fromJSON(cell_data);
+        };
+    };
+
+
+    // Split/merge
+
+    Notebook.prototype.split_cell = function () {
+        // Todo: implement spliting for other cell types.
+        var cell = this.get_selected_cell();
+        if (cell.is_splittable()) {
+            texta = cell.get_pre_cursor();
+            textb = cell.get_post_cursor();
+            if (cell instanceof IPython.CodeCell) {
+                cell.set_text(texta);
+                var new_cell = this.insert_cell_below('code');
+                new_cell.set_text(textb);
+            } else if (cell instanceof IPython.MarkdownCell) {
+                cell.set_text(texta);
+                cell.render();
+                var new_cell = this.insert_cell_below('markdown');
+                new_cell.edit(); // editor must be visible to call set_text
+                new_cell.set_text(textb);
+                new_cell.render();
+            } else if (cell instanceof IPython.HTMLCell) {
+                cell.set_text(texta);
+                cell.render();
+                var new_cell = this.insert_cell_below('html');
+                new_cell.edit(); // editor must be visible to call set_text
+                new_cell.set_text(textb);
+                new_cell.render();
+            };
+        };
+    };
+
+
+    Notebook.prototype.merge_cell_above = function () {
+        var index = this.get_selected_index();
+        var cell = this.get_cell(index);
+        if (index > 0) {
+            upper_cell = this.get_cell(index-1);
+            upper_text = upper_cell.get_text();
+            text = cell.get_text();
+            if (cell instanceof IPython.CodeCell) {
+                cell.set_text(upper_text+'\n'+text);
+            } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
+                cell.edit();
+                cell.set_text(upper_text+'\n'+text);
+                cell.render();
+            };
+            this.delete_cell(index-1);
+            this.select(this.find_cell_index(cell));
+        };
+    };
+
+
+    Notebook.prototype.merge_cell_below = function () {
+        var index = this.get_selected_index();
+        var cell = this.get_cell(index);
+        if (index < this.ncells()-1) {
+            lower_cell = this.get_cell(index+1);
+            lower_text = lower_cell.get_text();
+            text = cell.get_text();
+            if (cell instanceof IPython.CodeCell) {
+                cell.set_text(text+'\n'+lower_text);
+            } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) {
+                cell.edit();
+                cell.set_text(text+'\n'+lower_text);
+                cell.render();
+            };
+            this.delete_cell(index+1);
+            this.select(this.find_cell_index(cell));
+        };
+    };
+
+
+    // Cell collapsing and output clearing
+
+    Notebook.prototype.collapse = function (index) {
+        var i = this.index_or_selected(index);
+        this.get_cell(i).collapse();
+        this.dirty = true;
+    };
+
+
+    Notebook.prototype.expand = function (index) {
+        var i = this.index_or_selected(index);
+        this.get_cell(i).expand();
+        this.dirty = true;
+    };
+
+
+    Notebook.prototype.toggle_output = function (index) {
+        var i = this.index_or_selected(index);
+        this.get_cell(i).toggle_output();
+        this.dirty = true;
+    };
+
+
+    Notebook.prototype.set_timebeforetooltip = function (time) {
+        this.time_before_tooltip = time;
+    };
+
+
+    Notebook.prototype.set_tooltipontab = function (state) {
+        this.tooltip_on_tab = state;
+    };
+
+
+    Notebook.prototype.set_smartcompleter = function (state) {
+        this.smart_completer = state;
+    };
+
+
+    Notebook.prototype.clear_all_output = function () {
+        var ncells = this.ncells();
+        var cells = this.get_cells();
+        for (var i=0; i<ncells; i++) {
+            if (cells[i] instanceof IPython.CodeCell) {
+                cells[i].clear_output(true,true,true);
+            }
+        };
+        this.dirty = true;
+    };
+
+
+    // Other cell functions: line numbers, ...
+
+    Notebook.prototype.cell_toggle_line_numbers = function() {
+        this.get_selected_cell().toggle_line_numbers();
+    };
+
+    // Kernel related things
+
+    Notebook.prototype.start_kernel = function () {
+        this.kernel = new IPython.Kernel();
+        var notebook_id = IPython.save_widget.get_notebook_id();
+        this.kernel.start(notebook_id, $.proxy(this.kernel_started, this));
+    };
+
+
+    Notebook.prototype.restart_kernel = function () {
+        var that = this;
+        var notebook_id = IPython.save_widget.get_notebook_id();
+
+        var dialog = $('<div/>');
+        dialog.html('Do you want to restart the current kernel?  You will lose all variables defined in it.');
+        $(document).append(dialog);
+        dialog.dialog({
+            resizable: false,
+            modal: true,
+            title: "Restart kernel or continue running?",
+            closeText: '',
+            buttons : {
+                "Restart": function () {
+                    that.kernel.restart($.proxy(that.kernel_started, that));
+                    $(this).dialog('close');
+                },
+                "Continue running": function () {
+                    $(this).dialog('close');
+                }
+            }
+        });
+    };
+
+
+    Notebook.prototype.kernel_started = function () {
+        console.log("Kernel started: ", this.kernel.kernel_id);
+        this.kernel.shell_channel.onmessage = $.proxy(this.handle_shell_reply,this);
+        this.kernel.iopub_channel.onmessage = $.proxy(this.handle_iopub_reply,this);
+    };
+
+
+    Notebook.prototype.handle_shell_reply = function (e) {
+        reply = $.parseJSON(e.data);
+        var header = reply.header;
+        var content = reply.content;
+        var msg_type = header.msg_type;
+        // console.log(reply);
+        var cell = this.cell_for_msg(reply.parent_header.msg_id);
+        if (msg_type === "execute_reply") {
+            cell.set_input_prompt(content.execution_count);
+            cell.element.removeClass("running");
+            this.dirty = true;
+        } else if (msg_type === "complete_reply") {
+            cell.finish_completing(content.matched_text, content.matches);
+        } else if (msg_type === "object_info_reply"){
+            //console.log('back from object_info_request : ')
+            rep = reply.content;
+            if(rep.found)
+            {
+                cell.finish_tooltip(rep);
+            }
+        } else {
+          //console.log("unknown reply:"+msg_type);
+        }
+        // when having a rely from object_info_reply,
+        // no payload so no nned to handle it
+        if(typeof(content.payload)!='undefined') {
+            var payload = content.payload || [];
+            this.handle_payload(cell, payload);
+        }
+    };
+
+
+    Notebook.prototype.handle_payload = function (cell, payload) {
+        var l = payload.length;
+        for (var i=0; i<l; i++) {
+            if (payload[i].source === 'IPython.zmq.page.page') {
+                if (payload[i].text.trim() !== '') {
+                    IPython.pager.clear();
+                    IPython.pager.expand();
+                    IPython.pager.append_text(payload[i].text);
+                }
+            } else if (payload[i].source === 'IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input') {
+                var index = this.find_cell_index(cell);
+                var new_cell = this.insert_cell_below('code',index);
+                new_cell.set_text(payload[i].text);
+                this.dirty = true;
+            }
+        };
+    };
+
+
+    Notebook.prototype.handle_iopub_reply = function (e) {
+        reply = $.parseJSON(e.data);
+        var content = reply.content;
+        // console.log(reply);
+        var msg_type = reply.header.msg_type;
+        var cell = this.cell_for_msg(reply.parent_header.msg_id);
+        if (msg_type !== 'status' && !cell){
+            // message not from this notebook, but should be attached to a cell
+            console.log("Received IOPub message not caused by one of my cells");
+            console.log(reply);
+            return;
+        }
+        var output_types = ['stream','display_data','pyout','pyerr'];
+        if (output_types.indexOf(msg_type) >= 0) {
+            this.handle_output(cell, msg_type, content);
+        } else if (msg_type === 'status') {
+            if (content.execution_state === 'busy') {
+                IPython.kernel_status_widget.status_busy();
+            } else if (content.execution_state === 'idle') {
+                IPython.kernel_status_widget.status_idle();
+            } else if (content.execution_state === 'dead') {
+                this.handle_status_dead();
+            };
+        } else if (msg_type === 'clear_output') {
+            cell.clear_output(content.stdout, content.stderr, content.other);
+        };
+    };
+
+
+    Notebook.prototype.handle_status_dead = function () {
+        var that = this;
+        this.kernel.stop_channels();
+        var dialog = $('<div/>');
+        dialog.html('The kernel has died, would you like to restart it? If you do not restart the kernel, you will be able to save the notebook, but running code will not work until the notebook is reopened.');
+        $(document).append(dialog);
+        dialog.dialog({
+            resizable: false,
+            modal: true,
+            title: "Dead kernel",
+            buttons : {
+                "Restart": function () {
+                    that.start_kernel();
+                    $(this).dialog('close');
+                },
+                "Continue running": function () {
+                    $(this).dialog('close');
+                }
+            }
+        });
+    };
+
+
+    Notebook.prototype.handle_output = function (cell, msg_type, content) {
+        var json = {};
+        json.output_type = msg_type;
+        if (msg_type === "stream") {
+            json.text = utils.fixConsole(content.data);
+            json.stream = content.name;
+        } else if (msg_type === "display_data") {
+            json = this.convert_mime_types(json, content.data);
+        } else if (msg_type === "pyout") {
+            json.prompt_number = content.execution_count;
+            json = this.convert_mime_types(json, content.data);
+        } else if (msg_type === "pyerr") {
+            json.ename = content.ename;
+            json.evalue = content.evalue;
+            var traceback = [];
+            for (var i=0; i<content.traceback.length; i++) {
+                traceback.push(utils.fixConsole(content.traceback[i]));
+            }
+            json.traceback = traceback;
+        };
+        cell.append_output(json);
+        this.dirty = true;
+    };
+
+
+    Notebook.prototype.convert_mime_types = function (json, data) {
+        if (data['text/plain'] !== undefined) {
+            json.text = utils.fixConsole(data['text/plain']);
+        };
+        if (data['text/html'] !== undefined) {
+            json.html = data['text/html'];
+        };
+        if (data['image/svg+xml'] !== undefined) {
+            json.svg = data['image/svg+xml'];
+        };
+        if (data['image/png'] !== undefined) {
+            json.png = data['image/png'];
+        };
+        if (data['image/jpeg'] !== undefined) {
+            json.jpeg = data['image/jpeg'];
+        };
+        if (data['text/latex'] !== undefined) {
+            json.latex = data['text/latex'];
+        };
+        if (data['application/json'] !== undefined) {
+            json.json = data['application/json'];
+        };
+        if (data['application/javascript'] !== undefined) {
+            json.javascript = data['application/javascript'];
+        }
+        return json;    
+    };
+
+
+    Notebook.prototype.execute_selected_cell = function (options) {
+        // add_new: should a new cell be added if we are at the end of the nb
+        // terminal: execute in terminal mode, which stays in the current cell
+        default_options = {terminal: false, add_new: true};
+        $.extend(default_options, options);
+        var that = this;
+        var cell = that.get_selected_cell();
+        var cell_index = that.find_cell_index(cell);
+        if (cell instanceof IPython.CodeCell) {
+            cell.clear_output(true, true, true);
+            cell.set_input_prompt('*');
+            cell.element.addClass("running");
+            var code = cell.get_text();
+            var msg_id = that.kernel.execute(cell.get_text());
+            that.msg_cell_map[msg_id] = cell.cell_id;
+        } else if (cell instanceof IPython.HTMLCell) {
+            cell.render();
+        }
+        if (default_options.terminal) {
+            cell.select_all();
+        } else {
+            if ((cell_index === (that.ncells()-1)) && default_options.add_new) {
+                that.insert_cell_below('code');
+                // If we are adding a new cell at the end, scroll down to show it.
+                that.scroll_to_bottom();
+            } else {
+                that.select(cell_index+1);
+            };
+        };
+        this.dirty = true;
+    };
+
+
+    Notebook.prototype.execute_all_cells = function () {
+        var ncells = this.ncells();
+        for (var i=0; i<ncells; i++) {
+            this.select(i);
+            this.execute_get_selected_cell({add_new:false});
+        };
+        this.scroll_to_bottom();
+    };
+
+
+    Notebook.prototype.request_tool_tip = function (cell,func) {
+        // Feel free to shorten this logic if you are better
+        // than me in regEx
+        // basicaly you shoul be able to get xxx.xxx.xxx from 
+        // something(range(10), kwarg=smth) ; xxx.xxx.xxx( firstarg, rand(234,23), kwarg1=2, 
+        // remove everything between matchin bracket (need to iterate)
+        matchBracket = /\([^\(\)]+\)/g;
+        oldfunc = func;
+        func = func.replace(matchBracket,"");
+        while( oldfunc != func )
+        {
+        oldfunc = func;
+        func = func.replace(matchBracket,"");
+        }
+        // remove everythin after last open bracket
+        endBracket = /\([^\(]*$/g;
+        func = func.replace(endBracket,"");
+        var re = /[a-zA-Z._]+$/g;
+        var msg_id = this.kernel.object_info_request(re.exec(func));
+        if(typeof(msg_id)!='undefined'){
+            this.msg_cell_map[msg_id] = cell.cell_id;
+            }
+    };
+
+    Notebook.prototype.complete_cell = function (cell, line, cursor_pos) {
+        var msg_id = this.kernel.complete(line, cursor_pos);
+        this.msg_cell_map[msg_id] = cell.cell_id;
+    };
+
+    // Persistance and loading
+
+
+    Notebook.prototype.fromJSON = function (data) {
+        var ncells = this.ncells();
+        var i;
+        for (i=0; i<ncells; i++) {
+            // Always delete cell 0 as they get renumbered as they are deleted.
+            this.delete_cell(0);
+        };
+        // Save the metadata
+        this.metadata = data.metadata;
+        // Only handle 1 worksheet for now.
+        var worksheet = data.worksheets[0];
+        if (worksheet !== undefined) {
+            var new_cells = worksheet.cells;
+            ncells = new_cells.length;
+            var cell_data = null;
+            var new_cell = null;
+            for (i=0; i<ncells; i++) {
+                cell_data = new_cells[i];
+                new_cell = this.insert_cell_below(cell_data.cell_type);
+                new_cell.fromJSON(cell_data);
+            };
+        };
+    };
+
+
+    Notebook.prototype.toJSON = function () {
+        var cells = this.get_cells();
+        var ncells = cells.length;
+        cell_array = new Array(ncells);
+        for (var i=0; i<ncells; i++) {
+            cell_array[i] = cells[i].toJSON();
+        };
+        data = {
+            // Only handle 1 worksheet for now.
+            worksheets : [{cells:cell_array}],
+            metadata : this.metadata
+        };
+        return data;
+    };
+
+    Notebook.prototype.save_notebook = function () {
+        var notebook_id = IPython.save_widget.get_notebook_id();
+        var nbname = IPython.save_widget.get_notebook_name();
+        // We may want to move the name/id/nbformat logic inside toJSON?
+        var data = this.toJSON();
+        data.metadata.name = nbname;
+        data.nbformat = 2;
+        // We do the call with settings so we can set cache to false.
+        var settings = {
+            processData : false,
+            cache : false,
+            type : "PUT",
+            data : JSON.stringify(data),
+            headers : {'Content-Type': 'application/json'},
+            success : $.proxy(this.notebook_saved,this),
+            error : $.proxy(this.notebook_save_failed,this)
+        };
+        IPython.save_widget.status_saving();
+        var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
+        $.ajax(url, settings);
+    };
+
+
+    Notebook.prototype.notebook_saved = function (data, status, xhr) {
+        this.dirty = false;
+        IPython.save_widget.notebook_saved();
+        IPython.save_widget.status_last_saved();
+    };
+
+
+    Notebook.prototype.notebook_save_failed = function (xhr, status, error_msg) {
+        IPython.save_widget.status_save_failed();
+    };
+
+
+    Notebook.prototype.load_notebook = function () {
+        var that = this;
+        var notebook_id = IPython.save_widget.get_notebook_id();
+        // We do the call with settings so we can set cache to false.
+        var settings = {
+            processData : false,
+            cache : false,
+            type : "GET",
+            dataType : "json",
+            success : function (data, status, xhr) {
+                that.notebook_loaded(data, status, xhr);
+            }
+        };
+        IPython.save_widget.status_loading();
+        var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
+        $.ajax(url, settings);
+    };
+
+
+    Notebook.prototype.notebook_loaded = function (data, status, xhr) {
+        this.fromJSON(data);
+        if (this.ncells() === 0) {
+            this.insert_cell_below('code');
+        };
+        IPython.save_widget.status_last_saved();
+        IPython.save_widget.set_notebook_name(data.metadata.name);
+        this.dirty = false;
+        if (! this.read_only) {
+            this.start_kernel();
+        }
+        this.select(0);
+        this.scroll_to_top();
+        IPython.save_widget.update_url();
+        IPython.layout_manager.do_resize();
+    };
+
+    IPython.Notebook = Notebook;
+
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebooklist.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebooklist.js
new file mode 100644
index 0000000..50dd96a
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebooklist.js
@@ -0,0 +1,251 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// NotebookList
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var NotebookList = function (selector) {
+        this.selector = selector;
+        if (this.selector !== undefined) {
+            this.element = $(selector);
+            this.style();
+            this.bind_events();
+        }
+    };
+
+    NotebookList.prototype.style = function () {
+        this.element.addClass('ui-widget ui-widget-content');
+        $('div#project_name').addClass('ui-widget ui-widget-header');
+    };
+
+
+    NotebookList.prototype.bind_events = function () {
+        if (IPython.read_only){
+            return;
+        }
+        var that = this;
+        this.element.bind('dragover', function () {
+            return false;
+        });
+        this.element.bind('drop', function (event) {
+            var files = event.originalEvent.dataTransfer.files;
+            for (var i = 0, f; f = files[i]; i++) {
+                var reader = new FileReader();
+                reader.readAsText(f);
+                var fname = f.name.split('.'); 
+                var nbname = fname.slice(0,-1).join('.');
+                var nbformat = fname.slice(-1)[0];
+                if (nbformat === 'ipynb') {nbformat = 'json';};
+                if (nbformat === 'py' || nbformat === 'json') {
+                    var item = that.new_notebook_item(0);
+                    that.add_name_input(nbname, item);
+                    item.data('nbformat', nbformat);
+                    // Store the notebook item in the reader so we can use it later
+                    // to know which item it belongs to.
+                    $(reader).data('item', item);
+                    reader.onload = function (event) {
+                        var nbitem = $(event.target).data('item');
+                        that.add_notebook_data(event.target.result, nbitem);
+                        that.add_upload_button(nbitem);
+                    };
+                };
+            }
+            return false;
+        });
+    };
+
+
+    NotebookList.prototype.load_list = function () {
+        var settings = {
+            processData : false,
+            cache : false,
+            type : "GET",
+            dataType : "json",
+            success : $.proxy(this.list_loaded, this)
+        };
+        var url = $('body').data('baseProjectUrl') + 'notebooks';
+        $.ajax(url, settings);
+    };
+
+
+    NotebookList.prototype.list_loaded = function (data, status, xhr) {
+        var len = data.length;
+        // Todo: remove old children
+        for (var i=0; i<len; i++) {
+            var notebook_id = data[i].notebook_id;
+            var nbname = data[i].name;
+            var item = this.new_notebook_item(i);
+            this.add_link(notebook_id, nbname, item);
+            if (!IPython.read_only){
+                // hide delete buttons when readonly
+                this.add_delete_button(item);
+            }
+        };
+    };
+
+
+    NotebookList.prototype.new_notebook_item = function (index) {
+        var item = $('<div/>');
+        item.addClass('notebook_item ui-widget ui-widget-content ui-helper-clearfix');
+        var item_name = $('<span/>').addClass('item_name');
+
+        item.append(item_name);
+        if (index === -1) {
+            this.element.append(item);
+        } else {
+            this.element.children().eq(index).after(item);
+        }
+        return item;
+    };
+
+
+    NotebookList.prototype.add_link = function (notebook_id, nbname, item) {
+        item.data('nbname', nbname);
+        item.data('notebook_id', notebook_id);
+        var new_item_name = $('<span/>').addClass('item_name');
+        new_item_name.append(
+            $('<a/>').
+            attr('href', $('body').data('baseProjectUrl')+notebook_id).
+            attr('target','_blank').
+            text(nbname)
+        );
+        var e = item.find('.item_name');
+        if (e.length === 0) {
+            item.append(new_item_name);
+        } else {
+            e.replaceWith(new_item_name);
+        };
+    };
+
+
+    NotebookList.prototype.add_name_input = function (nbname, item) {
+        item.data('nbname', nbname);
+        var new_item_name = $('<span/>').addClass('item_name');
+        new_item_name.append(
+            $('<input/>').addClass('ui-widget ui-widget-content').
+            attr('value', nbname).
+            attr('size', '30').
+            attr('type', 'text')
+        );
+        var e = item.find('.item_name');
+        if (e.length === 0) {
+            item.append(new_item_name);
+        } else {
+            e.replaceWith(new_item_name);
+        };
+    };
+
+
+    NotebookList.prototype.add_notebook_data = function (data, item) {
+        item.data('nbdata',data);
+    };
+
+
+    NotebookList.prototype.add_delete_button = function (item) {
+        var new_buttons = $('<span/>').addClass('item_buttons');
+        var delete_button = $('<button>Delete</button>').button().
+            click(function (e) {
+                // $(this) is the button that was clicked.
+                var that = $(this);
+                // We use the nbname and notebook_id from the parent notebook_item element's
+                // data because the outer scopes values change as we iterate through the loop.
+                var parent_item = that.parents('div.notebook_item');
+                var nbname = parent_item.data('nbname');
+                var notebook_id = parent_item.data('notebook_id');
+                var dialog = $('<div/>');
+                dialog.html('Are you sure you want to permanently delete the notebook: ' + nbname + '?');
+                parent_item.append(dialog);
+                dialog.dialog({
+                    resizable: false,
+                    modal: true,
+                    title: "Delete notebook",
+                    buttons : {
+                        "Delete": function () {
+                            var settings = {
+                                processData : false,
+                                cache : false,
+                                type : "DELETE",
+                                dataType : "json",
+                                success : function (data, status, xhr) {
+                                    parent_item.remove();
+                                }
+                            };
+                            var url = $('body').data('baseProjectUrl') + 'notebooks/' + notebook_id;
+                            $.ajax(url, settings);
+                            $(this).dialog('close');
+                        },
+                        "Cancel": function () {
+                            $(this).dialog('close');
+                        }
+                    }
+                });
+            });
+        new_buttons.append(delete_button);
+        var e = item.find('.item_buttons');
+        if (e.length === 0) {
+            item.append(new_buttons);
+        } else {
+            e.replaceWith(new_buttons);
+        };
+    };
+
+
+    NotebookList.prototype.add_upload_button = function (item) {
+        var that = this;
+        var new_buttons = $('<span/>').addClass('item_buttons');
+        var upload_button = $('<button>Upload</button>').button().
+            click(function (e) {
+                var nbname = item.find('.item_name > input').attr('value');
+                var nbformat = item.data('nbformat');
+                var nbdata = item.data('nbdata');
+                var content_type = 'text/plain';
+                if (nbformat === 'json') {
+                    content_type = 'application/json';
+                } else if (nbformat === 'py') {
+                    content_type = 'application/x-python';
+                };
+                var settings = {
+                    processData : false,
+                    cache : false,
+                    type : 'POST',
+                    dataType : 'json',
+                    data : nbdata,
+                    headers : {'Content-Type': content_type},
+                    success : function (data, status, xhr) {
+                        that.add_link(data, nbname, item);
+                        that.add_delete_button(item);
+                    }
+                };
+
+                var qs = $.param({name:nbname, format:nbformat});
+                var url = $('body').data('baseProjectUrl') + 'notebooks?' + qs;
+                $.ajax(url, settings);
+            });
+        var cancel_button = $('<button>Cancel</button>').button().
+            click(function (e) {
+                item.remove();
+            });
+        upload_button.addClass('upload_button');
+        new_buttons.append(upload_button).append(cancel_button);
+        var e = item.find('.item_buttons');
+        if (e.length === 0) {
+            item.append(new_buttons);
+        } else {
+            e.replaceWith(new_buttons);
+        };
+    };
+
+
+    IPython.NotebookList = NotebookList;
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebookmain.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebookmain.js
new file mode 100644
index 0000000..868f482
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/notebookmain.js
@@ -0,0 +1,116 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// On document ready
+//============================================================================
+
+
+$(document).ready(function () {
+    if (window.MathJax){ 
+        // MathJax loaded
+        MathJax.Hub.Config({
+            tex2jax: {
+                inlineMath: [ ['$','$'], ["\\(","\\)"] ],
+                displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
+            },
+            displayAlign: 'left', // Change this to 'center' to center equations.
+            "HTML-CSS": {
+                styles: {'.MathJax_Display': {"margin": 0}}
+            }
+        });
+    }else if (window.mathjax_url != ""){
+        // Don't have MathJax, but should. Show dialog.
+        var dialog = $('<div></div>')
+            .append(
+                $("<p></p>").addClass('dialog').html(
+                    "Math/LaTeX rendering will be disabled."
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "If you have administrative access to the notebook server and" +
+                    " a working internet connection, you can install a local copy" +
+                    " of MathJax for offline use with the following command on the server" +
+                    " at a Python or IPython prompt:"
+                )
+            ).append(
+                $("<pre></pre>").addClass('dialog').html(
+                    ">>> from IPython.external import mathjax; mathjax.install_mathjax()"
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "This will try to install MathJax into the IPython source directory."
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "If IPython is installed to a location that requires" +
+                    " administrative privileges to write, you will need to make this call as" +
+                    " an administrator, via 'sudo'."
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "When you start the notebook server, you can instruct it to disable MathJax support altogether:"
+                )
+            ).append(
+                $("<pre></pre>").addClass('dialog').html(
+                    "$ ipython notebook --no-mathjax"
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "which will prevent this dialog from appearing."
+                )
+            ).dialog({
+                title: "Failed to retrieve MathJax from '" + window.mathjax_url + "'",
+                width: "70%",
+                modal: true,
+            })
+    }else{
+        // No MathJax, but none expected. No dialog.
+    }
+
+
+    IPython.markdown_converter = new Markdown.Converter();
+    IPython.read_only = $('meta[name=read_only]').attr("content") == 'True';
+
+    $('div#header').addClass('border-box-sizing');
+    $('div#main_app').addClass('border-box-sizing ui-widget ui-widget-content');
+    $('div#notebook_panel').addClass('border-box-sizing ui-widget');
+
+    IPython.layout_manager = new IPython.LayoutManager();
+    IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter');
+    IPython.save_widget = new IPython.SaveWidget('span#save_widget');
+    IPython.quick_help = new IPython.QuickHelp('span#quick_help_area');
+    IPython.login_widget = new IPython.LoginWidget('span#login_widget');
+    IPython.notebook = new IPython.Notebook('div#notebook');
+    IPython.kernel_status_widget = new IPython.KernelStatusWidget('#kernel_status');
+    IPython.menubar = new IPython.MenuBar('#menubar')
+    IPython.kernel_status_widget.status_idle();
+    IPython.fulledit_widget = new IPython.FullEditWidget('#fulledit_widget');
+
+    IPython.layout_manager.do_resize();
+
+    // These have display: none in the css file and are made visible here to prevent FLOUC.
+    $('div#header').css('display','block');
+
+    if(IPython.read_only){
+        // hide various elements from read-only view
+        $('div#pager').remove();
+        $('div#pager_splitter').remove();
+        $('span#login_widget').removeClass('hidden');
+
+        // set the notebook name field as not modifiable
+        $('#notebook_name').attr('disabled','disabled')
+    }
+
+    $('div#menubar').css('display','block');
+    $('div#main_app').css('display','block');
+
+    IPython.layout_manager.do_resize();
+    IPython.notebook.load_notebook();
+
+});
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/pager.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/pager.js
new file mode 100644
index 0000000..c3d4fcf
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/pager.js
@@ -0,0 +1,102 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Pager
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+    var Pager = function (pager_selector, pager_splitter_selector) {
+        this.pager_element = $(pager_selector);
+        this.pager_splitter_element = $(pager_splitter_selector);
+        this.expanded = false;
+        this.percentage_height = 0.40;
+        this.style();
+        this.bind_events();
+    };
+
+
+    Pager.prototype.style = function () {
+        this.pager_splitter_element.addClass('border-box-sizing ui-widget ui-state-default');
+        this.pager_element.addClass('border-box-sizing ui-widget');
+        this.pager_splitter_element.attr('title', 'Click to Show/Hide pager area');
+    };
+
+
+    Pager.prototype.bind_events = function () {
+        var that = this;
+
+        this.pager_element.bind('collapse_pager', function () {
+            that.pager_element.hide('fast');
+        });
+
+        this.pager_element.bind('expand_pager', function () {
+            that.pager_element.show('fast');
+        });
+
+        this.pager_splitter_element.hover(
+            function () {
+                that.pager_splitter_element.addClass('ui-state-hover');
+            },
+            function () {
+                that.pager_splitter_element.removeClass('ui-state-hover');
+            }
+        );
+
+        this.pager_splitter_element.click(function () {
+            that.toggle();
+        });
+
+    };
+
+
+    Pager.prototype.collapse = function () {
+        if (this.expanded === true) {
+            this.pager_element.add($('div#notebook')).trigger('collapse_pager');
+            this.expanded = false;
+        };
+    };
+
+
+    Pager.prototype.expand = function () {
+        if (this.expanded !== true) {
+            this.pager_element.add($('div#notebook')).trigger('expand_pager');
+            this.expanded = true;
+        };
+    };
+
+
+    Pager.prototype.toggle = function () {
+        if (this.expanded === true) {
+            this.collapse();
+        } else {
+            this.expand();
+        };
+    };
+
+
+    Pager.prototype.clear = function (text) {
+        this.pager_element.empty();
+    };
+
+
+    Pager.prototype.append_text = function (text) {
+        var toinsert = $("<div/>").addClass("output_area output_stream");
+        toinsert.append($('<pre/>').html(utils.fixConsole(text)));
+        this.pager_element.append(toinsert);
+    };   
+
+
+    IPython.Pager = Pager;
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/printnotebookmain.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/printnotebookmain.js
new file mode 100644
index 0000000..ce5ec98
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/printnotebookmain.js
@@ -0,0 +1,94 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// On document ready
+//============================================================================
+
+
+$(document).ready(function () {
+    if (window.MathJax){ 
+        // MathJax loaded
+        MathJax.Hub.Config({
+            tex2jax: {
+                inlineMath: [ ['$','$'], ["\\(","\\)"] ],
+                displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
+            },
+            displayAlign: 'left', // Change this to 'center' to center equations.
+            "HTML-CSS": {
+                styles: {'.MathJax_Display': {"margin": 0}}
+            }
+        });
+    }else if (window.mathjax_url != ""){
+        // Don't have MathJax, but should. Show dialog.
+        var dialog = $('<div></div>')
+            .append(
+                $("<p></p>").addClass('dialog').html(
+                    "Math/LaTeX rendering will be disabled."
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "If you have administrative access to the notebook server and" +
+                    " a working internet connection, you can install a local copy" +
+                    " of MathJax for offline use with the following command on the server" +
+                    " at a Python or IPython prompt:"
+                )
+            ).append(
+                $("<pre></pre>").addClass('dialog').html(
+                    ">>> from IPython.external import mathjax; mathjax.install_mathjax()"
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "This will try to install MathJax into the IPython source directory."
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "If IPython is installed to a location that requires" +
+                    " administrative privileges to write, you will need to make this call as" +
+                    " an administrator, via 'sudo'."
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "When you start the notebook server, you can instruct it to disable MathJax support altogether:"
+                )
+            ).append(
+                $("<pre></pre>").addClass('dialog').html(
+                    "$ ipython notebook --no-mathjax"
+                )
+            ).append(
+                $("<p></p>").addClass('dialog').html(
+                    "which will prevent this dialog from appearing."
+                )
+            ).dialog({
+                title: "Failed to retrieve MathJax from '" + window.mathjax_url + "'",
+                width: "70%",
+                modal: true,
+            })
+    }else{
+        // No MathJax, but none expected. No dialog.
+    }
+    
+    IPython.markdown_converter = new Markdown.Converter();
+    IPython.read_only = $('meta[name=read_only]').attr("content") == 'True';
+
+    $('div#header').addClass('border-box-sizing');
+    $('div#main_app').addClass('border-box-sizing ui-widget ui-widget-content');
+    $('div#notebook_panel').addClass('border-box-sizing ui-widget');
+
+    IPython.save_widget = new IPython.SaveWidget('span#save_widget');
+    IPython.login_widget = new IPython.LoginWidget('span#login_widget');
+    IPython.notebook = new IPython.Notebook('div#notebook');
+
+    // These have display: none in the css file and are made visible here to prevent FLOUC.
+    $('div#header').css('display','block');
+    $('div#main_app').css('display','block');
+
+    // Perform these actions after the notebook has been loaded.
+    IPython.notebook.load_notebook(function () {});
+
+});
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/projectdashboardmain.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/projectdashboardmain.js
new file mode 100644
index 0000000..516b406
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/projectdashboardmain.js
@@ -0,0 +1,42 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// On document ready
+//============================================================================
+
+
+$(document).ready(function () {
+
+    $('div#header').addClass('border-box-sizing');
+    $('div#header_border').addClass('border-box-sizing ui-widget ui-widget-content');
+
+    $('div#main_app').addClass('border-box-sizing ui-widget');
+    $('div#app_hbox').addClass('hbox');
+
+    $('div#content_toolbar').addClass('ui-widget ui-helper-clearfix');    
+
+    $('#new_notebook').button().click(function (e) {
+        window.open($('body').data('baseProjectUrl')+'new');
+    });
+
+    $('div#left_panel').addClass('box-flex');
+    $('div#right_panel').addClass('box-flex');
+
+    IPython.read_only = $('meta[name=read_only]').attr("content") == 'True';
+    IPython.notebook_list = new IPython.NotebookList('div#notebook_list');
+    IPython.login_widget = new IPython.LoginWidget('span#login_widget');
+
+    IPython.notebook_list.load_list();
+
+    // These have display: none in the css file and are made visible here to prevent FLOUC.
+    $('div#header').css('display','block');
+    $('div#main_app').css('display','block');
+
+
+});
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/quickhelp.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/quickhelp.js
new file mode 100644
index 0000000..41aa3ef
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/quickhelp.js
@@ -0,0 +1,69 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// QuickHelp button
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var QuickHelp = function (selector) {
+    };
+
+    QuickHelp.prototype.show_keyboard_shortcuts = function () {
+        // toggles display of keyboard shortcut dialog
+        var that = this;
+        if ( this.shortcut_dialog ){
+            // if dialog is already shown, close it
+            this.shortcut_dialog.dialog("close");
+            this.shortcut_dialog = null;
+            return;
+        }
+        var dialog = $('<div/>');
+        this.shortcut_dialog = dialog;
+        var shortcuts = [
+            {key: 'Shift-Enter', help: 'run cell'},
+            {key: 'Ctrl-Enter', help: 'run cell in-place'},
+            {key: 'Ctrl-m x', help: 'cut cell'},
+            {key: 'Ctrl-m c', help: 'copy cell'},
+            {key: 'Ctrl-m v', help: 'paste cell'},
+            {key: 'Ctrl-m d', help: 'delete cell'},
+            {key: 'Ctrl-m e', help: 'toggle edit cell in Ace'},
+            {key: 'Ctrl-m a', help: 'insert cell above'},
+            {key: 'Ctrl-m b', help: 'insert cell below'},
+            {key: 'Ctrl-m t', help: 'toggle output'},
+            {key: 'Ctrl-m l', help: 'toggle line numbers'},
+            {key: 'Ctrl-m s', help: 'save notebook'},
+            {key: 'Ctrl-m j', help: 'move cell down'},
+            {key: 'Ctrl-m k', help: 'move cell up'},
+            {key: 'Ctrl-m y', help: 'code cell'},
+            {key: 'Ctrl-m m', help: 'markdown cell'},
+            {key: 'Ctrl-m p', help: 'select previous'},
+            {key: 'Ctrl-m n', help: 'select next'},
+            {key: 'Ctrl-m i', help: 'interrupt kernel'},
+            {key: 'Ctrl-m .', help: 'restart kernel'},
+            {key: 'Ctrl-m h', help: 'show keyboard shortcuts'}
+        ];
+        for (var i=0; i<shortcuts.length; i++) {
+            dialog.append($('<div>').
+                append($('<span/>').addClass('shortcut_key').html(shortcuts[i].key)).
+                append($('<span/>').addClass('shortcut_descr').html(' : ' + shortcuts[i].help))
+            );
+        };
+        dialog.bind('dialogclose', function(event) {
+            // dialog has been closed, allow it to be drawn again.
+            that.shortcut_dialog = null;
+        });
+        dialog.dialog({title: 'Keyboard shortcuts', closeText: ''});
+    };
+
+    // Set module variables
+    IPython.QuickHelp = QuickHelp;
+
+    return IPython;
+
+}(IPython));
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/savewidget.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/savewidget.js
new file mode 100644
index 0000000..e93493f
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/savewidget.js
@@ -0,0 +1,179 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// SaveWidget
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    var utils = IPython.utils;
+
+    var SaveWidget = function (selector) {
+        this.selector = selector;
+        this.notebook_name_blacklist_re = /[\/\\]/;
+        this.last_saved_name = '';
+        if (this.selector !== undefined) {
+            this.element = $(selector);
+            this.style();
+            this.bind_events();
+        }
+    };
+
+
+    SaveWidget.prototype.style = function () {
+        this.element.find('span#save_widget').addClass('ui-widget');
+        this.element.find('span#notebook_name').addClass('ui-widget ui-widget-content');
+        this.element.find('span#save_status').addClass('ui-widget ui-widget-content')
+            .css({border: 'none', 'margin-left': '20px'});
+    };
+
+
+    SaveWidget.prototype.bind_events = function () {
+        var that = this;
+        this.element.find('span#notebook_name').click(function () {
+            that.rename_notebook();
+        });
+        this.element.find('span#notebook_name').hover(function () {
+            $(this).addClass("ui-state-hover");
+        }, function () {
+            $(this).removeClass("ui-state-hover");
+        });
+    };
+
+
+    SaveWidget.prototype.save_notebook = function () {
+        IPython.notebook.save_notebook();
+    };
+
+
+    SaveWidget.prototype.rename_notebook = function () {
+        var that = this;
+        var dialog = $('<div/>');
+        dialog.append(
+            $('<h3/>').html('Enter a new notebook name:')
+            .css({'margin-bottom': '10px'})
+        );
+        dialog.append(
+            $('<input/>').attr('type','text').attr('size','25')
+            .addClass('ui-widget ui-widget-content')
+            .attr('value',that.get_notebook_name())
+        );
+        // $(document).append(dialog);
+        dialog.dialog({
+            resizable: false,
+            modal: true,
+            title: "Rename Notebook",
+            closeText: "",
+            close: function(event, ui) {$(this).dialog('destroy').remove();},
+            buttons : {
+                "OK": function () {
+                    var new_name = $(this).find('input').attr('value');
+                    if (!that.test_notebook_name(new_name)) {
+                        $(this).find('h3').html(
+                            "Invalid notebook name. Notebook names must "+
+                            "have 1 or more characters and can contain any characters " +
+                            "except / and \\. Please enter a new notebook name:"
+                        );
+                    } else {
+                        that.set_notebook_name(new_name);
+                        that.save_notebook();
+                        $(this).dialog('close');
+                    }
+                },
+                "Cancel": function () {
+                    $(this).dialog('close');
+                }
+            }
+        });
+    }
+
+    SaveWidget.prototype.notebook_saved = function () {
+        this.set_document_title();
+        this.last_saved_name = this.get_notebook_name();
+    };
+
+
+    SaveWidget.prototype.get_notebook_name = function () {
+        return this.element.find('span#notebook_name').html();
+    };
+
+
+    SaveWidget.prototype.set_notebook_name = function (nbname) {
+        this.element.find('span#notebook_name').html(nbname);
+        this.set_document_title();
+        this.last_saved_name = nbname;
+    };
+
+
+    SaveWidget.prototype.set_document_title = function () {
+        nbname = this.get_notebook_name();
+        document.title = nbname;
+    };
+        
+
+    SaveWidget.prototype.get_notebook_id = function () {
+        return $('body').data('notebookId');
+    };
+
+
+    SaveWidget.prototype.update_url = function () {
+        var notebook_id = this.get_notebook_id();
+        if (notebook_id !== '') {
+            var new_url = '/'+notebook_id;
+            window.history.replaceState({}, '', new_url);
+        };
+    };
+
+
+    SaveWidget.prototype.test_notebook_name = function (nbname) {
+        nbname = nbname || '';
+        if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) {
+            return true;
+        } else {
+            return false;
+        };
+    };
+
+
+    SaveWidget.prototype.set_last_saved = function () {
+        var d = new Date();
+        $('#save_status').html('Last saved: '+d.format('mmm dd h:MM TT'));
+        
+    };
+
+    SaveWidget.prototype.reset_status = function () {
+        this.element.find('span#save_status').html('');
+    };
+
+
+    SaveWidget.prototype.status_last_saved = function () {
+        this.set_last_saved();
+    };
+
+
+    SaveWidget.prototype.status_saving = function () {
+        this.element.find('span#save_status').html('Saving...');
+    };
+
+
+    SaveWidget.prototype.status_save_failed = function () {
+        this.element.find('span#save_status').html('Save failed');
+    };
+
+
+    SaveWidget.prototype.status_loading = function () {
+        this.element.find('span#save_status').html('Loading...');
+    };
+
+
+    IPython.SaveWidget = SaveWidget;
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/textcell.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/textcell.js
new file mode 100644
index 0000000..07dd4c8
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/textcell.js
@@ -0,0 +1,290 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// TextCell
+//============================================================================
+
+var IPython = (function (IPython) {
+
+    // TextCell base class
+
+    var TextCell = function (notebook) {
+        this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
+        IPython.Cell.apply(this, arguments);
+        this.rendered = false;
+        this.cell_type = this.cell_type || 'text';
+    };
+
+
+    TextCell.prototype = new IPython.Cell();
+
+
+    TextCell.prototype.create_element = function () {
+        var cell = $("<div>").addClass('cell text_cell border-box-sizing');
+        cell.attr('tabindex','2');
+        var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
+        this.code_mirror = CodeMirror(input_area.get(0), {
+            indentUnit : 4,
+            mode: this.code_mirror_mode,
+            theme: 'default',
+            value: this.placeholder,
+            readOnly: this.read_only,
+            onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
+        });
+        // The tabindex=-1 makes this div focusable.
+        var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
+            addClass('rendered_html').attr('tabindex','-1');
+        cell.append(input_area).append(render_area);
+        this.element = cell;
+    };
+
+
+    TextCell.prototype.bind_events = function () {
+        IPython.Cell.prototype.bind_events.apply(this);
+        var that = this;
+        this.element.keydown(function (event) {
+            if (event.which === 13) {
+                if (that.rendered) {
+                    that.edit();
+                    return false;
+                };
+            };
+        });
+        this.element.dblclick(function () {
+            that.edit();
+        });
+    };
+
+
+    TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
+        // This method gets called in CodeMirror's onKeyDown/onKeyPress
+        // handlers and is used to provide custom key handling. Its return
+        // value is used to determine if CodeMirror should ignore the event:
+        // true = ignore, false = don't ignore.
+
+        if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
+            // Always ignore shift-enter in CodeMirror as we handle it.
+            return true;
+        }
+        return false;
+    };
+
+
+    TextCell.prototype.select = function () {
+        IPython.Cell.prototype.select.apply(this);
+        var output = this.element.find("div.text_cell_render");
+        output.trigger('focus');
+    };
+
+
+    TextCell.prototype.unselect = function() {
+        // render on selection of another cell
+        this.render();
+        IPython.Cell.prototype.unselect.apply(this);
+    };
+
+
+    TextCell.prototype.edit = function () {
+        if ( this.read_only ) return;
+        if (this.rendered === true) {
+            var text_cell = this.element;
+            var output = text_cell.find("div.text_cell_render");  
+            output.hide();
+            text_cell.find('div.text_cell_input').show();
+            // I don't know why I need to do this, but if I don't do
+            // refresh/focus/refresh, the to_markdown method won't work.
+            this.code_mirror.refresh();
+            this.code_mirror.focus();
+            // This final refresh is needed on Firefox to trigger the editor
+            // to be auto-sized. This glitch only happens on cell that are
+            // loaded initially and haven't had their editor focused before.
+            this.code_mirror.refresh();
+            this.rendered = false;
+            if (this.get_text() === this.placeholder) {
+                this.set_text('');
+                this.refresh();
+            }
+        }
+    };
+
+
+    // Subclasses must define render.
+    TextCell.prototype.render = function () {};
+
+
+    TextCell.prototype.get_text = function() {
+        return this.code_mirror.getValue();
+    };
+
+
+    TextCell.prototype.set_text = function(text) {
+        this.code_mirror.setValue(text);
+        this.code_mirror.refresh();
+    };
+
+
+    TextCell.prototype.get_rendered = function() {
+        return this.element.find('div.text_cell_render').html();
+    };
+
+
+    TextCell.prototype.set_rendered = function(text) {
+        this.element.find('div.text_cell_render').html(text);
+    };
+
+
+    TextCell.prototype.at_top = function () {
+        if (this.rendered) {
+            return true;
+        } else {
+            return false;
+        }
+    };
+
+
+    TextCell.prototype.at_bottom = function () {
+        if (this.rendered) {
+            return true;
+        } else {
+            return false;
+        }
+    };
+
+
+    TextCell.prototype.fromJSON = function (data) {
+        if (data.cell_type === this.cell_type) {
+            if (data.source !== undefined) {
+                this.set_text(data.source);
+                this.set_rendered(data.rendered || '');
+                this.rendered = false;
+                this.render();
+            }
+        }
+    };
+
+
+    TextCell.prototype.toJSON = function () {
+        var data = {};
+        data.cell_type = this.cell_type;
+        data.source = this.get_text();
+        return data;
+    };
+
+
+    // HTMLCell
+
+    var HTMLCell = function (notebook) {
+        this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
+        IPython.TextCell.apply(this, arguments);
+        this.cell_type = 'html';
+    };
+
+
+    HTMLCell.prototype = new TextCell();
+
+
+    HTMLCell.prototype.render = function () {
+        if (this.rendered === false) {
+            var text = this.get_text();
+            if (text === "") { text = this.placeholder; }
+            this.set_rendered(text);
+            this.typeset();
+            this.element.find('div.text_cell_input').hide();
+            this.element.find("div.text_cell_render").show();
+            this.rendered = true;
+        }
+    };
+
+
+    // MarkdownCell
+
+    var MarkdownCell = function (notebook) {
+        this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
+        IPython.TextCell.apply(this, arguments);
+        this.cell_type = 'markdown';
+    };
+
+
+    MarkdownCell.prototype = new TextCell();
+
+
+    MarkdownCell.prototype.render = function () {
+        if (this.rendered === false) {
+            var text = this.get_text();
+            if (text === "") { text = this.placeholder; }
+            var html = IPython.markdown_converter.makeHtml(text);
+            this.set_rendered(html);
+            this.typeset()
+            this.element.find('div.text_cell_input').hide();
+            this.element.find("div.text_cell_render").show();
+            var code_snippets = this.element.find("pre > code");
+            code_snippets.replaceWith(function () {
+                var code = $(this).html();
+                /* Substitute br for newlines and   for spaces
+                   before highlighting, since prettify doesn't
+                   preserve those on all browsers */
+                code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
+                code = code.replace(/ /gm, ' ');
+                code = prettyPrintOne(code);
+
+                return '<code class="prettyprint">' + code + '</code>';
+            });
+            this.rendered = true;
+        }
+    };
+
+
+    // RSTCell
+
+    var RSTCell = function (notebook) {
+        this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
+        IPython.TextCell.apply(this, arguments);
+        this.cell_type = 'rst';
+    };
+
+
+    RSTCell.prototype = new TextCell();
+
+
+    RSTCell.prototype.render = function () {
+        if (this.rendered === false) {
+            var text = this.get_text();
+            if (text === "") { text = this.placeholder; }
+            var settings = {
+                processData : false,
+                cache : false,
+                type : "POST",
+                data : text,
+                headers : {'Content-Type': 'application/x-rst'},
+                success : $.proxy(this.handle_render,this)
+            };
+            $.ajax("/rstservice/render", settings);
+            this.element.find('div.text_cell_input').hide();
+            this.element.find("div.text_cell_render").show();
+            this.set_rendered("Rendering...");
+        }
+    };
+
+
+    RSTCell.prototype.handle_render = function (data, status, xhr) {
+        this.set_rendered(data);
+        this.typeset();
+        this.rendered = true;
+    };
+
+
+    IPython.TextCell = TextCell;
+    IPython.HTMLCell = HTMLCell;
+    IPython.MarkdownCell = MarkdownCell;
+    IPython.RSTCell = RSTCell;
+
+
+    return IPython;
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/utils.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/utils.js
new file mode 100644
index 0000000..bce44b3
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/js/utils.js
@@ -0,0 +1,101 @@
+//----------------------------------------------------------------------------
+//  Copyright (C) 2008-2011  The IPython Development Team
+//
+//  Distributed under the terms of the BSD License.  The full license is in
+//  the file COPYING, distributed as part of this software.
+//----------------------------------------------------------------------------
+
+//============================================================================
+// Utilities
+//============================================================================
+
+IPython.namespace('IPython.utils');
+
+IPython.utils = (function (IPython) {
+
+    var uuid = function () {
+        // http://www.ietf.org/rfc/rfc4122.txt
+        var s = [];
+        var hexDigits = "0123456789ABCDEF";
+        for (var i = 0; i < 32; i++) {
+            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
+        }
+        s[12] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
+        s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
+
+        var uuid = s.join("");
+        return uuid;
+    };
+
+
+    //Fix raw text to parse correctly in crazy XML
+    function xmlencode(string) {
+        return string.replace(/\&/g,'&'+'amp;')
+            .replace(/</g,'&'+'lt;')
+            .replace(/>/g,'&'+'gt;')
+            .replace(/\'/g,'&'+'apos;')
+            .replace(/\"/g,'&'+'quot;')
+            .replace(/`/g,'&'+'#96;');
+    }
+
+
+    //Map from terminal commands to CSS classes
+    ansi_colormap = {
+        "30":"ansiblack", "31":"ansired",
+        "32":"ansigreen", "33":"ansiyellow",
+        "34":"ansiblue", "35":"ansipurple","36":"ansicyan", 
+        "37":"ansigrey", "01":"ansibold"
+    };
+
+    // Transform ANI color escape codes into HTML <span> tags with css
+    // classes listed in the above ansi_colormap object. The actual color used
+    // are set in the css file.
+    function fixConsole(txt) {
+        txt = xmlencode(txt);
+        var re = /\033\[([\d;]*?)m/;
+        var opened = false;
+        var cmds = [];
+        var opener = "";
+        var closer = "";
+        
+        while (re.test(txt)) {
+            var cmds = txt.match(re)[1].split(";");
+            closer = opened?"</span>":"";
+            opened = cmds.length > 1 || cmds[0] != 0;
+            var rep = [];
+            for (var i in cmds)
+                if (typeof(ansi_colormap[cmds[i]]) != "undefined")
+                    rep.push(ansi_colormap[cmds[i]]);
+            opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":"";
+            txt = txt.replace(re, closer + opener);
+        }
+        if (opened) txt += "</span>";
+        return txt;
+    }
+
+
+    grow = function(element) {
+        // Grow the cell by hand. This is used upon reloading from JSON, when the
+        // autogrow handler is not called.
+        var dom = element.get(0);
+        var lines_count = 0;
+        // modified split rule from
+        // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
+        var lines = dom.value.split(/\r|\r\n|\n/);
+        lines_count = lines.length;
+        if (lines_count >= 1) {
+            dom.rows = lines_count;
+        } else {
+            dom.rows = 1;
+        }
+    };
+
+
+    return {
+        uuid : uuid,
+        fixConsole : fixConsole,
+        grow : grow
+    };
+
+}(IPython));
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/pagedown/LICENSE.txt b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pagedown/LICENSE.txt
new file mode 100644
index 0000000..ca48b4f
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pagedown/LICENSE.txt
@@ -0,0 +1,32 @@
+A javascript port of Markdown, as used on Stack Overflow
+and the rest of Stack Exchange network.
+
+Largely based on showdown.js by John Fraser (Attacklab).
+
+Original Markdown Copyright (c) 2004-2005 John Gruber
+  <http://daringfireball.net/projects/markdown/>
+
+
+Original Showdown code copyright (c) 2007 John Fraser
+
+Modifications and bugfixes (c) 2009 Dana Robinson
+Modifications and bugfixes (c) 2009-2011 Stack Exchange Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/pagedown/Markdown.Converter.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pagedown/Markdown.Converter.js
new file mode 100644
index 0000000..9a1a4f7
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pagedown/Markdown.Converter.js
@@ -0,0 +1,1318 @@
+var Markdown;
+
+if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module
+    Markdown = exports;
+else
+    Markdown = {};
+    
+// The following text is included for historical reasons, but should
+// be taken with a pinch of salt; it's not all true anymore.
+
+//
+// Wherever possible, Showdown is a straight, line-by-line port
+// of the Perl version of Markdown.
+//
+// This is not a normal parser design; it's basically just a
+// series of string substitutions.  It's hard to read and
+// maintain this way,  but keeping Showdown close to the original
+// design makes it easier to port new features.
+//
+// More importantly, Showdown behaves like markdown.pl in most
+// edge cases.  So web applications can do client-side preview
+// in Javascript, and then build identical HTML on the server.
+//
+// This port needs the new RegExp functionality of ECMA 262,
+// 3rd Edition (i.e. Javascript 1.5).  Most modern web browsers
+// should do fine.  Even with the new regular expression features,
+// We do a lot of work to emulate Perl's regex functionality.
+// The tricky changes in this file mostly have the "attacklab:"
+// label.  Major or self-explanatory changes don't.
+//
+// Smart diff tools like Araxis Merge will be able to match up
+// this file with markdown.pl in a useful way.  A little tweaking
+// helps: in a copy of markdown.pl, replace "#" with "//" and
+// replace "$text" with "text".  Be sure to ignore whitespace
+// and line endings.
+//
+
+
+//
+// Usage:
+//
+//   var text = "Markdown *rocks*.";
+//
+//   var converter = new Markdown.Converter();
+//   var html = converter.makeHtml(text);
+//
+//   alert(html);
+//
+// Note: move the sample code to the bottom of this
+// file before uncommenting it.
+//
+
+(function () {
+
+    function identity(x) { return x; }
+    function returnFalse(x) { return false; }
+
+    function HookCollection() { }
+
+    HookCollection.prototype = {
+
+        chain: function (hookname, func) {
+            var original = this[hookname];
+            if (!original)
+                throw new Error("unknown hook " + hookname);
+
+            if (original === identity)
+                this[hookname] = func;
+            else
+                this[hookname] = function (x) { return func(original(x)); }
+        },
+        set: function (hookname, func) {
+            if (!this[hookname])
+                throw new Error("unknown hook " + hookname);
+            this[hookname] = func;
+        },
+        addNoop: function (hookname) {
+            this[hookname] = identity;
+        },
+        addFalse: function (hookname) {
+            this[hookname] = returnFalse;
+        }
+    };
+
+    Markdown.HookCollection = HookCollection;
+
+    // g_urls and g_titles allow arbitrary user-entered strings as keys. This
+    // caused an exception (and hence stopped the rendering) when the user entered
+    // e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this
+    // (since no builtin property starts with "s_"). See
+    // http://meta.stackoverflow.com/questions/64655/strange-wmd-bug
+    // (granted, switching from Array() to Object() alone would have left only __proto__
+    // to be a problem)
+    function SaveHash() { }
+    SaveHash.prototype = {
+        set: function (key, value) {
+            this["s_" + key] = value;
+        },
+        get: function (key) {
+            return this["s_" + key];
+        }
+    };
+
+    Markdown.Converter = function () {
+        var pluginHooks = this.hooks = new HookCollection();
+        pluginHooks.addNoop("plainLinkText");  // given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link
+        pluginHooks.addNoop("preConversion");  // called with the orignal text as given to makeHtml. The result of this plugin hook is the actual markdown source that will be cooked
+        pluginHooks.addNoop("postConversion"); // called with the final cooked HTML code. The result of this plugin hook is the actual output of makeHtml
+
+        //
+        // Private state of the converter instance:
+        //
+
+        // Global hashes, used by various utility routines
+        var g_urls;
+        var g_titles;
+        var g_html_blocks;
+
+        // Used to track when we're inside an ordered or unordered list
+        // (see _ProcessListItems() for details):
+        var g_list_level;
+
+        this.makeHtml = function (text) {
+
+            //
+            // Main function. The order in which other subs are called here is
+            // essential. Link and image substitutions need to happen before
+            // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>
+            // and <img> tags get encoded.
+            //
+
+            // This will only happen if makeHtml on the same converter instance is called from a plugin hook.
+            // Don't do that.
+            if (g_urls)
+                throw new Error("Recursive call to converter.makeHtml");
+        
+            // Create the private state objects.
+            g_urls = new SaveHash();
+            g_titles = new SaveHash();
+            g_html_blocks = [];
+            g_list_level = 0;
+
+            text = pluginHooks.preConversion(text);
+
+            // attacklab: Replace ~ with ~T
+            // This lets us use tilde as an escape char to avoid md5 hashes
+            // The choice of character is arbitray; anything that isn't
+            // magic in Markdown will work.
+            text = text.replace(/~/g, "~T");
+
+            // attacklab: Replace $ with ~D
+            // RegExp interprets $ as a special character
+            // when it's in a replacement string
+            text = text.replace(/\$/g, "~D");
+
+            // Standardize line endings
+            text = text.replace(/\r\n/g, "\n"); // DOS to Unix
+            text = text.replace(/\r/g, "\n"); // Mac to Unix
+
+            // Make sure text begins and ends with a couple of newlines:
+            text = "\n\n" + text + "\n\n";
+
+            // Convert all tabs to spaces.
+            text = _Detab(text);
+
+            // Strip any lines consisting only of spaces and tabs.
+            // This makes subsequent regexen easier to write, because we can
+            // match consecutive blank lines with /\n+/ instead of something
+            // contorted like /[ \t]*\n+/ .
+            text = text.replace(/^[ \t]+$/mg, "");
+
+            // Turn block-level HTML blocks into hash entries
+            text = _HashHTMLBlocks(text);
+
+            // Strip link definitions, store in hashes.
+            text = _StripLinkDefinitions(text);
+
+            text = _RunBlockGamut(text);
+
+            text = _UnescapeSpecialChars(text);
+
+            // attacklab: Restore dollar signs
+            text = text.replace(/~D/g, "$$");
+
+            // attacklab: Restore tildes
+            text = text.replace(/~T/g, "~");
+
+            text = pluginHooks.postConversion(text);
+
+            g_html_blocks = g_titles = g_urls = null;
+
+            return text;
+        };
+
+        function _StripLinkDefinitions(text) {
+            //
+            // Strips link definitions from text, stores the URLs and titles in
+            // hash references.
+            //
+
+            // Link defs are in the form: ^[id]: url "optional title"
+
+            /*
+            text = text.replace(/
+                ^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1
+                [ \t]*
+                \n?                 // maybe *one* newline
+                [ \t]*
+                <?(\S+?)>?          // url = $2
+                (?=\s|$)            // lookahead for whitespace instead of the lookbehind removed below
+                [ \t]*
+                \n?                 // maybe one newline
+                [ \t]*
+                (                   // (potential) title = $3
+                    (\n*)           // any lines skipped = $4 attacklab: lookbehind removed
+                    [ \t]+
+                    ["(]
+                    (.+?)           // title = $5
+                    [")]
+                    [ \t]*
+                )?                  // title is optional
+                (?:\n+|$)
+            /gm, function(){...});
+            */
+
+            text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,
+                function (wholeMatch, m1, m2, m3, m4, m5) {
+                    m1 = m1.toLowerCase();
+                    g_urls.set(m1, _EncodeAmpsAndAngles(m2));  // Link IDs are case-insensitive
+                    if (m4) {
+                        // Oops, found blank lines, so it's not a title.
+                        // Put back the parenthetical statement we stole.
+                        return m3;
+                    } else if (m5) {
+                        g_titles.set(m1, m5.replace(/"/g, """));
+                    }
+
+                    // Completely remove the definition from the text
+                    return "";
+                }
+            );
+
+            return text;
+        }
+
+        function _HashHTMLBlocks(text) {
+
+            // Hashify HTML blocks:
+            // We only want to do this for block-level HTML tags, such as headers,
+            // lists, and tables. That's because we still want to wrap <p>s around
+            // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+            // phrase emphasis, and spans. The list of tags we're looking for is
+            // hard-coded:
+            var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
+            var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
+
+            // First, look for nested blocks, e.g.:
+            //   <div>
+            //     <div>
+            //     tags for inner block must be indented.
+            //     </div>
+            //   </div>
+            //
+            // The outermost tags must start at the left margin for this to match, and
+            // the inner nested divs must be indented.
+            // We need to do this before the next, more liberal match, because the next
+            // match will start at the first `<div>` and stop at the first `</div>`.
+
+            // attacklab: This regex can be expensive when it fails.
+
+            /*
+            text = text.replace(/
+                (                       // save in $1
+                    ^                   // start of line  (with /m)
+                    <($block_tags_a)    // start tag = $2
+                    \b                  // word break
+                                        // attacklab: hack around khtml/pcre bug...
+                    [^\r]*?\n           // any number of lines, minimally matching
+                    </\2>               // the matching end tag
+                    [ \t]*              // trailing spaces/tabs
+                    (?=\n+)             // followed by a newline
+                )                       // attacklab: there are sentinel newlines at end of document
+            /gm,function(){...}};
+            */
+            text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashElement);
+
+            //
+            // Now match more liberally, simply from `\n<tag>` to `</tag>\n`
+            //
+
+            /*
+            text = text.replace(/
+                (                       // save in $1
+                    ^                   // start of line  (with /m)
+                    <($block_tags_b)    // start tag = $2
+                    \b                  // word break
+                                        // attacklab: hack around khtml/pcre bug...
+                    [^\r]*?             // any number of lines, minimally matching
+                    .*</\2>             // the matching end tag
+                    [ \t]*              // trailing spaces/tabs
+                    (?=\n+)             // followed by a newline
+                )                       // attacklab: there are sentinel newlines at end of document
+            /gm,function(){...}};
+            */
+            text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, hashElement);
+
+            // Special case just for <hr />. It was easier to make a special case than
+            // to make the other regex more complicated.  
+
+            /*
+            text = text.replace(/
+                \n                  // Starting after a blank line
+                [ ]{0,3}
+                (                   // save in $1
+                    (<(hr)          // start tag = $2
+                        \b          // word break
+                        ([^<>])*?
+                    \/?>)           // the matching end tag
+                    [ \t]*
+                    (?=\n{2,})      // followed by a blank line
+                )
+            /g,hashElement);
+            */
+            text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement);
+
+            // Special case for standalone HTML comments:
+
+            /*
+            text = text.replace(/
+                \n\n                                            // Starting after a blank line
+                [ ]{0,3}                                        // attacklab: g_tab_width - 1
+                (                                               // save in $1
+                    <!
+                    (--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)   // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256
+                    >
+                    [ \t]*
+                    (?=\n{2,})                                  // followed by a blank line
+                )
+            /g,hashElement);
+            */
+            text = text.replace(/\n\n[ ]{0,3}(<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashElement);
+
+            // PHP and ASP-style processor instructions (<?...?> and <%...%>)
+
+            /*
+            text = text.replace(/
+                (?:
+                    \n\n            // Starting after a blank line
+                )
+                (                   // save in $1
+                    [ ]{0,3}        // attacklab: g_tab_width - 1
+                    (?:
+                        <([?%])     // $2
+                        [^\r]*?
+                        \2>
+                    )
+                    [ \t]*
+                    (?=\n{2,})      // followed by a blank line
+                )
+            /g,hashElement);
+            */
+            text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement);
+
+            return text;
+        }
+
+        function hashElement(wholeMatch, m1) {
+            var blockText = m1;
+
+            // Undo double lines
+            blockText = blockText.replace(/^\n+/, "");
+
+            // strip trailing blank lines
+            blockText = blockText.replace(/\n+$/g, "");
+
+            // Replace the element text with a marker ("~KxK" where x is its key)
+            blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n";
+
+            return blockText;
+        }
+
+        function _RunBlockGamut(text, doNotUnhash) {
+            //
+            // These are all the transformations that form block-level
+            // tags like paragraphs, headers, and list items.
+            //
+            text = _DoHeaders(text);
+
+            // Do Horizontal Rules:
+            var replacement = "<hr />\n";
+            text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, replacement);
+            text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm, replacement);
+            text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, replacement);
+
+            text = _DoLists(text);
+            text = _DoCodeBlocks(text);
+            text = _DoBlockQuotes(text);
+
+            // We already ran _HashHTMLBlocks() before, in Markdown(), but that
+            // was to escape raw HTML in the original Markdown source. This time,
+            // we're escaping the markup we've just created, so that we don't wrap
+            // <p> tags around block-level tags.
+            text = _HashHTMLBlocks(text);
+            text = _FormParagraphs(text, doNotUnhash);
+
+            return text;
+        }
+
+        function _RunSpanGamut(text) {
+            //
+            // These are all the transformations that occur *within* block-level
+            // tags like paragraphs, headers, and list items.
+            //
+
+            text = _DoCodeSpans(text);
+            text = _EscapeSpecialCharsWithinTagAttributes(text);
+            text = _EncodeBackslashEscapes(text);
+
+            // Process anchor and image tags. Images must come first,
+            // because ![foo][f] looks like an anchor.
+            text = _DoImages(text);
+            text = _DoAnchors(text);
+
+            // Make links out of things like `<http://example.com/>`
+            // Must come after _DoAnchors(), because you can use < and >
+            // delimiters in inline links like [this](<url>).
+            text = _DoAutoLinks(text);
+            text = _EncodeAmpsAndAngles(text);
+            text = _DoItalicsAndBold(text);
+
+            // Do hard breaks:
+            text = text.replace(/  +\n/g, " <br>\n");
+
+            return text;
+        }
+
+        function _EscapeSpecialCharsWithinTagAttributes(text) {
+            //
+            // Within tags -- meaning between < and > -- encode [\ ` * _] so they
+            // don't conflict with their use in Markdown for code, italics and strong.
+            //
+
+            // Build a regex to find HTML tags and comments.  See Friedl's 
+            // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+
+            // SE: changed the comment part of the regex
+
+            var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;
+
+            text = text.replace(regex, function (wholeMatch) {
+                var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
+                tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987
+                return tag;
+            });
+
+            return text;
+        }
+
+        function _DoAnchors(text) {
+            //
+            // Turn Markdown link shortcuts into XHTML <a> tags.
+            //
+            //
+            // First, handle reference-style links: [link text] [id]
+            //
+
+            /*
+            text = text.replace(/
+                (                           // wrap whole match in $1
+                    \[
+                    (
+                        (?:
+                            \[[^\]]*\]      // allow brackets nested one level
+                            |
+                            [^\[]           // or anything else
+                        )*
+                    )
+                    \]
+
+                    [ ]?                    // one optional space
+                    (?:\n[ ]*)?             // one optional newline followed by spaces
+
+                    \[
+                    (.*?)                   // id = $3
+                    \]
+                )
+                ()()()()                    // pad remaining backreferences
+            /g, writeAnchorTag);
+            */
+            text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
+
+            //
+            // Next, inline-style links: [link text](url "optional title")
+            //
+
+            /*
+            text = text.replace(/
+                (                           // wrap whole match in $1
+                    \[
+                    (
+                        (?:
+                            \[[^\]]*\]      // allow brackets nested one level
+                            |
+                            [^\[\]]         // or anything else
+                        )*
+                    )
+                    \]
+                    \(                      // literal paren
+                    [ \t]*
+                    ()                      // no id, so leave $3 empty
+                    <?(                     // href = $4
+                        (?:
+                            \([^)]*\)       // allow one level of (correctly nested) parens (think MSDN)
+                            |
+                            [^()]
+                        )*?
+                    )>?                
+                    [ \t]*
+                    (                       // $5
+                        (['"])              // quote char = $6
+                        (.*?)               // Title = $7
+                        \6                  // matching quote
+                        [ \t]*              // ignore any spaces/tabs between closing quote and )
+                    )?                      // title is optional
+                    \)
+                )
+            /g, writeAnchorTag);
+            */
+
+            text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?((?:\([^)]*\)|[^()])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
+
+            //
+            // Last, handle reference-style shortcuts: [link text]
+            // These must come last in case you've also got [link test][1]
+            // or [link test](/foo)
+            //
+
+            /*
+            text = text.replace(/
+                (                   // wrap whole match in $1
+                    \[
+                    ([^\[\]]+)      // link text = $2; can't contain '[' or ']'
+                    \]
+                )
+                ()()()()()          // pad rest of backreferences
+            /g, writeAnchorTag);
+            */
+            text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
+
+            return text;
+        }
+
+        function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+            if (m7 == undefined) m7 = "";
+            var whole_match = m1;
+            var link_text = m2;
+            var link_id = m3.toLowerCase();
+            var url = m4;
+            var title = m7;
+
+            if (url == "") {
+                if (link_id == "") {
+                    // lower-case and turn embedded newlines into spaces
+                    link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");
+                }
+                url = "#" + link_id;
+
+                if (g_urls.get(link_id) != undefined) {
+                    url = g_urls.get(link_id);
+                    if (g_titles.get(link_id) != undefined) {
+                        title = g_titles.get(link_id);
+                    }
+                }
+                else {
+                    if (whole_match.search(/\(\s*\)$/m) > -1) {
+                        // Special case for explicit empty url
+                        url = "";
+                    } else {
+                        return whole_match;
+                    }
+                }
+            }
+            url = encodeProblemUrlChars(url);
+            url = escapeCharacters(url, "*_");
+            var result = "<a href=\"" + url + "\"";
+
+            if (title != "") {
+                title = title.replace(/"/g, """);
+                title = escapeCharacters(title, "*_");
+                result += " title=\"" + title + "\"";
+            }
+
+            result += ">" + link_text + "</a>";
+
+            return result;
+        }
+
+        function _DoImages(text) {
+            //
+            // Turn Markdown image shortcuts into <img> tags.
+            //
+
+            //
+            // First, handle reference-style labeled images: ![alt text][id]
+            //
+
+            /*
+            text = text.replace(/
+                (                   // wrap whole match in $1
+                    !\[
+                    (.*?)           // alt text = $2
+                    \]
+
+                    [ ]?            // one optional space
+                    (?:\n[ ]*)?     // one optional newline followed by spaces
+
+                    \[
+                    (.*?)           // id = $3
+                    \]
+                )
+                ()()()()            // pad rest of backreferences
+            /g, writeImageTag);
+            */
+            text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
+
+            //
+            // Next, handle inline images:  ![alt text](url "optional title")
+            // Don't forget: encode * and _
+
+            /*
+            text = text.replace(/
+                (                   // wrap whole match in $1
+                    !\[
+                    (.*?)           // alt text = $2
+                    \]
+                    \s?             // One optional whitespace character
+                    \(              // literal paren
+                    [ \t]*
+                    ()              // no id, so leave $3 empty
+                    <?(\S+?)>?      // src url = $4
+                    [ \t]*
+                    (               // $5
+                        (['"])      // quote char = $6
+                        (.*?)       // title = $7
+                        \6          // matching quote
+                        [ \t]*
+                    )?              // title is optional
+                    \)
+                )
+            /g, writeImageTag);
+            */
+            text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
+
+            return text;
+        }
+
+        function writeImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+            var whole_match = m1;
+            var alt_text = m2;
+            var link_id = m3.toLowerCase();
+            var url = m4;
+            var title = m7;
+
+            if (!title) title = "";
+
+            if (url == "") {
+                if (link_id == "") {
+                    // lower-case and turn embedded newlines into spaces
+                    link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");
+                }
+                url = "#" + link_id;
+
+                if (g_urls.get(link_id) != undefined) {
+                    url = g_urls.get(link_id);
+                    if (g_titles.get(link_id) != undefined) {
+                        title = g_titles.get(link_id);
+                    }
+                }
+                else {
+                    return whole_match;
+                }
+            }
+
+            alt_text = alt_text.replace(/"/g, """);
+            url = escapeCharacters(url, "*_");
+            var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
+
+            // attacklab: Markdown.pl adds empty title attributes to images.
+            // Replicate this bug.
+
+            //if (title != "") {
+            title = title.replace(/"/g, """);
+            title = escapeCharacters(title, "*_");
+            result += " title=\"" + title + "\"";
+            //}
+
+            result += " />";
+
+            return result;
+        }
+
+        function _DoHeaders(text) {
+
+            // Setext-style headers:
+            //  Header 1
+            //  ========
+            //  
+            //  Header 2
+            //  --------
+            //
+            text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+                function (wholeMatch, m1) { return "<h1>" + _RunSpanGamut(m1) + "</h1>\n\n"; }
+            );
+
+            text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
+                function (matchFound, m1) { return "<h2>" + _RunSpanGamut(m1) + "</h2>\n\n"; }
+            );
+
+            // atx-style headers:
+            //  # Header 1
+            //  ## Header 2
+            //  ## Header 2 with closing hashes ##
+            //  ...
+            //  ###### Header 6
+            //
+
+            /*
+            text = text.replace(/
+                ^(\#{1,6})      // $1 = string of #'s
+                [ \t]*
+                (.+?)           // $2 = Header text
+                [ \t]*
+                \#*             // optional closing #'s (not counted)
+                \n+
+            /gm, function() {...});
+            */
+
+            text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
+                function (wholeMatch, m1, m2) {
+                    var h_level = m1.length;
+                    return "<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">\n\n";
+                }
+            );
+
+            return text;
+        }
+
+        function _DoLists(text) {
+            //
+            // Form HTML ordered (numbered) and unordered (bulleted) lists.
+            //
+
+            // attacklab: add sentinel to hack around khtml/safari bug:
+            // http://bugs.webkit.org/show_bug.cgi?id=11231
+            text += "~0";
+
+            // Re-usable pattern to match any entirel ul or ol list:
+
+            /*
+            var whole_list = /
+                (                                   // $1 = whole list
+                    (                               // $2
+                        [ ]{0,3}                    // attacklab: g_tab_width - 1
+                        ([*+-]|\d+[.])              // $3 = first list item marker
+                        [ \t]+
+                    )
+                    [^\r]+?
+                    (                               // $4
+                        ~0                          // sentinel for workaround; should be $
+                        |
+                        \n{2,}
+                        (?=\S)
+                        (?!                         // Negative lookahead for another list item marker
+                            [ \t]*
+                            (?:[*+-]|\d+[.])[ \t]+
+                        )
+                    )
+                )
+            /g
+            */
+            var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
+
+            if (g_list_level) {
+                text = text.replace(whole_list, function (wholeMatch, m1, m2) {
+                    var list = m1;
+                    var list_type = (m2.search(/[*+-]/g) > -1) ? "ul" : "ol";
+
+                    var result = _ProcessListItems(list, list_type);
+
+                    // Trim any trailing whitespace, to put the closing `</$list_type>`
+                    // up on the preceding line, to get it past the current stupid
+                    // HTML block parser. This is a hack to work around the terrible
+                    // hack that is the HTML block parser.
+                    result = result.replace(/\s+$/, "");
+                    result = "<" + list_type + ">" + result + "</" + list_type + ">\n";
+                    return result;
+                });
+            } else {
+                whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
+                text = text.replace(whole_list, function (wholeMatch, m1, m2, m3) {
+                    var runup = m1;
+                    var list = m2;
+
+                    var list_type = (m3.search(/[*+-]/g) > -1) ? "ul" : "ol";
+                    var result = _ProcessListItems(list, list_type);
+                    result = runup + "<" + list_type + ">\n" + result + "</" + list_type + ">\n";
+                    return result;
+                });
+            }
+
+            // attacklab: strip sentinel
+            text = text.replace(/~0/, "");
+
+            return text;
+        }
+
+        var _listItemMarkers = { ol: "\\d+[.]", ul: "[*+-]" };
+
+        function _ProcessListItems(list_str, list_type) {
+            //
+            //  Process the contents of a single ordered or unordered list, splitting it
+            //  into individual list items.
+            //
+            //  list_type is either "ul" or "ol".
+
+            // The $g_list_level global keeps track of when we're inside a list.
+            // Each time we enter a list, we increment it; when we leave a list,
+            // we decrement. If it's zero, we're not in a list anymore.
+            //
+            // We do this because when we're not inside a list, we want to treat
+            // something like this:
+            //
+            //    I recommend upgrading to version
+            //    8. Oops, now this line is treated
+            //    as a sub-list.
+            //
+            // As a single paragraph, despite the fact that the second line starts
+            // with a digit-period-space sequence.
+            //
+            // Whereas when we're inside a list (or sub-list), that line will be
+            // treated as the start of a sub-list. What a kludge, huh? This is
+            // an aspect of Markdown's syntax that's hard to parse perfectly
+            // without resorting to mind-reading. Perhaps the solution is to
+            // change the syntax rules such that sub-lists must start with a
+            // starting cardinal number; e.g. "1." or "a.".
+
+            g_list_level++;
+
+            // trim trailing blank lines:
+            list_str = list_str.replace(/\n{2,}$/, "\n");
+
+            // attacklab: add sentinel to emulate \z
+            list_str += "~0";
+
+            // In the original attacklab showdown, list_type was not given to this function, and anything
+            // that matched /[*+-]|\d+[.]/ would just create the next <li>, causing this mismatch:
+            //
+            //  Markdown          rendered by WMD        rendered by MarkdownSharp
+            //  ------------------------------------------------------------------
+            //  1. first          1. first               1. first
+            //  2. second         2. second              2. second
+            //  - third           3. third                   * third
+            //
+            // We changed this to behave identical to MarkdownSharp. This is the constructed RegEx,
+            // with {MARKER} being one of \d+[.] or [*+-], depending on list_type:
+        
+            /*
+            list_str = list_str.replace(/
+                (^[ \t]*)                       // leading whitespace = $1
+                ({MARKER}) [ \t]+               // list marker = $2
+                ([^\r]+?                        // list item text   = $3
+                    (\n+)
+                )
+                (?=
+                    (~0 | \2 ({MARKER}) [ \t]+)
+                )
+            /gm, function(){...});
+            */
+
+            var marker = _listItemMarkers[list_type];
+            var re = new RegExp("(^[ \\t]*)(" + marker + ")[ \\t]+([^\\r]+?(\\n+))(?=(~0|\\1(" + marker + ")[ \\t]+))", "gm");
+            var last_item_had_a_double_newline = false;
+            list_str = list_str.replace(re,
+                function (wholeMatch, m1, m2, m3) {
+                    var item = m3;
+                    var leading_space = m1;
+                    var ends_with_double_newline = /\n\n$/.test(item);
+                    var contains_double_newline = ends_with_double_newline || item.search(/\n{2,}/) > -1;
+
+                    if (contains_double_newline || last_item_had_a_double_newline) {
+                        item = _RunBlockGamut(_Outdent(item), /* doNotUnhash = */true);
+                    }
+                    else {
+                        // Recursion for sub-lists:
+                        item = _DoLists(_Outdent(item));
+                        item = item.replace(/\n$/, ""); // chomp(item)
+                        item = _RunSpanGamut(item);
+                    }
+                    last_item_had_a_double_newline = ends_with_double_newline;
+                    return "<li>" + item + "</li>\n";
+                }
+            );
+
+            // attacklab: strip sentinel
+            list_str = list_str.replace(/~0/g, "");
+
+            g_list_level--;
+            return list_str;
+        }
+
+        function _DoCodeBlocks(text) {
+            //
+            //  Process Markdown `<pre><code>` blocks.
+            //  
+
+            /*
+            text = text.replace(/
+                (?:\n\n|^)
+                (                               // $1 = the code block -- one or more lines, starting with a space/tab
+                    (?:
+                        (?:[ ]{4}|\t)           // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+                        .*\n+
+                    )+
+                )
+                (\n*[ ]{0,3}[^ \t\n]|(?=~0))    // attacklab: g_tab_width
+            /g ,function(){...});
+            */
+
+            // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+            text += "~0";
+
+            text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
+                function (wholeMatch, m1, m2) {
+                    var codeblock = m1;
+                    var nextChar = m2;
+
+                    codeblock = _EncodeCode(_Outdent(codeblock));
+                    codeblock = _Detab(codeblock);
+                    codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
+                    codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
+
+                    codeblock = "<pre><code>" + codeblock + "\n</code></pre>";
+
+                    return "\n\n" + codeblock + "\n\n" + nextChar;
+                }
+            );
+
+            // attacklab: strip sentinel
+            text = text.replace(/~0/, "");
+
+            return text;
+        }
+
+        function hashBlock(text) {
+            text = text.replace(/(^\n+|\n+$)/g, "");
+            return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
+        }
+
+        function _DoCodeSpans(text) {
+            //
+            // * Backtick quotes are used for <code></code> spans.
+            // 
+            // * You can use multiple backticks as the delimiters if you want to
+            //   include literal backticks in the code span. So, this input:
+            //     
+            //      Just type ``foo `bar` baz`` at the prompt.
+            //     
+            //   Will translate to:
+            //     
+            //      <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
+            //     
+            //   There's no arbitrary limit to the number of backticks you
+            //   can use as delimters. If you need three consecutive backticks
+            //   in your code, use four for delimiters, etc.
+            //
+            // * You can use spaces to get literal backticks at the edges:
+            //     
+            //      ... type `` `bar` `` ...
+            //     
+            //   Turns to:
+            //     
+            //      ... type <code>`bar`</code> ...
+            //
+
+            /*
+            text = text.replace(/
+                (^|[^\\])       // Character before opening ` can't be a backslash
+                (`+)            // $2 = Opening run of `
+                (               // $3 = The code block
+                    [^\r]*?
+                    [^`]        // attacklab: work around lack of lookbehind
+                )
+                \2              // Matching closer
+                (?!`)
+            /gm, function(){...});
+            */
+
+            text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
+                function (wholeMatch, m1, m2, m3, m4) {
+                    var c = m3;
+                    c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
+                    c = c.replace(/[ \t]*$/g, ""); // trailing whitespace
+                    c = _EncodeCode(c);
+                    return m1 + "<code>" + c + "</code>";
+                }
+            );
+
+            return text;
+        }
+
+        function _EncodeCode(text) {
+            //
+            // Encode/escape certain characters inside Markdown code runs.
+            // The point is that in code, these characters are literals,
+            // and lose their special Markdown meanings.
+            //
+            // Encode all ampersands; HTML entities are not
+            // entities within a Markdown code span.
+            text = text.replace(/&/g, "&");
+
+            // Do the angle bracket song and dance:
+            text = text.replace(/</g, "<");
+            text = text.replace(/>/g, ">");
+
+            // Now, escape characters that are magic in Markdown:
+            text = escapeCharacters(text, "\*_{}[]\\", false);
+
+            // jj the line above breaks this:
+            //---
+
+            //* Item
+
+            //   1. Subitem
+
+            //            special char: *
+            //---
+
+            return text;
+        }
+
+        function _DoItalicsAndBold(text) {
+
+            // <strong> must go first:
+            text = text.replace(/([\W_]|^)(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\2([\W_]|$)/g,
+            "$1<strong>$3</strong>$4");
+
+            text = text.replace(/([\W_]|^)(\*|_)(?=\S)([^\r\*_]*?\S)\2([\W_]|$)/g,
+            "$1<em>$3</em>$4");
+
+            return text;
+        }
+
+        function _DoBlockQuotes(text) {
+
+            /*
+            text = text.replace(/
+                (                           // Wrap whole match in $1
+                    (
+                        ^[ \t]*>[ \t]?      // '>' at the start of a line
+                        .+\n                // rest of the first line
+                        (.+\n)*             // subsequent consecutive lines
+                        \n*                 // blanks
+                    )+
+                )
+            /gm, function(){...});
+            */
+
+            text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
+                function (wholeMatch, m1) {
+                    var bq = m1;
+
+                    // attacklab: hack around Konqueror 3.5.4 bug:
+                    // "----------bug".replace(/^-/g,"") == "bug"
+
+                    bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting
+
+                    // attacklab: clean up hack
+                    bq = bq.replace(/~0/g, "");
+
+                    bq = bq.replace(/^[ \t]+$/gm, "");     // trim whitespace-only lines
+                    bq = _RunBlockGamut(bq);             // recurse
+
+                    bq = bq.replace(/(^|\n)/g, "$1  ");
+                    // These leading spaces screw with <pre> content, so we need to fix that:
+                    bq = bq.replace(
+                            /(\s*<pre>[^\r]+?<\/pre>)/gm,
+                        function (wholeMatch, m1) {
+                            var pre = m1;
+                            // attacklab: hack around Konqueror 3.5.4 bug:
+                            pre = pre.replace(/^  /mg, "~0");
+                            pre = pre.replace(/~0/g, "");
+                            return pre;
+                        });
+
+                    return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");
+                }
+            );
+            return text;
+        }
+
+        function _FormParagraphs(text, doNotUnhash) {
+            //
+            //  Params:
+            //    $text - string to process with html <p> tags
+            //
+
+            // Strip leading and trailing lines:
+            text = text.replace(/^\n+/g, "");
+            text = text.replace(/\n+$/g, "");
+
+            var grafs = text.split(/\n{2,}/g);
+            var grafsOut = [];
+
+            //
+            // Wrap <p> tags.
+            //
+            var end = grafs.length;
+            for (var i = 0; i < end; i++) {
+                var str = grafs[i];
+
+                // if this is an HTML marker, copy it
+                if (str.search(/~K(\d+)K/g) >= 0) {
+                    grafsOut.push(str);
+                }
+                else if (str.search(/\S/) >= 0) {
+                    str = _RunSpanGamut(str);
+                    str = str.replace(/^([ \t]*)/g, "<p>");
+                    str += "</p>"
+                    grafsOut.push(str);
+                }
+
+            }
+            //
+            // Unhashify HTML blocks
+            //
+            if (!doNotUnhash) {
+                end = grafsOut.length;
+                for (var i = 0; i < end; i++) {
+                    // if this is a marker for an html block...
+                    while (grafsOut[i].search(/~K(\d+)K/) >= 0) {
+                        var blockText = g_html_blocks[RegExp.$1];
+                        blockText = blockText.replace(/\$/g, "$$$$"); // Escape any dollar signs
+                        grafsOut[i] = grafsOut[i].replace(/~K\d+K/, blockText);
+                    }
+                }
+            }
+            return grafsOut.join("\n\n");
+        }
+
+        function _EncodeAmpsAndAngles(text) {
+            // Smart processing for ampersands and angle brackets that need to be encoded.
+
+            // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
+            //   http://bumppo.net/projects/amputator/
+            text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&");
+
+            // Encode naked <'s
+            text = text.replace(/<(?![a-z\/?\$!])/gi, "<");
+
+            return text;
+        }
+
+        function _EncodeBackslashEscapes(text) {
+            //
+            //   Parameter:  String.
+            //   Returns:    The string, with after processing the following backslash
+            //               escape sequences.
+            //
+
+            // attacklab: The polite way to do this is with the new
+            // escapeCharacters() function:
+            //
+            //     text = escapeCharacters(text,"\\",true);
+            //     text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
+            //
+            // ...but we're sidestepping its use of the (slow) RegExp constructor
+            // as an optimization for Firefox.  This function gets called a LOT.
+
+            text = text.replace(/\\(\\)/g, escapeCharacters_callback);
+            text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, escapeCharacters_callback);
+            return text;
+        }
+
+        function _DoAutoLinks(text) {
+
+            // note that at this point, all other URL in the text are already hyperlinked as <a href=""></a>
+            // *except* for the <http://www.foo.com> case
+
+            // automatically add < and > around unadorned raw hyperlinks
+            // must be preceded by space/BOF and followed by non-word/EOF character    
+            text = text.replace(/(^|\s)(https?|ftp)(:\/\/[-A-Z0-9+&@#\/%?=~_|\[\]\(\)!:,\.;]*[-A-Z0-9+&@#\/%=~_|\[\]])($|\W)/gi, "$1<$2$3>$4");
+
+            //  autolink anything like <http://example.com>
+            
+            var replacer = function (wholematch, m1) { return "<a href=\"" + m1 + "\">" + pluginHooks.plainLinkText(m1) + "</a>"; }
+            text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, replacer);
+
+            // Email addresses: <address at domain.foo>
+            /*
+            text = text.replace(/
+                <
+                (?:mailto:)?
+                (
+                    [-.\w]+
+                    \@
+                    [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+                )
+                >
+            /gi, _DoAutoLinks_callback());
+            */
+
+            /* disabling email autolinking, since we don't do that on the server, either
+            text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
+                function(wholeMatch,m1) {
+                    return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
+                }
+            );
+            */
+            return text;
+        }
+
+        function _UnescapeSpecialChars(text) {
+            //
+            // Swap back in all the special characters we've hidden.
+            //
+            text = text.replace(/~E(\d+)E/g,
+                function (wholeMatch, m1) {
+                    var charCodeToReplace = parseInt(m1);
+                    return String.fromCharCode(charCodeToReplace);
+                }
+            );
+            return text;
+        }
+
+        function _Outdent(text) {
+            //
+            // Remove one level of line-leading tabs or spaces
+            //
+
+            // attacklab: hack around Konqueror 3.5.4 bug:
+            // "----------bug".replace(/^-/g,"") == "bug"
+
+            text = text.replace(/^(\t|[ ]{1,4})/gm, "~0"); // attacklab: g_tab_width
+
+            // attacklab: clean up hack
+            text = text.replace(/~0/g, "")
+
+            return text;
+        }
+
+        function _Detab(text) {
+            if (!/\t/.test(text))
+                return text;
+
+            var spaces = ["    ", "   ", "  ", " "],
+            skew = 0,
+            v;
+
+            return text.replace(/[\n\t]/g, function (match, offset) {
+                if (match === "\n") {
+                    skew = offset + 1;
+                    return match;
+                }
+                v = (offset - skew) % 4;
+                skew = offset + 1;
+                return spaces[v];
+            });
+        }
+
+        //
+        //  attacklab: Utility functions
+        //
+
+        var _problemUrlChars = /(?:["'*()[\]:]|~D)/g;
+
+        // hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems 
+        function encodeProblemUrlChars(url) {
+            if (!url)
+                return "";
+
+            var len = url.length;
+
+            return url.replace(_problemUrlChars, function (match, offset) {
+                if (match == "~D") // escape for dollar
+                    return "%24";
+                if (match == ":") {
+                    if (offset == len - 1 || /[0-9\/]/.test(url.charAt(offset + 1)))
+                        return ":"
+                }
+                return "%" + match.charCodeAt(0).toString(16);
+            });
+        }
+
+
+        function escapeCharacters(text, charsToEscape, afterBackslash) {
+            // First we have to escape the escape characters so that
+            // we can build a character class out of them
+            var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g, "\\$1") + "])";
+
+            if (afterBackslash) {
+                regexString = "\\\\" + regexString;
+            }
+
+            var regex = new RegExp(regexString, "g");
+            text = text.replace(regex, escapeCharacters_callback);
+
+            return text;
+        }
+
+
+        function escapeCharacters_callback(wholeMatch, m1) {
+            var charCodeToEscape = m1.charCodeAt(0);
+            return "~E" + charCodeToEscape + "E";
+        }
+
+    }; // end of the Markdown.Converter constructor
+
+})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/COPYING b/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/COPYING
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/COPYING
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/prettify.css b/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/prettify.css
new file mode 100644
index 0000000..33b5483
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/prettify.css
@@ -0,0 +1,48 @@
+.pln{
+    color:#000
+}
+
+ at media screen{
+    .str{
+        color:#BA2121;
+    }.kwd{
+        color:#008000;
+        font-weight: bold;
+    }.com{
+        color:#408080;
+        font-style: italic;
+    }.typ{
+        color:#606
+    }.lit{
+        color:#666666;
+    }.pun,.opn,.clo{
+    }.tag{
+        color:#008
+    }.atn{
+        color:#606
+    }.atv{
+        color:#080
+    }.dec,.var{
+        color:#606
+    }.fun{
+        color:red
+    }
+}
+
+pre.prettyprint{
+    padding:2px;
+    border:1px solid #888
+}
+
+ol.linenums{
+    margin-top:0;
+    margin-bottom:0
+}
+
+li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{
+    list-style-type:none
+}
+
+li.L1,li.L3,li.L5,li.L7,li.L9{
+    background:#eee
+}
\ No newline at end of file
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/prettify.js b/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/prettify.js
new file mode 100644
index 0000000..eef5ad7
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/static/prettify/prettify.js
@@ -0,0 +1,28 @@
+var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\ [...]
+[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a) [...]
+f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\ [...]
+(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l= [...]
+{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+ [...]
+t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0 [...]
+"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){fo [...]
+l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s [...]
+q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com [...]
+q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]) [...]
+"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("B [...]
+a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f. [...]
+for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0] [...]
+m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}funct [...]
+a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.n [...]
+j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,uni [...]
+"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,thro [...]
+H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield [...]
+J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,pac [...]
+I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z] [...]
+["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+ [...]
+/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuote [...]
+["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,i [...]
+hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g), [...]
+!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.l [...]
+250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_ [...]
+PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/pytangologo.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pytangologo.png
new file mode 100644
index 0000000..5823afa
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pytangologo.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/static/pytangologo_original.png b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pytangologo_original.png
new file mode 100644
index 0000000..f4ea083
Binary files /dev/null and b/PyTango/ipython/ipython_00_12/examples/notebooks/static/pytangologo_original.png differ
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/templates/layout.html b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/layout.html
new file mode 100644
index 0000000..1ed95be
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/layout.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+    <meta charset="utf-8">
+
+    <title>{% block title %}ITango Notebook{% end %}</title>
+
+    <link rel="stylesheet" href="/static/jquery/css/themes/base/jquery-ui.min.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/base.css" type="text/css"/>
+    {% block stylesheet %}
+    {% end %}
+
+    {% block meta %}
+    {% end %}
+
+</head>
+
+<body {% block params %}{% end %}>
+
+<div id="header">
+    <span id="ipython_notebook"><h1><img src='/static/pytangologo.png' alt='ITango Notebook'/></h1></span>
+
+    {% block login_widget %}
+
+      <span id="login_widget">
+        {% if logged_in %}
+          <button id="logout">Logout</button>
+        {% elif login_available and not logged_in %}
+          <button id="login">Login</button>
+        {% end %}
+      </span>
+
+    {% end %}
+
+    {% block header %}
+    {% end %}
+</div>
+
+<div id="header_border"></div>
+
+<div id="main_app">
+
+    <div id="app_hbox">
+
+    <div id="left_panel">
+    {% block left_panel %}
+    {% end %}
+    </div>
+
+    <div id="content_panel">
+        {% if message %}
+
+          {% for key in message %}
+            <div class="message {{key}}">
+               {{message[key]}}
+            </div>
+          {% end %}
+        {% end %}
+
+        {% block content_panel %}
+        {% end %}
+    </div>
+    <div id="right_panel">
+    {% block right_panel %}
+    {% end %}
+    </div>
+
+    </div>
+
+</div>
+
+<script src="/static/jquery/js/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/jquery/js/jquery-ui.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/loginmain.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
+
+{% block script %}
+{% end %}
+
+</body>
+
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/templates/login.html b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/login.html
new file mode 100644
index 0000000..4c5b2c0
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/login.html
@@ -0,0 +1,26 @@
+{% extends layout.html %}
+
+{% block content_panel %}
+
+    {% if login_available %}
+
+    <form action="/login?next={{url_escape(next)}}" method="post">
+        Password: <input type="password" name="password" id="focus">
+        <input type="submit" value="Sign in" id="signin">
+    </form>
+
+    {% end %}
+
+{% end %}
+
+{% block login_widget %}
+{% end %}
+
+{% block script %}
+<script type="text/javascript">
+  $(document).ready(function() {
+    IPython.login_widget = new IPython.LoginWidget('span#login_widget');
+    $('#focus').focus();
+  });
+</script>
+{% end %}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/templates/logout.html b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/logout.html
new file mode 100644
index 0000000..8087508
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/logout.html
@@ -0,0 +1,28 @@
+{% extends layout.html %}
+
+{% block content_panel %}
+  <ul>
+    {% if read_only or not login_available %}
+
+    Proceed to the <a href="/">list of notebooks</a>.</li>
+
+    {% else %}
+
+    Proceed to the <a href="/login">login page</a>.</li>
+
+    {% end %}
+
+  </ul>
+
+{% end %}
+
+{% block login_widget %}
+{% end %}
+
+{% block script %}
+<script type="text/javascript">
+  $(document).ready(function() {
+    IPython.login_widget = new IPython.LoginWidget('span#login_widget');
+  });
+</script>
+{% end %}
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/templates/notebook.html b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/notebook.html
new file mode 100644
index 0000000..163374e
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/notebook.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+    <meta charset="utf-8">
+
+    <title>ITango Notebook</title>
+
+    {% if mathjax_url %}
+    <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML" charset="utf-8"></script>
+    {% end %}
+    <script type="text/javascript">
+    // MathJax disabled, set as null to distingish from *missing* MathJax,
+    // where it will be undefined, and should prompt a dialog later.
+    window.mathjax_url = "{{mathjax_url}}";
+    </script>
+
+    <link rel="stylesheet" href="/static/jquery/css/themes/base/jquery-ui.min.css" type="text/css" />
+    <link rel="stylesheet" href="/static/codemirror/lib/codemirror.css">
+    <link rel="stylesheet" href="/static/codemirror/theme/ipython.css">
+
+    <link rel="stylesheet" href="/static/prettify/prettify.css"/>
+
+    <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/base.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/notebook.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/renderedhtml.css" type="text/css" />
+
+    {% comment  In the notebook, the read-only flag is used to determine %}
+    {% comment  whether to hide the side panels and switch off input %}
+    <meta name="read_only" content="{{read_only and not logged_in}}"/>
+
+</head>
+
+<body
+    data-project={{project}} data-notebook-id={{notebook_id}}
+    data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
+>
+
+<div id="header">
+    <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='/static/pytangologo.png' alt='ITango Notebook'/></a></h1></span>
+    <span id="save_widget">
+        <span id="notebook_name"></span>
+        <span id="save_status"></span>
+    </span>
+
+    <span id="login_widget">
+      {% comment  This is a temporary workaround to hide the logout button %}
+      {% comment  when appropriate until notebook.html is templated %}
+      {% if logged_in %}
+        <button id="logout">Logout</button>
+      {% elif not logged_in and login_available %}
+        <button id="login">Login</button>
+      {% end %}
+    </span>
+
+    <span id="kernel_status">Idle</span>
+</div>
+
+<div id="menubar">
+    <ul id="menus">
+        <li><a href="#">File</a>
+            <ul>
+                <li id="new_notebook"><a href="#">New</a></li>
+                <li id="open_notebook"><a href="#">Open...</a></li>
+                <hr/>
+                <li id="copy_notebook"><a href="#">Make a Copy...</a></li>
+                <li id="rename_notebook"><a href="#">Rename...</a></li>
+                <li id="save_notebook"><a href="#">Save</a></li>
+                <hr/>
+                <li><a href="#">Download as</a>
+                    <ul>
+                        <li id="download_ipynb"><a href="#">IPython (.ipynb)</a></li>
+                        <li id="download_py"><a href="#">Python (.py)</a></li>
+                    </ul>
+                </li>
+                <hr/>
+                <li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
+            </ul>
+        </li>
+        <li><a href="#">Edit</a>
+            <ul>
+                <li id="cut_cell"><a href="#">Cut</a></li>
+                <li id="copy_cell"><a href="#">Copy</a></li>
+                <li id="paste_cell" class="ui-state-disabled"><a href="#">Paste</a></li>
+                <li id="paste_cell_above" class="ui-state-disabled"><a href="#">Paste Above</a></li>
+                <li id="paste_cell_below" class="ui-state-disabled"><a href="#">Paste Below</a></li>
+                <li id="delete_cell"><a href="#">Delete</a></li>
+                <hr/>
+                <li id="split_cell"><a href="#">Split</a></li>
+                <li id="merge_cell_above"><a href="#">Merge Above</a></li>
+                <li id="merge_cell_below"><a href="#">Merge Below</a></li>
+                <hr/>
+                <li id="move_cell_up"><a href="#">Move Up</a></li>
+                <li id="move_cell_down"><a href="#">Move Down</a></li>
+                <hr/>
+                <li id="select_previous"><a href="#">Select Previous</a></li>
+                <li id="select_next"><a href="#">Select Next</a></li>
+            </ul>
+        </li>
+        <li><a href="#">Insert</a>
+            <ul>
+                <li id="insert_cell_above"><a href="#">Insert Cell Above</a></li>
+                <li id="insert_cell_below"><a href="#">Insert Cell Below</a></li>
+            </ul>
+        </li>
+        <li><a href="#">Cell</a>
+            <ul>
+                <li id="full_edit_cell"><a href="#">Edit in Ace</a></li>
+                <hr/>
+                <li id="run_cell"><a href="#">Run</a></li>
+                <li id="run_cell_in_place"><a href="#">Run in Place</a></li>
+                <li id="run_all_cells"><a href="#">Run All</a></li>
+                <hr/>
+                <li id="to_code"><a href="#">Code Cell</a></li>
+                <li id="to_markdown"><a href="#">Markdown Cell</a></li>
+                <hr/>
+                <li id="toggle_output"><a href="#">Toggle Output</a></li>
+                <li id="clear_all_output"><a href="#">Clear All Output</a></li>
+            </ul>
+        </li>
+        <li><a href="#">Kernel</a>
+            <ul>
+                <li id="int_kernel"><a href="#">Interrupt</a></li>
+                <li id="restart_kernel"><a href="#">Restart</a></li>
+            </ul>
+        </li>
+        <li><a href="#">Help</a>
+            <ul>
+                <li><a href="http://ipython.org/documentation.html" target="_blank">IPython Help</a></li>
+                <li><a href="http://ipython.org/ipython-doc/stable/interactive/htmlnotebook.html" target="_blank">Notebook Help</a></li>
+                <li id="keyboard_shortcuts"><a href="#">Keyboard Shortcuts</a></li>
+                <hr/>
+                <li><a href="https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts" target="_blank">Ace Keyboard Shortcuts</a></li>
+                <hr/>
+                <li><a href="http://docs.python.org" target="_blank">Python</a></li>
+                <li><a href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a></li>
+                <li><a href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a></li>
+                <li><a href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a></li>
+                <li><a href="http://matplotlib.sourceforge.net/" target="_blank">Matplotlib</a></li>
+            </ul>
+        </li>
+    </ul>
+
+</div>
+
+<div id="main_app">
+
+    <div id="notebook_panel">
+        <div id="notebook"></div>
+        <div id="pager_splitter"></div>
+        <div id="pager"></div>
+    </div>
+
+</div>
+
+<div id="fulledit_widget" >
+    <div id="fulledit_header">
+        <button id="close_fulledit">Close</button>
+    </div>
+    <div id="fulledit_editor">some text</div>
+</div>
+
+<script src="/static/jquery/js/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/jquery/js/jquery-ui.min.js" type="text/javascript" charset="utf-8"></script>
+
+<script src="/static/codemirror/lib/codemirror.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/python/python.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/css/css.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
+
+<script src="/static/ace/ace.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ace/mode-python.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ace/mode-markdown.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ace/mode-html.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/ace/theme-textmate.js" type="text/javascript" charset="utf-8"></script>
+
+<script src="/static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
+
+<script src="/static/prettify/prettify.js" charset="utf-8"></script>
+<script src="/static/dateformat/date.format.js" charset="utf-8"></script>
+
+<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/utils.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/cell.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/layout.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/pager.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/menubar.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/fulleditwidget.js" type="text/javascript" charset="utf-8"></script>
+
+</body>
+
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/templates/printnotebook.html b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/printnotebook.html
new file mode 100644
index 0000000..65cab18
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/printnotebook.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+    <meta charset="utf-8">
+
+    <title>ITango Notebook</title>
+
+    {% if mathjax_url %}
+    <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML" charset="utf-8"></script>
+    {% end %}
+    <script type="text/javascript">
+    // MathJax disabled, set as null to distingish from *missing* MathJax,
+    // where it will be undefined, and should prompt a dialog later.
+    window.mathjax_url = "{{mathjax_url}}";
+    </script>
+
+    <link rel="stylesheet" href="/static/jquery/css/themes/base/jquery-ui.min.css" type="text/css" />
+    <link rel="stylesheet" href="/static/codemirror/lib/codemirror.css">
+    <link rel="stylesheet" href="/static/codemirror/mode/markdown/markdown.css">
+    <link rel="stylesheet" href="/static/codemirror/mode/rst/rst.css">
+    <link rel="stylesheet" href="/static/codemirror/theme/ipython.css">
+    <link rel="stylesheet" href="/static/codemirror/theme/default.css">
+
+    <link rel="stylesheet" href="/static/prettify/prettify.css"/>
+
+    <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/base.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/notebook.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/printnotebook.css" type="text/css" />
+    <link rel="stylesheet" href="/static/css/renderedhtml.css" type="text/css" />
+
+    {% comment  In the notebook, the read-only flag is used to determine %}
+    {% comment  whether to hide the side panels and switch off input %}
+    <meta name="read_only" content="{{read_only and not logged_in}}"/>
+
+</head>
+
+<body
+    data-project={{project}} data-notebook-id={{notebook_id}}
+    data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
+>
+
+<div id="header">
+    <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='/static/pytangologo.png' alt='ITango Notebook'/></a></h1></span>
+    <span id="save_widget">
+        <span id="notebook_name"></span>
+        <span id="save_status"></span>
+    </span>
+
+    <span id="login_widget">
+      {% comment  This is a temporary workaround to hide the logout button %}
+      {% comment  when appropriate until notebook.html is templated %}
+      {% if logged_in %}
+        <button id="logout">Logout</button>
+      {% elif not logged_in and login_available %}
+        <button id="login">Login</button>
+      {% end %}
+    </span>
+
+</div>
+
+
+<div id="main_app">
+
+    <div id="notebook_panel">
+        <div id="notebook"></div>
+    </div>
+
+</div>
+
+<script src="/static/jquery/js/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/jquery/js/jquery-ui.min.js" type="text/javascript" charset="utf-8"></script>
+
+<script src="/static/codemirror/lib/codemirror.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/python/python.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/css/css.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
+<script src="/static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
+
+<script src="/static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
+
+<script src="/static/prettify/prettify.js" charset="utf-8"></script>
+<script src="/static/dateformat/date.format.js" charset="utf-8"></script>
+
+<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/utils.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/cell.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
+<script src="/static/js/printnotebookmain.js" type="text/javascript" charset="utf-8"></script>
+
+</body>
+
+</html>
diff --git a/PyTango/ipython/ipython_00_12/examples/notebooks/templates/projectdashboard.html b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/projectdashboard.html
new file mode 100644
index 0000000..18f83cc
--- /dev/null
+++ b/PyTango/ipython/ipython_00_12/examples/notebooks/templates/projectdashboard.html
@@ -0,0 +1,43 @@
+{% extends layout.html %}
+
+{% block title %}
+ITango Dashboard
+{% end %}
+
+{% block stylesheet %}
+    <link rel="stylesheet" href="/static/css/projectdashboard.css" type="text/css" />
+{% end %}
+
+{% block meta %}
+    <meta name="read_only" content="{{read_only}}"/>
+{% end %}
+
+{% block params %}
+data-project={{project}}
+data-base-project-url={{base_project_url}}
+data-base-kernel-url={{base_kernel_url}}
+{% end %}
+
+{% block content_panel %}
+    {% if logged_in or not read_only %}
+
+    <div id="content_toolbar">
+        <span id="drag_info">Drag files onto the list to import
+        notebooks.</span>
+
+        <span id="notebooks_buttons">
+          <button id="new_notebook">New Notebook</button>
+        </span>
+    </div>
+
+    {% end %}
+
+    <div id="notebook_list">
+        <div id="project_name"><h2>{{project}}</h2></div>
+    </div>
+{% end %}
+
+{% block script %}
+    <script src="/static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script>
+    <script src="/static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script>
+{% end %}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pytango.git



More information about the debian-science-commits mailing list