You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@corinthia.apache.org by ja...@apache.org on 2015/08/17 10:49:53 UTC

[01/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Repository: incubator-corinthia
Updated Branches:
  refs/heads/master 63cd96d28 -> 9bf02bb20


http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/Layer1_interface.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/Layer1_interface.hpp b/experiments/editorFramework/src/Toolkit_Layer_1/Layer1_interface.hpp
new file mode 100644
index 0000000..042a1a7
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/Layer1_interface.hpp
@@ -0,0 +1,480 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+#pragma once
+
+#include <QString>
+#include <QRect>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QTextStream>
+
+/**
+ * \file JSInterface.h
+ *
+ * C++ interface to the JavaScript editor library
+ *
+ * All of the core editing operations for Corinthia are implemented in the Editor library, which is
+ * written in JavaScript. This library can be used either from within a web browser, or, in the case
+ * of the Qt application, from an embedded web view. For this app, we use a QWebView instance which
+ * maintains the in-memory DOM tree of the document, and has injected into it all of the javascript
+ * code that is part of the editor library.
+ *
+ * The source code of the Editor library lives in (repository-root)/Editor/src. During build of the
+ * Qt app, all the javascript files are copied into (build-dir)/share/corinthia/js. If you wish to
+ * make changes to the javascript code, you should modify the files in the former location, as the
+ * latter files will be overwritten on every build.
+ *
+ * The purpose of JSInterface.h and JSInterface.cpp is to provide a C++ wrapper over this. All of
+ * the methods defined in the classes below (with the exception of callbacks) ultimately result in a
+ * call to QWebFrame's evaluateJavaScript() method. See the documentation for JSInterface.cpp for
+ * details.
+ *
+ * The editor library is divided into *modules*, each of which implements a specific aspect of
+ * editing functionality. For example, the Cursor module contains methods for moving the cursor
+ * around the document, and inserting or deleting text at the current cursor position. Similarly,
+ * the Tables module contains methods for inserting, deleting, and modifying tables. A separate C++
+ * class is defined for each module, and an instance of each class is maintained by the "container"
+ * class, JSInterface. When using the code here, you should do so via a JSInterface instance.
+ */
+
+#define JS_MODULE_COMMON(className) \
+Q_DISABLE_COPY(className) \
+public: \
+className(JSEvaluator *evaluator) : JSModule(evaluator) {}
+
+QTextStream& qStdOut();
+QString QRectString(QRect rect);
+
+/**
+ * Callback interface
+ *
+ * While the module classes are for making calls from C++ to JavaScript, the JSCallbacks abstract
+ * class is for responding to requests from JavaScript to invoke C++ code. This is declared here as
+ * an abstract class (that is, with all methods virtual and no implementations provided) to avoid
+ * dependencies between the code in this file and other parts of the application. The
+ * EditorJSCallbacks class in Editor.cpp provides a concrete implementation of this, which is where
+ * the actual callback functions are implemented.
+ *
+ * Callbacks are always invoked *after* the execution of a particular editor library API function,
+ * not during. The reason for this design design in the library was to enable support for web view
+ * classes that did not provide native support for callbacks (as was the case for iOS, at least at
+ * the time the library was originally written).
+ *
+ * The way that callbacks are invoked is that after each editor API call, a query is performed for a
+ * list of pending callback messages. The evaluation logic iterates through these and invokes the
+ * appropriate callback method for each. For this reason, callbacks method are all 'void' - they
+ * never return a value. Callbacks are for notification purposes only - typically telling the
+ * application to update the UI in some manner.
+ */
+class JSCallbacks
+{
+public:
+    virtual ~JSCallbacks() {}
+    virtual void debug(const QString &message) = 0;
+    virtual void addOutlineItem(const QString &itemId, const QString &type, const QString &title) = 0;
+    virtual void updateOutlineItem(const QString &itemId, const QString &title) = 0;
+    virtual void removeOutlineItem(const QString &itemId) = 0;
+    virtual void outlineUpdated() = 0;
+    virtual void setCursor(int x, int y, int width, int height) = 0;
+    virtual void setSelectionHandles(int x1, int y1, int height1, int x2, int y2, int height2) = 0;
+    virtual void setTableSelection(int x, int y, int width, int height) = 0;
+    virtual void setSelectionBounds(int left, int top, int right, int bottom) = 0;
+    virtual void clearSelectionHandlesAndCursor() = 0;
+    virtual void updateAutoCorrect() = 0;
+    virtual void error(const QString &message, const QString &operation) = 0;
+};
+
+/**
+ * The JSEvaluator abstract class provides an evaluate() method which is called (indirectly) by all
+ * of the individual module methods. As with JSCallbacks, it is defined as abstract to avoid a
+ * dependency on the code outside of this file. The EditorJSEvaluator class in Editor.cpp provides a
+ * concrete implementation of this; its evaluate() method simply calls through to the
+ * evaluateJavaScript() method of QWebView.
+ *
+ * JSEvaluator also has a callbacks() method, which must return an instance of JSCallbacks. This
+ * makes JSEvaluator the "central point of contact" between the JavaScript interface and the rest of
+ * the application, in that it provides the necessary access to call *in* to javascript, and to
+ * respond (via callbacks) to calls *out* of javascript. Upon initialisation of a document window,
+ * concrete implementations of both JSCallbacks and JSEvaluator are created, the latter maintaining
+ * a reference to the former. See Editor::Editor() for where ths is actually done.
+ */
+class JSEvaluator
+{
+public:
+    virtual ~JSEvaluator() {}
+    virtual QString evaluate(const QString &script) = 0;
+    virtual JSCallbacks *callbacks() = 0;
+};
+
+class JSAutoCorrect;
+class JSChangeTracking;
+class JSClipboard;
+class JSCursor;
+class JSEquations;
+class JSFigures;
+class JSFormatting;
+class JSInput;
+class JSLists;
+class JSMain;
+class JSMetadata;
+class JSOutline;
+class JSPreview;
+class JSScan;
+class JSSelection;
+class JSStyles;
+class JSTables;
+class JSUndoManager;
+class JSViewport;
+class EDScanParagraph;
+
+class JSError
+{
+public:
+    const QString &type() { return _type; }
+    const QString &message() { return _message; }
+    const QString &operation() { return _operation; }
+    const QString &html() { return _html; }
+
+private:
+
+    QString _type;
+    QString _message;
+    QString _operation;
+    QString _html;
+};
+
+class JSModule
+{
+    Q_DISABLE_COPY(JSModule)
+public:
+    JSModule(JSEvaluator *evaluator) : _evaluator(evaluator) {};
+protected:
+    JSEvaluator *_evaluator;
+};
+
+// Functions implemented in AutoCorrect.js
+
+class JSAutoCorrect : public JSModule
+{
+    JS_MODULE_COMMON(JSAutoCorrect)
+    void correctPrecedingWord(int numChars, const QString &replacement, bool confirmed);
+    QJsonObject getCorrection();
+    QJsonObject getCorrectionCoords();
+    void acceptCorrection();
+    void replaceCorrection(const QString &replacement);
+};
+
+// Functions implemented in ChangeTracking.js
+
+class JSChangeTracking : public JSModule
+{
+    JS_MODULE_COMMON(JSChangeTracking)
+    bool showChanges();
+    bool trackChanges();
+    void setShowChanges(bool showChanges);
+    void setTrackChanges(bool trackChanges);
+};
+
+// Functions implemented in Clipboard.js
+
+class JSClipboard : public JSModule
+{
+    JS_MODULE_COMMON(JSClipboard)
+    QJsonObject clipboardCut();
+    QJsonObject clipboardCopy();
+    void pasteHTML(const QString &html);
+    void pasteText(const QString &text);
+};
+
+// Functions implemented in Cursor.js
+
+class JSCursor : public JSModule
+{
+    JS_MODULE_COMMON(JSCursor)
+    QString positionCursor(int x, int y, bool wordBoundary);
+    QRect getCursorPosition();
+    void moveLeft();
+    void moveRight();
+    void moveToStartOfDocument();
+    void moveToEndOfDocument();
+    void insertReference(const QString &itemId);
+    void insertLink(const QString &text, const QString &url);
+    void insertCharacter(unsigned short character, bool allowInvalidPos);
+    void deleteCharacter();
+    void enterPressed();
+    QString getPrecedingWord();
+    QJsonObject getLinkProperties();
+    void setLinkProperties(QJsonObject properties);
+    void setReferenceTarget(const QString &itemId);
+    void insertFootnote(const QString &content);
+    void insertEndnote(const QString &content);
+};
+
+// Functions implemented in Equations.js
+
+class JSEquations : public JSModule
+{
+    JS_MODULE_COMMON(JSEquations)
+    void insertEquation();
+};
+
+// Functions implemented in Figures.js
+
+class JSFigures : public JSModule
+{
+    JS_MODULE_COMMON(JSFigures)
+    void insertFigure(const QString &filename, const QString &width,
+                      bool numbered, const QString &caption);
+    QString getSelectedFigureId();
+    QJsonObject getProperties(const QString &itemId);
+    void setProperties(const QString &itemId, const QString &width, const QString &src);
+    QJsonObject getGeometry(const QString &itemId);
+};
+
+// Functions implemented in Formatting.js
+
+class JSFormatting : public JSModule
+{
+    JS_MODULE_COMMON(JSFormatting)
+    QJsonObject getFormatting();
+    void applyFormattingChanges(const QString &style, QJsonObject properties);
+};
+
+// Functions implemented in Input.js
+
+class JSInput : public JSModule
+{
+    JS_MODULE_COMMON(JSInput)
+    void removePosition(int posId);
+
+    QString textInRange(int startId, int startAdjust, int endId, int endAdjust);
+    void replaceRange(int startId, int endId, const QString &text);
+    QJsonObject selectedTextRange();
+    void setSelectedTextRange(int startId, int endId);
+    QJsonObject markedTextRange();
+    void setMarkedText(const QString &text, int startOffset, int endOffset);
+    void unmarkText();
+    bool forwardSelectionAffinity();
+    void setForwardSelectionAffinity(bool forwardSelectionAffinity);
+    int positionFromPositionOffset(int posId, int offset);
+    int positionFromPositionInDirectionOffset(int posId, const QString &direction, int offset);
+    int comparePositionToPosition(int positionId, int otherId);
+    int offsetFromPositionToPosition(int fromPosition, int toPosition);
+    int positionWithinRangeFarthestInDirection(int startId, int endId, const QString &direction);
+    QJsonObject characterRangeByExtendingPositionInDirection(int positionId, const QString &direction);
+    QJsonObject firstRectForRange(int startId, int endId);
+    QJsonObject caretRectForPosition(int posId);
+    int closestPositionToPoint(int x, int y);
+    int closestPositionToPointWithinRange(int x, int y, int startId, int endId);
+    QJsonObject characterRangeAtPoint(int x, int y);
+    int positionWithinRangeAtCharacterOffset(int startId, int endId, int offset);
+    int characterOffsetOfPositionWithinRange(int positionId, int startId, int endId);
+
+    bool isPositionAtBoundaryGranularityInDirection(int posId, const QString &granularity,
+                                                    const QString &direction);
+    bool isPositionWithinTextUnitInDirection(int posId, const QString &granularity,
+                                             const QString &direction);
+    int positionFromPositionToBoundaryInDirection(int posId, const QString &granularity,
+                                                  const QString &direction);
+    QJsonObject rangeEnclosingPositionWithGranularityInDirection(int posId,
+                                                                 const QString &granularity,
+                                                                 const QString &direction);
+};
+
+// Functions implemented in Lists.js
+
+class JSLists : public JSModule
+{
+    JS_MODULE_COMMON(JSLists)
+    void increaseIndent();
+    void decreaseIndent();
+    void clearList();
+    void setUnorderedList();
+    void setOrderedList();
+};
+
+// Functions implemented in Main.js
+
+class JSMain : public JSModule
+{
+    JS_MODULE_COMMON(JSMain)
+    QString getLanguage();
+    void setLanguage(const QString &language);
+    QString setGenerator(const QString &generator);
+    bool prepareForSave();
+    QString getHTML();
+    bool isEmptyDocument();
+};
+
+// Functions implemented in Metadata.js
+
+class JSMetadata : public JSModule
+{
+    JS_MODULE_COMMON(JSMetadata)
+    QJsonObject getMetadata();
+    void setMetadata(const QJsonObject &metadata);
+};
+
+// Functions implemented in Outline.js
+
+class JSOutline : public JSModule
+{
+    JS_MODULE_COMMON(JSOutline)
+    QJsonObject getOutline();
+    void moveSection(const QString &sectionId, const QString &parentId, const QString &nextId);
+    void deleteItem(const QString &itemId);
+    void goToItem(const QString &itemId);
+    void scheduleUpdateStructure();
+    void setNumbered(const QString &itemId, bool numbered);
+    void setTitle(const QString &itemId, const QString &title);
+    void insertTableOfContents();
+    void insertListOfFigures();
+    void insertListOfTables();
+    void setPrintMode(bool printMode);
+    QJsonObject examinePrintLayout(int pageHeight);
+    bool detectSectionNumbering();
+    QJsonObject findUsedStyles();
+};
+
+// Functions implemented in Preview.js
+
+class JSPreview : public JSModule
+{
+    JS_MODULE_COMMON(JSPreview)
+    void showForStyle(const QString &styleId, const QString &uiName, const QString &title);
+};
+
+// Functions implemented in Scan.js
+
+class JSScan : public JSModule
+{
+    JS_MODULE_COMMON(JSScan)
+    void reset();
+    EDScanParagraph *next();
+    int addMatch(int start, int end);
+    void showMatch(int matchId);
+    void replaceMatch(int matchId, const QString &text);
+    void removeMatch(int matchId);
+    void goToMatch(int matchId);
+};
+
+// Functions implemented in Selection.js
+
+class JSSelection : public JSModule
+{
+    JS_MODULE_COMMON(JSSelection)
+    void update();
+    void selectAll();
+    void selectParagraph();
+    void selectWordAtCursor();
+    QString dragSelectionBegin(int x, int y, bool selectWord);
+    QString dragSelectionUpdate(int x, int y, bool selectWord);
+    QString moveStartLeft();
+    QString moveStartRight();
+    QString moveEndLeft();
+    QString moveEndRight();
+    void setSelectionStartAtCoords(int x, int y);
+    void setSelectionEndAtCoords(int x, int y);
+    void setTableSelectionEdgeAtCoords(const QString &edge, int x, int y);
+    void print();
+};
+
+// Functions implemented in Styles.js
+
+class JSStyles : public JSModule
+{
+    JS_MODULE_COMMON(JSStyles)
+    QString getCSSText();
+    void setCSSText(const QString &cssText, const QJsonObject &rules);
+    QString paragraphClass();
+    void setParagraphClass(const QString &paragraphClass);
+};
+
+// Functions implemented in Tables.js
+
+class JSTables : public JSModule
+{
+    JS_MODULE_COMMON(JSTables)
+    void insertTable(int rows, int cols, const QString &width, bool numbered,
+                     const QString &caption, const QString &className);
+    void addAdjacentRow();
+    void addAdjacentColumn();
+    void removeAdjacentRow();
+    void removeAdjacentColumn();
+    void clearCells();
+    void mergeCells();
+    void splitSelection();
+    QString getSelectedTableId();
+    QJsonObject getProperties(const QString &itemId);
+    void setProperties(const QString &itemId, const QString &width);
+    void setColWidths(const QString &itemId, const QJsonArray &colWidths);
+    QJsonObject getGeometry(const QString &itemId);
+};
+
+// Functions implemented in UndoManager.js
+
+class JSUndoManager : public JSModule
+{
+    JS_MODULE_COMMON(JSUndoManager)
+    int getLength();
+    int getIndex();
+    void setIndex(int index);
+    void undo();
+    void redo();
+    void newGroup(const QString &name);
+    QString groupType();
+};
+
+// Functions implemented in Viewport.js
+
+class JSViewport : public JSModule
+{
+    JS_MODULE_COMMON(JSViewport)
+    void setViewportWidth(int width);
+    void setTextScale(int textScale);
+};
+
+// All modules
+
+class JSInterface
+{
+    Q_DISABLE_COPY(JSInterface)
+public:
+    JSInterface(JSEvaluator *evaluator);
+    JSAutoCorrect autoCorrect;
+    JSChangeTracking changeTracking;
+    JSClipboard clipboard;
+    JSCursor cursor;
+    JSEquations equations;
+    JSFigures figures;
+    JSFormatting formatting;
+    JSInput input;
+    JSLists lists;
+    JSMain main;
+    JSMetadata metadata;
+    JSOutline outline;
+    JSPreview preview;
+    JSScan scan;
+    JSSelection selection;
+    JSStyles styles;
+    JSTables tables;
+    JSUndoManager undoManager;
+    JSViewport viewport;
+};
+
+void processCallbacks(JSEvaluator *evaluator);

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/README b/experiments/editorFramework/src/Toolkit_Layer_1/README
new file mode 100644
index 0000000..8288d80
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/README
@@ -0,0 +1,3 @@
+first example will be Qt
+
+Code will be moved in from other experiments

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/qt/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/qt/README b/experiments/editorFramework/src/Toolkit_Layer_1/qt/README
new file mode 100644
index 0000000..0c59bb8
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/qt/README
@@ -0,0 +1 @@
+Qt example code

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/qt/moc_windows.cpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/qt/moc_windows.cpp b/experiments/editorFramework/src/Toolkit_Layer_1/qt/moc_windows.cpp
new file mode 100644
index 0000000..a7022d6
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/qt/moc_windows.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'windows.hpp'
+**
+** Created by: The Qt Meta Object Compiler version 67 (Qt 5.5.0)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "windows.hpp"
+#include <QtCore/qbytearray.h>
+#include <QtCore/qmetatype.h>
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'windows.hpp' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 67
+#error "This file was generated using the moc from 5.5.0. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+struct qt_meta_stringdata_MainWindow_t {
+    QByteArrayData data[1];
+    char stringdata0[11];
+};
+#define QT_MOC_LITERAL(idx, ofs, len) \
+    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
+    qptrdiff(offsetof(qt_meta_stringdata_MainWindow_t, stringdata0) + ofs \
+        - idx * sizeof(QByteArrayData)) \
+    )
+static const qt_meta_stringdata_MainWindow_t qt_meta_stringdata_MainWindow = {
+    {
+QT_MOC_LITERAL(0, 0, 10) // "MainWindow"
+
+    },
+    "MainWindow"
+};
+#undef QT_MOC_LITERAL
+
+static const uint qt_meta_data_MainWindow[] = {
+
+ // content:
+       7,       // revision
+       0,       // classname
+       0,    0, // classinfo
+       0,    0, // methods
+       0,    0, // properties
+       0,    0, // enums/sets
+       0,    0, // constructors
+       0,       // flags
+       0,       // signalCount
+
+       0        // eod
+};
+
+void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+    Q_UNUSED(_o);
+    Q_UNUSED(_id);
+    Q_UNUSED(_c);
+    Q_UNUSED(_a);
+}
+
+const QMetaObject MainWindow::staticMetaObject = {
+    { &QWidget::staticMetaObject, qt_meta_stringdata_MainWindow.data,
+      qt_meta_data_MainWindow,  qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
+};
+
+
+const QMetaObject *MainWindow::metaObject() const
+{
+    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
+}
+
+void *MainWindow::qt_metacast(const char *_clname)
+{
+    if (!_clname) return Q_NULLPTR;
+    if (!strcmp(_clname, qt_meta_stringdata_MainWindow.stringdata0))
+        return static_cast<void*>(const_cast< MainWindow*>(this));
+    return QWidget::qt_metacast(_clname);
+}
+
+int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+    _id = QWidget::qt_metacall(_c, _id, _a);
+    if (_id < 0)
+        return _id;
+    return _id;
+}
+QT_END_MOC_NAMESPACE

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.cpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.cpp b/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.cpp
new file mode 100644
index 0000000..0599b8f
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.cpp
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.//
+// 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.
+
+#pragma once
+#include "windows.hpp"
+#include "qt_toolkit.hpp"
+
+
+
+// Constructor/Destructor
+qt_toolkit::qt_toolkit(toolkit_callback *setCallback, int setDebugLevel) {
+    int    argc = 0;
+    char **argv = NULL;
+
+
+    callback   = setCallback;
+    debugLevel = setDebugLevel;
+    app        = new QApplication(argc, argv);
+}
+qt_toolkit::~qt_toolkit() {
+    if (window)
+        delete window;
+    if (app)
+        delete app;
+}
+
+
+
+// Instanciate the derived class.
+toolkit * toolkit::createInstance(toolkit_callback *tk, int setDebugLevel) {
+    return (toolkit *)new qt_toolkit(tk, setDebugLevel);
+}
+
+
+
+// Prepare graphic
+bool qt_toolkit::startWindow() {
+    window = new MainWindow(app);
+    return true;
+}
+
+
+
+// Sart message loop, and to not return
+void qt_toolkit::run() {
+    window->show();
+    app->exec();
+}
+
+
+
+// Activate Javascript function
+bool qt_toolkit::callJavascript(const char *function) {
+    return true;
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.hpp b/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.hpp
new file mode 100644
index 0000000..6603e41
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/qt/qt_toolkit.hpp
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+#pragma once
+#include "../toolkit.hpp"
+#include <QtWidgets/QApplication>
+
+
+
+/*
+ * Implementation of toolkit generic interface in Qt
+ *
+ */
+
+
+
+class qt_toolkit : toolkit
+{
+    /* toolkit qt implementation */
+
+public:
+    /* Inherited functions */
+    bool startWindow();
+    void run();
+    bool callJavascript(const char *function);
+
+
+
+    // Constructor/Destructor
+    qt_toolkit(toolkit_callback *setCallback, int setDebugLevel);
+    ~qt_toolkit();
+
+
+
+private: 
+    QApplication     *app;
+    MainWindow       *window;
+    toolkit_callback *callback;
+    int               debugLevel;
+};
+

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.cpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.cpp b/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.cpp
new file mode 100644
index 0000000..57a9686
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.cpp
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.//
+// 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.
+
+#pragma once
+#include "windows.hpp"
+
+
+MainWindow::MainWindow(QApplication *app) {
+}
+MainWindow::~MainWindow() {
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.hpp b/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.hpp
new file mode 100644
index 0000000..07d6eff
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/qt/windows.hpp
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+#pragma once
+#include <QtWidgets/QWidget>
+
+
+
+/******************** WINDOWS.HPP ********************
+ * This file contain all the graphical classes 
+ * inherited from Qt
+ */
+
+
+
+// Main window, this adds all other widgets inside
+class MainWindow : public QWidget
+{
+    Q_OBJECT
+public:
+    MainWindow(QApplication *app);
+    ~MainWindow();
+
+
+    
+public slots:
+/*
+    void insertTable();
+    void insertLink();
+    void insertCharacter();
+    void backspace();
+    void moveLeft();
+    void moveRight();
+    void undo();
+    void redo();
+ */
+
+
+private:
+    QApplication *_app;
+//    Toolbar *_toolbar;
+//    Editor *_editor;
+};

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/toolkit.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/toolkit.hpp b/experiments/editorFramework/src/Toolkit_Layer_1/toolkit.hpp
new file mode 100644
index 0000000..374c743
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/toolkit.hpp
@@ -0,0 +1,139 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+#pragma once
+
+
+
+/*
+ * Interface between implementation dependent toolkit and the API available for the handling.
+ *
+ * This file describes the smallest possible interface, in order to facilitate easier
+ * implementation of other toolkits.
+ *
+ * The toolkit implementation has the following responsibilities:
+ * - Make all graphic manipulation and event handling
+ * - Generate the main window, with buttons and a text frame (to show the actual text). Layout is in the TK.
+ * - Receive and pass events from the windows/buttons/javasscripts
+ * - Manipulate the buttons (enable/disable etc)
+ * - Handle dialog boxes, layout is in the TK
+ * - Start Javascripts on the text
+ * - Provide low level call back with results
+ *
+ * The toolkit generic part has the following responsibilities:
+ * - Provide single calls for every javascript function
+ * - Provide manipulation calls (enable, focus etc) for every button
+ * - Provide high level call back for each javascript function and button
+ *
+ * Some of the TK implementations might have a license incompatible with a Apache release, as a consequence the toolkit class
+ * makes a complete seperation between the apache world, and the potential non-apache world.
+ *
+ * The interface consist of 2 classes
+ * the toolkit class is instanciated in the implementation part of Layer1 and called from generic Layer1 to activate actions.
+ *
+ * The toolkit_callback class is instanciated in the generic part of Layer1 and called from the toolkit implementation to pass
+ * results back to the generic layer
+ */
+
+
+
+class toolkit_callback {
+    /* Callback interface
+     *
+     * this class is pure virtual, to make sure it gets implemented in generic layer without any dependencies
+     * from the toolkit implementation layer.
+     *
+     * Callbacks are always invoked *after* the execution of a particular editor library API function,
+     * not during. The reason for this design design in the library was to enable support for web view
+     * classes that did not provide native support for callbacks (as was the case for iOS, at least at
+     * the time the library was originally written).
+     *
+     * The way that callbacks are invoked is that after each editor API call, a query is performed for a
+     * list of pending callback messages. The evaluation logic iterates through these and invokes the
+     * appropriate callback method for each. For this reason, callbacks method are all 'void' - they
+     * never return a value. Callbacks are for notification purposes only - typically telling layer2
+     * to update the UI in some manner.
+     */
+
+public:
+    // Request a debug message to be passed to the log system 
+    // level can have values as defined in the toolkit class
+    virtual void debug(int level, const char *message) = 0;
+
+
+
+    // pass back Javascript result
+    virtual void notifyJavascript(const char *message) = 0;
+
+
+
+    // pass back Button action
+    // button can have values as defined in toolkit class
+    // (note windows actions are handled as special buttons)
+    virtual void notifyButtonPressed(int button) = 0;
+
+
+
+    // pass back Dialogbox action
+    // dialog can have values as defined in toolkit class
+    virtual void notifyDialog(int dialog, const char *message) = 0;
+};
+
+
+
+class toolkit
+{
+    /* toolkit interface
+    *
+    * this class is pure virtual, to make sure it gets implemented in toolkit implementation without any dependencies
+    * from the generic layer.
+    *
+    * Methods in this class activate graphical functions
+    *
+    * A static createInstance() is supplied to allow the TK implementation to instanciate the derived class
+    */
+
+public:
+    // Enumeration for DEBUG level
+    static const enum {
+        DEBUG_NONE,
+        DEBUG_INFO,
+        DEBUG_WARNING,
+        DEBUG_DEBUG,
+        DEBUG_ERROR
+    };
+
+
+
+    // Function to create a new instance, this is needed to allow the implementation class
+    // to have a derived class that contain implementation dependent functions and variables
+    static toolkit *createInstance(toolkit_callback *callback, int setDebugLevel);
+
+
+
+    // Start windows etc
+    virtual bool startWindow() = 0;
+
+
+
+    // Start message loop, does not return, unless main window is terminated
+    virtual void run() = 0;
+
+
+
+    // Start Javascript
+    virtual bool callJavascript(const char *function) = 0;
+};

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Toolkit_Layer_1/web/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Toolkit_Layer_1/web/README b/experiments/editorFramework/src/Toolkit_Layer_1/web/README
new file mode 100644
index 0000000..ffb28ff
--- /dev/null
+++ b/experiments/editorFramework/src/Toolkit_Layer_1/web/README
@@ -0,0 +1 @@
+Web server code


[15/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/elements.txt
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/elements.txt b/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/elements.txt
new file mode 100644
index 0000000..bd23f64
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/elements.txt
@@ -0,0 +1,113 @@
+#document
+#text
+#comment
+a
+abbr
+address
+area
+article
+aside
+audio
+b
+base
+bdi
+bdo
+blockquote
+body
+br
+button
+canvas
+caption
+cite
+code
+col
+colgroup
+command
+data
+datalist
+dd
+del
+details
+dfn
+dialog
+div
+dl
+dt
+em
+embed
+fieldset
+figcaption
+figure
+footer
+form
+h1
+h2
+h3
+h4
+h5
+h6
+head
+header
+hgroup
+hr
+html
+i
+iframe
+img
+input
+ins
+kbd
+keygen
+label
+legend
+li
+link
+map
+mark
+menu
+meta
+meter
+nav
+noscript
+object
+ol
+optgroup
+option
+output
+p
+param
+pre
+progress
+q
+rp
+rt
+ruby
+s
+samp
+script
+section
+select
+small
+source
+span
+strong
+style
+sub
+summary
+sup
+table
+tbody
+td
+textarea
+tfoot
+th
+thead
+time
+title
+tr
+track
+u
+ul
+var
+video
+wbr

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/genelementtypes.pl
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/genelementtypes.pl b/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/genelementtypes.pl
new file mode 100644
index 0000000..46416e1
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/elementtypes/genelementtypes.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+
+$filename = $ARGV[0];
+
+#print "filename $filename\n";
+
+@names = ();
+
+open($fh,"<",$filename) or die "Can't open $filename";
+while ($name = <$fh>) {
+  $name =~ s/\n$//;
+  push(@names,$name);
+}
+close($fh);
+
+print("// Automatically generated from $filename\n");
+print("ElementTypes = {\n");
+$nextId = 1;
+for $name (@names) {
+  $upper = uc($name);
+  $lower = lc($name);
+  print("  \"$upper\": $nextId,\n");
+  print("  \"$lower\": $nextId,\n");
+  $nextId++;
+}
+print("};\n");
+print("\n");
+$nextId = 1;
+for $name (@names) {
+  $temp = $name;
+  $temp =~ s/#//;
+  $upper = uc($temp);
+  print("HTML_$upper = $nextId;\n");
+  $nextId++;
+}
+print("HTML_COUNT = $nextId;\n");

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/empty.html
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/empty.html b/experiments/editorFramework/src/Javascript_Layer_0/empty.html
new file mode 100644
index 0000000..42682b4
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/empty.html
@@ -0,0 +1 @@
+<html><body></body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/first.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/first.js b/experiments/editorFramework/src/Javascript_Layer_0/first.js
new file mode 100644
index 0000000..48cfd85
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/first.js
@@ -0,0 +1,45 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+// FIXME: The _PREFIX variables below must be replaced with functions that return the
+// appropriate namespace prefix for the document in question (since we can't rely on the
+// values that LibreOffice/MS Word happen to use by default)
+
+var XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
+
+// ODF
+
+var OFFICE_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
+var STYLE_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:style:1.0";
+var TEXT_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
+var TABLE_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
+var FO_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0";
+var SVG_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";
+var XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
+
+var OFFICE_PREFIX = "office:";
+var STYLE_PREFIX = "style:";
+var TEXT_PREFIX = "text:";
+var TABLE_PREFIX = "table:";
+var FO_PREFIX = "fo:";
+var SVG_PREFIX = "svg:";
+var XLINK_PREFIX = "xlink:";
+
+// OOXML
+
+var WORD_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
+var WORD_PREFIX = "w:";

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/traversal.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/traversal.js b/experiments/editorFramework/src/Javascript_Layer_0/traversal.js
new file mode 100644
index 0000000..439870f
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/traversal.js
@@ -0,0 +1,184 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+function prevNode(node)
+{
+    if (node.previousSibling != null) {
+        node = node.previousSibling;
+        while (node.lastChild != null)
+            node = node.lastChild;
+        return node;
+    }
+    else {
+        return node.parentNode;
+    }
+}
+
+function nextNodeAfter(node,entering,exiting)
+{
+    while (node != null) {
+        if (node.nextSibling != null) {
+            if (exiting != null)
+                exiting(node);
+            node = node.nextSibling;
+            if (entering != null)
+                entering(node);
+            break;
+        }
+
+        if (exiting != null)
+            exiting(node);
+        node = node.parentNode;
+    }
+    return node;
+}
+
+function nextNode(node,entering,exiting)
+{
+    if (node.firstChild) {
+        node = node.firstChild;
+        if (entering != null)
+            entering(node);
+        return node;
+    }
+    else {
+        return nextNodeAfter(node,entering,exiting);
+    }
+}
+
+function prevTextNode(node)
+{
+    do {
+        node = prevNode(node);
+    } while ((node != null) && (node.nodeType != Node.TEXT_NODE));
+    return node;
+}
+
+function nextTextNode(node)
+{
+    do {
+        node = nextNode(node);
+    } while ((node != null) && (node.nodeType != Node.TEXT_NODE));
+    return node;
+}
+
+function firstChildElement(node)
+{
+    var first = node.firstChild;
+    while ((first != null) && (first.nodeType != Node.ELEMENT_NODE))
+        first = first.nextSibling;
+    return first;
+}
+
+function lastChildElement(node)
+{
+    var last = node.lastChild;
+    while ((last != null) && (last.nodeType != Node.ELEMENT_NODE))
+        last = last.previousSibling;
+    return last;
+}
+
+function firstDescendant(node)
+{
+    while (node.firstChild != null)
+        node = node.firstChild;
+    return node;
+}
+
+function lastDescendant(node)
+{
+    while (node.lastChild != null)
+        node = node.lastChild;
+    return node;
+}
+
+function firstDescendantOfType(node,type)
+{
+    if (node._type == type)
+        return node;
+
+    for (var child = node.firstChild; child != null; child = child.nextSibling) {
+        var result = firstDescendantOfType(child,type);
+        if (result != null)
+            return result;
+    }
+    return null;
+}
+
+function firstChildOfType(node,type)
+{
+    for (var child = node.firstChild; child != null; child = child.nextSibling) {
+        if (child._type == type)
+            return child;
+    }
+    return null;
+}
+
+function getNodeDepth(node)
+{
+    var depth = 0;
+    for (; node != null; node = node.parentNode)
+        depth++;
+    return depth;
+}
+
+function getNodeText(node)
+{
+    var strings = new Array();
+    recurse(node);
+    return strings.join("").replace(/\s+/g," ");
+
+    function recurse(node)
+    {
+        if (node.nodeType == Node.TEXT_NODE)
+            strings.push(node.nodeValue);
+
+        for (var child = node.firstChild; child != null; child = child.nextSibling)
+            recurse(child);
+    }
+}
+
+function isWhitespaceTextNode(node)
+{
+    if (node.nodeType != Node.TEXT_NODE)
+        return false;
+    return isWhitespaceString(node.nodeValue);
+}
+
+function isNonWhitespaceTextNode(node)
+{
+    if (node.nodeType != Node.TEXT_NODE)
+        return false;
+    return !isWhitespaceString(node.nodeValue);
+}
+
+function printTree(node,indent,offset)
+{
+    if (indent == null)
+        indent = "";
+    if (offset == null)
+        offset = "";
+    if ((node.nodeType == Node.ELEMENT_NODE) && node.hasAttribute("class"))
+        debug(indent+offset+nodeString(node)+"."+node.getAttribute("class"));
+    else
+        debug(indent+offset+nodeString(node));
+    var childOffset = 0;
+    for (var child = node.firstChild; child != null; child = child.nextSibling) {
+        printTree(child,indent+"    ",childOffset+" ");
+        childOffset++;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/types.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/types.js b/experiments/editorFramework/src/Javascript_Layer_0/types.js
new file mode 100644
index 0000000..b49a709
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/types.js
@@ -0,0 +1,280 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var CONTAINER_ELEMENTS = new Array(HTML_COUNT);
+CONTAINER_ELEMENTS[HTML_DOCUMENT] = true;
+CONTAINER_ELEMENTS[HTML_HTML] = true;
+CONTAINER_ELEMENTS[HTML_BODY] = true;
+CONTAINER_ELEMENTS[HTML_UL] = true;
+CONTAINER_ELEMENTS[HTML_OL] = true,
+CONTAINER_ELEMENTS[HTML_LI] = true;
+CONTAINER_ELEMENTS[HTML_TABLE] = true;
+CONTAINER_ELEMENTS[HTML_CAPTION] = true;
+CONTAINER_ELEMENTS[HTML_THEAD] = true;
+CONTAINER_ELEMENTS[HTML_TFOOT] = true;
+CONTAINER_ELEMENTS[HTML_TBODY] = true;
+CONTAINER_ELEMENTS[HTML_TR] = true;
+CONTAINER_ELEMENTS[HTML_TH] = true;
+CONTAINER_ELEMENTS[HTML_TD] = true;
+CONTAINER_ELEMENTS[HTML_COL] = true;
+CONTAINER_ELEMENTS[HTML_FIGURE] = true;
+CONTAINER_ELEMENTS[HTML_FIGCAPTION] = true;
+CONTAINER_ELEMENTS[HTML_NAV] = true;
+
+var PARAGRAPH_ELEMENTS = new Array(HTML_COUNT);
+PARAGRAPH_ELEMENTS[HTML_P] = true;
+PARAGRAPH_ELEMENTS[HTML_H1] = true;
+PARAGRAPH_ELEMENTS[HTML_H2] = true;
+PARAGRAPH_ELEMENTS[HTML_H3] = true;
+PARAGRAPH_ELEMENTS[HTML_H4] = true;
+PARAGRAPH_ELEMENTS[HTML_H5] = true;
+PARAGRAPH_ELEMENTS[HTML_H6] = true;
+PARAGRAPH_ELEMENTS[HTML_DIV] = true;
+PARAGRAPH_ELEMENTS[HTML_PRE] = true;
+PARAGRAPH_ELEMENTS[HTML_BLOCKQUOTE] = true;
+
+var BLOCK_ELEMENTS = new Array(HTML_COUNT);
+for (var i = 0; i < HTML_COUNT; i++)
+    BLOCK_ELEMENTS[i] = (CONTAINER_ELEMENTS[i] || PARAGRAPH_ELEMENTS[i]);
+
+var INLINE_ELEMENTS = new Array(HTML_COUNT);
+for (var i = 0; i < HTML_COUNT; i++)
+    INLINE_ELEMENTS[i] = !BLOCK_ELEMENTS[i];
+
+var HEADING_ELEMENTS = new Array(HTML_COUNT);
+HEADING_ELEMENTS[HTML_H1] = true;
+HEADING_ELEMENTS[HTML_H2] = true;
+HEADING_ELEMENTS[HTML_H3] = true;
+HEADING_ELEMENTS[HTML_H4] = true;
+HEADING_ELEMENTS[HTML_H5] = true;
+HEADING_ELEMENTS[HTML_H6] = true;
+
+var CONTAINERS_ALLOWING_CHILDREN = new Array(HTML_COUNT);
+CONTAINERS_ALLOWING_CHILDREN[HTML_BODY] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_LI] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_CAPTION] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_TH] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_TD] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_FIGURE] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_FIGCAPTION] = true;
+CONTAINERS_ALLOWING_CHILDREN[HTML_NAV] = true;
+
+var OUTLINE_TITLE_ELEMENTS = new Array(HTML_COUNT);
+OUTLINE_TITLE_ELEMENTS[HTML_H1] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_H2] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_H3] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_H4] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_H5] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_H6] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_FIGCAPTION] = true;
+OUTLINE_TITLE_ELEMENTS[HTML_CAPTION] = true;
+
+var Keys = {
+    HEADING_NUMBER: "uxwrite-heading-number",
+    FIGURE_NUMBER: "uxwrite-figure-number",
+    TABLE_NUMBER: "uxwrite-table-number",
+    SECTION_TOC: "tableofcontents",
+    FIGURE_TOC: "listoffigures",
+    TABLE_TOC: "listoftables",
+    SELECTION_HIGHLIGHT: "uxwrite-selection-highlight",
+    AUTOCORRECT_ENTRY: "uxwrite-autocorrect-entry",
+    UXWRITE_PREFIX: "uxwrite-",
+    NONE_STYLE: "__none",
+    AUTOCORRECT_CLASS: "uxwrite-autocorrect",
+    SELECTION_CLASS: "uxwrite-selection",
+    ABSTRACT_ELEMENT: "uxwrite-abstract",
+    SPELLING_CLASS: "uxwrite-spelling",
+    MATCH_CLASS: "uxwrite-match",
+};
+
+var ITEM_NUMBER_CLASSES = {
+    "uxwrite-heading-number": true,
+    "uxwrite-figure-number": true,
+    "uxwrite-table-number": true,
+};
+
+var OPAQUE_NODE_CLASSES = {
+    "uxwrite-heading-number": true,
+    "uxwrite-figure-number": true,
+    "uxwrite-table-number": true,
+    "tableofcontents": true,
+    "listoffigures": true,
+    "listoftables": true,
+    "uxwrite-selection-highlight": true,
+    "uxwrite-field": true,
+};
+
+function isContainerNode(node)
+{
+    return CONTAINER_ELEMENTS[node._type];
+}
+
+function isParagraphNode(node)
+{
+    return PARAGRAPH_ELEMENTS[node._type];
+}
+
+function isHeadingNode(node)
+{
+    return HEADING_ELEMENTS[node._type];
+}
+
+function isBlockNode(node)
+{
+    return BLOCK_ELEMENTS[node._type];
+}
+
+function isBlockOrNoteNode(node)
+{
+    return BLOCK_ELEMENTS[node._type] || isNoteNode(node);
+}
+
+function isInlineNode(node)
+{
+    return INLINE_ELEMENTS[node._type];
+}
+
+function isListNode(node)
+{
+    var type = node._type;
+    return ((type == HTML_UL) || (type == HTML_OL));
+}
+
+function isTableCell(node)
+{
+    switch (node._type) {
+    case HTML_TD:
+    case HTML_TH:
+        return true;
+    default:
+        return false;
+    }
+}
+
+function isRefNode(node)
+{
+    return ((node._type == HTML_A) &&
+            node.hasAttribute("href") &&
+            node.getAttribute("href").charAt(0) == "#");
+}
+
+function isNoteNode(node)
+{
+    if (node._type != HTML_SPAN)
+        return false;
+    var className = DOM_getAttribute(node,"class");
+    return ((className == "footnote") || (className == "endnote"));
+}
+
+function isEmptyNoteNode(node)
+{
+    return isNoteNode(node) && !nodeHasContent(node);
+}
+
+function isItemNumber(node)
+{
+    if (node.nodeType == Node.TEXT_NODE) {
+        return isItemNumber(node.parentNode);
+    }
+    else if (node.nodeType == Node.ELEMENT_NODE) {
+        if ((node._type == HTML_SPAN) && node.hasAttribute("class")) {
+            return ITEM_NUMBER_CLASSES[node.getAttribute("class")];
+        }
+    }
+    return false;
+}
+
+function isOpaqueNode(node)
+{
+    if (node == null)
+        return false;
+
+    switch (node._type) {
+    case HTML_TEXT:
+    case HTML_COMMENT:
+        return isOpaqueNode(node.parentNode);
+    case HTML_IMG:
+        return true;
+    case HTML_A:
+        return node.hasAttribute("href");
+    case HTML_DOCUMENT:
+        return false;
+    default:
+        if (node.hasAttribute("class") && OPAQUE_NODE_CLASSES[node.getAttribute("class")])
+            return true;
+        else
+            return isOpaqueNode(node.parentNode);
+    }
+}
+
+function isAutoCorrectNode(node)
+{
+    return ((node._type == HTML_SPAN) &&
+            (node.getAttribute("class") == Keys.AUTOCORRECT_CLASS));
+}
+
+function isSelectionHighlight(node)
+{
+    return ((node.nodeType == Node.ELEMENT_NODE) &&
+            node.getAttribute("class") == Keys.SELECTION_CLASS);
+}
+
+function isSelectionSpan(node)
+{
+    return ((node != null) &&
+            (node._type == HTML_SPAN) &&
+            (DOM_getAttribute(node,"class") == Keys.SELECTION_CLASS));
+};
+
+function isTOCNode(node)
+{
+    if (node._type == HTML_NAV) {
+        var cls = node.getAttribute("class");
+        if ((cls == Keys.SECTION_TOC) ||
+            (cls == Keys.FIGURE_TOC) ||
+            (cls == Keys.TABLE_TOC))
+            return true;
+    }
+    return false;
+}
+
+function isInTOC(node)
+{
+    if (isTOCNode(node))
+        return true;
+    if (node.parentNode != null)
+        return isInTOC(node.parentNode);
+    return false;
+}
+
+function isSpecialBlockNode(node)
+{
+    switch (node._type) {
+    case HTML_TABLE:
+    case HTML_FIGURE:
+        return true;
+    case HTML_NAV:
+        return isTOCNode(node);
+    default:
+        return false;
+    }
+}
+
+function isAbstractSpan(node)
+{
+    return ((node._type == HTML_SPAN) && node.hasAttribute(Keys.ABSTRACT_ELEMENT));
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/util.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/util.js b/experiments/editorFramework/src/Javascript_Layer_0/util.js
new file mode 100644
index 0000000..191fc55
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/util.js
@@ -0,0 +1,365 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+function arrayContains(array,value)
+{
+    for (var i = 0; i < array.length; i++) {
+        if (array[i] == value)
+            return true;
+    }
+    return false;
+}
+
+// Note: you can use slice() to copy a real javascript array, but this function can be used to copy
+// DOM NodeLists (e.g. as returned by document.getElementsByTagName) as well, since they don't
+// support the slice method
+function arrayCopy(array)
+{
+    if (array == null)
+        return null;
+    var copy = new Array();
+    for (var i = 0; i < array.length; i++)
+        copy.push(array[i]);
+    return copy;
+}
+
+function quoteString(str)
+{
+    if (str == null)
+        return null;
+
+    if (str.indexOf('"') < 0)
+        return str;
+
+    var quoted = "";
+    for (var i = 0; i < str.length; i++) {
+        if (str.charAt(i) == '"')
+            quoted += "\\\"";
+        else
+            quoted += str.charAt(i);
+    }
+    return quoted;
+}
+
+function nodeString(node)
+{
+    if (node == null)
+        return "null";
+    var id = "";
+    if (window.debugIds)
+        id = node._nodeId+":";
+    if (node.nodeType == Node.TEXT_NODE) {
+        return id+JSON.stringify(node.nodeValue);
+    }
+    else if (node.nodeType == Node.ELEMENT_NODE) {
+        var name = (node.namespaceURI == null) ? node.nodeName.toUpperCase() : node.nodeName;
+        if (node.hasAttribute("id"))
+            return id+name+"#"+node.getAttribute("id");
+        else
+            return id+name;
+    }
+    else {
+        return id+node.toString();
+    }
+}
+
+function rectString(rect)
+{
+    if (rect == null)
+        return null;
+    else
+        return "("+rect.left+","+rect.top+") - ("+rect.right+","+rect.bottom+")";
+}
+
+function rectIsEmpty(rect)
+{
+    return ((rect == null) ||
+            ((rect.width == 0) && (rect.height == 0)));
+}
+
+function rectContainsPoint(rect,x,y)
+{
+    return ((x >= rect.left) && (x < rect.right) &&
+            (y >= rect.top) && (y < rect.bottom));
+}
+
+function clone(object)
+{
+    var result = new Object();
+    for (var name in object)
+        result[name] = object[name];
+    return result;
+}
+
+function nodeHasContent(node)
+{
+    switch (node._type) {
+    case HTML_TEXT:
+        return !isWhitespaceString(node.nodeValue);
+    case HTML_IMG:
+    case HTML_TABLE:
+        return true;
+    default:
+        if (isOpaqueNode(node))
+            return true;
+
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            if (nodeHasContent(child))
+                return true;
+        }
+        return false;
+    }
+}
+
+function isWhitespaceString(str)
+{
+    return (str.match(isWhitespaceString.regexp) != null);
+}
+
+isWhitespaceString.regexp = /^\s*$/;
+
+function normalizeWhitespace(str)
+{
+    str = str.replace(/^\s+/,"");
+    str = str.replace(/\s+$/,"");
+    str = str.replace(/\s+/g," ");
+    return str;
+}
+
+function DoublyLinkedList()
+{
+    this.first = null;
+    this.last = null;
+}
+
+DoublyLinkedList.prototype.insertAfter = function(item,after)
+{
+    item.prev = null;
+    item.next = null;
+
+    if (this.first == null) { // empty list
+        this.first = item;
+        this.last = item;
+    }
+    else if (after == null) { // insert at start
+        item.next = this.first;
+        this.first = item;
+    }
+    else {
+        item.next = after.next;
+        item.prev = after;
+        if (this.last == after)
+            this.last = item;
+    }
+
+    if (item.next != null)
+        item.next.prev = item;
+    if (item.prev != null)
+        item.prev.next = item;
+};
+
+DoublyLinkedList.prototype.remove = function(item)
+{
+    if (this.first == item)
+        this.first = this.first.next;
+    if (this.last == item)
+        this.last = this.last.prev;
+    if (item.prev != null)
+        item.prev.next = item.next;
+    if (item.next != null)
+        item.next.prev = item.prev;
+    item.prev = null;
+    item.next = null;
+};
+
+function diff(src,dest)
+{
+    var traces = new Array();
+
+    traces[1] = new DiffEntry(0,0,0,0,null);
+
+    for (var distance = 0; true; distance++) {
+        for (var k = -distance; k <= distance; k += 2) {
+            var srcEnd;
+            var prev;
+
+            var del = traces[k-1];
+            var ins = traces[k+1];
+
+            if (((k == -distance) && ins) ||
+                ((k != distance) && ins && del && (del.srcEnd < ins.srcEnd))) {
+                // Down - insertion
+                prev = ins;
+                srcEnd = prev.srcEnd;
+            }
+            else if (del) {
+                // Right - deletion
+                prev = del;
+                srcEnd = prev.srcEnd+1;
+            }
+            else {
+                traces[k] = null;
+                continue;
+            }
+
+            destEnd = srcEnd - k;
+            var srcStart = srcEnd;
+            var destStart = destEnd;
+            while ((srcEnd < src.length) && (destEnd < dest.length) &&
+                   (src[srcEnd] == dest[destEnd])) {
+                srcEnd++;
+                destEnd++;
+            }
+            if ((srcEnd > src.length) || (destEnd > dest.length))
+                traces[k] = null;
+            else
+                traces[k] = new DiffEntry(srcStart,destStart,srcEnd,destEnd,prev);
+            if ((srcEnd >= src.length) && (destEnd >= dest.length)) {
+                return entryToArray(src,dest,traces[k]);
+            }
+        }
+    }
+
+    function DiffEntry(srcStart,destStart,srcEnd,destEnd,prev)
+    {
+        this.srcStart = srcStart;
+        this.destStart = destStart;
+        this.srcEnd = srcEnd;
+        this.destEnd = destEnd;
+        this.prev = prev;
+    }
+
+    function entryToArray(src,dest,entry)
+    {
+        var results = new Array();
+        results.push(entry);
+        for (entry = entry.prev; entry != null; entry = entry.prev) {
+            if ((entry.srcStart != entry.srcEnd) || (entry.destStart != entry.destEnd))
+                results.push(entry);
+        }
+        return results.reverse();
+    }
+}
+
+function TimingEntry(name,time)
+{
+    this.name = name;
+    this.time = time;
+}
+
+function TimingInfo()
+{
+    this.entries = new Array();
+    this.total = 0;
+    this.lastTime = null;
+}
+
+TimingInfo.prototype.start = function()
+{
+    this.entries.length = 0;
+    this.lastTime = new Date();
+};
+
+TimingInfo.prototype.addEntry = function(name)
+{
+    if (this.lastTime == null)
+        this.start();
+
+    var now = new Date();
+    var interval = now - this.lastTime;
+    this.entries.push(new TimingEntry(name,interval));
+    this.total += interval;
+    this.lastTime = now;
+};
+
+TimingInfo.prototype.print = function(title)
+{
+    debug(title);
+    for (var i = 0; i < this.entries.length; i++) {
+        var entry = this.entries[i];
+        debug("    "+entry.name+": "+entry.time+"ms");
+    }
+};
+
+function readFileApp(filename)
+{
+    var req = new XMLHttpRequest("file:///read/"+filename);
+    req.open("POST","/read/"+encodeURI(filename),false);
+    req.send();
+    if (req.status == 404)
+        return null; // file not found
+    else if ((req.status != 200) && (req.status != 0))
+        throw new Error(req.status+": "+req.responseText);
+    var doc = req.responseXML;
+    if (doc != null)
+        DOM_assignNodeIds(doc);
+    return doc;
+}
+
+function readFileTest(filename)
+{
+    var req = new XMLHttpRequest();
+    req.open("GET",filename,false);
+    req.send();
+    var xml = req.responseXML;
+    if (xml == null)
+        return null;
+    DOM_assignNodeIds(xml.documentElement);
+    return xml;
+}
+
+function fromTokenList(value)
+{
+    var result = new Object();
+    if (value != null) {
+        var components = value.toLowerCase().split(/\s+/);
+        for (var i = 0; i < components.length; i++) {
+            if (components[i].length > 0)
+                result[components[i]] = true;
+        }
+    }
+    return result;
+}
+
+function toTokenList(properties)
+{
+    var tokens = new Array();
+
+    if (properties != null) {
+        // Sort the names to ensure deterministic results in test cases
+        var names = Object.getOwnPropertyNames(properties).sort();
+        for (var i = 0; i < names.length; i++) {
+            var name = names[i];
+            if (properties[name])
+                tokens.push(name);
+        }
+    }
+
+    if (tokens.length == null)
+        return null;
+    else
+        return tokens.join(" ");
+}
+
+function xywhAbsElementRect(element)
+{
+    var rect = element.getBoundingClientRect();
+    return { x: rect.left + window.scrollX,
+             y: rect.top + window.scrollY,
+             width: rect.width,
+             height: rect.height };
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/license.txt
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/license.txt b/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/license.txt
deleted file mode 100644
index e9c8672..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/license.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-Copyright (c) 2007, John Fraser  
-<http://www.attacklab.net/>  
-All rights reserved.
-
-Original Markdown copyright (c) 2004, John Gruber  
-<http://daringfireball.net/>  
-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.
-
-* Neither the name "Markdown" nor the names of its contributors may
-  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 the copyright owner
-or contributors 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.

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/showdown.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/showdown.js b/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/showdown.js
deleted file mode 100644
index 734dabb..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/3rdparty/showdown/showdown.js
+++ /dev/null
@@ -1,1302 +0,0 @@
-//
-// showdown.js -- A javascript port of Markdown.
-//
-// Copyright (c) 2007 John Fraser.
-//
-// Original Markdown Copyright (c) 2004-2005 John Gruber
-//   <http://daringfireball.net/projects/markdown/>
-//
-// Redistributable under a BSD-style open source license.
-// See license.txt for more information.
-//
-// The full source distribution is at:
-//
-//				A A L
-//				T C A
-//				T K B
-//
-//   <http://www.attacklab.net/>
-//
-
-//
-// 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.
-//
-
-
-//
-// Showdown usage:
-//
-//   var text = "Markdown *rocks*.";
-//
-//   var converter = new Showdown.converter();
-//   var html = converter.makeHtml(text);
-//
-//   alert(html);
-//
-// Note: move the sample code to the bottom of this
-// file before uncommenting it.
-//
-
-
-//
-// Showdown namespace
-//
-var Showdown = {};
-
-//
-// converter
-//
-// Wraps all "globals" so that the only thing
-// exposed is makeHtml().
-//
-Showdown.converter = function() {
-
-//
-// Globals:
-//
-
-// 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 = 0;
-
-
-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.
-//
-
-	// Clear the global hashes. If we don't clear these, you get conflicts
-	// from other articles when generating a page which contains more than
-	// one article (e.g. an index page that shows the N most recent
-	// articles):
-	g_urls = new Array();
-	g_titles = new Array();
-	g_html_blocks = new Array();
-
-	// 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,"~");
-
-	return text;
-}
-
-
-var _StripLinkDefinitions = function(text) {
-//
-// Strips link definitions from text, stores the URLs and titles in
-// hash references.
-//
-
-	// Link defs are in the form: ^[id]: url "optional title"
-
-	/*
-		var text = text.replace(/
-				^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1
-				  [ \t]*
-				  \n?				// maybe *one* newline
-				  [ \t]*
-				<?(\S+?)>?			// url = $2
-				  [ \t]*
-				  \n?				// maybe one newline
-				  [ \t]*
-				(?:
-				  (\n*)				// any lines skipped = $3 attacklab: lookbehind removed
-				  ["(]
-				  (.+?)				// title = $4
-				  [")]
-				  [ \t]*
-				)?					// title is optional
-				(?:\n+|$)
-			  /gm,
-			  function(){...});
-	*/
-	var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,
-		function (wholeMatch,m1,m2,m3,m4) {
-			m1 = m1.toLowerCase();
-			g_urls[m1] = _EncodeAmpsAndAngles(m2);  // Link IDs are case-insensitive
-			if (m3) {
-				// Oops, found blank lines, so it's not a title.
-				// Put back the parenthetical statement we stole.
-				return m3+m4;
-			} else if (m4) {
-				g_titles[m1] = m4.replace(/"/g,"&quot;");
-			}
-			
-			// Completely remove the definition from the text
-			return "";
-		}
-	);
-
-	return text;
-}
-
-
-var _HashHTMLBlocks = function(text) {
-	// attacklab: Double up blank lines to reduce lookaround
-	text = text.replace(/\n/g,"\n\n");
-
-	// 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.
-	/*
-		var 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`
-	//
-
-	/*
-		var 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(/
-		(						// save in $1
-			\n\n				// Starting after a blank line
-			[ ]{0,3}
-			(<(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(/
-		(						// save in $1
-			\n\n				// Starting after a blank line
-			[ ]{0,3}			// attacklab: g_tab_width - 1
-			<!
-			(--[^\r]*?--\s*)+
-			>
-			[ \t]*
-			(?=\n{2,})			// followed by a blank line
-		)
-		/g,hashElement);
-	*/
-	text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \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);
-
-	// attacklab: Undo double lines (see comment at top of this function)
-	text = text.replace(/\n\n/g,"\n");
-	return text;
-}
-
-var hashElement = function(wholeMatch,m1) {
-	var blockText = m1;
-
-	// Undo double lines
-	blockText = blockText.replace(/\n\n/g,"\n");
-	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;
-};
-
-var _RunBlockGamut = function(text) {
-//
-// These are all the transformations that form block-level
-// tags like paragraphs, headers, and list items.
-//
-	text = _DoHeaders(text);
-
-	// Do Horizontal Rules:
-	var key = hashBlock("<hr />");
-	text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
-	text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);
-	text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);
-
-	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);
-
-	return text;
-}
-
-
-var _RunSpanGamut = function(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;
-}
-
-var _EscapeSpecialCharsWithinTagAttributes = function(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.
-	var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
-
-	text = text.replace(regex, function(wholeMatch) {
-		var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");
-		tag = escapeCharacters(tag,"\\`*_");
-		return tag;
-	});
-
-	return text;
-}
-
-var _DoAnchors = function(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,_DoAnchors_callback);
-	*/
-	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
-			[ \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;
-}
-
-var writeAnchorTag = function(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[link_id] != undefined) {
-			url = g_urls[link_id];
-			if (g_titles[link_id] != undefined) {
-				title = g_titles[link_id];
-			}
-		}
-		else {
-			if (whole_match.search(/\(\s*\)$/m)>-1) {
-				// Special case for explicit empty url
-				url = "";
-			} else {
-				return whole_match;
-			}
-		}
-	}	
-	
-	url = escapeCharacters(url,"*_");
-	var result = "<a href=\"" + url + "\"";
-	
-	if (title != "") {
-		title = title.replace(/"/g,"&quot;");
-		title = escapeCharacters(title,"*_");
-		result +=  " title=\"" + title + "\"";
-	}
-	
-	result += ">" + link_text + "</a>";
-	
-	return result;
-}
-
-
-var _DoImages = function(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;
-}
-
-var writeImageTag = function(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[link_id] != undefined) {
-			url = g_urls[link_id];
-			if (g_titles[link_id] != undefined) {
-				title = g_titles[link_id];
-			}
-		}
-		else {
-			return whole_match;
-		}
-	}	
-	
-	alt_text = alt_text.replace(/"/g,"&quot;");
-	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,"&quot;");
-		title = escapeCharacters(title,"*_");
-		result +=  " title=\"" + title + "\"";
-	//}
-	
-	result += " />";
-	
-	return result;
-}
-
-
-var _DoHeaders = function(text) {
-
-	// Setext-style headers:
-	//	Header 1
-	//	========
-	//  
-	//	Header 2
-	//	--------
-	//
-	text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
-		function(wholeMatch,m1){return hashBlock('<h1 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h1>");});
-
-	text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
-		function(matchFound,m1){return hashBlock('<h2 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h2>");});
-
-	// 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 hashBlock("<h" + h_level + ' id="' + headerId(m2) + '">' + _RunSpanGamut(m2) + "</h" + h_level + ">");
-		});
-
-	function headerId(m) {
-		return m.replace(/[^\w]/g, '').toLowerCase();
-	}
-	return text;
-}
-
-// This declaration keeps Dojo compressor from outputting garbage:
-var _ProcessListItems;
-
-var _DoLists = function(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";
-
-			// Turn double returns into triple returns, so that we can make a
-			// paragraph for the last item in a list, if necessary:
-			list = list.replace(/\n{2,}/g,"\n\n\n");;
-			var result = _ProcessListItems(list);
-	
-			// 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";
-			// Turn double returns into triple returns, so that we can make a
-			// paragraph for the last item in a list, if necessary:
-			var list = list.replace(/\n{2,}/g,"\n\n\n");;
-			var result = _ProcessListItems(list);
-			result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n";	
-			return result;
-		});
-	}
-
-	// attacklab: strip sentinel
-	text = text.replace(/~0/,"");
-
-	return text;
-}
-
-_ProcessListItems = function(list_str) {
-//
-//  Process the contents of a single ordered or unordered list, splitting it
-//  into individual list items.
-//
-	// 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";
-
-	/*
-		list_str = list_str.replace(/
-			(\n)?							// leading line = $1
-			(^[ \t]*)						// leading whitespace = $2
-			([*+-]|\d+[.]) [ \t]+			// list marker = $3
-			([^\r]+?						// list item text   = $4
-			(\n{1,2}))
-			(?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
-		/gm, function(){...});
-	*/
-	list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
-		function(wholeMatch,m1,m2,m3,m4){
-			var item = m4;
-			var leading_line = m1;
-			var leading_space = m2;
-
-			if (leading_line || (item.search(/\n{2,}/)>-1)) {
-				item = _RunBlockGamut(_Outdent(item));
-			}
-			else {
-				// Recursion for sub-lists:
-				item = _DoLists(_Outdent(item));
-				item = item.replace(/\n$/,""); // chomp(item)
-				item = _RunSpanGamut(item);
-			}
-
-			return  "<li>" + item + "</li>\n";
-		}
-	);
-
-	// attacklab: strip sentinel
-	list_str = list_str.replace(/~0/g,"");
-
-	g_list_level--;
-	return list_str;
-}
-
-
-var _DoCodeBlocks = function(text) {
-//
-//  Process Markdown `<pre><code>` blocks.
-//  
-
-	/*
-		text = text.replace(text,
-			/(?:\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 hashBlock(codeblock) + nextChar;
-		}
-	);
-
-	// attacklab: strip sentinel
-	text = text.replace(/~0/,"");
-
-	return text;
-}
-
-var hashBlock = function(text) {
-	text = text.replace(/(^\n+|\n+$)/g,"");
-	return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n";
-}
-
-
-var _DoCodeSpans = function(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;
-}
-
-
-var _EncodeCode = function(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,"&amp;");
-
-	// Do the angle bracket song and dance:
-	text = text.replace(/</g,"&lt;");
-	text = text.replace(/>/g,"&gt;");
-
-	// 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;
-}
-
-
-var _DoItalicsAndBold = function(text) {
-
-	// <strong> must go first:
-	text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
-		"<strong>$2</strong>");
-
-	text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
-		"<em>$2</em>");
-
-	return text;
-}
-
-
-var _DoBlockQuotes = function(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;
-}
-
-
-var _FormParagraphs = function(text) {
-//
-//  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 = new Array();
-
-	//
-	// 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
-	//
-	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");
-}
-
-
-var _EncodeAmpsAndAngles = function(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,"&amp;");
-	
-	// Encode naked <'s
-	text = text.replace(/<(?![a-z\/?\$!])/gi,"&lt;");
-	
-	return text;
-}
-
-
-var _EncodeBackslashEscapes = function(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;
-}
-
-
-var _DoAutoLinks = function(text) {
-
-	text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
-
-	// Email addresses: <ad...@domain.foo>
-
-	/*
-		text = text.replace(/
-			<
-			(?:mailto:)?
-			(
-				[-.\w]+
-				\@
-				[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
-			)
-			>
-		/gi, _DoAutoLinks_callback());
-	*/
-	text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
-		function(wholeMatch,m1) {
-			return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
-		}
-	);
-
-	return text;
-}
-
-
-var _EncodeEmailAddress = function(addr) {
-//
-//  Input: an email address, e.g. "foo@example.com"
-//
-//  Output: the email address as a mailto link, with each character
-//	of the address encoded as either a decimal or hex entity, in
-//	the hopes of foiling most address harvesting spam bots. E.g.:
-//
-//	<a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
-//	   x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
-//	   &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
-//
-//  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
-//  mailing list: <http://tinyurl.com/yu7ue>
-//
-
-	// attacklab: why can't javascript speak hex?
-	function char2hex(ch) {
-		var hexDigits = '0123456789ABCDEF';
-		var dec = ch.charCodeAt(0);
-		return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15));
-	}
-
-	var encode = [
-		function(ch){return "&#"+ch.charCodeAt(0)+";";},
-		function(ch){return "&#x"+char2hex(ch)+";";},
-		function(ch){return ch;}
-	];
-
-	addr = "mailto:" + addr;
-
-	addr = addr.replace(/./g, function(ch) {
-		if (ch == "@") {
-		   	// this *must* be encoded. I insist.
-			ch = encode[Math.floor(Math.random()*2)](ch);
-		} else if (ch !=":") {
-			// leave ':' alone (to spot mailto: later)
-			var r = Math.random();
-			// roughly 10% raw, 45% hex, 45% dec
-			ch =  (
-					r > .9  ?	encode[2](ch)   :
-					r > .45 ?	encode[1](ch)   :
-								encode[0](ch)
-				);
-		}
-		return ch;
-	});
-
-	addr = "<a href=\"" + addr + "\">" + addr + "</a>";
-	addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part
-
-	return addr;
-}
-
-
-var _UnescapeSpecialChars = function(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;
-}
-
-
-var _Outdent = function(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;
-}
-
-var _Detab = function(text) {
-// attacklab: Detab's completely rewritten for speed.
-// In perl we could fix it by anchoring the regexp with \G.
-// In javascript we're less fortunate.
-
-	// expand first n-1 tabs
-	text = text.replace(/\t(?=\t)/g,"    "); // attacklab: g_tab_width
-
-	// replace the nth with two sentinels
-	text = text.replace(/\t/g,"~A~B");
-
-	// use the sentinel to anchor our regex so it doesn't explode
-	text = text.replace(/~B(.+?)~A/g,
-		function(wholeMatch,m1,m2) {
-			var leadingText = m1;
-			var numSpaces = 4 - leadingText.length % 4;  // attacklab: g_tab_width
-
-			// there *must* be a better way to do this:
-			for (var i=0; i<numSpaces; i++) leadingText+=" ";
-
-			return leadingText;
-		}
-	);
-
-	// clean up sentinels
-	text = text.replace(/~A/g,"    ");  // attacklab: g_tab_width
-	text = text.replace(/~B/g,"");
-
-	return text;
-}
-
-
-//
-//  attacklab: Utility functions
-//
-
-
-var escapeCharacters = function(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;
-}
-
-
-var escapeCharacters_callback = function(wholeMatch,m1) {
-	var charCodeToEscape = m1.charCodeAt(0);
-	return "~E"+charCodeToEscape+"E";
-}
-
-} // end of Showdown.converter
-
-// export
-if (typeof exports != 'undefined') exports.Showdown = Showdown;

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/AutoCorrect.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/AutoCorrect.js b/experiments/editorFramework/src/Layer0_Javascript/AutoCorrect.js
deleted file mode 100644
index a80e17d..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/AutoCorrect.js
+++ /dev/null
@@ -1,285 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var AutoCorrect_init;
-var AutoCorrect_removeListeners;
-var AutoCorrect_addCorrection;
-var AutoCorrect_removeCorrection;
-var AutoCorrect_getCorrections;
-
-var AutoCorrect_correctPrecedingWord;
-var AutoCorrect_getCorrection;
-var AutoCorrect_getCorrectionCoords;
-var AutoCorrect_acceptCorrection;
-var AutoCorrect_revertCorrection;
-var AutoCorrect_replaceCorrection;
-
-(function() {
-
-    function removeCorrectionSpan(span)
-    {
-        if (span.parentNode == null)
-            return;
-        Selection_preserveWhileExecuting(function() {
-            var firstChild = span.firstChild;
-            DOM_removeNodeButKeepChildren(span);
-            if (firstChild != null)
-                Formatting_mergeWithNeighbours(firstChild,{});
-        });
-    }
-
-    function Correction(span)
-    {
-        this.span = span;
-        this.modificationListener = function(event) {
-            if (DOM_getIgnoreMutations())
-                return;
-            PostponedActions_add(function() {
-                // This will trigger a removeCorrection() call
-                removeCorrectionSpan(span);
-            });
-        };
-    }
-
-    Correction.prototype.toString = function()
-    {
-        return this.span.getAttribute("original")+" -> "+getNodeText(this.span);
-    }
-
-    var correctionsByNode = null;
-    var correctionList = null;
-
-    // private
-    function docNodeInserted(event)
-    {
-        try {
-            recurse(event.target);
-        }
-        catch (e) {
-            Editor_error(e);
-        }
-
-        function recurse(node)
-        {
-            if (isAutoCorrectNode(node))
-                AutoCorrect_addCorrection(node);
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-    // private
-    function docNodeRemoved(event)
-    {
-        try {
-            recurse(event.target);
-        }
-        catch (e) {
-            Editor_error(e);
-        }
-
-        function recurse(node)
-        {
-            if (isAutoCorrectNode(node))
-                AutoCorrect_removeCorrection(node);
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-    AutoCorrect_init = function()
-    {
-        correctionsByNode = new NodeMap();
-        correctionList = new Array();
-        document.addEventListener("DOMNodeInserted",docNodeInserted);
-        document.addEventListener("DOMNodeRemoved",docNodeRemoved);
-    }
-
-    // public (for the undo tests, when they report results)
-    AutoCorrect_removeListeners = function()
-    {
-        document.removeEventListener("DOMNodeInserted",docNodeInserted);
-        document.removeEventListener("DOMNodeRemoved",docNodeRemoved);
-    }
-
-    AutoCorrect_addCorrection = function(span)
-    {
-        var correction = new Correction(span);
-        correctionsByNode.put(span,correction);
-        correctionList.push(correction);
-        Editor_updateAutoCorrect();
-
-        span.addEventListener("DOMSubtreeModified",correction.modificationListener);
-    }
-
-    AutoCorrect_removeCorrection = function(span)
-    {
-        var correction = correctionsByNode.get(span);
-        if (correction == null)
-            throw new Error("No autocorrect entry for "+JSON.stringify(getNodeText(span)));
-
-        var index = null;
-        for (var i = 0; i < correctionList.length; i++) {
-            if (correctionList[i].span == span) {
-                index = i;
-                break;
-            }
-        }
-        if (index == null)
-            throw new Error("Correction "+correction+" not found in correctionList");
-        correctionList.splice(index,1);
-        Editor_updateAutoCorrect();
-
-        span.removeEventListener("DOMSubtreeModified",correction.modificationListener);
-        correctionsByNode.remove(span);
-    }
-
-    AutoCorrect_getCorrections = function()
-    {
-        var result = new Array();
-        for (var i = 0; i < correctionList.length; i++) {
-            var correction = correctionList[i];
-            result.push({ original: correction.span.getAttribute("original"),
-                          replacement: getNodeText(correction.span)});
-        }
-        return result;
-    }
-
-    AutoCorrect_correctPrecedingWord = function(numChars,replacement,confirmed)
-    {
-        Selection_preserveWhileExecuting(function() {
-            var selRange = Selection_get();
-            if ((selRange == null) && !Range_isEmpty(selRange))
-                return;
-
-            var node = selRange.start.node;
-            var offset = selRange.start.offset;
-            if (node.nodeType != Node.TEXT_NODE)
-                return;
-
-            var original = node.nodeValue.substring(offset-numChars,offset);
-
-            if (confirmed) {
-                DOM_replaceCharacters(node,offset-numChars,offset,replacement);
-                return;
-            }
-
-            UndoManager_newGroup("Auto-correct");
-            var before = node.nodeValue.substring(0,offset-numChars);
-            var beforeText = DOM_createTextNode(document,before);
-            var replacementText = DOM_createTextNode(document,replacement);
-            var span = DOM_createElement(document,"SPAN");
-            DOM_setAttribute(span,"class",Keys.AUTOCORRECT_CLASS);
-            DOM_setAttribute(span,"original",original);
-            DOM_appendChild(span,replacementText);
-            DOM_insertBefore(node.parentNode,beforeText,node);
-            DOM_insertBefore(node.parentNode,span,node);
-            DOM_deleteCharacters(node,0,offset);
-            // Add the new group in a postponed action, so that the change to the style element
-            // is not counted as a separate action
-            PostponedActions_add(UndoManager_newGroup);
-        });
-    }
-
-    AutoCorrect_getCorrection = function()
-    {
-        var correction = getCurrent();
-        if (correction == null)
-            return null;
-
-        return { original: correction.span.getAttribute("original"),
-                 replacement: getNodeText(correction.span) };
-    }
-
-    AutoCorrect_getCorrectionCoords = function()
-    {
-        var correction = getCurrent();
-        if (correction == null)
-            return null;
-
-        var textNode = correction.span.firstChild;
-        if ((textNode == null) || (textNode.nodeType != Node.TEXT_NODE))
-            return null;
-
-        var offset = Math.floor(textNode.nodeValue.length/2);
-        Selection_set(textNode,offset,textNode,offset);
-        Cursor_ensureCursorVisible();
-        var rect = Position_displayRectAtPos(new Position(textNode,offset));
-
-        if (rect == null) // FIXME: pos
-            throw new Error("no rect for pos "+(new Position(textNode,offset)));
-
-        if (rect == null)
-            return null;
-
-        return { x: rect.left, y: rect.top };
-    }
-
-    function getCurrent()
-    {
-        var range = Selection_get();
-        if (range != null) {
-            var endNode = Position_closestActualNode(range.end);
-            for (; endNode != null; endNode = endNode.parentNode) {
-                if (isAutoCorrectNode(endNode))
-                    return correctionsByNode.get(endNode);
-            }
-        }
-
-        if (correctionList.length > 0)
-            return correctionList[correctionList.length-1];
-
-        return null;
-    }
-
-    AutoCorrect_acceptCorrection = function()
-    {
-        UndoManager_newGroup("Accept");
-        var correction = getCurrent();
-        if (correction == null)
-            return;
-
-        removeCorrectionSpan(correction.span);
-        UndoManager_newGroup();
-    }
-
-    AutoCorrect_revertCorrection = function()
-    {
-        var correction = getCurrent();
-        if (correction == null)
-            return;
-
-        AutoCorrect_replaceCorrection(correction.span.getAttribute("original"));
-    }
-
-    AutoCorrect_replaceCorrection = function(replacement)
-    {
-        UndoManager_newGroup("Replace");
-        var correction = getCurrent();
-        if (correction == null)
-            return;
-
-        Selection_preserveWhileExecuting(function() {
-            var text = DOM_createTextNode(document,replacement);
-            DOM_insertBefore(correction.span.parentNode,text,correction.span);
-            DOM_deleteNode(correction.span);
-            Formatting_mergeWithNeighbours(text,{});
-        });
-        UndoManager_newGroup();
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/ChangeTracking.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/ChangeTracking.js b/experiments/editorFramework/src/Layer0_Javascript/ChangeTracking.js
deleted file mode 100644
index ba25a44..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/ChangeTracking.js
+++ /dev/null
@@ -1,127 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var ChangeTracking_showChanges;
-var ChangeTracking_trackChanges;
-var ChangeTracking_setShowChanges;
-var ChangeTracking_setTrackChanges;
-var ChangeTracking_acceptSelectedChanges;
-
-(function() {
-
-    var showChangesEnabled = false;
-    var trackChangesEnabled = false;
-
-    ChangeTracking_showChanges = function()
-    {
-        return showChangesEnabled;
-    }
-
-    ChangeTracking_trackChanges = function()
-    {
-        return trackChangesEnabled;
-    }
-
-    ChangeTracking_setShowChanges = function(enabled)
-    {
-        showChangesEnabled = enabled;
-    }
-
-    ChangeTracking_setTrackChanges = function(enabled)
-    {
-        trackChangesEnabled = enabled;
-    }
-
-    ChangeTracking_acceptSelectedChanges = function()
-    {
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-
-        var outermost = Range_getOutermostNodes(selRange,true);
-        var checkEmpty = new Array();
-
-        Selection_preserveWhileExecuting(function() {
-            for (var i = 0; i < outermost.length; i++) {
-                recurse(outermost[i]);
-
-                var next;
-                for (ancestor = outermost[i].parentNode; ancestor != null; ancestor = next) {
-                    next = ancestor.parentNode;
-                    if (ancestor._type == HTML_DEL) {
-                        checkEmpty.push(ancestor.parentNode);
-                        DOM_deleteNode(ancestor);
-                    }
-                    else if (ancestor._type == HTML_INS)
-                        DOM_removeNodeButKeepChildren(ancestor);
-                }
-            }
-
-            for (var i = 0; i < checkEmpty.length; i++) {
-                var node = checkEmpty[i];
-                if (node == null)
-                    continue;
-                var empty = true;
-                for (var child = node.firstChild; child != null; child = child.nextSibling) {
-                    if (!isWhitespaceTextNode(child)) {
-                        empty = false;
-                        break;
-                    }
-                }
-                if (empty) {
-                    switch (node._type) {
-                    case HTML_LI:
-                    case HTML_UL:
-                    case HTML_OL:
-                        checkEmpty.push(node.parentNode);
-                        DOM_deleteNode(node);
-                        break;
-                    }
-                }
-            }
-        });
-
-        var selRange = Selection_get();
-        if (selRange != null) {
-            var start = Position_closestMatchForwards(selRange.start,Position_okForInsertion);
-            var end = Position_closestMatchBackwards(selRange.end,Position_okForInsertion);
-            if (!Range_isForwards(new Range(start.node,start.offset,end.node,end.offset)))
-                end = Position_closestMatchForwards(selRange.end,Position_okForInsertion);
-            Selection_set(start.node,start.offset,end.node,end.offset);
-        }
-
-        function recurse(node)
-        {
-            if (node._type == HTML_DEL) {
-                checkEmpty.push(node.parentNode);
-                DOM_deleteNode(node);
-                return;
-            }
-
-            var next;
-            for (var child = node.firstChild; child != null; child = next) {
-                next = child.nextSibling;
-                recurse(child);
-            }
-
-            if (node._type == HTML_INS) {
-                DOM_removeNodeButKeepChildren(node);
-            }
-        }
-    }
-
-})();


[13/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/DOM.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/DOM.js b/experiments/editorFramework/src/Layer0_Javascript/DOM.js
deleted file mode 100644
index b2371bc..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/DOM.js
+++ /dev/null
@@ -1,966 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-// Helper functions
-var DOM_assignNodeIds;
-
-// Primitive node creation operations
-var DOM_createElement;
-var DOM_createElementNS;
-var DOM_createTextNode;
-var DOM_createComment;
-var DOM_cloneNode;
-
-// Primitive and high-level node mutation operations
-var DOM_appendChild;
-var DOM_insertBefore;
-var DOM_deleteNode;
-var DOM_setAttribute;
-var DOM_setAttributeNS;
-var DOM_removeAttribute;
-var DOM_removeAttributeNS;
-var DOM_setStyleProperties;
-var DOM_insertCharacters;
-var DOM_moveCharacters;
-var DOM_deleteCharacters;
-var DOM_setNodeValue;
-
-// High-level DOM operations
-var DOM_getAttribute;
-var DOM_getAttributeNS;
-var DOM_getStringAttribute;
-var DOM_getStringAttributeNS;
-var DOM_getStyleProperties;
-var DOM_deleteAllChildren;
-var DOM_shallowCopyElement;
-var DOM_replaceElement;
-var DOM_wrapNode;
-var DOM_wrapSiblings;
-var DOM_mergeWithNextSibling;
-var DOM_nodesMergeable;
-var DOM_replaceCharacters;
-var DOM_addTrackedPosition;
-var DOM_removeTrackedPosition;
-var DOM_removeAdjacentWhitespace;
-var DOM_documentHead;
-var DOM_ensureUniqueIds;
-var DOM_nodeOffset;
-var DOM_maxChildOffset;
-var DOM_ignoreMutationsWhileExecuting;
-var DOM_getIgnoreMutations;
-var DOM_addListener;
-var DOM_removeListener;
-var DOM_Listener;
-
-(function() {
-
-    var nextNodeId = 0;
-    var nodeData = new Object();
-    var ignoreMutations = 0;
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    //                                                                                            //
-    //                                    DOM Helper Functions                                    //
-    //                                                                                            //
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-
-    function addUndoAction()
-    {
-        if (window.undoSupported)
-            UndoManager_addAction.apply(null,arrayCopy(arguments));
-    }
-
-    function assignNodeId(node)
-    {
-        if (node._nodeId != null)
-            throw new Error(node+" already has id");
-        node._nodeId = nextNodeId++;
-        node._type = ElementTypes[node.nodeName];
-        return node;
-    }
-
-    function checkNodeId(node)
-    {
-        if (node._nodeId == null)
-            throw new Error(node.nodeName+" lacks _nodeId");
-    }
-
-    // public
-    DOM_assignNodeIds = function(root)
-    {
-        if (root._nodeId != null)
-            throw new Error(root+" already has id");
-        recurse(root);
-        return;
-
-        function recurse(node) {
-            node._nodeId = nextNodeId++;
-            node._type = ElementTypes[node.nodeName];
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    //                                                                                            //
-    //                                  Primitive DOM Operations                                  //
-    //                                                                                            //
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-
-    /*
-
-      The following functions are considered "primitive", in that they are the core functions
-      through which all manipulation of the DOM ultimately occurs. All other DOM functions call
-      these, either directly or indirectly, instead of making direct method calls on node objects.
-      These functions are divided into two categories: node creation and mode mutation.
-
-      The creation functions are as follows:
-
-      * createElement(document,elementName)
-      * createElementNS(document,namespaceURI,qualifiedName)
-      * createTextNode(document,data)
-      * createComment(document,data)
-      * cloneNode(original,deep,noIdAttr)
-
-      The purpose of these is to ensure that a unique _nodeId value is assigned to each node object,
-      which is needed for using the NodeSet and NodeMap classes. All nodes in a document must have
-      this set; we use our own functions for this because DOM provides no other way of uniquely
-      identifying nodes in a way that allows them to be stored in a hash table.
-
-      The mutation functions are as follows:
-
-      * insertBeforeInternal(parent,newChild,refChild)
-      * deleteNodeInternal(node,deleteDescendantData)
-      * setAttribute(element,name,value)
-      * setAttributeNS(element,namespaceURI,qualifiedName,value)
-      * setStyleProperties(element,properties)
-      * insertCharacters(textNode,offset,characters)
-      * deleteCharacters(textNode,startOffset,endOffset)
-      * moveCharacters(srcTextNode,srcStartOffset,srcEndOffset,destTextNode,destOffset)
-      * setNodeValue(textNode,value)
-
-      These functions exist to allow us to record undo information. We can't use DOM mutation events
-      for this purpose they're not fully supported in WebKit.
-
-      Every time a mutation operation is performed on a node, we add an action to the undo stack
-      corresponding to the inverse of that operaton, i.e. an action that undoes the operaton. It
-      is absolutely critical that all changes to a DOM node go through these functions, regardless
-      of whether or not the node currently resides in the tree. This ensures that the undo history
-      is able to correctly revert the tree to the same state that it was in at the relevant point
-      in time.
-
-      By routing all DOM modifications through these few functions, virtually all of the other
-      javascript code can be ignorant of the undo manager, provided the only state they change is
-      in the DOM. Parts of the code which maintain their own state about the document, such as the
-      style manager, must implement their own undo-compliant state manipulation logic.
-
-      *** IMPORTANT ***
-
-      Just in case it isn't already clear, you must *never* make direct calls to methods like
-      appendChild() and createElement() on the node objects themselves. Doing so will result in
-      subtle and probably hard-to-find bugs. As far as all javascript code for UX Write is
-      concerned, consider the public functions defined in this file to be the DOM API. You can use
-      check-dom-methods.sh to search for any cases where this rule has been violated.
-
-      */
-
-    // public
-    DOM_createElement = function(document,elementName)
-    {
-        return assignNodeId(document.createElement(elementName)); // check-ok
-    }
-
-    // public
-    DOM_createElementNS = function(document,namespaceURI,qualifiedName)
-    {
-        return assignNodeId(document.createElementNS(namespaceURI,qualifiedName)); // check-ok
-    }
-
-    // public
-    DOM_createTextNode = function(document,data)
-    {
-        return assignNodeId(document.createTextNode(data)); // check-ok
-    }
-
-    // public
-    DOM_createComment = function(document,data)
-    {
-        return assignNodeId(document.createComment(data)); // check-ok
-    }
-
-    // public
-    DOM_cloneNode = function(original,deep,noIdAttr)
-    {
-        var clone = original.cloneNode(deep); // check-ok
-        DOM_assignNodeIds(clone);
-        if (noIdAttr)
-            clone.removeAttribute("id"); // check-ok
-        return clone;
-    }
-
-    function insertBeforeInternal(parent,newChild,refChild)
-    {
-        if (newChild.parentNode == null) {
-            addUndoAction(deleteNodeInternal,newChild)
-        }
-        else {
-            var oldParent = newChild.parentNode;
-            var oldNext = newChild.nextSibling;
-            addUndoAction(insertBeforeInternal,oldParent,newChild,oldNext);
-        }
-
-        parent.insertBefore(newChild,refChild); // check-ok
-    }
-
-    function deleteNodeInternal(node,deleteDescendantData)
-    {
-        checkNodeId(node);
-
-        addUndoAction(insertBeforeInternal,node.parentNode,node,node.nextSibling);
-
-        if (node.parentNode == null)
-            throw new Error("Undo delete "+nodeString(node)+": parent is null");
-        node.parentNode.removeChild(node); // check-ok
-
-        // Delete all data associated with the node. This is not preserved across undo/redo;
-        // currently the only thing we are using this data for is tracked positions, and we
-        // are going to be recording undo information for the selection separately, so this is
-        // not a problem.
-        if (deleteDescendantData)
-            deleteNodeDataRecursive(node);
-        else
-            deleteNodeData(node);
-
-        return;
-
-        function deleteNodeData(current)
-        {
-            delete nodeData[current._nodeId];
-        }
-
-        function deleteNodeDataRecursive(current)
-        {
-            deleteNodeData(current);
-            for (var child = current.firstChild; child != null; child = child.nextSibling)
-                deleteNodeDataRecursive(child);
-        }
-    }
-
-    // public
-    DOM_setAttribute = function(element,name,value)
-    {
-        if (element.hasAttribute(name))
-            addUndoAction(DOM_setAttribute,element,name,element.getAttribute(name));
-        else
-            addUndoAction(DOM_setAttribute,element,name,null);
-
-        if (value == null)
-            element.removeAttribute(name); // check-ok
-        else
-            element.setAttribute(name,value); // check-ok
-    }
-
-    // public
-    DOM_setAttributeNS = function(element,namespaceURI,qualifiedName,value)
-    {
-        var localName = qualifiedName.replace(/^.*:/,"");
-        if (element.hasAttributeNS(namespaceURI,localName)) {
-            var oldValue = element.getAttributeNS(namespaceURI,localName);
-            var oldQName = element.getAttributeNodeNS(namespaceURI,localName).nodeName; // check-ok
-            addUndoAction(DOM_setAttributeNS,element,namespaceURI,oldQName,oldValue)
-        }
-        else {
-            addUndoAction(DOM_setAttributeNS,element,namespaceURI,localName,null);
-        }
-
-        if (value == null)
-            element.removeAttributeNS(namespaceURI,localName); // check-ok
-        else
-            element.setAttributeNS(namespaceURI,qualifiedName,value); // check-ok
-    }
-
-    // public
-    DOM_setStyleProperties = function(element,properties)
-    {
-        if (Object.getOwnPropertyNames(properties).length == 0)
-            return;
-
-        if (element.hasAttribute("style"))
-            addUndoAction(DOM_setAttribute,element,"style",element.getAttribute("style"));
-        else
-            addUndoAction(DOM_setAttribute,element,"style",null);
-
-        for (var name in properties)
-            element.style.setProperty(name,properties[name]); // check-ok
-
-        if (element.getAttribute("style") == "")
-            element.removeAttribute("style"); // check-ok
-    }
-
-    // public
-    DOM_insertCharacters = function(textNode,offset,characters)
-    {
-        if (textNode.nodeType != Node.TEXT_NODE)
-            throw new Error("DOM_insertCharacters called on non-text node");
-        if ((offset < 0) || (offset > textNode.nodeValue.length))
-            throw new Error("DOM_insertCharacters called with invalid offset");
-        trackedPositionsForNode(textNode).forEach(function (position) {
-            if (position.offset > offset)
-                position.offset += characters.length;
-        });
-        textNode.nodeValue = textNode.nodeValue.slice(0,offset) +
-                             characters +
-                             textNode.nodeValue.slice(offset);
-        var startOffset = offset;
-        var endOffset = offset + characters.length;
-        addUndoAction(DOM_deleteCharacters,textNode,startOffset,endOffset);
-    }
-
-    // public
-    DOM_deleteCharacters = function(textNode,startOffset,endOffset)
-    {
-        if (textNode.nodeType != Node.TEXT_NODE)
-            throw new Error("DOM_deleteCharacters called on non-text node "+nodeString(textNode));
-        if (endOffset == null)
-            endOffset = textNode.nodeValue.length;
-        if (endOffset < startOffset)
-            throw new Error("DOM_deleteCharacters called with invalid start/end offset");
-        trackedPositionsForNode(textNode).forEach(function (position) {
-            var deleteCount = endOffset - startOffset;
-            if ((position.offset > startOffset) && (position.offset < endOffset))
-                position.offset = startOffset;
-            else if (position.offset >= endOffset)
-                position.offset -= deleteCount;
-        });
-
-        var removed = textNode.nodeValue.slice(startOffset,endOffset);
-        addUndoAction(DOM_insertCharacters,textNode,startOffset,removed);
-
-        textNode.nodeValue = textNode.nodeValue.slice(0,startOffset) +
-                             textNode.nodeValue.slice(endOffset);
-    }
-
-    // public
-    DOM_moveCharacters = function(srcTextNode,srcStartOffset,srcEndOffset,destTextNode,destOffset,
-                                  excludeStartPos,excludeEndPos)
-    {
-        if (srcTextNode == destTextNode)
-            throw new Error("src and dest text nodes cannot be the same");
-        if (srcStartOffset > srcEndOffset)
-            throw new Error("Invalid src range "+srcStartOffset+" - "+srcEndOffset);
-        if (srcStartOffset < 0)
-            throw new Error("srcStartOffset < 0");
-        if (srcEndOffset > srcTextNode.nodeValue.length)
-            throw new Error("srcEndOffset beyond end of src length");
-        if (destOffset < 0)
-            throw new Error("destOffset < 0");
-        if (destOffset > destTextNode.nodeValue.length)
-            throw new Error("destOffset beyond end of dest length");
-
-        var length = srcEndOffset - srcStartOffset;
-
-        addUndoAction(DOM_moveCharacters,destTextNode,destOffset,destOffset+length,
-                      srcTextNode,srcStartOffset,excludeStartPos,excludeEndPos);
-
-        trackedPositionsForNode(destTextNode).forEach(function (pos) {
-            var startMatch = excludeStartPos ? (pos.offset > destOffset)
-                                             : (pos.offset >= destOffset);
-            if (startMatch)
-                pos.offset += length;
-        });
-        trackedPositionsForNode(srcTextNode).forEach(function (pos) {
-
-            var startMatch = excludeStartPos ? (pos.offset > srcStartOffset)
-                                             : (pos.offset >= srcStartOffset);
-            var endMatch = excludeEndPos ? (pos.offset < srcEndOffset)
-                                         : (pos.offset <= srcEndOffset);
-
-            if (startMatch && endMatch) {
-                pos.node = destTextNode;
-                pos.offset = destOffset + (pos.offset - srcStartOffset);
-            }
-            else if (pos.offset >= srcEndOffset) {
-                pos.offset -= length;
-            }
-        });
-        var extract = srcTextNode.nodeValue.substring(srcStartOffset,srcEndOffset);
-        srcTextNode.nodeValue = srcTextNode.nodeValue.slice(0,srcStartOffset) +
-                                srcTextNode.nodeValue.slice(srcEndOffset);
-        destTextNode.nodeValue = destTextNode.nodeValue.slice(0,destOffset) +
-                                 extract +
-                                 destTextNode.nodeValue.slice(destOffset);
-    }
-
-    // public
-    DOM_setNodeValue = function(textNode,value)
-    {
-        if (textNode.nodeType != Node.TEXT_NODE)
-            throw new Error("DOM_setNodeValue called on non-text node");
-        trackedPositionsForNode(textNode).forEach(function (position) {
-            position.offset = 0;
-        });
-        var oldValue = textNode.nodeValue;
-        addUndoAction(DOM_setNodeValue,textNode,oldValue);
-        textNode.nodeValue = value;
-    }
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    //                                                                                            //
-    //                                  High-level DOM Operations                                 //
-    //                                                                                            //
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-
-    function appendChildInternal(parent,newChild)
-    {
-        insertBeforeInternal(parent,newChild,null);
-    }
-
-    // public
-    DOM_appendChild = function(node,child)
-    {
-        return DOM_insertBefore(node,child,null);
-    }
-
-    // public
-    DOM_insertBefore = function(parent,child,nextSibling)
-    {
-        var newOffset;
-        if (nextSibling != null)
-            newOffset = DOM_nodeOffset(nextSibling);
-        else
-            newOffset = parent.childNodes.length;
-
-        var oldParent = child.parentNode;
-        if (oldParent != null) { // already in tree
-            var oldOffset = DOM_nodeOffset(child);
-
-            if ((oldParent == parent) && (newOffset > oldOffset))
-                newOffset--;
-
-            trackedPositionsForNode(oldParent).forEach(function (position) {
-                if (position.offset > oldOffset) {
-                    position.offset--;
-                }
-                else if (position.offset == oldOffset) {
-                    position.node = parent;
-                    position.offset = newOffset;
-                }
-            });
-        }
-
-        var result = insertBeforeInternal(parent,child,nextSibling);
-        trackedPositionsForNode(parent).forEach(function (position) {
-            if (position.offset > newOffset)
-                position.offset++;
-        });
-        return result;
-    }
-
-    // public
-    DOM_deleteNode = function(node)
-    {
-        if (node.parentNode == null) // already deleted
-            return;
-        adjustPositionsRecursive(node);
-        deleteNodeInternal(node,true);
-
-        function adjustPositionsRecursive(current)
-        {
-            for (var child = current.firstChild; child != null; child = child.nextSibling)
-                adjustPositionsRecursive(child);
-
-            trackedPositionsForNode(current.parentNode).forEach(function (position) {
-                var offset = DOM_nodeOffset(current);
-                if (offset < position.offset) {
-                    position.offset--;
-                }
-            });
-            trackedPositionsForNode(current).forEach(function (position) {
-                var offset = DOM_nodeOffset(current);
-                position.node = current.parentNode;
-                position.offset = offset;
-            });
-        }
-    }
-
-    // public
-    DOM_removeAttribute = function(element,name,value)
-    {
-        DOM_setAttribute(element,name,null);
-    }
-
-    // public
-    DOM_removeAttributeNS = function(element,namespaceURI,localName)
-    {
-        DOM_setAttributeNS(element,namespaceURI,localName,null)
-    }
-
-    // public
-    DOM_getAttribute = function(element,name)
-    {
-        if (element.hasAttribute(name))
-            return element.getAttribute(name);
-        else
-            return null;
-    }
-
-    // public
-    DOM_getAttributeNS = function(element,namespaceURI,localName)
-    {
-        if (element.hasAttributeNS(namespaceURI,localName))
-            return element.getAttributeNS(namespaceURI,localName);
-        else
-            return null;
-    }
-
-    // public
-    DOM_getStringAttribute = function(element,name)
-    {
-        var value = element.getAttribute(name);
-        return (value == null) ? "" : value;
-    }
-
-    // public
-    DOM_getStringAttributeNS = function(element,namespaceURI,localName)
-    {
-        var value = element.getAttributeNS(namespaceURI,localName);
-        return (value == null) ? "" : value;
-    }
-
-    // public
-    DOM_getStyleProperties = function(node)
-    {
-        var properties = new Object();
-        if (node.nodeType == Node.ELEMENT_NODE) {
-            for (var i = 0; i < node.style.length; i++) {
-                var name = node.style[i];
-                var value = node.style.getPropertyValue(name);
-                properties[name] = value;
-            }
-        }
-        return properties;
-    }
-
-    // public
-    DOM_deleteAllChildren = function(parent)
-    {
-        while (parent.firstChild != null)
-            DOM_deleteNode(parent.firstChild);
-    }
-
-    // public
-    DOM_shallowCopyElement = function(element)
-    {
-        return DOM_cloneNode(element,false,true);
-    }
-
-    // public
-    DOM_removeNodeButKeepChildren = function(node)
-    {
-        if (node.parentNode == null)
-            throw new Error("Node "+nodeString(node)+" has no parent");
-        var offset = DOM_nodeOffset(node);
-        var childCount = node.childNodes.length;
-
-        trackedPositionsForNode(node.parentNode).forEach(function (position) {
-            if (position.offset > offset)
-                position.offset += childCount-1;
-        });
-
-        trackedPositionsForNode(node).forEach(function (position) {
-            position.node = node.parentNode;
-            position.offset += offset;
-        });
-
-        var parent = node.parentNode;
-        var nextSibling = node.nextSibling;
-        deleteNodeInternal(node,false);
-
-        while (node.firstChild != null) {
-            var child = node.firstChild;
-            insertBeforeInternal(parent,child,nextSibling);
-        }
-    }
-
-    // public
-    DOM_replaceElement = function(oldElement,newName)
-    {
-        var listeners = listenersForNode(oldElement);
-        var newElement = DOM_createElement(document,newName);
-        for (var i = 0; i < oldElement.attributes.length; i++) {
-            var name = oldElement.attributes[i].nodeName; // check-ok
-            var value = oldElement.getAttribute(name);
-            DOM_setAttribute(newElement,name,value);
-        }
-
-        var positions = arrayCopy(trackedPositionsForNode(oldElement));
-        if (positions != null) {
-            for (var i = 0; i < positions.length; i++) {
-                if (positions[i].node != oldElement)
-                    throw new Error("replaceElement: position with wrong node");
-                positions[i].node = newElement;
-            }
-        }
-
-        var parent = oldElement.parentNode;
-        var nextSibling = oldElement.nextSibling;
-        while (oldElement.firstChild != null)
-            appendChildInternal(newElement,oldElement.firstChild);
-        // Deletion must be done first so if it's a heading, the outline code picks up the change
-        // correctly. Otherwise, there could be two elements in the document with the same id at
-        // the same time.
-        deleteNodeInternal(oldElement,false);
-        insertBeforeInternal(parent,newElement,nextSibling);
-
-        for (var i = 0; i < listeners.length; i++)
-            listeners[i].afterReplaceElement(oldElement,newElement);
-
-        return newElement;
-    }
-
-    // public
-    DOM_wrapNode = function(node,elementName)
-    {
-        return DOM_wrapSiblings(node,node,elementName);
-    }
-
-    DOM_wrapSiblings = function(first,last,elementName)
-    {
-        var parent = first.parentNode;
-        var wrapper = DOM_createElement(document,elementName);
-
-        if (first.parentNode != last.parentNode)
-            throw new Error("first and last are not siblings");
-
-        if (parent != null) {
-            var firstOffset = DOM_nodeOffset(first);
-            var lastOffset = DOM_nodeOffset(last);
-            var nodeCount = lastOffset - firstOffset + 1;
-            trackedPositionsForNode(parent).forEach(function (position) {
-                if ((position.offset >= firstOffset) && (position.offset <= lastOffset+1)) {
-                    position.node = wrapper;
-                    position.offset -= firstOffset;
-                }
-                else if (position.offset > lastOffset+1) {
-                    position.offset -= (nodeCount-1);
-                }
-            });
-
-            insertBeforeInternal(parent,wrapper,first);
-        }
-
-        var end = last.nextSibling;
-        var current = first;
-        while (current != end) {
-            var next = current.nextSibling;
-            appendChildInternal(wrapper,current);
-            current = next;
-        }
-        return wrapper;
-    }
-
-    // public
-    DOM_mergeWithNextSibling = function(current,whiteList)
-    {
-        var parent = current.parentNode;
-        var next = current.nextSibling;
-
-        if ((next == null) || !DOM_nodesMergeable(current,next,whiteList))
-            return;
-
-        var currentLength = DOM_maxChildOffset(current);
-        var nextOffset = DOM_nodeOffset(next);
-
-        var lastChild = null;
-
-        if (current.nodeType == Node.ELEMENT_NODE) {
-            lastChild = current.lastChild;
-            DOM_insertBefore(current,next,null);
-            DOM_removeNodeButKeepChildren(next);
-        }
-        else {
-            DOM_insertCharacters(current,current.nodeValue.length,next.nodeValue);
-
-            trackedPositionsForNode(next).forEach(function (position) {
-                position.node = current;
-                position.offset = position.offset+currentLength;
-            });
-
-            trackedPositionsForNode(current.parentNode).forEach(function (position) {
-                if (position.offset == nextOffset) {
-                    position.node = current;
-                    position.offset = currentLength;
-                }
-            });
-
-            DOM_deleteNode(next);
-        }
-
-        if (lastChild != null)
-            DOM_mergeWithNextSibling(lastChild,whiteList);
-    }
-
-    // public
-    DOM_nodesMergeable = function(a,b,whiteList)
-    {
-        if ((a.nodeType == Node.TEXT_NODE) && (b.nodeType == Node.TEXT_NODE))
-            return true;
-        else if ((a.nodeType == Node.ELEMENT_NODE) && (b.nodeType == Node.ELEMENT_NODE))
-            return elementsMergableTypes(a,b);
-        else
-            return false;
-
-        function elementsMergableTypes(a,b)
-        {
-            if (whiteList["force"] && isParagraphNode(a) && isParagraphNode(b))
-                return true;
-            if ((a._type == b._type) &&
-                whiteList[a._type] &&
-                (a.attributes.length == b.attributes.length)) {
-                for (var i = 0; i < a.attributes.length; i++) {
-                    var attrName = a.attributes[i].nodeName; // check-ok
-                    if (a.getAttribute(attrName) != b.getAttribute(attrName))
-                        return false;
-                }
-                return true;
-            }
-
-            return false;
-        }
-    }
-
-    function getDataForNode(node,create)
-    {
-        if (node._nodeId == null)
-            throw new Error("getDataForNode: node "+node.nodeName+" has no _nodeId property");
-        if ((nodeData[node._nodeId] == null) && create)
-            nodeData[node._nodeId] = new Object();
-        return nodeData[node._nodeId];
-    }
-
-    function trackedPositionsForNode(node)
-    {
-        var data = getDataForNode(node,false);
-        if ((data != null) && (data.trackedPositions != null)) {
-            // Sanity check
-            for (var i = 0; i < data.trackedPositions.length; i++) {
-                if (data.trackedPositions[i].node != node)
-                    throw new Error("Position "+data.trackedPositions[i]+" has wrong node");
-            }
-            return arrayCopy(data.trackedPositions);
-        }
-        else {
-            return [];
-        }
-    }
-
-    function listenersForNode(node)
-    {
-        var data = getDataForNode(node,false);
-        if ((data != null) && (data.listeners != null))
-            return data.listeners;
-        else
-            return [];
-    }
-
-    // public
-    DOM_replaceCharacters = function(textNode,startOffset,endOffset,replacement)
-    {
-        // Note that we do the insertion *before* the deletion so that the position is properly
-        // maintained, and ends up at the end of the replacement (unless it was previously at
-        // startOffset, in which case it will stay the same)
-        DOM_insertCharacters(textNode,startOffset,replacement);
-        DOM_deleteCharacters(textNode,startOffset+replacement.length,endOffset+replacement.length);
-    }
-
-    // public
-    DOM_addTrackedPosition = function(position)
-    {
-        var data = getDataForNode(position.node,true);
-        if (data.trackedPositions == null)
-            data.trackedPositions = new Array();
-        data.trackedPositions.push(position);
-    }
-
-    // public
-    DOM_removeTrackedPosition = function(position)
-    {
-        var data = getDataForNode(position.node,false);
-        if ((data == null) || (data.trackedPositions == null))
-            throw new Error("DOM_removeTrackedPosition: no registered positions for this node "+
-                            "("+position.node.nodeName+")");
-        for (var i = 0; i < data.trackedPositions.length; i++) {
-            if (data.trackedPositions[i] == position) {
-                data.trackedPositions.splice(i,1);
-                return;
-            }
-        }
-        throw new Error("DOM_removeTrackedPosition: position is not registered ("+
-                        data.trackedPositions.length+" others)");
-    }
-
-    // public
-    DOM_removeAdjacentWhitespace = function(node)
-    {
-        while ((node.previousSibling != null) && (isWhitespaceTextNode(node.previousSibling)))
-            DOM_deleteNode(node.previousSibling);
-        while ((node.nextSibling != null) && (isWhitespaceTextNode(node.nextSibling)))
-            DOM_deleteNode(node.nextSibling);
-    }
-
-    // public
-    DOM_documentHead = function(document)
-    {
-        var html = document.documentElement;
-        for (var child = html.firstChild; child != null; child = child.nextSibling) {
-            if (child._type == HTML_HEAD)
-                return child;
-        }
-        throw new Error("Document contains no HEAD element");
-    }
-
-    // public
-    DOM_ensureUniqueIds = function(root)
-    {
-        var ids = new Object();
-        var duplicates = new Array();
-
-        discoverDuplicates(root);
-        renameDuplicates();
-
-        return;
-
-        function discoverDuplicates(node)
-        {
-            if (node.nodeType != Node.ELEMENT_NODE)
-                return;
-
-            var id = node.getAttribute("id");
-            if ((id != null) && (id != "")) {
-                if (ids[id])
-                    duplicates.push(node);
-                else
-                    ids[id] = true;
-            }
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                discoverDuplicates(child);
-        }
-
-        function renameDuplicates()
-        {
-            var nextNumberForPrefix = new Object();
-            for (var i = 0; i < duplicates.length; i++) {
-                var id = duplicates[i].getAttribute("id");
-                var prefix = id.replace(/[0-9]+$/,"");
-                var num = nextNumberForPrefix[prefix] ? nextNumberForPrefix[prefix] : 1;
-
-                var candidate;
-                do {
-                    candidate = prefix + num;
-                    num++;
-                } while (ids[candidate]);
-
-                DOM_setAttribute(duplicates[i],"id",candidate);
-                ids[candidate] = true;
-                nextNumberForPrefix[prefix] = num;
-            }
-        }
-    }
-
-    // public
-    DOM_nodeOffset = function(node,parent)
-    {
-        if ((node == null) && (parent != null))
-            return DOM_maxChildOffset(parent);
-        var offset = 0;
-        for (var n = node.parentNode.firstChild; n != node; n = n.nextSibling)
-            offset++;
-        return offset;
-    }
-
-    // public
-    DOM_maxChildOffset = function(node)
-    {
-        if (node.nodeType == Node.TEXT_NODE)
-            return node.nodeValue.length;
-        else if (node.nodeType == Node.ELEMENT_NODE)
-            return node.childNodes.length;
-        else
-            throw new Error("maxOffset: invalid node type ("+node.nodeType+")");
-    }
-
-    function incIgnoreMutations()
-    {
-        UndoManager_addAction(decIgnoreMutations);
-        ignoreMutations++;
-    }
-
-    function decIgnoreMutations()
-    {
-        UndoManager_addAction(incIgnoreMutations);
-        ignoreMutations--;
-        if (ignoreMutations < 0)
-            throw new Error("ignoreMutations is now negative");
-    }
-
-    // public
-    DOM_ignoreMutationsWhileExecuting = function(fun)
-    {
-        incIgnoreMutations();
-        try {
-            return fun();
-        }
-        finally {
-            decIgnoreMutations();
-        }
-    }
-
-    // public
-    DOM_getIgnoreMutations = function()
-    {
-        return ignoreMutations;
-    }
-
-    // public
-    DOM_addListener = function(node,listener)
-    {
-        var data = getDataForNode(node,true);
-        if (data.listeners == null)
-            data.listeners = [listener];
-        else
-            data.listeners.push(listener);
-    }
-
-    // public
-    DOM_removeListener = function(node,listener)
-    {
-        var list = listenersForNode(node);
-        var index = list.indexOf(listener);
-        if (index >= 0)
-            list.splice(index,1);
-    }
-
-    // public
-    function Listener()
-    {
-    }
-
-    Listener.prototype.afterReplaceElement = function(oldElement,newElement) {}
-
-    DOM_Listener = Listener;
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Editor.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Editor.js b/experiments/editorFramework/src/Layer0_Javascript/Editor.js
deleted file mode 100644
index 50f0d21..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Editor.js
+++ /dev/null
@@ -1,113 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Editor_getBackMessages;
-var Editor_debug;
-var Editor_addOutlineItem;
-var Editor_updateOutlineItem;
-var Editor_removeOutlineItem;
-var Editor_outlineUpdated;
-var Editor_setCursor;
-var Editor_setSelectionHandles;
-var Editor_clearSelectionHandlesAndCursor;
-var Editor_setSelectionBounds;
-var Editor_updateAutoCorrect;
-var Editor_error;
-var debug;
-
-(function(){
-
-    var backMessages = new Array();
-
-    function addBackMessage()
-    {
-        backMessages.push(arrayCopy(arguments));
-        return null;
-    }
-
-    Editor_getBackMessages = function()
-    {
-        var result = JSON.stringify(backMessages);
-        backMessages = new Array();
-        return result;
-    };
-
-    Editor_debug = function(str)
-    {
-        addBackMessage("debug",str);
-    };
-
-    Editor_error = function(error,type)
-    {
-        if (type == null)
-            type = "";
-        addBackMessage("error",error.toString(),type);
-    };
-
-    Editor_addOutlineItem = function(itemId,type,title)
-    {
-        addBackMessage("addOutlineItem",itemId,type,title);
-    };
-
-    Editor_updateOutlineItem = function(itemId,title)
-    {
-        addBackMessage("updateOutlineItem",itemId,title);
-    };
-
-    Editor_removeOutlineItem = function(itemId)
-    {
-        addBackMessage("removeOutlineItem",itemId);
-    };
-
-    Editor_outlineUpdated = function()
-    {
-        addBackMessage("outlineUpdated");
-    };
-
-    Editor_setCursor = function(x,y,width,height)
-    {
-        addBackMessage("setCursor",x,y,width,height);
-    };
-
-    Editor_setSelectionHandles = function(x1,y1,height1,x2,y2,height2)
-    {
-        addBackMessage("setSelectionHandles",x1,y1,height1,x2,y2,height2);
-    };
-
-    Editor_setTableSelection = function(x,y,width,height)
-    {
-        addBackMessage("setTableSelection",x,y,width,height);
-    };
-
-    Editor_setSelectionBounds = function(left,top,right,bottom)
-    {
-        addBackMessage("setSelectionBounds",left,top,right,bottom);
-    };
-
-    Editor_clearSelectionHandlesAndCursor = function()
-    {
-        addBackMessage("clearSelectionHandlesAndCursor");
-    };
-
-    Editor_updateAutoCorrect = function()
-    {
-        addBackMessage("updateAutoCorrect");
-    };
-
-    debug = Editor_debug;
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/ElementTypes.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/ElementTypes.js b/experiments/editorFramework/src/Layer0_Javascript/ElementTypes.js
deleted file mode 100644
index 06702a2..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/ElementTypes.js
+++ /dev/null
@@ -1,344 +0,0 @@
-// Automatically generated from elements.txt
-ElementTypes = {
-  "#DOCUMENT": 1,
-  "#document": 1,
-  "#TEXT": 2,
-  "#text": 2,
-  "#COMMENT": 3,
-  "#comment": 3,
-  "A": 4,
-  "a": 4,
-  "ABBR": 5,
-  "abbr": 5,
-  "ADDRESS": 6,
-  "address": 6,
-  "AREA": 7,
-  "area": 7,
-  "ARTICLE": 8,
-  "article": 8,
-  "ASIDE": 9,
-  "aside": 9,
-  "AUDIO": 10,
-  "audio": 10,
-  "B": 11,
-  "b": 11,
-  "BASE": 12,
-  "base": 12,
-  "BDI": 13,
-  "bdi": 13,
-  "BDO": 14,
-  "bdo": 14,
-  "BLOCKQUOTE": 15,
-  "blockquote": 15,
-  "BODY": 16,
-  "body": 16,
-  "BR": 17,
-  "br": 17,
-  "BUTTON": 18,
-  "button": 18,
-  "CANVAS": 19,
-  "canvas": 19,
-  "CAPTION": 20,
-  "caption": 20,
-  "CITE": 21,
-  "cite": 21,
-  "CODE": 22,
-  "code": 22,
-  "COL": 23,
-  "col": 23,
-  "COLGROUP": 24,
-  "colgroup": 24,
-  "COMMAND": 25,
-  "command": 25,
-  "DATA": 26,
-  "data": 26,
-  "DATALIST": 27,
-  "datalist": 27,
-  "DD": 28,
-  "dd": 28,
-  "DEL": 29,
-  "del": 29,
-  "DETAILS": 30,
-  "details": 30,
-  "DFN": 31,
-  "dfn": 31,
-  "DIALOG": 32,
-  "dialog": 32,
-  "DIV": 33,
-  "div": 33,
-  "DL": 34,
-  "dl": 34,
-  "DT": 35,
-  "dt": 35,
-  "EM": 36,
-  "em": 36,
-  "EMBED": 37,
-  "embed": 37,
-  "FIELDSET": 38,
-  "fieldset": 38,
-  "FIGCAPTION": 39,
-  "figcaption": 39,
-  "FIGURE": 40,
-  "figure": 40,
-  "FOOTER": 41,
-  "footer": 41,
-  "FORM": 42,
-  "form": 42,
-  "H1": 43,
-  "h1": 43,
-  "H2": 44,
-  "h2": 44,
-  "H3": 45,
-  "h3": 45,
-  "H4": 46,
-  "h4": 46,
-  "H5": 47,
-  "h5": 47,
-  "H6": 48,
-  "h6": 48,
-  "HEAD": 49,
-  "head": 49,
-  "HEADER": 50,
-  "header": 50,
-  "HGROUP": 51,
-  "hgroup": 51,
-  "HR": 52,
-  "hr": 52,
-  "HTML": 53,
-  "html": 53,
-  "I": 54,
-  "i": 54,
-  "IFRAME": 55,
-  "iframe": 55,
-  "IMG": 56,
-  "img": 56,
-  "INPUT": 57,
-  "input": 57,
-  "INS": 58,
-  "ins": 58,
-  "KBD": 59,
-  "kbd": 59,
-  "KEYGEN": 60,
-  "keygen": 60,
-  "LABEL": 61,
-  "label": 61,
-  "LEGEND": 62,
-  "legend": 62,
-  "LI": 63,
-  "li": 63,
-  "LINK": 64,
-  "link": 64,
-  "MAP": 65,
-  "map": 65,
-  "MARK": 66,
-  "mark": 66,
-  "MENU": 67,
-  "menu": 67,
-  "META": 68,
-  "meta": 68,
-  "METER": 69,
-  "meter": 69,
-  "NAV": 70,
-  "nav": 70,
-  "NOSCRIPT": 71,
-  "noscript": 71,
-  "OBJECT": 72,
-  "object": 72,
-  "OL": 73,
-  "ol": 73,
-  "OPTGROUP": 74,
-  "optgroup": 74,
-  "OPTION": 75,
-  "option": 75,
-  "OUTPUT": 76,
-  "output": 76,
-  "P": 77,
-  "p": 77,
-  "PARAM": 78,
-  "param": 78,
-  "PRE": 79,
-  "pre": 79,
-  "PROGRESS": 80,
-  "progress": 80,
-  "Q": 81,
-  "q": 81,
-  "RP": 82,
-  "rp": 82,
-  "RT": 83,
-  "rt": 83,
-  "RUBY": 84,
-  "ruby": 84,
-  "S": 85,
-  "s": 85,
-  "SAMP": 86,
-  "samp": 86,
-  "SCRIPT": 87,
-  "script": 87,
-  "SECTION": 88,
-  "section": 88,
-  "SELECT": 89,
-  "select": 89,
-  "SMALL": 90,
-  "small": 90,
-  "SOURCE": 91,
-  "source": 91,
-  "SPAN": 92,
-  "span": 92,
-  "STRONG": 93,
-  "strong": 93,
-  "STYLE": 94,
-  "style": 94,
-  "SUB": 95,
-  "sub": 95,
-  "SUMMARY": 96,
-  "summary": 96,
-  "SUP": 97,
-  "sup": 97,
-  "TABLE": 98,
-  "table": 98,
-  "TBODY": 99,
-  "tbody": 99,
-  "TD": 100,
-  "td": 100,
-  "TEXTAREA": 101,
-  "textarea": 101,
-  "TFOOT": 102,
-  "tfoot": 102,
-  "TH": 103,
-  "th": 103,
-  "THEAD": 104,
-  "thead": 104,
-  "TIME": 105,
-  "time": 105,
-  "TITLE": 106,
-  "title": 106,
-  "TR": 107,
-  "tr": 107,
-  "TRACK": 108,
-  "track": 108,
-  "U": 109,
-  "u": 109,
-  "UL": 110,
-  "ul": 110,
-  "VAR": 111,
-  "var": 111,
-  "VIDEO": 112,
-  "video": 112,
-  "WBR": 113,
-  "wbr": 113,
-};
-
-HTML_DOCUMENT = 1;
-HTML_TEXT = 2;
-HTML_COMMENT = 3;
-HTML_A = 4;
-HTML_ABBR = 5;
-HTML_ADDRESS = 6;
-HTML_AREA = 7;
-HTML_ARTICLE = 8;
-HTML_ASIDE = 9;
-HTML_AUDIO = 10;
-HTML_B = 11;
-HTML_BASE = 12;
-HTML_BDI = 13;
-HTML_BDO = 14;
-HTML_BLOCKQUOTE = 15;
-HTML_BODY = 16;
-HTML_BR = 17;
-HTML_BUTTON = 18;
-HTML_CANVAS = 19;
-HTML_CAPTION = 20;
-HTML_CITE = 21;
-HTML_CODE = 22;
-HTML_COL = 23;
-HTML_COLGROUP = 24;
-HTML_COMMAND = 25;
-HTML_DATA = 26;
-HTML_DATALIST = 27;
-HTML_DD = 28;
-HTML_DEL = 29;
-HTML_DETAILS = 30;
-HTML_DFN = 31;
-HTML_DIALOG = 32;
-HTML_DIV = 33;
-HTML_DL = 34;
-HTML_DT = 35;
-HTML_EM = 36;
-HTML_EMBED = 37;
-HTML_FIELDSET = 38;
-HTML_FIGCAPTION = 39;
-HTML_FIGURE = 40;
-HTML_FOOTER = 41;
-HTML_FORM = 42;
-HTML_H1 = 43;
-HTML_H2 = 44;
-HTML_H3 = 45;
-HTML_H4 = 46;
-HTML_H5 = 47;
-HTML_H6 = 48;
-HTML_HEAD = 49;
-HTML_HEADER = 50;
-HTML_HGROUP = 51;
-HTML_HR = 52;
-HTML_HTML = 53;
-HTML_I = 54;
-HTML_IFRAME = 55;
-HTML_IMG = 56;
-HTML_INPUT = 57;
-HTML_INS = 58;
-HTML_KBD = 59;
-HTML_KEYGEN = 60;
-HTML_LABEL = 61;
-HTML_LEGEND = 62;
-HTML_LI = 63;
-HTML_LINK = 64;
-HTML_MAP = 65;
-HTML_MARK = 66;
-HTML_MENU = 67;
-HTML_META = 68;
-HTML_METER = 69;
-HTML_NAV = 70;
-HTML_NOSCRIPT = 71;
-HTML_OBJECT = 72;
-HTML_OL = 73;
-HTML_OPTGROUP = 74;
-HTML_OPTION = 75;
-HTML_OUTPUT = 76;
-HTML_P = 77;
-HTML_PARAM = 78;
-HTML_PRE = 79;
-HTML_PROGRESS = 80;
-HTML_Q = 81;
-HTML_RP = 82;
-HTML_RT = 83;
-HTML_RUBY = 84;
-HTML_S = 85;
-HTML_SAMP = 86;
-HTML_SCRIPT = 87;
-HTML_SECTION = 88;
-HTML_SELECT = 89;
-HTML_SMALL = 90;
-HTML_SOURCE = 91;
-HTML_SPAN = 92;
-HTML_STRONG = 93;
-HTML_STYLE = 94;
-HTML_SUB = 95;
-HTML_SUMMARY = 96;
-HTML_SUP = 97;
-HTML_TABLE = 98;
-HTML_TBODY = 99;
-HTML_TD = 100;
-HTML_TEXTAREA = 101;
-HTML_TFOOT = 102;
-HTML_TH = 103;
-HTML_THEAD = 104;
-HTML_TIME = 105;
-HTML_TITLE = 106;
-HTML_TR = 107;
-HTML_TRACK = 108;
-HTML_U = 109;
-HTML_UL = 110;
-HTML_VAR = 111;
-HTML_VIDEO = 112;
-HTML_WBR = 113;
-HTML_COUNT = 114;

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Equations.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Equations.js b/experiments/editorFramework/src/Layer0_Javascript/Equations.js
deleted file mode 100644
index 46bace8..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Equations.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Equations_insertEquation;
-
-(function() {
-
-    Equations_insertEquation = function()
-    {
-        var math = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","math");
-        var mrow = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
-        var msup = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","msup");
-        var mi = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
-        var mn = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mn");
-        var mfrac = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mfrac");
-        var mrow1 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
-        var mrow2 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
-        var mi1 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
-        var mi2 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
-        var mo = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mo");
-
-        DOM_appendChild(mi,DOM_createTextNode(document,"x"));
-        DOM_appendChild(mn,DOM_createTextNode(document,"2"));
-        DOM_appendChild(mo,DOM_createTextNode(document,"+"));
-        DOM_appendChild(mi1,DOM_createTextNode(document,"a"));
-        DOM_appendChild(mi2,DOM_createTextNode(document,"b"));
-        DOM_appendChild(mrow1,mi1);
-        DOM_appendChild(mrow2,mi2);
-        DOM_appendChild(mfrac,mrow1);
-        DOM_appendChild(mfrac,mrow2);
-        DOM_appendChild(msup,mi);
-        DOM_appendChild(msup,mn);
-        DOM_appendChild(mrow,msup);
-        DOM_appendChild(mrow,mo);
-        DOM_appendChild(mrow,mfrac);
-        DOM_appendChild(math,mrow);
-
-        Clipboard_pasteNodes([math]);
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Figures.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Figures.js b/experiments/editorFramework/src/Layer0_Javascript/Figures.js
deleted file mode 100644
index dcda1fc..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Figures.js
+++ /dev/null
@@ -1,125 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Figures_insertFigure;
-var Figures_getSelectedFigureId;
-var Figures_getProperties;
-var Figures_setProperties;
-var Figures_getGeometry;
-
-(function() {
-
-    // public
-    Figures_insertFigure = function(filename,width,numbered,caption)
-    {
-        UndoManager_newGroup("Insert figure");
-
-        var figure = DOM_createElement(document,"FIGURE");
-        var img = DOM_createElement(document,"IMG");
-        DOM_setAttribute(img,"src",encodeURI(filename));
-        DOM_setStyleProperties(img,{"width": width});
-        DOM_appendChild(figure,img);
-
-        if ((caption != null) && (caption != "")) {
-            var figcaption = DOM_createElement(document,"FIGCAPTION");
-            DOM_appendChild(figcaption,DOM_createTextNode(document,caption));
-            DOM_appendChild(figure,figcaption);
-        }
-
-        Clipboard_pasteNodes([figure]);
-
-        // Now that the figure has been inserted into the DOM tree, the outline code will
-        // have noticed it and added an id attribute, as well as a caption giving the
-        // table number.
-        Outline_setNumbered(figure.getAttribute("id"),numbered);
-
-        // Place the cursor directly after the figure
-        var offset = DOM_nodeOffset(figure);
-        var pos = new Position(figure.parentNode,offset);
-        pos = Position_closestMatchForwards(pos,Position_okForMovement);
-        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-
-        PostponedActions_add(UndoManager_newGroup);
-    }
-
-    Figures_getSelectedFigureId = function()
-    {
-        var element = Cursor_getAdjacentNodeWithType(HTML_FIGURE);
-        return element ? element.getAttribute("id") : null;
-    }
-
-    // public
-    Figures_getProperties = function(itemId)
-    {
-        var figure = document.getElementById(itemId);
-        if (figure == null)
-            return null;
-        var rect = figure.getBoundingClientRect();
-        var result = { width: null, src: null };
-
-        var img = firstDescendantOfType(figure,HTML_IMG);
-        if (img != null) {
-            result.src = decodeURI(img.getAttribute("src"));
-            result.width = img.style.width;
-
-            if ((result.width == null) || (result.width == ""))
-                result.width = DOM_getAttribute(img,"width");
-        }
-        return result;
-    }
-
-    // public
-    Figures_setProperties = function(itemId,width,src)
-    {
-        var figure = document.getElementById(itemId);
-        if (figure == null)
-            return null;
-        var img = firstDescendantOfType(figure,HTML_IMG);
-        if (img != null) {
-            if (src == null)
-                DOM_removeAttribute(img,"src");
-            else
-                DOM_setAttribute(img,"src",encodeURI(src));
-
-            DOM_setStyleProperties(img,{"width": width});
-            if (img.getAttribute("style") == "")
-                DOM_removeAttribute(img,"style");
-            Selection_update();
-        }
-    }
-
-    // public
-    Figures_getGeometry = function(itemId)
-    {
-        var figure = document.getElementById(itemId);
-        if ((figure == null) || (figure.parentNode == null))
-            return null;
-        var img = firstDescendantOfType(figure,HTML_IMG);
-        if (img == null)
-            return null;
-
-        var figcaption = firstChildOfType(figure,HTML_FIGCAPTION);
-
-        var result = new Object();
-        result.contentRect = xywhAbsElementRect(img);
-        result.fullRect = xywhAbsElementRect(figure);
-        result.parentRect = xywhAbsElementRect(figure.parentNode);
-        result.hasCaption = (figcaption != null);
-        return result;
-    }
-
-})();


[20/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Selection.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Selection.js b/experiments/editorFramework/src/Javascript_Layer_0/Selection.js
new file mode 100644
index 0000000..c4f8efb
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Selection.js
@@ -0,0 +1,1430 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+// FIXME: cursor does not display correctly if it is after a space at the end of the line
+
+var Selection_isMarked;
+var Selection_get;
+var Selection_set;
+var Selection_clear;
+
+var Selection_update;
+var Selection_selectAll;
+var Selection_selectParagraph;
+var Selection_selectWordAtCursor;
+var Selection_dragSelectionBegin;
+var Selection_dragSelectionUpdate;
+var Selection_moveStartLeft;
+var Selection_moveStartRight;
+var Selection_moveEndLeft;
+var Selection_moveEndRight;
+var Selection_setSelectionStartAtCoords;
+var Selection_setSelectionEndAtCoords;
+var Selection_setTableSelectionEdgeAtCoords;
+var Selection_setEmptySelectionAt;
+var Selection_deleteRangeContents;
+var Selection_deleteContents;
+var Selection_clearSelection;
+var Selection_preserveWhileExecuting;
+var Selection_posAtStartOfWord;
+var Selection_posAtEndOfWord;
+var Selection_preferElementPositions;
+var Selection_print;
+
+(function() {
+
+    var HANDLE_NONE = 0;
+    var HANDLE_START = 1;
+    var HANDLE_END = 2;
+
+    var activeHandle = HANDLE_NONE;
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    //                                                                                            //
+    //                                 Selection getter and setter                                //
+    //                                                                                            //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+
+    var Selection_setInternal;
+
+    (function() {
+
+        var selection = new Object();
+
+        Selection_isMarked = function()
+        {
+            if (selection.value == null)
+                return null;
+            else
+                return selection.value.isMarked;
+        }
+
+        // public
+        Selection_get = function()
+        {
+            if (selection.value == null)
+                return null;
+            else
+                return new Range(selection.value.startNode,selection.value.startOffset,
+                                 selection.value.endNode,selection.value.endOffset);
+        }
+
+        // public
+        Selection_setInternal =
+            function(newStartNode,newStartOffset,newEndNode,newEndOffset,isMarked)
+        {
+            var range = new Range(newStartNode,newStartOffset,newEndNode,newEndOffset);
+            if (!Range_isForwards(range))
+                range = new Range(newEndNode,newEndOffset,newStartNode,newStartOffset);
+            range = boundaryCompliantRange(range);
+
+            UndoManager_setProperty(selection,"value",
+                                    { startNode: range.start.node,
+                                      startOffset: range.start.offset,
+                                      endNode: range.end.node,
+                                      endOffset: range.end.offset,
+                                      isMarked: isMarked });
+        }
+
+        Selection_set = function(newStartNode,newStartOffset,newEndNode,newEndOffset,
+                                 keepActiveHandle,isMarked)
+        {
+            Selection_setInternal(newStartNode,newStartOffset,newEndNode,newEndOffset,isMarked);
+            Selection_update();
+            if (!keepActiveHandle)
+                activeHandle = HANDLE_NONE;
+        }
+
+        // public
+        Selection_clear = function()
+        {
+            UndoManager_setProperty(selection,"value",null);
+            Selection_update();
+        }
+    })();
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    //                                                                                            //
+    //                                  Other selection functions                                 //
+    //                                                                                            //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+
+    var selectionDivs = new Array();
+    var selectionHighlights = new Array();
+    var tableSelection = null;
+
+    // private
+    updateTableSelection = function(selRange)
+    {
+        tableSelection = Tables_regionFromRange(selRange);
+        if (tableSelection == null)
+            return false;
+
+        Range_trackWhileExecuting(selRange,function() {
+
+            removeSelectionHighlights(getRangeData(null));
+
+            var sel = tableSelection;
+
+            var topLeftTD = Table_get(sel.structure,sel.top,sel.left);
+            var bottomRightTD = Table_get(sel.structure,sel.bottom,sel.right);
+
+            var topLeftRect = topLeftTD.element.getBoundingClientRect();
+            var bottomRightRect = bottomRightTD.element.getBoundingClientRect();
+
+            var left = topLeftRect.left;
+            var top = topLeftRect.top;
+
+            var bottom = bottomRightRect.bottom;
+            var right = bottomRightRect.right;
+
+            var x = left;
+            var y = top;
+            var width = right - left;
+            var height = bottom - top;
+
+            x += window.scrollX;
+            y += window.scrollY;
+
+            var div = makeSelectionDiv();
+            DOM_setAttribute(div,"class",Keys.SELECTION_HIGHLIGHT);
+            DOM_setStyleProperties(div,{ "position": "absolute",
+                                         "left": x+"px",
+                                         "top": y+"px",
+                                         "width": width+"px",
+                                         "height": height+"px",
+                                         "background-color": "rgb(201,221,238)",
+                                         "z-index": -1 });
+
+            setTableEdges(x,y,width,height);
+            setEditorHandles({ type: "table", x: x, y: y, width: width, height: height });
+        });
+
+        Selection_setInternal(selRange.start.node,selRange.start.offset,
+                              selRange.end.node,selRange.end.offset);
+
+        return true;
+    }
+
+    function makeSelectionDiv()
+    {
+        var div = DOM_createElement(document,"DIV");
+        DOM_appendChild(document.body,div);
+        selectionDivs.push(div);
+        return div;
+    }
+
+    function setTableEdges(x,y,width,height)
+    {
+        var left = makeSelectionDiv();
+        var right = makeSelectionDiv();
+        var top = makeSelectionDiv();
+        var bottom = makeSelectionDiv();
+
+        var thick = 2;
+        width++;
+        height++;
+        setBoxCoords(left,x-thick,y-thick,thick,height+2*thick);
+        setBoxCoords(right,x+width,y-thick,thick,height+2*thick);
+        setBoxCoords(top,x-thick,y-thick,width+2*thick,thick);
+        setBoxCoords(bottom,x-thick,y+height,width+2*thick,thick);
+
+        function setBoxCoords(box,x,y,width,height)
+        {
+            DOM_setStyleProperties(box,{ "position": "absolute",
+                                         "left": x+"px",
+                                         "top": y+"px",
+                                         "width": width+"px",
+                                         "height": height+"px",
+                                         "background-color": "blue",
+                                         "z-index": 1 });
+        }
+    }
+
+    var editorHandles = { type: "none" };
+    function setEditorHandles(info)
+    {
+        var oldEditorHandles = editorHandles;
+        editorHandles = info;
+        UndoManager_addAction(function() {
+            setEditorHandles(oldEditorHandles);
+        });
+        if (info.type == "cursor") {
+            Editor_setCursor(info.left,info.top,info.width,info.height);
+        }
+        else if (info.type == "selection") {
+            if (!Selection_isMarked()) {
+                Editor_setSelectionHandles(info.x1,info.y1,
+                                           info.height1,info.x2,info.y2,info.height2);
+            }
+            Editor_setSelectionBounds(info.boundsLeft,info.boundsTop,
+                                      info.boundsRight,info.boundsBottom);
+        }
+        else if (info.type == "none") {
+            Editor_clearSelectionHandlesAndCursor();
+        }
+        else if (info.type == "table") {
+            Editor_setTableSelection(info.x,info.y,info.width,info.height);
+        }
+        else {
+            throw new Error("setEditorHandles: unknown type "+type);
+        }
+    }
+
+    function getPrevHighlightText(node)
+    {
+        if ((node.previousSibling != null) &&
+            isSelectionHighlight(node.previousSibling) &&
+            (node.previousSibling.lastChild != null) &&
+            (node.previousSibling.lastChild.nodeType == Node.TEXT_NODE))
+            return node.previousSibling.lastChild;
+        else
+            return null;
+    }
+
+    function getNextHighlightText(node)
+    {
+        if ((node.nextSibling != null) &&
+            isSelectionHighlight(node.nextSibling) &&
+            (node.nextSibling.firstChild != null) &&
+            (node.nextSibling.firstChild.nodeType == Node.TEXT_NODE))
+            return node.nextSibling.firstChild;
+        else
+            return null;
+    }
+
+    function getTextNodeBefore(node)
+    {
+        var prev = node.previousSibling;
+        if ((prev != null) && (prev.nodeType == Node.TEXT_NODE)) {
+            return prev;
+        }
+        else {
+            var text = DOM_createTextNode(document,"");
+            DOM_insertBefore(node.parentNode,text,node);
+            return text;
+        }
+    }
+
+    function getTextNodeAfter(node)
+    {
+        var next = node.nextSibling;
+        if ((next != null) && (next.nodeType == Node.TEXT_NODE)) {
+            return next;
+        }
+        else {
+            var text = DOM_createTextNode(document,"");
+            DOM_insertBefore(node.parentNode,text,node.nextSibling);
+            return text;
+        }
+    }
+
+    function setSelectionHighlights(highlights)
+    {
+        UndoManager_addAction(setSelectionHighlights,selectionHighlights);
+        selectionHighlights = highlights;
+    }
+
+    function createSelectionHighlights(data)
+    {
+        var newHighlights = arrayCopy(selectionHighlights);
+
+        var outermost = data.outermost;
+        for (var i = 0; i < outermost.length; i++) {
+            recurse(outermost[i]);
+        }
+
+        setSelectionHighlights(newHighlights);
+
+        function recurse(node)
+        {
+            if (isSpecialBlockNode(node)) {
+                if (!isSelectionHighlight(node.parentNode)) {
+                    var wrapped = DOM_wrapNode(node,"DIV");
+                    DOM_setAttribute(wrapped,"class",Keys.SELECTION_CLASS);
+                    newHighlights.push(wrapped);
+                }
+            }
+            else if (isNoteNode(node)) {
+                if (!isSelectionHighlight(node.parentNode)) {
+                    var wrapped = DOM_wrapNode(node,"SPAN");
+                    DOM_setAttribute(wrapped,"class",Keys.SELECTION_CLASS);
+                    newHighlights.push(wrapped);
+                }
+            }
+            else if (node.nodeType == Node.TEXT_NODE) {
+                createTextHighlight(node,data,newHighlights);
+            }
+            else {
+                var next;
+                for (var child = node.firstChild; child != null; child = next) {
+                    next = child.nextSibling;
+                    recurse(child);
+                }
+            }
+        }
+    }
+
+    function createTextHighlight(node,data,newHighlights)
+    {
+        var selRange = data.range;
+        if (isSelectionHighlight(node.parentNode)) {
+
+            if ((node == selRange.end.node) && (node.nodeValue.length > selRange.end.offset)) {
+                var destTextNode = getTextNodeAfter(node.parentNode);
+                DOM_moveCharacters(node,
+                                   selRange.end.offset,
+                                   node.nodeValue.length,
+                                   destTextNode,0,
+                                   true,false);
+            }
+            if ((node == selRange.start.node) && (selRange.start.offset > 0)) {
+                var destTextNode = getTextNodeBefore(node.parentNode);
+                DOM_moveCharacters(node,
+                                   0,
+                                   selRange.start.offset,
+                                   destTextNode,destTextNode.nodeValue.length,
+                                   false,true);
+            }
+
+            return;
+        }
+
+        var anext;
+        for (var a = node; a != null; a = anext) {
+            anext = a.parentNode;
+            if (isSelectionHighlight(a))
+                DOM_removeNodeButKeepChildren(a);
+        }
+
+        if (node == selRange.end.node) {
+            if (isWhitespaceString(node.nodeValue.substring(0,selRange.end.offset)))
+                return;
+            Formatting_splitTextAfter(selRange.end,
+                                      function() { return true; });a
+        }
+
+
+        if (node == selRange.start.node) {
+            if (isWhitespaceString(node.nodeValue.substring(selRange.start.offset)))
+                return;
+            Formatting_splitTextBefore(selRange.start,
+                                       function() { return true; });
+        }
+
+        var prevText = getPrevHighlightText(node);
+        var nextText = getNextHighlightText(node);
+
+        if ((prevText != null) && containsSelection(data.nodeSet,prevText)) {
+            DOM_moveCharacters(node,0,node.nodeValue.length,
+                               prevText,prevText.nodeValue.length,true,false);
+            DOM_deleteNode(node);
+        }
+        else if ((nextText != null) && containsSelection(data.nodeSet,nextText)) {
+            DOM_moveCharacters(node,0,node.nodeValue.length,
+                               nextText,0,false,true);
+            DOM_deleteNode(node);
+        }
+        else if (!isWhitespaceTextNode(node)) {
+            // Call moveCharacters() with an empty range, to force any tracked positions
+            // that are at the end of prevText or the start of nextText to move into this
+            // node
+            if (prevText != null) {
+                DOM_moveCharacters(prevText,
+                                   prevText.nodeValue.length,prevText.nodeValue.length,
+                                   node,0);
+            }
+            if (nextText != null) {
+                DOM_moveCharacters(nextText,0,0,node,node.nodeValue.length);
+            }
+
+            var wrapped = DOM_wrapNode(node,"SPAN");
+            DOM_setAttribute(wrapped,"class",Keys.SELECTION_CLASS);
+            newHighlights.push(wrapped);
+        }
+    }
+
+    function getRangeData(selRange)
+    {
+        var nodeSet = new NodeSet();
+        var nodes;
+        var outermost;
+        if (selRange != null) {
+            outermost = Range_getOutermostNodes(selRange);
+            nodes = Range_getAllNodes(selRange);
+            for (var i = 0; i < nodes.length; i++)
+                nodeSet.add(nodes[i]);
+        }
+        else {
+            nodes = new Array();
+            outermost = new Array();
+        }
+        return { range: selRange, nodeSet: nodeSet, nodes: nodes, outermost: outermost };
+    }
+
+    function removeSelectionHighlights(data,force)
+    {
+        var selectedSet = data.nodeSet;
+
+        var remainingHighlights = new Array();
+        var checkMerge = new Array();
+        for (var i = 0; i < selectionHighlights.length; i++) {
+            var span = selectionHighlights[i];
+            if ((span.parentNode != null) && (force || !containsSelection(selectedSet,span))) {
+                if (span.firstChild != null)
+                    checkMerge.push(span.firstChild);
+                if (span.lastChild != null)
+                    checkMerge.push(span.lastChild);
+
+                DOM_removeNodeButKeepChildren(span);
+            }
+            else if (span.parentNode != null) {
+                remainingHighlights.push(span);
+            }
+        }
+        setSelectionHighlights(remainingHighlights);
+
+        for (var i = 0; i < checkMerge.length; i++) {
+            // if not already merged
+            if ((checkMerge[i] != null) && (checkMerge[i].parentNode != null)) {
+                Formatting_mergeWithNeighbours(checkMerge[i],{});
+            }
+        }
+    }
+
+    function containsSelection(selectedSet,node)
+    {
+        if (selectedSet.contains(node))
+            return true;
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            if (containsSelection(selectedSet,child))
+                return true;
+        }
+        return false;
+    }
+
+    Selection_update = function()
+    {
+        var selRange = Selection_get();
+        var selMarked = Selection_isMarked();
+
+        Range_trackWhileExecuting(selRange,function() {
+            // Remove table selection DIVs
+            for (var i = 0; i < selectionDivs.length; i++)
+                DOM_deleteNode(selectionDivs[i]);
+            selectionDivs = new Array();
+        });
+
+        if (selRange == null) {
+            DOM_ignoreMutationsWhileExecuting(function() {
+                removeSelectionHighlights(getRangeData(null));
+            });
+            return;
+        }
+
+        Range_assertValid(selRange,"Selection");
+
+        if (Range_isEmpty(selRange)) {
+            // We just have a cursor
+
+            Range_trackWhileExecuting(selRange,function() {
+                DOM_ignoreMutationsWhileExecuting(function() {
+                    removeSelectionHighlights(getRangeData(selRange));
+                });
+            });
+            // Selection may have changed as a result of removeSelectionHighlights()
+            Selection_setInternal(selRange.start.node,selRange.start.offset,
+                                  selRange.end.node,selRange.end.offset,
+                                  selMarked);
+            selRange = Selection_get(); // since setInternal can theoretically change it
+
+            // If we can't find the cursor rect for some reason, just don't update the position.
+            // This is better than using an incorrect position or throwing an exception.
+            var rect = Position_displayRectAtPos(selRange.end);
+            if (rect != null) {
+                var left = rect.left + window.scrollX;
+                var top = rect.top + window.scrollY;
+                var height = rect.height;
+                var width = rect.width ? rect.width : 2;
+                setEditorHandles({ type: "cursor",
+                                   left: left,
+                                   top: top,
+                                   width: width,
+                                   height: height});
+            }
+            return;
+        }
+
+        if (updateTableSelection(selRange))
+            return;
+
+        var rects = Range_getClientRects(selRange);
+
+        if ((rects != null) && (rects.length > 0)) {
+            var boundsLeft = null;
+            var boundsRight = null;
+            var boundsTop = null;
+            var boundsBottom = null
+
+            for (var i = 0; i < rects.length; i++) {
+                var left = rects[i].left + window.scrollX;
+                var top = rects[i].top + window.scrollY;
+                var width = rects[i].width;
+                var height = rects[i].height;
+                var right = left + width;
+                var bottom = top + height;
+
+                if (boundsLeft == null) {
+                    boundsLeft = left;
+                    boundsTop = top;
+                    boundsRight = right;
+                    boundsBottom = bottom;
+                }
+                else {
+                    if (boundsLeft > left)
+                        boundsLeft = left;
+                    if (boundsRight < right)
+                        boundsRight = right;
+                    if (boundsTop > top)
+                        boundsTop = top;
+                    if (boundsBottom < bottom)
+                        boundsBottom = bottom;
+                }
+            }
+
+            Range_trackWhileExecuting(selRange,function() {
+                DOM_ignoreMutationsWhileExecuting(function() {
+                    var data = getRangeData(selRange);
+                    createSelectionHighlights(data);
+                    removeSelectionHighlights(data);
+                });
+            });
+
+            // Selection may have changed as a result of create/removeSelectionHighlights()
+            Selection_setInternal(selRange.start.node,selRange.start.offset,
+                                  selRange.end.node,selRange.end.offset,
+                                  selMarked);
+
+            var firstRect = rects[0];
+            var lastRect = rects[rects.length-1];
+
+            var x1 = firstRect.left + window.scrollX;
+            var y1 = firstRect.top + window.scrollY;
+            var height1 = firstRect.height;
+            var x2 = lastRect.right + window.scrollX;
+            var y2 = lastRect.top + window.scrollY;
+            var height2 = lastRect.height;
+
+            setEditorHandles({ type: "selection",
+                               x1: x1,
+                               y1: y1,
+                               height1: height1,
+                               x2: x2,
+                               y2: y2,
+                               height2: height2,
+                               boundsLeft: boundsLeft,
+                               boundsTop: boundsTop,
+                               boundsRight: boundsRight,
+                               boundsBottom: boundsBottom });;
+
+        }
+        else {
+            setEditorHandles({ type: "none" });
+        }
+        return;
+
+        function getAbsoluteOffset(node)
+        {
+            var offsetLeft = 0;
+            var offsetTop = 0;
+            for (; node != null; node = node.parentNode) {
+                if (node.offsetLeft != null)
+                    offsetLeft += node.offsetLeft;
+                if (node.offsetTop != null)
+                    offsetTop += node.offsetTop;
+            }
+            return { offsetLeft: offsetLeft, offsetTop: offsetTop };
+        }
+    }
+
+    // public
+    Selection_selectAll = function()
+    {
+        Selection_set(document.body,0,document.body,document.body.childNodes.length);
+    }
+
+    // public
+    Selection_selectParagraph = function()
+    {
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+        var startNode = Position_closestActualNode(selRange.start);
+        while (!isParagraphNode(startNode) && !isContainerNode(startNode))
+            startNode = startNode.parentNode;
+
+        var endNode = Position_closestActualNode(selRange.end);
+        while (!isParagraphNode(endNode) && !isContainerNode(endNode))
+            endNode = endNode.parentNode;
+
+        var startPos = new Position(startNode,0);
+        var endPos = new Position(endNode,DOM_maxChildOffset(endNode));
+        startPos = Position_closestMatchForwards(startPos,Position_okForMovement);
+        endPos = Position_closestMatchBackwards(endPos,Position_okForMovement);
+
+        Selection_set(startPos.node,startPos.offset,endPos.node,endPos.offset);
+    }
+
+    // private
+    function getPunctuationCharsForRegex()
+    {
+        var escaped = "^$\\.*+?()[]{}|"; // From ECMAScript regexp spec (PatternCharacter)
+        var unescaped = "";
+        for (var i = 32; i <= 127; i++) {
+            var c = String.fromCharCode(i);
+            if ((escaped.indexOf(c) < 0) && !c.match(/[\w\d]/))
+                unescaped += c;
+        }
+        return unescaped + escaped.replace(/(.)/g,"\\$1");
+    }
+
+    // The following regular expressions are used by selectWordAtCursor(). We initialise them at
+    // startup to avoid repeatedly initialising them.
+    var punctuation = getPunctuationCharsForRegex();
+    var wsPunctuation = "\\s"+punctuation;
+
+    // Note: We use a blacklist of punctuation characters here instead of a whitelist of "word"
+    // characters, as the \w character class in javascript regular expressions only matches
+    // characters in english words. By using a blacklist, and assuming every other character is
+    // part of a word, we can select words containing non-english characters. This isn't a perfect
+    // solution, because there are many unicode characters that represent punctuation as well, but
+    // at least we handle the common ones here.
+
+    var reOtherEnd = new RegExp("["+wsPunctuation+"]*$");
+    var reOtherStart = new RegExp("^["+wsPunctuation+"]*");
+    var reWordOtherEnd = new RegExp("[^"+wsPunctuation+"]*["+wsPunctuation+"]*$");
+    var reWordOtherStart = new RegExp("^["+wsPunctuation+"]*[^"+wsPunctuation+"]*");
+
+    var reWordStart = new RegExp("^[^"+wsPunctuation+"]+");
+    var reWordEnd = new RegExp("[^"+wsPunctuation+"]+$");
+
+    Selection_posAtStartOfWord = function(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if (node.nodeType == Node.TEXT_NODE) {
+            var before = node.nodeValue.substring(0,offset);
+            var matches = before.match(reWordEnd);
+            if (matches) {
+                var wordStart = offset - matches[0].length;
+                return new Position(node,wordStart);
+            }
+        }
+
+        return pos;
+    }
+
+    Selection_posAtEndOfWord = function(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if (node.nodeType == Node.TEXT_NODE) {
+            var after = node.nodeValue.substring(offset);
+            var matches = after.match(reWordStart);
+            if (matches) {
+                var wordEnd = offset + matches[0].length;
+                return new Position(node,wordEnd);
+            }
+        }
+
+        return pos;
+    }
+
+    function rangeOfWordAtPos(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if (node.nodeType == Node.TEXT_NODE) {
+            var before = node.nodeValue.substring(0,offset);
+            var after = node.nodeValue.substring(offset);
+
+            var otherBefore = before.match(reOtherEnd)[0];
+            var otherAfter = after.match(reOtherStart)[0];
+
+            var wordOtherBefore = before.match(reWordOtherEnd)[0];
+            var wordOtherAfter = after.match(reWordOtherStart)[0];
+
+            var startOffset = offset;
+            var endOffset = offset;
+
+            var haveWordBefore = (wordOtherBefore.length != otherBefore.length);
+            var haveWordAfter = (wordOtherAfter.length != otherAfter.length);
+
+            if ((otherBefore.length == 0) && (otherAfter.length == 0)) {
+                startOffset = offset - wordOtherBefore.length;
+                endOffset = offset + wordOtherAfter.length;
+            }
+            else if (haveWordBefore && !haveWordAfter) {
+                startOffset = offset - wordOtherBefore.length;
+            }
+            else if (haveWordAfter && !haveWordBefore) {
+                endOffset = offset + wordOtherAfter.length;
+            }
+            else if (otherBefore.length <= otherAfter.length) {
+                startOffset = offset - wordOtherBefore.length;
+            }
+            else {
+                endOffset = offset + wordOtherAfter.length;
+            }
+
+            return new Range(node,startOffset,node,endOffset);
+        }
+        else if (node.nodeType == Node.ELEMENT_NODE) {
+            var nodeBefore = node.childNodes[offset-1];
+            var nodeAfter = node.childNodes[offset];
+
+            if ((nodeBefore != null) && !isWhitespaceTextNode(nodeBefore))
+                return new Range(node,offset-1,node,offset);
+            else if ((nodeAfter != null) && !isWhitespaceTextNode(nodeAfter))
+                return new Range(node,offset,node,offset+1);
+        }
+
+        return null;
+    }
+
+    // public
+    Selection_selectWordAtCursor = function()
+    {
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+
+        var pos = Position_closestMatchBackwards(selRange.end,Position_okForMovement);
+        var range = rangeOfWordAtPos(pos);
+        if (range != null) {
+            Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
+        }
+    }
+
+    // public
+    Selection_dragSelectionBegin = function(x,y,selectWord)
+    {
+        var pos = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
+
+        if (pos == null) {
+            Selection_clear();
+            return "error";
+        }
+
+        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+
+        if (selectWord)
+            Selection_selectWordAtCursor();
+
+        return "end";
+    }
+
+    var selectionHandleEnd = true;
+
+    function toStartOfWord(pos)
+    {
+        if (Input_isAtWordBoundary(pos,"backward"))
+            return pos;
+        var boundary = Input_toWordBoundary(pos,"backward");
+        return (boundary != null) ? boundary : pos;
+    }
+
+    function toEndOfWord(pos)
+    {
+        if (Input_isAtWordBoundary(pos,"forward"))
+            return pos;
+        var boundary = Input_toWordBoundary(pos,"forward");
+        return (boundary != null) ? boundary : pos;
+    }
+
+    // public
+    Selection_dragSelectionUpdate = function(x,y,selectWord)
+    {
+        y = Cursor_scrollDocumentForY(y);
+
+        var pos = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
+        var selRange = Selection_get();
+        if ((pos == null) || (selRange == null))
+            return "none";
+
+        var start = selRange.start;
+        var end = selRange.end;
+
+        if (selectionHandleEnd) {
+            if (Position_compare(pos,start) < 0) {
+                if (selectWord)
+                    pos = toStartOfWord(pos);
+                selectionHandleEnd = false;
+            }
+            else {
+                if (selectWord)
+                    pos = toEndOfWord(pos);
+            }
+            Selection_set(start.node,start.offset,pos.node,pos.offset);
+        }
+        else {
+            if (Position_compare(pos,end) > 0) {
+                if (selectWord)
+                    pos = toEndOfWord(pos);
+                selectionHandleEnd = true;
+            }
+            else {
+                if (selectWord)
+                    pos = toStartOfWord(pos);
+            }
+            Selection_set(pos.node,pos.offset,end.node,end.offset);
+        }
+
+        return selectionHandleEnd ? "end" : "start";
+    }
+
+    function moveBoundary(command)
+    {
+        var range = Selection_get();
+        if (range == null)
+            return;
+
+        var pos = null;
+        if (command == "start-left")
+            range.start = pos = Position_prevMatch(range.start,Position_okForMovement);
+        else if (command == "start-right")
+            range.start = pos = Position_nextMatch(range.start,Position_okForMovement);
+        else if (command == "end-left")
+            range.end = pos = Position_prevMatch(range.end,Position_okForMovement);
+        else if (command == "end-right")
+            range.end = pos = Position_nextMatch(range.end,Position_okForMovement);
+
+        if ((range.start != null) && (range.end != null)) {
+            var result;
+            range = Range_forwards(range);
+            Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
+            if (range.end == pos)
+                return "end";
+            else if (range.end == pos)
+                return "start";
+        }
+        return null;
+    }
+
+    // public
+    Selection_moveStartLeft = function()
+    {
+        return moveBoundary("start-left");
+    }
+
+    // public
+    Selection_moveStartRight = function()
+    {
+        return moveBoundary("start-right");
+    }
+
+    // public
+    Selection_moveEndLeft = function()
+    {
+        return moveBoundary("end-left");
+    }
+
+    // public
+    Selection_moveEndRight = function()
+    {
+        return moveBoundary("end-right");
+    }
+
+    // public
+    Selection_setSelectionStartAtCoords = function(x,y)
+    {
+        var position = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
+        if (position != null) {
+            position = Position_closestMatchBackwards(position,Position_okForMovement);
+            var selRange = Selection_get();
+            var newRange = new Range(position.node,position.offset,
+                                     selRange.end.node,selRange.end.offset);
+            if (Range_isForwards(newRange)) {
+                Selection_set(newRange.start.node,newRange.start.offset,
+                              newRange.end.node,newRange.end.offset);
+            }
+        }
+    }
+
+    // public
+    Selection_setSelectionEndAtCoords = function(x,y)
+    {
+        var position = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
+        if (position != null) {
+            position = Position_closestMatchBackwards(position,Position_okForMovement);
+            var selRange = Selection_get();
+            var newRange = new Range(selRange.start.node,selRange.start.offset,
+                                     position.node,position.offset);
+            if (Range_isForwards(newRange)) {
+                Selection_set(newRange.start.node,newRange.start.offset,
+                              newRange.end.node,newRange.end.offset);
+            }
+        }
+    }
+
+    // public
+    Selection_setTableSelectionEdgeAtCoords = function(edge,x,y)
+    {
+        if (tableSelection == null)
+            return;
+
+        var structure = tableSelection.structure;
+        var pointInfo = findCellInTable(structure,x,y);
+        if (pointInfo == null)
+            return;
+
+        if (edge == "topLeft") {
+            if (pointInfo.row <= tableSelection.bottom)
+                tableSelection.top = pointInfo.row;
+            if (pointInfo.col <= tableSelection.right)
+                tableSelection.left = pointInfo.col;
+        }
+        else if (edge == "bottomRight") {
+            if (pointInfo.row >= tableSelection.top)
+                tableSelection.bottom = pointInfo.row;
+            if (pointInfo.col >= tableSelection.left)
+                tableSelection.right = pointInfo.col;
+        }
+
+        // FIXME: handle the case where there is no cell at the specified row and column
+        var topLeftCell = Table_get(structure,tableSelection.top,tableSelection.left);
+        var bottomRightCell = Table_get(structure,tableSelection.bottom,tableSelection.right);
+
+        var topLeftNode = topLeftCell.element.parentNode;
+        var topLeftOffset = DOM_nodeOffset(topLeftCell.element);
+        var bottomRightNode = bottomRightCell.element.parentNode;
+        var bottomRightOffset = DOM_nodeOffset(bottomRightCell.element)+1;
+
+        Selection_set(topLeftNode,topLeftOffset,bottomRightNode,bottomRightOffset);
+
+        // FIXME: this could possibly be optimised
+        function findCellInTable(structure,x,y)
+        {
+            for (var r = 0; r < structure.numRows; r++) {
+                for (var c = 0; c < structure.numCols; c++) {
+                    var cell = Table_get(structure,r,c);
+                    if (cell != null) {
+                        var rect = cell.element.getBoundingClientRect();
+                        if ((x >= rect.left) && (x <= rect.right) &&
+                            (y >= rect.top) && (y <= rect.bottom))
+                            return cell;
+                    }
+                }
+            }
+            return null;
+        }
+    }
+
+    // public
+    Selection_setEmptySelectionAt = function(node,offset)
+    {
+        Selection_set(node,offset,node,offset);
+    }
+
+    // private
+    function deleteTextSelection(selRange,keepEmpty)
+    {
+        var nodes = Range_getOutermostNodes(selRange);
+        for (var i = 0; i < nodes.length; i++) {
+            var node = nodes[i];
+
+            var removeWholeNode = false;
+
+            if ((node == selRange.start.node) &&
+                (node == selRange.end.node)) {
+                var startOffset = selRange.start.offset;
+                var endOffset = selRange.end.offset;
+                if ((node.nodeType == Node.TEXT_NODE) &&
+                    ((startOffset > 0) || (endOffset < node.nodeValue.length))) {
+                    DOM_deleteCharacters(node,startOffset,endOffset);
+                }
+                else {
+                    removeWholeNode = true;
+                }
+            }
+            else if (node == selRange.start.node) {
+                var offset = selRange.start.offset;
+                if ((node.nodeType == Node.TEXT_NODE) && (offset > 0)) {
+                    DOM_deleteCharacters(node,offset);
+                }
+                else {
+                    removeWholeNode = true;
+                }
+            }
+            else if (node == selRange.end.node) {
+                var offset = selRange.end.offset;
+                if ((node.nodeType == Node.TEXT_NODE) && (offset < node.nodeValue.length)) {
+                    DOM_deleteCharacters(node,0,offset);
+                }
+                else {
+                    removeWholeNode = true;
+                }
+            }
+            else {
+                removeWholeNode = true;
+            }
+
+            if (removeWholeNode) {
+                switch (node._type) {
+                case HTML_TD:
+                case HTML_TH:
+                    DOM_deleteAllChildren(node);
+                    break;
+                default:
+                    DOM_deleteNode(node);
+                    break;
+                }
+            }
+        }
+
+        var detail = Range_detail(selRange);
+
+        var sameTextNode = (selRange.start.node == selRange.end.node) &&
+                           (selRange.start.node.nodeType == Node.TEXT_NODE);
+
+        if ((detail.startAncestor != null) && (detail.endAncestor != null) &&
+            (detail.startAncestor.nextSibling == detail.endAncestor) &&
+            !sameTextNode) {
+            prepareForMerge(detail);
+            DOM_mergeWithNextSibling(detail.startAncestor,
+                                          Formatting_MERGEABLE_BLOCK_AND_INLINE);
+            if (isParagraphNode(detail.startAncestor) &&
+                (detail.startAncestor._type != HTML_DIV))
+                removeParagraphDescendants(detail.startAncestor);
+        }
+
+        if (!keepEmpty) {
+            var startNode = selRange.start.node;
+            var endNode = selRange.end.node;
+            if (startNode.parentNode != null)
+                delEmpty(selRange,startNode);
+            if (endNode.parentNode != null)
+                delEmpty(selRange,endNode);
+        }
+
+        Cursor_updateBRAtEndOfParagraph(Range_singleNode(selRange));
+    }
+
+    function delEmpty(selRange,node)
+    {
+        while ((node != document.body) &&
+               (node.nodeType == Node.ELEMENT_NODE) &&
+               (node.firstChild == null)) {
+
+            if (isTableCell(node) || isTableCell(node.parentNode))
+                return;
+
+            if (!fixPositionOutside(selRange.start,node))
+                break;
+            if (!fixPositionOutside(selRange.end,node))
+                break;
+
+            var parent = node.parentNode;
+            Range_trackWhileExecuting(selRange,function() {
+                DOM_deleteNode(node);
+            });
+            node = parent;
+        }
+    }
+
+    function fixPositionOutside(pos,node)
+    {
+        if (pos.node == node) {
+            var before = new Position(node.parentNode,DOM_nodeOffset(node));
+            var after = new Position(node.parentNode,DOM_nodeOffset(node)+1);
+            before = Position_prevMatch(before,Position_okForMovement);
+            after = Position_nextMatch(after,Position_okForMovement);
+
+            if (before != null) {
+                pos.node = before.node;
+                pos.offset = before.offset;
+            }
+            else if (after != null) {
+                pos.node = after.node;
+                pos.offset = after.offset;
+            }
+            else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    Selection_deleteRangeContents = function(range,keepEmpty)
+    {
+        Range_trackWhileExecuting(range,function() {
+            DOM_ignoreMutationsWhileExecuting(function() {
+                removeSelectionHighlights(getRangeData(range),true);
+            });
+
+            var region = Tables_regionFromRange(range);
+            if (region != null)
+                Tables_deleteRegion(region);
+            else
+                deleteTextSelection(range,keepEmpty);
+        });
+
+        Selection_set(range.start.node,range.start.offset,range.start.node,range.start.offset);
+    }
+
+    Selection_deleteContents = function(keepEmpty)
+    {
+        var range = Selection_get();
+        if (range == null)
+            return;
+        Selection_deleteRangeContents(range,keepEmpty);
+    }
+
+    // private
+    function removeParagraphDescendants(parent)
+    {
+        var next;
+        for (var child = parent.firstChild; child != null; child = next) {
+            next = child.nextSibling;
+            removeParagraphDescendants(child);
+            if (isParagraphNode(child))
+                DOM_removeNodeButKeepChildren(child);
+        }
+    }
+
+    // private
+    function findFirstParagraph(node)
+    {
+        if (isParagraphNode(node))
+            return node;
+        if (node._type == HTML_LI) {
+            var nonWhitespaceInline = false;
+
+            for (var child = node.firstChild; child != null; child = child.nextSibling) {
+                if (isInlineNode(child) && !isWhitespaceTextNode(child))
+                    nonWhitespaceInline = true;
+
+                if (isParagraphNode(child)) {
+                    if (nonWhitespaceInline)
+                        return putPrecedingSiblingsInParagraph(node,child);
+                    return child;
+                }
+                else if (isListNode(child)) {
+                    if (nonWhitespaceInline)
+                        return putPrecedingSiblingsInParagraph(node,child);
+                    return findFirstParagraph(child);
+                }
+            }
+            if (nonWhitespaceInline)
+                return putPrecedingSiblingsInParagraph(node,null);
+        }
+        return null;
+
+        function putPrecedingSiblingsInParagraph(parent,node)
+        {
+            var p = DOM_createElement(document,"P");
+            while (parent.firstChild != node)
+                DOM_appendChild(p,parent.firstChild);
+            return p;
+        }
+    }
+
+    // private
+    function prepareForMerge(detail)
+    {
+        if (isParagraphNode(detail.startAncestor) && isInlineNode(detail.endAncestor)) {
+            var name = detail.startAncestor.nodeName; // check-ok
+            var newParagraph = DOM_createElement(document,name);
+            DOM_insertBefore(detail.endAncestor.parentNode,newParagraph,detail.endAncestor);
+            DOM_appendChild(newParagraph,detail.endAncestor);
+            detail.endAncestor = newParagraph;
+        }
+        else if (isInlineNode(detail.startAncestor) && isParagraphNode(detail.endAncestor)) {
+            var name = detail.endAncestor.nodeName; // check-ok
+            var newParagraph = DOM_createElement(document,name);
+            DOM_insertBefore(detail.startAncestor.parentNode,newParagraph,
+                             detail.startAncestor.nextSibling);
+            DOM_appendChild(newParagraph,detail.startAncestor);
+            detail.startAncestor = newParagraph;
+        }
+        else if (isParagraphNode(detail.startAncestor) &&
+                 isListNode(detail.endAncestor) &&
+                 (detail.endAncestor.firstChild._type == HTML_LI)) {
+            var list = detail.endAncestor;
+            var li = detail.endAncestor.firstChild;
+
+            var paragraph = findFirstParagraph(li);
+            if (paragraph != null) {
+                DOM_insertBefore(list.parentNode,paragraph,list);
+                var name = detail.startAncestor.nodeName; // check-ok
+                DOM_replaceElement(paragraph,name);
+            }
+            if (!nodeHasContent(li))
+                DOM_deleteNode(li);
+            if (firstChildElement(list) == null)
+                DOM_deleteNode(list);
+        }
+        else if (isParagraphNode(detail.endAncestor) &&
+                 isListNode(detail.startAncestor) &&
+                 (detail.startAncestor.lastChild._type == HTML_LI)) {
+            var list = detail.startAncestor;
+            var li = detail.startAncestor.lastChild;
+            var p = detail.endAncestor;
+            var oldLastChild = li.lastChild;
+            while (p.firstChild != null)
+                DOM_insertBefore(li,p.firstChild,null);
+            DOM_deleteNode(p);
+            if (oldLastChild != null) {
+                DOM_mergeWithNextSibling(oldLastChild,
+                                              Formatting_MERGEABLE_BLOCK_AND_INLINE);
+            }
+        }
+
+        if ((detail.startAncestor.lastChild != null) && (detail.endAncestor.firstChild != null)) {
+            var childDetail = new Object();
+            childDetail.startAncestor = detail.startAncestor.lastChild;
+            childDetail.endAncestor = detail.endAncestor.firstChild;
+            prepareForMerge(childDetail);
+        }
+    }
+
+    // public
+    Selection_clearSelection = function()
+    {
+        Selection_clear();
+    }
+
+    // public
+    Selection_preserveWhileExecuting = function(fun)
+    {
+        var range = Selection_get();
+
+        // Since the selection may have changed as a result of changes to the document, we
+        // have to call clear() or set() so that undo history is saved
+        if (range == null) {
+            result = fun();
+            Selection_clear();
+        }
+        else {
+            result = Range_trackWhileExecuting(range,fun);
+            Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
+        }
+        return result;
+    }
+
+    Selection_preferElementPositions = function()
+    {
+        var range = Selection_get();
+        if (range == null)
+            return;
+        range.start = Position_preferElementPosition(range.start);
+        range.end = Position_preferElementPosition(range.end);
+        Selection_set(range.start.node,range.start.offset,
+                      range.end.node,range.end.offset);
+    }
+
+    function getBoundaryContainer(node,topAncestor)
+    {
+        var container = document.body;
+        for (; node != topAncestor.parentNode; node = node.parentNode) {
+            switch (node._type) {
+            case HTML_FIGURE:
+            case HTML_TABLE:
+                container = node;
+                break;
+            }
+        }
+        return container;
+    }
+
+    function boundaryCompliantRange(range)
+    {
+        if (range == null)
+            return null;
+
+        var detail = Range_detail(range);
+        var start = range.start;
+        var end = range.end;
+        var startNode = Position_closestActualNode(start);
+        var endNode = Position_closestActualNode(end);
+        var startContainer = getBoundaryContainer(startNode.parentNode,detail.commonAncestor);
+        var endContainer = getBoundaryContainer(endNode.parentNode,detail.commonAncestor);
+
+        if (startContainer != endContainer) {
+
+            var doStart = false;
+            var doEnd = false;
+
+            if (nodeHasAncestor(startContainer,endContainer)) {
+                doStart = true;
+            }
+            else if (nodeHasAncestor(endContainer,startContainer)) {
+                doEnd = true;
+            }
+            else {
+                doStart = true;
+                doEnd = true;
+            }
+
+            if (doStart && (startContainer != document.body))
+                start = new Position(startContainer.parentNode,DOM_nodeOffset(startContainer));
+            if (doEnd && (endContainer != document.body))
+                end = new Position(endContainer.parentNode,DOM_nodeOffset(endContainer)+1);
+        }
+        return new Range(start.node,start.offset,end.node,end.offset);
+
+        function nodeHasAncestor(node,ancestor)
+        {
+            for (; node != null; node = node.parentNode) {
+                if (node == ancestor)
+                    return true;
+            }
+            return false;
+        }
+    }
+
+    Selection_print = function()
+    {
+        debug("");
+        debug("");
+        debug("");
+        debug("================================================================================");
+
+        var sel = Selection_get();
+        if (sel == null) {
+            debug("No selection");
+            return;
+        }
+
+        printSelectionElement(document.body,"");
+
+        function printSelectionElement(node,indent)
+        {
+            var className = DOM_getAttribute(node,"class");
+            if (className != null)
+                debug(indent+node.nodeName+" ("+className+")");
+            else
+                debug(indent+node.nodeName);
+
+            var child = node.firstChild;
+            var offset = 0;
+            while (true) {
+
+                var isStart = ((sel.start.node == node) && (sel.start.offset == offset));
+                var isEnd = ((sel.end.node == node) && (sel.end.offset == offset));
+                if (isStart && isEnd)
+                    debug(indent+"    []");
+                else if (isStart)
+                    debug(indent+"    [");
+                else if (isEnd)
+                    debug(indent+"    ]");
+
+                if (child == null)
+                    break;
+
+                if (child.nodeType == Node.ELEMENT_NODE)
+                    printSelectionElement(child,indent+"    ");
+                else
+                    printSelectionText(child,indent+"    ");
+
+                child = child.nextSibling;
+                offset++;
+            }
+        }
+
+        function printSelectionText(node,indent)
+        {
+            var value = node.nodeValue;
+
+            if (sel.end.node == node) {
+                var afterSelection = value.substring(sel.end.offset);
+                value = value.substring(0,sel.end.offset) + "]" + afterSelection;
+            }
+
+            if (sel.start.node == node) {
+                var beforeSelection = value.substring(0,sel.start.offset);
+                value = beforeSelection + "[" + value.substring(sel.start.offset);
+            }
+
+            debug(indent+JSON.stringify(value));
+        }
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/StringBuilder.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/StringBuilder.js b/experiments/editorFramework/src/Javascript_Layer_0/StringBuilder.js
new file mode 100644
index 0000000..9332b79
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/StringBuilder.js
@@ -0,0 +1,21 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+function StringBuilder()
+{
+    this.str = "";
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Styles.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Styles.js b/experiments/editorFramework/src/Javascript_Layer_0/Styles.js
new file mode 100644
index 0000000..c09f41d
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Styles.js
@@ -0,0 +1,179 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Styles_getRule;
+var Styles_nextSelectorAfter;
+var Styles_getParagraphClass;
+var Styles_setParagraphClass;
+var Styles_headingNumbering;
+var Styles_getCSSText;
+var Styles_setCSSText;
+var Styles_getBuiltinCSSURL;
+var Styles_init;
+
+(function() {
+
+    var rules = new Object();
+    var paragraphClass = null;
+
+    Styles_getRule = function(selector)
+    {
+        return rules[selector];
+    }
+
+    Styles_nextSelectorAfter = function(element)
+    {
+        var selector = element.nodeName.toLowerCase();
+        var className = DOM_getAttribute(element,"class");
+        if (className != null)
+            selector = selector+"."+className;
+
+        var nextElementName = null;
+        var nextClassName = null;
+
+        var rule = Styles_getRule(selector);
+        if (rule != null) {
+            var nextSelector = rule["-uxwrite-next"];
+            if (nextSelector != null) {
+                try {
+                    nextSelector = JSON.parse(nextSelector);
+                    if (typeof(nextSelector) != "string")
+                        nextSelector = null;
+                }
+                catch (e) {
+                    nextSelector = null;
+                }
+            }
+            if (nextSelector != null) {
+                var dotIndex = nextSelector.indexOf(".");
+                if (dotIndex >= 0) {
+                    nextElementName = nextSelector.substring(0,dotIndex);
+                    nextClassName = nextSelector.substring(dotIndex+1);
+                }
+                else {
+                    nextElementName = nextSelector;
+                }
+            }
+        }
+
+        if ((nextElementName == null) ||
+            (ElementTypes[nextElementName] == null) ||
+            (!PARAGRAPH_ELEMENTS[ElementTypes[nextElementName]])) {
+            nextElementName = null;
+            nextClassName = null;
+        }
+
+        if (isHeadingNode(element)) {
+            nextElementName = "p";
+            nextClassName = Styles_getParagraphClass();
+        }
+
+        if (nextElementName == null)
+            return null;
+        else if (nextClassName == null)
+            return nextElementName;
+        else
+            return nextElementName+"."+nextClassName;
+    }
+
+    Styles_getParagraphClass = function()
+    {
+        return paragraphClass;
+    }
+
+    Styles_setParagraphClass = function(cls)
+    {
+        paragraphClass = cls;
+    }
+
+    Styles_headingNumbering = function()
+    {
+        return ((rules["h1::before"] != null) &&
+                (rules["h1::before"]["content"] != null));
+    }
+
+    Styles_getCSSText = function()
+    {
+        var head = DOM_documentHead(document);
+        var cssText = "";
+        for (var child = head.firstChild; child != null; child = child.nextSibling) {
+            if (child._type == HTML_STYLE) {
+                for (var t = child.firstChild; t != null; t = t.nextSibling) {
+                    if (t._type == HTML_TEXT)
+                        cssText += t.nodeValue;
+                }
+            }
+        }
+        return cssText;
+    }
+
+    Styles_setCSSText = function(cssText,cssRules)
+    {
+        UndoManager_newGroup("Update styles");
+        var head = DOM_documentHead(document);
+        var next;
+        for (var child = head.firstChild; child != null; child = next) {
+            next = child.nextSibling;
+            if (child._type == HTML_STYLE)
+                DOM_deleteNode(child);
+        }
+        var style = DOM_createElement(document,"STYLE");
+        DOM_appendChild(style,DOM_createTextNode(document,cssText));
+        DOM_appendChild(head,style);
+        rules = cssRules; // FIXME: undo support? (must coordinate with ObjC code)
+        Outline_scheduleUpdateStructure();
+        return {}; // Objective C caller expects JSON result
+    }
+
+    function addBuiltinStylesheet(cssURL)
+    {
+        var head = DOM_documentHead(document);
+        for (var child = head.firstChild; child != null; child = child.nextSibling) {
+            if ((child._type == HTML_LINK) &&
+                (child.getAttribute("rel") == "stylesheet") &&
+                (child.getAttribute("href") == cssURL)) {
+                // Link element was already added by HTMLInjectionProtocol
+                return;
+            }
+        }
+
+        // HTMLInjectionProtocol was unable to find <head> element and insert the stylesheet link,
+        // so add it ourselves
+        var link = DOM_createElement(document,"LINK");
+        DOM_setAttribute(link,"rel","stylesheet");
+        DOM_setAttribute(link,"href",cssURL);
+        DOM_insertBefore(head,link,head.firstChild);
+    }
+
+    var builtinCSSURL = null;
+
+    Styles_getBuiltinCSSURL = function()
+    {
+        return builtinCSSURL;
+    }
+
+    // public
+    Styles_init = function(cssURL)
+    {
+        if (cssURL != null)
+            builtinCSSURL = cssURL;
+
+        if (builtinCSSURL != null)
+            addBuiltinStylesheet(builtinCSSURL);
+    }
+
+})();


[28/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
included MOC compiler for Qt implementation

Changed the Layer namings, to avoid the PITA of having all layers start with Layer<foo>.
Added moc generated moc file to the Qt implementation (this is to avoid everybody needing to run moc)
Ready to all graphic in the Qt implementation.
The Web implementation has been verified on paper, but will not be implemented until Qt works.


Project: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/commit/9bf02bb2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/tree/9bf02bb2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/diff/9bf02bb2

Branch: refs/heads/master
Commit: 9bf02bb20c831351ac3b01524b408085f5c9b21e
Parents: 63cd96d
Author: jani <ja...@apache.org>
Authored: Mon Aug 17 10:45:43 2015 +0200
Committer: jani <ja...@apache.org>
Committed: Mon Aug 17 10:45:43 2015 +0200

----------------------------------------------------------------------
 .../src/API_Layer_2/EDJSInterface.h             |   349 +
 .../src/API_Layer_2/EDJSInterface.m             |  1759 +++
 .../src/API_Layer_2/Layer2_interface.h          |   480 +
 .../editorFramework/src/API_Layer_2/README      |     1 +
 .../src/Docformat_Layer_4/README                |     1 +
 .../editorFramework/src/Handling_Layer_3/README |     1 +
 .../3rdparty/showdown/license.txt               |    34 +
 .../3rdparty/showdown/showdown.js               |  1302 ++
 .../src/Javascript_Layer_0/AutoCorrect.js       |   285 +
 .../src/Javascript_Layer_0/ChangeTracking.js    |   127 +
 .../src/Javascript_Layer_0/Clipboard.js         |   757 ++
 .../src/Javascript_Layer_0/Cursor.js            |  1050 ++
 .../src/Javascript_Layer_0/DOM.js               |   966 ++
 .../src/Javascript_Layer_0/Editor.js            |   113 +
 .../src/Javascript_Layer_0/ElementTypes.js      |   344 +
 .../src/Javascript_Layer_0/Equations.js         |    55 +
 .../src/Javascript_Layer_0/Figures.js           |   125 +
 .../src/Javascript_Layer_0/Formatting.js        |  1281 ++
 .../src/Javascript_Layer_0/Hierarchy.js         |   284 +
 .../src/Javascript_Layer_0/Input.js             |   746 ++
 .../src/Javascript_Layer_0/Lists.js             |   553 +
 .../src/Javascript_Layer_0/Main.js              |   393 +
 .../src/Javascript_Layer_0/Metadata.js          |    32 +
 .../src/Javascript_Layer_0/NodeSet.js           |   201 +
 .../src/Javascript_Layer_0/Outline.js           |  1434 +++
 .../src/Javascript_Layer_0/Position.js          |  1164 ++
 .../src/Javascript_Layer_0/PostponedActions.js  |    55 +
 .../src/Javascript_Layer_0/Preview.js           |   139 +
 .../src/Javascript_Layer_0/README               |     1 +
 .../src/Javascript_Layer_0/Range.js             |   566 +
 .../src/Javascript_Layer_0/Scan.js              |   179 +
 .../src/Javascript_Layer_0/Selection.js         |  1430 ++
 .../src/Javascript_Layer_0/StringBuilder.js     |    21 +
 .../src/Javascript_Layer_0/Styles.js            |   179 +
 .../src/Javascript_Layer_0/Tables.js            |  1362 ++
 .../src/Javascript_Layer_0/Text.js              |   543 +
 .../src/Javascript_Layer_0/UndoManager.js       |   270 +
 .../src/Javascript_Layer_0/Viewport.js          |    80 +
 .../src/Javascript_Layer_0/check-dom-methods.sh |    15 +
 .../src/Javascript_Layer_0/dtdsource/dtd.js     |  5562 ++++++++
 .../dtdsource/gen_dtd_data.html                 |   247 +
 .../src/Javascript_Layer_0/dtdsource/html4.dtd  |  1078 ++
 .../src/Javascript_Layer_0/dtdsource/html4.xml  | 11464 +++++++++++++++++
 .../elementtypes/elements.txt                   |   113 +
 .../elementtypes/genelementtypes.pl             |    36 +
 .../src/Javascript_Layer_0/empty.html           |     1 +
 .../src/Javascript_Layer_0/first.js             |    45 +
 .../src/Javascript_Layer_0/traversal.js         |   184 +
 .../src/Javascript_Layer_0/types.js             |   280 +
 .../src/Javascript_Layer_0/util.js              |   365 +
 .../3rdparty/showdown/license.txt               |    34 -
 .../3rdparty/showdown/showdown.js               |  1302 --
 .../src/Layer0_Javascript/AutoCorrect.js        |   285 -
 .../src/Layer0_Javascript/ChangeTracking.js     |   127 -
 .../src/Layer0_Javascript/Clipboard.js          |   757 --
 .../src/Layer0_Javascript/Cursor.js             |  1050 --
 .../src/Layer0_Javascript/DOM.js                |   966 --
 .../src/Layer0_Javascript/Editor.js             |   113 -
 .../src/Layer0_Javascript/ElementTypes.js       |   344 -
 .../src/Layer0_Javascript/Equations.js          |    55 -
 .../src/Layer0_Javascript/Figures.js            |   125 -
 .../src/Layer0_Javascript/Formatting.js         |  1281 --
 .../src/Layer0_Javascript/Hierarchy.js          |   284 -
 .../src/Layer0_Javascript/Input.js              |   746 --
 .../src/Layer0_Javascript/Lists.js              |   553 -
 .../src/Layer0_Javascript/Main.js               |   393 -
 .../src/Layer0_Javascript/Metadata.js           |    32 -
 .../src/Layer0_Javascript/NodeSet.js            |   201 -
 .../src/Layer0_Javascript/Outline.js            |  1434 ---
 .../src/Layer0_Javascript/Position.js           |  1164 --
 .../src/Layer0_Javascript/PostponedActions.js   |    55 -
 .../src/Layer0_Javascript/Preview.js            |   139 -
 .../src/Layer0_Javascript/README                |     1 -
 .../src/Layer0_Javascript/Range.js              |   566 -
 .../src/Layer0_Javascript/Scan.js               |   179 -
 .../src/Layer0_Javascript/Selection.js          |  1430 --
 .../src/Layer0_Javascript/StringBuilder.js      |    21 -
 .../src/Layer0_Javascript/Styles.js             |   179 -
 .../src/Layer0_Javascript/Tables.js             |  1362 --
 .../src/Layer0_Javascript/Text.js               |   543 -
 .../src/Layer0_Javascript/UndoManager.js        |   270 -
 .../src/Layer0_Javascript/Viewport.js           |    80 -
 .../src/Layer0_Javascript/check-dom-methods.sh  |    15 -
 .../src/Layer0_Javascript/dtdsource/dtd.js      |  5562 --------
 .../dtdsource/gen_dtd_data.html                 |   247 -
 .../src/Layer0_Javascript/dtdsource/html4.dtd   |  1078 --
 .../src/Layer0_Javascript/dtdsource/html4.xml   | 11464 -----------------
 .../Layer0_Javascript/elementtypes/elements.txt |   113 -
 .../elementtypes/genelementtypes.pl             |    36 -
 .../src/Layer0_Javascript/empty.html            |     1 -
 .../src/Layer0_Javascript/first.js              |    45 -
 .../src/Layer0_Javascript/traversal.js          |   184 -
 .../src/Layer0_Javascript/types.js              |   280 -
 .../src/Layer0_Javascript/util.js               |   365 -
 .../src/Layer1_toolkit/Layer1_interface.hpp     |   480 -
 .../editorFramework/src/Layer1_toolkit/README   |     3 -
 .../src/Layer1_toolkit/qt/README                |     1 -
 .../src/Layer1_toolkit/qt/qt_toolkit.cpp        |    57 -
 .../src/Layer1_toolkit/qt/qt_toolkit.hpp        |    44 -
 .../src/Layer1_toolkit/qt/windows.hpp           |    48 -
 .../src/Layer1_toolkit/toolkit.hpp              |   123 -
 .../src/Layer1_toolkit/web/README               |     1 -
 .../src/Layer2_API/EDJSInterface.h              |   349 -
 .../src/Layer2_API/EDJSInterface.m              |  1759 ---
 .../src/Layer2_API/Layer2_interface.h           |   480 -
 .../editorFramework/src/Layer2_API/README       |     1 -
 .../editorFramework/src/Layer3_Handling/README  |     1 -
 .../editorFramework/src/Layer4_Docformat/README |     1 -
 .../src/Toolkit_Layer_1/Layer1_interface.hpp    |   480 +
 .../editorFramework/src/Toolkit_Layer_1/README  |     3 +
 .../src/Toolkit_Layer_1/qt/README               |     1 +
 .../src/Toolkit_Layer_1/qt/moc_windows.cpp      |    89 +
 .../src/Toolkit_Layer_1/qt/qt_toolkit.cpp       |    68 +
 .../src/Toolkit_Layer_1/qt/qt_toolkit.hpp       |    54 +
 .../src/Toolkit_Layer_1/qt/windows.cpp          |    24 +
 .../src/Toolkit_Layer_1/qt/windows.hpp          |    56 +
 .../src/Toolkit_Layer_1/toolkit.hpp             |   139 +
 .../src/Toolkit_Layer_1/web/README              |     1 +
 118 files changed, 38967 insertions(+), 38809 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/API_Layer_2/EDJSInterface.h
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/API_Layer_2/EDJSInterface.h b/experiments/editorFramework/src/API_Layer_2/EDJSInterface.h
new file mode 100644
index 0000000..bd6e0d5
--- /dev/null
+++ b/experiments/editorFramework/src/API_Layer_2/EDJSInterface.h
@@ -0,0 +1,349 @@
+//
+//  EDJSInterface.h
+//  Editor
+//
+//  Created by Peter Kelly on 22/11/11.
+//  Copyright (c) 2011-2014 UX Productivity Pty Ltd. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreGraphics/CoreGraphics.h>
+
+@class JSAutoCorrect;
+@class JSChangeTracking;
+@class JSClipboard;
+@class JSCursor;
+@class JSEquations;
+@class JSFigures;
+@class JSFormatting;
+@class JSInput;
+@class JSLists;
+@class JSMain;
+@class JSMetadata;
+@class JSOutline;
+@class JSPreview;
+@class JSScan;
+@class JSSelection;
+@class JSStyles;
+@class JSTables;
+@class JSUndoManager;
+@class JSViewport;
+@class EDScanParagraph;
+
+@interface JSError : NSError
+
+@property (copy, readonly) NSString *type;
+@property (copy, readonly) NSString *message;
+@property (copy, readonly) NSString *operation;
+@property (copy, readonly) NSString *html;
+
+@end
+
+@protocol JSInterfaceDelegate
+
+- (void)jsAddOutlineItem:(NSString *)itemId type:(NSString *)type title:(NSString *)title;
+- (void)jsUpdateOutlineItem:(NSString *)itemId title:(NSString *)title;
+- (void)jsRemoveOutlineItem:(NSString *)itemId;
+- (void)jsOutlineUpdated;
+- (void)jsSetCursorX:(int)x y:(int)y width:(int)width height:(int)height;
+- (void)jsSetSelectionHandlesX1:(int)x1 y1:(int)y1 height1:(int)height1
+                             x2:(int)x2 y2:(int)y2 height2:(int)height2;
+- (void)jsSetTableSelectionX:(int)x y:(int)y width:(int)width height:(int)height;
+- (void)jsSetSelectionBoundsLeft:(int)left top:(int)top right:(int)right bottom:(int)bottom;
+- (void)jsClearSelectionHandlesAndCursor;
+- (void)jsUpdateAutoCorrect;
+
+@end
+
+@protocol JSEvaluator
+
+- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
+
+@end
+
+@interface JSInterface : NSObject
+
+@property (weak) NSObject<JSEvaluator> *evaluator;
+@property (weak) NSObject<JSInterfaceDelegate> *delegate;
+@property (assign) BOOL jsInitialised;
+@property (strong) JSAutoCorrect *autoCorrect;
+@property (strong) JSChangeTracking *changeTracking;
+@property (strong) JSClipboard *clipboard;
+@property (strong) JSCursor *cursor;
+@property (strong) JSEquations *equations;
+@property (strong) JSFigures *figures;
+@property (strong) JSFormatting *formatting;
+@property (strong) JSInput *input;
+@property (strong) JSLists *lists;
+@property (strong) JSMain *main;
+@property (strong) JSMetadata *metadata;
+@property (strong) JSOutline *outline;
+@property (strong) JSPreview *preview;
+@property (strong) JSScan *scan;
+@property (strong) JSSelection *selection;
+@property (strong) JSStyles *styles;
+@property (strong) JSTables *tables;
+@property (strong) JSUndoManager *undoManager;
+@property (strong) JSViewport *viewport;
+@property (copy) NSString *currentOperation;
+@property (strong) JSError *error;
+@property (assign) BOOL documentModified;
+
+- (JSInterface *)initWithEvaluator:(NSObject<JSEvaluator> *)evaluator;
+- (BOOL)initJavaScriptWidth:(int)width textScale:(int)textScale cssURL:(NSString *)cssURL
+             clientRectsBug:(BOOL)clientRectsBug;
+- (void)printStatistics;
+
+@end
+
+@interface JSModule : NSObject
+
+@property (assign) JSInterface *js;
+
+- (JSModule *)initWithJS:(JSInterface *)js;
+
+@end
+
+// Functions implemented in AutoCorrect.js
+
+@interface JSAutoCorrect : JSModule
+
+- (void)correctPreceding:(int)numChars word:(NSString *)replacement confirmed:(BOOL)confirmed;
+- (NSDictionary *)getCorrection;
+- (NSDictionary *)getCorrectionCoords;
+- (void)acceptCorrection;
+- (void)replaceCorrection:(NSString *)replacement;
+
+@end
+
+// Functions implemented in ChangeTracking.js
+
+@interface JSChangeTracking : JSModule
+- (BOOL)showChanges;
+- (BOOL)trackChanges;
+- (void)setShowChanges:(BOOL)showChanges;
+- (void)setTrackChanges:(BOOL)trackChanges;
+@end
+
+// Functions implemented in Clipboard.js
+
+@interface JSClipboard : JSModule
+- (NSDictionary *)clipboardCut;
+- (NSDictionary *)clipboardCopy;
+- (void)pasteHTML:(NSString *)html;
+- (void)pasteText:(NSString *)text;
+@end
+
+// Functions implemented in Cursor.js
+
+@interface JSCursor : JSModule
+- (NSString *)positionCursorX:(int)x y:(int)y wordBoundary:(BOOL)wordBoundary;
+- (CGRect)getCursorPosition;
+- (void)moveLeft;
+- (void)moveRight;
+- (void)moveToStartOfDocument;
+- (void)moveToEndOfDocument;
+- (void)insertReference:(NSString *)itemId;
+- (void)insertLinkWithText:(NSString *)text URL:(NSString *)URL;
+- (void)insertCharacter:(unichar)character allowInvalidPos:(BOOL)allowInvalidPos;
+- (void)deleteCharacter;
+- (void)enterPressed;
+- (NSString *)getPrecedingWord;
+- (NSDictionary *)getLinkProperties;
+- (void)setLinkProperties:(NSDictionary *)properties;
+- (void)setReferenceTarget:(NSString *)itemId;
+- (void)insertFootnote:(NSString *)content;
+- (void)insertEndnote:(NSString *)content;
+@end
+
+// Functions implemented in Equations.js
+
+@interface JSEquations : JSModule
+- (void)insertEquation;
+@end
+
+// Functions implemented in Figures.js
+
+@interface JSFigures : JSModule
+- (void)insertFigure:(NSString *)filename width:(NSString *)width
+            numbered:(BOOL)numbered caption:(NSString *)caption;
+- (NSString *)getSelectedFigureId;
+- (NSDictionary *)getProperties:(NSString *)itemId;
+- (void)setProperties:(NSString *)itemId width:(NSString *)width src:(NSString *)src;
+- (NSDictionary *)getGeometry:(NSString *)itemId;
+@end
+
+// Functions implemented in Formatting.js
+
+@interface JSFormatting : JSModule
+- (NSDictionary *)getFormatting;
+- (void)applyFormattingChangesStyle:(NSString *)style properties:(NSDictionary *)properties;
+@end
+
+// Functions implemented in Input.js
+
+@interface JSInput : JSModule
+- (void)removePosition:(int)posId;
+
+// UITextInput methods
+- (NSString *)textInRangeStartId:(int)startId startAdjust:(int)startAdjust
+                           endId:(int)endId endAdjust:(int)endAdjust;
+- (void)replaceRangeStart:(int)startId end:(int)endId withText:(NSString *)text;
+- (NSDictionary *)selectedTextRange;
+- (void)setSelectedTextRangeStart:(int)startId end:(int)endId;
+- (NSDictionary *)markedTextRange;
+- (void)setMarkedText:(NSString *)text startOffset:(int)startOffset endOffset:(int)endOffset;
+- (void)unmarkText;
+- (BOOL)forwardSelectionAffinity;
+- (void)setForwardSelectionAffinity:(BOOL)forwardSelectionAffinity;
+- (int)positionFromPosition:(int)posId offset:(int)offset;
+- (int)positionFromPosition:(int)posId inDirection:(NSString *)direction offset:(int)offset;
+- (int)comparePosition:(int)positionId toPosition:(int)otherId;
+- (int)offsetFromPosition:(int)fromPosition toPosition:(int)toPosition;
+- (int)positionWithinRangeStart:(int)startId end:(int)endId farthestInDirection:(NSString *)direction;
+- (NSDictionary *)characterRangeByExtendingPosition:(int)positionId inDirection:(NSString *)direction;
+- (NSDictionary *)firstRectForRangeStart:(int)startId end:(int)endId;
+- (NSDictionary *)caretRectForPosition:(int)posId;
+- (int)closestPositionToPointX:(int)x y:(int)y;
+- (int)closestPositionToPointX:(int)x y:(int)y withinRangeStart:(int)startId end:(int)endId;
+- (NSDictionary *)characterRangeAtPointX:(int)x y:(int)y;
+- (int)positionWithinRangeStart:(int)startId end:(int)endId atCharacterOffset:(int)offset;
+- (int)characterOffsetOfPosition:(int)positionId withinRangeStart:(int)startId end:(int)endId;
+
+// UITextInputTokenizer methods
+- (BOOL)isPosition:(int)posId atBoundary:(NSString *)granularity inDirection:(NSString *)direction;
+- (BOOL)isPosition:(int)posId withinTextUnit:(NSString *)granularity inDirection:(NSString *)direction;
+- (int)positionFromPosition:(int)posId toBoundary:(NSString *)granularity inDirection:(NSString *)direction;
+- (NSDictionary *)rangeEnclosingPosition:(int)posId withGranularity:(NSString *)granularity inDirection:(NSString *)direction;
+@end
+
+// Functions implemented in Lists.js
+
+@interface JSLists : JSModule
+- (void)increaseIndent;
+- (void)decreaseIndent;
+- (void)clearList;
+- (void)setUnorderedList;
+- (void)setOrderedList;
+@end
+
+// Functions implemented in Main.js
+
+@interface JSMain : JSModule
+- (NSString *)getLanguage;
+- (void)setLanguage:(NSString *)language;
+- (NSString *)setGenerator:(NSString *)generator;
+- (BOOL)prepareForSave;
+- (NSString *)getHTML;
+- (BOOL)isEmptyDocument;
+@end
+
+// Functions implemented in Metadata.js
+
+@interface JSMetadata : JSModule
+- (NSDictionary *)getMetadata;
+- (void)setMetadata:(NSDictionary *)metadata;
+@end
+
+// Functions implemented in Outline.js
+
+@interface JSOutline : JSModule
+- (NSDictionary *)getOutline;
+- (void)moveSection:(NSString *)sectionId parentId:(NSString *)parentId nextId:(NSString *)nextId;
+- (void)deleteItem:(NSString *)itemId;
+- (void)goToItem:(NSString *)itemId;
+- (void)scheduleUpdateStructure;
+- (void)set:(NSString *)itemId numbered:(BOOL)numbered;
+- (void)set:(NSString *)itemId title:(NSString *)title;
+- (void)insertTableOfContents;
+- (void)insertListOfFigures;
+- (void)insertListOfTables;
+- (void)setPrintMode:(BOOL)printMode;
+- (NSDictionary *)examinePrintLayout:(int)pageHeight;
+- (BOOL)detectSectionNumbering;
+- (NSDictionary *)findUsedStyles;
+@end
+
+// Functions implemented in Preview.js
+
+@interface JSPreview : JSModule
+- (void)showForStyle:(NSString *)styleId uiName:(NSString *)uiName title:(NSString *)title;
+@end
+
+// Functions implemented in Scan.js
+
+@interface JSScan : JSModule
+- (void)reset;
+- (EDScanParagraph *)next;
+- (int)addMatchStart:(int)start end:(int)end;
+- (void)showMatch:(int)matchId;
+- (void)replaceMatch:(int)matchId with:(NSString *)text;
+- (void)removeMatch:(int)matchId;
+- (void)goToMatch:(int)matchId;
+@end
+
+// Functions implemented in Selection.js
+
+@interface JSSelection : JSModule
+- (void)update;
+- (void)selectAll;
+- (void)selectParagraph;
+- (void)selectWordAtCursor;
+- (NSString *)dragSelectionBeginX:(int)x y:(int)y selectWord:(BOOL)selectWord;
+- (NSString *)dragSelectionUpdateX:(int)x y:(int)y selectWord:(BOOL)selectWord;
+- (NSString *)moveStartLeft;
+- (NSString *)moveStartRight;
+- (NSString *)moveEndLeft;
+- (NSString *)moveEndRight;
+- (void)setSelectionStartAtCoordsX:(int)x y:(int)y;
+- (void)setSelectionEndAtCoordsX:(int)x y:(int)y;
+- (void)setTableSelectionEdge:(NSString *)edge atCoordsX:(int)x y:(int)y;
+- (void)print;
+@end
+
+// Functions implemented in Styles.js
+
+@interface JSStyles : JSModule
+- (NSString *)getCSSText;
+- (void)setCSSText:(NSString *)cssText rules:(NSDictionary *)rules;
+- (NSString *)paragraphClass;
+- (void)setParagraphClass:(NSString *)paragraphClass;
+@end
+
+// Functions implemented in Tables.js
+
+@interface JSTables : JSModule
+- (void)insertTableRows:(int)rows cols:(int)cols width:(NSString *)width numbered:(BOOL)numbered
+                caption:(NSString *)caption className:(NSString *)className;
+- (void)addAdjacentRow;
+- (void)addAdjacentColumn;
+- (void)removeAdjacentRow;
+- (void)removeAdjacentColumn;
+- (void)clearCells;
+- (void)mergeCells;
+- (void)splitSelection;
+- (NSString *)getSelectedTableId;
+- (NSDictionary *)getProperties:(NSString *)itemId;
+- (void)setProperties:(NSString *)itemId width:(NSString *)width;
+- (void)set:(NSString *)itemId colWidths:(NSArray *)colWidths;
+- (NSDictionary *)getGeometry:(NSString *)itemId;
+@end
+
+// Functions implemented in UndoManager.js
+
+@interface JSUndoManager : JSModule
+- (int)getLength;
+- (int)getIndex;
+- (void)setIndex:(int)index;
+- (void)undo;
+- (void)redo;
+- (void)newGroup:(NSString *)name;
+- (NSString *)groupType;
+@end
+
+// Functions implemented in Viewport.js
+
+@interface JSViewport : JSModule
+- (void)setViewportWidth:(int)width;
+- (void)setTextScale:(int)textScale;
+@end

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/API_Layer_2/EDJSInterface.m
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/API_Layer_2/EDJSInterface.m b/experiments/editorFramework/src/API_Layer_2/EDJSInterface.m
new file mode 100644
index 0000000..5e34546
--- /dev/null
+++ b/experiments/editorFramework/src/API_Layer_2/EDJSInterface.m
@@ -0,0 +1,1759 @@
+//
+//  EDJSInterface.m
+//  Editor
+//
+//  Created by Peter Kelly on 22/11/11.
+//  Copyright (c) 2011-2014 UX Productivity Pty Ltd. All rights reserved.
+//
+
+#import "EDJSInterface.h"
+#import "EDScan.h"
+#import "EDUtil.h"
+#import <FileClient/FCError.h>
+#import <FileClient/FCUtil.h>
+
+typedef enum {
+    AutoCorrect_correctPrecedingWord,
+    AutoCorrect_getCorrection,
+    AutoCorrect_getCorrectionCoords,
+    AutoCorrect_acceptCorrection,
+    AutoCorrect_replaceCorrection,
+    ChangeTracking_showChanges,
+    ChangeTracking_trackChanges,
+    ChangeTracking_setShowChanges,
+    ChangeTracking_setTrackChanges,
+    Clipboard_cut,
+    Clipboard_copy,
+    Clipboard_pasteHTML,
+    Clipboard_pasteText,
+    Cursor_positionCursor,
+    Cursor_getCursorPosition,
+    Cursor_moveLeft,
+    Cursor_moveRight,
+    Cursor_moveToStartOfDocument,
+    Cursor_moveToEndOfDocument,
+    Cursor_insertReference,
+    Cursor_insertLink,
+    Cursor_insertCharacter,
+    Cursor_deleteCharacter,
+    Cursor_enterPressed,
+    Cursor_getPrecedingWord,
+    Cursor_getLinkProperties,
+    Cursor_setLinkProperties,
+    Cursor_setReferenceTarget,
+    Cursor_insertFootnote,
+    Cursor_insertEndnote,
+    Editor_getBackMessages,
+    Equations_insertEquation,
+    Figures_insertFigure,
+    Figures_getSelectedFigureId,
+    Figures_getProperties,
+    Figures_setProperties,
+    Figures_getGeometry,
+    Formatting_getFormatting,
+    Formatting_applyFormattingChanges,
+    Input_removePosition,
+    Input_textInRange,
+    Input_replaceRange,
+    Input_selectedTextRange,
+    Input_setSelectedTextRange,
+    Input_markedTextRange,
+    Input_setMarkedText,
+    Input_unmarkText,
+    Input_forwardSelectionAffinity,
+    Input_setForwardSelectionAffinity,
+    Input_positionFromPositionOffset,
+    Input_positionFromPositionInDirectionOffset,
+    Input_comparePositionToPosition,
+    Input_offsetFromPositionToPosition,
+    Input_positionWithinRangeFarthestInDirection,
+    Input_characterRangeByExtendingPositionInDirection,
+    Input_firstRectForRange,
+    Input_caretRectForPosition,
+    Input_closestPositionToPoint,
+    Input_closestPositionToPointWithinRange,
+    Input_characterRangeAtPoint,
+    Input_positionWithinRangeAtCharacterOffset,
+    Input_characterOffsetOfPositionWithinRange,
+    Input_isPositionAtBoundaryGranularityInDirection,
+    Input_isPositionWithinTextUnitInDirection,
+    Input_positionFromPositionToBoundaryInDirection,
+    Input_rangeEnclosingPositionWithGranularityInDirection,
+    Lists_increaseIndent,
+    Lists_decreaseIndent,
+    Lists_clearList,
+    Lists_setUnorderedList,
+    Lists_setOrderedList,
+    Main_getLanguage,
+    Main_setLanguage,
+    Main_setGenerator,
+    Main_init,
+    Main_getErrorReportingInfo,
+    Main_execute,
+    Main_prepareForSave,
+    Main_getHTML,
+    Main_isEmptyDocument,
+    Metadata_getMetadata,
+    Metadata_setMetadata,
+    Outline_moveSection,
+    Outline_deleteItem,
+    Outline_goToItem,
+    Outline_scheduleUpdateStructure,
+    Outline_setNumbered,
+    Outline_setTitle,
+    Outline_getOutline,
+    Outline_insertTableOfContents,
+    Outline_insertListOfFigures,
+    Outline_insertListOfTables,
+    Outline_setPrintMode,
+    Outline_examinePrintLayout,
+    Outline_detectSectionNumbering,
+    Outline_findUsedStyles,
+    Preview_showForStyle,
+    Scan_reset,
+    Scan_next,
+    Scan_addMatch,
+    Scan_showMatch,
+    Scan_replaceMatch,
+    Scan_removeMatch,
+    Scan_goToMatch,
+    Selection_update,
+    Selection_selectAll,
+    Selection_selectParagraph,
+    Selection_selectWordAtCursor,
+    Selection_dragSelectionBegin,
+    Selection_dragSelectionUpdate,
+    Selection_moveStartLeft,
+    Selection_moveStartRight,
+    Selection_moveEndLeft,
+    Selection_moveEndRight,
+    Selection_setSelectionStartAtCoords,
+    Selection_setSelectionEndAtCoords,
+    Selection_setTableSelectionEdgeAtCoords,
+    Selection_print,
+    Styles_getCSSText,
+    Styles_setCSSText,
+    Styles_getParagraphClass,
+    Styles_setParagraphClass,
+    Tables_insertTable,
+    Tables_addAdjacentRow,
+    Tables_addAdjacentColumn,
+    Tables_removeAdjacentRow,
+    Tables_removeAdjacentColumn,
+    Tables_clearCells,
+    Tables_mergeCells,
+    Tables_splitSelection,
+    Tables_getSelectedTableId,
+    Tables_getProperties,
+    Tables_setProperties,
+    Tables_setColWidths,
+    Tables_getGeometry,
+    UndoManager_getLength,
+    UndoManager_getIndex,
+    UndoManager_setIndex,
+    UndoManager_undo,
+    UndoManager_redo,
+    UndoManager_newGroup,
+    UndoManager_groupType,
+    Viewport_setViewportWidth,
+    Viewport_setTextScale,
+    JSInterfaceFunctionCount,
+} JSInterfaceFunction;
+
+static BOOL functionModifiesDocument(JSInterfaceFunction fun)
+{
+    switch (fun)
+    {
+        case AutoCorrect_correctPrecedingWord:
+        case AutoCorrect_acceptCorrection:
+        case AutoCorrect_replaceCorrection:
+        case ChangeTracking_setShowChanges:
+        case ChangeTracking_setTrackChanges:
+        case Clipboard_cut:
+        case Clipboard_pasteHTML:
+        case Clipboard_pasteText:
+        case Cursor_insertReference:
+        case Cursor_insertLink:
+        case Cursor_insertCharacter:
+        case Cursor_deleteCharacter:
+        case Cursor_enterPressed:
+        case Cursor_setLinkProperties:
+        case Cursor_setReferenceTarget:
+        case Cursor_insertFootnote:
+        case Cursor_insertEndnote:
+        case Equations_insertEquation:
+        case Figures_insertFigure:
+        case Figures_setProperties:
+        case Formatting_applyFormattingChanges:
+        case Lists_increaseIndent:
+        case Lists_decreaseIndent:
+        case Lists_clearList:
+        case Lists_setUnorderedList:
+        case Lists_setOrderedList:
+        case Main_setLanguage:
+        case Main_prepareForSave:
+        case Metadata_setMetadata:
+        case Outline_moveSection:
+        case Outline_deleteItem:
+        case Outline_scheduleUpdateStructure:
+        case Outline_setNumbered:
+        case Outline_setTitle:
+        case Outline_insertTableOfContents:
+        case Outline_insertListOfFigures:
+        case Outline_insertListOfTables:
+        case Outline_setPrintMode:
+        case Outline_examinePrintLayout:
+        case Scan_replaceMatch:
+        case Styles_setCSSText:
+        case Tables_insertTable:
+        case Tables_addAdjacentRow:
+        case Tables_addAdjacentColumn:
+        case Tables_removeAdjacentRow:
+        case Tables_removeAdjacentColumn:
+        case Tables_clearCells:
+        case Tables_mergeCells:
+        case Tables_splitSelection:
+        case Tables_setProperties:
+        case Tables_setColWidths:
+        case UndoManager_undo:
+        case UndoManager_redo:
+            return true;
+        case AutoCorrect_getCorrection:
+        case AutoCorrect_getCorrectionCoords:
+        case ChangeTracking_showChanges:
+        case ChangeTracking_trackChanges:
+        case Clipboard_copy:
+        case Cursor_positionCursor:
+        case Cursor_getCursorPosition:
+        case Cursor_moveLeft:
+        case Cursor_moveRight:
+        case Cursor_moveToStartOfDocument:
+        case Cursor_moveToEndOfDocument:
+        case Cursor_getPrecedingWord:
+        case Cursor_getLinkProperties:
+        case Editor_getBackMessages:
+        case Figures_getSelectedFigureId:
+        case Figures_getProperties:
+        case Figures_getGeometry:
+        case Formatting_getFormatting:
+        case Input_removePosition:
+        case Input_textInRange:
+        case Input_replaceRange:
+        case Input_selectedTextRange:
+        case Input_setSelectedTextRange:
+        case Input_markedTextRange:
+        case Input_setMarkedText:
+        case Input_unmarkText:
+        case Input_forwardSelectionAffinity:
+        case Input_setForwardSelectionAffinity:
+        case Input_positionFromPositionOffset:
+        case Input_positionFromPositionInDirectionOffset:
+        case Input_comparePositionToPosition:
+        case Input_offsetFromPositionToPosition:
+        case Input_positionWithinRangeFarthestInDirection:
+        case Input_characterRangeByExtendingPositionInDirection:
+        case Input_firstRectForRange:
+        case Input_caretRectForPosition:
+        case Input_closestPositionToPoint:
+        case Input_closestPositionToPointWithinRange:
+        case Input_characterRangeAtPoint:
+        case Input_positionWithinRangeAtCharacterOffset:
+        case Input_characterOffsetOfPositionWithinRange:
+        case Input_isPositionAtBoundaryGranularityInDirection:
+        case Input_isPositionWithinTextUnitInDirection:
+        case Input_positionFromPositionToBoundaryInDirection:
+        case Input_rangeEnclosingPositionWithGranularityInDirection:
+        case Main_getLanguage:
+        case Main_setGenerator:
+        case Main_init:
+        case Main_getErrorReportingInfo:
+        case Main_execute:
+        case Main_getHTML:
+        case Main_isEmptyDocument:
+        case Metadata_getMetadata:
+        case Outline_getOutline:
+        case Outline_goToItem:
+        case Outline_detectSectionNumbering:
+        case Outline_findUsedStyles:
+        case Preview_showForStyle:
+        case Scan_reset:
+        case Scan_next:
+        case Scan_addMatch:
+        case Scan_showMatch:
+        case Scan_removeMatch:
+        case Scan_goToMatch:
+        case Selection_update:
+        case Selection_selectAll:
+        case Selection_selectParagraph:
+        case Selection_selectWordAtCursor:
+        case Selection_dragSelectionBegin:
+        case Selection_dragSelectionUpdate:
+        case Selection_moveStartLeft:
+        case Selection_moveStartRight:
+        case Selection_moveEndLeft:
+        case Selection_moveEndRight:
+        case Selection_setSelectionStartAtCoords:
+        case Selection_setSelectionEndAtCoords:
+        case Selection_setTableSelectionEdgeAtCoords:
+        case Selection_print:
+        case Styles_getCSSText:
+        case Styles_getParagraphClass:
+        case Styles_setParagraphClass:
+        case Tables_getSelectedTableId:
+        case Tables_getProperties:
+        case Tables_getGeometry:
+        case UndoManager_getLength:
+        case UndoManager_getIndex:
+        case UndoManager_setIndex:
+        case UndoManager_newGroup:
+        case UndoManager_groupType:
+        case Viewport_setViewportWidth:
+        case Viewport_setTextScale:
+        case JSInterfaceFunctionCount:
+            return false;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                             JSError                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSError
+
+- (JSError *)initWithType:(NSString *)type
+                  message:(NSString *)message
+                operation:(NSString *)operation
+                     html:(NSString *)html
+{
+    if (!(self = [super init]))
+        return nil;
+    _type = [type copy];
+    _message = [message copy];
+    _operation = [operation copy];
+    _html = [html copy];
+    return self;
+}
+
+- (NSString *)description
+{
+    NSMutableString *errorInfo = [NSMutableString stringWithCapacity: 0];
+    [errorInfo appendFormat: @"%@\n", _message];
+    [errorInfo appendFormat: @"Operation: %@\n", _operation];
+    [errorInfo appendFormat: @"\n"];
+    [errorInfo appendFormat: @"HTML:\n%@\n", _html];
+    return errorInfo;
+}
+
+- (NSString *)localizedDescription
+{
+    return [self description];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                           JSInterface                                          //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSInterface
+{
+    NSUInteger _numCalls[JSInterfaceFunctionCount];
+    NSTimeInterval _timeUsed[JSInterfaceFunctionCount];
+    NSTimeInterval _totalTimeUsed;
+}
+
+- (JSInterface *)initWithEvaluator:(NSObject<JSEvaluator> *)evaluator
+{
+    if (!(self = [super init]))
+        return nil;
+    _evaluator = evaluator;
+
+    _autoCorrect = [[JSAutoCorrect alloc] initWithJS: self];
+    _changeTracking = [[JSChangeTracking alloc] initWithJS: self];
+    _clipboard = [[JSClipboard alloc] initWithJS: self];
+    _cursor = [[JSCursor alloc] initWithJS: self];
+    _equations = [[JSEquations alloc] initWithJS: self];
+    _figures = [[JSFigures alloc] initWithJS: self];
+    _formatting = [[JSFormatting alloc] initWithJS: self];
+    _input = [[JSInput alloc] initWithJS: self];
+    _lists = [[JSLists alloc] initWithJS: self];
+    _main = [[JSMain alloc] initWithJS: self];
+    _metadata = [[JSMetadata alloc] initWithJS: self];
+    _outline = [[JSOutline alloc] initWithJS: self];
+    _preview = [[JSPreview alloc] initWithJS: self];
+    _scan = [[JSScan alloc] initWithJS: self];
+    _selection = [[JSSelection alloc] initWithJS: self];
+    _styles = [[JSStyles alloc] initWithJS: self];
+    _tables = [[JSTables alloc] initWithJS: self];
+    _undoManager = [[JSUndoManager alloc] initWithJS: self];
+    _viewport = [[JSViewport alloc] initWithJS: self];
+
+    return self;
+}
+
+- (void)dealloc
+{
+    _autoCorrect.js = nil;
+    _changeTracking.js = nil;
+    _clipboard.js = nil;
+    _cursor.js = nil;
+    _equations.js = nil;
+    _figures.js = nil;
+    _formatting.js = nil;
+    _input.js = nil;
+    _lists.js = nil;
+    _main.js = nil;
+    _metadata.js = nil;
+    _outline.js = nil;
+    _preview.js = nil;
+    _scan.js = nil;
+    _selection.js = nil;
+    _styles.js = nil;
+    _tables.js = nil;
+    _undoManager.js = nil;
+    _viewport.js = nil;
+}
+
+- (BOOL)initJavaScriptWidth:(int)width textScale:(int)textScale cssURL:(NSString *)cssURL
+             clientRectsBug:(BOOL)clientRectsBug
+{
+    // Special case javascript call to Main_init(). We don't use the normal mechanism here because
+    // at this point the JS interface has not been initialised, and the check for this in
+    // executeJavaScriptWithJSONResult would cause it to fail.
+    NSString *code = [NSString stringWithFormat: @"interface_functions[%d](%d,%d,\"%@\",%@)",
+                      Main_init, width, textScale, cssURL, clientRectsBug ? @"true" : @"false"];
+    NSString *result = [_evaluator stringByEvaluatingJavaScriptFromString: code];
+    [self jsCallCompleted];
+    if ([@"true" isEqualToString: result]) {
+        return YES;
+    }
+    else {
+        self.currentOperation = @"JavaScript initialisation";
+        [self reportErrorWithType: nil format: @"%@", result];
+        self.currentOperation = nil;
+        return NO;
+    }
+}
+
+- (void)jsCallCompleted
+{
+    // Process pending callbacks
+    NSString *getBackMessages = [NSString stringWithFormat: @"interface_functions[%d]()",
+                                 Editor_getBackMessages];
+    NSString *str = [_evaluator stringByEvaluatingJavaScriptFromString: getBackMessages];
+    NSData *data = [str dataUsingEncoding: NSUTF8StringEncoding];
+    NSArray *array = [NSJSONSerialization JSONObjectWithData: data options: 0 error: nil];
+    for (NSArray *message in array)
+        [self dispatchCallbackMessage: message];
+}
+
+- (NSString *)operationStringWithFunction:(JSInterfaceFunction)function nargs:(int)nargs arguments:(va_list)ap
+{
+    NSMutableString *operation = [NSMutableString stringWithCapacity: 0];
+    [operation appendFormat: @"interface_functions[%d](", function];
+    NSObject *arg;
+    for (int argno = 0; argno < nargs; argno++) {
+        arg = va_arg(ap,NSObject*);
+        if (argno > 0)
+            [operation appendString: @","];
+        if (arg == nil) {
+            [operation appendString: @"null"];
+        }
+        else if ([arg isKindOfClass: [NSNumber class]]) {
+            [operation appendString: [arg description]];
+        }
+        else if ([arg isKindOfClass: [NSNull class]]) {
+            [operation appendString: @"null"];
+        }
+        else if ([arg isKindOfClass: [NSArray class]] || [arg isKindOfClass: [NSDictionary class]]) {
+            NSError *err = nil;
+            NSData *data = [NSJSONSerialization dataWithJSONObject: arg options: 0 error: &err];
+            if (data == nil) {
+                [NSException raise: @"NSJSONSerialization"
+                            format: @"executeJavaScript %d: cannot serialise argument %d to JSON: %@",
+                                    function, argno, FCErrorDescription(err)];
+            }
+            else {
+                NSString *str = [[NSString alloc] initWithBytes: data.bytes length: data.length
+                                                       encoding: NSUTF8StringEncoding];
+                [operation appendString: str];
+            }
+        }
+        else {
+            char *quoted = DFQuote(arg.description.UTF8String);
+            NSString *nsQuoted = [NSString stringWithUTF8String: quoted];
+            [operation appendString: nsQuoted];
+            free(quoted);
+        }
+    }
+    [operation appendString: @")"];
+    return operation;
+}
+
+- (id)executeJavaScriptWithJSONResult:(BOOL)jsonResult function:(JSInterfaceFunction)function nargs:(int)nargs arguments:(va_list)ap
+{
+    NSDate *start = [NSDate date];
+    if (!_jsInitialised) {
+        [NSException raise: @"JavaScriptNotInitialised"
+                    format: @"Yet to receive a jsInterfaceInitFinished from JavaScript code"];
+    }
+    self.currentOperation = [self operationStringWithFunction: function nargs: nargs arguments: ap];
+    id result;
+    if (!jsonResult) {
+        NSString *code = [NSString stringWithFormat: @"interface_functions[%d](function() { return %@; });",
+                                                     Main_execute, self.currentOperation];
+        result = [_evaluator stringByEvaluatingJavaScriptFromString: code];
+        [self jsCallCompleted];
+    }
+    else {
+        NSString *code = [NSString stringWithFormat: @"interface_functions[%d](function() { return JSON.stringify(%@); });",
+                                                     Main_execute, self.currentOperation];
+
+        NSString *str = [_evaluator stringByEvaluatingJavaScriptFromString: code];
+        [self jsCallCompleted];
+
+        if ([str isEqualToString: @"null"]) {
+            result = nil;
+        }
+        else {
+            NSData *data = [str dataUsingEncoding: NSUTF8StringEncoding];
+            NSError *err = nil;
+            result = [NSJSONSerialization JSONObjectWithData: data options: 0 error: &err];
+            if (result == nil) {
+                [self reportErrorWithType: nil format: @"Cannot deserialise JSON result \"%@\": %@",
+                 str, FCErrorDescription(err)];
+            }
+        }
+    }
+
+    NSDate *end = [NSDate date];
+    NSTimeInterval interval = [end timeIntervalSinceDate: start];
+    _numCalls[function]++;
+    _timeUsed[function] += interval;
+    _totalTimeUsed += interval;
+
+    self.currentOperation = nil;
+    if (functionModifiesDocument(function))
+        self.documentModified = YES;
+    return result;
+}
+
+- (void)printStatistics
+{
+    if (_totalTimeUsed == 0.0)
+        return;
+
+    printf("\n");
+    printf("%-10s %-10s %-10s %-10s\n","Function","Calls","Time","Time pct");
+
+    NSMutableArray *order = [NSMutableArray arrayWithCapacity: 0];
+    for (NSUInteger i = 0; i < JSInterfaceFunctionCount; i++)
+        [order addObject: [NSNumber numberWithUnsignedInteger: i]];
+    [order sortUsingComparator:^NSComparisonResult(NSNumber *n1, NSNumber *n2) {
+        NSUInteger i1 = n1.unsignedIntValue;
+        NSUInteger i2 = n2.unsignedIntValue;
+        if (_timeUsed[i1] < _timeUsed[i2])
+            return NSOrderedAscending;
+        else if (_timeUsed[i1] > _timeUsed[i2])
+            return NSOrderedDescending;
+        else
+            return NSOrderedSame;
+    }];
+    for (NSNumber *n in order) {
+        NSUInteger i = n.unsignedIntValue;
+        double pct = 100*(_timeUsed[i]/_totalTimeUsed);
+        if (pct >= 0.01) {
+            printf("%-10d %-10d %-10d %.2f%%\n",(int)i,(int)_numCalls[i],(int)(_timeUsed[i]*1000),pct);
+        }
+    }
+    printf("totalTimeUsed = %.2fms\n",1000*_totalTimeUsed);
+}
+
+- (id)executeJavaScriptJSON:(JSInterfaceFunction)function nargs:(int)nargs, ...
+{
+    va_list ap;
+    va_start(ap,nargs);
+    NSString *result = (NSString *)[self executeJavaScriptWithJSONResult: YES
+                                                                function: function
+                                                                   nargs: nargs
+                                                               arguments: ap];
+    va_end(ap);
+    return result;
+}
+
+- (NSString *)executeJavaScript:(JSInterfaceFunction)function nargs:(int)nargs, ...
+{
+    va_list ap;
+    va_start(ap,nargs);
+    NSString *result = (NSString *)[self executeJavaScriptWithJSONResult: NO
+                                                                function: function
+                                                                   nargs: nargs
+                                                               arguments: ap];
+    va_end(ap);
+    return result;
+}
+
+- (void)dispatchCallbackMessage:(NSArray*)array
+{
+    if (array.count == 0)
+        return;
+
+    if (![[array objectAtIndex: 0] isKindOfClass: [NSString class]])
+        return;
+
+    NSString *functionName = [array objectAtIndex: 0];
+
+    if ([functionName isEqualToString: @"debug"] &&
+        ([array count] == 2) &&
+        [[array objectAtIndex: 1] isKindOfClass: [NSString class]]) {
+        NSString *message = [array objectAtIndex: 1];
+        debug(@"%@\n",message);
+    }
+    else if ([functionName isEqualToString: @"addOutlineItem"] &&
+             [_delegate respondsToSelector: @selector(jsAddOutlineItem:type:title:)] &&
+             ([array count] == 4) &&
+             [[array objectAtIndex: 1] isKindOfClass: [NSString class]] &&
+             [[array objectAtIndex: 2] isKindOfClass: [NSString class]]) {
+        // 3 could be a a string or null
+        NSString *title = [array objectAtIndex: 3];
+        if ([title isKindOfClass: [NSNull class]])
+            title = nil;
+        [_delegate jsAddOutlineItem: [array objectAtIndex: 1]
+                              type: [array objectAtIndex: 2]
+                             title: title];
+    }
+    else if ([functionName isEqualToString: @"updateOutlineItem"] &&
+             [_delegate respondsToSelector: @selector(jsUpdateOutlineItem:title:)] &&
+             ([array count] == 3) &&
+             [[array objectAtIndex: 1] isKindOfClass: [NSString class]] &&
+             [[array objectAtIndex: 2] isKindOfClass: [NSString class]]) {
+        [_delegate jsUpdateOutlineItem: [array objectAtIndex: 1] title: [array objectAtIndex: 2]];
+    }
+    else if ([functionName isEqualToString: @"removeOutlineItem"] &&
+             [_delegate respondsToSelector: @selector(jsRemoveOutlineItem:)] &&
+             ([array count] == 2) &&
+             [[array objectAtIndex: 1] isKindOfClass: [NSString class]]) {
+        [_delegate jsRemoveOutlineItem: [array objectAtIndex: 1]];
+    }
+    else if ([functionName isEqualToString: @"outlineUpdated"] &&
+             [_delegate respondsToSelector: @selector(jsOutlineUpdated)] &&
+             [array count] == 1) {
+        [_delegate jsOutlineUpdated];
+    }
+    else if ([functionName isEqualToString: @"setSelectionHandles"] &&
+             [_delegate respondsToSelector: @selector(jsSetSelectionHandlesX1:y1:height1:x2:y2:height2:)] &&
+             ([array count] == 7) &&
+             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 5] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 6] isKindOfClass: [NSNumber class]])) {
+        [_delegate jsSetSelectionHandlesX1: ((NSNumber *)[array objectAtIndex: 1]).intValue
+                                       y1: ((NSNumber *)[array objectAtIndex: 2]).intValue
+                                  height1: ((NSNumber *)[array objectAtIndex: 3]).intValue
+                                       x2: ((NSNumber *)[array objectAtIndex: 4]).intValue
+                                       y2: ((NSNumber *)[array objectAtIndex: 5]).intValue
+                                  height2: ((NSNumber *)[array objectAtIndex: 6]).intValue];
+    }
+    else if ([functionName isEqualToString: @"setTableSelection"] &&
+             [_delegate respondsToSelector: @selector(jsSetTableSelectionX:y:width:height:)] &&
+             ([array count] == 5) &&
+             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]])) {
+        [_delegate jsSetTableSelectionX: ((NSNumber *)[array objectAtIndex: 1]).intValue
+                                     y: ((NSNumber *)[array objectAtIndex: 2]).intValue
+                                 width: ((NSNumber *)[array objectAtIndex: 3]).intValue
+                                height: ((NSNumber *)[array objectAtIndex: 4]).intValue];
+    }
+    else if ([functionName isEqualToString: @"setCursor"] &&
+             [_delegate respondsToSelector: @selector(jsSetCursorX:y:width:height:)] &&
+             ([array count] == 5) &&
+             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]])) {
+        [_delegate jsSetCursorX: ((NSNumber *)[array objectAtIndex: 1]).intValue
+                             y: ((NSNumber *)[array objectAtIndex: 2]).intValue
+                         width: ((NSNumber *)[array objectAtIndex: 3]).intValue
+                        height: ((NSNumber *)[array objectAtIndex: 4]).intValue];
+    }
+    else if ([functionName isEqualToString: @"clearSelectionHandlesAndCursor"] &&
+             [_delegate respondsToSelector: @selector(jsClearSelectionHandlesAndCursor)] &&
+             ([array count] == 1)) {
+        [_delegate jsClearSelectionHandlesAndCursor];
+    }
+    else if ([functionName isEqualToString: @"setSelectionBounds"] &&
+             [_delegate respondsToSelector: @selector(jsSetSelectionBoundsLeft:top:right:bottom:)] &&
+             ([array count] == 5) &&
+             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
+             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]])) {
+        [_delegate jsSetSelectionBoundsLeft: ((NSNumber *)[array objectAtIndex: 1]).intValue
+                                       top: ((NSNumber *)[array objectAtIndex: 2]).intValue
+                                     right: ((NSNumber *)[array objectAtIndex: 3]).intValue
+                                    bottom: ((NSNumber *)[array objectAtIndex: 4]).intValue];
+    }
+    else if ([functionName isEqualToString: @"updateAutoCorrect"] &&
+             [_delegate respondsToSelector: @selector(jsUpdateAutoCorrect)]) {
+        [_delegate jsUpdateAutoCorrect];
+    }
+    else if ([functionName isEqualToString: @"error"] &&
+             (array.count == 3) &&
+             [[array objectAtIndex: 1] isKindOfClass: [NSString class]] &&
+             [[array objectAtIndex: 2] isKindOfClass: [NSString class]]) {
+        NSString *message = [array objectAtIndex: 1];
+        NSString *type = [array objectAtIndex: 2];
+        if (type.length == 0)
+            type = nil;
+        [self reportErrorWithType: type format: @"%@", message];
+    }
+}
+
+- (void)reportErrorWithType:(NSString *)type format:(NSString *)format, ...
+{
+    if (self.error != nil)
+        return;
+
+    va_list ap;
+    va_start(ap,format);
+    NSString *basicError = [[NSString alloc] initWithFormat: format arguments: ap];
+    va_end(ap);
+
+    NSString *getErrorReportingInfo = [NSString stringWithFormat: @"interface_functions[%d]()",
+                                       Main_getErrorReportingInfo];
+    NSString *html = [_evaluator stringByEvaluatingJavaScriptFromString: getErrorReportingInfo];
+
+    self.error = [[JSError alloc] initWithType: type
+                                       message: basicError
+                                     operation: self.currentOperation
+                                          html: html];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSModule                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSModule
+
+- (JSModule *)initWithJS:(JSInterface *)js
+{
+    if (!(self = [super init]))
+        return nil;
+    _js = js;
+    return self;
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                          JSAutoCorrect                                         //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSAutoCorrect
+
+- (void)correctPreceding:(int)numChars word:(NSString *)replacement confirmed:(BOOL)confirmed;
+{
+    [self.js executeJavaScript: AutoCorrect_correctPrecedingWord nargs: 3,
+     [NSNumber numberWithInt: numChars], replacement, [NSNumber numberWithBool: confirmed]];
+}
+
+- (NSDictionary *)getCorrection
+{
+    return [self.js executeJavaScriptJSON: AutoCorrect_getCorrection nargs: 0];
+}
+
+- (NSDictionary *)getCorrectionCoords
+{
+    return [self.js executeJavaScriptJSON: AutoCorrect_getCorrectionCoords nargs: 0];
+}
+
+- (void)acceptCorrection
+{
+    [self.js executeJavaScript: AutoCorrect_acceptCorrection nargs: 0];
+}
+
+- (void)replaceCorrection:(NSString *)replacement
+{
+    [self.js executeJavaScript: AutoCorrect_replaceCorrection nargs: 1, replacement];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                        JSChangeTracking                                        //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSChangeTracking
+
+- (BOOL)showChanges
+{
+    NSString *result = [self.js executeJavaScript: ChangeTracking_showChanges nargs: 0];
+    return [result isEqualToString: @"true"];
+}
+
+- (BOOL)trackChanges
+{
+    NSString *result = [self.js executeJavaScript: ChangeTracking_trackChanges nargs: 0];
+    return [result isEqualToString: @"true"];
+}
+
+- (void)setShowChanges:(BOOL)showChanges
+{
+    [self.js executeJavaScript: ChangeTracking_setShowChanges
+                         nargs: 1, [NSNumber numberWithBool: showChanges]];
+}
+
+- (void)setTrackChanges:(BOOL)trackChanges
+{
+    [self.js executeJavaScript: ChangeTracking_setTrackChanges
+                         nargs: 1, [NSNumber numberWithBool: trackChanges]];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                           JSClipboard                                          //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSClipboard
+
+// The copy operation is called clipboardCopy to keep the static analyzer happy, because it thinks
+// that it relates to making a copy of the object and reports a memory leak. The cut operation
+// is named similarly just for consistency.
+
+- (NSDictionary *)clipboardCut
+{
+    return [self.js executeJavaScriptJSON: Clipboard_cut nargs: 0];
+}
+
+- (NSDictionary *)clipboardCopy
+{
+    return [self.js executeJavaScriptJSON: Clipboard_copy nargs: 0];
+}
+
+- (void)pasteHTML:(NSString *)html
+{
+    [self.js executeJavaScript: Clipboard_pasteHTML nargs: 1, html];
+}
+
+- (void)pasteText:(NSString *)text
+{
+    [self.js executeJavaScript: Clipboard_pasteText nargs: 1, text];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSCursor                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Cursor.js
+
+@implementation JSCursor
+
+- (NSString *)positionCursorX:(int)x y:(int)y wordBoundary:(BOOL)wordBoundary
+{
+    return [self.js executeJavaScript: Cursor_positionCursor nargs: 3,
+            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
+            [NSNumber numberWithBool: wordBoundary]];
+}
+
+- (CGRect)getCursorPosition
+{
+    NSDictionary *result = [self.js executeJavaScriptJSON: Cursor_getCursorPosition nargs: 0];
+    return CGRectMake(NSDictionaryGetInt(result,@"x"),
+                      NSDictionaryGetInt(result,@"y"),
+                      NSDictionaryGetInt(result,@"width"),
+                      NSDictionaryGetInt(result,@"height"));
+}
+
+- (void)moveLeft
+{
+    [self.js executeJavaScript: Cursor_moveLeft nargs: 0];
+}
+
+- (void)moveRight
+{
+    [self.js executeJavaScript: Cursor_moveRight nargs: 0];
+}
+
+- (void)moveToStartOfDocument
+{
+    [self.js executeJavaScript: Cursor_moveToStartOfDocument nargs: 0];
+}
+
+- (void)moveToEndOfDocument
+{
+    [self.js executeJavaScript: Cursor_moveToEndOfDocument nargs: 0];
+}
+
+- (void)insertReference:(NSString *)itemId
+{
+    [self.js executeJavaScript: Cursor_insertReference nargs: 1, itemId];
+}
+
+- (void)insertLinkWithText:(NSString *)text URL:(NSString *)URL
+{
+    [self.js executeJavaScript: Cursor_insertLink nargs: 2, text, URL];
+}
+
+- (void)insertCharacter:(unichar)character allowInvalidPos:(BOOL)allowInvalidPos
+{
+    NSString *str = [NSString stringWithFormat: @"%C", character];
+    [self.js executeJavaScript: Cursor_insertCharacter nargs: 2, str,
+     [NSNumber numberWithBool: allowInvalidPos]];
+}
+
+- (void)deleteCharacter
+{
+    [self.js executeJavaScript: Cursor_deleteCharacter nargs: 0];
+}
+
+- (void)enterPressed
+{
+    [self.js executeJavaScript: Cursor_enterPressed nargs: 0];
+}
+
+- (NSString *)getPrecedingWord
+{
+    return [self.js executeJavaScript: Cursor_getPrecedingWord nargs: 0];
+}
+
+- (NSDictionary *)getLinkProperties
+{
+    return [self.js executeJavaScriptJSON: Cursor_getLinkProperties nargs: 0];
+}
+
+- (void)setLinkProperties:(NSDictionary *)properties
+{
+    [self.js executeJavaScript: Cursor_setLinkProperties nargs: 1, properties];
+}
+
+- (void)setReferenceTarget:(NSString *)itemId
+{
+    [self.js executeJavaScript: Cursor_setReferenceTarget nargs: 1, itemId];
+}
+
+- (void)insertFootnote:(NSString *)content
+{
+    [self.js executeJavaScript: Cursor_insertFootnote nargs: 1, content];
+}
+
+- (void)insertEndnote:(NSString *)content
+{
+    [self.js executeJavaScript: Cursor_insertEndnote nargs: 1, content];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            Equations                                           //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSEquations
+
+- (void)insertEquation
+{
+    [self.js executeJavaScript: Equations_insertEquation nargs: 0];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSFigures                                           //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSFigures
+
+- (void)insertFigure:(NSString *)filename width:(NSString *)width
+            numbered:(BOOL)numbered caption:(NSString *)caption
+{
+    [self.js executeJavaScript: Figures_insertFigure nargs: 4,
+     filename, width, [NSNumber numberWithBool: numbered], caption];
+}
+
+- (NSString *)getSelectedFigureId
+{
+    return [self.js executeJavaScript: Figures_getSelectedFigureId nargs: 0];
+}
+
+- (NSDictionary *)getProperties:(NSString *)itemId
+{
+    return [self.js executeJavaScriptJSON: Figures_getProperties nargs: 1, itemId];
+}
+
+- (void)setProperties:(NSString *)itemId width:(NSString *)width src:(NSString *)src
+{
+    [self.js executeJavaScript: Figures_setProperties nargs: 3, itemId, width, src];
+}
+
+- (NSDictionary *)getGeometry:(NSString *)itemId
+{
+    return [self.js executeJavaScriptJSON: Figures_getGeometry nargs: 1, itemId];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                          JSFormatting                                          //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Formatting.js
+
+@implementation JSFormatting
+
+- (NSDictionary *)getFormatting
+{
+    return [self.js executeJavaScriptJSON: Formatting_getFormatting nargs: 0];
+}
+
+- (void)applyFormattingChangesStyle:(NSString *)style properties:(NSDictionary *)properties
+{
+    [self.js executeJavaScript: Formatting_applyFormattingChanges nargs: 2, style, properties];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                             JSInput                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSInput
+
+- (void)removePosition:(int)posId
+{
+    [self.js executeJavaScript: Input_removePosition nargs: 1, [NSNumber numberWithInt: posId]];
+}
+
+- (NSString *)textInRangeStartId:(int)startId startAdjust:(int)startAdjust
+                           endId:(int)endId endAdjust:(int)endAdjust
+{
+    return [self.js executeJavaScript: Input_textInRange nargs: 4,
+            [NSNumber numberWithInt: startId],
+            [NSNumber numberWithInt: startAdjust],
+            [NSNumber numberWithInt: endId],
+            [NSNumber numberWithInt: endAdjust]];
+}
+
+- (void)replaceRangeStart:(int)startId end:(int)endId withText:(NSString *)text
+{
+    [self.js executeJavaScript: Input_replaceRange nargs: 3,
+     [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId], text];
+}
+
+- (NSDictionary *)selectedTextRange
+{
+    return [self.js executeJavaScriptJSON: Input_selectedTextRange nargs: 0];
+}
+
+- (void)setSelectedTextRangeStart:(int)startId end:(int)endId
+{
+    [self.js executeJavaScript: Input_setSelectedTextRange nargs: 2,
+     [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
+}
+
+- (NSDictionary *)markedTextRange
+{
+    return [self.js executeJavaScriptJSON: Input_markedTextRange nargs: 0];
+}
+
+- (void)setMarkedText:(NSString *)text startOffset:(int)startOffset endOffset:(int)endOffset
+{
+    [self.js executeJavaScript: Input_setMarkedText nargs: 3,
+     text, [NSNumber numberWithInt: startOffset], [NSNumber numberWithInt: endOffset]];
+}
+
+- (void)unmarkText
+{
+    [self.js executeJavaScript: Input_unmarkText nargs: 0];
+}
+
+- (BOOL)forwardSelectionAffinity
+{
+    NSString *result = [self.js executeJavaScript: Input_forwardSelectionAffinity nargs: 0];
+    return [result isEqualToString: @"true"];
+}
+
+- (void)setForwardSelectionAffinity:(BOOL)forwardSelectionAffinity
+{
+    [self.js executeJavaScript: Input_setForwardSelectionAffinity nargs: 1,
+     [NSNumber numberWithBool: forwardSelectionAffinity]];
+}
+
+- (int)positionFromPosition:(int)posId offset:(int)offset
+{
+    NSString *result = [self.js executeJavaScript: Input_positionFromPositionOffset nargs: 2,
+                        [NSNumber numberWithInt: posId], [NSNumber numberWithInt: offset]];
+    return result.intValue;
+}
+
+- (int)positionFromPosition:(int)posId inDirection:(NSString *)direction offset:(int)offset
+{
+    NSString *result = [self.js executeJavaScript: Input_positionFromPositionInDirectionOffset nargs: 3,
+                        [NSNumber numberWithInt: posId], direction, [NSNumber numberWithInt: offset]];
+    return result.intValue;
+}
+
+- (int)comparePosition:(int)positionId toPosition:(int)otherId
+{
+    NSString *result = [self.js executeJavaScript: Input_comparePositionToPosition nargs: 2,
+                        [NSNumber numberWithInt: positionId], [NSNumber numberWithInt: otherId]];
+    return result.intValue;
+}
+
+- (int)offsetFromPosition:(int)fromPosition toPosition:(int)toPosition
+{
+    NSString *result = [self.js executeJavaScript: Input_offsetFromPositionToPosition nargs: 2,
+                        [NSNumber numberWithInt: fromPosition], [NSNumber numberWithInt: toPosition]];
+    return result.intValue;
+}
+
+- (int)positionWithinRangeStart:(int)startId end:(int)endId farthestInDirection:(NSString *)direction
+{
+    NSString *result = [self.js executeJavaScript: Input_positionWithinRangeFarthestInDirection nargs: 3,
+                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId], direction];
+    return result.intValue;
+}
+
+- (NSDictionary *)characterRangeByExtendingPosition:(int)positionId inDirection:(NSString *)direction
+{
+    return [self.js executeJavaScriptJSON: Input_characterRangeByExtendingPositionInDirection nargs: 2,
+            [NSNumber numberWithInt: positionId], direction];
+}
+
+- (NSDictionary *)firstRectForRangeStart:(int)startId end:(int)endId
+{
+    return [self.js executeJavaScriptJSON: Input_firstRectForRange nargs: 2,
+            [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
+}
+
+- (NSDictionary *)caretRectForPosition:(int)posId
+{
+    return [self.js executeJavaScriptJSON: Input_caretRectForPosition nargs: 1,
+            [NSNumber numberWithInt: posId]];
+}
+
+- (int)closestPositionToPointX:(int)x y:(int)y
+{
+    NSString *result = [self.js executeJavaScript: Input_closestPositionToPoint nargs: 2,
+                        [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
+    return result.intValue;
+}
+
+- (int)closestPositionToPointX:(int)x y:(int)y withinRangeStart:(int)startId end:(int)endId
+{
+    NSString *result = [self.js executeJavaScript: Input_closestPositionToPointWithinRange nargs: 4,
+                        [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
+                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
+    return result.intValue;
+}
+
+- (NSDictionary *)characterRangeAtPointX:(int)x y:(int)y
+{
+    return [self.js executeJavaScriptJSON: Input_characterRangeAtPoint nargs: 2,
+            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
+}
+
+- (int)positionWithinRangeStart:(int)startId end:(int)endId atCharacterOffset:(int)offset
+{
+    NSString *result = [self.js executeJavaScript: Input_positionWithinRangeAtCharacterOffset nargs: 3,
+                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId],
+                        [NSNumber numberWithInt: offset]];
+    return result.intValue;
+}
+
+- (int)characterOffsetOfPosition:(int)positionId withinRangeStart:(int)startId end:(int)endId
+{
+    NSString *result = [self.js executeJavaScript: Input_characterOffsetOfPositionWithinRange nargs: 3,
+                        [NSNumber numberWithInt: positionId],
+                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
+    return result.intValue;
+}
+
+// UITextInputTokenizer methods
+
+- (BOOL)isPosition:(int)posId atBoundary:(NSString *)granularity inDirection:(NSString *)direction
+{
+    NSString *result = [self.js executeJavaScript: Input_isPositionAtBoundaryGranularityInDirection nargs: 3,
+                        [NSNumber numberWithInt: posId], granularity, direction];
+    return [result isEqualToString: @"true"];
+}
+
+- (BOOL)isPosition:(int)posId withinTextUnit:(NSString *)granularity inDirection:(NSString *)direction
+{
+    NSString *result = [self.js executeJavaScript: Input_isPositionWithinTextUnitInDirection nargs: 3,
+                        [NSNumber numberWithInt: posId], granularity, direction];
+    return [result isEqualToString: @"true"];
+}
+
+- (int)positionFromPosition:(int)posId toBoundary:(NSString *)granularity inDirection:(NSString *)direction
+{
+    NSString *result = [self.js executeJavaScript: Input_positionFromPositionToBoundaryInDirection nargs: 3,
+                        [NSNumber numberWithInt: posId], granularity, direction];
+    return result.intValue;
+}
+
+- (NSDictionary *)rangeEnclosingPosition:(int)posId withGranularity:(NSString *)granularity inDirection:(NSString *)direction
+{
+    return [self.js executeJavaScriptJSON: Input_rangeEnclosingPositionWithGranularityInDirection nargs: 3,
+            [NSNumber numberWithInt: posId], granularity, direction];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                             JSLists                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Lists.js
+
+@implementation JSLists
+
+- (void)increaseIndent
+{
+    [self.js executeJavaScript: Lists_increaseIndent nargs: 0];
+}
+
+- (void)decreaseIndent
+{
+    [self.js executeJavaScript: Lists_decreaseIndent nargs: 0];
+}
+
+- (void)clearList
+{
+    [self.js executeJavaScript: Lists_clearList nargs: 0];
+}
+
+- (void)setUnorderedList
+{
+    [self.js executeJavaScript: Lists_setUnorderedList nargs: 0];
+}
+
+- (void)setOrderedList
+{
+    [self.js executeJavaScript: Lists_setOrderedList nargs: 0];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                             JSMain                                             //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Main.js
+
+@implementation JSMain
+
+- (NSString *)getLanguage
+{
+    return [self.js executeJavaScript: Main_getLanguage nargs: 0];
+}
+
+- (void)setLanguage:(NSString *)language
+{
+    [self.js executeJavaScript: Main_setLanguage nargs: 1, language];
+}
+
+- (NSString *)setGenerator:(NSString *)generator
+{
+    return [self.js executeJavaScript: Main_setGenerator nargs: 1, generator];
+}
+
+- (BOOL)prepareForSave
+{
+    NSString *result = [self.js executeJavaScript: Main_prepareForSave nargs: 0];
+    return [@"true" isEqualToString: result];
+}
+
+- (NSString *)getHTML;
+{
+    return [self.js executeJavaScript: Main_getHTML nargs: 0];
+}
+
+- (BOOL)isEmptyDocument
+{
+    NSString *result = [self.js executeJavaScript: Main_isEmptyDocument nargs: 0];
+    return [result isEqualToString: @"true"];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                           JSMetadata                                           //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSMetadata
+
+- (NSDictionary *)getMetadata
+{
+    return [self.js executeJavaScriptJSON: Metadata_getMetadata nargs: 0];
+}
+
+- (void)setMetadata:(NSDictionary *)metadata
+{
+    [self.js executeJavaScriptJSON: Metadata_setMetadata nargs: 1, metadata];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSOutline                                           //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Outline.js
+
+@implementation JSOutline
+
+- (NSDictionary *)getOutline
+{
+    return [self.js executeJavaScriptJSON: Outline_getOutline nargs: 0];
+}
+
+- (void)moveSection:(NSString *)sectionId parentId:(NSString *)parentId nextId:(NSString *)nextId
+{
+    [self.js executeJavaScript: Outline_moveSection nargs: 3, sectionId, parentId, nextId];
+}
+
+- (void)deleteItem:(NSString *)itemId
+{
+    [self.js executeJavaScript: Outline_deleteItem nargs: 1, itemId];
+}
+
+- (void)scheduleUpdateStructure
+{
+    [self.js executeJavaScript: Outline_scheduleUpdateStructure nargs: 0];
+}
+
+- (void)goToItem:(NSString *)itemId
+{
+    [self.js executeJavaScript: Outline_goToItem nargs: 1, itemId];
+}
+
+- (void)set:(NSString *)itemId numbered:(BOOL)numbered
+{
+    [self.js executeJavaScript: Outline_setNumbered nargs: 2, itemId, [NSNumber numberWithBool: numbered]];
+}
+
+- (void)set:(NSString *)itemId title:(NSString *)title
+{
+    [self.js executeJavaScript: Outline_setTitle nargs: 2, itemId, title];
+}
+
+- (void)insertTableOfContents
+{
+    [self.js executeJavaScript: Outline_insertTableOfContents nargs: 0];
+}
+
+- (void)insertListOfFigures
+{
+    [self.js executeJavaScript: Outline_insertListOfFigures nargs: 0];
+}
+
+- (void)insertListOfTables
+{
+    [self.js executeJavaScript: Outline_insertListOfTables nargs: 0];
+}
+
+- (void)setPrintMode:(BOOL)printMode
+{
+    [self.js executeJavaScript: Outline_setPrintMode nargs: 1, [NSNumber numberWithBool: printMode]];
+}
+
+- (NSDictionary *)examinePrintLayout:(int)pageHeight
+{
+    return [self.js executeJavaScriptJSON: Outline_examinePrintLayout nargs: 1,
+            [NSNumber numberWithInt: pageHeight]];
+}
+
+- (BOOL)detectSectionNumbering
+{
+    NSString *result = [self.js executeJavaScript: Outline_detectSectionNumbering nargs: 0];
+    return [result isEqualToString: @"true"];
+}
+
+- (NSDictionary *)findUsedStyles
+{
+    return [self.js executeJavaScriptJSON: Outline_findUsedStyles nargs: 0];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSPreview                                           //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSPreview
+
+- (void)showForStyle:(NSString *)styleId uiName:(NSString *)uiName title:(NSString *)title
+{
+    [self.js executeJavaScript: Preview_showForStyle nargs: 3, styleId, uiName, title];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                             JSScan                                             //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSScan
+
+- (void)reset
+{
+    [self.js executeJavaScript: Scan_reset nargs: 0];
+}
+
+- (EDScanParagraph *)next
+{
+    NSDictionary *dict = [self.js executeJavaScriptJSON: Scan_next nargs: 0];
+    if ((dict == nil) || ![dict isKindOfClass: [NSDictionary class]])
+        return nil;
+
+    NSString *text = FCGetString(dict,@"text",nil);
+    NSString *sectionId = FCGetString(dict,@"sectionId",nil);
+    if (text == nil)
+        return nil;
+
+    return [[EDScanParagraph alloc] initWithText: text sectionId: sectionId];
+}
+
+- (int)addMatchStart:(int)start end:(int)end
+{
+    return [self.js executeJavaScript: Scan_addMatch nargs: 2,
+            [NSNumber numberWithInt: start],
+            [NSNumber numberWithInt: end]].intValue;
+}
+
+- (void)showMatch:(int)matchId
+{
+    [self.js executeJavaScript: Scan_showMatch nargs: 1, [NSNumber numberWithInt: matchId]];
+}
+
+- (void)replaceMatch:(int)matchId with:(NSString *)text
+{
+    [self.js executeJavaScript: Scan_replaceMatch nargs: 2, [NSNumber numberWithInt: matchId], text];
+}
+
+- (void)removeMatch:(int)matchId
+{
+    [self.js executeJavaScript: Scan_removeMatch nargs: 1, [NSNumber numberWithInt: matchId]];
+}
+
+- (void)goToMatch:(int)matchId
+{
+    [self.js executeJavaScript: Scan_goToMatch nargs: 1, [NSNumber numberWithInt: matchId]];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                           JSSelection                                          //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Selection.js
+
+@implementation JSSelection
+
+- (void)update
+{
+    [self.js executeJavaScript: Selection_update nargs: 0];
+}
+
+- (void)selectAll
+{
+    [self.js executeJavaScript: Selection_selectAll nargs: 0];
+}
+
+- (void)selectParagraph
+{
+    [self.js executeJavaScript: Selection_selectParagraph nargs: 0];
+}
+
+- (void)selectWordAtCursor
+{
+    [self.js executeJavaScript: Selection_selectWordAtCursor nargs: 0];
+}
+
+- (NSString *)dragSelectionBeginX:(int)x y:(int)y selectWord:(BOOL)selectWord
+{
+    return [self.js executeJavaScript: Selection_dragSelectionBegin nargs: 3,
+            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
+            [NSNumber numberWithBool: selectWord]];
+}
+
+- (NSString *)dragSelectionUpdateX:(int)x y:(int)y selectWord:(BOOL)selectWord
+{
+    return [self.js executeJavaScript: Selection_dragSelectionUpdate nargs: 3,
+            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
+            [NSNumber numberWithBool: selectWord]];
+}
+
+- (NSString *)moveStartLeft
+{
+    return [self.js executeJavaScript: Selection_moveStartLeft nargs: 0];
+}
+
+- (NSString *)moveStartRight
+{
+    return [self.js executeJavaScript: Selection_moveStartRight nargs: 0];
+}
+
+- (NSString *)moveEndLeft
+{
+    return [self.js executeJavaScript: Selection_moveEndLeft nargs: 0];
+}
+
+- (NSString *)moveEndRight
+{
+    return [self.js executeJavaScript: Selection_moveEndRight nargs: 0];
+}
+
+- (void)setSelectionStartAtCoordsX:(int)x y:(int)y
+{
+    [self.js executeJavaScript: Selection_setSelectionStartAtCoords nargs: 2,
+                             [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
+}
+
+- (void)setSelectionEndAtCoordsX:(int)x y:(int)y
+{
+    [self.js executeJavaScript: Selection_setSelectionEndAtCoords nargs: 2,
+                             [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
+}
+
+- (void)setTableSelectionEdge:(NSString *)edge atCoordsX:(int)x y:(int)y
+{
+    [self.js executeJavaScript: Selection_setTableSelectionEdgeAtCoords nargs: 3,
+                           edge, [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
+}
+
+- (void)print
+{
+    [self.js executeJavaScript: Selection_print nargs: 0];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSStyles                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSStyles
+
+- (NSString *)getCSSText
+{
+    return [self.js executeJavaScript: Styles_getCSSText nargs: 0];
+}
+
+- (void)setCSSText:(NSString *)cssText rules:(NSDictionary *)rules
+{
+//    debug(@"---------------------- setCSSText ----------------------\n");
+//    debug(@"%@",cssText);
+//    if ((cssText.length > 0) && ([cssText characterAtIndex: cssText.length-1] != '\n'))
+//        debug(@"\n");
+//    debug(@"--------------------------------------------------------\n");
+    [self.js executeJavaScriptJSON: Styles_setCSSText nargs: 2, cssText, rules];
+}
+
+- (NSString *)paragraphClass
+{
+    return [self.js executeJavaScript: Styles_getParagraphClass nargs: 0];
+}
+
+- (void)setParagraphClass:(NSString *)paragraphClass;
+{
+    [self.js executeJavaScript: Styles_setParagraphClass nargs: 1, paragraphClass];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                            JSTables                                            //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Tables.js
+
+@implementation JSTables
+
+- (void)insertTableRows:(int)rows cols:(int)cols width:(NSString *)width numbered:(BOOL)numbered
+                caption:(NSString *)caption className:(NSString *)className;
+{
+    [self.js executeJavaScript: Tables_insertTable nargs: 6,
+                             [NSNumber numberWithInt: rows], [NSNumber numberWithInt: cols],
+                             width, [NSNumber numberWithBool: numbered], caption, className];
+}
+
+- (void)addAdjacentRow
+{
+    [self.js executeJavaScript: Tables_addAdjacentRow nargs: 0];
+}
+
+- (void)addAdjacentColumn
+{
+    [self.js executeJavaScript: Tables_addAdjacentColumn nargs: 0];
+}
+
+- (void)removeAdjacentRow
+{
+    [self.js executeJavaScript: Tables_removeAdjacentRow nargs: 0];
+}
+
+- (void)removeAdjacentColumn
+{
+    [self.js executeJavaScript: Tables_removeAdjacentColumn nargs: 0];
+}
+
+- (void)clearCells
+{
+    [self.js executeJavaScript: Tables_clearCells nargs: 0];
+}
+
+- (void)mergeCells
+{
+    [self.js executeJavaScript: Tables_mergeCells nargs: 0];
+}
+
+- (void)splitSelection
+{
+    [self.js executeJavaScript: Tables_splitSelection nargs: 0];
+}
+
+- (NSString *)getSelectedTableId
+{
+    return [self.js executeJavaScript: Tables_getSelectedTableId nargs: 0];
+}
+
+- (NSDictionary *)getProperties:(NSString *)itemId
+{
+    return [self.js executeJavaScriptJSON: Tables_getProperties nargs: 1, itemId];
+}
+
+- (void)setProperties:(NSString *)itemId width:(NSString *)width
+{
+    [self.js executeJavaScript: Tables_setProperties nargs: 2, itemId, width];
+}
+
+- (void)set:(NSString *)itemId colWidths:(NSArray *)colWidths
+{
+    [self.js executeJavaScript: Tables_setColWidths nargs: 2, itemId, colWidths];
+}
+
+- (NSDictionary *)getGeometry:(NSString *)itemId
+{
+    return [self.js executeJavaScriptJSON: Tables_getGeometry nargs: 1, itemId];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                          JSUndoManager                                         //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation JSUndoManager
+
+- (int)getLength
+{
+    NSString *result = [self.js executeJavaScript: UndoManager_getLength nargs: 0];
+    return result.intValue;
+}
+
+- (int)getIndex
+{
+    NSString *result = [self.js executeJavaScript: UndoManager_getIndex nargs: 0];
+    return result.intValue;
+}
+
+- (void)setIndex:(int)index
+{
+    [self.js executeJavaScript: UndoManager_setIndex nargs: 1, [NSNumber numberWithInt: index]];
+}
+
+- (void)undo
+{
+    [self.js executeJavaScript: UndoManager_undo nargs: 0];
+}
+
+- (void)redo
+{
+    [self.js executeJavaScript: UndoManager_redo nargs: 0];
+}
+
+- (void)newGroup:(NSString *)name
+{
+    [self.js executeJavaScript: UndoManager_newGroup nargs: 1, name];
+}
+
+- (NSString *)groupType
+{
+    return [self.js executeJavaScript: UndoManager_groupType nargs: 0];
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//                                                                                                //
+//                                           JSViewport                                           //
+//                                                                                                //
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Functions implemented in Viewport.js
+
+@implementation JSViewport
+
+- (void)setViewportWidth:(int)width
+{
+    [self.js executeJavaScript: Viewport_setViewportWidth nargs: 1, [NSNumber numberWithInt: width]];
+}
+
+- (void)setTextScale:(int)textScale
+{
+    [self.js executeJavaScript: Viewport_setTextScale nargs: 1, [NSNumber numberWithInt: textScale]];
+}
+
+@end


[04/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.xml
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.xml b/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.xml
deleted file mode 100644
index 79d31d6..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.xml
+++ /dev/null
@@ -1,11464 +0,0 @@
-<!DOCTYPE dtd PUBLIC "-//Norman Walsh//DTD DTDParse V2.0//EN"
-              "dtd.dtd" [
-]>
-<dtd version='1.0'
-     unexpanded='1'
-     title="?untitled?"
-     namecase-general="1"
-     namecase-entity="0"
-     xml="0"
-     system-id="html4.dtd"
-     public-id=""
-     declaration=""
-     created-by="DTDParse V2.00"
-     created-on="Sat Feb  4 15:13:29 2012"
->
-<entity name="ContentTypes"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="ContentType"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="Coords"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="heading"
-        type="param"
->
-<text-expanded>H1|H2|H3|H4|H5|H6</text-expanded>
-<text>H1|H2|H3|H4|H5|H6</text>
-</entity>
-
-<entity name="HTML.Version"
-        type="param"
->
-<text-expanded>-//W3C//DTD HTML 4.01 Transitional//EN</text-expanded>
-<text>-//W3C//DTD HTML 4.01 Transitional//EN</text>
-</entity>
-
-<entity name="Text"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="cellhalign"
-        type="param"
->
-<text-expanded>align      (left|center|right|justify|char) #IMPLIED
-   char       CDATA    #IMPLIED  -- alignment char, e.g. char=':' --
-   charoff    CDATA       #IMPLIED  -- offset for alignment char --</text-expanded>
-<text>align      (left|center|right|justify|char) #IMPLIED
-   char       %Character;    #IMPLIED  -- alignment char, e.g. char=':' --
-   charoff    %Length;       #IMPLIED  -- offset for alignment char --</text>
-</entity>
-
-<entity name="special"
-        type="param"
->
-<text-expanded>A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
-    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME</text-expanded>
-<text>A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
-    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME</text>
-</entity>
-
-<entity name="LinkTypes"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="HTML.Frameset"
-        type="param"
->
-<text-expanded>IGNORE</text-expanded>
-<text>IGNORE</text>
-</entity>
-
-<entity name="flow"
-        type="param"
->
-<text-expanded>P | H1|H2|H3|H4|H5|H6 | UL | OL |  DIR | MENU | PRE | DL | DIV | CENTER |
-      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
-      TABLE | FIELDSET | ADDRESS | #PCDATA | TT | I | B | U | S | STRIKE | BIG | SMALL | EM | STRONG | DFN | CODE |
-                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM | A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
-    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text-expanded>
-<text>%block; | %inline;</text>
-</entity>
-
-<entity name="HTML.Reserved"
-        type="param"
->
-<text-expanded>IGNORE</text-expanded>
-<text>IGNORE</text>
-</entity>
-
-<entity name="Charsets"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="TFrame"
-        type="param"
->
-<text-expanded>(void|above|below|hsides|lhs|rhs|vsides|box|border)</text-expanded>
-<text>(void|above|below|hsides|lhs|rhs|vsides|box|border)</text>
-</entity>
-
-<entity name="list"
-        type="param"
->
-<text-expanded>UL | OL |  DIR | MENU</text-expanded>
-<text>UL | OL |  DIR | MENU</text>
-</entity>
-
-<entity name="inline"
-        type="param"
->
-<text-expanded>#PCDATA | TT | I | B | U | S | STRIKE | BIG | SMALL | EM | STRONG | DFN | CODE |
-                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM | A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
-    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text-expanded>
-<text>#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;</text>
-</entity>
-
-<entity name="attrs"
-        type="param"
->
-<text-expanded>id          ID             #IMPLIED  -- document-wide unique id --
-  class       CDATA          #IMPLIED  -- space-separated list of classes --
-  style       CDATA   #IMPLIED  -- associated style info --
-  title       CDATA         #IMPLIED  -- advisory title -- lang        NAME #IMPLIED  -- language code --
-  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text -- onclick     CDATA       #IMPLIED  -- a pointer button was clicked --
-  ondblclick  CDATA       #IMPLIED  -- a pointer button was double clicked--
-  onmousedown CDATA       #IMPLIED  -- a pointer button was pressed down --
-  onmouseup   CDATA       #IMPLIED  -- a pointer button was released --
-  onmouseover CDATA       #IMPLIED  -- a pointer was moved onto --
-  onmousemove CDATA       #IMPLIED  -- a pointer was moved within --
-  onmouseout  CDATA       #IMPLIED  -- a pointer was moved away --
-  onkeypress  CDATA       #IMPLIED  -- a key was pressed and released --
-  onkeydown   CDATA       #IMPLIED  -- a key was pressed down --
-  onkeyup     CDATA       #IMPLIED  -- a key was released --</text-expanded>
-<text>%coreattrs; %i18n; %events;</text>
-</entity>
-
-<entity name="head.misc"
-        type="param"
->
-<text-expanded>SCRIPT|STYLE|META|LINK|OBJECT</text-expanded>
-<text>SCRIPT|STYLE|META|LINK|OBJECT</text>
-</entity>
-
-<entity name="TRules"
-        type="param"
->
-<text-expanded>(none | groups | rows | cols | all)</text-expanded>
-<text>(none | groups | rows | cols | all)</text>
-</entity>
-
-<entity name="align"
-        type="param"
->
-<text-expanded>align (left|center|right|justify)  #IMPLIED</text-expanded>
-<text>align (left|center|right|justify)  #IMPLIED</text>
-</entity>
-
-<entity name="LAlign"
-        type="param"
->
-<text-expanded>(top|bottom|left|right)</text-expanded>
-<text>(top|bottom|left|right)</text>
-</entity>
-
-<entity name="Shape"
-        type="param"
->
-<text-expanded>(rect|circle|poly|default)</text-expanded>
-<text>(rect|circle|poly|default)</text>
-</entity>
-
-<entity name="head.content"
-        type="param"
->
-<text-expanded>TITLE &amp; ISINDEX? &amp; BASE?</text-expanded>
-<text>TITLE &amp; ISINDEX? &amp; BASE?</text>
-</entity>
-
-<entity name="MultiLength"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="bodycolors"
-        type="param"
->
-<text-expanded>
-  bgcolor     CDATA        #IMPLIED  -- document background color --
-  text        CDATA        #IMPLIED  -- document text color --
-  link        CDATA        #IMPLIED  -- color of links --
-  vlink       CDATA        #IMPLIED  -- color of visited links --
-  alink       CDATA        #IMPLIED  -- color of selected links --
-  </text-expanded>
-<text>
-  bgcolor     %Color;        #IMPLIED  -- document background color --
-  text        %Color;        #IMPLIED  -- document text color --
-  link        %Color;        #IMPLIED  -- color of links --
-  vlink       %Color;        #IMPLIED  -- color of visited links --
-  alink       %Color;        #IMPLIED  -- color of selected links --
-  </text>
-</entity>
-
-<entity name="Character"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="InputType"
-        type="param"
->
-<text-expanded>(TEXT | PASSWORD | CHECKBOX |
-    RADIO | SUBMIT | RESET |
-    FILE | HIDDEN | IMAGE | BUTTON)</text-expanded>
-<text>(TEXT | PASSWORD | CHECKBOX |
-    RADIO | SUBMIT | RESET |
-    FILE | HIDDEN | IMAGE | BUTTON)</text>
-</entity>
-
-<entity name="reserved"
-        type="param"
->
-<text-expanded></text-expanded>
-<text></text>
-</entity>
-
-<entity name="CAlign"
-        type="param"
->
-<text-expanded>(top|bottom|left|right)</text-expanded>
-<text>(top|bottom|left|right)</text>
-</entity>
-
-<entity name="pre.exclusion"
-        type="param"
->
-<text-expanded>IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT</text-expanded>
-<text>IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT</text>
-</entity>
-
-<entity name="coreattrs"
-        type="param"
->
-<text-expanded>id          ID             #IMPLIED  -- document-wide unique id --
-  class       CDATA          #IMPLIED  -- space-separated list of classes --
-  style       CDATA   #IMPLIED  -- associated style info --
-  title       CDATA         #IMPLIED  -- advisory title --</text-expanded>
-<text>id          ID             #IMPLIED  -- document-wide unique id --
-  class       CDATA          #IMPLIED  -- space-separated list of classes --
-  style       %StyleSheet;   #IMPLIED  -- associated style info --
-  title       %Text;         #IMPLIED  -- advisory title --</text>
-</entity>
-
-<entity name="formctrl"
-        type="param"
->
-<text-expanded>INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text-expanded>
-<text>INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text>
-</entity>
-
-<entity name="LIStyle"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="noframes.content"
-        type="param"
->
-<text-expanded>(P | H1|H2|H3|H4|H5|H6 | UL | OL |  DIR | MENU | PRE | DL | DIV | CENTER |
-      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
-      TABLE | FIELDSET | ADDRESS | #PCDATA | TT | I | B | U | S | STRIKE | BIG | SMALL | EM | STRONG | DFN | CODE |
-                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM | A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
-    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | INPUT | SELECT | TEXTAREA | LABEL | BUTTON)*</text-expanded>
-<text>(%flow;)*</text>
-</entity>
-
-<entity name="MediaDesc"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="Color"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="fontstyle"
-        type="param"
->
-<text-expanded>TT | I | B | U | S | STRIKE | BIG | SMALL</text-expanded>
-<text>TT | I | B | U | S | STRIKE | BIG | SMALL</text>
-</entity>
-
-<entity name="Scope"
-        type="param"
->
-<text-expanded>(row|col|rowgroup|colgroup)</text-expanded>
-<text>(row|col|rowgroup|colgroup)</text>
-</entity>
-
-<entity name="OLStyle"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="cellvalign"
-        type="param"
->
-<text-expanded>valign     (top|middle|bottom|baseline) #IMPLIED</text-expanded>
-<text>valign     (top|middle|bottom|baseline) #IMPLIED</text>
-</entity>
-
-<entity name="Pixels"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="phrase"
-        type="param"
->
-<text-expanded>EM | STRONG | DFN | CODE |
-                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM</text-expanded>
-<text>EM | STRONG | DFN | CODE |
-                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM</text>
-</entity>
-
-<entity name="Datetime"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="StyleSheet"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="preformatted"
-        type="param"
->
-<text-expanded>PRE</text-expanded>
-<text>PRE</text>
-</entity>
-
-<entity name="ULStyle"
-        type="param"
->
-<text-expanded>(disc|square|circle)</text-expanded>
-<text>(disc|square|circle)</text>
-</entity>
-
-<entity name="URI"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="IAlign"
-        type="param"
->
-<text-expanded>(top|middle|bottom|left|right)</text-expanded>
-<text>(top|middle|bottom|left|right)</text>
-</entity>
-
-<entity name="html.content"
-        type="param"
->
-<text-expanded>HEAD, BODY</text-expanded>
-<text>HEAD, BODY</text>
-</entity>
-
-<entity name="version"
-        type="param"
->
-<text-expanded>version CDATA #FIXED '-//W3C//DTD HTML 4.01 Transitional//EN'</text-expanded>
-<text>version CDATA #FIXED '%HTML.Version;'</text>
-</entity>
-
-<entity name="Charset"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="i18n"
-        type="param"
->
-<text-expanded>lang        NAME #IMPLIED  -- language code --
-  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --</text-expanded>
-<text>lang        %LanguageCode; #IMPLIED  -- language code --
-  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --</text>
-</entity>
-
-<entity name="Length"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="FrameTarget"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="TAlign"
-        type="param"
->
-<text-expanded>(left|center|right)</text-expanded>
-<text>(left|center|right)</text>
-</entity>
-
-<entity name="events"
-        type="param"
->
-<text-expanded>onclick     CDATA       #IMPLIED  -- a pointer button was clicked --
-  ondblclick  CDATA       #IMPLIED  -- a pointer button was double clicked--
-  onmousedown CDATA       #IMPLIED  -- a pointer button was pressed down --
-  onmouseup   CDATA       #IMPLIED  -- a pointer button was released --
-  onmouseover CDATA       #IMPLIED  -- a pointer was moved onto --
-  onmousemove CDATA       #IMPLIED  -- a pointer was moved within --
-  onmouseout  CDATA       #IMPLIED  -- a pointer was moved away --
-  onkeypress  CDATA       #IMPLIED  -- a key was pressed and released --
-  onkeydown   CDATA       #IMPLIED  -- a key was pressed down --
-  onkeyup     CDATA       #IMPLIED  -- a key was released --</text-expanded>
-<text>onclick     %Script;       #IMPLIED  -- a pointer button was clicked --
-  ondblclick  %Script;       #IMPLIED  -- a pointer button was double clicked--
-  onmousedown %Script;       #IMPLIED  -- a pointer button was pressed down --
-  onmouseup   %Script;       #IMPLIED  -- a pointer button was released --
-  onmouseover %Script;       #IMPLIED  -- a pointer was moved onto --
-  onmousemove %Script;       #IMPLIED  -- a pointer was moved within --
-  onmouseout  %Script;       #IMPLIED  -- a pointer was moved away --
-  onkeypress  %Script;       #IMPLIED  -- a key was pressed and released --
-  onkeydown   %Script;       #IMPLIED  -- a key was pressed down --
-  onkeyup     %Script;       #IMPLIED  -- a key was released --</text>
-</entity>
-
-<entity name="block"
-        type="param"
->
-<text-expanded>P | H1|H2|H3|H4|H5|H6 | UL | OL |  DIR | MENU | PRE | DL | DIV | CENTER |
-      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
-      TABLE | FIELDSET | ADDRESS</text-expanded>
-<text>P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
-      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
-      TABLE | FIELDSET | ADDRESS</text>
-</entity>
-
-<entity name="Script"
-        type="param"
->
-<text-expanded>CDATA</text-expanded>
-<text>CDATA</text>
-</entity>
-
-<entity name="LanguageCode"
-        type="param"
->
-<text-expanded>NAME</text-expanded>
-<text>NAME</text>
-</entity>
-
-<element name="S" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="S">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="INPUT" stagm="-" etagm="O"
-         content-type="element">
-<content-model-expanded>
-  <empty/>
-</content-model-expanded>
-<content-model>
-  <empty/>
-</content-model>
-</element>
-
-<attlist name="INPUT">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  type        %InputType;    TEXT      -- what kind of widget is needed --
-  name        CDATA          #IMPLIED  -- submit as part of form --
-  value       CDATA          #IMPLIED  -- Specify for radio buttons and checkboxes --
-  checked     (checked)      #IMPLIED  -- for radio buttons and check boxes --
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  readonly    (readonly)     #IMPLIED  -- for text and passwd --
-  size        CDATA          #IMPLIED  -- specific to each type of field --
-  maxlength   NUMBER         #IMPLIED  -- max chars for text fields --
-  src         %URI;          #IMPLIED  -- for fields with images --
-  alt         CDATA          #IMPLIED  -- short description --
-  usemap      %URI;          #IMPLIED  -- use client-side image map --
-  ismap       (ismap)        #IMPLIED  -- use server-side image map --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  onselect    %Script;       #IMPLIED  -- some text was selected --
-  onchange    %Script;       #IMPLIED  -- the element value was changed --
-  accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
-  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
-  %reserved;                           -- reserved for possible future use --
-  </attdecl>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onchange"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="readonly"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="readonly"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="align"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="top middle bottom left right"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="src"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="value"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="name"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="checked"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="checked"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="type"
-           type=""
-           enumeration="yes"
-           value="TEXT PASSWORD CHECKBOX RADIO SUBMIT RESET FILE HIDDEN IMAGE BUTTON"
-           default="TEXT"/>
-<attribute name="accesskey"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="disabled"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="disabled"
-           default=""/>
-<attribute name="usemap"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ismap"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ismap"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="size"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onblur"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onfocus"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="maxlength"
-           type="#IMPLIED"
-           value="NUMBER"
-           default=""/>
-<attribute name="onselect"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="accept"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="alt"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="tabindex"
-           type="#IMPLIED"
-           value="NUMBER"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="ACRONYM" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="ACRONYM">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="SPAN" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="SPAN">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %reserved;                   -- reserved for possible future use --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="FIELDSET" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <sequence-group>
-    <pcdata/>
-    <element-name name="LEGEND"/>
-    <or-group occurrence="*">
-      <element-name name="P"/>
-      <element-name name="H1"/>
-      <element-name name="H2"/>
-      <element-name name="H3"/>
-      <element-name name="H4"/>
-      <element-name name="H5"/>
-      <element-name name="H6"/>
-      <element-name name="UL"/>
-      <element-name name="OL"/>
-      <element-name name="DIR"/>
-      <element-name name="MENU"/>
-      <element-name name="PRE"/>
-      <element-name name="DL"/>
-      <element-name name="DIV"/>
-      <element-name name="CENTER"/>
-      <element-name name="NOSCRIPT"/>
-      <element-name name="NOFRAMES"/>
-      <element-name name="BLOCKQUOTE"/>
-      <element-name name="FORM"/>
-      <element-name name="ISINDEX"/>
-      <element-name name="HR"/>
-      <element-name name="TABLE"/>
-      <element-name name="FIELDSET"/>
-      <element-name name="ADDRESS"/>
-      <pcdata/>
-      <element-name name="TT"/>
-      <element-name name="I"/>
-      <element-name name="B"/>
-      <element-name name="U"/>
-      <element-name name="S"/>
-      <element-name name="STRIKE"/>
-      <element-name name="BIG"/>
-      <element-name name="SMALL"/>
-      <element-name name="EM"/>
-      <element-name name="STRONG"/>
-      <element-name name="DFN"/>
-      <element-name name="CODE"/>
-      <element-name name="SAMP"/>
-      <element-name name="KBD"/>
-      <element-name name="VAR"/>
-      <element-name name="CITE"/>
-      <element-name name="ABBR"/>
-      <element-name name="ACRONYM"/>
-      <element-name name="A"/>
-      <element-name name="IMG"/>
-      <element-name name="APPLET"/>
-      <element-name name="OBJECT"/>
-      <element-name name="FONT"/>
-      <element-name name="BASEFONT"/>
-      <element-name name="BR"/>
-      <element-name name="SCRIPT"/>
-      <element-name name="MAP"/>
-      <element-name name="Q"/>
-      <element-name name="SUB"/>
-      <element-name name="SUP"/>
-      <element-name name="SPAN"/>
-      <element-name name="BDO"/>
-      <element-name name="IFRAME"/>
-      <element-name name="INPUT"/>
-      <element-name name="SELECT"/>
-      <element-name name="TEXTAREA"/>
-      <element-name name="LABEL"/>
-      <element-name name="BUTTON"/>
-    </or-group>
-  </sequence-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group>
-    <pcdata/>
-    <element-name name="LEGEND"/>
-    <sequence-group occurrence="*">
-      <parament-name name="flow"/>
-    </sequence-group>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="FIELDSET">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="H3" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="H3">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %align;                              -- align, text alignment --
-  </attdecl>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="align"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="left center right justify"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="OPTION" stagm="-" etagm="O"
-         content-type="mixed">
-<content-model-expanded>
-  <sequence-group>
-    <pcdata/>
-  </sequence-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group>
-    <pcdata/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="OPTION">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  selected    (selected)     #IMPLIED
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  label       %Text;         #IMPLIED  -- for use in hierarchical menus --
-  value       CDATA          #IMPLIED  -- defaults to element content --
-  </attdecl>
-<attribute name="disabled"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="disabled"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="value"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="label"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="selected"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="selected"
-           default=""/>
-</attlist>
-
-<element name="OPTGROUP" stagm="-" etagm="-"
-         content-type="element">
-<content-model-expanded>
-  <sequence-group occurrence="+">
-    <element-name name="OPTION"/>
-  </sequence-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="+">
-    <element-name name="OPTION"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="OPTGROUP">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  label       %Text;         #REQUIRED -- for use in hierarchical menus --
-  </attdecl>
-<attribute name="disabled"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="disabled"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="label"
-           type="#REQUIRED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="DEL" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <element-name name="P"/>
-    <element-name name="H1"/>
-    <element-name name="H2"/>
-    <element-name name="H3"/>
-    <element-name name="H4"/>
-    <element-name name="H5"/>
-    <element-name name="H6"/>
-    <element-name name="UL"/>
-    <element-name name="OL"/>
-    <element-name name="DIR"/>
-    <element-name name="MENU"/>
-    <element-name name="PRE"/>
-    <element-name name="DL"/>
-    <element-name name="DIV"/>
-    <element-name name="CENTER"/>
-    <element-name name="NOSCRIPT"/>
-    <element-name name="NOFRAMES"/>
-    <element-name name="BLOCKQUOTE"/>
-    <element-name name="FORM"/>
-    <element-name name="ISINDEX"/>
-    <element-name name="HR"/>
-    <element-name name="TABLE"/>
-    <element-name name="FIELDSET"/>
-    <element-name name="ADDRESS"/>
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="flow"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="DEL">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  cite        %URI;          #IMPLIED  -- info on reason for change --
-  datetime    %Datetime;     #IMPLIED  -- date and time of change --
-  </attdecl>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="datetime"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="cite"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="SUB" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="SUB">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="META" stagm="-" etagm="O"
-         content-type="element">
-<content-model-expanded>
-  <empty/>
-</content-model-expanded>
-<content-model>
-  <empty/>
-</content-model>
-</element>
-
-<attlist name="META">
-<attdecl>
-  %i18n;                               -- lang, dir, for use with content --
-  http-equiv  NAME           #IMPLIED  -- HTTP response header name  --
-  name        NAME           #IMPLIED  -- metainformation name --
-  content     CDATA          #REQUIRED -- associated information --
-  scheme      CDATA          #IMPLIED  -- select form of content --
-  </attdecl>
-<attribute name="http-equiv"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="content"
-           type="#REQUIRED"
-           value="CDATA"
-           default=""/>
-<attribute name="name"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="scheme"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-</attlist>
-
-<element name="SUP" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="SUP">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="FONT" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="FONT">
-<attdecl>
-  %coreattrs;                          -- id, class, style, title --
-  %i18n;                       -- lang, dir --
-  size        CDATA          #IMPLIED  -- [+|-]nn e.g. size="+1", size="4" --
-  color       %Color;        #IMPLIED  -- text color --
-  face        CDATA          #IMPLIED  -- comma-separated list of font names --
-  </attdecl>
-<attribute name="face"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="color"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="size"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-</attlist>
-
-<element name="HR" stagm="-" etagm="O"
-         content-type="element">
-<content-model-expanded>
-  <empty/>
-</content-model-expanded>
-<content-model>
-  <empty/>
-</content-model>
-</element>
-
-<attlist name="HR">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  align       (left|center|right) #IMPLIED
-  noshade     (noshade)      #IMPLIED
-  size        %Pixels;       #IMPLIED
-  width       %Length;       #IMPLIED
-  </attdecl>
-<attribute name="width"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="size"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="align"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="left center right"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="noshade"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="noshade"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="ISINDEX" stagm="-" etagm="O"
-         content-type="element">
-<content-model-expanded>
-  <empty/>
-</content-model-expanded>
-<content-model>
-  <empty/>
-</content-model>
-</element>
-
-<attlist name="ISINDEX">
-<attdecl>
-  %coreattrs;                          -- id, class, style, title --
-  %i18n;                               -- lang, dir --
-  prompt      %Text;         #IMPLIED  -- prompt message --</attdecl>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="prompt"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-</attlist>
-
-<element name="TITLE" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <sequence-group>
-    <pcdata/>
-  </sequence-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group>
-    <pcdata/>
-  </sequence-group>
-</content-model>
-<exclusions>
-  <or-group>
-    <element-name name="SCRIPT"/>
-    <element-name name="STYLE"/>
-    <element-name name="META"/>
-    <element-name name="LINK"/>
-    <element-name name="OBJECT"/>
-  </or-group>
-</exclusions>
-</element>
-
-<attlist name="TITLE">
-<attdecl> %i18n</attdecl>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-</attlist>
-
-<element name="BODY" stagm="O" etagm="O"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <element-name name="P"/>
-    <element-name name="H1"/>
-    <element-name name="H2"/>
-    <element-name name="H3"/>
-    <element-name name="H4"/>
-    <element-name name="H5"/>
-    <element-name name="H6"/>
-    <element-name name="UL"/>
-    <element-name name="OL"/>
-    <element-name name="DIR"/>
-    <element-name name="MENU"/>
-    <element-name name="PRE"/>
-    <element-name name="DL"/>
-    <element-name name="DIV"/>
-    <element-name name="CENTER"/>
-    <element-name name="NOSCRIPT"/>
-    <element-name name="NOFRAMES"/>
-    <element-name name="BLOCKQUOTE"/>
-    <element-name name="FORM"/>
-    <element-name name="ISINDEX"/>
-    <element-name name="HR"/>
-    <element-name name="TABLE"/>
-    <element-name name="FIELDSET"/>
-    <element-name name="ADDRESS"/>
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="flow"/>
-  </sequence-group>
-</content-model>
-<inclusions>
-  <or-group>
-    <element-name name="INS"/>
-    <element-name name="DEL"/>
-  </or-group>
-</inclusions>
-</element>
-
-<attlist name="BODY">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  onload          %Script;   #IMPLIED  -- the document has been loaded --
-  onunload        %Script;   #IMPLIED  -- the document has been removed --
-  background      %URI;      #IMPLIED  -- texture tile for document
-                                          background --
-  %bodycolors;                         -- bgcolor, text, link, vlink, alink --
-  </attdecl>
-<attribute name="vlink"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="alink"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="bgcolor"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="text"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="link"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="background"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onunload"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onload"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="NOSCRIPT" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <element-name name="P"/>
-    <element-name name="H1"/>
-    <element-name name="H2"/>
-    <element-name name="H3"/>
-    <element-name name="H4"/>
-    <element-name name="H5"/>
-    <element-name name="H6"/>
-    <element-name name="UL"/>
-    <element-name name="OL"/>
-    <element-name name="DIR"/>
-    <element-name name="MENU"/>
-    <element-name name="PRE"/>
-    <element-name name="DL"/>
-    <element-name name="DIV"/>
-    <element-name name="CENTER"/>
-    <element-name name="NOSCRIPT"/>
-    <element-name name="NOFRAMES"/>
-    <element-name name="BLOCKQUOTE"/>
-    <element-name name="FORM"/>
-    <element-name name="ISINDEX"/>
-    <element-name name="HR"/>
-    <element-name name="TABLE"/>
-    <element-name name="FIELDSET"/>
-    <element-name name="ADDRESS"/>
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="flow"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="NOSCRIPT">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="BASE" stagm="-" etagm="O"
-         content-type="element">
-<content-model-expanded>
-  <empty/>
-</content-model-expanded>
-<content-model>
-  <empty/>
-</content-model>
-</element>
-
-<attlist name="BASE">
-<attdecl>
-  href        %URI;          #IMPLIED  -- URI that acts as base URI --
-  target      %FrameTarget;  #IMPLIED  -- render in this frame --
-  </attdecl>
-<attribute name="target"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="href"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="EM" stagm="-" etagm="-"
-         content-type="mixed">
-<content-model-expanded>
-  <or-group occurrence="*">
-    <pcdata/>
-    <element-name name="TT"/>
-    <element-name name="I"/>
-    <element-name name="B"/>
-    <element-name name="U"/>
-    <element-name name="S"/>
-    <element-name name="STRIKE"/>
-    <element-name name="BIG"/>
-    <element-name name="SMALL"/>
-    <element-name name="EM"/>
-    <element-name name="STRONG"/>
-    <element-name name="DFN"/>
-    <element-name name="CODE"/>
-    <element-name name="SAMP"/>
-    <element-name name="KBD"/>
-    <element-name name="VAR"/>
-    <element-name name="CITE"/>
-    <element-name name="ABBR"/>
-    <element-name name="ACRONYM"/>
-    <element-name name="A"/>
-    <element-name name="IMG"/>
-    <element-name name="APPLET"/>
-    <element-name name="OBJECT"/>
-    <element-name name="FONT"/>
-    <element-name name="BASEFONT"/>
-    <element-name name="BR"/>
-    <element-name name="SCRIPT"/>
-    <element-name name="MAP"/>
-    <element-name name="Q"/>
-    <element-name name="SUB"/>
-    <element-name name="SUP"/>
-    <element-name name="SPAN"/>
-    <element-name name="BDO"/>
-    <element-name name="IFRAME"/>
-    <element-name name="INPUT"/>
-    <element-name name="SELECT"/>
-    <element-name name="TEXTAREA"/>
-    <element-name name="LABEL"/>
-    <element-name name="BUTTON"/>
-  </or-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="*">
-    <parament-name name="inline"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="EM">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  </attdecl>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="COL" stagm="-" etagm="O"
-         content-type="element">
-<content-model-expanded>
-  <empty/>
-</content-model-expanded>
-<content-model>
-  <empty/>
-</content-model>
-</element>
-
-<attlist name="COL">
-<attdecl>                          -- column groups and properties --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  span        NUMBER         1         -- COL attributes affect N columns --
-  width       %MultiLength;  #IMPLIED  -- column width specification --
-  %cellhalign;                         -- horizontal alignment in cells --
-  %cellvalign;                         -- vertical alignment in cells --
-  </attdecl>
-<attribute name="width"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="charoff"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="align"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="left center right justify char"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="valign"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="top middle bottom baseline"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="char"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="span"
-           type=""
-           value="NUMBER"
-           default="1"/>
-</attlist>
-
-<element name="TABLE" stagm="-" etagm="-"
-         content-type="element">
-<content-model-expanded>
-  <sequence-group>
-    <element-name name="CAPTION" occurrence="?"/>
-    <or-group>
-      <element-name name="COL" occurrence="*"/>
-      <element-name name="COLGROUP" occurrence="*"/>
-    </or-group>
-    <element-name name="THEAD" occurrence="?"/>
-    <element-name name="TFOOT" occurrence="?"/>
-    <element-name name="TBODY" occurrence="+"/>
-  </sequence-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group>
-    <element-name name="CAPTION" occurrence="?"/>
-    <or-group>
-      <element-name name="COL" occurrence="*"/>
-      <element-name name="COLGROUP" occurrence="*"/>
-    </or-group>
-    <element-name name="THEAD" occurrence="?"/>
-    <element-name name="TFOOT" occurrence="?"/>
-    <element-name name="TBODY" occurrence="+"/>
-  </sequence-group>
-</content-model>
-</element>
-
-<attlist name="TABLE">
-<attdecl>                        -- table element --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  summary     %Text;         #IMPLIED  -- purpose/structure for speech output--
-  width       %Length;       #IMPLIED  -- table width --
-  border      %Pixels;       #IMPLIED  -- controls frame width around table --
-  frame       %TFrame;       #IMPLIED  -- which parts of frame to render --
-  rules       %TRules;       #IMPLIED  -- rulings between rows and cols --
-  cellspacing %Length;       #IMPLIED  -- spacing between cells --
-  cellpadding %Length;       #IMPLIED  -- spacing within cells --
-  align       %TAlign;       #IMPLIED  -- table position relative to window --
-  bgcolor     %Color;        #IMPLIED  -- background color for cells --
-  %reserved;                           -- reserved for possible future use --
-  datapagesize CDATA         #IMPLIED  -- reserved for possible future use --
-  </attdecl>
-<attribute name="width"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="frame"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="void above below hsides lhs rhs vsides box border"
-           default=""/>
-<attribute name="ondblclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="rules"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="none groups rows cols all"
-           default=""/>
-<attribute name="dir"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="ltr rtl"
-           default=""/>
-<attribute name="onkeydown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="datapagesize"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="bgcolor"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="summary"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeyup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="cellspacing"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseup"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="id"
-           type="#IMPLIED"
-           value="ID"
-           default=""/>
-<attribute name="onmouseover"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="align"
-           type="#IMPLIED"
-           enumeration="yes"
-           value="left center right"
-           default=""/>
-<attribute name="lang"
-           type="#IMPLIED"
-           value="NAME"
-           default=""/>
-<attribute name="style"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousemove"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmouseout"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="border"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onmousedown"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onkeypress"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="cellpadding"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="onclick"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="title"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-<attribute name="class"
-           type="#IMPLIED"
-           value="CDATA"
-           default=""/>
-</attlist>
-
-<element name="DIR" stagm="-" etagm="-"
-         content-type="element">
-<content-model-expanded>
-  <sequence-group occurrence="+">
-    <element-name name="LI"/>
-  </sequence-group>
-</content-model-expanded>
-<content-model>
-  <sequence-group occurrence="+">
-    <element-name name="LI"/>
-  </sequence-group>
-</content-model>
-<exclusions>
-  <or-group>
-    <element-name name="P"/>
-    <element-name name="H1"/>
-    <element-name name="H2"/>
-    <element-name name="H3"/>
-    <element-name name="H4"/>
-    <element-name name="H5"/>
-    <element-name name="H6"/>
-    <element-name name="UL"/>
-    <element-name name="OL"/>
-    <element-name name="DIR"/>
-    <element-name name="MENU"/>
-    <element-name name="PRE"/>
-    <element-name name="DL"/>
-    <element-name name="DIV"/>
-    <element-name name="CENTER"/>
-    <element-name name="NOSCRIPT"/>
-    <element-name name="NOFRAMES"/>
-    <element-name name="BLOCKQUOTE"/>
-    <element-name name="FORM"/>
-    <element-name name="ISINDEX"/>
-    <element-name name="HR"/>
-    <element-name name="TABLE"/>
-    <element-name name="FIELDSET"/>
-    <element-name name="ADDRESS"/>
-  </or-group>
-</exclusions>
-</element>
-
-<attlist name="DIR">
-<attdecl>
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  compact     (compact)      #I

<TRUNCATED>


[11/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Lists.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Lists.js b/experiments/editorFramework/src/Layer0_Javascript/Lists.js
deleted file mode 100644
index a3a9772..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Lists.js
+++ /dev/null
@@ -1,553 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Lists_increaseIndent;
-var Lists_decreaseIndent;
-var Lists_clearList;
-var Lists_setUnorderedList;
-var Lists_setOrderedList;
-
-(function() {
-
-    // private
-    function findLIElements(range)
-    {
-        var listItems = new Array();
-
-        var node = range.start.node;
-        while (node != null) {
-
-            addListItems(listItems,node);
-
-            if (node == range.end.node)
-                break;
-
-            node = nextNode(node);
-        }
-        return listItems;
-
-        function addListItems(array,node)
-        {
-            if (node == null)
-                return;
-
-            if (node._type == HTML_LI) {
-                if (!arrayContains(array,node))
-                    array.push(node);
-                return;
-            }
-
-            if (!isWhitespaceTextNode(node))
-                addListItems(array,node.parentNode);
-        }
-    }
-
-    // public
-    Lists_increaseIndent = function()
-    {
-        Selection_preferElementPositions();
-        Selection_preserveWhileExecuting(function() {
-            var range = Selection_get();
-            if (range == null)
-                return null;
-
-            // Determine the set of LI nodes that are part of the selection
-            // Note that these could be spread out all over the place, e.g. in different lists,
-            // some in table cells etc
-            var listItems = findLIElements(range);
-
-            // For each LI node that is not the first in the list, move it to the child list of
-            // its previous sibling (creating the child list if necessary)
-
-            for (var i = 0; i < listItems.length; i++) {
-                var li = listItems[i];
-                var prevLi = li.previousSibling;
-                while ((prevLi != null) && (prevLi._type != HTML_LI))
-                    prevLi = prevLi.previousSibling;
-                // We can only increase the indentation of the current list item C if there is
-                // another list item P immediately preceding C. In this case, C becomes a child of
-                // another list L, where L is inside P. L may already exist, or we may need to
-                // create it.
-                if (prevLi != null) {
-                    var prevList = lastDescendentList(prevLi);
-                    var childList = firstDescendentList(li);
-                    var childListContainer = null;
-                    if (childList != null) {
-                        // childList may be contained inside one or more wrapper elements, in which
-                        // case we set childListContainer to point to the wrapper element that is a
-                        // child of li. Otherwise childListContainer will just be childList.
-                        childListContainer = childList;
-                        while (childListContainer.parentNode != li)
-                            childListContainer = childListContainer.parentNode;
-                    }
-
-                    if (prevList != null) {
-                        DOM_appendChild(prevList,li);
-                        if (childList != null) {
-                            while (childList.firstChild != null)
-                                DOM_appendChild(prevList,childList.firstChild);
-                            DOM_deleteNode(childListContainer);
-                            // alert("Case 1: prevList and childList");
-                        }
-                        else {
-                            // alert("Case 2: prevList and no childList");
-                        }
-                    }
-                    else {
-                        var newList;
-                        if (childList != null) {
-                            // alert("Case 3: no prevList but childList");
-                            newList = childList;
-                            DOM_appendChild(prevLi,childListContainer);
-                        }
-                        else {
-                            // alert("Case 4: no prevList and no childList");
-                            if (li.parentNode._type == HTML_UL)
-                                newList = DOM_createElement(document,"UL");
-                            else
-                                newList = DOM_createElement(document,"OL");
-                            DOM_appendChild(prevLi,newList);
-                        }
-                        DOM_insertBefore(newList,li,newList.firstChild);
-                    }
-                }
-            }
-        });
-
-        function firstDescendentList(node)
-        {
-            while (true) {
-                var node = firstChildElement(node);
-                if (node == null)
-                    return null;
-                switch (node._type) {
-                case HTML_UL:
-                case HTML_OL:
-                    return node;
-                }
-            }
-        }
-
-        function lastDescendentList(node)
-        {
-            while (true) {
-                var node = lastChildElement(node);
-                if (node == null)
-                    return null;
-                switch (node._type) {
-                case HTML_UL:
-                case HTML_OL:
-                    return node;
-                }
-            }
-        }
-    }
-
-    // public
-    Lists_decreaseIndent = function()
-    {
-        Selection_preferElementPositions();
-        Selection_preserveWhileExecuting(function() {
-            var range = Selection_get();
-            if (range == null)
-                return null;
-
-            // Determine the set of LI nodes that are part of the selection
-            // Note that these could be spread out all over the place, e.g. in different lists,
-            // some in table cells etc
-            var listItems = findLIElements(range);
-
-            // Remove from consideration any list items that have an ancestor that is going to
-            // be moved
-            var i = 0;
-            var changed;
-            while (i < listItems.length) {
-                var node = listItems[i];
-
-                var ancestorToBeRemoved = false;
-                for (var ancestor = node.parentNode;
-                     ancestor != null;
-                     ancestor = ancestor.parentNode) {
-                    if (arrayContains(listItems,ancestor))
-                        ancestorToBeRemoved = true;
-                }
-
-                if (ancestorToBeRemoved)
-                    listItems.splice(i,1);
-                else
-                    i++;
-            }
-
-            function haveContentAfter(node)
-            {
-                for (node = node.nextSibling; node != null; node = node.nextSibling) {
-                    if (nodeHasContent(node))
-                        return true;
-                }
-                return false;
-            }
-
-            // For LI nodes that are in a top-level list, change them to regular paragraphs
-            // For LI nodes that are part of a nested list, move them to the parent (this requires
-            // splitting the child list in two)
-            for (var i = 0; i < listItems.length; i++) {
-                var liNode = listItems[i];
-                var listNode = liNode.parentNode;
-                var containerChild = findContainerChild(listNode);
-
-                if (haveContentAfter(liNode)) {
-                    var secondHalf;
-                    if (listNode._type == HTML_UL)
-                        secondHalf = DOM_createElement(document,"UL");
-                    else
-                        secondHalf = DOM_createElement(document,"OL");
-
-                    DOM_appendChild(liNode,secondHalf);
-
-                    var following = liNode.nextSibling;
-                    while (following != null) {
-                        var next = following.nextSibling;
-                        DOM_appendChild(secondHalf,following);
-                        following = next;
-                    }
-                }
-
-                DOM_insertBefore(containerChild.parentNode,liNode,containerChild.nextSibling);
-                if (!isListNode(liNode.parentNode)) {
-                    Hierarchy_avoidInlineChildren(liNode);
-                    DOM_removeNodeButKeepChildren(liNode);
-                }
-
-                if (!nodeHasContent(listNode))
-                    DOM_deleteNode(listNode);
-            }
-        });
-
-        function findContainerChild(node)
-        {
-            while (node.parentNode != null) {
-                if (isContainerNode(node.parentNode) && (node.parentNode._type != HTML_LI))
-                    return node;
-                node = node.parentNode;
-            }
-        }
-    }
-
-    // private
-    function getListOperationNodes(range)
-    {
-        var detail = Range_detail(range);
-        var dca = detail.commonAncestor;
-        var ds = detail.startAncestor;
-        var de = detail.endAncestor;
-
-        while (isInlineNode(dca)) {
-            ds = dca;
-            de = dca;
-            dca = dca.parentNode;
-        }
-
-        var nodes = new Array();
-        var nodeSet = new NodeSet();
-
-        if (dca._type == HTML_LI)
-            return [dca];
-
-        // If, after moving up the tree until dca is a container node, a single node is selected,
-        // check if it is wholly contained within a single list item. If so, select just that
-        // list item.
-        var isStartLI = ((ds != null) && (ds._type == HTML_LI));
-        var isEndLI = ((de != null) && (de._type == HTML_LI));
-        if (!isStartLI && !isEndLI) {
-            for (var ancestor = dca; ancestor.parentNode != null; ancestor = ancestor.parentNode) {
-                if (ancestor.parentNode._type == HTML_LI) {
-                    var firstElement = true;
-
-                    for (var p = ancestor.previousSibling; p != null; p = p.previousSibling) {
-                        if (p.nodeType == Node.ELEMENT_NODE) {
-                            firstElement = false;
-                            break;
-                        }
-                    }
-
-                    if (firstElement)
-                        return [ancestor.parentNode];
-                }
-            }
-        }
-
-        var end = (de == null) ? null : de.nextSibling;
-
-        for (var child = ds; child != end; child = child.nextSibling) {
-            switch (child._type) {
-            case HTML_UL:
-            case HTML_OL:
-                for (var gc = child.firstChild; gc != null; gc = gc.nextSibling) {
-                    if (!isWhitespaceTextNode(gc))
-                        addNode(gc);
-                }
-                break;
-            default:
-                if ((child._type == HTML_DIV) &&
-                     child.getAttribute("class") == Keys.SELECTION_HIGHLIGHT) {
-                    // skip
-                }
-                else if (!isWhitespaceTextNode(child)) {
-                    addNode(child);
-                }
-                break;
-            }
-        }
-        if ((nodes.length == 0) && isParagraphNode(dca))
-            nodes.push(dca);
-        return nodes;
-
-        function addNode(node)
-        {
-            while (isInlineNode(node) && node.parentNode != document.body)
-                node = node.parentNode;
-            if (!nodeSet.contains(node)) {
-                nodeSet.add(node);
-                nodes.push(node);
-            }
-        }
-    }
-
-    // public
-    Lists_clearList = function()
-    {
-        Selection_preferElementPositions();
-        Selection_preserveWhileExecuting(function() {
-            var range = Selection_get();
-            if (range == null)
-                return;
-            Range_ensureInlineNodesInParagraph(range);
-
-            var nodes = getListOperationNodes(range);
-
-            for (var i = 0; i < nodes.length; i++) {
-                var node = nodes[i];
-                if (node._type == HTML_LI) {
-                    var li = node;
-                    var list = li.parentNode;
-                    var insertionPoint = null;
-
-                    DOM_removeAdjacentWhitespace(li);
-
-                    if (li.previousSibling == null) {
-                        insertionPoint = list;
-                    }
-                    else if (li.nextSibling == null) {
-                        insertionPoint = list.nextSibling;
-                    }
-                    else {
-                        var secondList = DOM_shallowCopyElement(list);
-                        DOM_insertBefore(list.parentNode,secondList,list.nextSibling);
-                        while (li.nextSibling != null) {
-                            DOM_appendChild(secondList,li.nextSibling);
-                            DOM_removeAdjacentWhitespace(li);
-                        }
-
-                        insertionPoint = secondList;
-                    }
-
-                    var parent = null;
-                    var child = li.firstChild;
-                    while (child != null) {
-                        var next = child.nextSibling;
-                        if (isInlineNode(child) && !isWhitespaceTextNode(child)) {
-                            child = Hierarchy_wrapInlineNodesInParagraph(child);
-                            next = child.nextSibling;
-                        }
-                        child = next;
-                    }
-                    DOM_insertBefore(list.parentNode,li,insertionPoint);
-                    DOM_removeNodeButKeepChildren(li);
-
-                    if (list.firstChild == null)
-                        DOM_deleteNode(list);
-                }
-            }
-        });
-
-        var range = Selection_get();
-        if (range == null)
-            return;
-        if (Range_isEmpty(range) &&
-            (range.start.node.nodeType == Node.ELEMENT_NODE) &&
-            (isContainerNode(range.start.node))) {
-
-            var p = DOM_createElement(document,"P");
-
-            var next = range.start.node.childNodes[range.start.offset+1];
-            DOM_insertBefore(range.start.node,p,next);
-
-            Cursor_updateBRAtEndOfParagraph(p);
-            Selection_set(p,0,p,0);
-        }
-    }
-
-    // private
-    function setList(type)
-    {
-        var range = Selection_get();
-        if (range == null)
-            return;
-
-        var nodes = getListOperationNodes(range);
-
-        if (nodes.length == 0) {
-            var text;
-            if (range.start.node.nodeType == Node.TEXT_NODE) {
-                text = range.start.node;
-            }
-            else if (range.start.node.nodeType == Node.ELEMENT_NODE) {
-                text = DOM_createTextNode(document,"");
-                DOM_insertBefore(range.start.node,
-                                 text,
-                                 range.start.node[range.start.offset+1]);
-            }
-            nodes = [text];
-
-            var offset = DOM_nodeOffset(text);
-            Selection_set(text,0,text,0);
-            range = Selection_get();
-        }
-
-        Range_trackWhileExecuting(range,function () {
-            // Set list to UL or OL
-
-            for (var i = 0; i < nodes.length; i++) {
-                var node = nodes[i];
-                var next;
-                var prev;
-                var li = null;
-                var oldList = null;
-                var listInsertionPoint;
-
-                if ((node._type == HTML_LI) && (node.parentNode._type == type)) {
-                    // Already in the correct type of list; don't need to do anything
-                    continue;
-                }
-
-                if (node._type == HTML_LI) {
-                    li = node;
-                    var list = li.parentNode;
-
-                    DOM_removeAdjacentWhitespace(list);
-                    prev = list.previousSibling;
-                    next = list.nextSibling;
-
-
-                    DOM_removeAdjacentWhitespace(li);
-
-                    if (li.previousSibling == null) {
-                        listInsertionPoint = list;
-                        next = null;
-                    }
-                    else if (li.nextSibling == null) {
-                        listInsertionPoint = list.nextSibling;
-                        prev = null;
-                    }
-                    else {
-                        var secondList = DOM_shallowCopyElement(list);
-                        DOM_insertBefore(list.parentNode,secondList,list.nextSibling);
-                        while (li.nextSibling != null) {
-                            DOM_insertBefore(secondList,li.nextSibling,null);
-                            DOM_removeAdjacentWhitespace(li);
-                        }
-
-                        listInsertionPoint = secondList;
-
-                        prev = null;
-                        next = null;
-                    }
-
-                    node = list;
-                    oldList = list;
-                }
-                else {
-                    DOM_removeAdjacentWhitespace(node);
-                    prev = node.previousSibling;
-                    next = node.nextSibling;
-                    listInsertionPoint = node;
-                }
-
-                var list;
-                var itemInsertionPoint;
-
-                if ((prev != null) && (prev._type == type)) {
-                    list = prev;
-                    itemInsertionPoint = null;
-                }
-                else if ((next != null) && (next._type == type)) {
-                    list = next;
-                    itemInsertionPoint = list.firstChild;
-                }
-                else {
-                    if (type == HTML_UL)
-                        list = DOM_createElement(document,"UL");
-                    else
-                        list = DOM_createElement(document,"OL");
-                    DOM_insertBefore(node.parentNode,list,listInsertionPoint);
-                    itemInsertionPoint = null;
-                }
-
-                if (li != null) {
-                    DOM_insertBefore(list,li,itemInsertionPoint);
-                }
-                else {
-                    var li = DOM_createElement(document,"LI");
-                    DOM_insertBefore(list,li,itemInsertionPoint);
-                    DOM_insertBefore(li,node,null);
-                }
-
-
-                if ((oldList != null) && (oldList.firstChild == null))
-                    DOM_deleteNode(oldList);
-
-                // Merge with adjacent list
-                DOM_removeAdjacentWhitespace(list);
-                if ((list.nextSibling != null) && (list.nextSibling._type == type)) {
-                    var followingList = list.nextSibling;
-                    while (followingList.firstChild != null) {
-                        if (isWhitespaceTextNode(followingList.firstChild))
-                            DOM_deleteNode(followingList.firstChild);
-                        else
-                            DOM_insertBefore(list,followingList.firstChild,null);
-                    }
-                    DOM_deleteNode(followingList);
-                }
-            }
-        });
-        Range_ensureValidHierarchy(range);
-        Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
-    }
-
-    // public
-    Lists_setUnorderedList = function()
-    {
-        setList(HTML_UL);
-    }
-
-    // public
-    Lists_setOrderedList = function()
-    {
-        setList(HTML_OL);
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Main.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Main.js b/experiments/editorFramework/src/Layer0_Javascript/Main.js
deleted file mode 100644
index f123423..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Main.js
+++ /dev/null
@@ -1,393 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Main_getLanguage;
-var Main_setLanguage;
-var Main_setGenerator;
-var Main_isEmptyDocument;
-var Main_prepareForSave;
-var Main_getHTML;
-var Main_getErrorReportingInfo;
-var Main_removeUnsupportedInput;
-var Main_removeSpecial;
-var Main_execute;
-var Main_init;
-
-var Main_clientRectsBug;
-
-(function() {
-
-    // public
-    Main_getLanguage = function()
-    {
-        var lang = document.documentElement.getAttribute("lang");
-        if (lang != null)
-            lang = lang.replace(/-/g,"_");
-        return lang;
-    }
-
-    // public
-    Main_setLanguage = function(lang)
-    {
-        if ((lang == null) || (lang == "")) {
-            DOM_removeAttribute(document.documentElement,"lang");
-        }
-        else {
-            lang = lang.replace(/_/g,"-");
-            DOM_setAttribute(document.documentElement,"lang",lang);
-        }
-    }
-
-    // public
-    Main_removeUnsupportedInput = function()
-    {
-        recurse(document.documentElement);
-
-        function recurse(node)
-        {
-            // Delete comments and processing instructions
-            if ((node.nodeType != Node.TEXT_NODE) &&
-                (node.nodeType != Node.ELEMENT_NODE)) {
-                DOM_deleteNode(node);
-            }
-            else {
-                var next;
-                for (var child = node.firstChild; child != null; child = next) {
-                    next = child.nextSibling;
-                    recurse(child);
-                }
-            }
-        }
-    }
-
-    // private
-    function addMetaCharset()
-    {
-        var head = DOM_documentHead(document);
-        var next;
-        for (var child = head.firstChild; child != null; child = next) {
-            next = child.nextSibling;
-            if ((child._type == HTML_META) && (child.hasAttribute("charset"))) {
-                DOM_deleteNode(child);
-            }
-            else if ((child._type == HTML_META) && child.hasAttribute("http-equiv") &&
-                     (child.getAttribute("http-equiv").toLowerCase() == "content-type")) {
-                DOM_deleteNode(child);
-            }
-        }
-
-        var meta = DOM_createElement(document,"META");
-        DOM_setAttribute(meta,"charset","utf-8");
-        DOM_insertBefore(head,meta,head.firstChild);
-    }
-
-    // public
-    Main_setGenerator = function(generator)
-    {
-        return UndoManager_disableWhileExecuting(function() {
-            var head = DOM_documentHead(document);
-            for (var child = head.firstChild; child != null; child = child.nextSibling) {
-                if ((child._type == HTML_META) &&
-                    child.hasAttribute("name") &&
-                    (child.getAttribute("name").toLowerCase() == "generator")) {
-                    var origGenerator = DOM_getAttribute(child,"content");
-                    DOM_setAttribute(child,"content",generator);
-
-                    if (origGenerator == null)
-                        return "";
-                    else
-                        return origGenerator;
-                }
-            }
-
-            var meta = DOM_createElement(document,"META");
-            DOM_setAttribute(meta,"name","generator");
-            DOM_setAttribute(meta,"content",generator);
-            DOM_insertBefore(head,meta,head.firstChild);
-
-            return "";
-        });
-    }
-
-    // public
-    Main_isEmptyDocument = function()
-    {
-        return !nodeHasContent(document.body);
-    }
-
-    // public
-    Main_prepareForSave = function()
-    {
-        // Force any end-of-group actions to be performed
-        UndoManager_newGroup();
-        return true;
-    }
-
-    // public
-    Main_getHTML = function()
-    {
-        return document.documentElement.outerHTML;
-    }
-
-    // public
-    Main_getErrorReportingInfo = function()
-    {
-        if (document.documentElement == null)
-            return "(document.documentElement is null)";
-        try {
-            var html = htmlWithSelection();
-            cleanse(html);
-            return html.outerHTML;
-        }
-        catch (e) {
-            try {
-                var html = DOM_cloneNode(document.documentElement,true);
-                cleanse(html);
-                return html.outerHTML+"\n[Error getting selection: "+e+"]";
-            }
-            catch (e2) {
-                return "[Error getting HTML: "+e2+"]";
-            }
-        }
-
-        function cleanse(node)
-        {
-            switch (node._type) {
-            case HTML_TEXT:
-            case HTML_COMMENT:
-                DOM_setNodeValue(node,cleanseString(node.nodeValue));
-                break;
-            case HTML_STYLE:
-            case HTML_SCRIPT:
-                return;
-            default:
-                if (node.nodeType == Node.ELEMENT_NODE) {
-                    cleanseAttribute(node,"original");
-                    if (node.hasAttribute("href") && !node.getAttribute("href").match(/^#/))
-                        cleanseAttribute(node,"href");
-                    for (var child = node.firstChild; child != null; child = child.nextSibling)
-                        cleanse(child);
-                }
-                break;
-            }
-        }
-
-        function cleanseAttribute(node,name)
-        {
-            if (node.hasAttribute(name)) {
-                var value = node.getAttribute(name);
-                value = cleanseString(value);
-                DOM_setAttribute(node,name,value);
-            }
-        }
-
-        function cleanseString(str)
-        {
-            return str.replace(/[^\s\.\@\^]/g,"X");
-        }
-
-        function htmlWithSelection()
-        {
-            var selectionRange = Selection_get();
-            if (selectionRange != null) {
-                selectionRange = Range_forwards(selectionRange);
-                var startSave = new Object();
-                var endSave = new Object();
-
-                var html = null;
-
-                Range_trackWhileExecuting(selectionRange,function() {
-                    // We use the strings @@^^ and ^^@@ to represent the selection
-                    // start and end, respectively. The reason for this is that after we have
-                    // cloned the tree, all text will be removed. We keeping the @ and ^
-                    // characters so we have some way to identifiy the selection markers;
-                    // leaving these in is not going to reveal any confidential information.
-
-                    addPositionMarker(selectionRange.end,"^^@@",endSave);
-                    addPositionMarker(selectionRange.start,"@@^^",startSave);
-
-                    html = DOM_cloneNode(document.documentElement,true);
-
-                    removePositionMarker(selectionRange.start,startSave);
-                    removePositionMarker(selectionRange.end,endSave);
-                });
-
-                return html;
-            }
-            else {
-                return DOM_cloneNode(document.documentElement,true);
-            }
-        }
-
-        function addPositionMarker(pos,name,save)
-        {
-            var node = pos.node;
-            var offset = pos.offset;
-            if (node.nodeType == Node.ELEMENT_NODE) {
-                save.tempNode = DOM_createTextNode(document,name);
-                DOM_insertBefore(node,save.tempNode,node.childNodes[offset]);
-            }
-            else if (node.nodeType == Node.TEXT_NODE) {
-                save.originalNodeValue = node.nodeValue;
-                node.nodeValue = node.nodeValue.slice(0,offset) + name + node.nodeValue.slice(offset);
-            }
-        }
-
-        function removePositionMarker(pos,save)
-        {
-            var node = pos.node;
-            var offset = pos.offset;
-            if (pos.node.nodeType == Node.ELEMENT_NODE) {
-                DOM_deleteNode(save.tempNode);
-            }
-            else if (pos.node.nodeType == Node.TEXT_NODE) {
-                node.nodeValue = save.originalNodeValue;
-            }
-        }
-    }
-
-    // public
-    Main_removeSpecial = function(node)
-    {
-        // We process the children first, so that if there are any nested removable elements (e.g.
-        // a selection span inside of an autocorrect span), all levels of nesting are taken care of
-        var next;
-        for (var child = node.firstChild; child != null; child = next) {
-            next = child.nextSibling;
-            Main_removeSpecial(child);
-        }
-
-        var cssClass = null;
-        if ((node.nodeType == Node.ELEMENT_NODE) && node.hasAttribute("class"))
-            cssClass = node.getAttribute("class");
-
-        if ((cssClass == Keys.HEADING_NUMBER) ||
-            (cssClass == Keys.FIGURE_NUMBER) ||
-            (cssClass == Keys.TABLE_NUMBER) ||
-            (cssClass == Keys.AUTOCORRECT_CLASS) ||
-            (cssClass == Keys.SELECTION_CLASS) ||
-            (cssClass == Keys.SELECTION_HIGHLIGHT)) {
-            DOM_removeNodeButKeepChildren(node);
-        }
-        else if ((node._type == HTML_META) &&
-                 node.hasAttribute("name") &&
-                 (node.getAttribute("name").toLowerCase() == "viewport")) {
-            DOM_deleteNode(node);
-        }
-        else if (node._type == HTML_LINK) {
-            if ((node.getAttribute("rel") == "stylesheet") &&
-                (node.getAttribute("href") == Styles_getBuiltinCSSURL())) {
-                DOM_deleteNode(node);
-            }
-        }
-    }
-
-    function simplifyStackString(e)
-    {
-        if (e.stack == null)
-            return "";
-        var lines = e.stack.toString().split(/\n/);
-        for (var i = 0; i < lines.length; i++) {
-            var nameMatch = lines[i].match(/^(.*)@/);
-            var name = (nameMatch != null) ? nameMatch[1] : "(anonymous function)";
-            var locMatch = lines[i].match(/:([0-9]+:[0-9]+)$/);
-            var loc = (locMatch != null) ? locMatch[1] : "?";
-            lines[i] = "stack["+(lines.length-i-1)+"] = "+name+"@"+loc;
-        }
-        return lines.join("\n");
-    }
-
-    // public
-    Main_execute = function(fun)
-    {
-        try {
-            var res = fun();
-            PostponedActions_perform();
-            return res;
-        }
-        catch (e) {
-            var message = (e.message != null) ? e.message : e.toString();
-            var stack = simplifyStackString(e);
-            Editor_error(message+"\n"+stack);
-        }
-    }
-
-    function fixEmptyBody()
-    {
-        for (var child = document.body.firstChild; child != null; child = child.nextSibling) {
-            if (nodeHasContent(child))
-                return;
-        }
-
-        for (var child = document.body.firstChild; child != null; child = child.nextSibling) {
-            if (child._type == HTML_P) {
-                Cursor_updateBRAtEndOfParagraph(child);
-                return;
-            }
-        }
-
-        var p = DOM_createElement(document,"P");
-        var br = DOM_createElement(document,"BR");
-        DOM_appendChild(p,br);
-        DOM_appendChild(document.body,p);
-    }
-
-    // public
-    Main_init = function(width,textScale,cssURL,clientRectsBug)
-    {
-        try {
-            Main_clientRectsBug = clientRectsBug;
-            if (document.documentElement == null)
-                throw new Error("document.documentElement is null");
-            if (document.body == null)
-                throw new Error("document.body is null");
-            var timing = new TimingInfo();
-            timing.start();
-            DOM_assignNodeIds(document);
-            timing.addEntry("DOM_assignNodeIds");
-            Main_removeUnsupportedInput();
-            timing.addEntry("Main_removeUnsupportedInput");
-            addMetaCharset();
-            timing.addEntry("addMetaCharset");
-            fixEmptyBody();
-            timing.addEntry("fixEmptyBody");
-            Outline_init();
-            timing.addEntry("Outline_init");
-            Styles_init(cssURL);
-            timing.addEntry("Styles_init");
-            Viewport_init(width,textScale);
-            timing.addEntry("Viewport_init");
-            AutoCorrect_init();
-            timing.addEntry("AutoCorrect_init");
-
-            PostponedActions_perform();
-            timing.addEntry("PostponedActions_perform");
-            Cursor_moveToStartOfDocument();
-            timing.addEntry("Cursor_moveToStartOfDocument");
-
-            UndoManager_clear();
-            timing.addEntry("UndoManager_clear");
-//            timing.print();
-
-            return true;
-        }
-        catch (e) {
-            return e.toString();
-        }
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Metadata.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Metadata.js b/experiments/editorFramework/src/Layer0_Javascript/Metadata.js
deleted file mode 100644
index fce4cca..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Metadata.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Metadata_getMetadata;
-var Metadata_setMetadata;
-
-(function() {
-
-    Metadata_getMetadata = function()
-    {
-        return {};
-    }
-
-    Metadata_setMetadata = function(metadata)
-    {
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/NodeSet.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/NodeSet.js b/experiments/editorFramework/src/Layer0_Javascript/NodeSet.js
deleted file mode 100644
index 77b7600..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/NodeSet.js
+++ /dev/null
@@ -1,201 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-function NodeSet()
-{
-    this.members = new Object();
-}
-
-NodeSet.prototype.add = function(node)
-{
-    if (node._nodeId == null)
-        throw new Error("NodeSet.add: node "+node.nodeName+" has no _nodeId property");
-    this.members[node._nodeId] = node;
-}
-
-NodeSet.prototype.remove = function(node)
-{
-    if (node._nodeId == null)
-        throw new Error("NodeSet.remove: node "+node.nodeName+" has no _nodeId property");
-    delete this.members[node._nodeId];
-}
-
-NodeSet.prototype.contains = function(node)
-{
-    if (node._nodeId == null)
-        throw new Error("NodeSet.contains: node "+node.nodeName+" has no _nodeId property");
-    return (this.members[node._nodeId] != null);
-}
-
-NodeSet.prototype.toArray = function()
-{
-    var result = new Array();
-    for (var id in this.members)
-        result.push(members[id]);
-    return result;
-}
-
-NodeSet.prototype.forEach = function(fun)
-{
-    var ids = Object.getOwnPropertyNames(this.members);
-    var set = this;
-    ids.forEach(function(id) { fun(set.members[id]); });
-}
-
-NodeSet.prototype.ancestor = function()
-{
-    var result = new NodeSet();
-    this.forEach(function (node) {
-        for (var p = node.parentNode; p != null; p = p.parentNode)
-            result.add(p);
-    });
-    return result;
-}
-
-NodeSet.prototype.ancestorOrSelf = function()
-{
-    var result = new NodeSet();
-    this.forEach(function (node) {
-        for (var p = node; p != null; p = p.parentNode)
-            result.add(p);
-    });
-    return result;
-}
-
-NodeSet.prototype.descendant = function()
-{
-    var result = new NodeSet();
-    this.forEach(function (node) {
-        recurse(node);
-    });
-    return result;
-
-    function recurse(node)
-    {
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            result.add(child);
-            recurse(child);
-        }
-    }
-}
-
-NodeSet.prototype.descendantOrSelf = function()
-{
-    var result = new NodeSet();
-    this.forEach(function (node) {
-        recurse(node);
-    });
-    return result;
-
-    function recurse(node)
-    {
-        result.add(node);
-        for (var child = node.firstChild; child != null; child = child.nextSibling)
-            recurse(child);
-    }
-}
-
-NodeSet.prototype.union = function(other)
-{
-    var result = new NodeSet();
-    this.forEach(function (node) { result.add(node); });
-    other.forEach(function (node) { result.add(node); });
-    return result;
-}
-
-NodeSet.prototype.intersection = function(other)
-{
-    var result = new NodeSet();
-    this.forEach(function (node) { if (other.contains(node)) { result.add(node); } });
-    return result;
-}
-
-NodeSet.fromArray = function(array)
-{
-    var set = new NodeSet();
-    array.forEach(function(node) { set.add(node); });
-    return set;
-}
-
-
-function NodeMap()
-{
-    this.keys = new Object();
-    this.values = new Object();
-}
-
-NodeMap.prototype.clear = function()
-{
-    this.keys = new Object();
-    this.values = new Object();
-}
-
-NodeMap.prototype.get = function(key)
-{
-    if (key._nodeId == null)
-        throw new Error("NodeMap.get: key "+key.keyName+" has no _nodeId property");
-    return this.values[key._nodeId];
-}
-
-NodeMap.prototype.put = function(key,value)
-{
-    if (key._nodeId == null)
-        throw new Error("NodeMap.add: key "+key.keyName+" has no _nodeId property");
-    this.keys[key._nodeId] = key;
-    this.values[key._nodeId] = value;
-}
-
-NodeMap.prototype.remove = function(key)
-{
-    if (key._nodeId == null)
-        throw new Error("NodeMap.remove: key "+key.keyName+" has no _nodeId property");
-    delete this.keys[key._nodeId];
-    delete this.values[key._nodeId];
-}
-
-NodeMap.prototype.containsKey = function(key)
-{
-    if (key._nodeId == null)
-        throw new Error("NodeMap.contains: key "+key.keyName+" has no _nodeId property");
-    return (this.values[key._nodeId] != null);
-}
-
-NodeMap.prototype.getKeys = function()
-{
-    var ids = Object.getOwnPropertyNames(this.values);
-    var result = new Array(ids.length);
-    for (var i = 0; i < ids.length; i++)
-        result[i] = this.keys[ids[i]];
-    return result;
-}
-
-NodeMap.prototype.forEach = function(fun)
-{
-    var ids = Object.getOwnPropertyNames(this.values);
-    var map = this;
-    ids.forEach(function(id) { fun(map.keys[id],map.values[id]); });
-}
-
-NodeMap.fromArray = function(array,fun)
-{
-    var map = new NodeMap();
-    if (fun != null)
-        array.forEach(function(node) { map.put(node,fun(node)); });
-    else
-        array.forEach(function(node) { map.put(node,null); });
-    return map;
-};



[24/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Formatting.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Formatting.js b/experiments/editorFramework/src/Javascript_Layer_0/Formatting.js
new file mode 100644
index 0000000..51bc5d3
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Formatting.js
@@ -0,0 +1,1281 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Formatting_splitTextBefore;
+var Formatting_splitTextAfter;
+var Formatting_movePreceding;
+var Formatting_moveFollowing;
+var Formatting_splitAroundSelection;
+var Formatting_mergeUpwards;
+var Formatting_mergeWithNeighbours;
+var Formatting_paragraphTextUpToPosition;
+var Formatting_getAllNodeProperties;
+var Formatting_getFormatting;
+var Formatting_pushDownInlineProperties;
+var Formatting_applyFormattingChanges;
+var Formatting_formatInlineNode;
+
+var Formatting_MERGEABLE_INLINE;
+var Formatting_MERGEABLE_BLOCK;
+var Formatting_MERGEABLE_BLOCK_AND_INLINE;
+
+(function() {
+
+    // Some properties in CSS, such as 'margin', 'border', and 'padding', are shorthands which
+    // set multiple, more fine-grained properties. The CSS spec outlines what these are - e.g.
+    // an assignment to the 'margin' property is considered a simultaneous assignment to
+    // 'margin-left', 'margin-right', 'margin-top', and 'margin-bottom' properties.
+
+    // However, Firefox contains a bug (https://bugzilla.mozilla.org/show_bug.cgi?id=241234),
+    // which has gone unfixed for more than six years, whereby it actually sets different
+    // properties for *-left and *-right, which are reflected when examining the style property
+    // of an element. Additionally, it also gives an error if you try to set these, so if you simply
+    // get all the style properties and try to set them again it won't work.
+
+    // To get around this problem, we record the following set of replacements. When getting the
+    // style properties of an element, we replace any properties with the names given below with
+    // their corresponding spec name. A null entry means that property should be ignored altogether.
+
+    // You should always use getStyleProperties() instead of accessing element.style directly.
+
+    var CSS_PROPERTY_REPLACEMENTS = {
+        "margin-left-value": "margin-left",
+        "margin-left-ltr-source": null,
+        "margin-left-rtl-source": null,
+        "margin-right-value": "margin-right",
+        "margin-right-ltr-source": null,
+        "margin-right-rtl-source": null,
+        "padding-left-value": "padding-left",
+        "padding-left-ltr-source": null,
+        "padding-left-rtl-source": null,
+        "padding-right-value": "padding-right",
+        "padding-right-ltr-source": null,
+        "padding-right-rtl-source": null,
+        "border-right-width-value": "border-right-width",
+        "border-right-width-ltr-source": null,
+        "border-right-width-rtl-source": null,
+        "border-left-width-value": "border-left-width",
+        "border-left-width-ltr-source": null,
+        "border-left-width-rtl-source": null,
+        "border-right-color-value": "border-right-color",
+        "border-right-color-ltr-source": null,
+        "border-right-color-rtl-source": null,
+        "border-left-color-value": "border-left-color",
+        "border-left-color-ltr-source": null,
+        "border-left-color-rtl-source": null,
+        "border-right-style-value": "border-right-style",
+        "border-right-style-ltr-source": null,
+        "border-right-style-rtl-source": null,
+        "border-left-style-value": "border-left-style",
+        "border-left-style-ltr-source": null,
+        "border-left-style-rtl-source": null,
+    };
+
+    // private
+    function getStyleProperties(element,dontReplace)
+    {
+        var properties = new Object();
+
+        for (var i = 0; i < element.style.length; i++) {
+            var name = element.style[i];
+            var value = element.style.getPropertyValue(name);
+
+            var replacement;
+            if (dontReplace) {
+                replacement = name;
+            }
+            else {
+                replacement = CSS_PROPERTY_REPLACEMENTS[name];
+                if (typeof(replacement) == "undefined")
+                    replacement = name;
+            }
+
+            if (replacement != null)
+                properties[replacement] = value;
+        }
+        return properties;
+    }
+
+    // public (for testing purposes only)
+    Formatting_splitAroundSelection = function(range,allowDirectInline)
+    {
+        Range_trackWhileExecuting(range,function() {
+            if (!allowDirectInline)
+                Range_ensureInlineNodesInParagraph(range);
+            Range_ensureValidHierarchy(range);
+
+            if ((range.start.node.nodeType == Node.TEXT_NODE) &&
+                (range.start.offset > 0)) {
+                Formatting_splitTextBefore(range.start);
+                if (range.end.node == range.start.node)
+                    range.end.offset -= range.start.offset;
+                range.start.offset = 0;
+            }
+            else if (range.start.node.nodeType == Node.ELEMENT_NODE) {
+                Formatting_movePreceding(range.start,isBlockOrNoteNode);
+            }
+            else {
+                Formatting_movePreceding(new Position(range.start.node.parentNode,
+                                                      DOM_nodeOffset(range.start.node)),
+                                         isBlockOrNoteNode);
+            }
+
+            // Save the start and end position of the range. The mutation listeners will move it
+            // when the following node is moved, which we don't actually want in this case.
+            var startNode = range.start.node;
+            var startOffset = range.start.offset;
+            var endNode = range.end.node;
+            var endOffset = range.end.offset;
+
+            if ((range.end.node.nodeType == Node.TEXT_NODE) &&
+                (range.end.offset < range.end.node.nodeValue.length)) {
+                Formatting_splitTextAfter(range.end);
+            }
+            else if (range.end.node.nodeType == Node.ELEMENT_NODE) {
+                Formatting_moveFollowing(range.end,isBlockOrNoteNode);
+            }
+            else {
+                Formatting_moveFollowing(new Position(range.end.node.parentNode,
+                                                      DOM_nodeOffset(range.end.node)+1),
+                                         isBlockOrNoteNode);
+            }
+
+            range.start.node = startNode;
+            range.start.offset = startOffset;
+            range.end.node = endNode;
+            range.end.offset = endOffset;
+        });
+    }
+
+    // public
+    Formatting_mergeUpwards = function(node,whiteList)
+    {
+        while ((node != null) && whiteList[node._type]) {
+            var parent = node.parentNode;
+            Formatting_mergeWithNeighbours(node,whiteList,true);
+            node = parent;
+        }
+    }
+
+    function isDiscardable(node)
+    {
+        if (node.nodeType != Node.ELEMENT_NODE)
+            return false;
+
+        if (!isInlineNode(node))
+            return false;
+
+        if (isOpaqueNode(node))
+            return false;
+
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            if (!isDiscardable(child))
+                return false;
+        }
+
+        return true;
+    }
+
+    // public (for use by tests)
+    Formatting_mergeWithNeighbours = function(node,whiteList,trim)
+    {
+        var parent = node.parentNode;
+        if (parent == null)
+            return;
+
+        var start = node;
+        var end = node;
+
+        while ((start.previousSibling != null) &&
+               DOM_nodesMergeable(start.previousSibling,start,whiteList))
+            start = start.previousSibling;
+
+        while ((end.nextSibling != null) &&
+               DOM_nodesMergeable(end,end.nextSibling,whiteList))
+            end = end.nextSibling;
+
+        if (trim) {
+            while ((start.previousSibling != null) && isDiscardable(start.previousSibling))
+                DOM_deleteNode(start.previousSibling);
+            while ((end.nextSibling != null) && isDiscardable(end.nextSibling))
+                DOM_deleteNode(end.nextSibling);
+        }
+
+        if (start != end) {
+            var lastMerge;
+            do {
+                lastMerge = (start.nextSibling == end);
+
+                var lastChild = null;
+                if (start.nodeType == Node.ELEMENT_NODE)
+                    lastChild = start.lastChild;
+
+                DOM_mergeWithNextSibling(start,whiteList);
+
+                if (lastChild != null)
+                    Formatting_mergeWithNeighbours(lastChild,whiteList);
+            } while (!lastMerge);
+        }
+    }
+
+    // private
+    function mergeRange(range,whiteList)
+    {
+        var nodes = Range_getAllNodes(range);
+        for (var i = 0; i < nodes.length; i++) {
+            var next;
+            for (var p = nodes[i]; p != null; p = next) {
+                next = p.parentNode;
+                Formatting_mergeWithNeighbours(p,whiteList);
+            }
+        }
+    }
+
+    // public (called from cursor.js)
+    Formatting_splitTextBefore = function(pos,parentCheckFn,force)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if (parentCheckFn == null)
+            parentCheckFn = isBlockNode;
+
+        if (force || (offset > 0)) {
+            var before = DOM_createTextNode(document,"");
+            DOM_insertBefore(node.parentNode,before,node);
+            DOM_moveCharacters(node,0,offset,before,0,false,true);
+            Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)),
+                                     parentCheckFn,force);
+            return new Position(before,before.nodeValue.length);
+        }
+        else {
+            Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)),
+                                     parentCheckFn,force);
+            return pos;
+        }
+    }
+
+    // public
+    Formatting_splitTextAfter = function(pos,parentCheckFn,force)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if (parentCheckFn == null)
+            parentCheckFn = isBlockNode;
+
+        if (force || (offset < pos.node.nodeValue.length)) {
+            var after = DOM_createTextNode(document,"");
+            DOM_insertBefore(node.parentNode,after,node.nextSibling);
+            DOM_moveCharacters(node,offset,node.nodeValue.length,after,0,true,false);
+            Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1),
+                                     parentCheckFn,force);
+            return new Position(after,0);
+        }
+        else {
+            Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1),
+                                     parentCheckFn,force);
+            return pos;
+        }
+    }
+
+    // FIXME: movePreceding and moveNext could possibly be optimised by passing in a (parent,child)
+    // pair instead of (node,offset), i.e. parent is the same as node, but rather than passing the
+    // index of a child, we pass the child itself (or null if the offset is equal to
+    // childNodes.length)
+    // public
+    Formatting_movePreceding = function(pos,parentCheckFn,force)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if (parentCheckFn(node) || (node == document.body))
+            return new Position(node,offset);
+
+        var toMove = new Array();
+        var justWhitespace = true;
+        var result = new Position(node,offset);
+        for (var i = 0; i < offset; i++) {
+            if (!isWhitespaceTextNode(node.childNodes[i]))
+                justWhitespace = false;
+            toMove.push(node.childNodes[i]);
+        }
+
+        if ((toMove.length > 0) || force) {
+            if (justWhitespace && !force) {
+                for (var i = 0; i < toMove.length; i++)
+                    DOM_insertBefore(node.parentNode,toMove[i],node);
+            }
+            else {
+                var copy = DOM_shallowCopyElement(node);
+                DOM_insertBefore(node.parentNode,copy,node);
+
+                for (var i = 0; i < toMove.length; i++)
+                    DOM_insertBefore(copy,toMove[i],null);
+                result = new Position(copy,copy.childNodes.length);
+            }
+        }
+
+        Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)),
+                                 parentCheckFn,force);
+        return result;
+    }
+
+    // public
+    Formatting_moveFollowing = function(pos,parentCheckFn,force)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if (parentCheckFn(node) || (node == document.body))
+            return new Position(node,offset);
+
+        var toMove = new Array();
+        var justWhitespace = true;
+        var result =  new Position(node,offset);
+        for (var i = offset; i < node.childNodes.length; i++) {
+            if (!isWhitespaceTextNode(node.childNodes[i]))
+                justWhitespace = false;
+            toMove.push(node.childNodes[i]);
+        }
+
+        if ((toMove.length > 0) || force) {
+            if (justWhitespace && !force) {
+                for (var i = 0; i < toMove.length; i++)
+                    DOM_insertBefore(node.parentNode,toMove[i],node.nextSibling);
+            }
+            else {
+                var copy = DOM_shallowCopyElement(node);
+                DOM_insertBefore(node.parentNode,copy,node.nextSibling);
+
+                for (var i = 0; i < toMove.length; i++)
+                    DOM_insertBefore(copy,toMove[i],null);
+                result = new Position(copy,0);
+            }
+        }
+
+        Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1),
+                                 parentCheckFn,force);
+        return result;
+    }
+
+    // public
+    Formatting_paragraphTextUpToPosition = function(pos)
+    {
+        if (pos.node.nodeType == Node.TEXT_NODE) {
+            return stringToStartOfParagraph(pos.node,pos.offset);
+        }
+        else {
+            return stringToStartOfParagraph(Position_closestActualNode(pos),0);
+        }
+
+        function stringToStartOfParagraph(node,offset)
+        {
+            var start = node;
+            var components = new Array();
+            while (isInlineNode(node)) {
+                if (node.nodeType == Node.TEXT_NODE) {
+                    if (node == start)
+                        components.push(node.nodeValue.slice(0,offset));
+                    else
+                        components.push(node.nodeValue);
+                }
+
+                if (node.previousSibling != null) {
+                    node = node.previousSibling;
+                    while (isInlineNode(node) && (node.lastChild != null))
+                        node = node.lastChild;
+                }
+                else {
+                    node = node.parentNode;
+                }
+            }
+            return components.reverse().join("");
+        }
+    }
+
+    // public
+    Formatting_getFormatting = function()
+    {
+        // FIXME: implement a more efficient version of this algorithm which avoids duplicate checks
+
+        var range = Selection_get();
+        if (range == null)
+            return {};
+
+        Range_assertValid(range,"Selection");
+
+        var outermost = Range_getOutermostNodes(range,true);
+
+        var leafNodes = new Array();
+        for (var i = 0; i < outermost.length; i++) {
+            findLeafNodes(outermost[i],leafNodes);
+        }
+        var empty = Range_isEmpty(range);
+
+        var commonProperties = null;
+        for (var i = 0; i < leafNodes.length; i++) {
+            if (!isWhitespaceTextNode(leafNodes[i]) || empty) {
+                var leafNodeProperties = Formatting_getAllNodeProperties(leafNodes[i]);
+                if (leafNodeProperties["-uxwrite-paragraph-style"] == null)
+                    leafNodeProperties["-uxwrite-paragraph-style"] = Keys.NONE_STYLE;
+                if (commonProperties == null)
+                    commonProperties = leafNodeProperties;
+                else
+                    commonProperties = intersection(commonProperties,leafNodeProperties);
+            }
+        }
+
+        if (commonProperties == null)
+            commonProperties = {"-uxwrite-paragraph-style": Keys.NONE_STYLE};
+
+        for (var i = 0; i < leafNodes.length; i++) {
+            var leaf = leafNodes[i];
+            if (leaf._type == HTML_LI) {
+                switch (leaf.parentNode._type) {
+                case HTML_UL:
+                    commonProperties["-uxwrite-in-ul"] = "true";
+                    break;
+                case HTML_OL:
+                    commonProperties["-uxwrite-in-ol"] = "true";
+                    break;
+                }
+            }
+            else {
+                for (var ancestor = leaf;
+                     ancestor.parentNode != null;
+                     ancestor = ancestor.parentNode) {
+
+                    if (ancestor.parentNode._type == HTML_LI) {
+                        var havePrev = false;
+                        for (var c = ancestor.previousSibling; c != null; c = c.previousSibling) {
+                            if (!isWhitespaceTextNode(c)) {
+                                havePrev = true;
+                                break;
+                            }
+                        }
+                        if (!havePrev) {
+                            var listNode = ancestor.parentNode.parentNode;
+                            switch (listNode._type) {
+                            case HTML_UL:
+                                commonProperties["-uxwrite-in-ul"] = "true";
+                                break;
+                            case HTML_OL:
+                                commonProperties["-uxwrite-in-ol"] = "true";
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        getFlags(range.start,commonProperties);
+
+        return commonProperties;
+
+        function getFlags(pos,commonProperties)
+        {
+            var strBeforeCursor = Formatting_paragraphTextUpToPosition(pos);
+
+            if (isWhitespaceString(strBeforeCursor)) {
+                var firstInParagraph = true;
+                for (var p = pos.node; isInlineNode(p); p = p.parentNode) {
+                    if (p.previousSibling != null)
+                        firstInParagraph = false;
+                }
+                if (firstInParagraph)
+                    commonProperties["-uxwrite-shift"] = "true";
+            }
+            if (strBeforeCursor.match(/\.\s*$/))
+                commonProperties["-uxwrite-shift"] = "true";
+            if (strBeforeCursor.match(/\([^\)]*$/))
+                commonProperties["-uxwrite-in-brackets"] = "true";
+            if (strBeforeCursor.match(/\u201c[^\u201d]*$/))
+                commonProperties["-uxwrite-in-quotes"] = "true";
+        }
+
+        function intersection(a,b)
+        {
+            var result = new Object();
+            for (var name in a) {
+                if (a[name] == b[name])
+                    result[name] = a[name];
+            }
+            return result;
+        }
+
+        function findLeafNodes(node,result)
+        {
+            if (node.firstChild == null) {
+                result.push(node);
+            }
+            else {
+                for (var child = node.firstChild; child != null; child = child.nextSibling)
+                    findLeafNodes(child,result);
+            }
+        }
+    }
+
+    // public
+    Formatting_getAllNodeProperties = function(node)
+    {
+        if (node == null)
+            throw new Error("Node is not in tree");
+
+        if (node == node.ownerDocument.body)
+            return new Object();
+
+        var properties = Formatting_getAllNodeProperties(node.parentNode);
+
+        if (node.nodeType == Node.ELEMENT_NODE) {
+            // Note: Style names corresponding to element names must be in lowercase, because
+            // canonicaliseSelector() in Styles.js always converts selectors to lowercase.
+            if (node.hasAttribute("STYLE")) {
+                var nodeProperties = getStyleProperties(node);
+                for (var name in nodeProperties)
+                    properties[name] = nodeProperties[name];
+            }
+
+            var type = node._type;
+            switch (type) {
+            case HTML_B:
+                properties["font-weight"] = "bold";
+                break;
+            case HTML_I:
+                properties["font-style"] = "italic";
+                break;
+            case HTML_U: {
+                var components = [];
+                if (properties["text-decoration"] != null) {
+                    var components = properties["text-decoration"].toLowerCase().split(/\s+/);
+                    if (components.indexOf("underline") == -1)
+                        properties["text-decoration"] += " underline";
+                }
+                else {
+                    properties["text-decoration"] = "underline";
+                }
+                break;
+            }
+//            case HTML_TT:
+//                properties["-uxwrite-in-tt"] = "true";
+//                break;
+            case HTML_IMG:
+                properties["-uxwrite-in-image"] = "true";
+                break;
+            case HTML_FIGURE:
+                properties["-uxwrite-in-figure"] = "true";
+                break;
+            case HTML_TABLE:
+                properties["-uxwrite-in-table"] = "true";
+                break;
+            case HTML_A:
+                if (node.hasAttribute("href")) {
+                    var href = node.getAttribute("href");
+                    if (href.charAt(0) == "#")
+                        properties["-uxwrite-in-reference"] = "true";
+                    else
+                        properties["-uxwrite-in-link"] = "true";
+                }
+                break;
+            case HTML_NAV: {
+                var className = DOM_getAttribute(node,"class");
+                if ((className == Keys.SECTION_TOC) ||
+                    (className == Keys.FIGURE_TOC) ||
+                    (className == Keys.TABLE_TOC))
+                    properties["-uxwrite-in-toc"] = "true";
+                break;
+            }
+            default:
+                if (PARAGRAPH_ELEMENTS[type]) {
+                    var name = node.nodeName.toLowerCase();
+                    var selector;
+                    if (node.hasAttribute("class"))
+                        selector = name + "." + node.getAttribute("class");
+                    else
+                        selector = name;
+                    properties["-uxwrite-paragraph-style"] = selector;
+                }
+                break;
+            }
+
+            if (OUTLINE_TITLE_ELEMENTS[type] && node.hasAttribute("id"))
+                properties["-uxwrite-in-item-title"] = node.getAttribute("id");
+        }
+
+        return properties;
+    }
+
+    var PARAGRAPH_PROPERTIES = {
+        "margin-left": true,
+        "margin-right": true,
+        "margin-top": true,
+        "margin-bottom": true,
+
+        "padding-left": true,
+        "padding-right": true,
+        "padding-top": true,
+        "padding-bottom": true,
+
+        "border-left-width": true,
+        "border-right-width": true,
+        "border-top-width": true,
+        "border-bottom-width": true,
+
+        "border-left-style": true,
+        "border-right-style": true,
+        "border-top-style": true,
+        "border-bottom-style": true,
+
+        "border-left-color": true,
+        "border-right-color": true,
+        "border-top-color": true,
+        "border-bottom-color": true,
+
+        "border-top-left-radius": true,
+        "border-top-right-radius": true,
+        "border-bottom-left-radius": true,
+        "border-bottom-right-radius": true,
+
+        "text-align": true,
+        "text-indent": true,
+        "line-height": true,
+        "display": true,
+
+        "width": true,
+        "height": true,
+    };
+
+    var SPECIAL_PROPERTIES = {
+        "-webkit-text-size-adjust": true, // set on HTML element for text scaling purposes
+    };
+
+    function isParagraphProperty(name)
+    {
+        return PARAGRAPH_PROPERTIES[name];
+    }
+
+    function isInlineProperty(name)
+    {
+        return !PARAGRAPH_PROPERTIES[name] && !SPECIAL_PROPERTIES[name];
+    }
+
+    // private
+    function putDirectInlineChildrenInParagraphs(parent)
+    {
+        var inlineChildren = new Array();
+        for (var child = parent.firstChild; child != null; child = child.nextSibling)
+            if (isInlineNode(child))
+                inlineChildren.push(child);
+        for (var i = 0; i < inlineChildren.length; i++) {
+            if (inlineChildren[i].parentNode == parent) { // may already have been moved
+                if (!isWhitespaceTextNode(inlineChildren[i]))
+                    Hierarchy_wrapInlineNodesInParagraph(inlineChildren[i]);
+            }
+        }
+    }
+
+    // private
+    function getParagraphs(nodes)
+    {
+        var array = new Array();
+        var set = new NodeSet();
+        for (var i = 0; i < nodes.length; i++) {
+            for (var anc = nodes[i].parentNode; anc != null; anc = anc.parentNode) {
+                if (anc._type == HTML_LI)
+                    putDirectInlineChildrenInParagraphs(anc);
+            }
+            recurse(nodes[i]);
+        }
+
+        var remove = new NodeSet();
+        for (var i = 0; i < array.length; i++) {
+            for (var anc = array[i].parentNode; anc != null; anc = anc.parentNode)
+                remove.add(anc);
+        }
+
+        var modified = new Array();
+        for (var i = 0; i < array.length; i++) {
+            if (!remove.contains(array[i]))
+                modified.push(array[i]);
+        }
+
+        return modified;
+
+        function recurse(node)
+        {
+            if (node._type == HTML_LI)
+                putDirectInlineChildrenInParagraphs(node);
+            if (node.firstChild == null) {
+                // Leaf node
+                for (var anc = node; anc != null; anc = anc.parentNode)
+                    if (isParagraphNode(anc)) {
+                        add(anc);
+                    }
+            }
+            else {
+                for (var child = node.firstChild; child != null; child = child.nextSibling)
+                    recurse(child);
+            }
+        }
+
+        function add(node)
+        {
+            if (!set.contains(node)) {
+                array.push(node);
+                set.add(node);
+            }
+        }
+    }
+
+    // private
+    function setParagraphStyle(paragraph,selector)
+    {
+        var wasHeading = isHeadingNode(paragraph);
+        DOM_removeAttribute(paragraph,"class");
+        if (selector == "") {
+            if (paragraph._type != HTML_P)
+                paragraph = DOM_replaceElement(paragraph,"P");
+        }
+        else {
+            var elementClassRegex = /^([a-zA-Z0-9]+)?(\.(.+))?$/;
+            var result = elementClassRegex.exec(selector);
+            if ((result != null) && (result.length == 4)) {
+                var elementName = result[1];
+                var className = result[3];
+
+                if (elementName == null)
+                    elementName = "P";
+                else
+                    elementName = elementName.toUpperCase();
+
+                var elementType = ElementTypes[elementName];
+
+                if (!PARAGRAPH_ELEMENTS[elementType])
+                    return; // better than throwing an exception
+
+                if (paragraph._type != elementType)
+                    paragraph = DOM_replaceElement(paragraph,elementName);
+
+                if (className != null)
+                    DOM_setAttribute(paragraph,"class",className);
+                else
+                    DOM_removeAttribute(paragraph,"class");
+            }
+        }
+
+        // FIXME: this will need to change when we add Word/ODF support, because the ids serve
+        // a purpose other than simply being targets for references
+        var isHeading = isHeadingNode(paragraph);
+        if (wasHeading && !isHeading)
+            DOM_removeAttribute(paragraph,"id");
+    }
+
+    // public
+    Formatting_pushDownInlineProperties = function(outermost)
+    {
+        for (var i = 0; i < outermost.length; i++)
+            outermost[i] = pushDownInlinePropertiesSingle(outermost[i]);
+    }
+
+    // private
+    function pushDownInlinePropertiesSingle(target)
+    {
+        recurse(target.parentNode);
+        return target;
+
+        function recurse(node)
+        {
+            if (node.nodeType == Node.DOCUMENT_NODE)
+                return;
+
+            if (node.parentNode != null)
+                recurse(node.parentNode);
+
+            var inlineProperties = new Object();
+            var nodeProperties = getStyleProperties(node);
+            for (var name in nodeProperties) {
+                if (isInlineProperty(name)) {
+                    inlineProperties[name] = nodeProperties[name];
+                }
+            }
+
+            var remove = new Object();
+            for (var name in inlineProperties)
+                remove[name] = null;
+            DOM_setStyleProperties(node,remove);
+
+            var type = node._type;
+            switch (type) {
+            case HTML_B:
+                inlineProperties["font-weight"] = "bold";
+                break;
+            case HTML_I:
+                inlineProperties["font-style"] = "italic";
+                break;
+            case HTML_U:
+                if (inlineProperties["text-decoration"] != null)
+                    inlineProperties["text-decoration"] += " underline";
+                else
+                    inlineProperties["text-decoration"] = "underline";
+                break;
+            }
+
+            var special = extractSpecial(inlineProperties);
+            var count = Object.getOwnPropertyNames(inlineProperties).length;
+
+            if ((count > 0) || special.bold || special.italic || special.underline) {
+
+                var next;
+                for (var child = node.firstChild; child != null; child = next) {
+                    next = child.nextSibling;
+
+                    if (isWhitespaceTextNode(child))
+                        continue;
+
+                    var replacement = applyInlineFormatting(child,inlineProperties,special);
+                    if (target == child)
+                        target = replacement;
+                }
+            }
+
+            if (node.hasAttribute("style") && (node.style.length == 0))
+                DOM_removeAttribute(node,"style");
+
+            switch (type) {
+            case HTML_B:
+            case HTML_I:
+            case HTML_U:
+                DOM_removeNodeButKeepChildren(node);
+                break;
+            }
+        }
+    }
+
+    // private
+    function wrapInline(node,elementName)
+    {
+        if (!isInlineNode(node) || isAbstractSpan(node)) {
+            var next;
+            for (var child = node.firstChild; child != null; child = next) {
+                next = child.nextSibling;
+                wrapInline(child,elementName);
+            }
+            return node;
+        }
+        else {
+            return DOM_wrapNode(node,elementName);
+        }
+    }
+
+    // private
+    function applyInlineFormatting(target,inlineProperties,special,applyToWhitespace)
+    {
+        if (!applyToWhitespace && isWhitespaceTextNode(target))
+            return;
+
+        if (special.underline)
+            target = wrapInline(target,"U");
+        if (special.italic)
+            target = wrapInline(target,"I");
+        if (special.bold)
+            target = wrapInline(target,"B");
+
+        var isbiu = false;
+        switch (target._type) {
+        case HTML_B:
+        case HTML_I:
+        case HTML_U:
+            isbiu = true;
+            break;
+        }
+
+        if ((Object.getOwnPropertyNames(inlineProperties).length > 0) &&
+            ((target.nodeType != Node.ELEMENT_NODE) ||
+             isbiu || isSpecialSpan(target))) {
+            target = wrapInline(target,"SPAN");
+        }
+
+
+        var propertiesToSet = new Object();
+        for (var name in inlineProperties) {
+            var existing = target.style.getPropertyValue(name);
+            if ((existing == null) || (existing == ""))
+                propertiesToSet[name] = inlineProperties[name];
+        }
+        DOM_setStyleProperties(target,propertiesToSet);
+
+        return target;
+    }
+
+    // private
+    function extractSpecial(properties)
+    {
+        var special = { bold: null, italic: null, underline: null };
+        var fontWeight = properties["font-weight"];
+        var fontStyle = properties["font-style"];
+        var textDecoration = properties["text-decoration"];
+
+        if (typeof(fontWeight) != "undefined") {
+            special.bold = false;
+            if ((fontWeight != null) &&
+                (fontWeight.toLowerCase() == "bold")) {
+                special.bold = true;
+                delete properties["font-weight"];
+            }
+        }
+
+        if (typeof(fontStyle) != "undefined") {
+            special.italic = false;
+            if ((fontStyle != null) &&
+                (fontStyle.toLowerCase() == "italic")) {
+                special.italic = true;
+                delete properties["font-style"];
+            }
+        }
+
+        if (typeof(textDecoration) != "undefined") {
+            special.underline = false;
+            if (textDecoration != null) {
+                var values = textDecoration.toLowerCase().split(/\s+/);
+                var index;
+                while ((index = values.indexOf("underline")) >= 0) {
+                    values.splice(index,1);
+                    special.underline = true;
+                }
+                if (values.length == 0)
+                    delete properties["text-decoration"];
+                else
+                    properties["text-decoration"] = values.join(" ");
+            }
+        }
+        return special;
+    }
+
+    // private
+    function removeProperties(outermost,properties)
+    {
+        properties = clone(properties);
+        var special = extractSpecial(properties);
+        var remaining = new Array();
+        for (var i = 0; i < outermost.length; i++) {
+            removePropertiesSingle(outermost[i],properties,special,remaining);
+        }
+        return remaining;
+    }
+
+    // private
+    function getOutermostParagraphs(paragraphs)
+    {
+        var all = new NodeSet();
+        for (var i = 0; i < paragraphs.length; i++)
+            all.add(paragraphs[i]);
+
+        var result = new Array();
+        for (var i = 0; i < paragraphs.length; i++) {
+            var haveAncestor = false;
+            for (var p = paragraphs[i].parentNode; p != null; p = p.parentNode) {
+                if (all.contains(p)) {
+                    haveAncestor = true;
+                    break;
+                }
+            }
+            if (!haveAncestor)
+                result.push(paragraphs[i]);
+        }
+        return result;
+    }
+
+    // private
+    function removePropertiesSingle(node,properties,special,remaining)
+    {
+        if ((node.nodeType == Node.ELEMENT_NODE) && (node.hasAttribute("style"))) {
+            var remove = new Object();
+            for (var name in properties)
+                remove[name] = null;
+            DOM_setStyleProperties(node,remove);
+        }
+
+        var willRemove = false;
+        switch (node._type) {
+        case HTML_B:
+            willRemove = (special.bold != null);
+            break;
+        case HTML_I:
+            willRemove = (special.italic != null);
+            break;
+        case HTML_U:
+            willRemove = (special.underline != null);
+            break;
+        case HTML_SPAN:
+            willRemove = (!node.hasAttribute("style") && !isSpecialSpan(node));
+            break;
+        }
+
+        var childRemaining = willRemove ? remaining : null;
+
+        var next;
+        for (var child = node.firstChild; child != null; child = next) {
+            next = child.nextSibling;
+            removePropertiesSingle(child,properties,special,childRemaining);
+        }
+
+        if (willRemove)
+            DOM_removeNodeButKeepChildren(node);
+        else if (remaining != null)
+            remaining.push(node);
+    }
+
+    function isSpecialSpan(span)
+    {
+        if (span._type == HTML_SPAN) {
+            if (span.hasAttribute(Keys.ABSTRACT_ELEMENT))
+                return true;
+            var className = DOM_getStringAttribute(span,"class");
+            if (className.indexOf(Keys.UXWRITE_PREFIX) == 0)
+                return true;
+            if ((className == "footnote") || (className == "endnote"))
+                return true;
+        }
+        return false;
+    }
+
+    // private
+    function containsOnlyWhitespace(ancestor)
+    {
+        for (child = ancestor.firstChild; child != null; child = child.nextSibling) {
+            if (!isWhitespaceTextNode(child))
+                return false;
+        }
+        return true;
+    }
+
+    // public
+    Formatting_applyFormattingChanges = function(style,properties)
+    {
+        debug("JS: applyFormattingChanges: style = "+JSON.stringify(style));
+        if (properties != null) {
+            var names = Object.getOwnPropertyNames(properties).sort();
+            for (var i = 0; i < names.length; i++) {
+                debug("    "+names[i]+" = "+properties[names[i]]);
+            }
+        }
+        UndoManager_newGroup("Apply formatting changes");
+
+        if (properties == null)
+            properties = new Object();
+
+        if (style == Keys.NONE_STYLE)
+            style = null;
+
+        var paragraphProperties = new Object();
+        var inlineProperties = new Object();
+
+        for (var name in properties) {
+            if (isParagraphProperty(name))
+                paragraphProperties[name] = properties[name];
+            else if (isInlineProperty(name))
+                inlineProperties[name] = properties[name];
+        }
+
+        var selectionRange = Selection_get();
+        if (selectionRange == null)
+            return;
+
+        // If we're applying formatting properties to an empty selection, and the node of the
+        // selection start & end is an element, add an empty text node so that we have something
+        // to apply the formatting to.
+        if (Range_isEmpty(selectionRange) &&
+            (selectionRange.start.node.nodeType == Node.ELEMENT_NODE)) {
+            var node = selectionRange.start.node;
+            var offset = selectionRange.start.offset;
+            var text = DOM_createTextNode(document,"");
+            DOM_insertBefore(node,text,node.childNodes[offset]);
+            Selection_set(text,0,text,0);
+            selectionRange = Selection_get();
+        }
+
+        // If the cursor is in a container (such as BODY OR FIGCAPTION), and not inside a paragraph,
+        // put it in one so we can set a paragraph style
+
+        if ((style != null) && Range_isEmpty(selectionRange)) {
+            var node = Range_singleNode(selectionRange);
+            while (isInlineNode(node))
+                node = node.parentNode;
+            if (isContainerNode(node) && containsOnlyInlineChildren(node)) {
+                var p = DOM_createElement(document,"P");
+                DOM_appendChild(node,p);
+                while (node.firstChild != p)
+                    DOM_appendChild(p,node.firstChild);
+                Cursor_updateBRAtEndOfParagraph(p);
+            }
+        }
+
+
+        var range = new Range(selectionRange.start.node,selectionRange.start.offset,
+                              selectionRange.end.node,selectionRange.end.offset);
+        var positions = [selectionRange.start,selectionRange.end,
+                         range.start,range.end];
+
+        var allowDirectInline = (style == null);
+        Position_trackWhileExecuting(positions,function() {
+            Formatting_splitAroundSelection(range,allowDirectInline);
+            Range_expand(range);
+            if (!allowDirectInline)
+                Range_ensureInlineNodesInParagraph(range);
+            Range_ensureValidHierarchy(range);
+            Range_expand(range);
+            var outermost = Range_getOutermostNodes(range);
+            var target = null;
+
+            var paragraphs;
+            if (outermost.length > 0)
+                paragraphs = getParagraphs(outermost);
+            else
+                paragraphs = getParagraphs([Range_singleNode(range)]);
+
+            // Push down inline properties
+            Formatting_pushDownInlineProperties(outermost);
+
+            outermost = removeProperties(outermost,inlineProperties);
+
+            // Set properties on inline nodes
+            for (var i = 0; i < outermost.length; i++) {
+                var existing = Formatting_getAllNodeProperties(outermost[i]);
+                var toSet = new Object();
+                for (var name in inlineProperties) {
+                    if ((inlineProperties[name] != null) &&
+                        (existing[name] != inlineProperties[name])) {
+                        toSet[name] = inlineProperties[name];
+                    }
+                }
+
+                var special = extractSpecial(toSet);
+                var applyToWhitespace = (outermost.length == 1);
+                applyInlineFormatting(outermost[i],toSet,special,applyToWhitespace);
+            }
+
+            // Remove properties from paragraph nodes
+            paragraphs = removeProperties(paragraphs,paragraphProperties,{});
+
+            // Set properties on paragraph nodes
+            var paragraphPropertiesToSet = new Object();
+            for (var name in paragraphProperties) {
+                if (paragraphProperties[name] != null)
+                    paragraphPropertiesToSet[name] = paragraphProperties[name];
+            }
+
+            var outermostParagraphs = getOutermostParagraphs(paragraphs);
+            for (var i = 0; i < outermostParagraphs.length; i++)
+                DOM_setStyleProperties(outermostParagraphs[i],paragraphPropertiesToSet);
+
+            // Set style on paragraph nodes
+            if (style != null) {
+                for (var i = 0; i < paragraphs.length; i++) {
+                    setParagraphStyle(paragraphs[i],style);
+                }
+            }
+
+            mergeRange(range,Formatting_MERGEABLE_INLINE);
+
+            if (target != null) {
+                for (var p = target; p != null; p = next) {
+                    next = p.parentNode;
+                    Formatting_mergeWithNeighbours(p,Formatting_MERGEABLE_INLINE);
+                }
+            }
+        });
+
+        // The current cursor position may no longer be valid, e.g. if a heading span was inserted
+        // and the cursor is at a position that is now immediately before the span.
+        var start = Position_closestMatchForwards(selectionRange.start,Position_okForInsertion);
+        var end = Position_closestMatchBackwards(selectionRange.end,Position_okForInsertion);
+        var tempRange = new Range(start.node,start.offset,end.node,end.offset);
+        tempRange = Range_forwards(tempRange);
+        Range_ensureValidHierarchy(tempRange);
+        start = tempRange.start;
+        end = tempRange.end;
+        Selection_set(start.node,start.offset,end.node,end.offset);
+
+        function containsOnlyInlineChildren(node)
+        {
+            for (var child = node.firstChild; child != null; child = child.nextSibling) {
+                if (!isInlineNode(child))
+                    return false;
+            }
+            return true;
+        }
+    }
+
+    Formatting_formatInlineNode = function(node,properties)
+    {
+        properties = clone(properties);
+        var special = extractSpecial(properties);
+        return applyInlineFormatting(node,properties,special,true);
+    }
+
+    Formatting_MERGEABLE_INLINE = new Array(HTML_COUNT);
+
+    Formatting_MERGEABLE_INLINE[HTML_TEXT] = true;
+
+    Formatting_MERGEABLE_INLINE[HTML_SPAN] = true;
+    Formatting_MERGEABLE_INLINE[HTML_A] = true;
+    Formatting_MERGEABLE_INLINE[HTML_Q] = true;
+
+    // HTML 4.01 Section 9.2.1: Phrase elements
+    Formatting_MERGEABLE_INLINE[HTML_EM] = true;
+    Formatting_MERGEABLE_INLINE[HTML_STRONG] = true;
+    Formatting_MERGEABLE_INLINE[HTML_DFN] = true;
+    Formatting_MERGEABLE_INLINE[HTML_CODE] = true;
+    Formatting_MERGEABLE_INLINE[HTML_SAMP] = true;
+    Formatting_MERGEABLE_INLINE[HTML_KBD] = true;
+    Formatting_MERGEABLE_INLINE[HTML_VAR] = true;
+    Formatting_MERGEABLE_INLINE[HTML_CITE] = true;
+    Formatting_MERGEABLE_INLINE[HTML_ABBR] = true;
+
+    // HTML 4.01 Section 9.2.3: Subscripts and superscripts
+    Formatting_MERGEABLE_INLINE[HTML_SUB] = true;
+    Formatting_MERGEABLE_INLINE[HTML_SUP] = true;
+
+    // HTML 4.01 Section 15.2.1: Font style elements
+    Formatting_MERGEABLE_INLINE[HTML_I] = true;
+    Formatting_MERGEABLE_INLINE[HTML_B] = true;
+    Formatting_MERGEABLE_INLINE[HTML_SMALL] = true;
+    Formatting_MERGEABLE_INLINE[HTML_S] = true;
+    Formatting_MERGEABLE_INLINE[HTML_U] = true;
+
+    Formatting_MERGEABLE_BLOCK = new Array(HTML_COUNT);
+
+    Formatting_MERGEABLE_BLOCK[HTML_P] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_H1] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_H2] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_H3] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_H4] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_H5] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_H6] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_DIV] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_PRE] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_BLOCKQUOTE] = true;
+
+    Formatting_MERGEABLE_BLOCK[HTML_UL] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_OL] = true;
+    Formatting_MERGEABLE_BLOCK[HTML_LI] = true;
+
+    Formatting_MERGEABLE_BLOCK_AND_INLINE = new Array(HTML_COUNT);
+    for (var i = 0; i < HTML_COUNT; i++) {
+        if (Formatting_MERGEABLE_INLINE[i] || Formatting_MERGEABLE_BLOCK[i])
+            Formatting_MERGEABLE_BLOCK_AND_INLINE[i] = true;
+        Formatting_MERGEABLE_BLOCK_AND_INLINE["force"] = true;
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Hierarchy.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Hierarchy.js b/experiments/editorFramework/src/Javascript_Layer_0/Hierarchy.js
new file mode 100644
index 0000000..07c0526
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Hierarchy.js
@@ -0,0 +1,284 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Hierarchy_ensureValidHierarchy;
+var Hierarchy_ensureInlineNodesInParagraph;
+var Hierarchy_wrapInlineNodesInParagraph;
+var Hierarchy_avoidInlineChildren;
+
+(function() {
+
+    // private
+    function wrapInlineChildren(first,last,ancestors)
+    {
+        var haveNonWhitespace = false;
+        for (var node = first; node != last.nextSibling; node = node.nextSibling) {
+            if (!isWhitespaceTextNode(node))
+                haveNonWhitespace = true;
+        }
+        if (!haveNonWhitespace)
+            return false;
+
+        var parentNode = first.parentNode;
+        var nextSibling = first;
+        for (var i = ancestors.length-1; i >= 0; i--) {
+            var ancestorCopy = DOM_shallowCopyElement(ancestors[i]);
+            DOM_insertBefore(parentNode,ancestorCopy,nextSibling);
+            parentNode = ancestorCopy;
+            nextSibling = null;
+
+            var node = first;
+            while (true) {
+                var next = node.nextSibling;
+                DOM_insertBefore(parentNode,node,null);
+                if (node == last)
+                    break;
+                node = next;
+            }
+        }
+    }
+
+    // private
+    function wrapInlineChildrenInAncestors(node,ancestors)
+    {
+        var firstInline = null;
+        var lastInline = null;
+
+        var child = node.firstChild;
+        while (true) {
+            var next = (child != null) ? child.nextSibling : null;
+            if ((child == null) || !isInlineNode(child)) {
+
+                if ((firstInline != null) && (lastInline != null)) {
+                    wrapInlineChildren(firstInline,lastInline,ancestors);
+                }
+                firstInline = null;
+                lastInline = null;
+                if (child != null)
+                    wrapInlineChildrenInAncestors(child,ancestors);
+            }
+            else {
+                if (firstInline == null)
+                    firstInline = child;
+                lastInline = child;
+            }
+            if (child == null)
+                break;
+            child = next;
+        }
+    }
+
+    function checkInvalidNesting(node)
+    {
+        var parent = node.parentNode;
+        if ((parent._type == HTML_DIV) &&
+            (DOM_getAttribute(parent,"class") == Keys.SELECTION_CLASS)) {
+            parent = parent.parentNode;
+        }
+
+        var invalidNesting = !isContainerNode(parent);
+        switch (parent._type) {
+        case HTML_DIV:
+            if (isParagraphNode(node) || isListNode(node))
+                invalidNesting = false; // this case is ok
+            break;
+        case HTML_CAPTION:
+        case HTML_FIGCAPTION:
+        case HTML_TABLE:
+        case HTML_FIGURE:
+            switch (node._type) {
+            case HTML_FIGURE:
+            case HTML_TABLE:
+            case HTML_H1:
+            case HTML_H2:
+            case HTML_H3:
+            case HTML_H4:
+            case HTML_H5:
+            case HTML_H6:
+                return true;
+            }
+            break;
+        }
+
+        return invalidNesting;
+    }
+
+    function checkInvalidHeadingNesting(node)
+    {
+        switch (node._type) {
+        case HTML_H1:
+        case HTML_H2:
+        case HTML_H3:
+        case HTML_H4:
+        case HTML_H5:
+        case HTML_H6:
+            switch (node.parentNode._type) {
+            case HTML_BODY:
+            case HTML_NAV:
+            case HTML_DIV:
+                return false;
+            default:
+                return true;
+            }
+            break;
+        default:
+            return false;
+        }
+    }
+
+    function nodeHasSignificantChildren(node)
+    {
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            if (!isWhitespaceTextNode(child))
+                return true;
+        }
+        return false;
+    }
+
+    // Enforce the restriction that any path from the root to a given node must be of the form
+    //    container+ paragraph inline
+    // or container+ paragraph
+    // or container+
+    // public
+    Hierarchy_ensureValidHierarchy = function(node,recursive,allowDirectInline)
+    {
+        var count = 0;
+        while ((node != null) && (node.parentNode != null) && (node != document.body)) {
+            count++;
+            if (count > 200)
+                throw new Error("too many iterations");
+
+            if (checkInvalidHeadingNesting(node)) {
+                var offset = DOM_nodeOffset(node);
+                var parent = node.parentNode;
+                Formatting_moveFollowing(new Position(node.parentNode,offset+1),
+                                         function() { return false; });
+                DOM_insertBefore(node.parentNode.parentNode,
+                                 node,
+                                 node.parentNode.nextSibling);
+
+                while ((parent != document.body) && !nodeHasSignificantChildren(parent)) {
+                    var grandParent = parent.parentNode;
+                    DOM_deleteNode(parent);
+                    parent = grandParent;
+                }
+
+                continue;
+            }
+            else if (isContainerNode(node) || isParagraphNode(node)) {
+                var invalidNesting = checkInvalidNesting(node);
+                if (invalidNesting) {
+                    var ancestors = new Array();
+                    var child = node;
+                    while (!isContainerNode(child.parentNode)) {
+                        if (isInlineNode(child.parentNode)) {
+                            var keep = false;
+                            if (child.parentNode._type == HTML_SPAN) {
+                                for (var i = 0; i < child.attributes.length; i++) {
+                                    var attr = child.attributes[i];
+                                    if (attr.nodeName.toUpperCase() != "ID")
+                                        keep = true;
+                                }
+                                if (keep)
+                                    ancestors.push(child.parentNode);
+                            }
+                            else {
+                                ancestors.push(child.parentNode);
+                            }
+                        }
+                        child = child.parentNode;
+                    }
+
+                    while (checkInvalidNesting(node)) {
+                        var offset = DOM_nodeOffset(node);
+                        var parent = node.parentNode;
+                        Formatting_moveFollowing(new Position(node.parentNode,offset+1),
+                                                 isContainerNode);
+                        DOM_insertBefore(node.parentNode.parentNode,
+                                         node,
+                                         node.parentNode.nextSibling);
+                        if (!nodeHasSignificantChildren(parent))
+                            DOM_deleteNode(parent);
+
+                    }
+                    wrapInlineChildrenInAncestors(node,ancestors);
+                }
+            }
+
+            node = node.parentNode;
+        }
+    }
+
+    Hierarchy_ensureInlineNodesInParagraph = function(node,weak)
+    {
+        var count = 0;
+        while ((node != null) && (node.parentNode != null) && (node != document.body)) {
+            count++;
+            if (count > 200)
+                throw new Error("too many iterations");
+            if (isInlineNode(node) &&
+                isContainerNode(node.parentNode) && (node.parentNode._type != HTML_LI) &&
+                (!weak || !isTableCell(node.parentNode)) &&
+                !isWhitespaceTextNode(node)) {
+                Hierarchy_wrapInlineNodesInParagraph(node);
+                return;
+            }
+            node = node.parentNode;
+        }
+    }
+
+    // public
+    Hierarchy_wrapInlineNodesInParagraph = function(node)
+    {
+        var start = node;
+        var end = node;
+
+        while ((start.previousSibling != null) && isInlineNode(start.previousSibling))
+            start = start.previousSibling;
+        while ((end.nextSibling != null) && isInlineNode(end.nextSibling))
+            end = end.nextSibling;
+
+        return DOM_wrapSiblings(start,end,"P");
+    }
+
+    Hierarchy_avoidInlineChildren = function(parent)
+    {
+        var child = parent.firstChild;
+
+        while (child != null) {
+            if (isInlineNode(child)) {
+                var start = child;
+                var end = child;
+                var haveContent = nodeHasContent(end);
+                while ((end.nextSibling != null) && isInlineNode(end.nextSibling)) {
+                    end = end.nextSibling;
+                    if (nodeHasContent(end))
+                        haveContent = true;
+                }
+                child = DOM_wrapSiblings(start,end,"P");
+                var next = child.nextSibling;
+                if (!nodeHasContent(child))
+                    DOM_deleteNode(child);
+                child = next;
+            }
+            else {
+                child = child.nextSibling;
+            }
+        }
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Input.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Input.js b/experiments/editorFramework/src/Javascript_Layer_0/Input.js
new file mode 100644
index 0000000..db8cb99
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Input.js
@@ -0,0 +1,746 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Input_removePosition;
+var Input_addPosition;
+var Input_getPosition;
+var Input_textInRange;
+var Input_replaceRange;
+var Input_selectedTextRange;
+var Input_setSelectedTextRange;
+var Input_markedTextRange;
+var Input_setMarkedText;
+var Input_unmarkText;
+var Input_forwardSelectionAffinity;
+var Input_setForwardSelectionAffinity;
+var Input_positionFromPositionOffset;
+var Input_positionFromPositionInDirectionOffset;
+var Input_comparePositionToPosition;
+var Input_offsetFromPositionToPosition;
+var Input_positionWithinRangeFarthestInDirection;
+var Input_characterRangeByExtendingPositionInDirection;
+var Input_firstRectForRange;
+var Input_caretRectForPosition;
+var Input_closestPositionToPoint;
+var Input_closestPositionToPointWithinRange;
+var Input_characterRangeAtPoint;
+var Input_positionWithinRangeAtCharacterOffset;
+var Input_characterOffsetOfPositionWithinRange;
+
+var Input_isAtWordBoundary;
+var Input_isAtParagraphBoundary;
+var Input_isPositionAtBoundaryGranularityInDirection;
+var Input_isPositionWithinTextUnitInDirection;
+var Input_toWordBoundary;
+var Input_toParagraphBoundary;
+var Input_toLineBoundary;
+var Input_positionFromPositionToBoundaryInDirection;
+var Input_rangeEnclosingPositionWithGranularityInDirection;
+
+// FIXME: ensure updateFormatting() is called after any cursor/selection changes
+// FIXME: test capitalisation of on-screen keyboard at start of sentence
+
+(function() {
+
+    //function idebug(str)
+    //{
+    //    debug(str);
+    //}
+
+    var forwardSelection = true;
+    var positions = new Object();
+    var BaseIdNull = 0;
+    var BaseIdDocumentStart = 1;
+    var BaseIdDocumentEnd = 2;
+    var BaseIdSelectionStart = 3;
+    var BaseIdSelectionEnd = 4;
+    var firstDynamicPosId = 5;
+    var nextPosId = firstDynamicPosId;
+
+    function addPosition(pos)
+    {
+        if (pos == null)
+            return 0;
+        var copy = new Position(pos.node,pos.offset);
+        copy.targetX = pos.targetX;
+        pos = copy;
+        pos.posId = nextPosId++;
+        positions[pos.posId] = pos;
+        Position_track(pos);
+        return pos.posId;
+    }
+
+    Input_addPosition = addPosition;
+
+    function getPosition(posId)
+    {
+        if (posId instanceof Position) // for tests
+            return posId;
+        if (posId < firstDynamicPosId) {
+            switch (posId) {
+            case BaseIdNull: {
+                return null;
+            }
+            case BaseIdDocumentStart: {
+                var pos = new Position(document.body,0);
+                pos = Position_closestMatchForwards(pos,Position_okForMovement);
+                return pos;
+            }
+            case BaseIdDocumentEnd: {
+                var pos = new Position(document.body,document.body.childNodes.length);
+                pos = Position_closestMatchBackwards(pos,Position_okForMovement);
+                return pos;
+            }
+            case BaseIdSelectionStart: {
+                var range = Selection_get();
+                return (range != null) ? range.start : null;
+            }
+            case BaseIdSelectionEnd: {
+                var range = Selection_get();
+                return (range != null) ? range.end : null;
+            }
+            default:
+                return null;
+            }
+        }
+        if (positions[posId] == null)
+            throw new Error("No position for pos id "+posId);
+        return positions[posId];
+    }
+
+    Input_getPosition = getPosition;
+
+    // void
+    Input_removePosition = function(posId)
+    {
+        //idebug("Input_removePosition("+posId+")");
+        var pos = positions[posId];
+        if (pos == null) {
+            throw new Error("no position for id "+posId);
+        }
+        Position_untrack(pos);
+        delete positions[posId];
+    }
+
+    // string
+    Input_textInRange = function(startId,startAdjust,endId,endAdjust)
+    {
+        var start = getPosition(startId);
+        var end = getPosition(endId);
+        start = positionRight(start,startAdjust);
+        end = positionRight(end,endAdjust);
+        if ((start == null) || (end == null))
+            return "";
+
+        var range = new Range(start.node,start.offset,end.node,end.offset);
+        var result = Range_getText(range);
+        //idebug("Input_textInRange("+startId+","+startAdjust+","+endId+","+endAdjust+") = "+
+        //       JSON.stringify(result));
+        return result;
+    }
+
+    // void
+    Input_replaceRange = function(startId,endId,text)
+    {
+        //idebug("Input_replaceRange("+startId+","+endId+","+JSON.stringify(text)+")");
+        var start = getPosition(startId);
+        var end = getPosition(endId);
+        if (start == null)
+            throw new Error("start is null");
+        if (end == null)
+            throw new Error("end is null");
+
+        var range = new Range(start.node,start.offset,end.node,end.offset);
+        Range_trackWhileExecuting(range,function() {
+            Selection_deleteRangeContents(range,true);
+        });
+        range.start = Position_preferTextPosition(range.start);
+        var node = range.start.node;
+        var offset = range.start.offset;
+
+        if (node.nodeType == Node.TEXT_NODE) {
+            DOM_insertCharacters(node,offset,text);
+            Cursor_set(node,offset+text.length);
+        }
+        else if (node.nodeType == Node.ELEMENT_NODE) {
+            var textNode = DOM_createTextNode(document,text);
+            DOM_insertBefore(node,textNode,node.childNodes[offset]);
+            Cursor_set(node,offset+1);
+        }
+    }
+
+    // { startId, endId }
+    Input_selectedTextRange = function()
+    {
+        var range = Selection_get();
+        if (range == null) {
+            //idebug("Input_selectedTextRange = null");
+            return null;
+        }
+        else {
+            var startId = addPosition(range.start);
+            var endId = addPosition(range.end);
+            //idebug("Input_selectedTextRange = "+startId+", "+endId);
+            return { startId: startId,
+                     endId: endId };
+        }
+    }
+
+    // void
+    Input_setSelectedTextRange = function(startId,endId)
+    {
+        //idebug("Input_setSelectedTextRange("+startId+","+endId+")");
+        var start = getPosition(startId);
+        var end = getPosition(endId);
+
+        var oldSelection = Selection_get();
+        var oldStart = (oldSelection != null) ? oldSelection.start : null;
+        var oldEnd = (oldSelection != null) ? oldSelection.end : null;
+
+        Selection_set(start.node,start.offset,end.node,end.offset);
+
+        // The positions may have changed as a result of spans being added/removed
+        var newRange = Selection_get();
+        start = newRange.start;
+        end = newRange.end;
+
+        if (Position_equal(start,end))
+            Cursor_ensurePositionVisible(end);
+        else if (Position_equal(oldStart,start) && !Position_equal(oldEnd,end))
+            Cursor_ensurePositionVisible(end);
+        else if (Position_equal(oldEnd,end) && !Position_equal(oldStart,start))
+            Cursor_ensurePositionVisible(start);
+    }
+
+    // { startId, endId }
+    Input_markedTextRange = function()
+    {
+        //idebug("Input_markedTextRange");
+        return null;
+    }
+
+    // void
+    Input_setMarkedText = function(text,startOffset,endOffset)
+    {
+        Selection_deleteContents(true);
+        var oldSel = Selection_get();
+        Range_trackWhileExecuting(oldSel,function() {
+            Cursor_insertCharacter(text,false,false,true);
+        });
+        var newSel = Selection_get();
+
+        Selection_set(oldSel.start.node,oldSel.start.offset,
+                      newSel.end.node,newSel.end.offset,false,true);
+    }
+
+    // void
+    Input_unmarkText = function()
+    {
+        var range = Selection_get();
+        Cursor_set(range.end.node,range.end.offset);
+        //idebug("Input_unmarkText");
+    }
+
+    // boolean
+    Input_forwardSelectionAffinity = function()
+    {
+        //idebug("Input_forwardSelectionAffinity");
+        return forwardSelection;
+    }
+
+    // void
+    Input_setForwardSelectionAffinity = function(value)
+    {
+        //idebug("Input_setForwardSelectionAffinity");
+        forwardSelection = value;
+    }
+
+    function positionRight(pos,offset)
+    {
+        if (offset > 0) {
+            for (; offset > 0; offset--) {
+                var next = Position_nextMatch(pos,Position_okForMovement);
+                if (next == null)
+                    return pos;
+                pos = next;
+            }
+        }
+        else {
+            for (; offset < 0; offset++) {
+                var prev = Position_prevMatch(pos,Position_okForMovement);
+                if (prev == null)
+                    return pos;
+                pos = prev;
+            }
+        }
+        return pos;
+    }
+
+    function positionDown(pos,offset)
+    {
+        if (offset > 0) {
+            for (; offset > 0; offset--) {
+                var below = Text_posBelow(pos);
+                if (below == null)
+                    return pos;
+                pos = below;
+            }
+        }
+        else {
+            for (; offset < 0; offset++) {
+                var above = Text_posAbove(pos);
+                if (above == null)
+                    return pos;
+                pos = above;
+            }
+        }
+        return pos;
+    }
+
+    // posId
+    Input_positionFromPositionOffset = function(posId,offset)
+    {
+        var pos = getPosition(posId);
+        var res = addPosition(positionRight(pos,offset));
+        //idebug("Input_positionFromPositionOffset("+posId+","+offset+") = "+res);
+        return res;
+    }
+
+    // posId
+    Input_positionFromPositionInDirectionOffset = function(posId,direction,offset)
+    {
+        //idebug("Input_positionFromPositionInDirectionOffset("+posId+","+direction+","+offset+")");
+        var pos = getPosition(posId);
+        if (direction == "left")
+            return addPosition(positionRight(pos,-offset));
+        else if (direction == "right")
+            return addPosition(positionRight(pos,offset));
+        else if (direction == "up")
+            return addPosition(positionDown(pos,-offset));
+        else if (direction == "down")
+            return addPosition(positionDown(pos,offset));
+        else
+            throw new Error("unknown direction: "+direction);
+    }
+
+    // int
+    Input_comparePositionToPosition = function(posId1,posId2)
+    {
+        //idebug("Input_comparePositionToPosition("+posId1+","+posId2+")");
+        var pos1 = getPosition(posId1);
+        var pos2 = getPosition(posId2);
+        if (pos1 == null)
+            throw new Error("pos1 is null");
+        if (pos2 == null)
+            throw new Error("pos2 is null");
+        return Position_compare(pos1,pos2);
+    }
+
+    // int
+    Input_offsetFromPositionToPosition = function(fromId,toId)
+    {
+        //idebug("Input_offsetFromPositionToPosition("+fromId+","+toId+")");
+        throw new Error("offsetFromPositionToPosition: not implemented");
+    }
+
+    Input_positionWithinRangeFarthestInDirection = function(startId,endId,direction)
+    {
+        //idebug("Input_positionWithinRangeFarthestInDirection("+startId+","+endId+","+direction);
+        throw new Error("positionWithinRangeFarthestInDirection: not implemented");
+    }
+
+    // { startId, endId }
+    Input_characterRangeByExtendingPositionInDirection = function(posId,direction)
+    {
+        //idebug("Input_characterRangeByExtendingPositionInDirection("+posId+","+direction);
+        throw new Error("characterRangeByExtendingPositionInDirection: not implemented");
+    }
+
+    Input_firstRectForRange = function(startId,endId)
+    {
+        //idebug("Input_firstRectForRange("+startId+","+endId+")");
+        var start = getPosition(startId);
+        var end = getPosition(endId);
+        var range = new Range(start.node,start.offset,end.node,end.offset);
+        var rects = Range_getClientRects(range);
+        if (rects.length == 0)
+            return { x: 0, y: 0, width: 0, height: 0 };
+        else
+            return { x: rects[0].left, y: rects[0].top,
+                     width: rects[0].width, height: rects[0].height };
+    }
+
+    Input_caretRectForPosition = function(posId)
+    {
+        //idebug("Input_caretRectForPosition("+posId+")");
+        var pos = getPosition(posId);
+        var rect = Position_rectAtPos(pos);
+        if (rect == null)
+            return { x: 0, y: 0, width: 0, height: 0 };
+        else
+            return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
+    }
+
+    // posId
+    Input_closestPositionToPoint = function(x,y)
+    {
+        //idebug("Input_closestPositionToPoint("+x+","+y+")");
+        throw new Error("closestPositionToPoint: not implemented");
+    }
+
+    // posId
+    Input_closestPositionToPointWithinRange = function(x,y,startId,endId)
+    {
+        //idebug("Input_closestPositionToPointWithinRange("+x+","+y+")");
+        throw new Error("closestPositionToPointWithinRange: not implemented");
+    }
+
+    // { startId, endId }
+    Input_characterRangeAtPoint = function(x,y)
+    {
+        //idebug("Input_characterRangeAtPoint("+x+","+y+")");
+        throw new Error("characterRangeAtPoint: not implemented");
+    }
+
+    // posId
+    Input_positionWithinRangeAtCharacterOffset = function(startId,endId,offset)
+    {
+        //idebug("Input_positionWithinRangeAtCharacterOffset("+startId+","+endId+","+offset+")");
+        throw new Error("positionWithinRangeAtCharacterOffset: not implemented");
+    }
+
+    // int
+    Input_characterOffsetOfPositionWithinRange = function(posId,startId,endId)
+    {
+        //idebug("Input_characterOffsetOfPositionWithinRange("+posId+","+startId+","+endId+")");
+        throw new Error("characterOffsetOfPositionWithinRange: not implemented");
+    }
+
+    // UITextInputTokenizer methods
+
+    var punctuation = "!\"#%&',-/:;<=>@`~\\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|";
+    var letterRE = new RegExp("[^\\s"+punctuation+"]");
+    var wordAtStartRE = new RegExp("^[^\\s"+punctuation+"]+");
+    var nonWordAtStartRE = new RegExp("^[\\s"+punctuation+"]+");
+    var wordAtEndRE = new RegExp("[^\\s"+punctuation+"]+$");
+    var nonWordAtEndRE = new RegExp("[\\s"+punctuation+"]+$");
+
+    function isForward(direction)
+    {
+        return ((direction == "forward") ||
+                (direction == "right") ||
+                (direction == "down"));
+    }
+
+    Input_isAtWordBoundary = function(pos,direction)
+    {
+        if (pos.node.nodeType != Node.TEXT_NODE)
+            return false;
+        var paragraph = Text_analyseParagraph(pos);
+        if (paragraph == null)
+            return false;
+        var offset = Paragraph_offsetAtPosition(paragraph,pos);
+        var before = paragraph.text.substring(0,offset);
+        var after = paragraph.text.substring(offset);
+        var text = paragraph.text;
+
+        var afterMatch = (offset < text.length) && (text.charAt(offset).match(letterRE));
+        var beforeMatch = (offset > 0) && (text.charAt(offset-1).match(letterRE));
+
+        // coerce to boolean
+        afterMatch = !!afterMatch;
+        beforeMatch = !!beforeMatch;
+
+        if (isForward(direction))
+            return beforeMatch && !afterMatch;
+        else
+            return !beforeMatch;
+    }
+
+    Input_isAtParagraphBoundary = function(pos,direction)
+    {
+    }
+
+    Input_isPositionAtBoundaryGranularityInDirection = function(posId,granularity,direction)
+    {
+        //idebug("Input_isPositionAtBoundaryGranularityInDirection("+
+        //       posId+","+granularity+","+direction+")");
+        var pos = getPosition(posId);
+        if (pos == null)
+            return false;
+
+        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
+        if ((granularity == "sentence") || (granularity == "document"))
+            return false;
+
+        if (granularity == "character") {
+            return true;
+        }
+        else if (granularity == "word") {
+            return Input_isAtWordBoundary(pos,direction);
+        }
+        else if ((granularity == "paragraph") || (granularity == "line")) {
+            if (isForward(direction))
+                return Position_equal(pos,Text_toEndOfBoundary(pos,granularity));
+            else
+                return Position_equal(pos,Text_toStartOfBoundary(pos,granularity));
+        }
+        else if (granularity == "sentence") {
+        }
+        else if (granularity == "document") {
+        }
+        throw new Error("unsupported granularity: "+granularity);
+    }
+
+    Input_isPositionWithinTextUnitInDirection = function(posId,granularity,direction)
+    {
+        //idebug("Input_isPositionWithinTextUnitInDirection("+
+        //       posId+","+granularity+","+direction+")");
+        var pos = getPosition(posId);
+        if (pos == null)
+            return false;
+
+        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
+        if ((granularity == "sentence") || (granularity == "document"))
+            return true;
+
+        if (granularity == "character") {
+            return true;
+        }
+        else if (granularity == "word") {
+            pos = Text_closestPosInDirection(pos,direction);
+            if (pos == null)
+                return false;
+            var paragraph = Text_analyseParagraph(pos);
+            if (paragraph == null)
+                return false;
+            if ((pos != null) && (pos.node.nodeType == Node.TEXT_NODE)) {
+                var offset = Paragraph_offsetAtPosition(paragraph,pos);
+                var text = paragraph.text;
+                if (isForward(direction))
+                    return !!((offset < text.length) && (text.charAt(offset).match(letterRE)));
+                else
+                    return !!((offset > 0) && (text.charAt(offset-1).match(letterRE)));
+            }
+            else {
+                return false;
+            }
+        }
+        else if (granularity == "sentence") {
+        }
+        else if ((granularity == "paragraph") || (granularity == "line")) {
+            var start = Text_toStartOfBoundary(pos,granularity);
+            var end = Text_toEndOfBoundary(pos,granularity);
+            start = start ? start : pos;
+            end = end ? end : pos;
+            if (isForward(direction)) {
+                return ((Position_compare(start,pos) <= 0) &&
+                        (Position_compare(pos,end) < 0));
+            }
+            else {
+                return ((Position_compare(start,pos) < 0) &&
+                        (Position_compare(pos,end) <= 0));
+            }
+        }
+        else if (granularity == "document") {
+        }
+        throw new Error("unsupported granularity: "+granularity);
+    }
+
+    Input_toWordBoundary = function(pos,direction)
+    {
+        pos = Text_closestPosInDirection(pos,direction);
+        if (pos == null)
+            return null;
+        var paragraph = Text_analyseParagraph(pos);
+        if (paragraph == null)
+            return null;
+        var run = Paragraph_runFromNode(paragraph,pos.node);
+        var offset = pos.offset + run.start;
+
+        if (isForward(direction)) {
+            var remaining = paragraph.text.substring(offset);
+            var afterWord = remaining.replace(wordAtStartRE,"");
+            var afterNonWord = remaining.replace(nonWordAtStartRE,"");
+
+            if (remaining.length == 0) {
+                return pos;
+            }
+            else if (afterWord.length < remaining.length) {
+                var newOffset = offset + (remaining.length - afterWord.length);
+                return Paragraph_positionAtOffset(paragraph,newOffset);
+            }
+            else {
+                var newOffset = offset + (remaining.length - afterNonWord.length);
+                return Paragraph_positionAtOffset(paragraph,newOffset);
+            }
+        }
+        else {
+            var remaining = paragraph.text.substring(0,offset);
+            var beforeWord = remaining.replace(wordAtEndRE,"");
+            var beforeNonWord = remaining.replace(nonWordAtEndRE,"");
+
+            if (remaining.length == 0) {
+                return pos;
+            }
+            else if (beforeWord.length < remaining.length) {
+                var newOffset = offset - (remaining.length - beforeWord.length);
+                return Paragraph_positionAtOffset(paragraph,newOffset);
+            }
+            else {
+                var newOffset = offset - (remaining.length - beforeNonWord.length);
+                return Paragraph_positionAtOffset(paragraph,newOffset);
+            }
+        }
+    }
+
+    Input_toParagraphBoundary = function(pos,direction)
+    {
+        if (isForward(direction)) {
+            var end = Text_toEndOfBoundary(pos,"paragraph");
+            if (Position_equal(pos,end)) {
+                end = Position_nextMatch(end,Position_okForMovement);
+                end = Text_toEndOfBoundary(end,"paragraph");
+                end = Text_toStartOfBoundary(end,"paragraph");
+            }
+            return end ? end : pos;
+        }
+        else {
+            var start = Text_toStartOfBoundary(pos,"paragraph");
+            if (Position_equal(pos,start)) {
+                start = Position_prevMatch(start,Position_okForMovement);
+                start = Text_toStartOfBoundary(start,"paragraph");
+                start = Text_toEndOfBoundary(start,"paragraph");
+            }
+            return start ? start : pos;
+        }
+    }
+
+    Input_toLineBoundary = function(pos,direction)
+    {
+        if (isForward(direction)) {
+            var end = Text_toEndOfBoundary(pos,"line");
+            return end ? end : pos;
+        }
+        else {
+            var start = Text_toStartOfBoundary(pos,"line");
+            return start ? start : pos;
+        }
+    }
+
+    Input_positionFromPositionToBoundaryInDirection = function(posId,granularity,direction)
+    {
+        //idebug("Input_positionFromPositionToBoundaryInDirection("+
+        //       posId+","+granularity+","+direction+")");
+        var pos = getPosition(posId);
+        if (pos == null)
+            return null;
+
+        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
+        if (granularity == "sentence")
+            granularity = "paragraph";
+
+        if (granularity == "word")
+            return addPosition(Input_toWordBoundary(pos,direction));
+        else if (granularity == "paragraph")
+            return addPosition(Input_toParagraphBoundary(pos,direction));
+        else if (granularity == "line")
+            return addPosition(Input_toLineBoundary(pos,direction));
+        else if (granularity == "character")
+            return Input_positionFromPositionInDirectionOffset(posId,direction,1);
+        else if (granularity == "document")
+            return isForward(direction) ? BaseIdDocumentEnd : BaseIdDocumentStart;
+        else
+            throw new Error("unsupported granularity: "+granularity);
+    }
+
+    Input_rangeEnclosingPositionWithGranularityInDirection = function(posId,granularity,direction)
+    {
+        //idebug("Input_rangeEnclosingPositionWithGranularityInDirection("+
+        //       posId+","+granularity+","+direction);
+        var pos = getPosition(posId);
+        if (pos == null)
+            return null;
+
+        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
+        if (granularity == "sentence")
+            granularity = "paragraph";
+
+        if (granularity == "word") {
+            pos = Text_closestPosInDirection(pos,direction);
+            if (pos == null)
+                return null;
+            var paragraph = Text_analyseParagraph(pos);
+            if (pos == null)
+                return addPosition(null);
+            if (paragraph == null)
+                return addPosition(null);
+            var run = Paragraph_runFromNode(paragraph,pos.node);
+            var offset = pos.offset + run.start;
+
+            var before = paragraph.text.substring(0,offset);
+            var after = paragraph.text.substring(offset);
+            var beforeWord = before.replace(wordAtEndRE,"");
+            var afterWord = after.replace(wordAtStartRE,"");
+
+            var ok;
+
+            if (isForward(direction))
+                ok = (afterWord.length < after.length);
+            else
+                ok = (beforeWord.length < before.length);
+
+            if (ok) {
+                var charsBefore = (before.length - beforeWord.length);
+                var charsAfter = (after.length - afterWord.length);
+                var startOffset = offset - charsBefore;
+                var endOffset = offset + charsAfter;
+
+                var startPos = Paragraph_positionAtOffset(paragraph,startOffset);
+                var endPos = Paragraph_positionAtOffset(paragraph,endOffset);
+                return { startId: addPosition(startPos),
+                         endId: addPosition(endPos) };
+            }
+            else {
+                return null;
+            }
+        }
+        else if ((granularity == "paragraph") || (granularity == "line")) {
+            var start = Text_toStartOfBoundary(pos,granularity);
+            var end = Text_toEndOfBoundary(pos,granularity);
+            start = start ? start : pos;
+            end = end ? end : pos;
+
+            if ((granularity == "paragraph") || !isForward(direction)) {
+                if (isForward(direction)) {
+                    if (Position_equal(pos,Text_toEndOfBoundary(pos,granularity)))
+                        return null;
+                }
+                else {
+                    if (Position_equal(pos,Text_toStartOfBoundary(pos,granularity)))
+                        return null;
+                }
+            }
+            return { startId: addPosition(start),
+                     endId: addPosition(end) };
+        }
+        else {
+            throw new Error("unsupported granularity: "+granularity);
+        }
+    }
+
+})();


[21/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Position.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Position.js b/experiments/editorFramework/src/Javascript_Layer_0/Position.js
new file mode 100644
index 0000000..ce4bc18
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Position.js
@@ -0,0 +1,1164 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Position;
+var Position_assertValid;
+var Position_prev;
+var Position_next;
+var Position_trackWhileExecuting;
+var Position_closestActualNode;
+var Position_okForInsertion;
+var Position_okForMovement;
+var Position_prevMatch;
+var Position_nextMatch;
+var Position_closestMatchForwards;
+var Position_closestMatchBackwards;
+var Position_track;
+var Position_untrack;
+var Position_rectAtPos;
+var Position_noteAncestor;
+var Position_captionAncestor;
+var Position_figureOrTableAncestor;
+var Position_displayRectAtPos;
+var Position_preferTextPosition;
+var Position_preferElementPosition;
+var Position_compare;
+var Position_atPoint;
+
+(function() {
+
+    // public
+    Position = function(node,offset)
+    {
+        if (node == document.documentElement)
+            throw new Error("node is root element");
+        Object.defineProperty(this,"self",{value: {}});
+        var self = this.self;
+        self.this = this;
+        self.node = node;
+        self.offset = offset;
+        self.origOffset = offset;
+        self.tracking = 0;
+        this.posId = null;
+        this.targetX = null;
+
+        Object.defineProperty(this,"node",{
+            get: function() { return this.self.node },
+            set: setNode,
+            enumerable: true });
+        Object.defineProperty(this,"offset",{
+            get: function() { return this.self.offset },
+            set: function(value) { this.self.offset = value },
+            enumerable: true});
+        Object.defineProperty(this,"origOffset",{
+            get: function() { return this.self.origOffset },
+            set: function(value) { this.self.origOffset = value },
+            enumerable: true});
+
+        Object.preventExtensions(this);
+    }
+
+    function actuallyStartTracking(self)
+    {
+        DOM_addTrackedPosition(self.this);
+    }
+
+    function actuallyStopTracking(self)
+    {
+        DOM_removeTrackedPosition(self.this);
+    }
+
+    function startTracking(self)
+    {
+        if (self.tracking == 0)
+            actuallyStartTracking(self);
+        self.tracking++;
+    }
+
+    function stopTracking(self)
+    {
+        self.tracking--;
+        if (self.tracking == 0)
+            actuallyStopTracking(self);
+    }
+
+    function setNode(node)
+    {
+        var self = this.self;
+        if (self.tracking > 0)
+            actuallyStopTracking(self);
+
+        self.node = node;
+
+        if (self.tracking > 0)
+            actuallyStartTracking(self);
+    }
+
+    function setNodeAndOffset(self,node,offset)
+    {
+        self.this.node = node;
+        self.this.offset = offset;
+    }
+
+    // public
+    Position.prototype.toString = function()
+    {
+        var self = this.self;
+        var result;
+        if (self.node.nodeType == Node.TEXT_NODE) {
+            var extra = "";
+            if (self.offset > self.node.nodeValue.length) {
+                for (var i = self.node.nodeValue.length; i < self.offset; i++)
+                    extra += "!";
+            }
+            var id = "";
+            if (window.debugIds)
+                id = self.node._nodeId+":";
+            result = id+JSON.stringify(self.node.nodeValue.slice(0,self.offset)+extra+"|"+
+                                       self.node.nodeValue.slice(self.offset));
+        }
+        else {
+            result = "("+nodeString(self.node)+","+self.offset+")";
+        }
+        if (this.posId != null)
+            result = "["+this.posId+"]"+result;
+        return result;
+    }
+
+    function positionSpecial(pos,forwards,backwards)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        var prev = node.childNodes[offset-1];
+        var next = node.childNodes[offset];
+
+        // Moving left from the start of a caption - go to the end of the table
+        if ((node._type == HTML_CAPTION) && backwards && (prev == null))
+            return new Position(node.parentNode,node.parentNode.childNodes.length);
+
+        // Moving right from the end of a caption - go after the table
+        if ((node._type == HTML_CAPTION) && forwards && (next == null))
+            return new Position(node.parentNode.parentNode,DOM_nodeOffset(node.parentNode)+1);
+
+        // Moving left from just after a table - go to the end of the caption (if there is one)
+        if ((prev != null) && (prev._type == HTML_TABLE) && backwards) {
+            var firstChild = firstChildElement(prev);
+            if ((firstChild._type == HTML_CAPTION))
+                return new Position(firstChild,firstChild.childNodes.length);
+        }
+
+        // Moving right from just before a table - bypass the the caption (if there is one)
+        if ((next != null) && (next._type == HTML_TABLE) && forwards) {
+            var firstChild = firstChildElement(next);
+            if (firstChild._type == HTML_CAPTION)
+                return new Position(next,DOM_nodeOffset(firstChild)+1);
+        }
+
+        // Moving right from the end of a table - go to the start of the caption (if there is one)
+        if ((node._type == HTML_TABLE) && (next == null) && forwards) {
+            var firstChild = firstChildElement(node);
+            if (firstChild._type == HTML_CAPTION)
+                return new Position(firstChild,0);
+        }
+
+        // Moving left just after a caption node - skip the caption
+        if ((prev != null) && (prev._type == HTML_CAPTION) && backwards)
+            return new Position(node,offset-1);
+
+        return null;
+    }
+
+    // public
+    Position_assertValid = function(pos,description)
+    {
+        if (description == null)
+            description = "Position";
+
+        for (var ancestor = pos.node; ancestor != document.body; ancestor = ancestor.parentNode) {
+            if (ancestor == null)
+                throw new Error(description+" node "+pos.node.nodeName+" is not in tree");
+        }
+
+        var max;
+        if (pos.node.nodeType == Node.ELEMENT_NODE)
+            max = pos.node.childNodes.length;
+        else if (pos.node.nodeType == Node.TEXT_NODE)
+            max = pos.node.nodeValue.length;
+        else
+            throw new Error(description+" has invalid node type "+pos.node.nodeType);
+
+        if ((pos.offset < 0) || (pos.offset > max)) {
+            throw new Error(description+" (in "+pos.node.nodeName+") has invalid offset "+
+                            pos.offset+" (max allowed is "+max+")");
+        }
+    }
+
+    // public
+    Position_prev = function(pos)
+    {
+        if (pos.node.nodeType == Node.ELEMENT_NODE) {
+            var r = positionSpecial(pos,false,true);
+            if (r != null)
+                return r;
+            if (pos.offset == 0) {
+                return upAndBack(pos);
+            }
+            else {
+                var child = pos.node.childNodes[pos.offset-1];
+                return new Position(child,DOM_maxChildOffset(child));
+            }
+        }
+        else if (pos.node.nodeType == Node.TEXT_NODE) {
+            if (pos.offset > 0)
+                return new Position(pos.node,pos.offset-1);
+            else
+                return upAndBack(pos);
+        }
+        else {
+            return null;
+        }
+
+        function upAndBack(pos)
+        {
+            if (pos.node == pos.node.ownerDocument.body)
+                return null;
+            else
+                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
+        }
+    }
+
+    // public
+    Position_next = function(pos)
+    {
+        if (pos.node.nodeType == Node.ELEMENT_NODE) {
+            var r = positionSpecial(pos,true,false);
+            if (r != null)
+                return r;
+            if (pos.offset == pos.node.childNodes.length)
+                return upAndForwards(pos);
+            else
+                return new Position(pos.node.childNodes[pos.offset],0);
+        }
+        else if (pos.node.nodeType == Node.TEXT_NODE) {
+            if (pos.offset < pos.node.nodeValue.length)
+                return new Position(pos.node,pos.offset+1);
+            else
+                return upAndForwards(pos);
+        }
+        else {
+            return null;
+        }
+
+        function upAndForwards(pos)
+        {
+            if (pos.node == pos.node.ownerDocument.body)
+                return null;
+            else
+                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
+        }
+    }
+
+    // public
+    Position_trackWhileExecuting = function(positions,fun)
+    {
+        for (var i = 0; i < positions.length; i++)
+            startTracking(positions[i].self);
+        try {
+            return fun();
+        }
+        finally {
+            for (var i = 0; i < positions.length; i++)
+                stopTracking(positions[i].self);
+        }
+    }
+
+    // public
+    Position_closestActualNode = function(pos,preferElement)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if ((node.nodeType != Node.ELEMENT_NODE) || (node.firstChild == null))
+            return node;
+        else if (offset == 0)
+            return node.firstChild;
+        else if (offset >= node.childNodes.length)
+            return node.lastChild;
+
+        var prev = node.childNodes[offset-1];
+        var next = node.childNodes[offset];
+        if (preferElement &&
+            (next.nodeType != Node.ELEMENT_NODE) &&
+            (prev.nodeType == Node.ELEMENT_NODE)) {
+            return prev;
+        }
+        else {
+            return next;
+        }
+    }
+
+    // public
+    Position_okForInsertion = function(pos)
+    {
+        return Position_okForMovement(pos,true);
+    }
+
+    function nodeCausesLineBreak(node)
+    {
+        return ((node._type == HTML_BR) || !isInlineNode(node));
+    }
+
+    function spacesUntilNextContent(node)
+    {
+        var spaces = 0;
+        while (true) {
+            if (node.firstChild) {
+                node = node.firstChild;
+            }
+            else if (node.nextSibling) {
+                node = node.nextSibling;
+            }
+            else {
+                while ((node.parentNode != null) && (node.parentNode.nextSibling == null)) {
+                    node = node.parentNode;
+                    if (nodeCausesLineBreak(node))
+                        return null;
+                }
+                if (node.parentNode == null)
+                    node = null;
+                else
+                    node = node.parentNode.nextSibling;
+            }
+
+            if ((node == null) || nodeCausesLineBreak(node))
+                return null;
+            if (isOpaqueNode(node))
+                return spaces;
+            if (node.nodeType == Node.TEXT_NODE) {
+                if (isWhitespaceTextNode(node)) {
+                    spaces += node.nodeValue.length;
+                }
+                else {
+                    var matches = node.nodeValue.match(/^\s+/);
+                    if (matches == null)
+                        return spaces;
+                    spaces += matches[0].length;
+                    return spaces;
+                }
+            }
+        }
+    }
+
+    // public
+    Position_okForMovement = function(pos,insertion)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        var type = node._type;
+
+        if (isOpaqueNode(node))
+            return false;
+
+        for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) {
+            var ancestorType = node._type;
+            if (ancestorType == HTML_FIGCAPTION)
+                break;
+            else if (ancestorType == HTML_FIGURE)
+                return false;
+        }
+
+        if (node.nodeType == Node.TEXT_NODE) {
+            var value = node.nodeValue;
+
+            // If there are multiple adjacent text nodes, consider them as one (adjusting the
+            // offset appropriately)
+
+            var firstNode = node;
+            var lastNode = node;
+
+            while ((firstNode.previousSibling != null) &&
+                   (firstNode.previousSibling.nodeType == Node.TEXT_NODE)) {
+                firstNode = firstNode.previousSibling;
+                value = firstNode.nodeValue + value;
+                offset += firstNode.nodeValue.length;
+            }
+
+            while ((lastNode.nextSibling != null) &&
+                   (lastNode.nextSibling.nodeType == Node.TEXT_NODE)) {
+                lastNode = lastNode.nextSibling;
+                value += lastNode.nodeValue;
+            }
+
+            var prevChar = value.charAt(offset-1);
+            var nextChar = value.charAt(offset);
+            var havePrevChar = ((prevChar != null) && !isWhitespaceString(prevChar));
+            var haveNextChar = ((nextChar != null) && !isWhitespaceString(nextChar));
+            if (havePrevChar && haveNextChar) {
+                var prevCode = value.charCodeAt(offset-1);
+                var nextCode = value.charCodeAt(offset);
+                if ((prevCode >= 0xD800) && (prevCode <= 0xDBFF) &&
+                    (nextCode >= 0xDC00) && (nextCode <= 0xDFFF)) {
+                    return false; // In middle of surrogate pair
+                }
+                return true;
+            }
+
+            if (isWhitespaceString(value)) {
+                if (offset == 0) {
+                    if ((node == firstNode) &&
+                        (firstNode.previousSibling == null) && (lastNode.nextSibling == null))
+                        return true;
+                    if ((node.nextSibling != null) && (node.nextSibling._type == HTML_BR))
+                        return true;
+                    if ((node.firstChild == null) &&
+                        (node.previousSibling == null) &&
+                        (node.nextSibling == null)) {
+                        return true;
+                    }
+                    if (insertion && (node.previousSibling != null) &&
+                        isInlineNode(node.previousSibling) &&
+                        !isOpaqueNode(node.previousSibling) &&
+                        (node.previousSibling._type != HTML_BR))
+                        return true;
+                }
+                return false;
+            }
+
+            if (insertion)
+                return true;
+
+            var precedingText = value.substring(0,offset);
+            if (isWhitespaceString(precedingText)) {
+                return (haveNextChar &&
+                        ((node.previousSibling == null) ||
+                         (node.previousSibling._type == HTML_BR) ||
+                         isNoteNode(node.previousSibling) ||
+                         (isParagraphNode(node.previousSibling)) ||
+                         (getNodeText(node.previousSibling).match(/\s$/)) ||
+                         isItemNumber(node.previousSibling) ||
+                         ((precedingText.length > 0))));
+            }
+
+            var followingText = value.substring(offset);
+            if (isWhitespaceString(followingText)) {
+                return (havePrevChar &&
+                        ((node.nextSibling == null) ||
+                         isNoteNode(node.nextSibling) ||
+                         (followingText.length > 0) ||
+                         (spacesUntilNextContent(node) != 0)));
+            }
+
+            return (havePrevChar || haveNextChar);
+        }
+        else if (node.nodeType == Node.ELEMENT_NODE) {
+            if (node.firstChild == null) {
+                switch (type) {
+                case HTML_LI:
+                case HTML_TH:
+                case HTML_TD:
+                    return true;
+                default:
+                    if (PARAGRAPH_ELEMENTS[type])
+                        return true;
+                    else
+                        break;
+                }
+            }
+
+            var prevNode = node.childNodes[offset-1];
+            var nextNode = node.childNodes[offset];
+            var prevType = (prevNode != null) ? prevNode._type : 0;
+            var nextType = (nextNode != null) ? nextNode._type : 0;
+
+            var prevIsNote = (prevNode != null) && isNoteNode(prevNode);
+            var nextIsNote = (nextNode != null) && isNoteNode(nextNode);
+            if (((nextNode == null) || !nodeHasContent(nextNode)) && prevIsNote)
+                return true;
+            if (((prevNode == null) || !nodeHasContent(prevNode)) && nextIsNote)
+                return true;
+            if (prevIsNote && nextIsNote)
+                return true;
+
+            if ((prevNode == null) && (nextNode == null) &&
+                (CONTAINERS_ALLOWING_CHILDREN[type] ||
+                (isInlineNode(node) && !isOpaqueNode(node) && (type != HTML_BR))))
+                return true;
+
+            if ((prevNode != null) && isSpecialBlockNode(prevNode))
+                return true;
+            if ((nextNode != null) && isSpecialBlockNode(nextNode))
+                return true;
+
+            if ((nextNode != null) && isItemNumber(nextNode))
+                return false;
+            if ((prevNode != null) && isItemNumber(prevNode))
+                return ((nextNode == null) || isWhitespaceTextNode(nextNode));
+
+            if ((nextNode != null) && (nextType == HTML_BR))
+                return ((prevType == 0) || (prevType != HTML_TEXT));
+
+            if ((prevNode != null) && (isOpaqueNode(prevNode) || (prevType == HTML_TABLE))) {
+
+                switch (nextType) {
+                case 0:
+                case HTML_TEXT:
+                case HTML_TABLE:
+                    return true;
+                default:
+                    return isOpaqueNode(nextNode);
+                }
+            }
+            if ((nextNode != null) && (isOpaqueNode(nextNode) || (nextType == HTML_TABLE))) {
+                switch (prevType) {
+                case 0:
+                case HTML_TEXT:
+                case HTML_TABLE:
+                    return true;
+                default:
+                    return isOpaqueNode(prevNode);
+                }
+            }
+        }
+
+        return false;
+    }
+
+    Position_prevMatch = function(pos,fun)
+    {
+        do {
+            pos = Position_prev(pos);
+        } while ((pos != null) && !fun(pos));
+        return pos;
+    }
+
+    Position_nextMatch = function(pos,fun)
+    {
+        do {
+            pos = Position_next(pos);
+        } while ((pos != null) && !fun(pos));
+        return pos;
+    }
+
+    function findEquivalentValidPosition(pos,fun)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if (node.nodeType == Node.ELEMENT_NODE) {
+            var before = node.childNodes[offset-1];
+            var after = node.childNodes[offset];
+            if ((before != null) && (before.nodeType == Node.TEXT_NODE)) {
+                var candidate = new Position(before,before.nodeValue.length);
+                if (fun(candidate))
+                    return candidate;
+            }
+            if ((after != null) && (after.nodeType == Node.TEXT_NODE)) {
+                var candidate = new Position(after,0);
+                if (fun(candidate))
+                    return candidate;
+            }
+        }
+
+        if ((pos.node.nodeType == Node.TEXT_NODE) &&
+            isWhitespaceString(pos.node.nodeValue.slice(pos.offset))) {
+            var str = pos.node.nodeValue;
+            var whitespace = str.match(/\s+$/);
+            if (whitespace) {
+                var adjusted = new Position(pos.node,
+                                            str.length - whitespace[0].length + 1);
+                return adjusted;
+            }
+        }
+        return pos;
+    }
+
+    // public
+    Position_closestMatchForwards = function(pos,fun)
+    {
+        if (pos == null)
+            return null;
+
+        if (!fun(pos))
+            pos = findEquivalentValidPosition(pos,fun);
+
+        if (fun(pos))
+            return pos;
+
+        var next = Position_nextMatch(pos,fun);
+        if (next != null)
+            return next;
+
+        var prev = Position_prevMatch(pos,fun);
+        if (prev != null)
+            return prev;
+
+        return new Position(document.body,document.body.childNodes.length);
+    }
+
+    // public
+    Position_closestMatchBackwards = function(pos,fun)
+    {
+        if (pos == null)
+            return null;
+
+        if (!fun(pos))
+            pos = findEquivalentValidPosition(pos,fun);
+
+        if (fun(pos))
+            return pos;
+
+        var prev = Position_prevMatch(pos,fun);
+        if (prev != null)
+            return prev;
+
+        var next = Position_nextMatch(pos,fun);
+        if (next != null)
+            return next;
+
+        return new Position(document.body,0);
+    }
+
+    Position_track = function(pos)
+    {
+        startTracking(pos.self);
+    }
+
+    Position_untrack = function(pos)
+    {
+        stopTracking(pos.self);
+    }
+
+    Position_rectAtPos = function(pos)
+    {
+        if (pos == null)
+            return null;
+        var range = new Range(pos.node,pos.offset,pos.node,pos.offset);
+        var rects = Range_getClientRects(range);
+
+        if ((rects.length > 0) && !rectIsEmpty(rects[0])) {
+            return rects[0];
+        }
+
+        if (isParagraphNode(pos.node) && (pos.offset == 0)) {
+            var rect = pos.node.getBoundingClientRect();
+            if (!rectIsEmpty(rect))
+                return rect;
+        }
+
+        return null;
+    }
+
+    function posAtStartOfParagraph(pos,paragraph)
+    {
+        return ((pos.node == paragraph.node) &&
+                (pos.offset == paragraph.startOffset));
+    }
+
+    function posAtEndOfParagraph(pos,paragraph)
+    {
+        return ((pos.node == paragraph.node) &&
+                (pos.offset == paragraph.endOffset));
+    }
+
+    function zeroWidthRightRect(rect)
+    {
+        return { left: rect.right, // 0 width
+                 right: rect.right,
+                 top: rect.top,
+                 bottom: rect.bottom,
+                 width: 0,
+                 height: rect.height };
+    }
+
+    function zeroWidthLeftRect(rect)
+    {
+        return { left: rect.left,
+                 right: rect.left, // 0 width
+                 top: rect.top,
+                 bottom: rect.bottom,
+                 width: 0,
+                 height: rect.height };
+    }
+
+    function zeroWidthMidRect(rect)
+    {
+        var mid = rect.left + rect.width/2;
+        return { left: mid,
+                 right: mid, // 0 width
+                 top: rect.top,
+                 bottom: rect.bottom,
+                 width: 0,
+                 height: rect.height };
+    }
+
+    Position_noteAncestor = function(pos)
+    {
+        var node = Position_closestActualNode(pos);
+        for (; node != null; node = node.parentNode) {
+            if (isNoteNode(node))
+                return node;
+        }
+        return null;
+    }
+
+    Position_captionAncestor = function(pos)
+    {
+        var node = Position_closestActualNode(pos);
+        for (; node != null; node = node.parentNode) {
+            if ((node._type == HTML_FIGCAPTION) || (node._type == HTML_CAPTION))
+                return node;
+        }
+        return null;
+    }
+
+    Position_figureOrTableAncestor = function(pos)
+    {
+        var node = Position_closestActualNode(pos);
+        for (; node != null; node = node.parentNode) {
+            if ((node._type == HTML_FIGURE) || (node._type == HTML_TABLE))
+                return node;
+        }
+        return null;
+    }
+
+    function exactRectAtPos(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if (node.nodeType == Node.ELEMENT_NODE) {
+            if (offset > node.childNodes.length)
+                throw new Error("Invalid offset: "+offset+" of "+node.childNodes.length);
+
+            var before = node.childNodes[offset-1];
+            var after = node.childNodes[offset];
+
+            // Cursor is immediately before table -> return table rect
+            if ((before != null) && isSpecialBlockNode(before))
+                return zeroWidthRightRect(before.getBoundingClientRect());
+
+            // Cursor is immediately after table -> return table rect
+            else if ((after != null) && isSpecialBlockNode(after))
+                return zeroWidthLeftRect(after.getBoundingClientRect());
+
+            // Start of empty paragraph
+            if ((node.nodeType == Node.ELEMENT_NODE) && (offset == 0) &&
+                isParagraphNode(node) && !nodeHasContent(node)) {
+                return zeroWidthLeftRect(node.getBoundingClientRect());
+            }
+
+            return null;
+        }
+        else if (node.nodeType == Node.TEXT_NODE) {
+            // First see if the client rects returned by the range gives us a valid value. This
+            // won't be the case if the cursor is surrounded by both sides on whitespace.
+            var result = rectAtRightOfRange(new Range(node,offset,node,offset));
+            if (result != null)
+                return result;
+
+            if (offset > 0) {
+                // Try and get the rect of the previous character; the cursor goes after that
+                var result = rectAtRightOfRange(new Range(node,offset-1,node,offset));
+                if (result != null)
+                    return result;
+            }
+
+            return null;
+        }
+        else {
+            return null;
+        }
+
+        function rectAtRightOfRange(range)
+        {
+            var rects = Range_getClientRects(range);
+            if ((rects == null) || (rects.length == 0) || (rects[rects.length-1].height == 0))
+                return null;
+            return zeroWidthRightRect(rects[rects.length-1]);
+        }
+    }
+
+    function tempSpaceRect(parentNode,nextSibling)
+    {
+        var space = DOM_createTextNode(document,String.fromCharCode(160));
+        DOM_insertBefore(parentNode,space,nextSibling);
+        var range = new Range(space,0,space,1);
+        var rects = Range_getClientRects(range);
+        DOM_deleteNode(space);
+        if (rects.length > 0)
+            return rects[0];
+        else
+            return nil;
+    }
+
+    Position_displayRectAtPos = function(pos)
+    {
+        rect = exactRectAtPos(pos);
+        if (rect != null)
+            return rect;
+
+        var noteNode = Position_noteAncestor(pos);
+        if ((noteNode != null) && !nodeHasContent(noteNode)) // In empty footnote or endnote
+            return zeroWidthMidRect(noteNode.getBoundingClientRect());
+
+        // If we're immediately before or after a footnote or endnote, calculate the rect by
+        // temporarily inserting a space character, and getting the rect at the start of that.
+        // This avoids us instead getting a rect inside the note, which is what would otherwise
+        // happen if there was no adjacent text node outside the note.
+        if ((pos.node.nodeType == Node.ELEMENT_NODE)) {
+            var before = pos.node.childNodes[pos.offset-1];
+            var after = pos.node.childNodes[pos.offset];
+            if (((before != null) && isNoteNode(before)) ||
+                ((after != null) && isNoteNode(after))) {
+                var rect = tempSpaceRect(pos.node,pos.node.childNodes[pos.offset]);
+                if (rect != null)
+                    return zeroWidthLeftRect(rect);
+            }
+        }
+
+        var captionNode = Position_captionAncestor(pos);
+        if ((captionNode != null) && !nodeHasContent(captionNode)) {
+            // Even if an empty caption has generated content (e.g. "Figure X: ") preceding it,
+            // we can't directly get the rect of that generated content. So we temporarily insert
+            // a text node containing a single space character, get the position to the right of
+            // that character, and then remove the text node.
+            var rect = tempSpaceRect(captionNode,null);
+            if (rect != null)
+                return zeroWidthRightRect(rect);
+        }
+
+        var paragraph = Text_findParagraphBoundaries(pos);
+
+        var backRect = null;
+        for (var backPos = pos; backPos != null; backPos = Position_prev(backPos)) {
+            backRect = exactRectAtPos(backPos);
+            if ((backRect != null) || posAtStartOfParagraph(backPos,paragraph))
+                break;
+        }
+
+        var forwardRect = null;
+        for (var forwardPos = pos; forwardPos != null; forwardPos = Position_next(forwardPos)) {
+            forwardRect = exactRectAtPos(forwardPos);
+            if ((forwardRect != null) || posAtEndOfParagraph(forwardPos,paragraph))
+                break;
+        }
+
+        if (backRect != null) {
+            return backRect;
+        }
+        else if (forwardRect != null) {
+            return forwardRect;
+        }
+        else {
+            // Fallback, e.g. for empty LI elements
+            var node = pos.node;
+            if (node.nodeType == Node.TEXT_NODE)
+                node = node.parentNode;
+            return zeroWidthLeftRect(node.getBoundingClientRect());
+        }
+    }
+
+    Position_equal = function(a,b)
+    {
+        if ((a == null) && (b == null))
+            return true;
+        if ((a != null) && (b != null) &&
+            (a.node == b.node) && (a.offset == b.offset))
+            return true;
+        return false;
+    }
+
+    Position_preferTextPosition = function(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+        if (node.nodeType == Node.ELEMENT_NODE) {
+            var before = node.childNodes[offset-1];
+            var after = node.childNodes[offset];
+            if ((before != null) && (before.nodeType == Node.TEXT_NODE))
+                return new Position(before,before.nodeValue.length);
+            if ((after != null) && (after.nodeType == Node.TEXT_NODE))
+                return new Position(after,0);
+        }
+        return pos;
+    }
+
+    Position_preferElementPosition = function(pos)
+    {
+        if (pos.node.nodeType == Node.TEXT_NODE) {
+            if (pos.node.parentNode == null)
+                throw new Error("Position "+pos+" has no parent node");
+            if (pos.offset == 0)
+                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
+            if (pos.offset == pos.node.nodeValue.length)
+                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
+        }
+        return pos;
+    }
+
+    Position_compare = function(first,second)
+    {
+        if ((first.node == second.node) && (first.offset == second.offset))
+            return 0;
+
+        var doc = first.node.ownerDocument;
+        if ((first.node.parentNode == null) && (first.node != doc.documentElement))
+            throw new Error("First node has been removed from document");
+        if ((second.node.parentNode == null) && (second.node != doc.documentElement))
+            throw new Error("Second node has been removed from document");
+
+        if (first.node == second.node)
+            return first.offset - second.offset;
+
+        var firstParent = null;
+        var firstChild = null;
+        var secondParent = null;
+        var secondChild = null;
+
+        if (second.node.nodeType == Node.ELEMENT_NODE) {
+            secondParent = second.node;
+            secondChild = second.node.childNodes[second.offset];
+        }
+        else {
+            secondParent = second.node.parentNode;
+            secondChild = second.node;
+        }
+
+        if (first.node.nodeType == Node.ELEMENT_NODE) {
+            firstParent = first.node;
+            firstChild = first.node.childNodes[first.offset];
+        }
+        else {
+            firstParent = first.node.parentNode;
+            firstChild = first.node;
+            if (firstChild == secondChild)
+                return 1;
+        }
+
+        var firstC = firstChild;
+        var firstP = firstParent;
+        while (firstP != null) {
+
+            var secondC = secondChild;
+            var secondP = secondParent;
+            while (secondP != null) {
+
+                if (firstP == secondC)
+                    return 1;
+
+                if (firstP == secondP) {
+                    // if secondC is last child, firstC must be secondC or come before it
+                    if (secondC == null)
+                        return -1;
+                    for (var n = firstC; n != null; n = n.nextSibling) {
+                        if (n == secondC)
+                            return -1;
+                    }
+                    return 1;
+                }
+
+                secondC = secondP;
+                secondP = secondP.parentNode;
+            }
+
+            firstC = firstP;
+            firstP = firstP.parentNode;
+        }
+        throw new Error("Could not find common ancestor");
+    }
+
+    // This function works around a bug in WebKit where caretRangeFromPoint sometimes returns an
+    // incorrect node (the last text node in the document). In a previous attempt to fix this bug,
+    // we first checked if the point was in the elements bounding rect, but this meant that it
+    // wasn't possible to place the cursor at the nearest node, if the click location was not
+    // exactly on a node.
+
+    // Now we instead check to see if the result of elementFromPoint is the same as the parent node
+    // of the text node returned by caretRangeFromPoint. If it isn't, then we assume that the latter
+    // result is incorrect, and return null.
+
+    // In the circumstances where this bug was observed, the last text node in the document was
+    // being returned from caretRangeFromPoint in some cases. In the typical case, this is going to
+    // be inside a paragraph node, but elementNodeFromPoint was returning the body element. The
+    // check we do now comparing the results of the two functions fixes this case, but won't work as
+    // intended if the document's last text node is a direct child of the body (as it may be in some
+    // HTML documents that users open).
+
+    function posOutsideSelection(pos)
+    {
+        pos = Position_preferElementPosition(pos);
+
+        if (!isSelectionSpan(pos.node))
+            return pos;
+
+        if (pos.offset == 0)
+            return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
+        else if (pos.offset == pos.node.childNodes.length)
+            return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
+        else
+            return pos;
+    }
+
+    Position_atPoint = function(x,y)
+    {
+        // In general, we can use document.caretRangeFromPoint(x,y) to determine the location of the
+        // cursor based on screen coordinates. However, this doesn't work if the screen coordinates
+        // are outside the bounding box of the document's body. So when this is true, we find either
+        // the first or last non-whitespace text node, calculate a y value that is half-way between
+        // the top and bottom of its first or last rect (respectively), and use that instead. This
+        // results in the cursor being placed on the first or last line when the user taps outside
+        // the document bounds.
+
+        var bodyRect = document.body.getBoundingClientRect();
+        var boundaryRect = null;
+        if (y <= bodyRect.top)
+            boundaryRect = findFirstTextRect();
+        else if (y >= bodyRect.bottom)
+            boundaryRect = findLastTextRect();
+
+        if (boundaryRect != null)
+            y = boundaryRect.top + boundaryRect.height/2;
+
+        // We get here if the coordinates are inside the document's bounding rect, or if getting the
+        // position from the first or last rect failed for some reason.
+
+        var range = document.caretRangeFromPoint(x,y);
+        if (range == null)
+            return null;
+
+        var pos = new Position(range.startContainer,range.startOffset);
+        pos = Position_preferElementPosition(pos);
+
+        if (pos.node.nodeType == Node.ELEMENT_NODE) {
+            var outside = posOutsideSelection(pos);
+            var prev = outside.node.childNodes[outside.offset-1];
+            var next = outside.node.childNodes[outside.offset];
+
+            if ((prev != null) && nodeMayContainPos(prev) && elementContainsPoint(prev,x,y))
+                return new Position(prev,0);
+
+            if ((next != null) && nodeMayContainPos(next) && elementContainsPoint(next,x,y))
+                return new Position(next,0);
+
+            if (next != null) {
+                var nextNode = outside.node;
+                var nextOffset = outside.offset+1;
+
+                if (isSelectionSpan(next) && (next.firstChild != null)) {
+                    nextNode = next;
+                    nextOffset = 1;
+                    next = next.firstChild;
+                }
+
+                if ((next != null) && isEmptyNoteNode(next)) {
+                    var rect = next.getBoundingClientRect();
+                    if (x > rect.right)
+                        return new Position(nextNode,nextOffset);
+                }
+            }
+        }
+
+        pos = adjustPositionForFigure(pos);
+
+        return pos;
+    }
+
+    // This is used for nodes that can potentially be the right match for a hit test, but for
+    // which caretRangeFromPoint() returns the wrong result
+    function nodeMayContainPos(node)
+    {
+        return ((node._type == HTML_IMG) || isEmptyNoteNode(node));
+    }
+
+    function elementContainsPoint(element,x,y)
+    {
+        var rect = element.getBoundingClientRect();
+        return ((x >= rect.left) && (x <= rect.right) &&
+                (y >= rect.top) && (y <= rect.bottom));
+    }
+
+    function isEmptyParagraphNode(node)
+    {
+        return ((node._type == HTML_P) &&
+                (node.lastChild != null) &&
+                (node.lastChild._type == HTML_BR) &&
+                !nodeHasContent(node));
+    }
+
+    function findLastTextRect()
+    {
+        var node = lastDescendant(document.body);
+
+        while ((node != null) &&
+               ((node.nodeType != Node.TEXT_NODE) || isWhitespaceTextNode(node))) {
+            if (isEmptyParagraphNode(node))
+                return node.getBoundingClientRect();
+            node = prevNode(node);
+        }
+
+        if (node != null) {
+            var domRange = document.createRange();
+            domRange.setStart(node,0);
+            domRange.setEnd(node,node.nodeValue.length);
+            var rects = domRange.getClientRects();
+            if ((rects != null) && (rects.length > 0))
+                return rects[rects.length-1];
+        }
+        return null;
+    }
+
+    function findFirstTextRect()
+    {
+        var node = firstDescendant(document.body);
+
+        while ((node != null) &&
+               ((node.nodeType != Node.TEXT_NODE) || isWhitespaceTextNode(node))) {
+            if (isEmptyParagraphNode(node))
+                return node.getBoundingClientRect();
+            node = nextNode(node);
+        }
+
+        if (node != null) {
+            var domRange = document.createRange();
+            domRange.setStart(node,0);
+            domRange.setEnd(node,node.nodeValue.length);
+            var rects = domRange.getClientRects();
+            if ((rects != null) && (rects.length > 0))
+                return rects[0];
+        }
+        return null;
+    }
+
+    function adjustPositionForFigure(position)
+    {
+        if (position == null)
+            return null;
+        if (position.node._type == HTML_FIGURE) {
+            var prev = position.node.childNodes[position.offset-1];
+            var next = position.node.childNodes[position.offset];
+            if ((prev != null) && (prev._type == HTML_IMG)) {
+                position = new Position(position.node.parentNode,
+                                        DOM_nodeOffset(position.node)+1);
+            }
+            else if ((next != null) && (next._type == HTML_IMG)) {
+                position = new Position(position.node.parentNode,
+                                        DOM_nodeOffset(position.node));
+            }
+        }
+        return position;
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/PostponedActions.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/PostponedActions.js b/experiments/editorFramework/src/Javascript_Layer_0/PostponedActions.js
new file mode 100644
index 0000000..d445536
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/PostponedActions.js
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var PostponedActions_add;
+var PostponedActions_perform;
+
+(function() {
+
+    function PostponedAction(fun,undoDisabled)
+    {
+        this.fun = fun;
+        this.undoDisabled = undoDisabled;
+    }
+
+    var actions = new Array();
+
+    PostponedActions_add = function(action)
+    {
+        actions.push(new PostponedAction(action,UndoManager_isDisabled()));
+    }
+
+    PostponedActions_perform = function()
+    {
+        var count = 0;
+        while (actions.length > 0) {
+            if (count >= 10)
+                throw new Error("Too many postponed actions");
+            var actionsToPerform = actions;
+            actions = new Array();
+            for (var i = 0; i < actionsToPerform.length; i++) {
+                var action = actionsToPerform[i];
+                if (action.undoDisabled)
+                    UndoManager_disableWhileExecuting(action.fun);
+                else
+                    action.fun();
+            }
+            count++;
+        }
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Preview.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Preview.js b/experiments/editorFramework/src/Javascript_Layer_0/Preview.js
new file mode 100644
index 0000000..97f9bf1
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Preview.js
@@ -0,0 +1,139 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Preview_showForStyle;
+
+(function(){
+
+    var previewText =
+        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in diam \n"+
+        "mauris. Integer in lorem sit amet dolor lacinia aliquet. Cras vehicula odio \n"+
+        "non enim euismod nec congue lorem varius. Sed eu libero arcu, eget tempus \n"+
+        "augue. Vivamus varius risus ac libero sagittis eu ultricies lectus \n"+
+        "consequat. Integer gravida accumsan fermentum. Morbi erat ligula, volutpat \n"+
+        "non accumsan sed, pellentesque quis purus. Vestibulum vestibulum tincidunt \n"+
+        "lectus non pellentesque. Quisque porttitor sollicitudin tellus, id porta \n"+
+        "velit interdum sit amet. Cras quis sem orci, vel convallis magna. \n"+
+        "Pellentesque congue, libero et iaculis volutpat, enim turpis sodales dui, \n"+
+        "lobortis pharetra lectus dolor at sem. Nullam aliquam, odio ac laoreet \n"+
+        "vulputate, ligula nunc euismod leo, vel bibendum magna leo ut orci. In \n"+
+        "tortor turpis, pellentesque nec cursus ut, consequat non ipsum. Praesent \n"+
+        "venenatis, leo in pulvinar pharetra, eros nisi convallis elit, vitae luctus \n"+
+        "magna velit ut lorem."
+
+    function setTableCellContents(node)
+    {
+        if (isTableCell(node)) {
+            DOM_deleteAllChildren(node);
+            DOM_appendChild(node,DOM_createTextNode(document,"Cell contents"));
+        }
+        else {
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                setTableCellContents(child);
+        }
+    }
+
+    function showForStyle(styleId,uiName,titleText)
+    {
+        var elementName = null;
+        var className = null;
+
+        var dotPos = styleId.indexOf(".");
+        if (dotPos >= 0) {
+            elementName = styleId.substring(0,dotPos);
+            className = styleId.substring(dotPos+1);
+        }
+        else {
+            elementName = styleId;
+            className = null;
+        }
+
+        var title = DOM_createTextNode(document,titleText);
+        var text = DOM_createTextNode(document,previewText);
+
+        Selection_clear();
+        DOM_deleteAllChildren(document.body);
+
+        if (PARAGRAPH_ELEMENTS[ElementTypes[elementName]]) {
+            var paragraph1 = createParagraphElement(elementName,className);
+            var paragraph2 = createParagraphElement(elementName,className);
+            DOM_appendChild(paragraph1,title);
+            DOM_appendChild(paragraph2,text);
+            DOM_appendChild(document.body,paragraph1);
+            DOM_appendChild(document.body,paragraph2);
+
+            if (className != null) {
+                DOM_setAttribute(paragraph1,"class",className);
+                DOM_setAttribute(paragraph2,"class",className);
+            }
+        }
+        else if (elementName == "span") {
+            var p1 = DOM_createElement(document,"P");
+            var p2 = DOM_createElement(document,"P");
+            var span1 = DOM_createElement(document,"SPAN");
+            var span2 = DOM_createElement(document,"SPAN");
+
+            if (className != null) {
+                DOM_setAttribute(span1,"class",className);
+                DOM_setAttribute(span2,"class",className);
+            }
+
+            DOM_appendChild(span1,title);
+            DOM_appendChild(span2,text);
+
+            DOM_appendChild(p1,span1);
+            DOM_appendChild(p2,span2);
+
+            DOM_appendChild(document.body,p1);
+            DOM_appendChild(document.body,p2);
+        }
+        else if ((elementName == "table") || (elementName == "caption")) {
+            // FIXME: cater for different table styles
+            Selection_selectAll();
+            Tables_insertTable(3,3,"66%",true,"Table caption");
+            Selection_clear();
+            var table = document.getElementsByTagName("TABLE")[0];
+            setTableCellContents(table);
+            if ((elementName == "table") && (className != null))
+                DOM_setAttribute(table,"class",className);
+        }
+        else if ((elementName == "figure") || (elementName == "figcaption")) {
+            Selection_selectAll();
+            Figures_insertFigure("SampleFigure.svg","75%",true,"TCP 3-way handshake");
+            Selection_clear();
+        }
+        else if (elementName == "body") {
+            // We use BR here instead of separate paragraphs, since we don't want the properties
+            // for the P element to be applied
+            DOM_appendChild(document.body,title);
+            DOM_appendChild(document.body,DOM_createElement(document,"BR"));
+            DOM_appendChild(document.body,DOM_createElement(document,"BR"));
+            DOM_appendChild(document.body,text);
+        }
+
+        function createParagraphElement(elementName,className)
+        {
+            var element = DOM_createElement(document,elementName);
+            if (className != null)
+                DOM_setAttribute(element,"class",className);
+            return element;
+        }
+    }
+
+    Preview_showForStyle = showForStyle;
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/README b/experiments/editorFramework/src/Javascript_Layer_0/README
new file mode 100644
index 0000000..10fd5f9
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/README
@@ -0,0 +1 @@
+the javascript files doing the actual in file editing and rendering.

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Range.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Range.js b/experiments/editorFramework/src/Javascript_Layer_0/Range.js
new file mode 100644
index 0000000..8d7c655
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Range.js
@@ -0,0 +1,566 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Range;
+
+var Range_assertValid;
+var Range_isEmpty;
+var Range_trackWhileExecuting;
+var Range_expand;
+var Range_isForwards;
+var Range_getAllNodes;
+var Range_singleNode;
+var Range_ensureInlineNodesInParagraph;
+var Range_ensureValidHierarchy;
+var Range_forwards;
+var Range_detail;
+var Range_getOutermostNodes;
+var Range_getClientRects;
+var Range_cloneContents;
+var Range_hasContent;
+var Range_getText;
+
+(function() {
+
+    Range = function(startNode,startOffset,endNode,endOffset)
+    {
+        this.start = new Position(startNode,startOffset);
+        this.end = new Position(endNode,endOffset);
+    }
+
+    Range_assertValid = function(range,description)
+    {
+        if (description == null)
+            description = "Range";
+        if (range == null)
+            throw new Error(description+" is null");
+        Position_assertValid(range.start,description+" start");
+        Position_assertValid(range.end,description+" end");
+    }
+
+    Range_isEmpty = function(range)
+    {
+        return ((range.start.node == range.end.node) &&
+                (range.start.offset == range.end.offset));
+    }
+
+    Range.prototype.toString = function()
+    {
+        return this.start.toString() + " - " + this.end.toString();
+    }
+
+    Range_trackWhileExecuting = function(range,fun)
+    {
+        if (range == null)
+            return fun();
+        else
+            return Position_trackWhileExecuting([range.start,range.end],fun);
+    }
+
+    Range_expand = function(range)
+    {
+        var doc = range.start.node.ownerDocument;
+        while ((range.start.offset == 0) && (range.start.node != doc.body)) {
+            var offset = DOM_nodeOffset(range.start.node);
+            range.start.node = range.start.node.parentNode;
+            range.start.offset = offset;
+        }
+
+        while ((range.end.offset == DOM_maxChildOffset(range.end.node)) &&
+               (range.end.node != doc.body)) {
+            var offset = DOM_nodeOffset(range.end.node);
+            range.end.node = range.end.node.parentNode;
+            range.end.offset = offset+1;
+        }
+    }
+
+    Range_isForwards = function(range)
+    {
+        return (Position_compare(range.start,range.end) <= 0);
+    }
+
+    Range_getAllNodes = function(range,atLeastOne)
+    {
+        var result = new Array();
+        var outermost = Range_getOutermostNodes(range,atLeastOne);
+        for (var i = 0; i < outermost.length; i++)
+            addRecursive(outermost[i]);
+        return result;
+
+        function addRecursive(node)
+        {
+            result.push(node);
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                addRecursive(child);
+        }
+    }
+
+    Range_singleNode = function(range)
+    {
+        return Position_closestActualNode(range.start,true);
+    }
+
+    Range_ensureInlineNodesInParagraph = function(range)
+    {
+        Range_trackWhileExecuting(range,function() {
+            var nodes = Range_getAllNodes(range,true);
+            for (var i = 0; i < nodes.length; i++)
+                Hierarchy_ensureInlineNodesInParagraph(nodes[i]);
+        });
+    }
+
+    Range_ensureValidHierarchy = function(range,allowDirectInline)
+    {
+        Range_trackWhileExecuting(range,function() {
+            var nodes = Range_getAllNodes(range,true);
+            for (var i = nodes.length-1; i >= 0; i--)
+                Hierarchy_ensureValidHierarchy(nodes[i],true,allowDirectInline);
+        });
+    }
+
+    Range_forwards = function(range)
+    {
+        if (Range_isForwards(range)) {
+            return range;
+        }
+        else {
+            var reverse = new Range(range.end.node,range.end.offset,
+                                    range.start.node,range.start.offset);
+            if (!Range_isForwards(reverse))
+                throw new Error("Both range "+range+" and its reverse are not forwards");
+            return reverse;
+        }
+    }
+
+    Range_detail = function(range)
+    {
+        if (!Range_isForwards(range)) {
+            var reverse = new Range(range.end.node,range.end.offset,
+                                    range.start.node,range.start.offset);
+            if (!Range_isForwards(reverse))
+                throw new Error("Both range "+range+" and its reverse are not forwards");
+            return Range_detail(reverse);
+        }
+
+        var detail = new Object();
+        var start = range.start;
+        var end = range.end;
+
+        // Start location
+        if (start.node.nodeType == Node.ELEMENT_NODE) {
+            detail.startParent = start.node;
+            detail.startChild = start.node.childNodes[start.offset];
+        }
+        else {
+            detail.startParent = start.node.parentNode;
+            detail.startChild = start.node;
+        }
+
+        // End location
+        if (end.node.nodeType == Node.ELEMENT_NODE) {
+            detail.endParent = end.node;
+            detail.endChild = end.node.childNodes[end.offset];
+        }
+        else if (end.offset == 0) {
+            detail.endParent = end.node.parentNode;
+            detail.endChild = end.node;
+        }
+        else {
+            detail.endParent = end.node.parentNode;
+            detail.endChild = end.node.nextSibling;
+        }
+
+        // Common ancestor
+        var startP = detail.startParent;
+        var startC = detail.startChild;
+        while (startP != null) {
+            var endP = detail.endParent;
+            var endC = detail.endChild
+            while (endP != null) {
+                if (startP == endP) {
+                    detail.commonAncestor = startP;
+                    detail.startAncestor = startC;
+                    detail.endAncestor = endC;
+                    // Found it
+                    return detail;
+                }
+                endC = endP;
+                endP = endP.parentNode;
+            }
+            startC = startP;
+            startP = startP.parentNode;
+        }
+        throw new Error("Start and end of range have no common ancestor");
+    }
+
+    Range_getOutermostNodes = function(range,atLeastOne,info)
+    {
+        var beforeNodes = new Array();
+        var middleNodes = new Array();
+        var afterNodes = new Array();
+
+        if (info != null) {
+            info.beginning = beforeNodes;
+            info.middle = middleNodes;
+            info.end = afterNodes;
+        }
+
+        if (Range_isEmpty(range))
+            return atLeastOne ? [Range_singleNode(range)] : [];
+
+        // Note: start and end are *points* - they are always *in between* nodes or characters, never
+        // *at* a node or character.
+        // Everything after the end point is excluded from the selection
+        // Everything after the start point, but before the end point, is included in the selection
+
+        // We use (parent,child) pairs so that we have a way to represent a point that comes after all
+        // the child nodes in a container - in which case the child is null. The parent, however, is
+        // always non-null;
+
+        var detail = Range_detail(range);
+        if (detail.commonAncestor == null)
+            return atLeastOne ? [Range_singleNode(range)] : [];
+        var startParent = detail.startParent;
+        var startChild = detail.startChild;
+        var endParent = detail.endParent;
+        var endChild = detail.endChild;
+        var commonParent = detail.commonAncestor;
+        var startAncestor = detail.startAncestor;
+        var endAncestor = detail.endAncestor;
+
+        // Add start nodes
+        var topParent = startParent;
+        var topChild = startChild;
+        while (topParent != commonParent) {
+            if (topChild != null)
+                beforeNodes.push(topChild);
+
+            while (((topChild == null) || (topChild.nextSibling == null)) &&
+                   (topParent != commonParent)) {
+                topChild = topParent;
+                topParent = topParent.parentNode;
+            }
+            if (topParent != commonParent)
+                topChild = topChild.nextSibling;
+        }
+
+        // Add middle nodes
+        if (startAncestor != endAncestor) {
+            var c = startAncestor;
+            if ((c != null) && (c != startChild))
+                c = c.nextSibling;
+            for (; c != endAncestor; c = c.nextSibling)
+                middleNodes.push(c);
+        }
+
+        // Add end nodes
+        var bottomParent = endParent;
+        var bottomChild = endChild;
+        while (true) {
+
+            while ((getPreviousSibling(bottomParent,bottomChild) == null) &&
+                   (bottomParent != commonParent)) {
+                bottomChild = bottomParent;
+                bottomParent = bottomParent.parentNode;
+            }
+            if (bottomParent != commonParent)
+                bottomChild = getPreviousSibling(bottomParent,bottomChild);
+
+            if (bottomParent == commonParent)
+                break;
+
+            afterNodes.push(bottomChild);
+        }
+        afterNodes = afterNodes.reverse();
+
+        var result = new Array();
+
+        Array.prototype.push.apply(result,beforeNodes);
+        Array.prototype.push.apply(result,middleNodes);
+        Array.prototype.push.apply(result,afterNodes);
+
+        if (result.length == 0)
+            return atLeastOne ? [Range_singleNode(range)] : [];
+        else
+            return result;
+
+        function getPreviousSibling(parent,child)
+        {
+            if (child != null)
+                return child.previousSibling;
+            else if (parent.lastChild != null)
+                return parent.lastChild;
+            else
+                return null;
+        }
+
+        function isAncestorLocation(ancestorParent,ancestorChild,
+                                    descendantParent,descendantChild)
+        {
+            while ((descendantParent != null) &&
+                   ((descendantParent != ancestorParent) || (descendantChild != ancestorChild))) {
+                descendantChild = descendantParent;
+                descendantParent = descendantParent.parentNode;
+            }
+
+            return ((descendantParent == ancestorParent) &&
+                    (descendantChild == ancestorChild));
+        }
+    }
+
+    Range_getClientRects = function(range)
+    {
+        var nodes = Range_getOutermostNodes(range,true);
+
+        // WebKit in iOS 5.0 and 5.1 has a bug where if the selection spans multiple paragraphs,
+        // the complete rect for paragraphs other than the first is returned, instead of just the
+        // portions of it that are actually in the range. To get around this problem, we go through
+        // each text node individually and collect all the rects.
+        var result = new Array();
+        var doc = range.start.node.ownerDocument;
+        var domRange = doc.createRange();
+        for (var nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {
+            var node = nodes[nodeIndex];
+            if (node.nodeType == Node.TEXT_NODE) {
+                var startOffset = (node == range.start.node) ? range.start.offset : 0;
+                var endOffset = (node == range.end.node) ? range.end.offset : node.nodeValue.length;
+                domRange.setStart(node,startOffset);
+                domRange.setEnd(node,endOffset);
+                var rects = domRange.getClientRects();
+                for (var rectIndex = 0; rectIndex < rects.length; rectIndex++) {
+                    var rect = rects[rectIndex];
+                    if (Main_clientRectsBug) {
+                        // Apple Bug ID 14682166 - getClientRects() returns coordinates relative
+                        // to top of document, when it should instead return coordinates relative
+                        // to the current client view (that is, taking into account scroll offsets)
+                        result.push({ left: rect.left - window.scrollX,
+                                      right: rect.right - window.scrollX,
+                                      top: rect.top - window.scrollY,
+                                      bottom: rect.bottom - window.scrollY,
+                                      width: rect.width,
+                                      height: rect.height });
+                    }
+                    else {
+                        result.push(rect);
+                    }
+                }
+            }
+            else if (node.nodeType == Node.ELEMENT_NODE) {
+                result.push(node.getBoundingClientRect());
+            }
+        }
+        return result;
+    }
+
+    Range_cloneContents = function(range)
+    {
+        var nodeSet = new NodeSet();
+        var ancestorSet = new NodeSet();
+        var detail = Range_detail(range);
+        var outermost = Range_getOutermostNodes(range);
+
+        var haveContent = false;
+        for (var i = 0; i < outermost.length; i++) {
+            if (!isWhitespaceTextNode(outermost[i]))
+                haveContent = true;
+            nodeSet.add(outermost[i]);
+            for (var node = outermost[i]; node != null; node = node.parentNode)
+                ancestorSet.add(node);
+        }
+
+        if (!haveContent)
+            return new Array();
+
+        var clone = recurse(detail.commonAncestor);
+
+        var ancestor = detail.commonAncestor;
+        while (isInlineNode(ancestor)) {
+            var ancestorClone = DOM_cloneNode(ancestor.parentNode,false);
+            DOM_appendChild(ancestorClone,clone);
+            ancestor = ancestor.parentNode;
+            clone = ancestorClone;
+        }
+
+        var childArray = new Array();
+        switch (clone._type) {
+        case HTML_UL:
+        case HTML_OL:
+            childArray.push(clone);
+            break;
+        default:
+            for (var child = clone.firstChild; child != null; child = child.nextSibling)
+                childArray.push(child);
+            Formatting_pushDownInlineProperties(childArray);
+            break;
+        }
+
+        return childArray;
+
+        function recurse(parent)
+        {
+            var clone = DOM_cloneNode(parent,false);
+            for (var child = parent.firstChild; child != null; child = child.nextSibling) {
+                if (nodeSet.contains(child)) {
+                    if ((child.nodeType == Node.TEXT_NODE) &&
+                        (child == range.start.node) &&
+                        (child == range.end.node)) {
+                        var substring = child.nodeValue.substring(range.start.offset,
+                                                                  range.end.offset);
+                        DOM_appendChild(clone,DOM_createTextNode(document,substring));
+                    }
+                    else if ((child.nodeType == Node.TEXT_NODE) &&
+                             (child == range.start.node)) {
+                        var substring = child.nodeValue.substring(range.start.offset);
+                        DOM_appendChild(clone,DOM_createTextNode(document,substring));
+                    }
+                    else if ((child.nodeType == Node.TEXT_NODE) &&
+                             (child == range.end.node)) {
+                        var substring = child.nodeValue.substring(0,range.end.offset);
+                        DOM_appendChild(clone,DOM_createTextNode(document,substring));
+                    }
+                    else {
+                        DOM_appendChild(clone,DOM_cloneNode(child,true));
+                    }
+                }
+                else if (ancestorSet.contains(child)) {
+                    DOM_appendChild(clone,recurse(child));
+                }
+            }
+            return clone;
+        }
+    }
+
+    Range_hasContent = function(range)
+    {
+        var outermost = Range_getOutermostNodes(range);
+        for (var i = 0; i < outermost.length; i++) {
+            var node = outermost[i];
+            if (node.nodeType == Node.TEXT_NODE) {
+                var value = node.nodeValue;
+                if ((node == range.start.node) && (node == range.end.node)) {
+                    if (!isWhitespaceString(value.substring(range.start.offset,range.end.offset)))
+                        return true;
+                }
+                else if (node == range.start.node) {
+                    if (!isWhitespaceString(value.substring(range.start.offset)))
+                        return true;
+                }
+                else if (node == range.end.node) {
+                    if (!isWhitespaceString(value.substring(0,range.end.offset)))
+                        return true;
+                }
+                else {
+                    if (!isWhitespaceString(value))
+                        return true;
+                }
+            }
+            else if (node.nodeType == Node.ELEMENT_NODE) {
+                if (nodeHasContent(node))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    Range_getText = function(range)
+    {
+        range = Range_forwards(range);
+
+        var start = range.start;
+        var end = range.end;
+
+        var startNode = start.node;
+        var startOffset = start.offset;
+
+        if (start.node.nodeType == Node.ELEMENT_NODE) {
+            if ((start.node.offset == start.node.childNodes.length) &&
+                (start.node.offset > 0))
+                startNode = nextNodeAfter(start.node);
+            else
+                startNode = start.node.childNodes[start.offset];
+            startOffset = 0;
+        }
+
+        var endNode = end.node;
+        var endOffset = end.offset;
+
+        if (end.node.nodeType == Node.ELEMENT_NODE) {
+            if ((end.node.offset == end.node.childNodes.length) &&
+                (end.node.offset > 0))
+                endNode = nextNodeAfter(end.node);
+            else
+                endNode = end.node.childNodes[end.offset];
+            endOffset = 0;
+        }
+
+        if ((startNode == null) || (endNode == null))
+            return "";
+
+        var components = new Array();
+        var node = startNode;
+        var significantParagraph = true;
+        while (true) {
+            if (node == null)
+                throw new Error("Cannot find end node");
+
+            if (node.nodeType == Node.TEXT_NODE) {
+
+                if (!significantParagraph && !isWhitespaceString(node.nodeValue)) {
+                    significantParagraph = true;
+                    components.push("\n");
+                }
+
+                if (significantParagraph) {
+                    var str;
+                    if ((node == startNode) && (node == endNode))
+                        str = node.nodeValue.substring(startOffset,endOffset);
+                    else if (node == startNode)
+                        str = node.nodeValue.substring(startOffset);
+                    else if (node == endNode)
+                        str = node.nodeValue.substring(0,endOffset);
+                    else
+                        str = node.nodeValue;
+                    str = str.replace(/\s+/g," ");
+                    components.push(str);
+                }
+            }
+
+            if (node == endNode)
+                break;
+
+
+            var next = nextNode(node,entering,exiting);
+            node = next;
+        }
+        return components.join("");
+
+        function entering(n)
+        {
+            if (isParagraphNode(n)) {
+                significantParagraph = true;
+                components.push("\n");
+            }
+        }
+
+        function exiting(n)
+        {
+            if (isParagraphNode(n))
+                significantParagraph = false;
+        }
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Scan.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Scan.js b/experiments/editorFramework/src/Javascript_Layer_0/Scan.js
new file mode 100644
index 0000000..e6cf4f5
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Scan.js
@@ -0,0 +1,179 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Scan_reset;
+var Scan_next;
+var Scan_addMatch;
+var Scan_showMatch;
+var Scan_replaceMatch;
+var Scan_removeMatch;
+var Scan_goToMatch;
+
+(function() {
+
+    function Match(matchId,startPos,endPos)
+    {
+        this.matchId = matchId;
+        this.startPos = startPos;
+        this.endPos = endPos;
+        this.spans = new Array();
+    }
+
+    var matchesById = new Object();
+    var nextMatchId = 1;
+
+    var curPos = null;
+    var curParagraph = null;
+
+    Scan_reset = function()
+    {
+        curPos = new Position(document.body,0);
+        curParagraph = null;
+        clearMatches();
+    }
+
+    Scan_next = function() {
+        if (curPos == null)
+            return null;
+        curPos = Text_toEndOfBoundary(curPos,"paragraph");
+        if (curPos == null)
+            return null;
+
+        curParagraph = Text_analyseParagraph(curPos);
+        if (curParagraph == null)
+            return null;
+
+        curPos = Position_nextMatch(curPos,Position_okForMovement);
+
+        var sectionId = null;
+        if (isHeadingNode(curParagraph.node) &&
+            (curParagraph.startOffset == 0) &&
+            (curParagraph.endOffset == curParagraph.node.childNodes.length)) {
+            sectionId = DOM_getAttribute(curParagraph.node,"id");
+        }
+
+        return { text: curParagraph.text,
+                 sectionId: sectionId };
+    }
+
+    Scan_addMatch = function(start,end) {
+        if (curParagraph == null)
+            throw new Error("curParagraph is null");
+        if ((start < 0) || (start > curParagraph.text.length))
+            throw new Error("invalid start");
+        if ((end < start) || (end > curParagraph.text.length))
+            throw new Error("invalid end");
+
+        var matchId = nextMatchId++;
+
+        var startRun = Paragraph_runFromOffset(curParagraph,start);
+        var endRun = Paragraph_runFromOffset(curParagraph,end);
+
+        if (startRun == null)
+            throw new Error("No start run");
+        if (endRun == null)
+            throw new Error("No end run");
+
+        var startPos = new Position(startRun.node,start - startRun.start);
+        var endPos = new Position(endRun.node,end - endRun.start);
+        Position_track(startPos);
+        Position_track(endPos);
+
+        var match = new Match(matchId,startPos,endPos);
+        matchesById[matchId] = match;
+        return matchId;
+    }
+
+    Scan_showMatch = function(matchId)
+    {
+        var match = matchesById[matchId];
+        if (match == null)
+            throw new Error("Match "+matchId+" not found");
+
+        var range = new Range(match.startPos.node,match.startPos.offset,
+                              match.endPos.node,match.endPos.offset);
+        var text = Range_getText(range);
+        Formatting_splitAroundSelection(range,true);
+        var outermost = Range_getOutermostNodes(range);
+        for (var i = 0; i < outermost.length; i++) {
+            var span = DOM_wrapNode(outermost[i],"SPAN");
+            DOM_setAttribute(span,"class",Keys.MATCH_CLASS);
+            match.spans.push(span);
+        }
+    }
+
+    Scan_replaceMatch = function(matchId,replacement)
+    {
+        var match = matchesById[matchId];
+        if (match == null)
+            throw new Error("Match "+matchId+" not found");
+
+        if (match.spans.length == 0)
+            return;
+
+        var span = match.spans[0];
+
+        Selection_preserveWhileExecuting(function() {
+            var replacementNode = DOM_createTextNode(document,replacement);
+            DOM_insertBefore(span.parentNode,replacementNode,span);
+
+            for (var i = 0; i < match.spans.length; i++)
+                DOM_deleteNode(match.spans[i]);
+
+            Formatting_mergeUpwards(replacementNode,Formatting_MERGEABLE_INLINE);
+        });
+
+        delete matchesById[matchId];
+    }
+
+    function removeSpansForMatch(match)
+    {
+        for (var i = 0; i < match.spans.length; i++)
+            DOM_removeNodeButKeepChildren(match.spans[i]);
+    }
+
+    Scan_removeMatch = function(matchId)
+    {
+        removeSpansForMatch(matchesById[matchId]);
+        delete matchesById[matchId];
+    }
+
+    Scan_goToMatch = function(matchId)
+    {
+        var match = matchesById[matchId];
+        if (match == null)
+            throw new Error("Match "+matchId+" not found");
+
+        Selection_set(match.startPos.node,match.startPos.offset,
+                      match.endPos.node,match.endPos.offset);
+        Cursor_ensurePositionVisible(match.startPos,true);
+    }
+
+    function clearMatches()
+    {
+        for (var matchId in matchesById) {
+            var match = matchesById[matchId];
+            removeSpansForMatch(match);
+            Position_untrack(match.startPos);
+            Position_untrack(match.endPos);
+        }
+
+        matchesById = new Object();
+        nextMatchId = 1;
+    }
+
+})();


[02/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer2_API/EDJSInterface.m
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer2_API/EDJSInterface.m b/experiments/editorFramework/src/Layer2_API/EDJSInterface.m
deleted file mode 100644
index 5e34546..0000000
--- a/experiments/editorFramework/src/Layer2_API/EDJSInterface.m
+++ /dev/null
@@ -1,1759 +0,0 @@
-//
-//  EDJSInterface.m
-//  Editor
-//
-//  Created by Peter Kelly on 22/11/11.
-//  Copyright (c) 2011-2014 UX Productivity Pty Ltd. All rights reserved.
-//
-
-#import "EDJSInterface.h"
-#import "EDScan.h"
-#import "EDUtil.h"
-#import <FileClient/FCError.h>
-#import <FileClient/FCUtil.h>
-
-typedef enum {
-    AutoCorrect_correctPrecedingWord,
-    AutoCorrect_getCorrection,
-    AutoCorrect_getCorrectionCoords,
-    AutoCorrect_acceptCorrection,
-    AutoCorrect_replaceCorrection,
-    ChangeTracking_showChanges,
-    ChangeTracking_trackChanges,
-    ChangeTracking_setShowChanges,
-    ChangeTracking_setTrackChanges,
-    Clipboard_cut,
-    Clipboard_copy,
-    Clipboard_pasteHTML,
-    Clipboard_pasteText,
-    Cursor_positionCursor,
-    Cursor_getCursorPosition,
-    Cursor_moveLeft,
-    Cursor_moveRight,
-    Cursor_moveToStartOfDocument,
-    Cursor_moveToEndOfDocument,
-    Cursor_insertReference,
-    Cursor_insertLink,
-    Cursor_insertCharacter,
-    Cursor_deleteCharacter,
-    Cursor_enterPressed,
-    Cursor_getPrecedingWord,
-    Cursor_getLinkProperties,
-    Cursor_setLinkProperties,
-    Cursor_setReferenceTarget,
-    Cursor_insertFootnote,
-    Cursor_insertEndnote,
-    Editor_getBackMessages,
-    Equations_insertEquation,
-    Figures_insertFigure,
-    Figures_getSelectedFigureId,
-    Figures_getProperties,
-    Figures_setProperties,
-    Figures_getGeometry,
-    Formatting_getFormatting,
-    Formatting_applyFormattingChanges,
-    Input_removePosition,
-    Input_textInRange,
-    Input_replaceRange,
-    Input_selectedTextRange,
-    Input_setSelectedTextRange,
-    Input_markedTextRange,
-    Input_setMarkedText,
-    Input_unmarkText,
-    Input_forwardSelectionAffinity,
-    Input_setForwardSelectionAffinity,
-    Input_positionFromPositionOffset,
-    Input_positionFromPositionInDirectionOffset,
-    Input_comparePositionToPosition,
-    Input_offsetFromPositionToPosition,
-    Input_positionWithinRangeFarthestInDirection,
-    Input_characterRangeByExtendingPositionInDirection,
-    Input_firstRectForRange,
-    Input_caretRectForPosition,
-    Input_closestPositionToPoint,
-    Input_closestPositionToPointWithinRange,
-    Input_characterRangeAtPoint,
-    Input_positionWithinRangeAtCharacterOffset,
-    Input_characterOffsetOfPositionWithinRange,
-    Input_isPositionAtBoundaryGranularityInDirection,
-    Input_isPositionWithinTextUnitInDirection,
-    Input_positionFromPositionToBoundaryInDirection,
-    Input_rangeEnclosingPositionWithGranularityInDirection,
-    Lists_increaseIndent,
-    Lists_decreaseIndent,
-    Lists_clearList,
-    Lists_setUnorderedList,
-    Lists_setOrderedList,
-    Main_getLanguage,
-    Main_setLanguage,
-    Main_setGenerator,
-    Main_init,
-    Main_getErrorReportingInfo,
-    Main_execute,
-    Main_prepareForSave,
-    Main_getHTML,
-    Main_isEmptyDocument,
-    Metadata_getMetadata,
-    Metadata_setMetadata,
-    Outline_moveSection,
-    Outline_deleteItem,
-    Outline_goToItem,
-    Outline_scheduleUpdateStructure,
-    Outline_setNumbered,
-    Outline_setTitle,
-    Outline_getOutline,
-    Outline_insertTableOfContents,
-    Outline_insertListOfFigures,
-    Outline_insertListOfTables,
-    Outline_setPrintMode,
-    Outline_examinePrintLayout,
-    Outline_detectSectionNumbering,
-    Outline_findUsedStyles,
-    Preview_showForStyle,
-    Scan_reset,
-    Scan_next,
-    Scan_addMatch,
-    Scan_showMatch,
-    Scan_replaceMatch,
-    Scan_removeMatch,
-    Scan_goToMatch,
-    Selection_update,
-    Selection_selectAll,
-    Selection_selectParagraph,
-    Selection_selectWordAtCursor,
-    Selection_dragSelectionBegin,
-    Selection_dragSelectionUpdate,
-    Selection_moveStartLeft,
-    Selection_moveStartRight,
-    Selection_moveEndLeft,
-    Selection_moveEndRight,
-    Selection_setSelectionStartAtCoords,
-    Selection_setSelectionEndAtCoords,
-    Selection_setTableSelectionEdgeAtCoords,
-    Selection_print,
-    Styles_getCSSText,
-    Styles_setCSSText,
-    Styles_getParagraphClass,
-    Styles_setParagraphClass,
-    Tables_insertTable,
-    Tables_addAdjacentRow,
-    Tables_addAdjacentColumn,
-    Tables_removeAdjacentRow,
-    Tables_removeAdjacentColumn,
-    Tables_clearCells,
-    Tables_mergeCells,
-    Tables_splitSelection,
-    Tables_getSelectedTableId,
-    Tables_getProperties,
-    Tables_setProperties,
-    Tables_setColWidths,
-    Tables_getGeometry,
-    UndoManager_getLength,
-    UndoManager_getIndex,
-    UndoManager_setIndex,
-    UndoManager_undo,
-    UndoManager_redo,
-    UndoManager_newGroup,
-    UndoManager_groupType,
-    Viewport_setViewportWidth,
-    Viewport_setTextScale,
-    JSInterfaceFunctionCount,
-} JSInterfaceFunction;
-
-static BOOL functionModifiesDocument(JSInterfaceFunction fun)
-{
-    switch (fun)
-    {
-        case AutoCorrect_correctPrecedingWord:
-        case AutoCorrect_acceptCorrection:
-        case AutoCorrect_replaceCorrection:
-        case ChangeTracking_setShowChanges:
-        case ChangeTracking_setTrackChanges:
-        case Clipboard_cut:
-        case Clipboard_pasteHTML:
-        case Clipboard_pasteText:
-        case Cursor_insertReference:
-        case Cursor_insertLink:
-        case Cursor_insertCharacter:
-        case Cursor_deleteCharacter:
-        case Cursor_enterPressed:
-        case Cursor_setLinkProperties:
-        case Cursor_setReferenceTarget:
-        case Cursor_insertFootnote:
-        case Cursor_insertEndnote:
-        case Equations_insertEquation:
-        case Figures_insertFigure:
-        case Figures_setProperties:
-        case Formatting_applyFormattingChanges:
-        case Lists_increaseIndent:
-        case Lists_decreaseIndent:
-        case Lists_clearList:
-        case Lists_setUnorderedList:
-        case Lists_setOrderedList:
-        case Main_setLanguage:
-        case Main_prepareForSave:
-        case Metadata_setMetadata:
-        case Outline_moveSection:
-        case Outline_deleteItem:
-        case Outline_scheduleUpdateStructure:
-        case Outline_setNumbered:
-        case Outline_setTitle:
-        case Outline_insertTableOfContents:
-        case Outline_insertListOfFigures:
-        case Outline_insertListOfTables:
-        case Outline_setPrintMode:
-        case Outline_examinePrintLayout:
-        case Scan_replaceMatch:
-        case Styles_setCSSText:
-        case Tables_insertTable:
-        case Tables_addAdjacentRow:
-        case Tables_addAdjacentColumn:
-        case Tables_removeAdjacentRow:
-        case Tables_removeAdjacentColumn:
-        case Tables_clearCells:
-        case Tables_mergeCells:
-        case Tables_splitSelection:
-        case Tables_setProperties:
-        case Tables_setColWidths:
-        case UndoManager_undo:
-        case UndoManager_redo:
-            return true;
-        case AutoCorrect_getCorrection:
-        case AutoCorrect_getCorrectionCoords:
-        case ChangeTracking_showChanges:
-        case ChangeTracking_trackChanges:
-        case Clipboard_copy:
-        case Cursor_positionCursor:
-        case Cursor_getCursorPosition:
-        case Cursor_moveLeft:
-        case Cursor_moveRight:
-        case Cursor_moveToStartOfDocument:
-        case Cursor_moveToEndOfDocument:
-        case Cursor_getPrecedingWord:
-        case Cursor_getLinkProperties:
-        case Editor_getBackMessages:
-        case Figures_getSelectedFigureId:
-        case Figures_getProperties:
-        case Figures_getGeometry:
-        case Formatting_getFormatting:
-        case Input_removePosition:
-        case Input_textInRange:
-        case Input_replaceRange:
-        case Input_selectedTextRange:
-        case Input_setSelectedTextRange:
-        case Input_markedTextRange:
-        case Input_setMarkedText:
-        case Input_unmarkText:
-        case Input_forwardSelectionAffinity:
-        case Input_setForwardSelectionAffinity:
-        case Input_positionFromPositionOffset:
-        case Input_positionFromPositionInDirectionOffset:
-        case Input_comparePositionToPosition:
-        case Input_offsetFromPositionToPosition:
-        case Input_positionWithinRangeFarthestInDirection:
-        case Input_characterRangeByExtendingPositionInDirection:
-        case Input_firstRectForRange:
-        case Input_caretRectForPosition:
-        case Input_closestPositionToPoint:
-        case Input_closestPositionToPointWithinRange:
-        case Input_characterRangeAtPoint:
-        case Input_positionWithinRangeAtCharacterOffset:
-        case Input_characterOffsetOfPositionWithinRange:
-        case Input_isPositionAtBoundaryGranularityInDirection:
-        case Input_isPositionWithinTextUnitInDirection:
-        case Input_positionFromPositionToBoundaryInDirection:
-        case Input_rangeEnclosingPositionWithGranularityInDirection:
-        case Main_getLanguage:
-        case Main_setGenerator:
-        case Main_init:
-        case Main_getErrorReportingInfo:
-        case Main_execute:
-        case Main_getHTML:
-        case Main_isEmptyDocument:
-        case Metadata_getMetadata:
-        case Outline_getOutline:
-        case Outline_goToItem:
-        case Outline_detectSectionNumbering:
-        case Outline_findUsedStyles:
-        case Preview_showForStyle:
-        case Scan_reset:
-        case Scan_next:
-        case Scan_addMatch:
-        case Scan_showMatch:
-        case Scan_removeMatch:
-        case Scan_goToMatch:
-        case Selection_update:
-        case Selection_selectAll:
-        case Selection_selectParagraph:
-        case Selection_selectWordAtCursor:
-        case Selection_dragSelectionBegin:
-        case Selection_dragSelectionUpdate:
-        case Selection_moveStartLeft:
-        case Selection_moveStartRight:
-        case Selection_moveEndLeft:
-        case Selection_moveEndRight:
-        case Selection_setSelectionStartAtCoords:
-        case Selection_setSelectionEndAtCoords:
-        case Selection_setTableSelectionEdgeAtCoords:
-        case Selection_print:
-        case Styles_getCSSText:
-        case Styles_getParagraphClass:
-        case Styles_setParagraphClass:
-        case Tables_getSelectedTableId:
-        case Tables_getProperties:
-        case Tables_getGeometry:
-        case UndoManager_getLength:
-        case UndoManager_getIndex:
-        case UndoManager_setIndex:
-        case UndoManager_newGroup:
-        case UndoManager_groupType:
-        case Viewport_setViewportWidth:
-        case Viewport_setTextScale:
-        case JSInterfaceFunctionCount:
-            return false;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                             JSError                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSError
-
-- (JSError *)initWithType:(NSString *)type
-                  message:(NSString *)message
-                operation:(NSString *)operation
-                     html:(NSString *)html
-{
-    if (!(self = [super init]))
-        return nil;
-    _type = [type copy];
-    _message = [message copy];
-    _operation = [operation copy];
-    _html = [html copy];
-    return self;
-}
-
-- (NSString *)description
-{
-    NSMutableString *errorInfo = [NSMutableString stringWithCapacity: 0];
-    [errorInfo appendFormat: @"%@\n", _message];
-    [errorInfo appendFormat: @"Operation: %@\n", _operation];
-    [errorInfo appendFormat: @"\n"];
-    [errorInfo appendFormat: @"HTML:\n%@\n", _html];
-    return errorInfo;
-}
-
-- (NSString *)localizedDescription
-{
-    return [self description];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                           JSInterface                                          //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSInterface
-{
-    NSUInteger _numCalls[JSInterfaceFunctionCount];
-    NSTimeInterval _timeUsed[JSInterfaceFunctionCount];
-    NSTimeInterval _totalTimeUsed;
-}
-
-- (JSInterface *)initWithEvaluator:(NSObject<JSEvaluator> *)evaluator
-{
-    if (!(self = [super init]))
-        return nil;
-    _evaluator = evaluator;
-
-    _autoCorrect = [[JSAutoCorrect alloc] initWithJS: self];
-    _changeTracking = [[JSChangeTracking alloc] initWithJS: self];
-    _clipboard = [[JSClipboard alloc] initWithJS: self];
-    _cursor = [[JSCursor alloc] initWithJS: self];
-    _equations = [[JSEquations alloc] initWithJS: self];
-    _figures = [[JSFigures alloc] initWithJS: self];
-    _formatting = [[JSFormatting alloc] initWithJS: self];
-    _input = [[JSInput alloc] initWithJS: self];
-    _lists = [[JSLists alloc] initWithJS: self];
-    _main = [[JSMain alloc] initWithJS: self];
-    _metadata = [[JSMetadata alloc] initWithJS: self];
-    _outline = [[JSOutline alloc] initWithJS: self];
-    _preview = [[JSPreview alloc] initWithJS: self];
-    _scan = [[JSScan alloc] initWithJS: self];
-    _selection = [[JSSelection alloc] initWithJS: self];
-    _styles = [[JSStyles alloc] initWithJS: self];
-    _tables = [[JSTables alloc] initWithJS: self];
-    _undoManager = [[JSUndoManager alloc] initWithJS: self];
-    _viewport = [[JSViewport alloc] initWithJS: self];
-
-    return self;
-}
-
-- (void)dealloc
-{
-    _autoCorrect.js = nil;
-    _changeTracking.js = nil;
-    _clipboard.js = nil;
-    _cursor.js = nil;
-    _equations.js = nil;
-    _figures.js = nil;
-    _formatting.js = nil;
-    _input.js = nil;
-    _lists.js = nil;
-    _main.js = nil;
-    _metadata.js = nil;
-    _outline.js = nil;
-    _preview.js = nil;
-    _scan.js = nil;
-    _selection.js = nil;
-    _styles.js = nil;
-    _tables.js = nil;
-    _undoManager.js = nil;
-    _viewport.js = nil;
-}
-
-- (BOOL)initJavaScriptWidth:(int)width textScale:(int)textScale cssURL:(NSString *)cssURL
-             clientRectsBug:(BOOL)clientRectsBug
-{
-    // Special case javascript call to Main_init(). We don't use the normal mechanism here because
-    // at this point the JS interface has not been initialised, and the check for this in
-    // executeJavaScriptWithJSONResult would cause it to fail.
-    NSString *code = [NSString stringWithFormat: @"interface_functions[%d](%d,%d,\"%@\",%@)",
-                      Main_init, width, textScale, cssURL, clientRectsBug ? @"true" : @"false"];
-    NSString *result = [_evaluator stringByEvaluatingJavaScriptFromString: code];
-    [self jsCallCompleted];
-    if ([@"true" isEqualToString: result]) {
-        return YES;
-    }
-    else {
-        self.currentOperation = @"JavaScript initialisation";
-        [self reportErrorWithType: nil format: @"%@", result];
-        self.currentOperation = nil;
-        return NO;
-    }
-}
-
-- (void)jsCallCompleted
-{
-    // Process pending callbacks
-    NSString *getBackMessages = [NSString stringWithFormat: @"interface_functions[%d]()",
-                                 Editor_getBackMessages];
-    NSString *str = [_evaluator stringByEvaluatingJavaScriptFromString: getBackMessages];
-    NSData *data = [str dataUsingEncoding: NSUTF8StringEncoding];
-    NSArray *array = [NSJSONSerialization JSONObjectWithData: data options: 0 error: nil];
-    for (NSArray *message in array)
-        [self dispatchCallbackMessage: message];
-}
-
-- (NSString *)operationStringWithFunction:(JSInterfaceFunction)function nargs:(int)nargs arguments:(va_list)ap
-{
-    NSMutableString *operation = [NSMutableString stringWithCapacity: 0];
-    [operation appendFormat: @"interface_functions[%d](", function];
-    NSObject *arg;
-    for (int argno = 0; argno < nargs; argno++) {
-        arg = va_arg(ap,NSObject*);
-        if (argno > 0)
-            [operation appendString: @","];
-        if (arg == nil) {
-            [operation appendString: @"null"];
-        }
-        else if ([arg isKindOfClass: [NSNumber class]]) {
-            [operation appendString: [arg description]];
-        }
-        else if ([arg isKindOfClass: [NSNull class]]) {
-            [operation appendString: @"null"];
-        }
-        else if ([arg isKindOfClass: [NSArray class]] || [arg isKindOfClass: [NSDictionary class]]) {
-            NSError *err = nil;
-            NSData *data = [NSJSONSerialization dataWithJSONObject: arg options: 0 error: &err];
-            if (data == nil) {
-                [NSException raise: @"NSJSONSerialization"
-                            format: @"executeJavaScript %d: cannot serialise argument %d to JSON: %@",
-                                    function, argno, FCErrorDescription(err)];
-            }
-            else {
-                NSString *str = [[NSString alloc] initWithBytes: data.bytes length: data.length
-                                                       encoding: NSUTF8StringEncoding];
-                [operation appendString: str];
-            }
-        }
-        else {
-            char *quoted = DFQuote(arg.description.UTF8String);
-            NSString *nsQuoted = [NSString stringWithUTF8String: quoted];
-            [operation appendString: nsQuoted];
-            free(quoted);
-        }
-    }
-    [operation appendString: @")"];
-    return operation;
-}
-
-- (id)executeJavaScriptWithJSONResult:(BOOL)jsonResult function:(JSInterfaceFunction)function nargs:(int)nargs arguments:(va_list)ap
-{
-    NSDate *start = [NSDate date];
-    if (!_jsInitialised) {
-        [NSException raise: @"JavaScriptNotInitialised"
-                    format: @"Yet to receive a jsInterfaceInitFinished from JavaScript code"];
-    }
-    self.currentOperation = [self operationStringWithFunction: function nargs: nargs arguments: ap];
-    id result;
-    if (!jsonResult) {
-        NSString *code = [NSString stringWithFormat: @"interface_functions[%d](function() { return %@; });",
-                                                     Main_execute, self.currentOperation];
-        result = [_evaluator stringByEvaluatingJavaScriptFromString: code];
-        [self jsCallCompleted];
-    }
-    else {
-        NSString *code = [NSString stringWithFormat: @"interface_functions[%d](function() { return JSON.stringify(%@); });",
-                                                     Main_execute, self.currentOperation];
-
-        NSString *str = [_evaluator stringByEvaluatingJavaScriptFromString: code];
-        [self jsCallCompleted];
-
-        if ([str isEqualToString: @"null"]) {
-            result = nil;
-        }
-        else {
-            NSData *data = [str dataUsingEncoding: NSUTF8StringEncoding];
-            NSError *err = nil;
-            result = [NSJSONSerialization JSONObjectWithData: data options: 0 error: &err];
-            if (result == nil) {
-                [self reportErrorWithType: nil format: @"Cannot deserialise JSON result \"%@\": %@",
-                 str, FCErrorDescription(err)];
-            }
-        }
-    }
-
-    NSDate *end = [NSDate date];
-    NSTimeInterval interval = [end timeIntervalSinceDate: start];
-    _numCalls[function]++;
-    _timeUsed[function] += interval;
-    _totalTimeUsed += interval;
-
-    self.currentOperation = nil;
-    if (functionModifiesDocument(function))
-        self.documentModified = YES;
-    return result;
-}
-
-- (void)printStatistics
-{
-    if (_totalTimeUsed == 0.0)
-        return;
-
-    printf("\n");
-    printf("%-10s %-10s %-10s %-10s\n","Function","Calls","Time","Time pct");
-
-    NSMutableArray *order = [NSMutableArray arrayWithCapacity: 0];
-    for (NSUInteger i = 0; i < JSInterfaceFunctionCount; i++)
-        [order addObject: [NSNumber numberWithUnsignedInteger: i]];
-    [order sortUsingComparator:^NSComparisonResult(NSNumber *n1, NSNumber *n2) {
-        NSUInteger i1 = n1.unsignedIntValue;
-        NSUInteger i2 = n2.unsignedIntValue;
-        if (_timeUsed[i1] < _timeUsed[i2])
-            return NSOrderedAscending;
-        else if (_timeUsed[i1] > _timeUsed[i2])
-            return NSOrderedDescending;
-        else
-            return NSOrderedSame;
-    }];
-    for (NSNumber *n in order) {
-        NSUInteger i = n.unsignedIntValue;
-        double pct = 100*(_timeUsed[i]/_totalTimeUsed);
-        if (pct >= 0.01) {
-            printf("%-10d %-10d %-10d %.2f%%\n",(int)i,(int)_numCalls[i],(int)(_timeUsed[i]*1000),pct);
-        }
-    }
-    printf("totalTimeUsed = %.2fms\n",1000*_totalTimeUsed);
-}
-
-- (id)executeJavaScriptJSON:(JSInterfaceFunction)function nargs:(int)nargs, ...
-{
-    va_list ap;
-    va_start(ap,nargs);
-    NSString *result = (NSString *)[self executeJavaScriptWithJSONResult: YES
-                                                                function: function
-                                                                   nargs: nargs
-                                                               arguments: ap];
-    va_end(ap);
-    return result;
-}
-
-- (NSString *)executeJavaScript:(JSInterfaceFunction)function nargs:(int)nargs, ...
-{
-    va_list ap;
-    va_start(ap,nargs);
-    NSString *result = (NSString *)[self executeJavaScriptWithJSONResult: NO
-                                                                function: function
-                                                                   nargs: nargs
-                                                               arguments: ap];
-    va_end(ap);
-    return result;
-}
-
-- (void)dispatchCallbackMessage:(NSArray*)array
-{
-    if (array.count == 0)
-        return;
-
-    if (![[array objectAtIndex: 0] isKindOfClass: [NSString class]])
-        return;
-
-    NSString *functionName = [array objectAtIndex: 0];
-
-    if ([functionName isEqualToString: @"debug"] &&
-        ([array count] == 2) &&
-        [[array objectAtIndex: 1] isKindOfClass: [NSString class]]) {
-        NSString *message = [array objectAtIndex: 1];
-        debug(@"%@\n",message);
-    }
-    else if ([functionName isEqualToString: @"addOutlineItem"] &&
-             [_delegate respondsToSelector: @selector(jsAddOutlineItem:type:title:)] &&
-             ([array count] == 4) &&
-             [[array objectAtIndex: 1] isKindOfClass: [NSString class]] &&
-             [[array objectAtIndex: 2] isKindOfClass: [NSString class]]) {
-        // 3 could be a a string or null
-        NSString *title = [array objectAtIndex: 3];
-        if ([title isKindOfClass: [NSNull class]])
-            title = nil;
-        [_delegate jsAddOutlineItem: [array objectAtIndex: 1]
-                              type: [array objectAtIndex: 2]
-                             title: title];
-    }
-    else if ([functionName isEqualToString: @"updateOutlineItem"] &&
-             [_delegate respondsToSelector: @selector(jsUpdateOutlineItem:title:)] &&
-             ([array count] == 3) &&
-             [[array objectAtIndex: 1] isKindOfClass: [NSString class]] &&
-             [[array objectAtIndex: 2] isKindOfClass: [NSString class]]) {
-        [_delegate jsUpdateOutlineItem: [array objectAtIndex: 1] title: [array objectAtIndex: 2]];
-    }
-    else if ([functionName isEqualToString: @"removeOutlineItem"] &&
-             [_delegate respondsToSelector: @selector(jsRemoveOutlineItem:)] &&
-             ([array count] == 2) &&
-             [[array objectAtIndex: 1] isKindOfClass: [NSString class]]) {
-        [_delegate jsRemoveOutlineItem: [array objectAtIndex: 1]];
-    }
-    else if ([functionName isEqualToString: @"outlineUpdated"] &&
-             [_delegate respondsToSelector: @selector(jsOutlineUpdated)] &&
-             [array count] == 1) {
-        [_delegate jsOutlineUpdated];
-    }
-    else if ([functionName isEqualToString: @"setSelectionHandles"] &&
-             [_delegate respondsToSelector: @selector(jsSetSelectionHandlesX1:y1:height1:x2:y2:height2:)] &&
-             ([array count] == 7) &&
-             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 5] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 6] isKindOfClass: [NSNumber class]])) {
-        [_delegate jsSetSelectionHandlesX1: ((NSNumber *)[array objectAtIndex: 1]).intValue
-                                       y1: ((NSNumber *)[array objectAtIndex: 2]).intValue
-                                  height1: ((NSNumber *)[array objectAtIndex: 3]).intValue
-                                       x2: ((NSNumber *)[array objectAtIndex: 4]).intValue
-                                       y2: ((NSNumber *)[array objectAtIndex: 5]).intValue
-                                  height2: ((NSNumber *)[array objectAtIndex: 6]).intValue];
-    }
-    else if ([functionName isEqualToString: @"setTableSelection"] &&
-             [_delegate respondsToSelector: @selector(jsSetTableSelectionX:y:width:height:)] &&
-             ([array count] == 5) &&
-             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]])) {
-        [_delegate jsSetTableSelectionX: ((NSNumber *)[array objectAtIndex: 1]).intValue
-                                     y: ((NSNumber *)[array objectAtIndex: 2]).intValue
-                                 width: ((NSNumber *)[array objectAtIndex: 3]).intValue
-                                height: ((NSNumber *)[array objectAtIndex: 4]).intValue];
-    }
-    else if ([functionName isEqualToString: @"setCursor"] &&
-             [_delegate respondsToSelector: @selector(jsSetCursorX:y:width:height:)] &&
-             ([array count] == 5) &&
-             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]])) {
-        [_delegate jsSetCursorX: ((NSNumber *)[array objectAtIndex: 1]).intValue
-                             y: ((NSNumber *)[array objectAtIndex: 2]).intValue
-                         width: ((NSNumber *)[array objectAtIndex: 3]).intValue
-                        height: ((NSNumber *)[array objectAtIndex: 4]).intValue];
-    }
-    else if ([functionName isEqualToString: @"clearSelectionHandlesAndCursor"] &&
-             [_delegate respondsToSelector: @selector(jsClearSelectionHandlesAndCursor)] &&
-             ([array count] == 1)) {
-        [_delegate jsClearSelectionHandlesAndCursor];
-    }
-    else if ([functionName isEqualToString: @"setSelectionBounds"] &&
-             [_delegate respondsToSelector: @selector(jsSetSelectionBoundsLeft:top:right:bottom:)] &&
-             ([array count] == 5) &&
-             ([[array objectAtIndex: 1] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 2] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 3] isKindOfClass: [NSNumber class]]) &&
-             ([[array objectAtIndex: 4] isKindOfClass: [NSNumber class]])) {
-        [_delegate jsSetSelectionBoundsLeft: ((NSNumber *)[array objectAtIndex: 1]).intValue
-                                       top: ((NSNumber *)[array objectAtIndex: 2]).intValue
-                                     right: ((NSNumber *)[array objectAtIndex: 3]).intValue
-                                    bottom: ((NSNumber *)[array objectAtIndex: 4]).intValue];
-    }
-    else if ([functionName isEqualToString: @"updateAutoCorrect"] &&
-             [_delegate respondsToSelector: @selector(jsUpdateAutoCorrect)]) {
-        [_delegate jsUpdateAutoCorrect];
-    }
-    else if ([functionName isEqualToString: @"error"] &&
-             (array.count == 3) &&
-             [[array objectAtIndex: 1] isKindOfClass: [NSString class]] &&
-             [[array objectAtIndex: 2] isKindOfClass: [NSString class]]) {
-        NSString *message = [array objectAtIndex: 1];
-        NSString *type = [array objectAtIndex: 2];
-        if (type.length == 0)
-            type = nil;
-        [self reportErrorWithType: type format: @"%@", message];
-    }
-}
-
-- (void)reportErrorWithType:(NSString *)type format:(NSString *)format, ...
-{
-    if (self.error != nil)
-        return;
-
-    va_list ap;
-    va_start(ap,format);
-    NSString *basicError = [[NSString alloc] initWithFormat: format arguments: ap];
-    va_end(ap);
-
-    NSString *getErrorReportingInfo = [NSString stringWithFormat: @"interface_functions[%d]()",
-                                       Main_getErrorReportingInfo];
-    NSString *html = [_evaluator stringByEvaluatingJavaScriptFromString: getErrorReportingInfo];
-
-    self.error = [[JSError alloc] initWithType: type
-                                       message: basicError
-                                     operation: self.currentOperation
-                                          html: html];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSModule                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSModule
-
-- (JSModule *)initWithJS:(JSInterface *)js
-{
-    if (!(self = [super init]))
-        return nil;
-    _js = js;
-    return self;
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                          JSAutoCorrect                                         //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSAutoCorrect
-
-- (void)correctPreceding:(int)numChars word:(NSString *)replacement confirmed:(BOOL)confirmed;
-{
-    [self.js executeJavaScript: AutoCorrect_correctPrecedingWord nargs: 3,
-     [NSNumber numberWithInt: numChars], replacement, [NSNumber numberWithBool: confirmed]];
-}
-
-- (NSDictionary *)getCorrection
-{
-    return [self.js executeJavaScriptJSON: AutoCorrect_getCorrection nargs: 0];
-}
-
-- (NSDictionary *)getCorrectionCoords
-{
-    return [self.js executeJavaScriptJSON: AutoCorrect_getCorrectionCoords nargs: 0];
-}
-
-- (void)acceptCorrection
-{
-    [self.js executeJavaScript: AutoCorrect_acceptCorrection nargs: 0];
-}
-
-- (void)replaceCorrection:(NSString *)replacement
-{
-    [self.js executeJavaScript: AutoCorrect_replaceCorrection nargs: 1, replacement];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                        JSChangeTracking                                        //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSChangeTracking
-
-- (BOOL)showChanges
-{
-    NSString *result = [self.js executeJavaScript: ChangeTracking_showChanges nargs: 0];
-    return [result isEqualToString: @"true"];
-}
-
-- (BOOL)trackChanges
-{
-    NSString *result = [self.js executeJavaScript: ChangeTracking_trackChanges nargs: 0];
-    return [result isEqualToString: @"true"];
-}
-
-- (void)setShowChanges:(BOOL)showChanges
-{
-    [self.js executeJavaScript: ChangeTracking_setShowChanges
-                         nargs: 1, [NSNumber numberWithBool: showChanges]];
-}
-
-- (void)setTrackChanges:(BOOL)trackChanges
-{
-    [self.js executeJavaScript: ChangeTracking_setTrackChanges
-                         nargs: 1, [NSNumber numberWithBool: trackChanges]];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                           JSClipboard                                          //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSClipboard
-
-// The copy operation is called clipboardCopy to keep the static analyzer happy, because it thinks
-// that it relates to making a copy of the object and reports a memory leak. The cut operation
-// is named similarly just for consistency.
-
-- (NSDictionary *)clipboardCut
-{
-    return [self.js executeJavaScriptJSON: Clipboard_cut nargs: 0];
-}
-
-- (NSDictionary *)clipboardCopy
-{
-    return [self.js executeJavaScriptJSON: Clipboard_copy nargs: 0];
-}
-
-- (void)pasteHTML:(NSString *)html
-{
-    [self.js executeJavaScript: Clipboard_pasteHTML nargs: 1, html];
-}
-
-- (void)pasteText:(NSString *)text
-{
-    [self.js executeJavaScript: Clipboard_pasteText nargs: 1, text];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSCursor                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Cursor.js
-
-@implementation JSCursor
-
-- (NSString *)positionCursorX:(int)x y:(int)y wordBoundary:(BOOL)wordBoundary
-{
-    return [self.js executeJavaScript: Cursor_positionCursor nargs: 3,
-            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
-            [NSNumber numberWithBool: wordBoundary]];
-}
-
-- (CGRect)getCursorPosition
-{
-    NSDictionary *result = [self.js executeJavaScriptJSON: Cursor_getCursorPosition nargs: 0];
-    return CGRectMake(NSDictionaryGetInt(result,@"x"),
-                      NSDictionaryGetInt(result,@"y"),
-                      NSDictionaryGetInt(result,@"width"),
-                      NSDictionaryGetInt(result,@"height"));
-}
-
-- (void)moveLeft
-{
-    [self.js executeJavaScript: Cursor_moveLeft nargs: 0];
-}
-
-- (void)moveRight
-{
-    [self.js executeJavaScript: Cursor_moveRight nargs: 0];
-}
-
-- (void)moveToStartOfDocument
-{
-    [self.js executeJavaScript: Cursor_moveToStartOfDocument nargs: 0];
-}
-
-- (void)moveToEndOfDocument
-{
-    [self.js executeJavaScript: Cursor_moveToEndOfDocument nargs: 0];
-}
-
-- (void)insertReference:(NSString *)itemId
-{
-    [self.js executeJavaScript: Cursor_insertReference nargs: 1, itemId];
-}
-
-- (void)insertLinkWithText:(NSString *)text URL:(NSString *)URL
-{
-    [self.js executeJavaScript: Cursor_insertLink nargs: 2, text, URL];
-}
-
-- (void)insertCharacter:(unichar)character allowInvalidPos:(BOOL)allowInvalidPos
-{
-    NSString *str = [NSString stringWithFormat: @"%C", character];
-    [self.js executeJavaScript: Cursor_insertCharacter nargs: 2, str,
-     [NSNumber numberWithBool: allowInvalidPos]];
-}
-
-- (void)deleteCharacter
-{
-    [self.js executeJavaScript: Cursor_deleteCharacter nargs: 0];
-}
-
-- (void)enterPressed
-{
-    [self.js executeJavaScript: Cursor_enterPressed nargs: 0];
-}
-
-- (NSString *)getPrecedingWord
-{
-    return [self.js executeJavaScript: Cursor_getPrecedingWord nargs: 0];
-}
-
-- (NSDictionary *)getLinkProperties
-{
-    return [self.js executeJavaScriptJSON: Cursor_getLinkProperties nargs: 0];
-}
-
-- (void)setLinkProperties:(NSDictionary *)properties
-{
-    [self.js executeJavaScript: Cursor_setLinkProperties nargs: 1, properties];
-}
-
-- (void)setReferenceTarget:(NSString *)itemId
-{
-    [self.js executeJavaScript: Cursor_setReferenceTarget nargs: 1, itemId];
-}
-
-- (void)insertFootnote:(NSString *)content
-{
-    [self.js executeJavaScript: Cursor_insertFootnote nargs: 1, content];
-}
-
-- (void)insertEndnote:(NSString *)content
-{
-    [self.js executeJavaScript: Cursor_insertEndnote nargs: 1, content];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            Equations                                           //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSEquations
-
-- (void)insertEquation
-{
-    [self.js executeJavaScript: Equations_insertEquation nargs: 0];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSFigures                                           //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSFigures
-
-- (void)insertFigure:(NSString *)filename width:(NSString *)width
-            numbered:(BOOL)numbered caption:(NSString *)caption
-{
-    [self.js executeJavaScript: Figures_insertFigure nargs: 4,
-     filename, width, [NSNumber numberWithBool: numbered], caption];
-}
-
-- (NSString *)getSelectedFigureId
-{
-    return [self.js executeJavaScript: Figures_getSelectedFigureId nargs: 0];
-}
-
-- (NSDictionary *)getProperties:(NSString *)itemId
-{
-    return [self.js executeJavaScriptJSON: Figures_getProperties nargs: 1, itemId];
-}
-
-- (void)setProperties:(NSString *)itemId width:(NSString *)width src:(NSString *)src
-{
-    [self.js executeJavaScript: Figures_setProperties nargs: 3, itemId, width, src];
-}
-
-- (NSDictionary *)getGeometry:(NSString *)itemId
-{
-    return [self.js executeJavaScriptJSON: Figures_getGeometry nargs: 1, itemId];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                          JSFormatting                                          //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Formatting.js
-
-@implementation JSFormatting
-
-- (NSDictionary *)getFormatting
-{
-    return [self.js executeJavaScriptJSON: Formatting_getFormatting nargs: 0];
-}
-
-- (void)applyFormattingChangesStyle:(NSString *)style properties:(NSDictionary *)properties
-{
-    [self.js executeJavaScript: Formatting_applyFormattingChanges nargs: 2, style, properties];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                             JSInput                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSInput
-
-- (void)removePosition:(int)posId
-{
-    [self.js executeJavaScript: Input_removePosition nargs: 1, [NSNumber numberWithInt: posId]];
-}
-
-- (NSString *)textInRangeStartId:(int)startId startAdjust:(int)startAdjust
-                           endId:(int)endId endAdjust:(int)endAdjust
-{
-    return [self.js executeJavaScript: Input_textInRange nargs: 4,
-            [NSNumber numberWithInt: startId],
-            [NSNumber numberWithInt: startAdjust],
-            [NSNumber numberWithInt: endId],
-            [NSNumber numberWithInt: endAdjust]];
-}
-
-- (void)replaceRangeStart:(int)startId end:(int)endId withText:(NSString *)text
-{
-    [self.js executeJavaScript: Input_replaceRange nargs: 3,
-     [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId], text];
-}
-
-- (NSDictionary *)selectedTextRange
-{
-    return [self.js executeJavaScriptJSON: Input_selectedTextRange nargs: 0];
-}
-
-- (void)setSelectedTextRangeStart:(int)startId end:(int)endId
-{
-    [self.js executeJavaScript: Input_setSelectedTextRange nargs: 2,
-     [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
-}
-
-- (NSDictionary *)markedTextRange
-{
-    return [self.js executeJavaScriptJSON: Input_markedTextRange nargs: 0];
-}
-
-- (void)setMarkedText:(NSString *)text startOffset:(int)startOffset endOffset:(int)endOffset
-{
-    [self.js executeJavaScript: Input_setMarkedText nargs: 3,
-     text, [NSNumber numberWithInt: startOffset], [NSNumber numberWithInt: endOffset]];
-}
-
-- (void)unmarkText
-{
-    [self.js executeJavaScript: Input_unmarkText nargs: 0];
-}
-
-- (BOOL)forwardSelectionAffinity
-{
-    NSString *result = [self.js executeJavaScript: Input_forwardSelectionAffinity nargs: 0];
-    return [result isEqualToString: @"true"];
-}
-
-- (void)setForwardSelectionAffinity:(BOOL)forwardSelectionAffinity
-{
-    [self.js executeJavaScript: Input_setForwardSelectionAffinity nargs: 1,
-     [NSNumber numberWithBool: forwardSelectionAffinity]];
-}
-
-- (int)positionFromPosition:(int)posId offset:(int)offset
-{
-    NSString *result = [self.js executeJavaScript: Input_positionFromPositionOffset nargs: 2,
-                        [NSNumber numberWithInt: posId], [NSNumber numberWithInt: offset]];
-    return result.intValue;
-}
-
-- (int)positionFromPosition:(int)posId inDirection:(NSString *)direction offset:(int)offset
-{
-    NSString *result = [self.js executeJavaScript: Input_positionFromPositionInDirectionOffset nargs: 3,
-                        [NSNumber numberWithInt: posId], direction, [NSNumber numberWithInt: offset]];
-    return result.intValue;
-}
-
-- (int)comparePosition:(int)positionId toPosition:(int)otherId
-{
-    NSString *result = [self.js executeJavaScript: Input_comparePositionToPosition nargs: 2,
-                        [NSNumber numberWithInt: positionId], [NSNumber numberWithInt: otherId]];
-    return result.intValue;
-}
-
-- (int)offsetFromPosition:(int)fromPosition toPosition:(int)toPosition
-{
-    NSString *result = [self.js executeJavaScript: Input_offsetFromPositionToPosition nargs: 2,
-                        [NSNumber numberWithInt: fromPosition], [NSNumber numberWithInt: toPosition]];
-    return result.intValue;
-}
-
-- (int)positionWithinRangeStart:(int)startId end:(int)endId farthestInDirection:(NSString *)direction
-{
-    NSString *result = [self.js executeJavaScript: Input_positionWithinRangeFarthestInDirection nargs: 3,
-                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId], direction];
-    return result.intValue;
-}
-
-- (NSDictionary *)characterRangeByExtendingPosition:(int)positionId inDirection:(NSString *)direction
-{
-    return [self.js executeJavaScriptJSON: Input_characterRangeByExtendingPositionInDirection nargs: 2,
-            [NSNumber numberWithInt: positionId], direction];
-}
-
-- (NSDictionary *)firstRectForRangeStart:(int)startId end:(int)endId
-{
-    return [self.js executeJavaScriptJSON: Input_firstRectForRange nargs: 2,
-            [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
-}
-
-- (NSDictionary *)caretRectForPosition:(int)posId
-{
-    return [self.js executeJavaScriptJSON: Input_caretRectForPosition nargs: 1,
-            [NSNumber numberWithInt: posId]];
-}
-
-- (int)closestPositionToPointX:(int)x y:(int)y
-{
-    NSString *result = [self.js executeJavaScript: Input_closestPositionToPoint nargs: 2,
-                        [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
-    return result.intValue;
-}
-
-- (int)closestPositionToPointX:(int)x y:(int)y withinRangeStart:(int)startId end:(int)endId
-{
-    NSString *result = [self.js executeJavaScript: Input_closestPositionToPointWithinRange nargs: 4,
-                        [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
-                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
-    return result.intValue;
-}
-
-- (NSDictionary *)characterRangeAtPointX:(int)x y:(int)y
-{
-    return [self.js executeJavaScriptJSON: Input_characterRangeAtPoint nargs: 2,
-            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
-}
-
-- (int)positionWithinRangeStart:(int)startId end:(int)endId atCharacterOffset:(int)offset
-{
-    NSString *result = [self.js executeJavaScript: Input_positionWithinRangeAtCharacterOffset nargs: 3,
-                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId],
-                        [NSNumber numberWithInt: offset]];
-    return result.intValue;
-}
-
-- (int)characterOffsetOfPosition:(int)positionId withinRangeStart:(int)startId end:(int)endId
-{
-    NSString *result = [self.js executeJavaScript: Input_characterOffsetOfPositionWithinRange nargs: 3,
-                        [NSNumber numberWithInt: positionId],
-                        [NSNumber numberWithInt: startId], [NSNumber numberWithInt: endId]];
-    return result.intValue;
-}
-
-// UITextInputTokenizer methods
-
-- (BOOL)isPosition:(int)posId atBoundary:(NSString *)granularity inDirection:(NSString *)direction
-{
-    NSString *result = [self.js executeJavaScript: Input_isPositionAtBoundaryGranularityInDirection nargs: 3,
-                        [NSNumber numberWithInt: posId], granularity, direction];
-    return [result isEqualToString: @"true"];
-}
-
-- (BOOL)isPosition:(int)posId withinTextUnit:(NSString *)granularity inDirection:(NSString *)direction
-{
-    NSString *result = [self.js executeJavaScript: Input_isPositionWithinTextUnitInDirection nargs: 3,
-                        [NSNumber numberWithInt: posId], granularity, direction];
-    return [result isEqualToString: @"true"];
-}
-
-- (int)positionFromPosition:(int)posId toBoundary:(NSString *)granularity inDirection:(NSString *)direction
-{
-    NSString *result = [self.js executeJavaScript: Input_positionFromPositionToBoundaryInDirection nargs: 3,
-                        [NSNumber numberWithInt: posId], granularity, direction];
-    return result.intValue;
-}
-
-- (NSDictionary *)rangeEnclosingPosition:(int)posId withGranularity:(NSString *)granularity inDirection:(NSString *)direction
-{
-    return [self.js executeJavaScriptJSON: Input_rangeEnclosingPositionWithGranularityInDirection nargs: 3,
-            [NSNumber numberWithInt: posId], granularity, direction];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                             JSLists                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Lists.js
-
-@implementation JSLists
-
-- (void)increaseIndent
-{
-    [self.js executeJavaScript: Lists_increaseIndent nargs: 0];
-}
-
-- (void)decreaseIndent
-{
-    [self.js executeJavaScript: Lists_decreaseIndent nargs: 0];
-}
-
-- (void)clearList
-{
-    [self.js executeJavaScript: Lists_clearList nargs: 0];
-}
-
-- (void)setUnorderedList
-{
-    [self.js executeJavaScript: Lists_setUnorderedList nargs: 0];
-}
-
-- (void)setOrderedList
-{
-    [self.js executeJavaScript: Lists_setOrderedList nargs: 0];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                             JSMain                                             //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Main.js
-
-@implementation JSMain
-
-- (NSString *)getLanguage
-{
-    return [self.js executeJavaScript: Main_getLanguage nargs: 0];
-}
-
-- (void)setLanguage:(NSString *)language
-{
-    [self.js executeJavaScript: Main_setLanguage nargs: 1, language];
-}
-
-- (NSString *)setGenerator:(NSString *)generator
-{
-    return [self.js executeJavaScript: Main_setGenerator nargs: 1, generator];
-}
-
-- (BOOL)prepareForSave
-{
-    NSString *result = [self.js executeJavaScript: Main_prepareForSave nargs: 0];
-    return [@"true" isEqualToString: result];
-}
-
-- (NSString *)getHTML;
-{
-    return [self.js executeJavaScript: Main_getHTML nargs: 0];
-}
-
-- (BOOL)isEmptyDocument
-{
-    NSString *result = [self.js executeJavaScript: Main_isEmptyDocument nargs: 0];
-    return [result isEqualToString: @"true"];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                           JSMetadata                                           //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSMetadata
-
-- (NSDictionary *)getMetadata
-{
-    return [self.js executeJavaScriptJSON: Metadata_getMetadata nargs: 0];
-}
-
-- (void)setMetadata:(NSDictionary *)metadata
-{
-    [self.js executeJavaScriptJSON: Metadata_setMetadata nargs: 1, metadata];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSOutline                                           //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Outline.js
-
-@implementation JSOutline
-
-- (NSDictionary *)getOutline
-{
-    return [self.js executeJavaScriptJSON: Outline_getOutline nargs: 0];
-}
-
-- (void)moveSection:(NSString *)sectionId parentId:(NSString *)parentId nextId:(NSString *)nextId
-{
-    [self.js executeJavaScript: Outline_moveSection nargs: 3, sectionId, parentId, nextId];
-}
-
-- (void)deleteItem:(NSString *)itemId
-{
-    [self.js executeJavaScript: Outline_deleteItem nargs: 1, itemId];
-}
-
-- (void)scheduleUpdateStructure
-{
-    [self.js executeJavaScript: Outline_scheduleUpdateStructure nargs: 0];
-}
-
-- (void)goToItem:(NSString *)itemId
-{
-    [self.js executeJavaScript: Outline_goToItem nargs: 1, itemId];
-}
-
-- (void)set:(NSString *)itemId numbered:(BOOL)numbered
-{
-    [self.js executeJavaScript: Outline_setNumbered nargs: 2, itemId, [NSNumber numberWithBool: numbered]];
-}
-
-- (void)set:(NSString *)itemId title:(NSString *)title
-{
-    [self.js executeJavaScript: Outline_setTitle nargs: 2, itemId, title];
-}
-
-- (void)insertTableOfContents
-{
-    [self.js executeJavaScript: Outline_insertTableOfContents nargs: 0];
-}
-
-- (void)insertListOfFigures
-{
-    [self.js executeJavaScript: Outline_insertListOfFigures nargs: 0];
-}
-
-- (void)insertListOfTables
-{
-    [self.js executeJavaScript: Outline_insertListOfTables nargs: 0];
-}
-
-- (void)setPrintMode:(BOOL)printMode
-{
-    [self.js executeJavaScript: Outline_setPrintMode nargs: 1, [NSNumber numberWithBool: printMode]];
-}
-
-- (NSDictionary *)examinePrintLayout:(int)pageHeight
-{
-    return [self.js executeJavaScriptJSON: Outline_examinePrintLayout nargs: 1,
-            [NSNumber numberWithInt: pageHeight]];
-}
-
-- (BOOL)detectSectionNumbering
-{
-    NSString *result = [self.js executeJavaScript: Outline_detectSectionNumbering nargs: 0];
-    return [result isEqualToString: @"true"];
-}
-
-- (NSDictionary *)findUsedStyles
-{
-    return [self.js executeJavaScriptJSON: Outline_findUsedStyles nargs: 0];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSPreview                                           //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSPreview
-
-- (void)showForStyle:(NSString *)styleId uiName:(NSString *)uiName title:(NSString *)title
-{
-    [self.js executeJavaScript: Preview_showForStyle nargs: 3, styleId, uiName, title];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                             JSScan                                             //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSScan
-
-- (void)reset
-{
-    [self.js executeJavaScript: Scan_reset nargs: 0];
-}
-
-- (EDScanParagraph *)next
-{
-    NSDictionary *dict = [self.js executeJavaScriptJSON: Scan_next nargs: 0];
-    if ((dict == nil) || ![dict isKindOfClass: [NSDictionary class]])
-        return nil;
-
-    NSString *text = FCGetString(dict,@"text",nil);
-    NSString *sectionId = FCGetString(dict,@"sectionId",nil);
-    if (text == nil)
-        return nil;
-
-    return [[EDScanParagraph alloc] initWithText: text sectionId: sectionId];
-}
-
-- (int)addMatchStart:(int)start end:(int)end
-{
-    return [self.js executeJavaScript: Scan_addMatch nargs: 2,
-            [NSNumber numberWithInt: start],
-            [NSNumber numberWithInt: end]].intValue;
-}
-
-- (void)showMatch:(int)matchId
-{
-    [self.js executeJavaScript: Scan_showMatch nargs: 1, [NSNumber numberWithInt: matchId]];
-}
-
-- (void)replaceMatch:(int)matchId with:(NSString *)text
-{
-    [self.js executeJavaScript: Scan_replaceMatch nargs: 2, [NSNumber numberWithInt: matchId], text];
-}
-
-- (void)removeMatch:(int)matchId
-{
-    [self.js executeJavaScript: Scan_removeMatch nargs: 1, [NSNumber numberWithInt: matchId]];
-}
-
-- (void)goToMatch:(int)matchId
-{
-    [self.js executeJavaScript: Scan_goToMatch nargs: 1, [NSNumber numberWithInt: matchId]];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                           JSSelection                                          //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Selection.js
-
-@implementation JSSelection
-
-- (void)update
-{
-    [self.js executeJavaScript: Selection_update nargs: 0];
-}
-
-- (void)selectAll
-{
-    [self.js executeJavaScript: Selection_selectAll nargs: 0];
-}
-
-- (void)selectParagraph
-{
-    [self.js executeJavaScript: Selection_selectParagraph nargs: 0];
-}
-
-- (void)selectWordAtCursor
-{
-    [self.js executeJavaScript: Selection_selectWordAtCursor nargs: 0];
-}
-
-- (NSString *)dragSelectionBeginX:(int)x y:(int)y selectWord:(BOOL)selectWord
-{
-    return [self.js executeJavaScript: Selection_dragSelectionBegin nargs: 3,
-            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
-            [NSNumber numberWithBool: selectWord]];
-}
-
-- (NSString *)dragSelectionUpdateX:(int)x y:(int)y selectWord:(BOOL)selectWord
-{
-    return [self.js executeJavaScript: Selection_dragSelectionUpdate nargs: 3,
-            [NSNumber numberWithInt: x], [NSNumber numberWithInt: y],
-            [NSNumber numberWithBool: selectWord]];
-}
-
-- (NSString *)moveStartLeft
-{
-    return [self.js executeJavaScript: Selection_moveStartLeft nargs: 0];
-}
-
-- (NSString *)moveStartRight
-{
-    return [self.js executeJavaScript: Selection_moveStartRight nargs: 0];
-}
-
-- (NSString *)moveEndLeft
-{
-    return [self.js executeJavaScript: Selection_moveEndLeft nargs: 0];
-}
-
-- (NSString *)moveEndRight
-{
-    return [self.js executeJavaScript: Selection_moveEndRight nargs: 0];
-}
-
-- (void)setSelectionStartAtCoordsX:(int)x y:(int)y
-{
-    [self.js executeJavaScript: Selection_setSelectionStartAtCoords nargs: 2,
-                             [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
-}
-
-- (void)setSelectionEndAtCoordsX:(int)x y:(int)y
-{
-    [self.js executeJavaScript: Selection_setSelectionEndAtCoords nargs: 2,
-                             [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
-}
-
-- (void)setTableSelectionEdge:(NSString *)edge atCoordsX:(int)x y:(int)y
-{
-    [self.js executeJavaScript: Selection_setTableSelectionEdgeAtCoords nargs: 3,
-                           edge, [NSNumber numberWithInt: x], [NSNumber numberWithInt: y]];
-}
-
-- (void)print
-{
-    [self.js executeJavaScript: Selection_print nargs: 0];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSStyles                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSStyles
-
-- (NSString *)getCSSText
-{
-    return [self.js executeJavaScript: Styles_getCSSText nargs: 0];
-}
-
-- (void)setCSSText:(NSString *)cssText rules:(NSDictionary *)rules
-{
-//    debug(@"---------------------- setCSSText ----------------------\n");
-//    debug(@"%@",cssText);
-//    if ((cssText.length > 0) && ([cssText characterAtIndex: cssText.length-1] != '\n'))
-//        debug(@"\n");
-//    debug(@"--------------------------------------------------------\n");
-    [self.js executeJavaScriptJSON: Styles_setCSSText nargs: 2, cssText, rules];
-}
-
-- (NSString *)paragraphClass
-{
-    return [self.js executeJavaScript: Styles_getParagraphClass nargs: 0];
-}
-
-- (void)setParagraphClass:(NSString *)paragraphClass;
-{
-    [self.js executeJavaScript: Styles_setParagraphClass nargs: 1, paragraphClass];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                            JSTables                                            //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Tables.js
-
-@implementation JSTables
-
-- (void)insertTableRows:(int)rows cols:(int)cols width:(NSString *)width numbered:(BOOL)numbered
-                caption:(NSString *)caption className:(NSString *)className;
-{
-    [self.js executeJavaScript: Tables_insertTable nargs: 6,
-                             [NSNumber numberWithInt: rows], [NSNumber numberWithInt: cols],
-                             width, [NSNumber numberWithBool: numbered], caption, className];
-}
-
-- (void)addAdjacentRow
-{
-    [self.js executeJavaScript: Tables_addAdjacentRow nargs: 0];
-}
-
-- (void)addAdjacentColumn
-{
-    [self.js executeJavaScript: Tables_addAdjacentColumn nargs: 0];
-}
-
-- (void)removeAdjacentRow
-{
-    [self.js executeJavaScript: Tables_removeAdjacentRow nargs: 0];
-}
-
-- (void)removeAdjacentColumn
-{
-    [self.js executeJavaScript: Tables_removeAdjacentColumn nargs: 0];
-}
-
-- (void)clearCells
-{
-    [self.js executeJavaScript: Tables_clearCells nargs: 0];
-}
-
-- (void)mergeCells
-{
-    [self.js executeJavaScript: Tables_mergeCells nargs: 0];
-}
-
-- (void)splitSelection
-{
-    [self.js executeJavaScript: Tables_splitSelection nargs: 0];
-}
-
-- (NSString *)getSelectedTableId
-{
-    return [self.js executeJavaScript: Tables_getSelectedTableId nargs: 0];
-}
-
-- (NSDictionary *)getProperties:(NSString *)itemId
-{
-    return [self.js executeJavaScriptJSON: Tables_getProperties nargs: 1, itemId];
-}
-
-- (void)setProperties:(NSString *)itemId width:(NSString *)width
-{
-    [self.js executeJavaScript: Tables_setProperties nargs: 2, itemId, width];
-}
-
-- (void)set:(NSString *)itemId colWidths:(NSArray *)colWidths
-{
-    [self.js executeJavaScript: Tables_setColWidths nargs: 2, itemId, colWidths];
-}
-
-- (NSDictionary *)getGeometry:(NSString *)itemId
-{
-    return [self.js executeJavaScriptJSON: Tables_getGeometry nargs: 1, itemId];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                          JSUndoManager                                         //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-@implementation JSUndoManager
-
-- (int)getLength
-{
-    NSString *result = [self.js executeJavaScript: UndoManager_getLength nargs: 0];
-    return result.intValue;
-}
-
-- (int)getIndex
-{
-    NSString *result = [self.js executeJavaScript: UndoManager_getIndex nargs: 0];
-    return result.intValue;
-}
-
-- (void)setIndex:(int)index
-{
-    [self.js executeJavaScript: UndoManager_setIndex nargs: 1, [NSNumber numberWithInt: index]];
-}
-
-- (void)undo
-{
-    [self.js executeJavaScript: UndoManager_undo nargs: 0];
-}
-
-- (void)redo
-{
-    [self.js executeJavaScript: UndoManager_redo nargs: 0];
-}
-
-- (void)newGroup:(NSString *)name
-{
-    [self.js executeJavaScript: UndoManager_newGroup nargs: 1, name];
-}
-
-- (NSString *)groupType
-{
-    return [self.js executeJavaScript: UndoManager_groupType nargs: 0];
-}
-
-@end
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//                                                                                                //
-//                                           JSViewport                                           //
-//                                                                                                //
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Functions implemented in Viewport.js
-
-@implementation JSViewport
-
-- (void)setViewportWidth:(int)width
-{
-    [self.js executeJavaScript: Viewport_setViewportWidth nargs: 1, [NSNumber numberWithInt: width]];
-}
-
-- (void)setTextScale:(int)textScale
-{
-    [self.js executeJavaScript: Viewport_setTextScale nargs: 1, [NSNumber numberWithInt: textScale]];
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer2_API/Layer2_interface.h
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer2_API/Layer2_interface.h b/experiments/editorFramework/src/Layer2_API/Layer2_interface.h
deleted file mode 100644
index 042a1a7..0000000
--- a/experiments/editorFramework/src/Layer2_API/Layer2_interface.h
+++ /dev/null
@@ -1,480 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-#pragma once
-
-#include <QString>
-#include <QRect>
-#include <QJsonObject>
-#include <QJsonArray>
-#include <QTextStream>
-
-/**
- * \file JSInterface.h
- *
- * C++ interface to the JavaScript editor library
- *
- * All of the core editing operations for Corinthia are implemented in the Editor library, which is
- * written in JavaScript. This library can be used either from within a web browser, or, in the case
- * of the Qt application, from an embedded web view. For this app, we use a QWebView instance which
- * maintains the in-memory DOM tree of the document, and has injected into it all of the javascript
- * code that is part of the editor library.
- *
- * The source code of the Editor library lives in (repository-root)/Editor/src. During build of the
- * Qt app, all the javascript files are copied into (build-dir)/share/corinthia/js. If you wish to
- * make changes to the javascript code, you should modify the files in the former location, as the
- * latter files will be overwritten on every build.
- *
- * The purpose of JSInterface.h and JSInterface.cpp is to provide a C++ wrapper over this. All of
- * the methods defined in the classes below (with the exception of callbacks) ultimately result in a
- * call to QWebFrame's evaluateJavaScript() method. See the documentation for JSInterface.cpp for
- * details.
- *
- * The editor library is divided into *modules*, each of which implements a specific aspect of
- * editing functionality. For example, the Cursor module contains methods for moving the cursor
- * around the document, and inserting or deleting text at the current cursor position. Similarly,
- * the Tables module contains methods for inserting, deleting, and modifying tables. A separate C++
- * class is defined for each module, and an instance of each class is maintained by the "container"
- * class, JSInterface. When using the code here, you should do so via a JSInterface instance.
- */
-
-#define JS_MODULE_COMMON(className) \
-Q_DISABLE_COPY(className) \
-public: \
-className(JSEvaluator *evaluator) : JSModule(evaluator) {}
-
-QTextStream& qStdOut();
-QString QRectString(QRect rect);
-
-/**
- * Callback interface
- *
- * While the module classes are for making calls from C++ to JavaScript, the JSCallbacks abstract
- * class is for responding to requests from JavaScript to invoke C++ code. This is declared here as
- * an abstract class (that is, with all methods virtual and no implementations provided) to avoid
- * dependencies between the code in this file and other parts of the application. The
- * EditorJSCallbacks class in Editor.cpp provides a concrete implementation of this, which is where
- * the actual callback functions are implemented.
- *
- * Callbacks are always invoked *after* the execution of a particular editor library API function,
- * not during. The reason for this design design in the library was to enable support for web view
- * classes that did not provide native support for callbacks (as was the case for iOS, at least at
- * the time the library was originally written).
- *
- * The way that callbacks are invoked is that after each editor API call, a query is performed for a
- * list of pending callback messages. The evaluation logic iterates through these and invokes the
- * appropriate callback method for each. For this reason, callbacks method are all 'void' - they
- * never return a value. Callbacks are for notification purposes only - typically telling the
- * application to update the UI in some manner.
- */
-class JSCallbacks
-{
-public:
-    virtual ~JSCallbacks() {}
-    virtual void debug(const QString &message) = 0;
-    virtual void addOutlineItem(const QString &itemId, const QString &type, const QString &title) = 0;
-    virtual void updateOutlineItem(const QString &itemId, const QString &title) = 0;
-    virtual void removeOutlineItem(const QString &itemId) = 0;
-    virtual void outlineUpdated() = 0;
-    virtual void setCursor(int x, int y, int width, int height) = 0;
-    virtual void setSelectionHandles(int x1, int y1, int height1, int x2, int y2, int height2) = 0;
-    virtual void setTableSelection(int x, int y, int width, int height) = 0;
-    virtual void setSelectionBounds(int left, int top, int right, int bottom) = 0;
-    virtual void clearSelectionHandlesAndCursor() = 0;
-    virtual void updateAutoCorrect() = 0;
-    virtual void error(const QString &message, const QString &operation) = 0;
-};
-
-/**
- * The JSEvaluator abstract class provides an evaluate() method which is called (indirectly) by all
- * of the individual module methods. As with JSCallbacks, it is defined as abstract to avoid a
- * dependency on the code outside of this file. The EditorJSEvaluator class in Editor.cpp provides a
- * concrete implementation of this; its evaluate() method simply calls through to the
- * evaluateJavaScript() method of QWebView.
- *
- * JSEvaluator also has a callbacks() method, which must return an instance of JSCallbacks. This
- * makes JSEvaluator the "central point of contact" between the JavaScript interface and the rest of
- * the application, in that it provides the necessary access to call *in* to javascript, and to
- * respond (via callbacks) to calls *out* of javascript. Upon initialisation of a document window,
- * concrete implementations of both JSCallbacks and JSEvaluator are created, the latter maintaining
- * a reference to the former. See Editor::Editor() for where ths is actually done.
- */
-class JSEvaluator
-{
-public:
-    virtual ~JSEvaluator() {}
-    virtual QString evaluate(const QString &script) = 0;
-    virtual JSCallbacks *callbacks() = 0;
-};
-
-class JSAutoCorrect;
-class JSChangeTracking;
-class JSClipboard;
-class JSCursor;
-class JSEquations;
-class JSFigures;
-class JSFormatting;
-class JSInput;
-class JSLists;
-class JSMain;
-class JSMetadata;
-class JSOutline;
-class JSPreview;
-class JSScan;
-class JSSelection;
-class JSStyles;
-class JSTables;
-class JSUndoManager;
-class JSViewport;
-class EDScanParagraph;
-
-class JSError
-{
-public:
-    const QString &type() { return _type; }
-    const QString &message() { return _message; }
-    const QString &operation() { return _operation; }
-    const QString &html() { return _html; }
-
-private:
-
-    QString _type;
-    QString _message;
-    QString _operation;
-    QString _html;
-};
-
-class JSModule
-{
-    Q_DISABLE_COPY(JSModule)
-public:
-    JSModule(JSEvaluator *evaluator) : _evaluator(evaluator) {};
-protected:
-    JSEvaluator *_evaluator;
-};
-
-// Functions implemented in AutoCorrect.js
-
-class JSAutoCorrect : public JSModule
-{
-    JS_MODULE_COMMON(JSAutoCorrect)
-    void correctPrecedingWord(int numChars, const QString &replacement, bool confirmed);
-    QJsonObject getCorrection();
-    QJsonObject getCorrectionCoords();
-    void acceptCorrection();
-    void replaceCorrection(const QString &replacement);
-};
-
-// Functions implemented in ChangeTracking.js
-
-class JSChangeTracking : public JSModule
-{
-    JS_MODULE_COMMON(JSChangeTracking)
-    bool showChanges();
-    bool trackChanges();
-    void setShowChanges(bool showChanges);
-    void setTrackChanges(bool trackChanges);
-};
-
-// Functions implemented in Clipboard.js
-
-class JSClipboard : public JSModule
-{
-    JS_MODULE_COMMON(JSClipboard)
-    QJsonObject clipboardCut();
-    QJsonObject clipboardCopy();
-    void pasteHTML(const QString &html);
-    void pasteText(const QString &text);
-};
-
-// Functions implemented in Cursor.js
-
-class JSCursor : public JSModule
-{
-    JS_MODULE_COMMON(JSCursor)
-    QString positionCursor(int x, int y, bool wordBoundary);
-    QRect getCursorPosition();
-    void moveLeft();
-    void moveRight();
-    void moveToStartOfDocument();
-    void moveToEndOfDocument();
-    void insertReference(const QString &itemId);
-    void insertLink(const QString &text, const QString &url);
-    void insertCharacter(unsigned short character, bool allowInvalidPos);
-    void deleteCharacter();
-    void enterPressed();
-    QString getPrecedingWord();
-    QJsonObject getLinkProperties();
-    void setLinkProperties(QJsonObject properties);
-    void setReferenceTarget(const QString &itemId);
-    void insertFootnote(const QString &content);
-    void insertEndnote(const QString &content);
-};
-
-// Functions implemented in Equations.js
-
-class JSEquations : public JSModule
-{
-    JS_MODULE_COMMON(JSEquations)
-    void insertEquation();
-};
-
-// Functions implemented in Figures.js
-
-class JSFigures : public JSModule
-{
-    JS_MODULE_COMMON(JSFigures)
-    void insertFigure(const QString &filename, const QString &width,
-                      bool numbered, const QString &caption);
-    QString getSelectedFigureId();
-    QJsonObject getProperties(const QString &itemId);
-    void setProperties(const QString &itemId, const QString &width, const QString &src);
-    QJsonObject getGeometry(const QString &itemId);
-};
-
-// Functions implemented in Formatting.js
-
-class JSFormatting : public JSModule
-{
-    JS_MODULE_COMMON(JSFormatting)
-    QJsonObject getFormatting();
-    void applyFormattingChanges(const QString &style, QJsonObject properties);
-};
-
-// Functions implemented in Input.js
-
-class JSInput : public JSModule
-{
-    JS_MODULE_COMMON(JSInput)
-    void removePosition(int posId);
-
-    QString textInRange(int startId, int startAdjust, int endId, int endAdjust);
-    void replaceRange(int startId, int endId, const QString &text);
-    QJsonObject selectedTextRange();
-    void setSelectedTextRange(int startId, int endId);
-    QJsonObject markedTextRange();
-    void setMarkedText(const QString &text, int startOffset, int endOffset);
-    void unmarkText();
-    bool forwardSelectionAffinity();
-    void setForwardSelectionAffinity(bool forwardSelectionAffinity);
-    int positionFromPositionOffset(int posId, int offset);
-    int positionFromPositionInDirectionOffset(int posId, const QString &direction, int offset);
-    int comparePositionToPosition(int positionId, int otherId);
-    int offsetFromPositionToPosition(int fromPosition, int toPosition);
-    int positionWithinRangeFarthestInDirection(int startId, int endId, const QString &direction);
-    QJsonObject characterRangeByExtendingPositionInDirection(int positionId, const QString &direction);
-    QJsonObject firstRectForRange(int startId, int endId);
-    QJsonObject caretRectForPosition(int posId);
-    int closestPositionToPoint(int x, int y);
-    int closestPositionToPointWithinRange(int x, int y, int startId, int endId);
-    QJsonObject characterRangeAtPoint(int x, int y);
-    int positionWithinRangeAtCharacterOffset(int startId, int endId, int offset);
-    int characterOffsetOfPositionWithinRange(int positionId, int startId, int endId);
-
-    bool isPositionAtBoundaryGranularityInDirection(int posId, const QString &granularity,
-                                                    const QString &direction);
-    bool isPositionWithinTextUnitInDirection(int posId, const QString &granularity,
-                                             const QString &direction);
-    int positionFromPositionToBoundaryInDirection(int posId, const QString &granularity,
-                                                  const QString &direction);
-    QJsonObject rangeEnclosingPositionWithGranularityInDirection(int posId,
-                                                                 const QString &granularity,
-                                                                 const QString &direction);
-};
-
-// Functions implemented in Lists.js
-
-class JSLists : public JSModule
-{
-    JS_MODULE_COMMON(JSLists)
-    void increaseIndent();
-    void decreaseIndent();
-    void clearList();
-    void setUnorderedList();
-    void setOrderedList();
-};
-
-// Functions implemented in Main.js
-
-class JSMain : public JSModule
-{
-    JS_MODULE_COMMON(JSMain)
-    QString getLanguage();
-    void setLanguage(const QString &language);
-    QString setGenerator(const QString &generator);
-    bool prepareForSave();
-    QString getHTML();
-    bool isEmptyDocument();
-};
-
-// Functions implemented in Metadata.js
-
-class JSMetadata : public JSModule
-{
-    JS_MODULE_COMMON(JSMetadata)
-    QJsonObject getMetadata();
-    void setMetadata(const QJsonObject &metadata);
-};
-
-// Functions implemented in Outline.js
-
-class JSOutline : public JSModule
-{
-    JS_MODULE_COMMON(JSOutline)
-    QJsonObject getOutline();
-    void moveSection(const QString &sectionId, const QString &parentId, const QString &nextId);
-    void deleteItem(const QString &itemId);
-    void goToItem(const QString &itemId);
-    void scheduleUpdateStructure();
-    void setNumbered(const QString &itemId, bool numbered);
-    void setTitle(const QString &itemId, const QString &title);
-    void insertTableOfContents();
-    void insertListOfFigures();
-    void insertListOfTables();
-    void setPrintMode(bool printMode);
-    QJsonObject examinePrintLayout(int pageHeight);
-    bool detectSectionNumbering();
-    QJsonObject findUsedStyles();
-};
-
-// Functions implemented in Preview.js
-
-class JSPreview : public JSModule
-{
-    JS_MODULE_COMMON(JSPreview)
-    void showForStyle(const QString &styleId, const QString &uiName, const QString &title);
-};
-
-// Functions implemented in Scan.js
-
-class JSScan : public JSModule
-{
-    JS_MODULE_COMMON(JSScan)
-    void reset();
-    EDScanParagraph *next();
-    int addMatch(int start, int end);
-    void showMatch(int matchId);
-    void replaceMatch(int matchId, const QString &text);
-    void removeMatch(int matchId);
-    void goToMatch(int matchId);
-};
-
-// Functions implemented in Selection.js
-
-class JSSelection : public JSModule
-{
-    JS_MODULE_COMMON(JSSelection)
-    void update();
-    void selectAll();
-    void selectParagraph();
-    void selectWordAtCursor();
-    QString dragSelectionBegin(int x, int y, bool selectWord);
-    QString dragSelectionUpdate(int x, int y, bool selectWord);
-    QString moveStartLeft();
-    QString moveStartRight();
-    QString moveEndLeft();
-    QString moveEndRight();
-    void setSelectionStartAtCoords(int x, int y);
-    void setSelectionEndAtCoords(int x, int y);
-    void setTableSelectionEdgeAtCoords(const QString &edge, int x, int y);
-    void print();
-};
-
-// Functions implemented in Styles.js
-
-class JSStyles : public JSModule
-{
-    JS_MODULE_COMMON(JSStyles)
-    QString getCSSText();
-    void setCSSText(const QString &cssText, const QJsonObject &rules);
-    QString paragraphClass();
-    void setParagraphClass(const QString &paragraphClass);
-};
-
-// Functions implemented in Tables.js
-
-class JSTables : public JSModule
-{
-    JS_MODULE_COMMON(JSTables)
-    void insertTable(int rows, int cols, const QString &width, bool numbered,
-                     const QString &caption, const QString &className);
-    void addAdjacentRow();
-    void addAdjacentColumn();
-    void removeAdjacentRow();
-    void removeAdjacentColumn();
-    void clearCells();
-    void mergeCells();
-    void splitSelection();
-    QString getSelectedTableId();
-    QJsonObject getProperties(const QString &itemId);
-    void setProperties(const QString &itemId, const QString &width);
-    void setColWidths(const QString &itemId, const QJsonArray &colWidths);
-    QJsonObject getGeometry(const QString &itemId);
-};
-
-// Functions implemented in UndoManager.js
-
-class JSUndoManager : public JSModule
-{
-    JS_MODULE_COMMON(JSUndoManager)
-    int getLength();
-    int getIndex();
-    void setIndex(int index);
-    void undo();
-    void redo();
-    void newGroup(const QString &name);
-    QString groupType();
-};
-
-// Functions implemented in Viewport.js
-
-class JSViewport : public JSModule
-{
-    JS_MODULE_COMMON(JSViewport)
-    void setViewportWidth(int width);
-    void setTextScale(int textScale);
-};
-
-// All modules
-
-class JSInterface
-{
-    Q_DISABLE_COPY(JSInterface)
-public:
-    JSInterface(JSEvaluator *evaluator);
-    JSAutoCorrect autoCorrect;
-    JSChangeTracking changeTracking;
-    JSClipboard clipboard;
-    JSCursor cursor;
-    JSEquations equations;
-    JSFigures figures;
-    JSFormatting formatting;
-    JSInput input;
-    JSLists lists;
-    JSMain main;
-    JSMetadata metadata;
-    JSOutline outline;
-    JSPreview preview;
-    JSScan scan;
-    JSSelection selection;
-    JSStyles styles;
-    JSTables tables;
-    JSUndoManager undoManager;
-    JSViewport viewport;
-};
-
-void processCallbacks(JSEvaluator *evaluator);

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer2_API/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer2_API/README b/experiments/editorFramework/src/Layer2_API/README
deleted file mode 100644
index 35baea8..0000000
--- a/experiments/editorFramework/src/Layer2_API/README
+++ /dev/null
@@ -1 +0,0 @@
-The API will center around the current javascript

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer3_Handling/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer3_Handling/README b/experiments/editorFramework/src/Layer3_Handling/README
deleted file mode 100644
index b2451f3..0000000
--- a/experiments/editorFramework/src/Layer3_Handling/README
+++ /dev/null
@@ -1 +0,0 @@
-handling is independent of the actual graphic representation.

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer4_Docformat/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer4_Docformat/README b/experiments/editorFramework/src/Layer4_Docformat/README
deleted file mode 100644
index df39b72..0000000
--- a/experiments/editorFramework/src/Layer4_Docformat/README
+++ /dev/null
@@ -1 +0,0 @@
-Connection to the DocFormat library


[19/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Tables.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Tables.js b/experiments/editorFramework/src/Javascript_Layer_0/Tables.js
new file mode 100644
index 0000000..f1f27be
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Tables.js
@@ -0,0 +1,1362 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Tables_insertTable;
+var Tables_addAdjacentRow;
+var Tables_addAdjacentColumn;
+var Tables_removeAdjacentRow;
+var Tables_removeAdjacentColumn;
+var Tables_deleteRegion;
+var Tables_clearCells;
+var Tables_mergeCells;
+var Tables_splitSelection;
+var Tables_cloneRegion;
+var Tables_analyseStructure;
+var Tables_findContainingCell;
+var Tables_findContainingTable;
+var Tables_regionFromRange;
+var Tables_getSelectedTableId;
+var Tables_getProperties;
+var Tables_setProperties;
+var Tables_getColWidths;
+var Tables_setColWidths;
+var Tables_getGeometry;
+
+var Table_get;
+var Table_set;
+var Table_setRegion;
+var Table_fix;
+var Table_fixColumnWidths;
+var TableRegion_splitCells;
+
+(function() {
+
+    function Cell(element,row,col)
+    {
+        this.element = element;
+        this.row = row;
+        this.col = col;
+
+        if (element.hasAttribute("colspan"))
+            this.colspan = parseInt(element.getAttribute("colspan"));
+        else
+            this.colspan = 1;
+        if (element.hasAttribute("rowspan"))
+            this.rowspan = parseInt(element.getAttribute("rowspan"));
+        else
+            this.rowspan = 1;
+
+        if (this.colspan < 1)
+            this.colspan = 1;
+        if (this.rowspan < 1)
+            this.rowspan = 1;
+
+        this.top = this.row;
+        this.bottom = this.top + this.rowspan - 1;
+        this.left = this.col;
+        this.right = this.left + this.colspan - 1;
+    }
+
+    function Cell_setRowspan(cell,rowspan)
+    {
+        if (rowspan < 1)
+            rowspan = 1;
+        cell.rowspan = rowspan;
+        cell.bottom = cell.top + cell.rowspan - 1;
+        if (rowspan == 1)
+            DOM_removeAttribute(cell.element,"rowspan");
+        else
+            DOM_setAttribute(cell.element,"rowspan",rowspan);
+    }
+
+    function Cell_setColspan(cell,colspan)
+    {
+        if (colspan < 1)
+            colspan = 1;
+        cell.colspan = colspan;
+        cell.right = cell.left + cell.colspan - 1;
+        if (colspan == 1)
+            DOM_removeAttribute(cell.element,"colspan");
+        else
+            DOM_setAttribute(cell.element,"colspan",colspan);
+    }
+
+    function Table(element)
+    {
+        this.element = element;
+        this.row = 0;
+        this.col = 0;
+        this.cells = new Array();
+        this.numRows = 0;
+        this.numCols = 0;
+        this.translated = false;
+        this.cellsByElement = new NodeMap();
+        Table_processTable(this,element);
+    }
+
+    // public
+    Table_get = function(table,row,col)
+    {
+        if (table.cells[row] == null)
+            return null;
+        return table.cells[row][col];
+    }
+
+    // public
+    Table_set = function(table,row,col,cell)
+    {
+        if (table.numRows < row+1)
+            table.numRows = row+1;
+        if (table.numCols < col+1)
+            table.numCols = col+1;
+        if (table.cells[row] == null)
+            table.cells[row] = new Array();
+        table.cells[row][col] = cell;
+    }
+
+    // public
+    Table_setRegion = function(table,top,left,bottom,right,cell)
+    {
+        for (var row = top; row <= bottom; row++) {
+            for (var col = left; col <= right; col++) {
+                var destCell = Table_get(table,row,col);
+                DOM_deleteNode(destCell.element);
+                Table_set(table,row,col,cell);
+            }
+        }
+    }
+
+    function Table_processTable(table,node)
+    {
+        var type = node._type;
+        switch (node._type) {
+        case HTML_TD:
+        case HTML_TH: {
+            while (Table_get(table,table.row,table.col) != null)
+                table.col++;
+
+            var cell = new Cell(node,table.row,table.col);
+            table.cellsByElement.put(node,cell);
+
+            for (var r = 0; r < cell.rowspan; r++) {
+                for (var c = 0; c < cell.colspan; c++) {
+                    Table_set(table,table.row+r,table.col+c,cell);
+                }
+            }
+            table.col += cell.colspan;
+            break;
+        }
+        case HTML_TR:
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                Table_processTable(table,child);
+            table.row++;
+            table.col = 0;
+            break;
+        default:
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                Table_processTable(table,child);
+            break;
+        }
+    }
+
+    // public
+    Tables_insertTable = function(rows,cols,width,numbered,caption,className)
+    {
+        UndoManager_newGroup("Insert table");
+
+        if (rows < 1)
+            rows = 1;
+        if (cols < 1)
+            cols = 1;
+
+        var haveCaption = (caption != null) && (caption != "");
+        var table = DOM_createElement(document,"TABLE");
+
+        if (width != null)
+            DOM_setStyleProperties(table,{"width": width});
+
+        if (className != null)
+            DOM_setAttribute(table,"class",className);
+
+        // Caption comes first
+        if (haveCaption) {
+            var tableCaption = DOM_createElement(document,"CAPTION");
+            DOM_appendChild(tableCaption,DOM_createTextNode(document,caption));
+            DOM_appendChild(table,tableCaption);
+        }
+
+        // Set equal column widths
+        var colWidth = Math.round(100/cols)+"%";
+        for (var c = 0; c < cols; c++) {
+            var col = DOM_createElement(document,"COL");
+            DOM_setAttribute(col,"width",colWidth);
+            DOM_appendChild(table,col);
+        }
+
+        var firstTD = null;
+
+        // Then the rows and columns
+        var tbody = DOM_createElement(document,"TBODY");
+        DOM_appendChild(table,tbody);
+        for (var r = 0; r < rows; r++) {
+            var tr = DOM_createElement(document,"TR");
+            DOM_appendChild(tbody,tr);
+            for (var c = 0; c < cols; c++) {
+                var td = DOM_createElement(document,"TD");
+                var p = DOM_createElement(document,"P");
+                var br = DOM_createElement(document,"BR");
+                DOM_appendChild(tr,td);
+                DOM_appendChild(td,p);
+                DOM_appendChild(p,br);
+
+                if (firstTD == null)
+                    firstTD = td;
+            }
+        }
+
+        Clipboard_pasteNodes([table]);
+
+        // Now that the table has been inserted into the DOM tree, the outline code will
+        // have noticed it and added an id attribute, as well as a caption giving the
+        // table number.
+        Outline_setNumbered(table.getAttribute("id"),numbered);
+
+        // Place the cursor at the start of the first cell on the first row
+        var pos = new Position(firstTD,0);
+        pos = Position_closestMatchForwards(pos,Position_okForMovement);
+        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+
+        PostponedActions_add(UndoManager_newGroup);
+    }
+
+    // private
+    function createEmptyTableCell(elementName)
+    {
+        var br = DOM_createElement(document,"BR");
+        var p = DOM_createElement(document,"P");
+        var td = DOM_createElement(document,elementName);
+        DOM_appendChild(p,br);
+        DOM_appendChild(td,p);
+        return td;
+    }
+
+    // private
+    function addEmptyTableCell(newTR,elementName)
+    {
+        var td = createEmptyTableCell(elementName);
+        DOM_appendChild(newTR,td);
+        return td;
+    }
+
+    // private
+    function populateNewRow(structure,newTR,newRow,oldRow)
+    {
+        var col = 0;
+        while (col < structure.numCols) {
+            var existingCell = Table_get(structure,oldRow,col);
+            if (((newRow > oldRow) && (newRow < existingCell.row + existingCell.rowspan)) ||
+                ((newRow < oldRow) && (newRow >= existingCell.row))) {
+                Cell_setRowspan(existingCell,existingCell.rowspan+1);
+            }
+            else {
+                var td = addEmptyTableCell(newTR,existingCell.element.nodeName); // check-ok
+                if (existingCell.colspan != 1)
+                    DOM_setAttribute(td,"colspan",existingCell.colspan);
+            }
+            col += existingCell.colspan;
+        }
+    }
+
+    function tableAtRightOfRange(range)
+    {
+        if (!Range_isEmpty(range))
+            return null;
+
+        var pos = Position_preferElementPosition(range.start);
+        if ((pos.node.nodeType == Node.ELEMENT_NODE) &&
+            (pos.offset < pos.node.childNodes.length) &&
+            (pos.node.childNodes[pos.offset]._type == HTML_TABLE)) {
+            var element = pos.node.childNodes[pos.offset];
+            var table = Tables_analyseStructure(element);
+            return table;
+        }
+        return null;
+    }
+
+    function tableAtLeftOfRange(range)
+    {
+        if (!Range_isEmpty(range))
+            return null;
+
+        var pos = Position_preferElementPosition(range.start);
+        if ((pos.node.nodeType == Node.ELEMENT_NODE) &&
+            (pos.offset > 0) &&
+            (pos.node.childNodes[pos.offset-1]._type == HTML_TABLE)) {
+            var element = pos.node.childNodes[pos.offset-1];
+            var table = Tables_analyseStructure(element);
+            return table;
+        }
+        return null;
+    }
+
+    function insertRowAbove(table,row)
+    {
+        var cell = Table_get(table,row,0);
+        var oldTR = cell.element.parentNode;
+        var newTR = DOM_createElement(document,"TR");
+        DOM_insertBefore(oldTR.parentNode,newTR,oldTR);
+        populateNewRow(table,newTR,row-1,row);
+    }
+
+    function insertRowBelow(table,row)
+    {
+        var cell = Table_get(table,row,0);
+        var oldTR = cell.element.parentNode;
+        var newTR = DOM_createElement(document,"TR");
+        DOM_insertBefore(oldTR.parentNode,newTR,oldTR.nextSibling);
+        populateNewRow(table,newTR,row+1,row);
+    }
+
+    function insertRowAdjacentToRange(range)
+    {
+        var table;
+
+        table = tableAtLeftOfRange(range);
+        if (table != null) {
+            insertRowBelow(table,table.numRows-1);
+            return;
+        }
+
+        table = tableAtRightOfRange(range);
+        if (table != null) {
+            insertRowAbove(table,0);
+            return;
+        }
+    }
+
+    // public
+    Tables_addAdjacentRow = function()
+    {
+        UndoManager_newGroup("Insert row below");
+        Selection_preserveWhileExecuting(function() {
+            var range = Selection_get();
+            var region = Tables_regionFromRange(range,true);
+            if (region != null)
+                insertRowBelow(region.structure,region.bottom);
+            else
+                insertRowAdjacentToRange(range);
+        });
+        UndoManager_newGroup();
+    }
+
+    // private
+    function getColElements(table)
+    {
+        var cols = new Array();
+        for (child = table.firstChild; child != null; child = child.nextSibling) {
+            switch (child._type) {
+            case HTML_COLGROUP:
+                for (var gc = child.firstChild; gc != null; gc = gc.nextSibling) {
+                    if (gc._type == HTML_COL)
+                        cols.push(gc);
+                }
+                break;
+            case HTML_COL:
+                cols.push(child);
+                break;
+            }
+        }
+        return cols;
+    }
+
+    // private
+    function getColWidths(colElements,expectedCount)
+    {
+        // FIXME: also handle the case where the width has been set as a CSS property in the
+        // style attribute. There's probably not much we can do if the width comes from a style
+        // rule elsewhere in the document though.
+        var colWidths = new Array();
+        for (var i = 0; i < colElements.length; i++) {
+            if (colElements[i].hasAttribute("width"))
+                colWidths.push(colElements[i].getAttribute("width"));
+            else
+                colWidths.push("");
+        }
+        return colWidths;
+    }
+
+    // private
+    function addMissingColElements(structure,colElements)
+    {
+        // If there are fewer COL elements than there are colums, add extra ones, copying the
+        // width value from the last one
+        // FIXME: handle col elements with colspan > 1, as well as colgroups with width set
+        // FIXME: What if there are 0 col elements?
+        while (colElements.length < structure.numCols) {
+            var newColElement = DOM_createElement(document,"COL");
+            var lastColElement = colElements[colElements.length-1];
+            DOM_insertBefore(lastColElement.parentNode,newColElement,lastColElement.nextSibling);
+            colElements.push(newColElement);
+            DOM_setAttribute(newColElement,"width",lastColElement.getAttribute("width"));
+        }
+    }
+
+    // private
+    function fixColPercentages(structure,colElements)
+    {
+        var colWidths = getColWidths(colElements,structure.numCols);
+
+        var percentages = colWidths.map(getPercentage);
+        if (percentages.every(notNull)) {
+            var colWidthTotal = 0;
+            for (var i = 0; i < percentages.length; i++)
+                colWidthTotal += percentages[i];
+
+            for (var i = 0; i < colElements.length; i++) {
+                var pct = 100*percentages[i]/colWidthTotal;
+                // Store value using at most two decimal places
+                pct = Math.round(100*pct)/100;
+                DOM_setAttribute(colElements[i],"width",pct+"%");
+            }
+        }
+
+        function notNull(arg)
+        {
+            return (arg != null);
+        }
+
+        function getPercentage(str)
+        {
+            if (str.match(/^\s*\d+(\.\d+)?\s*%\s*$/))
+                return parseInt(str.replace(/\s*%\s*$/,""));
+            else
+                return null;
+        }
+    }
+
+    // private
+    function addColElement(structure,oldIndex,right)
+    {
+        var table = structure.element;
+
+        var colElements = getColElements(table);
+        if (colElements.length == 0) {
+            // The table doesn't have any COL elements; don't add any
+            return;
+        }
+
+        addMissingColElements(structure,colElements);
+
+        var prevColElement = colElements[oldIndex];
+        var newColElement = DOM_createElement(document,"COL");
+        DOM_setAttribute(newColElement,"width",prevColElement.getAttribute("width"));
+        if (right)
+            DOM_insertBefore(prevColElement.parentNode,newColElement,prevColElement.nextSibling);
+        else
+            DOM_insertBefore(prevColElement.parentNode,newColElement,prevColElement);
+
+        if (right) {
+            colElements.splice(oldIndex+1,0,newColElement);
+        }
+        else {
+            colElements.splice(oldIndex+1,0,newColElement);
+        }
+
+        fixColPercentages(structure,colElements);
+    }
+
+    // private
+    function deleteColElements(structure,left,right)
+    {
+        var table = structure.element;
+
+        var colElements = getColElements(table);
+        if (colElements.length == 0) {
+            // The table doesn't have any COL elements
+            return;
+        }
+
+        addMissingColElements(structure,colElements);
+
+        for (var col = left; col <= right; col++)
+            DOM_deleteNode(colElements[col]);
+        colElements.splice(left,right-left+1);
+
+        fixColPercentages(structure,colElements);
+    }
+
+    // private
+    function addColumnCells(structure,oldIndex,right)
+    {
+        for (var row = 0; row < structure.numRows; row++) {
+            var cell = Table_get(structure,row,oldIndex);
+            var oldTD = cell.element;
+            if (cell.row == row) {
+
+                if (((right && (oldIndex+1 < cell.col + cell.colspan)) ||
+                    (!right && (oldIndex-1 >= cell.col))) &&
+                    (cell.colspan > 1)) {
+                    Cell_setColspan(cell,cell.colspan+1);
+                }
+                else {
+                    var newTD = createEmptyTableCell(oldTD.nodeName); // check-ok
+                    if (right)
+                        DOM_insertBefore(cell.element.parentNode,newTD,oldTD.nextSibling);
+                    else
+                        DOM_insertBefore(cell.element.parentNode,newTD,oldTD);
+                    if (cell.rowspan != 1)
+                        DOM_setAttribute(newTD,"rowspan",cell.rowspan);
+                }
+            }
+        }
+    }
+
+    function insertColumnAdjacentToRange(range)
+    {
+        var table;
+
+        table = tableAtLeftOfRange(range);
+        if (table != null) {
+            var right = table.numCols-1;
+            addColElement(table,right,right+1);
+            addColumnCells(table,right,true);
+            return;
+        }
+
+        table = tableAtRightOfRange(range);
+        if (table != null) {
+            var left = 0;
+            addColElement(table,left,left-1);
+            addColumnCells(table,left,false);
+            return;
+        }
+    }
+
+    // public
+    Tables_addAdjacentColumn = function()
+    {
+        UndoManager_newGroup("Insert column at right");
+        Selection_preserveWhileExecuting(function() {
+            var range = Selection_get();
+            var region = Tables_regionFromRange(range,true);
+            if (region != null) {
+                addColElement(region.structure,region.right,region.right+1);
+                addColumnCells(region.structure,region.right,true);
+            }
+            else {
+                insertColumnAdjacentToRange(range);
+            }
+        });
+        UndoManager_newGroup();
+    }
+
+    function columnHasContent(table,col)
+    {
+        for (var row = 0; row < table.numRows; row++) {
+            var cell = Table_get(table,row,col);
+            if ((cell != null) && (cell.col == col) && nodeHasContent(cell.element))
+                return true;
+        }
+        return false;
+    }
+
+    function rowHasContent(table,row)
+    {
+        for (var col = 0; col < table.numCols; col++) {
+            var cell = Table_get(table,row,col);
+            if ((cell != null) && (cell.row == row) && nodeHasContent(cell.element))
+                return true;
+        }
+        return false;
+    }
+
+    function selectRegion(table,top,bottom,left,right)
+    {
+        left = clampCol(table,left);
+        right = clampCol(table,right);
+        top = clampRow(table,top);
+        bottom = clampRow(table,bottom);
+
+        var tlCell = Table_get(table,top,left);
+        var brCell = Table_get(table,bottom,right);
+        if ((tlCell != null) && (brCell != null)) {
+            var tlPos = new Position(tlCell.element,0);
+            tlPos = Position_closestMatchForwards(tlPos,Position_okForMovement);
+
+            var brPos = new Position(brCell.element,brCell.element.childNodes.length);
+            brPos = Position_closestMatchBackwards(brPos,Position_okForMovement);
+
+            Selection_set(tlPos.node,tlPos.offset,brPos.node,brPos.offset);
+        }
+    }
+
+    function clampCol(table,col)
+    {
+        if (col > table.numCols-1)
+            col = table.numCols-1;
+        if (col < 0)
+            col = 0;
+        return col;
+    }
+
+    function clampRow(table,row)
+    {
+        if (row > table.numRows-1)
+            row = table.numRows-1;
+        if (row < 0)
+            row = 0;
+        return row;
+    }
+
+    function removeRowAdjacentToRange(range)
+    {
+        var table;
+
+        table = tableAtLeftOfRange(range);
+        if ((table != null) && (table.numRows >= 2)) {
+            UndoManager_newGroup("Delete one row");
+            var row = table.numRows-1;
+            Tables_deleteRegion(new TableRegion(table,row,row,0,table.numCols-1));
+            UndoManager_newGroup();
+            return;
+        }
+
+        table = tableAtRightOfRange(range);
+        if ((table != null) && (table.numRows >= 2)) {
+            UndoManager_newGroup("Delete one row");
+            Tables_deleteRegion(new TableRegion(table,0,0,0,table.numCols-1));
+            UndoManager_newGroup();
+            return;
+        }
+    }
+
+    Tables_removeAdjacentRow = function()
+    {
+        var range = Selection_get();
+        var region = Tables_regionFromRange(range,true);
+
+        if (region == null) {
+            removeRowAdjacentToRange(range);
+            return;
+        }
+
+        if (region.structure.numRows <= 1)
+            return;
+
+        UndoManager_newGroup("Delete one row");
+
+        var table = region.structure;
+        var left = region.left;
+        var right = region.right;
+        var top = region.top;
+        var bottom = region.bottom;
+
+        // Is there an empty row below the selection? If so, delete it
+        if ((bottom+1 < table.numRows) && !rowHasContent(table,bottom+1)) {
+            Selection_preserveWhileExecuting(function() {
+                Tables_deleteRegion(new TableRegion(table,bottom+1,bottom+1,0,table.numCols-1));
+            });
+        }
+
+        // Is there an empty row above the selection? If so, delete it
+        else if ((top-1 >= 0) && !rowHasContent(table,top-1)) {
+            Selection_preserveWhileExecuting(function() {
+                Tables_deleteRegion(new TableRegion(table,top-1,top-1,0,table.numCols-1));
+            });
+        }
+
+
+        // There are no empty rows adjacent to the selection. Delete the right-most row
+        // of the selection (which may be the only one)
+        else {
+            Selection_preserveWhileExecuting(function() {
+                Tables_deleteRegion(new TableRegion(table,bottom,bottom,0,table.numCols-1));
+            });
+
+            table = Tables_analyseStructure(table.element);
+            var multiple = (top != bottom);
+
+            if (multiple) {
+                selectRegion(table,top,bottom-1,left,right);
+            }
+            else {
+                var newRow = clampRow(table,bottom);
+                var newCell = Table_get(table,newRow,left);
+                if (newCell != null) {
+                    var pos = new Position(newCell.element,0);
+                    pos = Position_closestMatchForwards(pos,Position_okForMovement);
+                    Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+                }
+            }
+        }
+
+        UndoManager_newGroup();
+    }
+
+    function removeColumnAdjacentToRange(range)
+    {
+        var table;
+
+        table = tableAtLeftOfRange(range);
+        if ((table != null) && (table.numCols >= 2)) {
+            UndoManager_newGroup("Delete one column");
+            var col = table.numCols-1;
+            Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,col,col));
+            UndoManager_newGroup();
+            return;
+        }
+
+        table = tableAtRightOfRange(range);
+        if ((table != null) && (table.numCols >= 2)) {
+            UndoManager_newGroup("Delete one column");
+            Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,0,0));
+            UndoManager_newGroup();
+            return;
+        }
+    }
+
+    Tables_removeAdjacentColumn = function()
+    {
+        var range = Selection_get();
+        var region = Tables_regionFromRange(range,true);
+
+        if (region == null) {
+            removeColumnAdjacentToRange(range);
+            return;
+        }
+
+        if (region.structure.numCols <= 1)
+            return;
+
+        UndoManager_newGroup("Delete one column");
+
+        var table = region.structure;
+        var left = region.left;
+        var right = region.right;
+        var top = region.top;
+        var bottom = region.bottom;
+
+        // Is there an empty column to the right of the selection? If so, delete it
+        if ((right+1 < table.numCols) && !columnHasContent(table,right+1)) {
+            Selection_preserveWhileExecuting(function() {
+                Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,right+1,right+1));
+            });
+        }
+
+        // Is there an empty column to the left of the selection? If so, delete it
+        else if ((left-1 >= 0) && !columnHasContent(table,left-1)) {
+            Selection_preserveWhileExecuting(function() {
+                Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,left-1,left-1));
+            });
+        }
+
+        // There are no empty columns adjacent to the selection. Delete the right-most column
+        // of the selection (which may be the only one)
+        else {
+            Selection_preserveWhileExecuting(function() {
+                Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,right,right));
+            });
+
+            table = Tables_analyseStructure(table.element);
+            var multiple = (left != right);
+
+            if (multiple) {
+                selectRegion(table,top,bottom,left,right-1);
+            }
+            else {
+                var newCol = clampCol(table,right);
+                var newCell = Table_get(table,top,newCol);
+                if (newCell != null) {
+                    var pos = new Position(newCell.element,0);
+                    pos = Position_closestMatchForwards(pos,Position_okForMovement);
+                    Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+                }
+            }
+        }
+
+        UndoManager_newGroup();
+    }
+
+    // private
+    function deleteTable(structure)
+    {
+        DOM_deleteNode(structure.element);
+    }
+
+    // private
+    function deleteRows(structure,top,bottom)
+    {
+        var trElements = new Array();
+        getTRs(structure.element,trElements);
+
+        for (var row = top; row <= bottom; row++)
+            DOM_deleteNode(trElements[row]);
+    }
+
+    // private
+    function getTRs(node,result)
+    {
+        if (node._type == HTML_TR) {
+            result.push(node);
+        }
+        else {
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                getTRs(child,result);
+        }
+    }
+
+    // private
+    function deleteColumns(structure,left,right)
+    {
+        var nodesToDelete = new NodeSet();
+        for (var row = 0; row < structure.numRows; row++) {
+            for (var col = left; col <= right; col++) {
+                var cell = Table_get(structure,row,col);
+                nodesToDelete.add(cell.element);
+            }
+        }
+        nodesToDelete.forEach(DOM_deleteNode);
+        deleteColElements(structure,left,right);
+    }
+
+    // private
+    function deleteCellContents(region)
+    {
+        var structure = region.structure;
+        for (var row = region.top; row <= region.bottom; row++) {
+            for (var col = region.left; col <= region.right; col++) {
+                var cell = Table_get(structure,row,col);
+                DOM_deleteAllChildren(cell.element);
+            }
+        }
+    }
+
+    // public
+    Tables_deleteRegion = function(region)
+    {
+        var structure = region.structure;
+
+        var coversEntireWidth = (region.left == 0) && (region.right == structure.numCols-1);
+        var coversEntireHeight = (region.top == 0) && (region.bottom == structure.numRows-1);
+
+        if (coversEntireWidth && coversEntireHeight)
+            deleteTable(region.structure);
+        else if (coversEntireWidth)
+            deleteRows(structure,region.top,region.bottom);
+        else if (coversEntireHeight)
+            deleteColumns(structure,region.left,region.right);
+        else
+            deleteCellContents(region);
+    }
+
+    // public
+    Tables_clearCells = function()
+    {
+    }
+
+    // public
+    Tables_mergeCells = function()
+    {
+        Selection_preserveWhileExecuting(function() {
+            var region = Tables_regionFromRange(Selection_get());
+            if (region == null)
+                return;
+
+            var structure = region.structure;
+
+            // FIXME: handle the case of missing cells
+            // (or even better, add cells where there are some missing)
+
+            for (var row = region.top; row <= region.bottom; row++) {
+                for (var col = region.left; col <= region.right; col++) {
+                    var cell = Table_get(structure,row,col);
+                    var cellFirstRow = cell.row;
+                    var cellLastRow = cell.row + cell.rowspan - 1;
+                    var cellFirstCol = cell.col;
+                    var cellLastCol = cell.col + cell.colspan - 1;
+
+                    if ((cellFirstRow < region.top) || (cellLastRow > region.bottom) ||
+                        (cellFirstCol < region.left) || (cellLastCol > region.right)) {
+                        debug("Can't merge this table: cell at "+row+","+col+
+                              " goes outside bounds of selection");
+                        return;
+                    }
+                }
+            }
+
+            var mergedCell = Table_get(structure,region.top,region.left);
+
+            for (var row = region.top; row <= region.bottom; row++) {
+                for (var col = region.left; col <= region.right; col++) {
+                    var cell = Table_get(structure,row,col);
+                    // parentNode will be null if we've already done this cell
+                    if ((cell != mergedCell) && (cell.element.parentNode != null)) {
+                        while (cell.element.firstChild != null)
+                            DOM_appendChild(mergedCell.element,cell.element.firstChild);
+                        DOM_deleteNode(cell.element);
+                    }
+                }
+            }
+
+            var totalRows = region.bottom - region.top + 1;
+            var totalCols = region.right - region.left + 1;
+            if (totalRows == 1)
+                DOM_removeAttribute(mergedCell.element,"rowspan");
+            else
+                DOM_setAttribute(mergedCell.element,"rowspan",totalRows);
+            if (totalCols == 1)
+                DOM_removeAttribute(mergedCell.element,"colspan");
+            else
+                DOM_setAttribute(mergedCell.element,"colspan",totalCols);
+        });
+    }
+
+    // public
+    Tables_splitSelection = function()
+    {
+        Selection_preserveWhileExecuting(function() {
+            var range = Selection_get();
+            Range_trackWhileExecuting(range,function() {
+                var region = Tables_regionFromRange(range,true);
+                if (region != null)
+                    TableRegion_splitCells(region);
+            });
+        });
+    }
+
+    // public
+    TableRegion_splitCells = function(region)
+    {
+        var structure = region.structure;
+        var trElements = new Array();
+        getTRs(structure.element,trElements);
+
+        for (var row = region.top; row <= region.bottom; row++) {
+            for (var col = region.left; col <= region.right; col++) {
+                var cell = Table_get(structure,row,col);
+                if ((cell.rowspan > 1) || (cell.colspan > 1)) {
+
+                    var original = cell.element;
+
+                    for (var r = cell.top; r <= cell.bottom; r++) {
+                        for (var c = cell.left; c <= cell.right; c++) {
+                            if ((r == cell.top) && (c == cell.left))
+                                continue;
+                            var newTD = createEmptyTableCell(original.nodeName); // check-ok
+                            var nextElement = null;
+
+                            var nextCol = cell.right+1;
+                            while (nextCol < structure.numCols) {
+                                var nextCell = Table_get(structure,r,nextCol);
+                                if ((nextCell != null) && (nextCell.row == r)) {
+                                    nextElement = nextCell.element;
+                                    break;
+                                }
+                                nextCol++;
+                            }
+
+                            DOM_insertBefore(trElements[r],newTD,nextElement);
+                            Table_set(structure,r,c,new Cell(newTD,r,c));
+                        }
+                    }
+                    DOM_removeAttribute(original,"rowspan");
+                    DOM_removeAttribute(original,"colspan");
+                }
+            }
+        }
+    }
+
+    // public
+    Tables_cloneRegion = function(region)
+    {
+        var cellNodesDone = new NodeSet();
+        var table = DOM_shallowCopyElement(region.structure.element);
+        for (var row = region.top; row <= region.bottom; row++) {
+            var tr = DOM_createElement(document,"TR");
+            DOM_appendChild(table,tr);
+            for (var col = region.left; col <= region.right; col++) {
+                var cell = Table_get(region.structure,row,col);
+                if (!cellNodesDone.contains(cell.element)) {
+                    DOM_appendChild(tr,DOM_cloneNode(cell.element,true));
+                    cellNodesDone.add(cell.element);
+                }
+            }
+        }
+        return table;
+    }
+
+    // private
+    function pasteCells(fromTableElement,toRegion)
+    {
+        // FIXME
+        var fromStructure = Tables_analyseStructure(fromTableElement);
+    }
+
+    // public
+    Table_fix = function(table)
+    {
+        var changed = false;
+
+        var tbody = null;
+        for (var child = table.element.firstChild; child != null; child = child.nextSibling) {
+            if (child._type == HTML_TBODY)
+                tbody = child;
+        }
+
+        if (tbody == null)
+            return table; // FIXME: handle presence of THEAD and TFOOT, and also a missing TBODY
+
+        var trs = new Array();
+        for (var child = tbody.firstChild; child != null; child = child.nextSibling) {
+            if (child._type == HTML_TR)
+                trs.push(child);
+        }
+
+        while (trs.length < table.numRows) {
+            var tr = DOM_createElement(document,"TR");
+            DOM_appendChild(tbody,tr);
+            trs.push(tr);
+        }
+
+        for (var row = 0; row < table.numRows; row++) {
+            for (var col = 0; col < table.numCols; col++) {
+                var cell = Table_get(table,row,col);
+                if (cell == null) {
+                    var td = createEmptyTableCell("TD");
+                    DOM_appendChild(trs[row],td);
+                    changed = true;
+                }
+            }
+        }
+
+        if (changed)
+            return new Table(table.element);
+        else
+            return table;
+    }
+
+    // public
+    Table_fixColumnWidths = function(structure)
+    {
+        var colElements = getColElements(structure.element);
+        if (colElements.length == 0)
+            return;
+        addMissingColElements(structure,colElements);
+
+        var widths = Tables_getColWidths(structure);
+        fixWidths(widths,structure.numCols);
+        colElements = getColElements(structure.element);
+        for (var i = 0; i < widths.length; i++)
+            DOM_setAttribute(colElements[i],"width",widths[i]+"%");
+    }
+
+    // public
+    Tables_analyseStructure = function(element)
+    {
+        // FIXME: we should probably be preserving the selection here, since we are modifying
+        // the DOM (though I think it's unlikely it would cause problems, becausing the fixup
+        // logic only adds elements). However this method is called (indirectly) from within
+        // Selection_update(), which causes unbounded recursion due to the subsequent Selecton_set()
+        // that occurs.
+        var initial = new Table(element);
+        var fixed = Table_fix(initial);
+        return fixed;
+    }
+
+    // public
+    Tables_findContainingCell = function(node)
+    {
+        for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) {
+            if (isTableCell(ancestor))
+                return ancestor;
+        }
+        return null;
+    }
+
+    // public
+    Tables_findContainingTable = function(node)
+    {
+        for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) {
+            if (ancestor._type == HTML_TABLE)
+                return ancestor;
+        }
+        return null;
+    }
+
+    function TableRegion(structure,top,bottom,left,right)
+    {
+        this.structure = structure;
+        this.top = top;
+        this.bottom = bottom;
+        this.left = left;
+        this.right = right;
+    }
+
+    TableRegion.prototype.toString = function()
+    {
+        return "("+this.top+","+this.left+") - ("+this.bottom+","+this.right+")";
+    }
+
+    // public
+    Tables_regionFromRange = function(range,allowSameCell)
+    {
+        var region = null;
+
+        if (range == null)
+            return null;
+
+        var start = Position_closestActualNode(range.start,true);
+        var end = Position_closestActualNode(range.end,true);
+
+        var startTD = Tables_findContainingCell(start);
+        var endTD = Tables_findContainingCell(end);
+
+        if (!isTableCell(start) || !isTableCell(end)) {
+            if (!allowSameCell) {
+                if (startTD == endTD) // not in cell, or both in same cell
+                    return null;
+            }
+        }
+
+        if ((startTD == null) || (endTD == null))
+            return null;
+
+        var startTable = Tables_findContainingTable(startTD);
+        var endTable = Tables_findContainingTable(endTD);
+
+        if (startTable != endTable)
+            return null;
+
+        var structure = Tables_analyseStructure(startTable);
+
+        var startInfo = structure.cellsByElement.get(startTD);
+        var endInfo = structure.cellsByElement.get(endTD);
+
+        var startTopRow = startInfo.row;
+        var startBottomRow = startInfo.row + startInfo.rowspan - 1;
+        var startLeftCol = startInfo.col;
+        var startRightCol = startInfo.col + startInfo.colspan - 1;
+
+        var endTopRow = endInfo.row;
+        var endBottomRow = endInfo.row + endInfo.rowspan - 1;
+        var endLeftCol = endInfo.col;
+        var endRightCol = endInfo.col + endInfo.colspan - 1;
+
+        var top = (startTopRow < endTopRow) ? startTopRow : endTopRow;
+        var bottom = (startBottomRow > endBottomRow) ? startBottomRow : endBottomRow;
+        var left = (startLeftCol < endLeftCol) ? startLeftCol : endLeftCol;
+        var right = (startRightCol > endRightCol) ? startRightCol : endRightCol;
+
+        var region = new TableRegion(structure,top,bottom,left,right);
+        adjustRegionForSpannedCells(region);
+        return region;
+    }
+
+    // private
+    function adjustRegionForSpannedCells(region)
+    {
+        var structure = region.structure;
+        var boundariesOk;
+        var columnsOk;
+        do {
+            boundariesOk = true;
+            for (var row = region.top; row <= region.bottom; row++) {
+                var cell = Table_get(structure,row,region.left);
+                if (region.left > cell.left) {
+                    region.left = cell.left;
+                    boundariesOk = false;
+                }
+                cell = Table_get(structure,row,region.right);
+                if (region.right < cell.right) {
+                    region.right = cell.right;
+                    boundariesOk = false;
+                }
+            }
+
+            for (var col = region.left; col <= region.right; col++) {
+                var cell = Table_get(structure,region.top,col);
+                if (region.top > cell.top) {
+                    region.top = cell.top;
+                    boundariesOk = false;
+                }
+                cell = Table_get(structure,region.bottom,col);
+                if (region.bottom < cell.bottom) {
+                    region.bottom = cell.bottom;
+                    boundariesOk = false;
+                }
+            }
+        } while (!boundariesOk);
+    }
+
+    Tables_getSelectedTableId = function()
+    {
+        var element = Cursor_getAdjacentNodeWithType(HTML_TABLE);
+        return element ? element.getAttribute("id") : null;
+    }
+
+    Tables_getProperties = function(itemId)
+    {
+        var element = document.getElementById(itemId);
+        if ((element == null) || (element._type != HTML_TABLE))
+            return null;
+        var structure = Tables_analyseStructure(element);
+        var width = element.style.width;
+        return { width: width, rows: structure.numRows, cols: structure.numCols };
+    }
+
+    Tables_setProperties = function(itemId,width)
+    {
+        var table = document.getElementById(itemId);
+        if (table == null)
+            return null;
+        DOM_setStyleProperties(table,{ width: width });
+        Selection_update(); // ensure cursor/selection drawn in correct pos
+    }
+
+    // Returns an array of numbers representing the percentage widths (0 - 100) of each
+    // column. This works on the assumption that all tables are supposed to have all of
+    // their column widths specified, and in all cases as percentages. Any which do not
+    // are considered invalid, and have any non-percentage values filled in based on the
+    // average values of all valid percentage-based columns.
+    Tables_getColWidths = function(structure)
+    {
+        var colElements = getColElements(structure.element);
+        var colWidths = new Array();
+
+        for (var i = 0; i < structure.numCols; i++) {
+            var value = null;
+
+            if (i < colElements.length) {
+                var widthStr = DOM_getAttribute(colElements[i],"width");
+                if (widthStr != null) {
+                    value = parsePercentage(widthStr);
+                }
+            }
+
+            if ((value != null) && (value >= 1.0)) {
+                colWidths[i] = value;
+            }
+            else {
+                colWidths[i] = null;
+            }
+        }
+
+        fixWidths(colWidths,structure.numCols);
+
+        return colWidths;
+
+        function parsePercentage(str)
+        {
+            if (str.match(/^\s*\d+(\.\d+)?\s*%\s*$/))
+                return parseFloat(str.replace(/\s*%\s*$/,""));
+            else
+                return null;
+        }
+    }
+
+    function fixWidths(colWidths,numCols)
+    {
+        var totalWidth = 0;
+        var numValidCols = 0;
+        for (var i = 0; i < numCols; i++) {
+            if (colWidths[i] != null) {
+                totalWidth += colWidths[i];
+                numValidCols++;
+            }
+        }
+
+        var averageWidth = (numValidCols > 0) ? totalWidth/numValidCols : 1.0;
+        for (var i = 0; i < numCols; i++) {
+            if (colWidths[i] == null) {
+                colWidths[i] = averageWidth;
+                totalWidth += averageWidth;
+            }
+        }
+
+        // To cater for the case where the column widths do not all add up to 100%,
+        // recalculate all of them based on their value relative to the total width
+        // of all columns. For example, if there are three columns of 33%, 33%, and 33%,
+        // these will get rounded up to 33.33333.....%.
+        // If there are no column widths defined, each will have 100/numCols%.
+        if (totalWidth > 0) {
+            for (var i = 0; i < numCols; i++) {
+                colWidths[i] = 100.0*colWidths[i]/totalWidth;
+            }
+        }
+    }
+
+    // public
+    Tables_setColWidths = function(itemId,widths)
+    {
+        var element = document.getElementById(itemId);
+        if (element == null)
+            return null;
+
+        var structure = Tables_analyseStructure(element);
+
+        fixWidths(widths,structure.numCols);
+
+        var colElements = getColElements(element);
+        for (var i = 0; i < widths.length; i++)
+            DOM_setAttribute(colElements[i],"width",widths[i]+"%");
+
+        Selection_update();
+    }
+
+    // public
+    Tables_getGeometry = function(itemId)
+    {
+        var element = document.getElementById(itemId);
+        if ((element == null) || (element.parentNode == null))
+            return null;
+
+        var structure = Tables_analyseStructure(element);
+
+        var result = new Object();
+
+        // Calculate the rect based on the cells, not the whole table element;
+        // we want to ignore the caption
+        var topLeftCell = Table_get(structure,0,0);
+        var bottomRightCell = Table_get(structure,structure.numRows-1,structure.numCols-1);
+
+        if (topLeftCell == null)
+            throw new Error("No top left cell");
+        if (bottomRightCell == null)
+            throw new Error("No bottom right cell");
+
+        var topLeftRect = topLeftCell.element.getBoundingClientRect();
+        var bottomRightRect = bottomRightCell.element.getBoundingClientRect();
+
+        var left = topLeftRect.left + window.scrollX;
+        var right = bottomRightRect.right + window.scrollX;
+        var top = topLeftRect.top + window.scrollY;
+        var bottom = bottomRightRect.bottom + window.scrollY;
+
+        result.contentRect = { x: left, y: top, width: right - left, height: bottom - top };
+        result.fullRect = xywhAbsElementRect(element);
+        result.parentRect = xywhAbsElementRect(element.parentNode);
+
+        result.columnWidths = Tables_getColWidths(structure);
+
+        var caption = firstChildOfType(element,HTML_CAPTION);
+        result.hasCaption = (caption != null);
+
+        return result;
+
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Text.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Text.js b/experiments/editorFramework/src/Javascript_Layer_0/Text.js
new file mode 100644
index 0000000..5a69feb
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Text.js
@@ -0,0 +1,543 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Text_findParagraphBoundaries;
+var Text_analyseParagraph;
+var Text_posAbove;
+var Text_posBelow;
+var Text_closestPosBackwards;
+var Text_closestPosForwards;
+var Text_closestPosInDirection;
+
+var Paragraph_runFromOffset;
+var Paragraph_runFromNode;
+var Paragraph_positionAtOffset;
+var Paragraph_offsetAtPosition;
+var Paragraph_getRunRects;
+var Paragraph_getRunOrFallbackRects;
+
+var Text_toStartOfBoundary;
+var Text_toEndOfBoundary;
+
+(function() {
+
+    function Paragraph(node,startOffset,endOffset,runs,text)
+    {
+        this.node = node;
+        this.startOffset = startOffset;
+        this.endOffset = endOffset;
+        this.runs = runs;
+        this.text = text;
+
+        Object.defineProperty(this,"first",{
+            get: function() { throw new Error("Attempt to access first property of Position") },
+            set: function() {},
+            enumerable: true });
+        Object.defineProperty(this,"last",{
+            get: function() { throw new Error("Attempt to access last property of Position") },
+            set: function() {},
+            enumerable: true });
+    }
+
+    function Run(node,start,end)
+    {
+        this.node = node;
+        this.start = start;
+        this.end = end;
+    }
+
+    // In this code, we represent a paragraph by its first and last node. Normally, this will be
+    // the first and last child of a paragraph-level element (e.g. p or h1), but this scheme also
+    // represent a sequence of inline nodes between two paragraph or container nodes, e.g.
+    //
+    // <p>...</p> Some <i>inline</i> nodes <p>...</p>
+
+    Text_findParagraphBoundaries = function(pos)
+    {
+        Position_assertValid(pos);
+        var startOffset = pos.offset;
+        var endOffset = pos.offset;
+        var node = pos.node;
+
+        while (isInlineNode(node)) {
+            startOffset = DOM_nodeOffset(node);
+            endOffset = DOM_nodeOffset(node)+1;
+            node = node.parentNode;
+        }
+
+        if (node.nodeType != Node.ELEMENT_NODE)
+            throw new Error("Not an element node: "+nodeString(node));
+
+        while ((startOffset > 0) && isInlineNode(node.childNodes[startOffset-1]))
+            startOffset--;
+        while ((endOffset < node.childNodes.length) && isInlineNode(node.childNodes[endOffset]))
+            endOffset++;
+
+        return { node: node, startOffset: startOffset, endOffset: endOffset };
+    }
+
+    Text_analyseParagraph = function(pos)
+    {
+        var initial = pos.node;
+        var strings = new Array();
+        var runs = new Array();
+        var offset = 0;
+
+        var boundaries = Text_findParagraphBoundaries(pos);
+        if (boundaries == null)
+            return null;
+
+        for (var off = boundaries.startOffset; off < boundaries.endOffset; off++)
+            recurse(boundaries.node.childNodes[off]);
+
+        var text = strings.join("");
+
+        return new Paragraph(boundaries.node,boundaries.startOffset,boundaries.endOffset,runs,text);
+
+        function recurse(node)
+        {
+            if (node.nodeType == Node.TEXT_NODE) {
+                strings.push(node.nodeValue);
+                var start = offset;
+                var end = offset + node.nodeValue.length;
+                runs.push(new Run(node,start,end));
+                offset += node.nodeValue.length;
+            }
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+    Text_posAbove = function(pos,cursorRect,cursorX)
+    {
+        if (cursorX == null)
+            cursorX = pos.targetX;
+        pos = Position_closestMatchBackwards(pos,Position_okForMovement);
+        if (cursorRect == null) {
+            cursorRect = Position_rectAtPos(pos);
+            if (cursorRect == null)
+                return null;
+        }
+
+        if (cursorX == null) {
+            cursorX = cursorRect.left;
+        }
+
+        while (true) {
+            pos = Position_closestMatchBackwards(pos,Position_okForMovement);
+            if (pos == null)
+                return null;
+
+            var paragraph = Text_analyseParagraph(pos);
+            if (paragraph == null)
+                return null;
+
+            var rects = Paragraph_getRunOrFallbackRects(paragraph,pos);
+
+            rects = rects.filter(function (rect) {
+                return (rect.bottom <= cursorRect.top);
+            });
+
+
+
+            var bottom = findLowestBottom(rects);
+
+            rects = rects.filter(function (rect) { return (rect.bottom == bottom); });
+
+            // Scroll previous line into view, if necessary
+            var top = findHighestTop(rects);
+            if (top < 0) {
+                var offset = -top;
+                window.scrollBy(0,-offset);
+                rects = offsetRects(rects,0,offset);
+            }
+
+            for (var i = 0; i < rects.length; i++) {
+                if ((cursorX >= rects[i].left) && (cursorX <= rects[i].right)) {
+                    var newPos = Position_atPoint(cursorX,rects[i].top + rects[i].height/2);
+                    if (newPos != null) {
+                        newPos = Position_closestMatchBackwards(newPos,Position_okForInsertion);
+                        newPos.targetX = cursorX;
+                        return newPos;
+                    }
+                }
+            }
+
+            var rightMost = findRightMostRect(rects);
+            if (rightMost != null) {
+                var newPos = Position_atPoint(rightMost.right,rightMost.top + rightMost.height/2);
+                if (newPos != null) {
+                    newPos = Position_closestMatchBackwards(newPos,Position_okForInsertion);
+                    newPos.targetX = cursorX;
+                    return newPos;
+                }
+            }
+
+
+            pos = new Position(paragraph.node,paragraph.startOffset);
+            pos = Position_prevMatch(pos,Position_okForMovement);
+        }
+    }
+
+    var findHighestTop = function(rects)
+    {
+        var top = null;
+        for (var i = 0; i < rects.length; i++) {
+            if ((top == null) || (top > rects[i].top))
+                top = rects[i].top;
+        }
+        return top;
+    }
+
+    var findLowestBottom = function(rects)
+    {
+        var bottom = null;
+        for (var i = 0; i < rects.length; i++) {
+            if ((bottom == null) || (bottom < rects[i].bottom))
+                bottom = rects[i].bottom;
+        }
+        return bottom;
+    }
+
+    var findRightMostRect = function(rects)
+    {
+        var rightMost = null;
+        for (var i = 0; i < rects.length; i++) {
+            if ((rightMost == null) || (rightMost.right < rects[i].right))
+                rightMost = rects[i];
+        }
+        return rightMost;
+    }
+
+    var offsetRects = function(rects,offsetX,offsetY)
+    {
+        var result = new Array();
+        for (var i = 0; i < rects.length; i++) {
+            result.push({ top: rects[i].top + offsetY,
+                          bottom: rects[i].bottom + offsetY,
+                          left: rects[i].left + offsetX,
+                          right: rects[i].right + offsetX,
+                          width: rects[i].width,
+                          height: rects[i].height });
+        }
+        return result;
+    }
+
+    Text_posBelow = function(pos,cursorRect,cursorX)
+    {
+        if (cursorX == null)
+            cursorX = pos.targetX;
+        pos = Position_closestMatchForwards(pos,Position_okForMovement);
+        if (cursorRect == null) {
+            cursorRect = Position_rectAtPos(pos);
+            if (cursorRect == null)
+                return null;
+        }
+
+        if (cursorX == null) {
+            cursorX = cursorRect.left;
+        }
+
+
+        while (true) {
+            pos = Position_closestMatchForwards(pos,Position_okForMovement);
+            if (pos == null)
+                return null;
+
+            var paragraph = Text_analyseParagraph(pos);
+            if (paragraph == null)
+                return null;
+
+            var rects = Paragraph_getRunOrFallbackRects(paragraph,pos);
+
+            rects = rects.filter(function (rect) {
+                return (rect.top >= cursorRect.bottom);
+            });
+
+            var top = findHighestTop(rects);
+
+            rects = rects.filter(function (rect) { return (rect.top == top); });
+
+            // Scroll next line into view, if necessary
+            var bottom = findLowestBottom(rects);
+            if (bottom > window.innerHeight) {
+                var offset = window.innerHeight - bottom;
+                window.scrollBy(0,-offset);
+                rects = offsetRects(rects,0,offset);
+            }
+
+            for (var i = 0; i < rects.length; i++) {
+                if ((cursorX >= rects[i].left) && (cursorX <= rects[i].right)) {
+                    var newPos = Position_atPoint(cursorX,rects[i].top + rects[i].height/2);
+                    if (newPos != null) {
+                        newPos = Position_closestMatchForwards(newPos,Position_okForInsertion);
+                        newPos.targetX = cursorX;
+                        return newPos;
+                    }
+                }
+            }
+
+            var rightMost = findRightMostRect(rects);
+            if (rightMost != null) {
+                var newPos = Position_atPoint(rightMost.right,rightMost.top + rightMost.height/2);
+                if (newPos != null) {
+                    newPos = Position_closestMatchForwards(newPos,Position_okForInsertion);
+                    newPos.targetX = cursorX;
+                    return newPos;
+                }
+            }
+
+            pos = new Position(paragraph.node,paragraph.endOffset);
+            pos = Position_nextMatch(pos,Position_okForMovement);
+        }
+    }
+
+    Text_closestPosBackwards = function(pos)
+    {
+        if (isNonWhitespaceTextNode(pos.node))
+            return pos;
+        var node;
+        if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset > 0)) {
+            node = pos.node.childNodes[pos.offset-1];
+            while (node.lastChild != null)
+                node = node.lastChild;
+        }
+        else {
+            node = pos.node;
+        }
+        while ((node != null) && (node != document.body) && !isNonWhitespaceTextNode(node))
+            node = prevNode(node);
+
+        if ((node == null) || (node == document.body))
+            return null;
+        else
+            return new Position(node,node.nodeValue.length);
+    }
+
+    Text_closestPosForwards = function(pos)
+    {
+        if (isNonWhitespaceTextNode(pos.node))
+            return pos;
+        var node;
+        if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset < pos.node.childNodes.length)) {
+            node = pos.node.childNodes[pos.offset];
+            while (node.firstChild != null)
+                node = node.firstChild;
+        }
+        else {
+            node = nextNodeAfter(pos.node);
+        }
+        while ((node != null) && !isNonWhitespaceTextNode(node)) {
+            var old = nodeString(node);
+            node = nextNode(node);
+        }
+
+        if (node == null)
+            return null;
+        else
+            return new Position(node,0);
+    }
+
+    Text_closestPosInDirection = function(pos,direction)
+    {
+        if ((direction == "forward") ||
+            (direction == "right") ||
+            (direction == "down")) {
+            return Text_closestPosForwards(pos);
+        }
+        else {
+            return Text_closestPosBackwards(pos);
+        }
+    }
+
+    Paragraph_runFromOffset = function(paragraph,offset,end)
+    {
+        if (paragraph.runs.length == 0)
+            throw new Error("Paragraph has no runs");
+        if (!end) {
+
+            for (var i = 0; i < paragraph.runs.length; i++) {
+                var run = paragraph.runs[i];
+                if ((offset >= run.start) && (offset < run.end))
+                    return run;
+                if ((i == paragraph.runs.length-1) && (offset == run.end))
+                    return run;
+            }
+
+        }
+        else {
+
+            for (var i = 0; i < paragraph.runs.length; i++) {
+                var run = paragraph.runs[i];
+                if ((offset > run.start) && (offset <= run.end))
+                    return run;
+                if ((i == 0) && (offset == 0))
+                    return run;
+            }
+
+        }
+    }
+
+    Paragraph_runFromNode = function(paragraph,node)
+    {
+        for (var i = 0; i < paragraph.runs.length; i++) {
+            if (paragraph.runs[i].node == node)
+                return paragraph.runs[i];
+        }
+        throw new Error("Run for text node not found");
+    }
+
+    Paragraph_positionAtOffset = function(paragraph,offset,end)
+    {
+        var run = Paragraph_runFromOffset(paragraph,offset,end);
+        if (run == null)
+            throw new Error("Run at offset "+offset+" not found");
+        return new Position(run.node,offset-run.start);
+    }
+
+    Paragraph_offsetAtPosition = function(paragraph,pos)
+    {
+        var run = Paragraph_runFromNode(paragraph,pos.node);
+        return run.start + pos.offset;
+    }
+
+    Paragraph_getRunRects = function(paragraph)
+    {
+        var rects = new Array();
+        for (var i = 0; i < paragraph.runs.length; i++) {
+            var run = paragraph.runs[i];
+            var runRange = new Range(run.node,0,run.node,run.node.nodeValue.length);
+            var runRects = Range_getClientRects(runRange);
+            Array.prototype.push.apply(rects,runRects);
+        }
+        return rects;
+    }
+
+    Paragraph_getRunOrFallbackRects = function(paragraph,pos)
+    {
+        var rects = Paragraph_getRunRects(paragraph);
+        if ((rects.length == 0) && (paragraph.node.nodeType == Node.ELEMENT_NODE)) {
+            if (isBlockNode(paragraph.node) &&
+                (paragraph.startOffset == 0) &&
+                (paragraph.endOffset == paragraph.node.childNodes.length)) {
+                rects = [paragraph.node.getBoundingClientRect()];
+            }
+            else {
+                var beforeNode = paragraph.node.childNodes[paragraph.startOffset-1];
+                var afterNode = paragraph.node.childNodes[paragraph.endOffset];
+                if ((afterNode != null) && isBlockNode(afterNode)) {
+                    rects = [afterNode.getBoundingClientRect()];
+                }
+                else if ((beforeNode != null) && isBlockNode(beforeNode)) {
+                    rects = [beforeNode.getBoundingClientRect()];
+                }
+            }
+        }
+        return rects;
+    }
+
+    function toStartOfParagraph(pos)
+    {
+        pos = Position_closestMatchBackwards(pos,Position_okForMovement);
+        if (pos == null)
+            return null;
+        var paragraph = Text_analyseParagraph(pos);
+        if (paragraph == null)
+            return null;
+
+        var newPos = new Position(paragraph.node,paragraph.startOffset);
+        return Position_closestMatchForwards(newPos,Position_okForMovement);
+    }
+
+    function toEndOfParagraph(pos)
+    {
+        pos = Position_closestMatchForwards(pos,Position_okForMovement);
+        if (pos == null)
+            return null;
+        var paragraph = Text_analyseParagraph(pos);
+        if (paragraph == null)
+            return null;
+
+        var newPos = new Position(paragraph.node,paragraph.endOffset);
+        return Position_closestMatchBackwards(newPos,Position_okForMovement);
+    }
+
+    function toStartOfLine(pos)
+    {
+        var posRect = Position_rectAtPos(pos);
+        if (posRect == null) {
+            pos = Text_closestPosBackwards(pos);
+            posRect = Position_rectAtPos(pos);
+            if (posRect == null) {
+                return null;
+            }
+        }
+
+        while (true) {
+            var check = Position_prevMatch(pos,Position_okForMovement);
+            var checkRect = Position_rectAtPos(check); // handles check == null case
+            if (checkRect == null)
+                return pos;
+            if ((checkRect.bottom <= posRect.top) || (checkRect.top >= posRect.bottom))
+                return pos;
+            pos = check;
+        }
+    }
+
+    function toEndOfLine(pos)
+    {
+        var posRect = Position_rectAtPos(pos);
+        if (posRect == null) {
+            pos = Text_closestPosForwards(pos);
+            posRect = Position_rectAtPos(pos);
+            if (posRect == null) {
+                return null;
+            }
+        }
+
+        while (true) {
+            var check = Position_nextMatch(pos,Position_okForMovement);
+            var checkRect = Position_rectAtPos(check); // handles check == null case
+            if (checkRect == null)
+                return pos;
+            if ((checkRect.bottom <= posRect.top) || (checkRect.top >= posRect.bottom))
+                return pos;
+            pos = check;
+        }
+    }
+
+    Text_toStartOfBoundary = function(pos,boundary)
+    {
+        if (boundary == "paragraph")
+            return toStartOfParagraph(pos);
+        else if (boundary == "line")
+            return toStartOfLine(pos);
+        else
+            throw new Error("Unsupported boundary: "+boundary);
+    }
+
+    Text_toEndOfBoundary = function(pos,boundary)
+    {
+        if (boundary == "paragraph")
+            return toEndOfParagraph(pos);
+        else if (boundary == "line")
+            return toEndOfLine(pos);
+        else
+            throw new Error("Unsupported boundary: "+boundary);
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/UndoManager.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/UndoManager.js b/experiments/editorFramework/src/Javascript_Layer_0/UndoManager.js
new file mode 100644
index 0000000..9f63c43
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/UndoManager.js
@@ -0,0 +1,270 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+// FIXME: place a limit on the number of undo steps recorded - say, 30-50?
+
+var UndoManager_getLength;
+var UndoManager_getIndex;
+var UndoManager_setIndex;
+var UndoManager_print;
+var UndoManager_undo;
+var UndoManager_redo;
+var UndoManager_addAction;
+var UndoManager_newGroup;
+var UndoManager_groupType;
+var UndoManager_disableWhileExecuting;
+var UndoManager_isActive;
+var UndoManager_isDisabled;
+var UndoManager_clear;
+var UndoManager_setProperty;
+var UndoManager_deleteProperty;
+
+(function() {
+
+    var UNDO_LIMIT = 50;
+
+    function UndoGroup(type,onClose)
+    {
+        this.type = type;
+        this.onClose = onClose;
+        this.actions = new Array();
+    }
+
+    function UndoAction(fun,args)
+    {
+        this.fun = fun;
+        this.args = args;
+    }
+
+    UndoAction.prototype.toString = function()
+    {
+        var name;
+        if (this.fun.wrappedName != null)
+            name = this.fun.wrappedName;
+        else
+            name = this.fun.name;
+
+        var argStrings = new Array();
+        for (var i = 0; i < this.args.length; i++) {
+            if (this.args[i] instanceof Node)
+                argStrings.push(nodeString(this.args[i]));
+            else if (this.args[i] == null)
+                argStrings.push("null");
+            else
+                argStrings.push(this.args[i].toString());
+        }
+
+        return name + "(" + argStrings.join(",") + ")";
+    }
+
+    var undoStack = new Array();
+    var redoStack = new Array();
+    var inUndo = false;
+    var inRedo = false;
+    var currentGroup = null;
+    var disabled = 0;
+
+    // public
+    UndoManager_getLength = function()
+    {
+        return undoStack.length + redoStack.length;
+    }
+
+    // public
+    UndoManager_getIndex = function()
+    {
+        return undoStack.length;
+    }
+
+    // public
+    UndoManager_setIndex = function(index)
+    {
+        while (undoStack.length > index)
+            UndoManager_undo();
+        while (undoStack.length < index)
+            UndoManager_redo();
+    }
+
+    // public
+    UndoManager_print = function()
+    {
+        debug("");
+        debug("--------------------------------------------------------------------");
+        debug("Undo stack:");
+        for (var groupIndex = 0; groupIndex < undoStack.length; groupIndex++) {
+            var group = undoStack[groupIndex];
+            debug("    "+group.type);
+            for (var actionIndex = 0; actionIndex < group.actions.length; actionIndex++) {
+                var action = group.actions[actionIndex];
+                debug("        "+action);
+            }
+        }
+        debug("Redo stack:");
+        for (var groupIndex = 0; groupIndex < redoStack.length; groupIndex++) {
+            var group = redoStack[groupIndex];
+            debug("    "+group.type);
+            for (var actionIndex = 0; actionIndex < group.actions.length; actionIndex++) {
+                var action = group.actions[actionIndex];
+                debug("        "+action);
+            }
+        }
+        debug("Current group = "+currentGroup);
+        debug("--------------------------------------------------------------------");
+        debug("");
+    }
+
+    function closeCurrentGroup()
+    {
+        if ((currentGroup != null) && (currentGroup.onClose != null))
+            currentGroup.onClose();
+        currentGroup = null;
+    }
+
+    // public
+    UndoManager_undo = function()
+    {
+        closeCurrentGroup();
+        if (undoStack.length > 0) {
+            var group = undoStack.pop();
+            inUndo = true;
+            for (var i = group.actions.length-1; i >= 0; i--)
+                group.actions[i].fun.apply(null,group.actions[i].args);
+            inUndo = false;
+        }
+        closeCurrentGroup();
+    }
+
+    // public
+    UndoManager_redo = function()
+    {
+        closeCurrentGroup();
+        if (redoStack.length > 0) {
+            var group = redoStack.pop();
+            inRedo = true;
+            for (var i = group.actions.length-1; i >= 0; i--)
+                group.actions[i].fun.apply(null,group.actions[i].args);
+            inRedo = false;
+        }
+        closeCurrentGroup();
+    }
+
+    // public
+    UndoManager_addAction = function(fun)
+    {
+        if (disabled > 0)
+            return;
+
+        // remaining parameters after fun are arguments to be supplied to fun
+        var args = new Array();
+        for (var i = 1; i < arguments.length; i++)
+            args.push(arguments[i]);
+
+        if (!inUndo && !inRedo && (redoStack.length > 0))
+            redoStack.length = 0;
+
+        var stack = inUndo ? redoStack : undoStack;
+        if (currentGroup == null)
+            UndoManager_newGroup(null);
+
+        // Only add a group to the undo stack one it has at least one action, to avoid having
+        // empty groups present.
+        if (currentGroup.actions.length == 0) {
+            if (!inUndo && !inRedo && (stack.length == UNDO_LIMIT))
+                stack.shift();
+            stack.push(currentGroup);
+        }
+
+        currentGroup.actions.push(new UndoAction(fun,args));
+    }
+
+    // public
+    UndoManager_newGroup = function(type,onClose)
+    {
+        if (disabled > 0)
+            return;
+
+        closeCurrentGroup();
+
+        // We don't actually add the group to the undo stack until the first request to add an
+        // action to it. This way we don't end up with empty groups in the undo stack, which
+        // simplifies logic for moving back and forward through the undo history.
+
+        if ((type == null) || (type == ""))
+            type = "Anonymous";
+        currentGroup = new UndoGroup(type,onClose);
+    }
+
+    // public
+    UndoManager_groupType = function()
+    {
+        if (undoStack.length > 0)
+            return undoStack[undoStack.length-1].type;
+        else
+            return null;
+    }
+
+    UndoManager_disableWhileExecuting = function(fun) {
+        disabled++;
+        try {
+            return fun();
+        }
+        finally {
+            disabled--;
+        }
+    }
+
+    UndoManager_isActive = function()
+    {
+        return (inUndo || inRedo);
+    }
+
+    UndoManager_isDisabled = function() {
+        return (disabled > 0);
+    }
+
+    UndoManager_clear = function() {
+        undoStack.length = 0;
+        redoStack.length = 0;
+    }
+
+    function saveProperty(obj,name)
+    {
+        if (obj.hasOwnProperty(name))
+            UndoManager_addAction(UndoManager_setProperty,obj,name,obj[name]);
+        else
+            UndoManager_addAction(UndoManager_deleteProperty,obj,name);
+    }
+
+    UndoManager_setProperty = function(obj,name,value)
+    {
+        if (obj.hasOwnProperty(name) && (obj[name] == value))
+            return; // no point in adding an undo action
+        saveProperty(obj,name);
+        obj[name] = value;
+    }
+
+    UndoManager_deleteProperty = function(obj,name)
+    {
+        if (!obj.hasOwnProperty(name))
+            return; // no point in adding an undo action
+        saveProperty(obj,name);
+        delete obj[name];
+    }
+
+})();
+
+window.undoSupported = true;

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Viewport.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Viewport.js b/experiments/editorFramework/src/Javascript_Layer_0/Viewport.js
new file mode 100644
index 0000000..47fbdfd
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Viewport.js
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Viewport_init;
+var Viewport_setViewportWidth;
+var Viewport_setTextScale;
+
+(function() {
+
+    var viewportMetaElement = null;
+
+    // public
+    Viewport_init = function(width,textScale)
+    {
+        var head = DOM_documentHead(document);
+        for (var child = head.firstChild; child != null; child = child.nextSibling) {
+            if ((child._type == HTML_META) && (child.getAttribute("name") == "viewport")) {
+                viewportMetaElement = child;
+                break;
+            }
+        }
+
+        if (viewportMetaElement == null) {
+            viewportMetaElement = DOM_createElement(document,"META");
+            DOM_setAttribute(viewportMetaElement,"name","viewport");
+            DOM_appendChild(head,viewportMetaElement);
+        }
+
+        if (width != 0) {
+            // Only set the width and text scale if they are not already set, to avoid triggering
+            // an extra layout at load time
+            var contentValue = "width = "+width+", user-scalable = no";
+            if (viewportMetaElement.getAttribute("content") != contentValue)
+                DOM_setAttribute(viewportMetaElement,"content",contentValue);
+        }
+
+        if (textScale != 0) {
+            var pct = textScale+"%";
+            if (document.documentElement.style.getPropertyValue("-webkit-text-size-adjust") != pct)
+                DOM_setStyleProperties(document.documentElement,{"-webkit-text-size-adjust": pct});
+        }
+    }
+
+    // public
+    Viewport_setViewportWidth = function(width)
+    {
+        var contentValue = "width = "+width+", user-scalable = no";
+        if (viewportMetaElement.getAttribute("content") != contentValue)
+            DOM_setAttribute(viewportMetaElement,"content",contentValue);
+
+        Selection_update();
+        Cursor_ensureCursorVisible();
+    }
+
+    // public
+    Viewport_setTextScale = function(textScale)
+    {
+        var pct = textScale+"%";
+        if (document.documentElement.style.getPropertyValue("-webkit-text-size-adjust") != pct)
+            DOM_setStyleProperties(document.documentElement,{"-webkit-text-size-adjust": pct});
+
+        Selection_update();
+        Cursor_ensureCursorVisible();
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/check-dom-methods.sh
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/check-dom-methods.sh b/experiments/editorFramework/src/Javascript_Layer_0/check-dom-methods.sh
new file mode 100644
index 0000000..6e17a4e
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/check-dom-methods.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+jsgrep -F '.createElement' | grep -vF '// check-ok'
+jsgrep -F '.createTextNode' | grep -vF '// check-ok'
+jsgrep -F '.createComment' | grep -vF '// check-ok'
+jsgrep -F '.appendChild' | grep -vF '// check-ok'
+jsgrep -F '.insertBefore' | grep -vF '// check-ok'
+jsgrep -F '.removeChild' | grep -vF '// check-ok'
+jsgrep -F '.cloneNode' | grep -vF '// check-ok'
+jsgrep -F '.nodeName' | grep -vE '(dtdsource/|tests/|treevis/)' | grep -vF '// check-ok'
+jsgrep -F '.setAttribute' | grep -vE '(dtdsource/|treevis/|docx/)' | grep -vF '// check-ok'
+jsgrep -F '.removeAttribute' | grep -vE '(dtdsource/|treevis/|docx/)' | grep -vF '// check-ok'
+jsgrep -F '.setProperty' | grep -vE '(dtdsource/|treevis/)' | grep -vF '// check-ok'
+jsgrep -F '.removeProperty' | grep -vE '(dtdsource/|treevis/)' | grep -vF '// check-ok'
+jsgrep -E '\.style\[.* = ' | grep -vE '(treevis/|docx/)' | grep -vF '// check-ok'
+jsgrep -E '\.style\..* = ' | grep -vE '(treevis/|docx/)' | grep -vF '// check-ok'


[25/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/DOM.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/DOM.js b/experiments/editorFramework/src/Javascript_Layer_0/DOM.js
new file mode 100644
index 0000000..b2371bc
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/DOM.js
@@ -0,0 +1,966 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+// Helper functions
+var DOM_assignNodeIds;
+
+// Primitive node creation operations
+var DOM_createElement;
+var DOM_createElementNS;
+var DOM_createTextNode;
+var DOM_createComment;
+var DOM_cloneNode;
+
+// Primitive and high-level node mutation operations
+var DOM_appendChild;
+var DOM_insertBefore;
+var DOM_deleteNode;
+var DOM_setAttribute;
+var DOM_setAttributeNS;
+var DOM_removeAttribute;
+var DOM_removeAttributeNS;
+var DOM_setStyleProperties;
+var DOM_insertCharacters;
+var DOM_moveCharacters;
+var DOM_deleteCharacters;
+var DOM_setNodeValue;
+
+// High-level DOM operations
+var DOM_getAttribute;
+var DOM_getAttributeNS;
+var DOM_getStringAttribute;
+var DOM_getStringAttributeNS;
+var DOM_getStyleProperties;
+var DOM_deleteAllChildren;
+var DOM_shallowCopyElement;
+var DOM_replaceElement;
+var DOM_wrapNode;
+var DOM_wrapSiblings;
+var DOM_mergeWithNextSibling;
+var DOM_nodesMergeable;
+var DOM_replaceCharacters;
+var DOM_addTrackedPosition;
+var DOM_removeTrackedPosition;
+var DOM_removeAdjacentWhitespace;
+var DOM_documentHead;
+var DOM_ensureUniqueIds;
+var DOM_nodeOffset;
+var DOM_maxChildOffset;
+var DOM_ignoreMutationsWhileExecuting;
+var DOM_getIgnoreMutations;
+var DOM_addListener;
+var DOM_removeListener;
+var DOM_Listener;
+
+(function() {
+
+    var nextNodeId = 0;
+    var nodeData = new Object();
+    var ignoreMutations = 0;
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    //                                                                                            //
+    //                                    DOM Helper Functions                                    //
+    //                                                                                            //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+
+    function addUndoAction()
+    {
+        if (window.undoSupported)
+            UndoManager_addAction.apply(null,arrayCopy(arguments));
+    }
+
+    function assignNodeId(node)
+    {
+        if (node._nodeId != null)
+            throw new Error(node+" already has id");
+        node._nodeId = nextNodeId++;
+        node._type = ElementTypes[node.nodeName];
+        return node;
+    }
+
+    function checkNodeId(node)
+    {
+        if (node._nodeId == null)
+            throw new Error(node.nodeName+" lacks _nodeId");
+    }
+
+    // public
+    DOM_assignNodeIds = function(root)
+    {
+        if (root._nodeId != null)
+            throw new Error(root+" already has id");
+        recurse(root);
+        return;
+
+        function recurse(node) {
+            node._nodeId = nextNodeId++;
+            node._type = ElementTypes[node.nodeName];
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    //                                                                                            //
+    //                                  Primitive DOM Operations                                  //
+    //                                                                                            //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+
+    /*
+
+      The following functions are considered "primitive", in that they are the core functions
+      through which all manipulation of the DOM ultimately occurs. All other DOM functions call
+      these, either directly or indirectly, instead of making direct method calls on node objects.
+      These functions are divided into two categories: node creation and mode mutation.
+
+      The creation functions are as follows:
+
+      * createElement(document,elementName)
+      * createElementNS(document,namespaceURI,qualifiedName)
+      * createTextNode(document,data)
+      * createComment(document,data)
+      * cloneNode(original,deep,noIdAttr)
+
+      The purpose of these is to ensure that a unique _nodeId value is assigned to each node object,
+      which is needed for using the NodeSet and NodeMap classes. All nodes in a document must have
+      this set; we use our own functions for this because DOM provides no other way of uniquely
+      identifying nodes in a way that allows them to be stored in a hash table.
+
+      The mutation functions are as follows:
+
+      * insertBeforeInternal(parent,newChild,refChild)
+      * deleteNodeInternal(node,deleteDescendantData)
+      * setAttribute(element,name,value)
+      * setAttributeNS(element,namespaceURI,qualifiedName,value)
+      * setStyleProperties(element,properties)
+      * insertCharacters(textNode,offset,characters)
+      * deleteCharacters(textNode,startOffset,endOffset)
+      * moveCharacters(srcTextNode,srcStartOffset,srcEndOffset,destTextNode,destOffset)
+      * setNodeValue(textNode,value)
+
+      These functions exist to allow us to record undo information. We can't use DOM mutation events
+      for this purpose they're not fully supported in WebKit.
+
+      Every time a mutation operation is performed on a node, we add an action to the undo stack
+      corresponding to the inverse of that operaton, i.e. an action that undoes the operaton. It
+      is absolutely critical that all changes to a DOM node go through these functions, regardless
+      of whether or not the node currently resides in the tree. This ensures that the undo history
+      is able to correctly revert the tree to the same state that it was in at the relevant point
+      in time.
+
+      By routing all DOM modifications through these few functions, virtually all of the other
+      javascript code can be ignorant of the undo manager, provided the only state they change is
+      in the DOM. Parts of the code which maintain their own state about the document, such as the
+      style manager, must implement their own undo-compliant state manipulation logic.
+
+      *** IMPORTANT ***
+
+      Just in case it isn't already clear, you must *never* make direct calls to methods like
+      appendChild() and createElement() on the node objects themselves. Doing so will result in
+      subtle and probably hard-to-find bugs. As far as all javascript code for UX Write is
+      concerned, consider the public functions defined in this file to be the DOM API. You can use
+      check-dom-methods.sh to search for any cases where this rule has been violated.
+
+      */
+
+    // public
+    DOM_createElement = function(document,elementName)
+    {
+        return assignNodeId(document.createElement(elementName)); // check-ok
+    }
+
+    // public
+    DOM_createElementNS = function(document,namespaceURI,qualifiedName)
+    {
+        return assignNodeId(document.createElementNS(namespaceURI,qualifiedName)); // check-ok
+    }
+
+    // public
+    DOM_createTextNode = function(document,data)
+    {
+        return assignNodeId(document.createTextNode(data)); // check-ok
+    }
+
+    // public
+    DOM_createComment = function(document,data)
+    {
+        return assignNodeId(document.createComment(data)); // check-ok
+    }
+
+    // public
+    DOM_cloneNode = function(original,deep,noIdAttr)
+    {
+        var clone = original.cloneNode(deep); // check-ok
+        DOM_assignNodeIds(clone);
+        if (noIdAttr)
+            clone.removeAttribute("id"); // check-ok
+        return clone;
+    }
+
+    function insertBeforeInternal(parent,newChild,refChild)
+    {
+        if (newChild.parentNode == null) {
+            addUndoAction(deleteNodeInternal,newChild)
+        }
+        else {
+            var oldParent = newChild.parentNode;
+            var oldNext = newChild.nextSibling;
+            addUndoAction(insertBeforeInternal,oldParent,newChild,oldNext);
+        }
+
+        parent.insertBefore(newChild,refChild); // check-ok
+    }
+
+    function deleteNodeInternal(node,deleteDescendantData)
+    {
+        checkNodeId(node);
+
+        addUndoAction(insertBeforeInternal,node.parentNode,node,node.nextSibling);
+
+        if (node.parentNode == null)
+            throw new Error("Undo delete "+nodeString(node)+": parent is null");
+        node.parentNode.removeChild(node); // check-ok
+
+        // Delete all data associated with the node. This is not preserved across undo/redo;
+        // currently the only thing we are using this data for is tracked positions, and we
+        // are going to be recording undo information for the selection separately, so this is
+        // not a problem.
+        if (deleteDescendantData)
+            deleteNodeDataRecursive(node);
+        else
+            deleteNodeData(node);
+
+        return;
+
+        function deleteNodeData(current)
+        {
+            delete nodeData[current._nodeId];
+        }
+
+        function deleteNodeDataRecursive(current)
+        {
+            deleteNodeData(current);
+            for (var child = current.firstChild; child != null; child = child.nextSibling)
+                deleteNodeDataRecursive(child);
+        }
+    }
+
+    // public
+    DOM_setAttribute = function(element,name,value)
+    {
+        if (element.hasAttribute(name))
+            addUndoAction(DOM_setAttribute,element,name,element.getAttribute(name));
+        else
+            addUndoAction(DOM_setAttribute,element,name,null);
+
+        if (value == null)
+            element.removeAttribute(name); // check-ok
+        else
+            element.setAttribute(name,value); // check-ok
+    }
+
+    // public
+    DOM_setAttributeNS = function(element,namespaceURI,qualifiedName,value)
+    {
+        var localName = qualifiedName.replace(/^.*:/,"");
+        if (element.hasAttributeNS(namespaceURI,localName)) {
+            var oldValue = element.getAttributeNS(namespaceURI,localName);
+            var oldQName = element.getAttributeNodeNS(namespaceURI,localName).nodeName; // check-ok
+            addUndoAction(DOM_setAttributeNS,element,namespaceURI,oldQName,oldValue)
+        }
+        else {
+            addUndoAction(DOM_setAttributeNS,element,namespaceURI,localName,null);
+        }
+
+        if (value == null)
+            element.removeAttributeNS(namespaceURI,localName); // check-ok
+        else
+            element.setAttributeNS(namespaceURI,qualifiedName,value); // check-ok
+    }
+
+    // public
+    DOM_setStyleProperties = function(element,properties)
+    {
+        if (Object.getOwnPropertyNames(properties).length == 0)
+            return;
+
+        if (element.hasAttribute("style"))
+            addUndoAction(DOM_setAttribute,element,"style",element.getAttribute("style"));
+        else
+            addUndoAction(DOM_setAttribute,element,"style",null);
+
+        for (var name in properties)
+            element.style.setProperty(name,properties[name]); // check-ok
+
+        if (element.getAttribute("style") == "")
+            element.removeAttribute("style"); // check-ok
+    }
+
+    // public
+    DOM_insertCharacters = function(textNode,offset,characters)
+    {
+        if (textNode.nodeType != Node.TEXT_NODE)
+            throw new Error("DOM_insertCharacters called on non-text node");
+        if ((offset < 0) || (offset > textNode.nodeValue.length))
+            throw new Error("DOM_insertCharacters called with invalid offset");
+        trackedPositionsForNode(textNode).forEach(function (position) {
+            if (position.offset > offset)
+                position.offset += characters.length;
+        });
+        textNode.nodeValue = textNode.nodeValue.slice(0,offset) +
+                             characters +
+                             textNode.nodeValue.slice(offset);
+        var startOffset = offset;
+        var endOffset = offset + characters.length;
+        addUndoAction(DOM_deleteCharacters,textNode,startOffset,endOffset);
+    }
+
+    // public
+    DOM_deleteCharacters = function(textNode,startOffset,endOffset)
+    {
+        if (textNode.nodeType != Node.TEXT_NODE)
+            throw new Error("DOM_deleteCharacters called on non-text node "+nodeString(textNode));
+        if (endOffset == null)
+            endOffset = textNode.nodeValue.length;
+        if (endOffset < startOffset)
+            throw new Error("DOM_deleteCharacters called with invalid start/end offset");
+        trackedPositionsForNode(textNode).forEach(function (position) {
+            var deleteCount = endOffset - startOffset;
+            if ((position.offset > startOffset) && (position.offset < endOffset))
+                position.offset = startOffset;
+            else if (position.offset >= endOffset)
+                position.offset -= deleteCount;
+        });
+
+        var removed = textNode.nodeValue.slice(startOffset,endOffset);
+        addUndoAction(DOM_insertCharacters,textNode,startOffset,removed);
+
+        textNode.nodeValue = textNode.nodeValue.slice(0,startOffset) +
+                             textNode.nodeValue.slice(endOffset);
+    }
+
+    // public
+    DOM_moveCharacters = function(srcTextNode,srcStartOffset,srcEndOffset,destTextNode,destOffset,
+                                  excludeStartPos,excludeEndPos)
+    {
+        if (srcTextNode == destTextNode)
+            throw new Error("src and dest text nodes cannot be the same");
+        if (srcStartOffset > srcEndOffset)
+            throw new Error("Invalid src range "+srcStartOffset+" - "+srcEndOffset);
+        if (srcStartOffset < 0)
+            throw new Error("srcStartOffset < 0");
+        if (srcEndOffset > srcTextNode.nodeValue.length)
+            throw new Error("srcEndOffset beyond end of src length");
+        if (destOffset < 0)
+            throw new Error("destOffset < 0");
+        if (destOffset > destTextNode.nodeValue.length)
+            throw new Error("destOffset beyond end of dest length");
+
+        var length = srcEndOffset - srcStartOffset;
+
+        addUndoAction(DOM_moveCharacters,destTextNode,destOffset,destOffset+length,
+                      srcTextNode,srcStartOffset,excludeStartPos,excludeEndPos);
+
+        trackedPositionsForNode(destTextNode).forEach(function (pos) {
+            var startMatch = excludeStartPos ? (pos.offset > destOffset)
+                                             : (pos.offset >= destOffset);
+            if (startMatch)
+                pos.offset += length;
+        });
+        trackedPositionsForNode(srcTextNode).forEach(function (pos) {
+
+            var startMatch = excludeStartPos ? (pos.offset > srcStartOffset)
+                                             : (pos.offset >= srcStartOffset);
+            var endMatch = excludeEndPos ? (pos.offset < srcEndOffset)
+                                         : (pos.offset <= srcEndOffset);
+
+            if (startMatch && endMatch) {
+                pos.node = destTextNode;
+                pos.offset = destOffset + (pos.offset - srcStartOffset);
+            }
+            else if (pos.offset >= srcEndOffset) {
+                pos.offset -= length;
+            }
+        });
+        var extract = srcTextNode.nodeValue.substring(srcStartOffset,srcEndOffset);
+        srcTextNode.nodeValue = srcTextNode.nodeValue.slice(0,srcStartOffset) +
+                                srcTextNode.nodeValue.slice(srcEndOffset);
+        destTextNode.nodeValue = destTextNode.nodeValue.slice(0,destOffset) +
+                                 extract +
+                                 destTextNode.nodeValue.slice(destOffset);
+    }
+
+    // public
+    DOM_setNodeValue = function(textNode,value)
+    {
+        if (textNode.nodeType != Node.TEXT_NODE)
+            throw new Error("DOM_setNodeValue called on non-text node");
+        trackedPositionsForNode(textNode).forEach(function (position) {
+            position.offset = 0;
+        });
+        var oldValue = textNode.nodeValue;
+        addUndoAction(DOM_setNodeValue,textNode,oldValue);
+        textNode.nodeValue = value;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    //                                                                                            //
+    //                                  High-level DOM Operations                                 //
+    //                                                                                            //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+
+    function appendChildInternal(parent,newChild)
+    {
+        insertBeforeInternal(parent,newChild,null);
+    }
+
+    // public
+    DOM_appendChild = function(node,child)
+    {
+        return DOM_insertBefore(node,child,null);
+    }
+
+    // public
+    DOM_insertBefore = function(parent,child,nextSibling)
+    {
+        var newOffset;
+        if (nextSibling != null)
+            newOffset = DOM_nodeOffset(nextSibling);
+        else
+            newOffset = parent.childNodes.length;
+
+        var oldParent = child.parentNode;
+        if (oldParent != null) { // already in tree
+            var oldOffset = DOM_nodeOffset(child);
+
+            if ((oldParent == parent) && (newOffset > oldOffset))
+                newOffset--;
+
+            trackedPositionsForNode(oldParent).forEach(function (position) {
+                if (position.offset > oldOffset) {
+                    position.offset--;
+                }
+                else if (position.offset == oldOffset) {
+                    position.node = parent;
+                    position.offset = newOffset;
+                }
+            });
+        }
+
+        var result = insertBeforeInternal(parent,child,nextSibling);
+        trackedPositionsForNode(parent).forEach(function (position) {
+            if (position.offset > newOffset)
+                position.offset++;
+        });
+        return result;
+    }
+
+    // public
+    DOM_deleteNode = function(node)
+    {
+        if (node.parentNode == null) // already deleted
+            return;
+        adjustPositionsRecursive(node);
+        deleteNodeInternal(node,true);
+
+        function adjustPositionsRecursive(current)
+        {
+            for (var child = current.firstChild; child != null; child = child.nextSibling)
+                adjustPositionsRecursive(child);
+
+            trackedPositionsForNode(current.parentNode).forEach(function (position) {
+                var offset = DOM_nodeOffset(current);
+                if (offset < position.offset) {
+                    position.offset--;
+                }
+            });
+            trackedPositionsForNode(current).forEach(function (position) {
+                var offset = DOM_nodeOffset(current);
+                position.node = current.parentNode;
+                position.offset = offset;
+            });
+        }
+    }
+
+    // public
+    DOM_removeAttribute = function(element,name,value)
+    {
+        DOM_setAttribute(element,name,null);
+    }
+
+    // public
+    DOM_removeAttributeNS = function(element,namespaceURI,localName)
+    {
+        DOM_setAttributeNS(element,namespaceURI,localName,null)
+    }
+
+    // public
+    DOM_getAttribute = function(element,name)
+    {
+        if (element.hasAttribute(name))
+            return element.getAttribute(name);
+        else
+            return null;
+    }
+
+    // public
+    DOM_getAttributeNS = function(element,namespaceURI,localName)
+    {
+        if (element.hasAttributeNS(namespaceURI,localName))
+            return element.getAttributeNS(namespaceURI,localName);
+        else
+            return null;
+    }
+
+    // public
+    DOM_getStringAttribute = function(element,name)
+    {
+        var value = element.getAttribute(name);
+        return (value == null) ? "" : value;
+    }
+
+    // public
+    DOM_getStringAttributeNS = function(element,namespaceURI,localName)
+    {
+        var value = element.getAttributeNS(namespaceURI,localName);
+        return (value == null) ? "" : value;
+    }
+
+    // public
+    DOM_getStyleProperties = function(node)
+    {
+        var properties = new Object();
+        if (node.nodeType == Node.ELEMENT_NODE) {
+            for (var i = 0; i < node.style.length; i++) {
+                var name = node.style[i];
+                var value = node.style.getPropertyValue(name);
+                properties[name] = value;
+            }
+        }
+        return properties;
+    }
+
+    // public
+    DOM_deleteAllChildren = function(parent)
+    {
+        while (parent.firstChild != null)
+            DOM_deleteNode(parent.firstChild);
+    }
+
+    // public
+    DOM_shallowCopyElement = function(element)
+    {
+        return DOM_cloneNode(element,false,true);
+    }
+
+    // public
+    DOM_removeNodeButKeepChildren = function(node)
+    {
+        if (node.parentNode == null)
+            throw new Error("Node "+nodeString(node)+" has no parent");
+        var offset = DOM_nodeOffset(node);
+        var childCount = node.childNodes.length;
+
+        trackedPositionsForNode(node.parentNode).forEach(function (position) {
+            if (position.offset > offset)
+                position.offset += childCount-1;
+        });
+
+        trackedPositionsForNode(node).forEach(function (position) {
+            position.node = node.parentNode;
+            position.offset += offset;
+        });
+
+        var parent = node.parentNode;
+        var nextSibling = node.nextSibling;
+        deleteNodeInternal(node,false);
+
+        while (node.firstChild != null) {
+            var child = node.firstChild;
+            insertBeforeInternal(parent,child,nextSibling);
+        }
+    }
+
+    // public
+    DOM_replaceElement = function(oldElement,newName)
+    {
+        var listeners = listenersForNode(oldElement);
+        var newElement = DOM_createElement(document,newName);
+        for (var i = 0; i < oldElement.attributes.length; i++) {
+            var name = oldElement.attributes[i].nodeName; // check-ok
+            var value = oldElement.getAttribute(name);
+            DOM_setAttribute(newElement,name,value);
+        }
+
+        var positions = arrayCopy(trackedPositionsForNode(oldElement));
+        if (positions != null) {
+            for (var i = 0; i < positions.length; i++) {
+                if (positions[i].node != oldElement)
+                    throw new Error("replaceElement: position with wrong node");
+                positions[i].node = newElement;
+            }
+        }
+
+        var parent = oldElement.parentNode;
+        var nextSibling = oldElement.nextSibling;
+        while (oldElement.firstChild != null)
+            appendChildInternal(newElement,oldElement.firstChild);
+        // Deletion must be done first so if it's a heading, the outline code picks up the change
+        // correctly. Otherwise, there could be two elements in the document with the same id at
+        // the same time.
+        deleteNodeInternal(oldElement,false);
+        insertBeforeInternal(parent,newElement,nextSibling);
+
+        for (var i = 0; i < listeners.length; i++)
+            listeners[i].afterReplaceElement(oldElement,newElement);
+
+        return newElement;
+    }
+
+    // public
+    DOM_wrapNode = function(node,elementName)
+    {
+        return DOM_wrapSiblings(node,node,elementName);
+    }
+
+    DOM_wrapSiblings = function(first,last,elementName)
+    {
+        var parent = first.parentNode;
+        var wrapper = DOM_createElement(document,elementName);
+
+        if (first.parentNode != last.parentNode)
+            throw new Error("first and last are not siblings");
+
+        if (parent != null) {
+            var firstOffset = DOM_nodeOffset(first);
+            var lastOffset = DOM_nodeOffset(last);
+            var nodeCount = lastOffset - firstOffset + 1;
+            trackedPositionsForNode(parent).forEach(function (position) {
+                if ((position.offset >= firstOffset) && (position.offset <= lastOffset+1)) {
+                    position.node = wrapper;
+                    position.offset -= firstOffset;
+                }
+                else if (position.offset > lastOffset+1) {
+                    position.offset -= (nodeCount-1);
+                }
+            });
+
+            insertBeforeInternal(parent,wrapper,first);
+        }
+
+        var end = last.nextSibling;
+        var current = first;
+        while (current != end) {
+            var next = current.nextSibling;
+            appendChildInternal(wrapper,current);
+            current = next;
+        }
+        return wrapper;
+    }
+
+    // public
+    DOM_mergeWithNextSibling = function(current,whiteList)
+    {
+        var parent = current.parentNode;
+        var next = current.nextSibling;
+
+        if ((next == null) || !DOM_nodesMergeable(current,next,whiteList))
+            return;
+
+        var currentLength = DOM_maxChildOffset(current);
+        var nextOffset = DOM_nodeOffset(next);
+
+        var lastChild = null;
+
+        if (current.nodeType == Node.ELEMENT_NODE) {
+            lastChild = current.lastChild;
+            DOM_insertBefore(current,next,null);
+            DOM_removeNodeButKeepChildren(next);
+        }
+        else {
+            DOM_insertCharacters(current,current.nodeValue.length,next.nodeValue);
+
+            trackedPositionsForNode(next).forEach(function (position) {
+                position.node = current;
+                position.offset = position.offset+currentLength;
+            });
+
+            trackedPositionsForNode(current.parentNode).forEach(function (position) {
+                if (position.offset == nextOffset) {
+                    position.node = current;
+                    position.offset = currentLength;
+                }
+            });
+
+            DOM_deleteNode(next);
+        }
+
+        if (lastChild != null)
+            DOM_mergeWithNextSibling(lastChild,whiteList);
+    }
+
+    // public
+    DOM_nodesMergeable = function(a,b,whiteList)
+    {
+        if ((a.nodeType == Node.TEXT_NODE) && (b.nodeType == Node.TEXT_NODE))
+            return true;
+        else if ((a.nodeType == Node.ELEMENT_NODE) && (b.nodeType == Node.ELEMENT_NODE))
+            return elementsMergableTypes(a,b);
+        else
+            return false;
+
+        function elementsMergableTypes(a,b)
+        {
+            if (whiteList["force"] && isParagraphNode(a) && isParagraphNode(b))
+                return true;
+            if ((a._type == b._type) &&
+                whiteList[a._type] &&
+                (a.attributes.length == b.attributes.length)) {
+                for (var i = 0; i < a.attributes.length; i++) {
+                    var attrName = a.attributes[i].nodeName; // check-ok
+                    if (a.getAttribute(attrName) != b.getAttribute(attrName))
+                        return false;
+                }
+                return true;
+            }
+
+            return false;
+        }
+    }
+
+    function getDataForNode(node,create)
+    {
+        if (node._nodeId == null)
+            throw new Error("getDataForNode: node "+node.nodeName+" has no _nodeId property");
+        if ((nodeData[node._nodeId] == null) && create)
+            nodeData[node._nodeId] = new Object();
+        return nodeData[node._nodeId];
+    }
+
+    function trackedPositionsForNode(node)
+    {
+        var data = getDataForNode(node,false);
+        if ((data != null) && (data.trackedPositions != null)) {
+            // Sanity check
+            for (var i = 0; i < data.trackedPositions.length; i++) {
+                if (data.trackedPositions[i].node != node)
+                    throw new Error("Position "+data.trackedPositions[i]+" has wrong node");
+            }
+            return arrayCopy(data.trackedPositions);
+        }
+        else {
+            return [];
+        }
+    }
+
+    function listenersForNode(node)
+    {
+        var data = getDataForNode(node,false);
+        if ((data != null) && (data.listeners != null))
+            return data.listeners;
+        else
+            return [];
+    }
+
+    // public
+    DOM_replaceCharacters = function(textNode,startOffset,endOffset,replacement)
+    {
+        // Note that we do the insertion *before* the deletion so that the position is properly
+        // maintained, and ends up at the end of the replacement (unless it was previously at
+        // startOffset, in which case it will stay the same)
+        DOM_insertCharacters(textNode,startOffset,replacement);
+        DOM_deleteCharacters(textNode,startOffset+replacement.length,endOffset+replacement.length);
+    }
+
+    // public
+    DOM_addTrackedPosition = function(position)
+    {
+        var data = getDataForNode(position.node,true);
+        if (data.trackedPositions == null)
+            data.trackedPositions = new Array();
+        data.trackedPositions.push(position);
+    }
+
+    // public
+    DOM_removeTrackedPosition = function(position)
+    {
+        var data = getDataForNode(position.node,false);
+        if ((data == null) || (data.trackedPositions == null))
+            throw new Error("DOM_removeTrackedPosition: no registered positions for this node "+
+                            "("+position.node.nodeName+")");
+        for (var i = 0; i < data.trackedPositions.length; i++) {
+            if (data.trackedPositions[i] == position) {
+                data.trackedPositions.splice(i,1);
+                return;
+            }
+        }
+        throw new Error("DOM_removeTrackedPosition: position is not registered ("+
+                        data.trackedPositions.length+" others)");
+    }
+
+    // public
+    DOM_removeAdjacentWhitespace = function(node)
+    {
+        while ((node.previousSibling != null) && (isWhitespaceTextNode(node.previousSibling)))
+            DOM_deleteNode(node.previousSibling);
+        while ((node.nextSibling != null) && (isWhitespaceTextNode(node.nextSibling)))
+            DOM_deleteNode(node.nextSibling);
+    }
+
+    // public
+    DOM_documentHead = function(document)
+    {
+        var html = document.documentElement;
+        for (var child = html.firstChild; child != null; child = child.nextSibling) {
+            if (child._type == HTML_HEAD)
+                return child;
+        }
+        throw new Error("Document contains no HEAD element");
+    }
+
+    // public
+    DOM_ensureUniqueIds = function(root)
+    {
+        var ids = new Object();
+        var duplicates = new Array();
+
+        discoverDuplicates(root);
+        renameDuplicates();
+
+        return;
+
+        function discoverDuplicates(node)
+        {
+            if (node.nodeType != Node.ELEMENT_NODE)
+                return;
+
+            var id = node.getAttribute("id");
+            if ((id != null) && (id != "")) {
+                if (ids[id])
+                    duplicates.push(node);
+                else
+                    ids[id] = true;
+            }
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                discoverDuplicates(child);
+        }
+
+        function renameDuplicates()
+        {
+            var nextNumberForPrefix = new Object();
+            for (var i = 0; i < duplicates.length; i++) {
+                var id = duplicates[i].getAttribute("id");
+                var prefix = id.replace(/[0-9]+$/,"");
+                var num = nextNumberForPrefix[prefix] ? nextNumberForPrefix[prefix] : 1;
+
+                var candidate;
+                do {
+                    candidate = prefix + num;
+                    num++;
+                } while (ids[candidate]);
+
+                DOM_setAttribute(duplicates[i],"id",candidate);
+                ids[candidate] = true;
+                nextNumberForPrefix[prefix] = num;
+            }
+        }
+    }
+
+    // public
+    DOM_nodeOffset = function(node,parent)
+    {
+        if ((node == null) && (parent != null))
+            return DOM_maxChildOffset(parent);
+        var offset = 0;
+        for (var n = node.parentNode.firstChild; n != node; n = n.nextSibling)
+            offset++;
+        return offset;
+    }
+
+    // public
+    DOM_maxChildOffset = function(node)
+    {
+        if (node.nodeType == Node.TEXT_NODE)
+            return node.nodeValue.length;
+        else if (node.nodeType == Node.ELEMENT_NODE)
+            return node.childNodes.length;
+        else
+            throw new Error("maxOffset: invalid node type ("+node.nodeType+")");
+    }
+
+    function incIgnoreMutations()
+    {
+        UndoManager_addAction(decIgnoreMutations);
+        ignoreMutations++;
+    }
+
+    function decIgnoreMutations()
+    {
+        UndoManager_addAction(incIgnoreMutations);
+        ignoreMutations--;
+        if (ignoreMutations < 0)
+            throw new Error("ignoreMutations is now negative");
+    }
+
+    // public
+    DOM_ignoreMutationsWhileExecuting = function(fun)
+    {
+        incIgnoreMutations();
+        try {
+            return fun();
+        }
+        finally {
+            decIgnoreMutations();
+        }
+    }
+
+    // public
+    DOM_getIgnoreMutations = function()
+    {
+        return ignoreMutations;
+    }
+
+    // public
+    DOM_addListener = function(node,listener)
+    {
+        var data = getDataForNode(node,true);
+        if (data.listeners == null)
+            data.listeners = [listener];
+        else
+            data.listeners.push(listener);
+    }
+
+    // public
+    DOM_removeListener = function(node,listener)
+    {
+        var list = listenersForNode(node);
+        var index = list.indexOf(listener);
+        if (index >= 0)
+            list.splice(index,1);
+    }
+
+    // public
+    function Listener()
+    {
+    }
+
+    Listener.prototype.afterReplaceElement = function(oldElement,newElement) {}
+
+    DOM_Listener = Listener;
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Editor.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Editor.js b/experiments/editorFramework/src/Javascript_Layer_0/Editor.js
new file mode 100644
index 0000000..50f0d21
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Editor.js
@@ -0,0 +1,113 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Editor_getBackMessages;
+var Editor_debug;
+var Editor_addOutlineItem;
+var Editor_updateOutlineItem;
+var Editor_removeOutlineItem;
+var Editor_outlineUpdated;
+var Editor_setCursor;
+var Editor_setSelectionHandles;
+var Editor_clearSelectionHandlesAndCursor;
+var Editor_setSelectionBounds;
+var Editor_updateAutoCorrect;
+var Editor_error;
+var debug;
+
+(function(){
+
+    var backMessages = new Array();
+
+    function addBackMessage()
+    {
+        backMessages.push(arrayCopy(arguments));
+        return null;
+    }
+
+    Editor_getBackMessages = function()
+    {
+        var result = JSON.stringify(backMessages);
+        backMessages = new Array();
+        return result;
+    };
+
+    Editor_debug = function(str)
+    {
+        addBackMessage("debug",str);
+    };
+
+    Editor_error = function(error,type)
+    {
+        if (type == null)
+            type = "";
+        addBackMessage("error",error.toString(),type);
+    };
+
+    Editor_addOutlineItem = function(itemId,type,title)
+    {
+        addBackMessage("addOutlineItem",itemId,type,title);
+    };
+
+    Editor_updateOutlineItem = function(itemId,title)
+    {
+        addBackMessage("updateOutlineItem",itemId,title);
+    };
+
+    Editor_removeOutlineItem = function(itemId)
+    {
+        addBackMessage("removeOutlineItem",itemId);
+    };
+
+    Editor_outlineUpdated = function()
+    {
+        addBackMessage("outlineUpdated");
+    };
+
+    Editor_setCursor = function(x,y,width,height)
+    {
+        addBackMessage("setCursor",x,y,width,height);
+    };
+
+    Editor_setSelectionHandles = function(x1,y1,height1,x2,y2,height2)
+    {
+        addBackMessage("setSelectionHandles",x1,y1,height1,x2,y2,height2);
+    };
+
+    Editor_setTableSelection = function(x,y,width,height)
+    {
+        addBackMessage("setTableSelection",x,y,width,height);
+    };
+
+    Editor_setSelectionBounds = function(left,top,right,bottom)
+    {
+        addBackMessage("setSelectionBounds",left,top,right,bottom);
+    };
+
+    Editor_clearSelectionHandlesAndCursor = function()
+    {
+        addBackMessage("clearSelectionHandlesAndCursor");
+    };
+
+    Editor_updateAutoCorrect = function()
+    {
+        addBackMessage("updateAutoCorrect");
+    };
+
+    debug = Editor_debug;
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js b/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js
new file mode 100644
index 0000000..06702a2
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/ElementTypes.js
@@ -0,0 +1,344 @@
+// Automatically generated from elements.txt
+ElementTypes = {
+  "#DOCUMENT": 1,
+  "#document": 1,
+  "#TEXT": 2,
+  "#text": 2,
+  "#COMMENT": 3,
+  "#comment": 3,
+  "A": 4,
+  "a": 4,
+  "ABBR": 5,
+  "abbr": 5,
+  "ADDRESS": 6,
+  "address": 6,
+  "AREA": 7,
+  "area": 7,
+  "ARTICLE": 8,
+  "article": 8,
+  "ASIDE": 9,
+  "aside": 9,
+  "AUDIO": 10,
+  "audio": 10,
+  "B": 11,
+  "b": 11,
+  "BASE": 12,
+  "base": 12,
+  "BDI": 13,
+  "bdi": 13,
+  "BDO": 14,
+  "bdo": 14,
+  "BLOCKQUOTE": 15,
+  "blockquote": 15,
+  "BODY": 16,
+  "body": 16,
+  "BR": 17,
+  "br": 17,
+  "BUTTON": 18,
+  "button": 18,
+  "CANVAS": 19,
+  "canvas": 19,
+  "CAPTION": 20,
+  "caption": 20,
+  "CITE": 21,
+  "cite": 21,
+  "CODE": 22,
+  "code": 22,
+  "COL": 23,
+  "col": 23,
+  "COLGROUP": 24,
+  "colgroup": 24,
+  "COMMAND": 25,
+  "command": 25,
+  "DATA": 26,
+  "data": 26,
+  "DATALIST": 27,
+  "datalist": 27,
+  "DD": 28,
+  "dd": 28,
+  "DEL": 29,
+  "del": 29,
+  "DETAILS": 30,
+  "details": 30,
+  "DFN": 31,
+  "dfn": 31,
+  "DIALOG": 32,
+  "dialog": 32,
+  "DIV": 33,
+  "div": 33,
+  "DL": 34,
+  "dl": 34,
+  "DT": 35,
+  "dt": 35,
+  "EM": 36,
+  "em": 36,
+  "EMBED": 37,
+  "embed": 37,
+  "FIELDSET": 38,
+  "fieldset": 38,
+  "FIGCAPTION": 39,
+  "figcaption": 39,
+  "FIGURE": 40,
+  "figure": 40,
+  "FOOTER": 41,
+  "footer": 41,
+  "FORM": 42,
+  "form": 42,
+  "H1": 43,
+  "h1": 43,
+  "H2": 44,
+  "h2": 44,
+  "H3": 45,
+  "h3": 45,
+  "H4": 46,
+  "h4": 46,
+  "H5": 47,
+  "h5": 47,
+  "H6": 48,
+  "h6": 48,
+  "HEAD": 49,
+  "head": 49,
+  "HEADER": 50,
+  "header": 50,
+  "HGROUP": 51,
+  "hgroup": 51,
+  "HR": 52,
+  "hr": 52,
+  "HTML": 53,
+  "html": 53,
+  "I": 54,
+  "i": 54,
+  "IFRAME": 55,
+  "iframe": 55,
+  "IMG": 56,
+  "img": 56,
+  "INPUT": 57,
+  "input": 57,
+  "INS": 58,
+  "ins": 58,
+  "KBD": 59,
+  "kbd": 59,
+  "KEYGEN": 60,
+  "keygen": 60,
+  "LABEL": 61,
+  "label": 61,
+  "LEGEND": 62,
+  "legend": 62,
+  "LI": 63,
+  "li": 63,
+  "LINK": 64,
+  "link": 64,
+  "MAP": 65,
+  "map": 65,
+  "MARK": 66,
+  "mark": 66,
+  "MENU": 67,
+  "menu": 67,
+  "META": 68,
+  "meta": 68,
+  "METER": 69,
+  "meter": 69,
+  "NAV": 70,
+  "nav": 70,
+  "NOSCRIPT": 71,
+  "noscript": 71,
+  "OBJECT": 72,
+  "object": 72,
+  "OL": 73,
+  "ol": 73,
+  "OPTGROUP": 74,
+  "optgroup": 74,
+  "OPTION": 75,
+  "option": 75,
+  "OUTPUT": 76,
+  "output": 76,
+  "P": 77,
+  "p": 77,
+  "PARAM": 78,
+  "param": 78,
+  "PRE": 79,
+  "pre": 79,
+  "PROGRESS": 80,
+  "progress": 80,
+  "Q": 81,
+  "q": 81,
+  "RP": 82,
+  "rp": 82,
+  "RT": 83,
+  "rt": 83,
+  "RUBY": 84,
+  "ruby": 84,
+  "S": 85,
+  "s": 85,
+  "SAMP": 86,
+  "samp": 86,
+  "SCRIPT": 87,
+  "script": 87,
+  "SECTION": 88,
+  "section": 88,
+  "SELECT": 89,
+  "select": 89,
+  "SMALL": 90,
+  "small": 90,
+  "SOURCE": 91,
+  "source": 91,
+  "SPAN": 92,
+  "span": 92,
+  "STRONG": 93,
+  "strong": 93,
+  "STYLE": 94,
+  "style": 94,
+  "SUB": 95,
+  "sub": 95,
+  "SUMMARY": 96,
+  "summary": 96,
+  "SUP": 97,
+  "sup": 97,
+  "TABLE": 98,
+  "table": 98,
+  "TBODY": 99,
+  "tbody": 99,
+  "TD": 100,
+  "td": 100,
+  "TEXTAREA": 101,
+  "textarea": 101,
+  "TFOOT": 102,
+  "tfoot": 102,
+  "TH": 103,
+  "th": 103,
+  "THEAD": 104,
+  "thead": 104,
+  "TIME": 105,
+  "time": 105,
+  "TITLE": 106,
+  "title": 106,
+  "TR": 107,
+  "tr": 107,
+  "TRACK": 108,
+  "track": 108,
+  "U": 109,
+  "u": 109,
+  "UL": 110,
+  "ul": 110,
+  "VAR": 111,
+  "var": 111,
+  "VIDEO": 112,
+  "video": 112,
+  "WBR": 113,
+  "wbr": 113,
+};
+
+HTML_DOCUMENT = 1;
+HTML_TEXT = 2;
+HTML_COMMENT = 3;
+HTML_A = 4;
+HTML_ABBR = 5;
+HTML_ADDRESS = 6;
+HTML_AREA = 7;
+HTML_ARTICLE = 8;
+HTML_ASIDE = 9;
+HTML_AUDIO = 10;
+HTML_B = 11;
+HTML_BASE = 12;
+HTML_BDI = 13;
+HTML_BDO = 14;
+HTML_BLOCKQUOTE = 15;
+HTML_BODY = 16;
+HTML_BR = 17;
+HTML_BUTTON = 18;
+HTML_CANVAS = 19;
+HTML_CAPTION = 20;
+HTML_CITE = 21;
+HTML_CODE = 22;
+HTML_COL = 23;
+HTML_COLGROUP = 24;
+HTML_COMMAND = 25;
+HTML_DATA = 26;
+HTML_DATALIST = 27;
+HTML_DD = 28;
+HTML_DEL = 29;
+HTML_DETAILS = 30;
+HTML_DFN = 31;
+HTML_DIALOG = 32;
+HTML_DIV = 33;
+HTML_DL = 34;
+HTML_DT = 35;
+HTML_EM = 36;
+HTML_EMBED = 37;
+HTML_FIELDSET = 38;
+HTML_FIGCAPTION = 39;
+HTML_FIGURE = 40;
+HTML_FOOTER = 41;
+HTML_FORM = 42;
+HTML_H1 = 43;
+HTML_H2 = 44;
+HTML_H3 = 45;
+HTML_H4 = 46;
+HTML_H5 = 47;
+HTML_H6 = 48;
+HTML_HEAD = 49;
+HTML_HEADER = 50;
+HTML_HGROUP = 51;
+HTML_HR = 52;
+HTML_HTML = 53;
+HTML_I = 54;
+HTML_IFRAME = 55;
+HTML_IMG = 56;
+HTML_INPUT = 57;
+HTML_INS = 58;
+HTML_KBD = 59;
+HTML_KEYGEN = 60;
+HTML_LABEL = 61;
+HTML_LEGEND = 62;
+HTML_LI = 63;
+HTML_LINK = 64;
+HTML_MAP = 65;
+HTML_MARK = 66;
+HTML_MENU = 67;
+HTML_META = 68;
+HTML_METER = 69;
+HTML_NAV = 70;
+HTML_NOSCRIPT = 71;
+HTML_OBJECT = 72;
+HTML_OL = 73;
+HTML_OPTGROUP = 74;
+HTML_OPTION = 75;
+HTML_OUTPUT = 76;
+HTML_P = 77;
+HTML_PARAM = 78;
+HTML_PRE = 79;
+HTML_PROGRESS = 80;
+HTML_Q = 81;
+HTML_RP = 82;
+HTML_RT = 83;
+HTML_RUBY = 84;
+HTML_S = 85;
+HTML_SAMP = 86;
+HTML_SCRIPT = 87;
+HTML_SECTION = 88;
+HTML_SELECT = 89;
+HTML_SMALL = 90;
+HTML_SOURCE = 91;
+HTML_SPAN = 92;
+HTML_STRONG = 93;
+HTML_STYLE = 94;
+HTML_SUB = 95;
+HTML_SUMMARY = 96;
+HTML_SUP = 97;
+HTML_TABLE = 98;
+HTML_TBODY = 99;
+HTML_TD = 100;
+HTML_TEXTAREA = 101;
+HTML_TFOOT = 102;
+HTML_TH = 103;
+HTML_THEAD = 104;
+HTML_TIME = 105;
+HTML_TITLE = 106;
+HTML_TR = 107;
+HTML_TRACK = 108;
+HTML_U = 109;
+HTML_UL = 110;
+HTML_VAR = 111;
+HTML_VIDEO = 112;
+HTML_WBR = 113;
+HTML_COUNT = 114;

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Equations.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Equations.js b/experiments/editorFramework/src/Javascript_Layer_0/Equations.js
new file mode 100644
index 0000000..46bace8
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Equations.js
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Equations_insertEquation;
+
+(function() {
+
+    Equations_insertEquation = function()
+    {
+        var math = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","math");
+        var mrow = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
+        var msup = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","msup");
+        var mi = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
+        var mn = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mn");
+        var mfrac = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mfrac");
+        var mrow1 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
+        var mrow2 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mrow");
+        var mi1 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
+        var mi2 = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mi");
+        var mo = DOM_createElementNS(document,"http://www.w3.org/1998/Math/MathML","mo");
+
+        DOM_appendChild(mi,DOM_createTextNode(document,"x"));
+        DOM_appendChild(mn,DOM_createTextNode(document,"2"));
+        DOM_appendChild(mo,DOM_createTextNode(document,"+"));
+        DOM_appendChild(mi1,DOM_createTextNode(document,"a"));
+        DOM_appendChild(mi2,DOM_createTextNode(document,"b"));
+        DOM_appendChild(mrow1,mi1);
+        DOM_appendChild(mrow2,mi2);
+        DOM_appendChild(mfrac,mrow1);
+        DOM_appendChild(mfrac,mrow2);
+        DOM_appendChild(msup,mi);
+        DOM_appendChild(msup,mn);
+        DOM_appendChild(mrow,msup);
+        DOM_appendChild(mrow,mo);
+        DOM_appendChild(mrow,mfrac);
+        DOM_appendChild(math,mrow);
+
+        Clipboard_pasteNodes([math]);
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Figures.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Figures.js b/experiments/editorFramework/src/Javascript_Layer_0/Figures.js
new file mode 100644
index 0000000..dcda1fc
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Figures.js
@@ -0,0 +1,125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Figures_insertFigure;
+var Figures_getSelectedFigureId;
+var Figures_getProperties;
+var Figures_setProperties;
+var Figures_getGeometry;
+
+(function() {
+
+    // public
+    Figures_insertFigure = function(filename,width,numbered,caption)
+    {
+        UndoManager_newGroup("Insert figure");
+
+        var figure = DOM_createElement(document,"FIGURE");
+        var img = DOM_createElement(document,"IMG");
+        DOM_setAttribute(img,"src",encodeURI(filename));
+        DOM_setStyleProperties(img,{"width": width});
+        DOM_appendChild(figure,img);
+
+        if ((caption != null) && (caption != "")) {
+            var figcaption = DOM_createElement(document,"FIGCAPTION");
+            DOM_appendChild(figcaption,DOM_createTextNode(document,caption));
+            DOM_appendChild(figure,figcaption);
+        }
+
+        Clipboard_pasteNodes([figure]);
+
+        // Now that the figure has been inserted into the DOM tree, the outline code will
+        // have noticed it and added an id attribute, as well as a caption giving the
+        // table number.
+        Outline_setNumbered(figure.getAttribute("id"),numbered);
+
+        // Place the cursor directly after the figure
+        var offset = DOM_nodeOffset(figure);
+        var pos = new Position(figure.parentNode,offset);
+        pos = Position_closestMatchForwards(pos,Position_okForMovement);
+        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+
+        PostponedActions_add(UndoManager_newGroup);
+    }
+
+    Figures_getSelectedFigureId = function()
+    {
+        var element = Cursor_getAdjacentNodeWithType(HTML_FIGURE);
+        return element ? element.getAttribute("id") : null;
+    }
+
+    // public
+    Figures_getProperties = function(itemId)
+    {
+        var figure = document.getElementById(itemId);
+        if (figure == null)
+            return null;
+        var rect = figure.getBoundingClientRect();
+        var result = { width: null, src: null };
+
+        var img = firstDescendantOfType(figure,HTML_IMG);
+        if (img != null) {
+            result.src = decodeURI(img.getAttribute("src"));
+            result.width = img.style.width;
+
+            if ((result.width == null) || (result.width == ""))
+                result.width = DOM_getAttribute(img,"width");
+        }
+        return result;
+    }
+
+    // public
+    Figures_setProperties = function(itemId,width,src)
+    {
+        var figure = document.getElementById(itemId);
+        if (figure == null)
+            return null;
+        var img = firstDescendantOfType(figure,HTML_IMG);
+        if (img != null) {
+            if (src == null)
+                DOM_removeAttribute(img,"src");
+            else
+                DOM_setAttribute(img,"src",encodeURI(src));
+
+            DOM_setStyleProperties(img,{"width": width});
+            if (img.getAttribute("style") == "")
+                DOM_removeAttribute(img,"style");
+            Selection_update();
+        }
+    }
+
+    // public
+    Figures_getGeometry = function(itemId)
+    {
+        var figure = document.getElementById(itemId);
+        if ((figure == null) || (figure.parentNode == null))
+            return null;
+        var img = firstDescendantOfType(figure,HTML_IMG);
+        if (img == null)
+            return null;
+
+        var figcaption = firstChildOfType(figure,HTML_FIGCAPTION);
+
+        var result = new Object();
+        result.contentRect = xywhAbsElementRect(img);
+        result.fullRect = xywhAbsElementRect(figure);
+        result.parentRect = xywhAbsElementRect(figure.parentNode);
+        result.hasCaption = (figcaption != null);
+        return result;
+    }
+
+})();


[18/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/dtd.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/dtd.js b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/dtd.js
new file mode 100644
index 0000000..657cd82
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/dtd.js
@@ -0,0 +1,5562 @@
+// Automatically generated from HTML 4.01 dtd using dtdparse and gen_dtd_data.html
+// See http://nwalsh.com/perl/dtdparse/
+
+var ALLOWED_CHILDREN = {
+    "S": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "INPUT": {
+    },
+    "ACRONYM": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "SPAN": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "FIELDSET": {
+        "LEGEND": true,
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "H3": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "OPTION": {
+    },
+    "OPTGROUP": {
+        "OPTION": true,
+    },
+    "DEL": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "SUB": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "META": {
+    },
+    "SUP": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "FONT": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "HR": {
+    },
+    "ISINDEX": {
+    },
+    "TITLE": {
+    },
+    "BODY": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+        "INS": true,
+        "DEL": true,
+    },
+    "NOSCRIPT": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "BASE": {
+    },
+    "EM": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "COL": {
+    },
+    "TABLE": {
+        "CAPTION": true,
+        "COL": true,
+        "COLGROUP": true,
+        "THEAD": true,
+        "TFOOT": true,
+        "TBODY": true,
+    },
+    "DIR": {
+        "LI": true,
+    },
+    "BUTTON": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "HR": true,
+        "TABLE": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+    },
+    "HEAD": {
+        "TITLE": true,
+        "ISINDEX": true,
+        "BASE": true,
+        "SCRIPT": true,
+        "STYLE": true,
+        "META": true,
+        "LINK": true,
+        "OBJECT": true,
+    },
+    "CAPTION": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "Q": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "TR": {
+        "TH": true,
+        "TD": true,
+    },
+    "OL": {
+        "LI": true,
+    },
+    "TBODY": {
+        "TR": true,
+    },
+    "IFRAME": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "LEGEND": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "P": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "CODE": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "DD": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "KBD": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "AREA": {
+    },
+    "H4": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "TH": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "STYLE": {
+    },
+    "INS": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "H6": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "CITE": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "BIG": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "ABBR": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "UL": {
+        "LI": true,
+    },
+    "IMG": {
+    },
+    "DL": {
+        "DT": true,
+        "DD": true,
+    },
+    "H5": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "SAMP": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "MAP": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "AREA": true,
+    },
+    "TFOOT": {
+        "TR": true,
+    },
+    "DFN": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "H1": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "SCRIPT": {
+    },
+    "LINK": {
+    },
+    "DIV": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "H2": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "B": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "ADDRESS": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+        "P": true,
+    },
+    "LI": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "SMALL": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "COLGROUP": {
+        "COL": true,
+    },
+    "VAR": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "THEAD": {
+        "TR": true,
+    },
+    "TEXTAREA": {
+    },
+    "I": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "NOFRAMES": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "SELECT": {
+        "OPTGROUP": true,
+        "OPTION": true,
+    },
+    "STRIKE": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "PARAM": {
+    },
+    "U": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "LABEL": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "BUTTON": true,
+    },
+    "OBJECT": {
+        "PARAM": true,
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "BLOCKQUOTE": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "MENU": {
+        "LI": true,
+    },
+    "DT": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "HTML": {
+        "HEAD": true,
+        "BODY": true,
+    },
+    "A": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "BDO": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "PRE": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "BR": {
+    },
+    "BASEFONT": {
+    },
+    "TT": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "STRONG": {
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "TD": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "APPLET": {
+        "PARAM": true,
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "FORM": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+    "CENTER": {
+        "P": true,
+        "H1": true,
+        "H2": true,
+        "H3": true,
+        "H4": true,
+        "H5": true,
+        "H6": true,
+        "UL": true,
+        "OL": true,
+        "DIR": true,
+        "MENU": true,
+        "PRE": true,
+        "DL": true,
+        "DIV": true,
+        "CENTER": true,
+        "NOSCRIPT": true,
+        "NOFRAMES": true,
+        "BLOCKQUOTE": true,
+        "FORM": true,
+        "ISINDEX": true,
+        "HR": true,
+        "TABLE": true,
+        "FIELDSET": true,
+        "ADDRESS": true,
+        "TT": true,
+        "I": true,
+        "B": true,
+        "U": true,
+        "S": true,
+        "STRIKE": true,
+        "BIG": true,
+        "SMALL": true,
+        "EM": true,
+        "STRONG": true,
+        "DFN": true,
+        "CODE": true,
+        "SAMP": true,
+        "KBD": true,
+        "VAR": true,
+        "CITE": true,
+        "ABBR": true,
+        "ACRONYM": true,
+        "A": true,
+        "IMG": true,
+        "APPLET": true,
+        "OBJECT": true,
+        "FONT": true,
+        "BASEFONT": true,
+        "BR": true,
+        "SCRIPT": true,
+        "MAP": true,
+        "Q": true,
+        "SUB": true,
+        "SUP": true,
+        "SPAN": true,
+        "BDO": true,
+        "IFRAME": true,
+        "INPUT": true,
+        "SELECT": true,
+        "TEXTAREA": true,
+        "LABEL": true,
+        "BUTTON": true,
+    },
+};
+
+var ALLOWED_PARENTS = {
+    "TT": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "I": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "B": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "U": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "S": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "STRIKE": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "BIG": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "SMALL": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "EM": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "STRONG": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "DFN": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "CODE": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "SAMP": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "KBD": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "VAR": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "CITE": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "ABBR": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "ACRONYM": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "A": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "BDO": true,
+        "PRE": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "IMG": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+    },
+    "APPLET": {
+        "S": true,
+        "ACRONYM": true,
+        "SPAN": true,
+        "FIELDSET": true,
+        "H3": true,
+        "DEL": true,
+        "SUB": true,
+        "SUP": true,
+        "FONT": true,
+        "BODY": true,
+        "NOSCRIPT": true,
+        "EM": true,
+        "BUTTON": true,
+        "CAPTION": true,
+        "Q": true,
+        "IFRAME": true,
+        "LEGEND": true,
+        "P": true,
+        "CODE": true,
+        "DD": true,
+        "KBD": true,
+        "H4": true,
+        "TH": true,
+        "INS": true,
+        "H6": true,
+        "CITE": true,
+        "BIG": true,
+        "ABBR": true,
+        "H5": true,
+        "SAMP": true,
+        "DFN": true,
+        "H1": true,
+        "DIV": true,
+        "H2": true,
+        "B": true,
+        "ADDRESS": true,
+        "LI": true,
+        "SMALL": true,
+        "VAR": true,
+        "I": true,
+        "NOFRAMES": true,
+        "STRIKE": true,
+        "U": true,
+        "LABEL": true,
+        "OBJECT": true,
+        "BLOCKQUOTE": true,
+        "DT": true,
+        "A": true,
+        "BDO": true,
+        "TT": true,
+        "STRONG": true,
+        "TD": true,
+        "APPLET": true,
+        "FORM": true,
+        "CENTER": true,
+ 

<TRUNCATED>


[23/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Lists.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Lists.js b/experiments/editorFramework/src/Javascript_Layer_0/Lists.js
new file mode 100644
index 0000000..a3a9772
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Lists.js
@@ -0,0 +1,553 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Lists_increaseIndent;
+var Lists_decreaseIndent;
+var Lists_clearList;
+var Lists_setUnorderedList;
+var Lists_setOrderedList;
+
+(function() {
+
+    // private
+    function findLIElements(range)
+    {
+        var listItems = new Array();
+
+        var node = range.start.node;
+        while (node != null) {
+
+            addListItems(listItems,node);
+
+            if (node == range.end.node)
+                break;
+
+            node = nextNode(node);
+        }
+        return listItems;
+
+        function addListItems(array,node)
+        {
+            if (node == null)
+                return;
+
+            if (node._type == HTML_LI) {
+                if (!arrayContains(array,node))
+                    array.push(node);
+                return;
+            }
+
+            if (!isWhitespaceTextNode(node))
+                addListItems(array,node.parentNode);
+        }
+    }
+
+    // public
+    Lists_increaseIndent = function()
+    {
+        Selection_preferElementPositions();
+        Selection_preserveWhileExecuting(function() {
+            var range = Selection_get();
+            if (range == null)
+                return null;
+
+            // Determine the set of LI nodes that are part of the selection
+            // Note that these could be spread out all over the place, e.g. in different lists,
+            // some in table cells etc
+            var listItems = findLIElements(range);
+
+            // For each LI node that is not the first in the list, move it to the child list of
+            // its previous sibling (creating the child list if necessary)
+
+            for (var i = 0; i < listItems.length; i++) {
+                var li = listItems[i];
+                var prevLi = li.previousSibling;
+                while ((prevLi != null) && (prevLi._type != HTML_LI))
+                    prevLi = prevLi.previousSibling;
+                // We can only increase the indentation of the current list item C if there is
+                // another list item P immediately preceding C. In this case, C becomes a child of
+                // another list L, where L is inside P. L may already exist, or we may need to
+                // create it.
+                if (prevLi != null) {
+                    var prevList = lastDescendentList(prevLi);
+                    var childList = firstDescendentList(li);
+                    var childListContainer = null;
+                    if (childList != null) {
+                        // childList may be contained inside one or more wrapper elements, in which
+                        // case we set childListContainer to point to the wrapper element that is a
+                        // child of li. Otherwise childListContainer will just be childList.
+                        childListContainer = childList;
+                        while (childListContainer.parentNode != li)
+                            childListContainer = childListContainer.parentNode;
+                    }
+
+                    if (prevList != null) {
+                        DOM_appendChild(prevList,li);
+                        if (childList != null) {
+                            while (childList.firstChild != null)
+                                DOM_appendChild(prevList,childList.firstChild);
+                            DOM_deleteNode(childListContainer);
+                            // alert("Case 1: prevList and childList");
+                        }
+                        else {
+                            // alert("Case 2: prevList and no childList");
+                        }
+                    }
+                    else {
+                        var newList;
+                        if (childList != null) {
+                            // alert("Case 3: no prevList but childList");
+                            newList = childList;
+                            DOM_appendChild(prevLi,childListContainer);
+                        }
+                        else {
+                            // alert("Case 4: no prevList and no childList");
+                            if (li.parentNode._type == HTML_UL)
+                                newList = DOM_createElement(document,"UL");
+                            else
+                                newList = DOM_createElement(document,"OL");
+                            DOM_appendChild(prevLi,newList);
+                        }
+                        DOM_insertBefore(newList,li,newList.firstChild);
+                    }
+                }
+            }
+        });
+
+        function firstDescendentList(node)
+        {
+            while (true) {
+                var node = firstChildElement(node);
+                if (node == null)
+                    return null;
+                switch (node._type) {
+                case HTML_UL:
+                case HTML_OL:
+                    return node;
+                }
+            }
+        }
+
+        function lastDescendentList(node)
+        {
+            while (true) {
+                var node = lastChildElement(node);
+                if (node == null)
+                    return null;
+                switch (node._type) {
+                case HTML_UL:
+                case HTML_OL:
+                    return node;
+                }
+            }
+        }
+    }
+
+    // public
+    Lists_decreaseIndent = function()
+    {
+        Selection_preferElementPositions();
+        Selection_preserveWhileExecuting(function() {
+            var range = Selection_get();
+            if (range == null)
+                return null;
+
+            // Determine the set of LI nodes that are part of the selection
+            // Note that these could be spread out all over the place, e.g. in different lists,
+            // some in table cells etc
+            var listItems = findLIElements(range);
+
+            // Remove from consideration any list items that have an ancestor that is going to
+            // be moved
+            var i = 0;
+            var changed;
+            while (i < listItems.length) {
+                var node = listItems[i];
+
+                var ancestorToBeRemoved = false;
+                for (var ancestor = node.parentNode;
+                     ancestor != null;
+                     ancestor = ancestor.parentNode) {
+                    if (arrayContains(listItems,ancestor))
+                        ancestorToBeRemoved = true;
+                }
+
+                if (ancestorToBeRemoved)
+                    listItems.splice(i,1);
+                else
+                    i++;
+            }
+
+            function haveContentAfter(node)
+            {
+                for (node = node.nextSibling; node != null; node = node.nextSibling) {
+                    if (nodeHasContent(node))
+                        return true;
+                }
+                return false;
+            }
+
+            // For LI nodes that are in a top-level list, change them to regular paragraphs
+            // For LI nodes that are part of a nested list, move them to the parent (this requires
+            // splitting the child list in two)
+            for (var i = 0; i < listItems.length; i++) {
+                var liNode = listItems[i];
+                var listNode = liNode.parentNode;
+                var containerChild = findContainerChild(listNode);
+
+                if (haveContentAfter(liNode)) {
+                    var secondHalf;
+                    if (listNode._type == HTML_UL)
+                        secondHalf = DOM_createElement(document,"UL");
+                    else
+                        secondHalf = DOM_createElement(document,"OL");
+
+                    DOM_appendChild(liNode,secondHalf);
+
+                    var following = liNode.nextSibling;
+                    while (following != null) {
+                        var next = following.nextSibling;
+                        DOM_appendChild(secondHalf,following);
+                        following = next;
+                    }
+                }
+
+                DOM_insertBefore(containerChild.parentNode,liNode,containerChild.nextSibling);
+                if (!isListNode(liNode.parentNode)) {
+                    Hierarchy_avoidInlineChildren(liNode);
+                    DOM_removeNodeButKeepChildren(liNode);
+                }
+
+                if (!nodeHasContent(listNode))
+                    DOM_deleteNode(listNode);
+            }
+        });
+
+        function findContainerChild(node)
+        {
+            while (node.parentNode != null) {
+                if (isContainerNode(node.parentNode) && (node.parentNode._type != HTML_LI))
+                    return node;
+                node = node.parentNode;
+            }
+        }
+    }
+
+    // private
+    function getListOperationNodes(range)
+    {
+        var detail = Range_detail(range);
+        var dca = detail.commonAncestor;
+        var ds = detail.startAncestor;
+        var de = detail.endAncestor;
+
+        while (isInlineNode(dca)) {
+            ds = dca;
+            de = dca;
+            dca = dca.parentNode;
+        }
+
+        var nodes = new Array();
+        var nodeSet = new NodeSet();
+
+        if (dca._type == HTML_LI)
+            return [dca];
+
+        // If, after moving up the tree until dca is a container node, a single node is selected,
+        // check if it is wholly contained within a single list item. If so, select just that
+        // list item.
+        var isStartLI = ((ds != null) && (ds._type == HTML_LI));
+        var isEndLI = ((de != null) && (de._type == HTML_LI));
+        if (!isStartLI && !isEndLI) {
+            for (var ancestor = dca; ancestor.parentNode != null; ancestor = ancestor.parentNode) {
+                if (ancestor.parentNode._type == HTML_LI) {
+                    var firstElement = true;
+
+                    for (var p = ancestor.previousSibling; p != null; p = p.previousSibling) {
+                        if (p.nodeType == Node.ELEMENT_NODE) {
+                            firstElement = false;
+                            break;
+                        }
+                    }
+
+                    if (firstElement)
+                        return [ancestor.parentNode];
+                }
+            }
+        }
+
+        var end = (de == null) ? null : de.nextSibling;
+
+        for (var child = ds; child != end; child = child.nextSibling) {
+            switch (child._type) {
+            case HTML_UL:
+            case HTML_OL:
+                for (var gc = child.firstChild; gc != null; gc = gc.nextSibling) {
+                    if (!isWhitespaceTextNode(gc))
+                        addNode(gc);
+                }
+                break;
+            default:
+                if ((child._type == HTML_DIV) &&
+                     child.getAttribute("class") == Keys.SELECTION_HIGHLIGHT) {
+                    // skip
+                }
+                else if (!isWhitespaceTextNode(child)) {
+                    addNode(child);
+                }
+                break;
+            }
+        }
+        if ((nodes.length == 0) && isParagraphNode(dca))
+            nodes.push(dca);
+        return nodes;
+
+        function addNode(node)
+        {
+            while (isInlineNode(node) && node.parentNode != document.body)
+                node = node.parentNode;
+            if (!nodeSet.contains(node)) {
+                nodeSet.add(node);
+                nodes.push(node);
+            }
+        }
+    }
+
+    // public
+    Lists_clearList = function()
+    {
+        Selection_preferElementPositions();
+        Selection_preserveWhileExecuting(function() {
+            var range = Selection_get();
+            if (range == null)
+                return;
+            Range_ensureInlineNodesInParagraph(range);
+
+            var nodes = getListOperationNodes(range);
+
+            for (var i = 0; i < nodes.length; i++) {
+                var node = nodes[i];
+                if (node._type == HTML_LI) {
+                    var li = node;
+                    var list = li.parentNode;
+                    var insertionPoint = null;
+
+                    DOM_removeAdjacentWhitespace(li);
+
+                    if (li.previousSibling == null) {
+                        insertionPoint = list;
+                    }
+                    else if (li.nextSibling == null) {
+                        insertionPoint = list.nextSibling;
+                    }
+                    else {
+                        var secondList = DOM_shallowCopyElement(list);
+                        DOM_insertBefore(list.parentNode,secondList,list.nextSibling);
+                        while (li.nextSibling != null) {
+                            DOM_appendChild(secondList,li.nextSibling);
+                            DOM_removeAdjacentWhitespace(li);
+                        }
+
+                        insertionPoint = secondList;
+                    }
+
+                    var parent = null;
+                    var child = li.firstChild;
+                    while (child != null) {
+                        var next = child.nextSibling;
+                        if (isInlineNode(child) && !isWhitespaceTextNode(child)) {
+                            child = Hierarchy_wrapInlineNodesInParagraph(child);
+                            next = child.nextSibling;
+                        }
+                        child = next;
+                    }
+                    DOM_insertBefore(list.parentNode,li,insertionPoint);
+                    DOM_removeNodeButKeepChildren(li);
+
+                    if (list.firstChild == null)
+                        DOM_deleteNode(list);
+                }
+            }
+        });
+
+        var range = Selection_get();
+        if (range == null)
+            return;
+        if (Range_isEmpty(range) &&
+            (range.start.node.nodeType == Node.ELEMENT_NODE) &&
+            (isContainerNode(range.start.node))) {
+
+            var p = DOM_createElement(document,"P");
+
+            var next = range.start.node.childNodes[range.start.offset+1];
+            DOM_insertBefore(range.start.node,p,next);
+
+            Cursor_updateBRAtEndOfParagraph(p);
+            Selection_set(p,0,p,0);
+        }
+    }
+
+    // private
+    function setList(type)
+    {
+        var range = Selection_get();
+        if (range == null)
+            return;
+
+        var nodes = getListOperationNodes(range);
+
+        if (nodes.length == 0) {
+            var text;
+            if (range.start.node.nodeType == Node.TEXT_NODE) {
+                text = range.start.node;
+            }
+            else if (range.start.node.nodeType == Node.ELEMENT_NODE) {
+                text = DOM_createTextNode(document,"");
+                DOM_insertBefore(range.start.node,
+                                 text,
+                                 range.start.node[range.start.offset+1]);
+            }
+            nodes = [text];
+
+            var offset = DOM_nodeOffset(text);
+            Selection_set(text,0,text,0);
+            range = Selection_get();
+        }
+
+        Range_trackWhileExecuting(range,function () {
+            // Set list to UL or OL
+
+            for (var i = 0; i < nodes.length; i++) {
+                var node = nodes[i];
+                var next;
+                var prev;
+                var li = null;
+                var oldList = null;
+                var listInsertionPoint;
+
+                if ((node._type == HTML_LI) && (node.parentNode._type == type)) {
+                    // Already in the correct type of list; don't need to do anything
+                    continue;
+                }
+
+                if (node._type == HTML_LI) {
+                    li = node;
+                    var list = li.parentNode;
+
+                    DOM_removeAdjacentWhitespace(list);
+                    prev = list.previousSibling;
+                    next = list.nextSibling;
+
+
+                    DOM_removeAdjacentWhitespace(li);
+
+                    if (li.previousSibling == null) {
+                        listInsertionPoint = list;
+                        next = null;
+                    }
+                    else if (li.nextSibling == null) {
+                        listInsertionPoint = list.nextSibling;
+                        prev = null;
+                    }
+                    else {
+                        var secondList = DOM_shallowCopyElement(list);
+                        DOM_insertBefore(list.parentNode,secondList,list.nextSibling);
+                        while (li.nextSibling != null) {
+                            DOM_insertBefore(secondList,li.nextSibling,null);
+                            DOM_removeAdjacentWhitespace(li);
+                        }
+
+                        listInsertionPoint = secondList;
+
+                        prev = null;
+                        next = null;
+                    }
+
+                    node = list;
+                    oldList = list;
+                }
+                else {
+                    DOM_removeAdjacentWhitespace(node);
+                    prev = node.previousSibling;
+                    next = node.nextSibling;
+                    listInsertionPoint = node;
+                }
+
+                var list;
+                var itemInsertionPoint;
+
+                if ((prev != null) && (prev._type == type)) {
+                    list = prev;
+                    itemInsertionPoint = null;
+                }
+                else if ((next != null) && (next._type == type)) {
+                    list = next;
+                    itemInsertionPoint = list.firstChild;
+                }
+                else {
+                    if (type == HTML_UL)
+                        list = DOM_createElement(document,"UL");
+                    else
+                        list = DOM_createElement(document,"OL");
+                    DOM_insertBefore(node.parentNode,list,listInsertionPoint);
+                    itemInsertionPoint = null;
+                }
+
+                if (li != null) {
+                    DOM_insertBefore(list,li,itemInsertionPoint);
+                }
+                else {
+                    var li = DOM_createElement(document,"LI");
+                    DOM_insertBefore(list,li,itemInsertionPoint);
+                    DOM_insertBefore(li,node,null);
+                }
+
+
+                if ((oldList != null) && (oldList.firstChild == null))
+                    DOM_deleteNode(oldList);
+
+                // Merge with adjacent list
+                DOM_removeAdjacentWhitespace(list);
+                if ((list.nextSibling != null) && (list.nextSibling._type == type)) {
+                    var followingList = list.nextSibling;
+                    while (followingList.firstChild != null) {
+                        if (isWhitespaceTextNode(followingList.firstChild))
+                            DOM_deleteNode(followingList.firstChild);
+                        else
+                            DOM_insertBefore(list,followingList.firstChild,null);
+                    }
+                    DOM_deleteNode(followingList);
+                }
+            }
+        });
+        Range_ensureValidHierarchy(range);
+        Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
+    }
+
+    // public
+    Lists_setUnorderedList = function()
+    {
+        setList(HTML_UL);
+    }
+
+    // public
+    Lists_setOrderedList = function()
+    {
+        setList(HTML_OL);
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Main.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Main.js b/experiments/editorFramework/src/Javascript_Layer_0/Main.js
new file mode 100644
index 0000000..f123423
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Main.js
@@ -0,0 +1,393 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Main_getLanguage;
+var Main_setLanguage;
+var Main_setGenerator;
+var Main_isEmptyDocument;
+var Main_prepareForSave;
+var Main_getHTML;
+var Main_getErrorReportingInfo;
+var Main_removeUnsupportedInput;
+var Main_removeSpecial;
+var Main_execute;
+var Main_init;
+
+var Main_clientRectsBug;
+
+(function() {
+
+    // public
+    Main_getLanguage = function()
+    {
+        var lang = document.documentElement.getAttribute("lang");
+        if (lang != null)
+            lang = lang.replace(/-/g,"_");
+        return lang;
+    }
+
+    // public
+    Main_setLanguage = function(lang)
+    {
+        if ((lang == null) || (lang == "")) {
+            DOM_removeAttribute(document.documentElement,"lang");
+        }
+        else {
+            lang = lang.replace(/_/g,"-");
+            DOM_setAttribute(document.documentElement,"lang",lang);
+        }
+    }
+
+    // public
+    Main_removeUnsupportedInput = function()
+    {
+        recurse(document.documentElement);
+
+        function recurse(node)
+        {
+            // Delete comments and processing instructions
+            if ((node.nodeType != Node.TEXT_NODE) &&
+                (node.nodeType != Node.ELEMENT_NODE)) {
+                DOM_deleteNode(node);
+            }
+            else {
+                var next;
+                for (var child = node.firstChild; child != null; child = next) {
+                    next = child.nextSibling;
+                    recurse(child);
+                }
+            }
+        }
+    }
+
+    // private
+    function addMetaCharset()
+    {
+        var head = DOM_documentHead(document);
+        var next;
+        for (var child = head.firstChild; child != null; child = next) {
+            next = child.nextSibling;
+            if ((child._type == HTML_META) && (child.hasAttribute("charset"))) {
+                DOM_deleteNode(child);
+            }
+            else if ((child._type == HTML_META) && child.hasAttribute("http-equiv") &&
+                     (child.getAttribute("http-equiv").toLowerCase() == "content-type")) {
+                DOM_deleteNode(child);
+            }
+        }
+
+        var meta = DOM_createElement(document,"META");
+        DOM_setAttribute(meta,"charset","utf-8");
+        DOM_insertBefore(head,meta,head.firstChild);
+    }
+
+    // public
+    Main_setGenerator = function(generator)
+    {
+        return UndoManager_disableWhileExecuting(function() {
+            var head = DOM_documentHead(document);
+            for (var child = head.firstChild; child != null; child = child.nextSibling) {
+                if ((child._type == HTML_META) &&
+                    child.hasAttribute("name") &&
+                    (child.getAttribute("name").toLowerCase() == "generator")) {
+                    var origGenerator = DOM_getAttribute(child,"content");
+                    DOM_setAttribute(child,"content",generator);
+
+                    if (origGenerator == null)
+                        return "";
+                    else
+                        return origGenerator;
+                }
+            }
+
+            var meta = DOM_createElement(document,"META");
+            DOM_setAttribute(meta,"name","generator");
+            DOM_setAttribute(meta,"content",generator);
+            DOM_insertBefore(head,meta,head.firstChild);
+
+            return "";
+        });
+    }
+
+    // public
+    Main_isEmptyDocument = function()
+    {
+        return !nodeHasContent(document.body);
+    }
+
+    // public
+    Main_prepareForSave = function()
+    {
+        // Force any end-of-group actions to be performed
+        UndoManager_newGroup();
+        return true;
+    }
+
+    // public
+    Main_getHTML = function()
+    {
+        return document.documentElement.outerHTML;
+    }
+
+    // public
+    Main_getErrorReportingInfo = function()
+    {
+        if (document.documentElement == null)
+            return "(document.documentElement is null)";
+        try {
+            var html = htmlWithSelection();
+            cleanse(html);
+            return html.outerHTML;
+        }
+        catch (e) {
+            try {
+                var html = DOM_cloneNode(document.documentElement,true);
+                cleanse(html);
+                return html.outerHTML+"\n[Error getting selection: "+e+"]";
+            }
+            catch (e2) {
+                return "[Error getting HTML: "+e2+"]";
+            }
+        }
+
+        function cleanse(node)
+        {
+            switch (node._type) {
+            case HTML_TEXT:
+            case HTML_COMMENT:
+                DOM_setNodeValue(node,cleanseString(node.nodeValue));
+                break;
+            case HTML_STYLE:
+            case HTML_SCRIPT:
+                return;
+            default:
+                if (node.nodeType == Node.ELEMENT_NODE) {
+                    cleanseAttribute(node,"original");
+                    if (node.hasAttribute("href") && !node.getAttribute("href").match(/^#/))
+                        cleanseAttribute(node,"href");
+                    for (var child = node.firstChild; child != null; child = child.nextSibling)
+                        cleanse(child);
+                }
+                break;
+            }
+        }
+
+        function cleanseAttribute(node,name)
+        {
+            if (node.hasAttribute(name)) {
+                var value = node.getAttribute(name);
+                value = cleanseString(value);
+                DOM_setAttribute(node,name,value);
+            }
+        }
+
+        function cleanseString(str)
+        {
+            return str.replace(/[^\s\.\@\^]/g,"X");
+        }
+
+        function htmlWithSelection()
+        {
+            var selectionRange = Selection_get();
+            if (selectionRange != null) {
+                selectionRange = Range_forwards(selectionRange);
+                var startSave = new Object();
+                var endSave = new Object();
+
+                var html = null;
+
+                Range_trackWhileExecuting(selectionRange,function() {
+                    // We use the strings @@^^ and ^^@@ to represent the selection
+                    // start and end, respectively. The reason for this is that after we have
+                    // cloned the tree, all text will be removed. We keeping the @ and ^
+                    // characters so we have some way to identifiy the selection markers;
+                    // leaving these in is not going to reveal any confidential information.
+
+                    addPositionMarker(selectionRange.end,"^^@@",endSave);
+                    addPositionMarker(selectionRange.start,"@@^^",startSave);
+
+                    html = DOM_cloneNode(document.documentElement,true);
+
+                    removePositionMarker(selectionRange.start,startSave);
+                    removePositionMarker(selectionRange.end,endSave);
+                });
+
+                return html;
+            }
+            else {
+                return DOM_cloneNode(document.documentElement,true);
+            }
+        }
+
+        function addPositionMarker(pos,name,save)
+        {
+            var node = pos.node;
+            var offset = pos.offset;
+            if (node.nodeType == Node.ELEMENT_NODE) {
+                save.tempNode = DOM_createTextNode(document,name);
+                DOM_insertBefore(node,save.tempNode,node.childNodes[offset]);
+            }
+            else if (node.nodeType == Node.TEXT_NODE) {
+                save.originalNodeValue = node.nodeValue;
+                node.nodeValue = node.nodeValue.slice(0,offset) + name + node.nodeValue.slice(offset);
+            }
+        }
+
+        function removePositionMarker(pos,save)
+        {
+            var node = pos.node;
+            var offset = pos.offset;
+            if (pos.node.nodeType == Node.ELEMENT_NODE) {
+                DOM_deleteNode(save.tempNode);
+            }
+            else if (pos.node.nodeType == Node.TEXT_NODE) {
+                node.nodeValue = save.originalNodeValue;
+            }
+        }
+    }
+
+    // public
+    Main_removeSpecial = function(node)
+    {
+        // We process the children first, so that if there are any nested removable elements (e.g.
+        // a selection span inside of an autocorrect span), all levels of nesting are taken care of
+        var next;
+        for (var child = node.firstChild; child != null; child = next) {
+            next = child.nextSibling;
+            Main_removeSpecial(child);
+        }
+
+        var cssClass = null;
+        if ((node.nodeType == Node.ELEMENT_NODE) && node.hasAttribute("class"))
+            cssClass = node.getAttribute("class");
+
+        if ((cssClass == Keys.HEADING_NUMBER) ||
+            (cssClass == Keys.FIGURE_NUMBER) ||
+            (cssClass == Keys.TABLE_NUMBER) ||
+            (cssClass == Keys.AUTOCORRECT_CLASS) ||
+            (cssClass == Keys.SELECTION_CLASS) ||
+            (cssClass == Keys.SELECTION_HIGHLIGHT)) {
+            DOM_removeNodeButKeepChildren(node);
+        }
+        else if ((node._type == HTML_META) &&
+                 node.hasAttribute("name") &&
+                 (node.getAttribute("name").toLowerCase() == "viewport")) {
+            DOM_deleteNode(node);
+        }
+        else if (node._type == HTML_LINK) {
+            if ((node.getAttribute("rel") == "stylesheet") &&
+                (node.getAttribute("href") == Styles_getBuiltinCSSURL())) {
+                DOM_deleteNode(node);
+            }
+        }
+    }
+
+    function simplifyStackString(e)
+    {
+        if (e.stack == null)
+            return "";
+        var lines = e.stack.toString().split(/\n/);
+        for (var i = 0; i < lines.length; i++) {
+            var nameMatch = lines[i].match(/^(.*)@/);
+            var name = (nameMatch != null) ? nameMatch[1] : "(anonymous function)";
+            var locMatch = lines[i].match(/:([0-9]+:[0-9]+)$/);
+            var loc = (locMatch != null) ? locMatch[1] : "?";
+            lines[i] = "stack["+(lines.length-i-1)+"] = "+name+"@"+loc;
+        }
+        return lines.join("\n");
+    }
+
+    // public
+    Main_execute = function(fun)
+    {
+        try {
+            var res = fun();
+            PostponedActions_perform();
+            return res;
+        }
+        catch (e) {
+            var message = (e.message != null) ? e.message : e.toString();
+            var stack = simplifyStackString(e);
+            Editor_error(message+"\n"+stack);
+        }
+    }
+
+    function fixEmptyBody()
+    {
+        for (var child = document.body.firstChild; child != null; child = child.nextSibling) {
+            if (nodeHasContent(child))
+                return;
+        }
+
+        for (var child = document.body.firstChild; child != null; child = child.nextSibling) {
+            if (child._type == HTML_P) {
+                Cursor_updateBRAtEndOfParagraph(child);
+                return;
+            }
+        }
+
+        var p = DOM_createElement(document,"P");
+        var br = DOM_createElement(document,"BR");
+        DOM_appendChild(p,br);
+        DOM_appendChild(document.body,p);
+    }
+
+    // public
+    Main_init = function(width,textScale,cssURL,clientRectsBug)
+    {
+        try {
+            Main_clientRectsBug = clientRectsBug;
+            if (document.documentElement == null)
+                throw new Error("document.documentElement is null");
+            if (document.body == null)
+                throw new Error("document.body is null");
+            var timing = new TimingInfo();
+            timing.start();
+            DOM_assignNodeIds(document);
+            timing.addEntry("DOM_assignNodeIds");
+            Main_removeUnsupportedInput();
+            timing.addEntry("Main_removeUnsupportedInput");
+            addMetaCharset();
+            timing.addEntry("addMetaCharset");
+            fixEmptyBody();
+            timing.addEntry("fixEmptyBody");
+            Outline_init();
+            timing.addEntry("Outline_init");
+            Styles_init(cssURL);
+            timing.addEntry("Styles_init");
+            Viewport_init(width,textScale);
+            timing.addEntry("Viewport_init");
+            AutoCorrect_init();
+            timing.addEntry("AutoCorrect_init");
+
+            PostponedActions_perform();
+            timing.addEntry("PostponedActions_perform");
+            Cursor_moveToStartOfDocument();
+            timing.addEntry("Cursor_moveToStartOfDocument");
+
+            UndoManager_clear();
+            timing.addEntry("UndoManager_clear");
+//            timing.print();
+
+            return true;
+        }
+        catch (e) {
+            return e.toString();
+        }
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Metadata.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Metadata.js b/experiments/editorFramework/src/Javascript_Layer_0/Metadata.js
new file mode 100644
index 0000000..fce4cca
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Metadata.js
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Metadata_getMetadata;
+var Metadata_setMetadata;
+
+(function() {
+
+    Metadata_getMetadata = function()
+    {
+        return {};
+    }
+
+    Metadata_setMetadata = function(metadata)
+    {
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/NodeSet.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/NodeSet.js b/experiments/editorFramework/src/Javascript_Layer_0/NodeSet.js
new file mode 100644
index 0000000..77b7600
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/NodeSet.js
@@ -0,0 +1,201 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+function NodeSet()
+{
+    this.members = new Object();
+}
+
+NodeSet.prototype.add = function(node)
+{
+    if (node._nodeId == null)
+        throw new Error("NodeSet.add: node "+node.nodeName+" has no _nodeId property");
+    this.members[node._nodeId] = node;
+}
+
+NodeSet.prototype.remove = function(node)
+{
+    if (node._nodeId == null)
+        throw new Error("NodeSet.remove: node "+node.nodeName+" has no _nodeId property");
+    delete this.members[node._nodeId];
+}
+
+NodeSet.prototype.contains = function(node)
+{
+    if (node._nodeId == null)
+        throw new Error("NodeSet.contains: node "+node.nodeName+" has no _nodeId property");
+    return (this.members[node._nodeId] != null);
+}
+
+NodeSet.prototype.toArray = function()
+{
+    var result = new Array();
+    for (var id in this.members)
+        result.push(members[id]);
+    return result;
+}
+
+NodeSet.prototype.forEach = function(fun)
+{
+    var ids = Object.getOwnPropertyNames(this.members);
+    var set = this;
+    ids.forEach(function(id) { fun(set.members[id]); });
+}
+
+NodeSet.prototype.ancestor = function()
+{
+    var result = new NodeSet();
+    this.forEach(function (node) {
+        for (var p = node.parentNode; p != null; p = p.parentNode)
+            result.add(p);
+    });
+    return result;
+}
+
+NodeSet.prototype.ancestorOrSelf = function()
+{
+    var result = new NodeSet();
+    this.forEach(function (node) {
+        for (var p = node; p != null; p = p.parentNode)
+            result.add(p);
+    });
+    return result;
+}
+
+NodeSet.prototype.descendant = function()
+{
+    var result = new NodeSet();
+    this.forEach(function (node) {
+        recurse(node);
+    });
+    return result;
+
+    function recurse(node)
+    {
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            result.add(child);
+            recurse(child);
+        }
+    }
+}
+
+NodeSet.prototype.descendantOrSelf = function()
+{
+    var result = new NodeSet();
+    this.forEach(function (node) {
+        recurse(node);
+    });
+    return result;
+
+    function recurse(node)
+    {
+        result.add(node);
+        for (var child = node.firstChild; child != null; child = child.nextSibling)
+            recurse(child);
+    }
+}
+
+NodeSet.prototype.union = function(other)
+{
+    var result = new NodeSet();
+    this.forEach(function (node) { result.add(node); });
+    other.forEach(function (node) { result.add(node); });
+    return result;
+}
+
+NodeSet.prototype.intersection = function(other)
+{
+    var result = new NodeSet();
+    this.forEach(function (node) { if (other.contains(node)) { result.add(node); } });
+    return result;
+}
+
+NodeSet.fromArray = function(array)
+{
+    var set = new NodeSet();
+    array.forEach(function(node) { set.add(node); });
+    return set;
+}
+
+
+function NodeMap()
+{
+    this.keys = new Object();
+    this.values = new Object();
+}
+
+NodeMap.prototype.clear = function()
+{
+    this.keys = new Object();
+    this.values = new Object();
+}
+
+NodeMap.prototype.get = function(key)
+{
+    if (key._nodeId == null)
+        throw new Error("NodeMap.get: key "+key.keyName+" has no _nodeId property");
+    return this.values[key._nodeId];
+}
+
+NodeMap.prototype.put = function(key,value)
+{
+    if (key._nodeId == null)
+        throw new Error("NodeMap.add: key "+key.keyName+" has no _nodeId property");
+    this.keys[key._nodeId] = key;
+    this.values[key._nodeId] = value;
+}
+
+NodeMap.prototype.remove = function(key)
+{
+    if (key._nodeId == null)
+        throw new Error("NodeMap.remove: key "+key.keyName+" has no _nodeId property");
+    delete this.keys[key._nodeId];
+    delete this.values[key._nodeId];
+}
+
+NodeMap.prototype.containsKey = function(key)
+{
+    if (key._nodeId == null)
+        throw new Error("NodeMap.contains: key "+key.keyName+" has no _nodeId property");
+    return (this.values[key._nodeId] != null);
+}
+
+NodeMap.prototype.getKeys = function()
+{
+    var ids = Object.getOwnPropertyNames(this.values);
+    var result = new Array(ids.length);
+    for (var i = 0; i < ids.length; i++)
+        result[i] = this.keys[ids[i]];
+    return result;
+}
+
+NodeMap.prototype.forEach = function(fun)
+{
+    var ids = Object.getOwnPropertyNames(this.values);
+    var map = this;
+    ids.forEach(function(id) { fun(map.keys[id],map.values[id]); });
+}
+
+NodeMap.fromArray = function(array,fun)
+{
+    var map = new NodeMap();
+    if (fun != null)
+        array.forEach(function(node) { map.put(node,fun(node)); });
+    else
+        array.forEach(function(node) { map.put(node,null); });
+    return map;
+};



[10/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Outline.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Outline.js b/experiments/editorFramework/src/Layer0_Javascript/Outline.js
deleted file mode 100644
index 9812041..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Outline.js
+++ /dev/null
@@ -1,1434 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-// FIXME: The TOC/ItemList stuff won't work with Undo, because we're making DOM mutations in
-// response to other DOM mutations, so at undo time the changes will be made twice
-
-var Outline_init;
-var Outline_removeListeners;
-var Outline_moveSection;
-var Outline_deleteItem;
-var Outline_goToItem;
-var Outline_setTitle;
-var Outline_setNumbered;
-var Outline_getItemElement;
-var Outline_getOutline;
-var Outline_plainText;
-var Outline_insertTableOfContents;
-var Outline_insertListOfFigures;
-var Outline_insertListOfTables;
-var Outline_setPrintMode;
-var Outline_examinePrintLayout;
-var Outline_setReferenceTarget;
-var Outline_detectSectionNumbering;
-var Outline_findUsedStyles;
-var Outline_scheduleUpdateStructure;
-
-(function() {
-
-    var itemsByNode = null;
-    var refsById = null;
-    var nextItemId = 1;
-    var outlineDirty = false;
-    var ignoreModifications = 0;
-    var sectionNumberRegex = /^\s*(Chapter\s+)?\d+(\.\d+)*\.?\s+/i;
-    var figureNumberRegex = /^\s*Figure\s+\d+(\.\d+)*:?\s*/i;
-    var tableNumberRegex = /^\s*Table\s+\d+(\.\d+)*:?\s*/i;
-    var sections = null;
-    var figures = null;
-    var tables = null;
-    var doneInit = false;
-    var printMode = false;
-
-    function Category(type,nodeFilter,numberRegex)
-    {
-        this.type = type;
-        this.nodeFilter = nodeFilter;
-        this.numberRegex = numberRegex;
-        this.list = new DoublyLinkedList();
-        this.tocs = new NodeMap();
-    }
-
-    function addItemInternal(category,item,prevItem,title)
-    {
-        UndoManager_addAction(removeItemInternal,category,item);
-        category.list.insertAfter(item,prevItem);
-        item.title = title;
-        category.tocs.forEach(function(node,toc) { TOC_addOutlineItem(toc,item.id); });
-        Editor_addOutlineItem(item.id,category.type,title);
-    }
-
-    function removeItemInternal(category,item)
-    {
-        UndoManager_addAction(addItemInternal,category,item,item.prev,item.title);
-        category.list.remove(item);
-        category.tocs.forEach(function(node,toc) { TOC_removeOutlineItem(toc,item.id); });
-        item.title = null;
-        Editor_removeOutlineItem(item.id);
-    }
-
-    function Category_add(category,node)
-    {
-        var item = itemsByNode.get(node);
-        if (item == null)
-            item = new OutlineItem(category,node);
-
-        var prevItem = findPrevItemOfType(node,category.nodeFilter);
-        addItemInternal(category,item,prevItem,null);
-
-        // Register for notifications to changes to this item's node content. We may need to
-        // update the title when such a modification occurs.
-        node.addEventListener("DOMSubtreeModified",item.modificationListener);
-
-        OutlineItem_updateItemTitle(item);
-        scheduleUpdateStructure();
-        return item;
-
-        function findPrevItemOfType(node,typeFun)
-        {
-            do node = prevNode(node);
-            while ((node != null) && !typeFun(node));
-            return (node == null) ? null : itemsByNode.get(node);
-        }
-    }
-
-    function findFirstTextDescendant(node)
-    {
-        if (isWhitespaceTextNode(node))
-            return;
-        if (node.nodeType == Node.TEXT_NODE)
-            return node;
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            var result = findFirstTextDescendant(child);
-            if (result != null)
-                return result;
-        }
-        return null;
-    }
-
-    function Category_remove(category,node)
-    {
-        var item = itemsByNode.get(node);
-        if (item == null) {
-            throw new Error("Attempt to remove non-existant "+node.nodeName+
-                            " item "+node.getAttribute("id"));
-        }
-        removeItemInternal(category,item);
-        item.node.removeEventListener("DOMSubtreeModified",item.modificationListener);
-        var titleNode = OutlineItem_getTitleNode(item,false);
-        if ((titleNode != null) &&
-            ((item.type == "figure") || (item.type == "table")) &&
-            (titleNode.firstChild == null) &&
-            (titleNode.lastChild == null)) {
-            DOM_deleteNode(titleNode);
-        }
-        scheduleUpdateStructure();
-    }
-
-    function addTOCInternal(category,node,toc)
-    {
-        UndoManager_addAction(removeTOCInternal,category,node);
-        category.tocs.put(node,toc);
-    }
-
-    function removeTOCInternal(category,node)
-    {
-        var toc = category.tocs.get(node);
-        if (toc == null)
-            throw new Error("Attempt to remove ItemList that doesn't exist");
-
-        UndoManager_addAction(addTOCInternal,category,node,toc);
-
-        category.tocs.remove(node);
-    }
-
-    function Category_addTOC(category,node)
-    {
-        var toc = new TOC(node);
-        addTOCInternal(category,node,toc);
-
-        for (var item = category.list.first; item != null; item = item.next) {
-            TOC_addOutlineItem(toc,item.id);
-            TOC_updateOutlineItem(toc,item.id,item.title);
-        }
-
-        scheduleUpdateStructure();
-    }
-
-    function Category_removeTOC(category,node)
-    {
-        removeTOCInternal(category,node);
-    }
-
-    function TOC(node)
-    {
-        this.node = node;
-        this.textNodes = new Object();
-    }
-
-    function TOC_addOutlineItem(toc,id)
-    {
-        toc.textNodes[id] = DOM_createTextNode(document,"");
-    }
-
-    function TOC_removeOutlineItem(toc,id)
-    {
-        delete toc.textNodes[id];
-    }
-
-    function TOC_updateOutlineItem(toc,id,title)
-    {
-        DOM_setNodeValue(toc.textNodes[id],title);
-    }
-
-    function TOC_updateStructure(toc,structure,toplevelShadows,pageNumbers)
-    {
-        Hierarchy_ensureValidHierarchy(toc.node);
-        DOM_deleteAllChildren(toc.node);
-
-        var cls = toc.node.getAttribute("class");
-
-        if (toplevelShadows.length == 0) {
-            createEmptyTOC(toc.node);
-        }
-        else {
-            recurse(toplevelShadows,toc.node,1);
-        }
-
-        if (printMode) {
-            var brk = DOM_createElement(document,"DIV");
-            DOM_setStyleProperties(brk,{ "clear": "both" });
-            DOM_appendChild(toc.node,brk);
-        }
-
-        function createEmptyTOC(parent)
-        {
-            if (!printMode) {
-                var str = "";
-
-                if (cls == Keys.SECTION_TOC)
-                    str = "[No sections defined]";
-                else if (cls == Keys.FIGURE_TOC)
-                    str = "[No figures defined]";
-                else if (cls == Keys.TABLE_TOC)
-                    str = "[No tables defined]";
-
-                var text = DOM_createTextNode(document,str);
-
-                var div = DOM_createElement(document,"P");
-                DOM_setAttribute(div,"class","toc1");
-                DOM_appendChild(div,text);
-                DOM_appendChild(parent,div);
-            }
-        }
-
-        function recurse(shadows,parent,level)
-        {
-            if (level > 3)
-                return;
-
-            for (var i = 0; i < shadows.length; i++) {
-                var shadow = shadows[i];
-                var item = shadow.item;
-
-                if (printMode) {
-                    var div = DOM_createElement(document,"P");
-                    DOM_setAttribute(div,"class","toc"+level+"-print");
-                    DOM_appendChild(parent,div);
-
-                    var leftSpan = DOM_createElement(document,"SPAN");
-                    DOM_setAttribute(leftSpan,"class","toctitle");
-
-                    var rightSpan = DOM_createElement(document,"SPAN");
-                    DOM_setAttribute(rightSpan,"class","tocpageno");
-
-                    DOM_appendChild(div,leftSpan);
-                    DOM_appendChild(div,rightSpan);
-
-                    if (item.computedNumber != null) {
-                        var text = DOM_createTextNode(document,item.computedNumber+" ");
-                        DOM_appendChild(leftSpan,text);
-                    }
-
-                    DOM_appendChild(leftSpan,toc.textNodes[item.id]);
-                    var pageNo = pageNumbers ? pageNumbers.get(item.node) : null;
-                    if (pageNo == null)
-                        DOM_appendChild(rightSpan,DOM_createTextNode(document,"XXXX"));
-                    else
-                        DOM_appendChild(rightSpan,DOM_createTextNode(document,pageNo));
-                }
-                else {
-                    var div = DOM_createElement(document,"P");
-                    DOM_setAttribute(div,"class","toc"+level);
-                    DOM_appendChild(parent,div);
-
-                    var a = DOM_createElement(document,"A");
-                    DOM_setAttribute(a,"href","#"+item.id);
-                    DOM_appendChild(div,a);
-
-                    if (item.computedNumber != null)
-                        DOM_appendChild(a,DOM_createTextNode(document,item.computedNumber+" "));
-                    DOM_appendChild(a,toc.textNodes[item.id]);
-                }
-
-                recurse(shadow.children,parent,level+1);
-            }
-        }
-    }
-
-    function OutlineItem(category,node)
-    {
-        var type = category.type;
-        var item = this;
-        if ((node != null) && (node.hasAttribute("id"))) {
-            this.id = node.getAttribute("id");
-        }
-        else {
-            this.id = generateItemId();
-            if (node != null)
-                DOM_setAttribute(node,"id",this.id);
-        }
-        this.category = category;
-        this.type = type;
-        this.node = node;
-        this.title = null;
-        this.computedNumber = null;
-
-        this.spareSpan = DOM_createElement(document,"SPAN");
-        DOM_appendChild(this.spareSpan,DOM_createTextNode(document,""));
-        var spanClass = null;
-        if (this.type == "section")
-            spanClass = Keys.HEADING_NUMBER;
-        else if (this.type == "figure")
-            spanClass = Keys.FIGURE_NUMBER;
-        else if (this.type == "table")
-            spanClass = Keys.TABLE_NUMBER;
-        DOM_setAttribute(this.spareSpan,"class",spanClass);
-
-        // titleNode
-        if (this.type == "figure") {
-            this.spareTitle = DOM_createElement(document,"FIGCAPTION");
-        }
-        else if (this.type == "table") {
-            this.spareTitle = DOM_createElement(document,"CAPTION");
-        }
-
-        this.prev = null;
-        this.next = null;
-        this.modificationListener = function(event) { itemModified(item); }
-
-        itemsByNode.put(this.node,this);
-
-        Object.seal(this);
-        return;
-
-        function generateItemId()
-        {
-            var id;
-            do {
-                id = "item"+(nextItemId++);
-            } while (document.getElementById(id) != null);
-            return id;
-        }
-    }
-
-    function OutlineItem_getTitleNode(item,create)
-    {
-        if (item.type == "section") {
-            return item.node;
-        }
-        else if (item.type == "figure") {
-            var titleNode = findChild(item.node,HTML_FIGCAPTION);
-            if ((titleNode == null) && create) {
-                titleNode = item.spareTitle;
-                DOM_appendChild(item.node,titleNode);
-            }
-            return titleNode;
-        }
-        else if (item.type == "table") {
-            var titleNode = findChild(item.node,HTML_CAPTION);
-            if ((titleNode == null) && create) {
-                titleNode = item.spareTitle;
-                DOM_insertBefore(item.node,titleNode,item.node.firstChild);
-            }
-            return titleNode;
-        }
-
-        function findChild(node,type)
-        {
-            for (var child = node.firstChild; child != null; child = child.nextSibling) {
-                if (child._type == type)
-                    return child;
-            }
-            return null;
-        }
-    }
-
-    function OutlineItem_updateItemTitle(item)
-    {
-        var titleNode = OutlineItem_getTitleNode(item,false);
-        if (titleNode != null)
-            newTitle = normalizeWhitespace(getNodeText(titleNode));
-        else
-            newTitle = "";
-
-        if (item.title != newTitle) {
-            UndoManager_addAction(Editor_updateOutlineItem,item.id,item.title);
-            Editor_updateOutlineItem(item.id,newTitle);
-            item.title = newTitle;
-            item.category.tocs.forEach(function(node,toc) {
-                TOC_updateOutlineItem(toc,item.id,item.title);
-            });
-        }
-    }
-
-    function getNodeTextAfter(node)
-    {
-        var text = "";
-        for (var child = node.nextSibling; child != null; child = child.nextSibling)
-            text += getNodeText(child);
-        return text;
-    }
-
-    // private
-    function itemModified(item)
-    {
-        if (UndoManager_isActive())
-            return;
-        if (ignoreModifications > 0)
-            return;
-        OutlineItem_updateItemTitle(item);
-        updateRefsForItem(item);
-    }
-
-    function addRefForId(id,node)
-    {
-        UndoManager_addAction(removeRefForId,id,node);
-        if (refsById[id] == null)
-            refsById[id] = new Array();
-        refsById[id].push(node);
-    }
-
-    function removeRefForId(id,node)
-    {
-        UndoManager_addAction(addRefForId,id,node);
-        if (refsById[id] == null)
-            throw new Error("refRemoved: refsById["+id+"] is null");
-        var index = refsById[id].indexOf(node);
-        if (index < 0)
-            throw new Error("refRemoved: refsById["+id+"] does not contain node");
-        refsById[id].splice(index,1);
-        if (refsById[id] == null)
-            delete refsById[id];
-    }
-
-    // private
-    function refInserted(node)
-    {
-        var href = node.getAttribute("href");
-        if (href.charAt(0) != "#")
-            throw new Error("refInserted: not a # reference");
-        var id = href.substring(1);
-        addRefForId(id,node);
-        scheduleUpdateStructure();
-    }
-
-    // private
-    function refRemoved(node)
-    {
-        var href = node.getAttribute("href");
-        if (href.charAt(0) != "#")
-            throw new Error("refInserted: not a # reference");
-        var id = href.substring(1);
-        removeRefForId(id,node);
-    }
-
-    // private
-    function acceptNode(node)
-    {
-        for (var p = node; p != null; p = p.parentNode) {
-            if ((p._type == HTML_SPAN) && (p.getAttribute("class") == Keys.HEADING_NUMBER))
-                return false;
-        }
-        return true;
-    }
-
-    // private
-    function docNodeInserted(event)
-    {
-        if (UndoManager_isActive())
-            return;
-        if (DOM_getIgnoreMutations())
-            return;
-        try {
-            if (!acceptNode(event.target))
-                return;
-            recurse(event.target);
-        }
-        catch (e) {
-            Editor_error(e);
-        }
-
-        function recurse(node)
-        {
-            switch (node._type) {
-            case HTML_H1:
-            case HTML_H2:
-            case HTML_H3:
-            case HTML_H4:
-            case HTML_H5:
-            case HTML_H6: {
-                if (!isInTOC(node))
-                    Category_add(sections,node);
-                break;
-            }
-            case HTML_FIGURE:
-                Category_add(figures,node);
-                break;
-            case HTML_TABLE:
-                Category_add(tables,node);
-                break;
-            case HTML_A: {
-                if (isRefNode(node) && !isInTOC(node)) {
-                    refInserted(node);
-                }
-                break;
-            }
-            case HTML_NAV: {
-                var cls = node.getAttribute("class");
-                if (cls == Keys.SECTION_TOC)
-                    Category_addTOC(sections,node);
-                else if (cls == Keys.FIGURE_TOC)
-                    Category_addTOC(figures,node);
-                else if (cls == Keys.TABLE_TOC)
-                    Category_addTOC(tables,node);
-                break;
-            }
-            }
-
-            var next;
-            for (var child = node.firstChild; child != null; child = next) {
-                next = child.nextSibling;
-                recurse(child);
-            }
-        }
-    }
-
-    // private
-    function docNodeRemoved(event)
-    {
-        if (UndoManager_isActive())
-            return;
-        if (DOM_getIgnoreMutations())
-            return;
-        try {
-            if (!acceptNode(event.target))
-                return;
-            recurse(event.target);
-        }
-        catch (e) {
-            Editor_error(e);
-        }
-
-        function recurse(node)
-        {
-            switch (node._type) {
-            case HTML_H1:
-            case HTML_H2:
-            case HTML_H3:
-            case HTML_H4:
-            case HTML_H5:
-            case HTML_H6:
-                if (!isInTOC(node))
-                    Category_remove(sections,node);
-                break;
-            case HTML_FIGURE:
-                Category_remove(figures,node);
-                break;
-            case HTML_TABLE:
-                Category_remove(tables,node);
-                break;
-            case HTML_A:
-                if (isRefNode(node) && !isInTOC(node))
-                    refRemoved(node);
-                break;
-            case HTML_NAV:
-                var cls = node.getAttribute("class");
-                if (cls == Keys.SECTION_TOC)
-                    Category_removeTOC(sections,node);
-                else if (cls == Keys.FIGURE_TOC)
-                    Category_removeTOC(figures,node);
-                else if (cls == Keys.TABLE_TOC)
-                    Category_removeTOC(tables,node);
-                break;
-            }
-
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-    // private
-    function scheduleUpdateStructure()
-    {
-        if (UndoManager_isActive())
-            return;
-        if (!outlineDirty) {
-            outlineDirty = true;
-            PostponedActions_add(updateStructure);
-        }
-    }
-
-    Outline_scheduleUpdateStructure = scheduleUpdateStructure;
-
-    // private
-    function updateStructure()
-    {
-        if (!outlineDirty)
-            return;
-        outlineDirty = false;
-        if (UndoManager_isActive())
-            throw new Error("Structure update event while undo or redo active");
-        Selection_preserveWhileExecuting(function() {
-            updateStructureReal();
-        });
-    }
-
-    function Shadow(node)
-    {
-        this.node = node;
-        this.item = itemsByNode.get(node);
-        this.children = [];
-        this.parent = null;
-
-        switch (node._type) {
-        case HTML_H1:
-            this.level = 1;
-            break;
-        case HTML_H2:
-            this.level = 2;
-            break;
-        case HTML_H3:
-            this.level = 3;
-            break;
-        case HTML_H4:
-            this.level = 4;
-            break;
-        case HTML_H5:
-            this.level = 5;
-            break;
-        case HTML_H6:
-            this.level = 6;
-            break;
-        default:
-            this.level = 0;
-            break;
-        }
-    }
-
-    function Shadow_last(shadow)
-    {
-        if (shadow.children.length == 0)
-            return shadow;
-        else
-            return Shadow_last(shadow.children[shadow.children.length-1]);
-    }
-
-    function Shadow_outerNext(shadow,structure)
-    {
-        var last = Shadow_last(shadow);
-        if (last == null)
-            return null;
-        else if (last.item.next == null)
-            return null;
-        else
-            return structure.shadowsByNode.get(last.item.next.node);
-    }
-
-    function firstTextDescendant(node)
-    {
-        if (node.nodeType == Node.TEXT_NODE)
-            return node;
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            var result = firstTextDescendant(child);
-            if (result != null)
-                return result;
-        }
-        return null;
-    }
-
-    function Structure()
-    {
-        this.toplevelSections = new Array();
-        this.toplevelFigures = new Array();
-        this.toplevelTables = new Array();
-        this.shadowsByNode = new NodeMap();
-    }
-
-    function discoverStructure()
-    {
-        var structure = new Structure();
-        var nextToplevelSectionNumber = 1;
-        var nextFigureNumber = 1;
-        var nextTableNumber = 1;
-        var headingNumbering = Styles_headingNumbering();
-
-        var counters = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0, table: 0, figure: 0 };
-
-        var current = null;
-
-        for (var section = sections.list.first; section != null; section = section.next) {
-            structure.shadowsByNode.put(section.node,new Shadow(section.node));
-        }
-        for (var figure = figures.list.first; figure != null; figure = figure.next) {
-            structure.shadowsByNode.put(figure.node,new Shadow(figure.node));
-        }
-        for (var table = tables.list.first; table != null; table = table.next) {
-            structure.shadowsByNode.put(table.node,new Shadow(table.node));
-        }
-
-        for (var section = sections.list.first; section != null; section = section.next) {
-            var shadow = structure.shadowsByNode.get(section.node);
-            shadow.parent = null;
-            shadow.children = [];
-            shadow.nextChildSectionNumber = 1;
-        }
-
-        ignoreModifications++;
-
-        for (var section = sections.list.first; section != null; section = section.next) {
-            var shadow = structure.shadowsByNode.get(section.node);
-            var node = section.node;
-            var item = shadow.item;
-
-            if (!headingNumbering || (DOM_getAttribute(item.node,"class") == "Unnumbered")) {
-                item.computedNumber = null;
-            }
-            else {
-                var level = parseInt(node.nodeName.charAt(1));
-                counters[node.nodeName.toLowerCase()]++;
-                for (var inner = level+1; inner <= 6; inner++)
-                    counters["h"+inner] = 0;
-                item.computedNumber = "";
-                for (var i = 1; i <= level; i++) {
-                    if (i == 1)
-                        item.computedNumber += counters["h"+i];
-                    else
-                        item.computedNumber += "." + counters["h"+i];
-                }
-            }
-
-            while ((current != null) && (shadow.level < current.level+1))
-                current = current.parent;
-
-            shadow.parent = current;
-            if (current == null)
-                structure.toplevelSections.push(shadow);
-            else
-                current.children.push(shadow);
-
-            current = shadow;
-        }
-
-        for (var figure = figures.list.first; figure != null; figure = figure.next) {
-            var shadow = structure.shadowsByNode.get(figure.node);
-            var item = shadow.item;
-
-            var titleNode = OutlineItem_getTitleNode(item,false);
-            if ((titleNode == null) || DOM_getAttribute(titleNode,"class") == "Unnumbered") {
-                item.computedNumber = null;
-            }
-            else {
-                counters.figure++;
-                item.computedNumber = ""+counters.figure;
-            }
-
-            structure.toplevelFigures.push(shadow);
-        }
-
-        for (var table = tables.list.first; table != null; table = table.next) {
-            var shadow = structure.shadowsByNode.get(table.node);
-            var item = shadow.item;
-
-            var titleNode = OutlineItem_getTitleNode(item,false);
-            if ((titleNode == null) || DOM_getAttribute(titleNode,"class") == "Unnumbered") {
-                item.computedNumber = null;
-            }
-            else {
-                counters.table++;
-                item.computedNumber = ""+counters.table;
-            }
-
-            structure.toplevelTables.push(shadow);
-        }
-
-        ignoreModifications--;
-
-        return structure;
-    }
-
-    function updateStructureReal(pageNumbers)
-    {
-        var structure = discoverStructure();
-
-        for (var section = sections.list.first; section != null; section = section.next) {
-            var shadow = structure.shadowsByNode.get(section.node);
-            updateRefsForItem(shadow.item);
-        }
-
-        for (var figure = figures.list.first; figure != null; figure = figure.next) {
-            var shadow = structure.shadowsByNode.get(figure.node);
-            updateRefsForItem(shadow.item);
-        }
-
-        for (var table = tables.list.first; table != null; table = table.next) {
-            var shadow = structure.shadowsByNode.get(table.node);
-            updateRefsForItem(shadow.item);
-        }
-
-        sections.tocs.forEach(function (node,toc) {
-            TOC_updateStructure(toc,structure,structure.toplevelSections,pageNumbers);
-        });
-        figures.tocs.forEach(function (node,toc) {
-            TOC_updateStructure(toc,structure,structure.toplevelFigures,pageNumbers);
-        });
-        tables.tocs.forEach(function (node,toc) {
-            TOC_updateStructure(toc,structure,structure.toplevelTables,pageNumbers);
-        });
-
-        Editor_outlineUpdated();
-    }
-
-    Outline_getOutline = function()
-    {
-        var structure = discoverStructure();
-        var encSections = new Array();
-        var encFigures = new Array();
-        var encTables = new Array();
-
-        for (var i = 0; i < structure.toplevelSections.length; i++)
-            encodeShadow(structure.toplevelSections[i],encSections);
-        for (var i = 0; i < structure.toplevelFigures.length; i++)
-            encodeShadow(structure.toplevelFigures[i],encFigures);
-        for (var i = 0; i < structure.toplevelTables.length; i++)
-            encodeShadow(structure.toplevelTables[i],encTables);
-
-        return { sections: encSections,
-                 figures: encFigures,
-                 tables: encTables };
-
-        function encodeShadow(shadow,result)
-        {
-            var encChildren = new Array();
-            for (var i = 0; i < shadow.children.length; i++)
-                encodeShadow(shadow.children[i],encChildren);
-
-            var obj = { id: shadow.item.id,
-                        number: shadow.item.computedNumber ? shadow.item.computedNumber : "",
-                        children: encChildren };
-            result.push(obj);
-        }
-    }
-
-    function updateRefsForItem(item)
-    {
-        var id = item.node.getAttribute("id");
-        var refs = refsById[id];
-        if (refs == null)
-            return;
-        for (var i = 0; i < refs.length; i++) {
-            DOM_deleteAllChildren(refs[i]);
-            var text = null;
-
-            var className = DOM_getAttribute(refs[i],"class");
-            if (className == "uxwrite-ref-num") {
-                text = item.computedNumber;
-            }
-            else if (className == "uxwrite-ref-text") {
-                if (item.type == "section") {
-                    if (item.numberSpan != null)
-                        text = getNodeTextAfter(item.numberSpan);
-                    else
-                        text = normalizeWhitespace(getNodeText(item.node));
-                }
-                else if ((item.type == "figure") || (item.type == "table")) {
-                    var titleNode = OutlineItem_getTitleNode(item,false);
-                    if (titleNode != null) {
-                        text = getNodeText(titleNode);
-
-                        if ((item.computedNumber != null) && (item.type == "figure"))
-                            text = "Figure "+item.computedNumber+": "+text;
-                        else if ((item.computedNumber != null) && (item.type == "table"))
-                            text = "Table "+item.computedNumber+": "+text;
-                    }
-                }
-            }
-            else if (className == "uxwrite-ref-caption-text") {
-                if (item.type == "section") {
-                    if (item.numberSpan != null)
-                        text = getNodeTextAfter(item.numberSpan);
-                    else
-                        text = normalizeWhitespace(getNodeText(item.node));
-                }
-                else if ((item.type == "figure") || (item.type == "table")) {
-                    var titleNode = OutlineItem_getTitleNode(item,false);
-                    if (titleNode != null) {
-                        if (item.numberSpan != null)
-                            text = getNodeTextAfter(item.numberSpan);
-                        else
-                            text = normalizeWhitespace(getNodeText(titleNode));
-                    }
-                }
-            }
-            else if (className == "uxwrite-ref-label-num") {
-                if (item.computedNumber != null) {
-                    if (item.type == "section")
-                        text = "Section "+item.computedNumber;
-                    else if (item.type == "figure")
-                        text = "Figure "+item.computedNumber;
-                    else if (item.type == "table")
-                        text = "Table "+item.computedNumber;
-                }
-            }
-            else {
-                if (item.computedNumber != null)
-                    text = item.computedNumber;
-                else
-                    text = item.title;
-            }
-
-            if (text == null)
-                text = "?";
-
-            DOM_appendChild(refs[i],DOM_createTextNode(document,text));
-        }
-    }
-
-    Outline_plainText = function()
-    {
-        var strings = new Array();
-        var structure = discoverStructure();
-
-        strings.push("Sections:\n");
-        for (var section = sections.list.first; section != null; section = section.next) {
-            var shadow = structure.shadowsByNode.get(section.node);
-            if (shadow.level == 1)
-                printSectionRecursive(shadow,"    ");
-        }
-        strings.push("Figures:\n");
-        for (var figure = figures.list.first; figure != null; figure = figure.next) {
-            var shadow = structure.shadowsByNode.get(figure.node);
-            var titleNode = OutlineItem_getTitleNode(figure,false);
-            var title = titleNode ? getNodeText(titleNode) : "[no caption]";
-            if (shadow.item.computedNumber != null) {
-                if (title.length > 0)
-                    title = shadow.item.computedNumber+" "+title;
-                else
-                    title = shadow.item.computedNumber;
-            }
-            strings.push("    "+title+" ("+figure.id+")\n");
-        }
-        strings.push("Tables:\n");
-        for (var table = tables.list.first; table != null; table = table.next) {
-            var shadow = structure.shadowsByNode.get(table.node);
-            var titleNode = OutlineItem_getTitleNode(table,false);
-            var title = titleNode ? getNodeText(titleNode) : "[no caption]";
-            if (shadow.item.computedNumber != null) {
-                if (title.length > 0)
-                    title = shadow.item.computedNumber+" "+title;
-                else
-                    title = shadow.item.computedNumber;
-            }
-            strings.push("    "+title+" ("+table.id+")\n");
-        }
-        return strings.join("");
-
-        function printSectionRecursive(shadow,indent)
-        {
-            var titleNode = OutlineItem_getTitleNode(shadow.item,false);
-            var content = getNodeText(titleNode);
-            if (shadow.item.computedNumber != null)
-                content = shadow.item.computedNumber+" "+content;
-            if (isWhitespaceString(content))
-                content = "[empty]";
-            strings.push(indent+content+" ("+shadow.item.id+")\n");
-            for (var i = 0; i < shadow.children.length; i++)
-                printSectionRecursive(shadow.children[i],indent+"    ");
-        }
-    }
-
-    // public
-    Outline_init = function()
-    {
-        Selection_preserveWhileExecuting(function() {
-
-            function isTableNode(node)
-            {
-                return (node._type == HTML_TABLE);
-            }
-
-            function isFigureNode(node)
-            {
-                return (node._type == HTML_FIGURE);
-            }
-
-            function isNonTOCHeadingNode(node)
-            {
-                return (HEADING_ELEMENTS[node._type] && !isInTOC(node));
-            }
-
-            sections = new Category("section",isNonTOCHeadingNode,sectionNumberRegex);
-            figures = new Category("figure",isFigureNode,figureNumberRegex);
-            tables = new Category("table",isTableNode,tableNumberRegex);
-            itemsByNode = new NodeMap();
-            refsById = new Object();
-
-            DOM_ensureUniqueIds(document.documentElement);
-            document.addEventListener("DOMNodeInserted",docNodeInserted);
-            document.addEventListener("DOMNodeRemoved",docNodeRemoved);
-
-            docNodeInserted({target:document});
-        });
-        doneInit = true;
-    }
-
-    // public (for the undo tests, when they report results)
-    Outline_removeListeners = function()
-    {
-        document.removeEventListener("DOMNodeInserted",docNodeInserted);
-        document.removeEventListener("DOMNodeRemoved",docNodeRemoved);
-
-        removeCategoryListeners(sections);
-        removeCategoryListeners(figures);
-        removeCategoryListeners(tables);
-
-        function removeCategoryListeners(category)
-        {
-            for (var item = category.list.first; item != null; item = item.next)
-                item.node.removeEventListener("DOMSubtreeModified",item.modificationListener);
-        }
-    }
-
-    // private
-    function getShadowNodes(structure,shadow,result)
-    {
-        var endShadow = Shadow_outerNext(shadow,structure);
-        var endNode = endShadow ? endShadow.item.node : null;
-        for (var n = shadow.item.node; (n != null) && (n != endNode); n = n.nextSibling)
-            result.push(n);
-    }
-
-    // public
-    Outline_moveSection = function(sectionId,parentId,nextId)
-    {
-        UndoManager_newGroup("Move section");
-        Selection_clear();
-
-        updateStructure(); // make sure pointers are valid
-        // FIXME: I don't think we'll need the updateStructure() call now that we have
-        // discoverStructure(). In fact this function is a perfect illustration of why
-        // waiting till after the postponed action has been performed before relying on the
-        // pointer validity was a problem.
-
-
-        var structure = discoverStructure();
-
-        var node = document.getElementById(sectionId);
-        var section = itemsByNode.get(node);
-        var shadow = structure.shadowsByNode.get(node);
-
-        // FIXME: We should throw an exception if a parentId or nextId which does not exist
-        // in the document is specified. However there are currently some tests (like
-        // moveSection-nested*) which rely us interpreting such parameters as null.
-        var parentNode = parentId ? document.getElementById(parentId) : null;
-        var nextNode = nextId ? document.getElementById(nextId) : null;
-        var parent = parentNode ? structure.shadowsByNode.get(parentNode) : null;
-        var next = nextNode ? structure.shadowsByNode.get(nextNode) : null;
-
-        var sectionNodes = new Array();
-        getShadowNodes(structure,shadow,sectionNodes);
-
-        if ((next == null) && (parent != null))
-            next = Shadow_outerNext(parent,structure);
-
-        if (next == null) {
-            for (var i = 0; i < sectionNodes.length; i++)
-                DOM_appendChild(document.body,sectionNodes[i]);
-        }
-        else {
-            for (var i = 0; i < sectionNodes.length; i++)
-                DOM_insertBefore(next.item.node.parentNode,sectionNodes[i],next.item.node);
-        }
-
-        var pos = new Position(node,0,node,0);
-        pos = Position_closestMatchForwards(pos,Position_okForInsertion);
-        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-
-        scheduleUpdateStructure();
-        PostponedActions_add(UndoManager_newGroup);
-    }
-
-    // public
-    Outline_deleteItem = function(itemId)
-    {
-        UndoManager_newGroup("Delete outline item");
-        var structure = discoverStructure();
-        Selection_preserveWhileExecuting(function() {
-            var node = document.getElementById(itemId);
-            var item = itemsByNode.get(node);
-            var shadow = structure.shadowsByNode.get(item.node);
-            if (item.type == "section") {
-                var sectionNodes = new Array();
-                getShadowNodes(structure,shadow,sectionNodes);
-                for (var i = 0; i < sectionNodes.length; i++)
-                    DOM_deleteNode(sectionNodes[i]);
-            }
-            else {
-                DOM_deleteNode(item.node);
-            }
-        });
-
-        // Ensure the cursor or selection start/end positions are valid positions that the
-        // user is allowed to move to. This ensures we get an accurate rect for each position,
-        // avoiding an ugly effect where the cursor occupies the entire height of the document
-        // and is displayed on the far-left edge of the editing area.
-        var selRange = Selection_get();
-        if (selRange != null) {
-            var start = Position_closestMatchForwards(selRange.start,Position_okForMovement);
-            var end = Position_closestMatchForwards(selRange.end,Position_okForMovement);
-            Selection_set(start.node,start.offset,end.node,end.offset);
-        }
-
-        scheduleUpdateStructure();
-        PostponedActions_add(Cursor_ensureCursorVisible);
-        PostponedActions_add(UndoManager_newGroup);
-    }
-
-    // public
-    Outline_goToItem = function(itemId)
-    {
-        if (itemId == null) {
-            window.scrollTo(0);
-        }
-        else {
-            var node = document.getElementById(itemId);
-            if (node == null) {
-                // FIXME: this can happen if the user added some headings, pressed undo one or
-                // more times (in which case the editor's view of the outline structure fails to
-                // be updated), and then they click on an item. This is really an error but we
-                // handle it gracefully for now rather than causing a null pointer exception to
-                // be thrown.
-                return;
-            }
-            var position = new Position(node,0);
-            position = Position_closestMatchForwards(position,Position_okForMovement);
-            Selection_set(position.node,position.offset,position.node,position.offset);
-
-            var section = document.getElementById(itemId);
-            var location = webkitConvertPointFromNodeToPage(section,new WebKitPoint(0,0));
-            window.scrollTo(0,location.y);
-        }
-    }
-
-    // public
-    Outline_getItemElement = function(itemId)
-    {
-        return document.getElementById(itemId);
-    }
-
-    // public
-    Outline_setNumbered = function(itemId,numbered)
-    {
-        var node = document.getElementById(itemId);
-        var item = itemsByNode.get(node);
-
-        Selection_preserveWhileExecuting(function() {
-            if (item.type == "section") {
-                if (numbered)
-                    DOM_removeAttribute(node,"class");
-                else
-                    DOM_setAttribute(node,"class","Unnumbered");
-            }
-            else if ((item.type == "figure") || (item.type == "table")) {
-                if (numbered) {
-                    var caption = OutlineItem_getTitleNode(item,true);
-                    DOM_removeAttribute(caption,"class");
-                }
-                else {
-                    var caption = OutlineItem_getTitleNode(item,false);
-                    if (caption != null) {
-                        if (nodeHasContent(caption))
-                            DOM_setAttribute(caption,"class","Unnumbered");
-                        else
-                            DOM_deleteNode(caption);
-                    }
-                }
-            }
-        });
-
-        scheduleUpdateStructure();
-    }
-
-    // public
-    Outline_setTitle = function(itemId,title)
-    {
-        var node = document.getElementById(itemId);
-        var item = itemsByNode.get(node);
-        Selection_preserveWhileExecuting(function() {
-            var titleNode = OutlineItem_getTitleNode(item,true);
-            var oldEmpty = (item.title == "");
-            var newEmpty = (title == "");
-            if (oldEmpty != newEmpty) {
-                // Add or remove the : at the end of table and figure numbers
-                scheduleUpdateStructure();
-            }
-            if (item.numberSpan != null) {
-                while (item.numberSpan.nextSibling != null)
-                    DOM_deleteNode(item.numberSpan.nextSibling);
-            }
-            else {
-                DOM_deleteAllChildren(titleNode);
-            }
-            DOM_appendChild(titleNode,DOM_createTextNode(document,title));
-            OutlineItem_updateItemTitle(item);
-        });
-    }
-
-    // private
-    // FIXME: prevent a TOC from being inserted inside a heading, figure, or table
-    function insertTOC(key,initialText)
-    {
-        var div = DOM_createElement(document,"NAV");
-        DOM_setAttribute(div,"class",key);
-        Cursor_makeContainerInsertionPoint();
-        Clipboard_pasteNodes([div]);
-    }
-
-    // public
-    Outline_insertTableOfContents = function()
-    {
-        insertTOC(Keys.SECTION_TOC);
-    }
-
-    // public
-    Outline_insertListOfFigures = function()
-    {
-        insertTOC(Keys.FIGURE_TOC);
-    }
-
-    // public
-    Outline_insertListOfTables = function()
-    {
-        insertTOC(Keys.TABLE_TOC);
-    }
-
-    // public
-    Outline_setPrintMode = function(newPrintMode)
-    {
-        printMode = newPrintMode;
-        scheduleUpdateStructure();
-    }
-
-    // public
-    Outline_examinePrintLayout = function(pageHeight)
-    {
-        var result = new Object();
-        var structure = discoverStructure();
-        var pageNumbers = new NodeMap();
-
-        result.destsByPage = new Object();
-        result.linksByPage = new Object();
-        result.leafRectsByPage = new Object();
-
-        itemsByNode.forEach(function(node,item) {
-            var rect = node.getBoundingClientRect();
-            var pageNo = 1+Math.floor(rect.top/pageHeight);
-            var pageTop = (pageNo-1)*pageHeight;
-            var id = node.getAttribute("id");
-            pageNumbers.put(node,pageNo);
-
-            if (result.destsByPage[pageNo] == null)
-                result.destsByPage[pageNo] = new Array();
-            result.destsByPage[pageNo].push({ itemId: id,
-                                              x: rect.left,
-                                              y: rect.top - pageTop});
-        });
-
-        var links = document.getElementsByTagName("A");
-        for (var i = 0; i < links.length; i++) {
-            var a = links[i];
-
-            if (!a.hasAttribute("href"))
-                continue;
-
-            var offset = DOM_nodeOffset(a);
-            var range = new Range(a.parentNode,offset,a.parentNode,offset+1);
-            var rects = Range_getClientRects(range);
-            for (var rectIndex = 0; rectIndex < rects.length; rectIndex++) {
-                var rect = rects[rectIndex];
-                var pageNo = 1+Math.floor(rect.top/pageHeight);
-                var pageTop = (pageNo-1)*pageHeight;
-
-                if (result.linksByPage[pageNo] == null)
-                    result.linksByPage[pageNo] = new Array();
-                result.linksByPage[pageNo].push({ pageNo: pageNo,
-                                                  left: rect.left,
-                                                  top: rect.top - pageTop,
-                                                  width: rect.width,
-                                                  height: rect.height,
-                                                  href: a.getAttribute("href"), });
-            }
-        }
-
-        recurse(document.body);
-
-        updateStructureReal(pageNumbers);
-        return result;
-
-
-        function recurse(node)
-        {
-            if (node.firstChild == null) {
-                var offset = DOM_nodeOffset(node);
-                var range = new Range(node.parentNode,offset,node.parentNode,offset+1);
-                var rects = Range_getClientRects(range);
-                for (var i = 0; i < rects.length; i++) {
-                    var rect = rects[i];
-
-                    var pageNo = 1+Math.floor(rect.top/pageHeight);
-                    var pageTop = (pageNo-1)*pageHeight;
-
-                    if (result.leafRectsByPage[pageNo] == null)
-                        result.leafRectsByPage[pageNo] = new Array();
-                    result.leafRectsByPage[pageNo].push({ left: rect.left,
-                                                          top: rect.top - pageTop,
-                                                          width: rect.width,
-                                                          height: rect.height });
-                }
-            }
-
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-    Outline_setReferenceTarget = function(node,itemId)
-    {
-        Selection_preserveWhileExecuting(function() {
-            refRemoved(node);
-            DOM_setAttribute(node,"href","#"+itemId);
-            refInserted(node);
-        });
-    }
-
-    Outline_detectSectionNumbering = function()
-    {
-        var sectionNumbering = detectNumbering(sections);
-        if (sectionNumbering)
-            makeNumberingExplicit(sections);
-        makeNumberingExplicit(figures);
-        makeNumberingExplicit(tables);
-        return sectionNumbering;
-    }
-
-    function detectNumbering(category)
-    {
-        for (var item = category.list.first; item != null; item = item.next) {
-
-            var firstText = null;
-            var titleNode = OutlineItem_getTitleNode(item);
-
-            if (titleNode != null)
-                firstText = findFirstTextDescendant(titleNode);
-            if (firstText != null) {
-                var regex = category.numberRegex;
-                var str = firstText.nodeValue;
-                if (str.match(category.numberRegex))
-                    return true;
-            }
-        }
-    }
-
-    function makeNumberingExplicit(category)
-    {
-        for (var item = category.list.first; item != null; item = item.next) {
-            var firstText = null;
-            var titleNode = OutlineItem_getTitleNode(item);
-
-            if (titleNode != null)
-                firstText = findFirstTextDescendant(titleNode);
-            if (firstText != null) {
-                var regex = category.numberRegex;
-                var str = firstText.nodeValue;
-                if (str.match(category.numberRegex)) {
-                    var oldValue = str;
-                    var newValue = str.replace(category.numberRegex,"");
-                    DOM_setNodeValue(firstText,newValue);
-                }
-                else {
-                    var titleNode = OutlineItem_getTitleNode(item,true);
-                    if (titleNode != null)
-                        DOM_setAttribute(titleNode,"class","Unnumbered");
-                }
-            }
-        }
-    }
-
-    // Search through the document for any elements corresponding to built-in styles that are
-    // normally latent (i.e. only included in the stylesheet if used)
-    Outline_findUsedStyles = function()
-    {
-        var used = new Object();
-        recurse(document.body);
-        return used;
-
-        function recurse(node)
-        {
-            switch (node._type) {
-            case HTML_NAV: {
-                var className = DOM_getAttribute(node,"class");
-                if ((className == "tableofcontents") ||
-                    (className == "listoffigures") ||
-                    (className == "listoftables")) {
-                    used["nav."+className] = true;
-                }
-                break;
-            }
-            case HTML_FIGCAPTION:
-            case HTML_CAPTION:
-            case HTML_H1:
-            case HTML_H2:
-            case HTML_H3:
-            case HTML_H4:
-            case HTML_H5:
-            case HTML_H6: {
-                var elementName = node.nodeName.toLowerCase();
-                var className = DOM_getAttribute(node,"class");
-                if ((className == null) || (className == ""))
-                    used[elementName] = true;
-                else if (className == "Unnumbered")
-                    used[elementName+".Unnumbered"] = true;
-                break;
-            }
-            }
-
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-})();


[09/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Position.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Position.js b/experiments/editorFramework/src/Layer0_Javascript/Position.js
deleted file mode 100644
index ce4bc18..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Position.js
+++ /dev/null
@@ -1,1164 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Position;
-var Position_assertValid;
-var Position_prev;
-var Position_next;
-var Position_trackWhileExecuting;
-var Position_closestActualNode;
-var Position_okForInsertion;
-var Position_okForMovement;
-var Position_prevMatch;
-var Position_nextMatch;
-var Position_closestMatchForwards;
-var Position_closestMatchBackwards;
-var Position_track;
-var Position_untrack;
-var Position_rectAtPos;
-var Position_noteAncestor;
-var Position_captionAncestor;
-var Position_figureOrTableAncestor;
-var Position_displayRectAtPos;
-var Position_preferTextPosition;
-var Position_preferElementPosition;
-var Position_compare;
-var Position_atPoint;
-
-(function() {
-
-    // public
-    Position = function(node,offset)
-    {
-        if (node == document.documentElement)
-            throw new Error("node is root element");
-        Object.defineProperty(this,"self",{value: {}});
-        var self = this.self;
-        self.this = this;
-        self.node = node;
-        self.offset = offset;
-        self.origOffset = offset;
-        self.tracking = 0;
-        this.posId = null;
-        this.targetX = null;
-
-        Object.defineProperty(this,"node",{
-            get: function() { return this.self.node },
-            set: setNode,
-            enumerable: true });
-        Object.defineProperty(this,"offset",{
-            get: function() { return this.self.offset },
-            set: function(value) { this.self.offset = value },
-            enumerable: true});
-        Object.defineProperty(this,"origOffset",{
-            get: function() { return this.self.origOffset },
-            set: function(value) { this.self.origOffset = value },
-            enumerable: true});
-
-        Object.preventExtensions(this);
-    }
-
-    function actuallyStartTracking(self)
-    {
-        DOM_addTrackedPosition(self.this);
-    }
-
-    function actuallyStopTracking(self)
-    {
-        DOM_removeTrackedPosition(self.this);
-    }
-
-    function startTracking(self)
-    {
-        if (self.tracking == 0)
-            actuallyStartTracking(self);
-        self.tracking++;
-    }
-
-    function stopTracking(self)
-    {
-        self.tracking--;
-        if (self.tracking == 0)
-            actuallyStopTracking(self);
-    }
-
-    function setNode(node)
-    {
-        var self = this.self;
-        if (self.tracking > 0)
-            actuallyStopTracking(self);
-
-        self.node = node;
-
-        if (self.tracking > 0)
-            actuallyStartTracking(self);
-    }
-
-    function setNodeAndOffset(self,node,offset)
-    {
-        self.this.node = node;
-        self.this.offset = offset;
-    }
-
-    // public
-    Position.prototype.toString = function()
-    {
-        var self = this.self;
-        var result;
-        if (self.node.nodeType == Node.TEXT_NODE) {
-            var extra = "";
-            if (self.offset > self.node.nodeValue.length) {
-                for (var i = self.node.nodeValue.length; i < self.offset; i++)
-                    extra += "!";
-            }
-            var id = "";
-            if (window.debugIds)
-                id = self.node._nodeId+":";
-            result = id+JSON.stringify(self.node.nodeValue.slice(0,self.offset)+extra+"|"+
-                                       self.node.nodeValue.slice(self.offset));
-        }
-        else {
-            result = "("+nodeString(self.node)+","+self.offset+")";
-        }
-        if (this.posId != null)
-            result = "["+this.posId+"]"+result;
-        return result;
-    }
-
-    function positionSpecial(pos,forwards,backwards)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        var prev = node.childNodes[offset-1];
-        var next = node.childNodes[offset];
-
-        // Moving left from the start of a caption - go to the end of the table
-        if ((node._type == HTML_CAPTION) && backwards && (prev == null))
-            return new Position(node.parentNode,node.parentNode.childNodes.length);
-
-        // Moving right from the end of a caption - go after the table
-        if ((node._type == HTML_CAPTION) && forwards && (next == null))
-            return new Position(node.parentNode.parentNode,DOM_nodeOffset(node.parentNode)+1);
-
-        // Moving left from just after a table - go to the end of the caption (if there is one)
-        if ((prev != null) && (prev._type == HTML_TABLE) && backwards) {
-            var firstChild = firstChildElement(prev);
-            if ((firstChild._type == HTML_CAPTION))
-                return new Position(firstChild,firstChild.childNodes.length);
-        }
-
-        // Moving right from just before a table - bypass the the caption (if there is one)
-        if ((next != null) && (next._type == HTML_TABLE) && forwards) {
-            var firstChild = firstChildElement(next);
-            if (firstChild._type == HTML_CAPTION)
-                return new Position(next,DOM_nodeOffset(firstChild)+1);
-        }
-
-        // Moving right from the end of a table - go to the start of the caption (if there is one)
-        if ((node._type == HTML_TABLE) && (next == null) && forwards) {
-            var firstChild = firstChildElement(node);
-            if (firstChild._type == HTML_CAPTION)
-                return new Position(firstChild,0);
-        }
-
-        // Moving left just after a caption node - skip the caption
-        if ((prev != null) && (prev._type == HTML_CAPTION) && backwards)
-            return new Position(node,offset-1);
-
-        return null;
-    }
-
-    // public
-    Position_assertValid = function(pos,description)
-    {
-        if (description == null)
-            description = "Position";
-
-        for (var ancestor = pos.node; ancestor != document.body; ancestor = ancestor.parentNode) {
-            if (ancestor == null)
-                throw new Error(description+" node "+pos.node.nodeName+" is not in tree");
-        }
-
-        var max;
-        if (pos.node.nodeType == Node.ELEMENT_NODE)
-            max = pos.node.childNodes.length;
-        else if (pos.node.nodeType == Node.TEXT_NODE)
-            max = pos.node.nodeValue.length;
-        else
-            throw new Error(description+" has invalid node type "+pos.node.nodeType);
-
-        if ((pos.offset < 0) || (pos.offset > max)) {
-            throw new Error(description+" (in "+pos.node.nodeName+") has invalid offset "+
-                            pos.offset+" (max allowed is "+max+")");
-        }
-    }
-
-    // public
-    Position_prev = function(pos)
-    {
-        if (pos.node.nodeType == Node.ELEMENT_NODE) {
-            var r = positionSpecial(pos,false,true);
-            if (r != null)
-                return r;
-            if (pos.offset == 0) {
-                return upAndBack(pos);
-            }
-            else {
-                var child = pos.node.childNodes[pos.offset-1];
-                return new Position(child,DOM_maxChildOffset(child));
-            }
-        }
-        else if (pos.node.nodeType == Node.TEXT_NODE) {
-            if (pos.offset > 0)
-                return new Position(pos.node,pos.offset-1);
-            else
-                return upAndBack(pos);
-        }
-        else {
-            return null;
-        }
-
-        function upAndBack(pos)
-        {
-            if (pos.node == pos.node.ownerDocument.body)
-                return null;
-            else
-                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
-        }
-    }
-
-    // public
-    Position_next = function(pos)
-    {
-        if (pos.node.nodeType == Node.ELEMENT_NODE) {
-            var r = positionSpecial(pos,true,false);
-            if (r != null)
-                return r;
-            if (pos.offset == pos.node.childNodes.length)
-                return upAndForwards(pos);
-            else
-                return new Position(pos.node.childNodes[pos.offset],0);
-        }
-        else if (pos.node.nodeType == Node.TEXT_NODE) {
-            if (pos.offset < pos.node.nodeValue.length)
-                return new Position(pos.node,pos.offset+1);
-            else
-                return upAndForwards(pos);
-        }
-        else {
-            return null;
-        }
-
-        function upAndForwards(pos)
-        {
-            if (pos.node == pos.node.ownerDocument.body)
-                return null;
-            else
-                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
-        }
-    }
-
-    // public
-    Position_trackWhileExecuting = function(positions,fun)
-    {
-        for (var i = 0; i < positions.length; i++)
-            startTracking(positions[i].self);
-        try {
-            return fun();
-        }
-        finally {
-            for (var i = 0; i < positions.length; i++)
-                stopTracking(positions[i].self);
-        }
-    }
-
-    // public
-    Position_closestActualNode = function(pos,preferElement)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if ((node.nodeType != Node.ELEMENT_NODE) || (node.firstChild == null))
-            return node;
-        else if (offset == 0)
-            return node.firstChild;
-        else if (offset >= node.childNodes.length)
-            return node.lastChild;
-
-        var prev = node.childNodes[offset-1];
-        var next = node.childNodes[offset];
-        if (preferElement &&
-            (next.nodeType != Node.ELEMENT_NODE) &&
-            (prev.nodeType == Node.ELEMENT_NODE)) {
-            return prev;
-        }
-        else {
-            return next;
-        }
-    }
-
-    // public
-    Position_okForInsertion = function(pos)
-    {
-        return Position_okForMovement(pos,true);
-    }
-
-    function nodeCausesLineBreak(node)
-    {
-        return ((node._type == HTML_BR) || !isInlineNode(node));
-    }
-
-    function spacesUntilNextContent(node)
-    {
-        var spaces = 0;
-        while (true) {
-            if (node.firstChild) {
-                node = node.firstChild;
-            }
-            else if (node.nextSibling) {
-                node = node.nextSibling;
-            }
-            else {
-                while ((node.parentNode != null) && (node.parentNode.nextSibling == null)) {
-                    node = node.parentNode;
-                    if (nodeCausesLineBreak(node))
-                        return null;
-                }
-                if (node.parentNode == null)
-                    node = null;
-                else
-                    node = node.parentNode.nextSibling;
-            }
-
-            if ((node == null) || nodeCausesLineBreak(node))
-                return null;
-            if (isOpaqueNode(node))
-                return spaces;
-            if (node.nodeType == Node.TEXT_NODE) {
-                if (isWhitespaceTextNode(node)) {
-                    spaces += node.nodeValue.length;
-                }
-                else {
-                    var matches = node.nodeValue.match(/^\s+/);
-                    if (matches == null)
-                        return spaces;
-                    spaces += matches[0].length;
-                    return spaces;
-                }
-            }
-        }
-    }
-
-    // public
-    Position_okForMovement = function(pos,insertion)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        var type = node._type;
-
-        if (isOpaqueNode(node))
-            return false;
-
-        for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) {
-            var ancestorType = node._type;
-            if (ancestorType == HTML_FIGCAPTION)
-                break;
-            else if (ancestorType == HTML_FIGURE)
-                return false;
-        }
-
-        if (node.nodeType == Node.TEXT_NODE) {
-            var value = node.nodeValue;
-
-            // If there are multiple adjacent text nodes, consider them as one (adjusting the
-            // offset appropriately)
-
-            var firstNode = node;
-            var lastNode = node;
-
-            while ((firstNode.previousSibling != null) &&
-                   (firstNode.previousSibling.nodeType == Node.TEXT_NODE)) {
-                firstNode = firstNode.previousSibling;
-                value = firstNode.nodeValue + value;
-                offset += firstNode.nodeValue.length;
-            }
-
-            while ((lastNode.nextSibling != null) &&
-                   (lastNode.nextSibling.nodeType == Node.TEXT_NODE)) {
-                lastNode = lastNode.nextSibling;
-                value += lastNode.nodeValue;
-            }
-
-            var prevChar = value.charAt(offset-1);
-            var nextChar = value.charAt(offset);
-            var havePrevChar = ((prevChar != null) && !isWhitespaceString(prevChar));
-            var haveNextChar = ((nextChar != null) && !isWhitespaceString(nextChar));
-            if (havePrevChar && haveNextChar) {
-                var prevCode = value.charCodeAt(offset-1);
-                var nextCode = value.charCodeAt(offset);
-                if ((prevCode >= 0xD800) && (prevCode <= 0xDBFF) &&
-                    (nextCode >= 0xDC00) && (nextCode <= 0xDFFF)) {
-                    return false; // In middle of surrogate pair
-                }
-                return true;
-            }
-
-            if (isWhitespaceString(value)) {
-                if (offset == 0) {
-                    if ((node == firstNode) &&
-                        (firstNode.previousSibling == null) && (lastNode.nextSibling == null))
-                        return true;
-                    if ((node.nextSibling != null) && (node.nextSibling._type == HTML_BR))
-                        return true;
-                    if ((node.firstChild == null) &&
-                        (node.previousSibling == null) &&
-                        (node.nextSibling == null)) {
-                        return true;
-                    }
-                    if (insertion && (node.previousSibling != null) &&
-                        isInlineNode(node.previousSibling) &&
-                        !isOpaqueNode(node.previousSibling) &&
-                        (node.previousSibling._type != HTML_BR))
-                        return true;
-                }
-                return false;
-            }
-
-            if (insertion)
-                return true;
-
-            var precedingText = value.substring(0,offset);
-            if (isWhitespaceString(precedingText)) {
-                return (haveNextChar &&
-                        ((node.previousSibling == null) ||
-                         (node.previousSibling._type == HTML_BR) ||
-                         isNoteNode(node.previousSibling) ||
-                         (isParagraphNode(node.previousSibling)) ||
-                         (getNodeText(node.previousSibling).match(/\s$/)) ||
-                         isItemNumber(node.previousSibling) ||
-                         ((precedingText.length > 0))));
-            }
-
-            var followingText = value.substring(offset);
-            if (isWhitespaceString(followingText)) {
-                return (havePrevChar &&
-                        ((node.nextSibling == null) ||
-                         isNoteNode(node.nextSibling) ||
-                         (followingText.length > 0) ||
-                         (spacesUntilNextContent(node) != 0)));
-            }
-
-            return (havePrevChar || haveNextChar);
-        }
-        else if (node.nodeType == Node.ELEMENT_NODE) {
-            if (node.firstChild == null) {
-                switch (type) {
-                case HTML_LI:
-                case HTML_TH:
-                case HTML_TD:
-                    return true;
-                default:
-                    if (PARAGRAPH_ELEMENTS[type])
-                        return true;
-                    else
-                        break;
-                }
-            }
-
-            var prevNode = node.childNodes[offset-1];
-            var nextNode = node.childNodes[offset];
-            var prevType = (prevNode != null) ? prevNode._type : 0;
-            var nextType = (nextNode != null) ? nextNode._type : 0;
-
-            var prevIsNote = (prevNode != null) && isNoteNode(prevNode);
-            var nextIsNote = (nextNode != null) && isNoteNode(nextNode);
-            if (((nextNode == null) || !nodeHasContent(nextNode)) && prevIsNote)
-                return true;
-            if (((prevNode == null) || !nodeHasContent(prevNode)) && nextIsNote)
-                return true;
-            if (prevIsNote && nextIsNote)
-                return true;
-
-            if ((prevNode == null) && (nextNode == null) &&
-                (CONTAINERS_ALLOWING_CHILDREN[type] ||
-                (isInlineNode(node) && !isOpaqueNode(node) && (type != HTML_BR))))
-                return true;
-
-            if ((prevNode != null) && isSpecialBlockNode(prevNode))
-                return true;
-            if ((nextNode != null) && isSpecialBlockNode(nextNode))
-                return true;
-
-            if ((nextNode != null) && isItemNumber(nextNode))
-                return false;
-            if ((prevNode != null) && isItemNumber(prevNode))
-                return ((nextNode == null) || isWhitespaceTextNode(nextNode));
-
-            if ((nextNode != null) && (nextType == HTML_BR))
-                return ((prevType == 0) || (prevType != HTML_TEXT));
-
-            if ((prevNode != null) && (isOpaqueNode(prevNode) || (prevType == HTML_TABLE))) {
-
-                switch (nextType) {
-                case 0:
-                case HTML_TEXT:
-                case HTML_TABLE:
-                    return true;
-                default:
-                    return isOpaqueNode(nextNode);
-                }
-            }
-            if ((nextNode != null) && (isOpaqueNode(nextNode) || (nextType == HTML_TABLE))) {
-                switch (prevType) {
-                case 0:
-                case HTML_TEXT:
-                case HTML_TABLE:
-                    return true;
-                default:
-                    return isOpaqueNode(prevNode);
-                }
-            }
-        }
-
-        return false;
-    }
-
-    Position_prevMatch = function(pos,fun)
-    {
-        do {
-            pos = Position_prev(pos);
-        } while ((pos != null) && !fun(pos));
-        return pos;
-    }
-
-    Position_nextMatch = function(pos,fun)
-    {
-        do {
-            pos = Position_next(pos);
-        } while ((pos != null) && !fun(pos));
-        return pos;
-    }
-
-    function findEquivalentValidPosition(pos,fun)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if (node.nodeType == Node.ELEMENT_NODE) {
-            var before = node.childNodes[offset-1];
-            var after = node.childNodes[offset];
-            if ((before != null) && (before.nodeType == Node.TEXT_NODE)) {
-                var candidate = new Position(before,before.nodeValue.length);
-                if (fun(candidate))
-                    return candidate;
-            }
-            if ((after != null) && (after.nodeType == Node.TEXT_NODE)) {
-                var candidate = new Position(after,0);
-                if (fun(candidate))
-                    return candidate;
-            }
-        }
-
-        if ((pos.node.nodeType == Node.TEXT_NODE) &&
-            isWhitespaceString(pos.node.nodeValue.slice(pos.offset))) {
-            var str = pos.node.nodeValue;
-            var whitespace = str.match(/\s+$/);
-            if (whitespace) {
-                var adjusted = new Position(pos.node,
-                                            str.length - whitespace[0].length + 1);
-                return adjusted;
-            }
-        }
-        return pos;
-    }
-
-    // public
-    Position_closestMatchForwards = function(pos,fun)
-    {
-        if (pos == null)
-            return null;
-
-        if (!fun(pos))
-            pos = findEquivalentValidPosition(pos,fun);
-
-        if (fun(pos))
-            return pos;
-
-        var next = Position_nextMatch(pos,fun);
-        if (next != null)
-            return next;
-
-        var prev = Position_prevMatch(pos,fun);
-        if (prev != null)
-            return prev;
-
-        return new Position(document.body,document.body.childNodes.length);
-    }
-
-    // public
-    Position_closestMatchBackwards = function(pos,fun)
-    {
-        if (pos == null)
-            return null;
-
-        if (!fun(pos))
-            pos = findEquivalentValidPosition(pos,fun);
-
-        if (fun(pos))
-            return pos;
-
-        var prev = Position_prevMatch(pos,fun);
-        if (prev != null)
-            return prev;
-
-        var next = Position_nextMatch(pos,fun);
-        if (next != null)
-            return next;
-
-        return new Position(document.body,0);
-    }
-
-    Position_track = function(pos)
-    {
-        startTracking(pos.self);
-    }
-
-    Position_untrack = function(pos)
-    {
-        stopTracking(pos.self);
-    }
-
-    Position_rectAtPos = function(pos)
-    {
-        if (pos == null)
-            return null;
-        var range = new Range(pos.node,pos.offset,pos.node,pos.offset);
-        var rects = Range_getClientRects(range);
-
-        if ((rects.length > 0) && !rectIsEmpty(rects[0])) {
-            return rects[0];
-        }
-
-        if (isParagraphNode(pos.node) && (pos.offset == 0)) {
-            var rect = pos.node.getBoundingClientRect();
-            if (!rectIsEmpty(rect))
-                return rect;
-        }
-
-        return null;
-    }
-
-    function posAtStartOfParagraph(pos,paragraph)
-    {
-        return ((pos.node == paragraph.node) &&
-                (pos.offset == paragraph.startOffset));
-    }
-
-    function posAtEndOfParagraph(pos,paragraph)
-    {
-        return ((pos.node == paragraph.node) &&
-                (pos.offset == paragraph.endOffset));
-    }
-
-    function zeroWidthRightRect(rect)
-    {
-        return { left: rect.right, // 0 width
-                 right: rect.right,
-                 top: rect.top,
-                 bottom: rect.bottom,
-                 width: 0,
-                 height: rect.height };
-    }
-
-    function zeroWidthLeftRect(rect)
-    {
-        return { left: rect.left,
-                 right: rect.left, // 0 width
-                 top: rect.top,
-                 bottom: rect.bottom,
-                 width: 0,
-                 height: rect.height };
-    }
-
-    function zeroWidthMidRect(rect)
-    {
-        var mid = rect.left + rect.width/2;
-        return { left: mid,
-                 right: mid, // 0 width
-                 top: rect.top,
-                 bottom: rect.bottom,
-                 width: 0,
-                 height: rect.height };
-    }
-
-    Position_noteAncestor = function(pos)
-    {
-        var node = Position_closestActualNode(pos);
-        for (; node != null; node = node.parentNode) {
-            if (isNoteNode(node))
-                return node;
-        }
-        return null;
-    }
-
-    Position_captionAncestor = function(pos)
-    {
-        var node = Position_closestActualNode(pos);
-        for (; node != null; node = node.parentNode) {
-            if ((node._type == HTML_FIGCAPTION) || (node._type == HTML_CAPTION))
-                return node;
-        }
-        return null;
-    }
-
-    Position_figureOrTableAncestor = function(pos)
-    {
-        var node = Position_closestActualNode(pos);
-        for (; node != null; node = node.parentNode) {
-            if ((node._type == HTML_FIGURE) || (node._type == HTML_TABLE))
-                return node;
-        }
-        return null;
-    }
-
-    function exactRectAtPos(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if (node.nodeType == Node.ELEMENT_NODE) {
-            if (offset > node.childNodes.length)
-                throw new Error("Invalid offset: "+offset+" of "+node.childNodes.length);
-
-            var before = node.childNodes[offset-1];
-            var after = node.childNodes[offset];
-
-            // Cursor is immediately before table -> return table rect
-            if ((before != null) && isSpecialBlockNode(before))
-                return zeroWidthRightRect(before.getBoundingClientRect());
-
-            // Cursor is immediately after table -> return table rect
-            else if ((after != null) && isSpecialBlockNode(after))
-                return zeroWidthLeftRect(after.getBoundingClientRect());
-
-            // Start of empty paragraph
-            if ((node.nodeType == Node.ELEMENT_NODE) && (offset == 0) &&
-                isParagraphNode(node) && !nodeHasContent(node)) {
-                return zeroWidthLeftRect(node.getBoundingClientRect());
-            }
-
-            return null;
-        }
-        else if (node.nodeType == Node.TEXT_NODE) {
-            // First see if the client rects returned by the range gives us a valid value. This
-            // won't be the case if the cursor is surrounded by both sides on whitespace.
-            var result = rectAtRightOfRange(new Range(node,offset,node,offset));
-            if (result != null)
-                return result;
-
-            if (offset > 0) {
-                // Try and get the rect of the previous character; the cursor goes after that
-                var result = rectAtRightOfRange(new Range(node,offset-1,node,offset));
-                if (result != null)
-                    return result;
-            }
-
-            return null;
-        }
-        else {
-            return null;
-        }
-
-        function rectAtRightOfRange(range)
-        {
-            var rects = Range_getClientRects(range);
-            if ((rects == null) || (rects.length == 0) || (rects[rects.length-1].height == 0))
-                return null;
-            return zeroWidthRightRect(rects[rects.length-1]);
-        }
-    }
-
-    function tempSpaceRect(parentNode,nextSibling)
-    {
-        var space = DOM_createTextNode(document,String.fromCharCode(160));
-        DOM_insertBefore(parentNode,space,nextSibling);
-        var range = new Range(space,0,space,1);
-        var rects = Range_getClientRects(range);
-        DOM_deleteNode(space);
-        if (rects.length > 0)
-            return rects[0];
-        else
-            return nil;
-    }
-
-    Position_displayRectAtPos = function(pos)
-    {
-        rect = exactRectAtPos(pos);
-        if (rect != null)
-            return rect;
-
-        var noteNode = Position_noteAncestor(pos);
-        if ((noteNode != null) && !nodeHasContent(noteNode)) // In empty footnote or endnote
-            return zeroWidthMidRect(noteNode.getBoundingClientRect());
-
-        // If we're immediately before or after a footnote or endnote, calculate the rect by
-        // temporarily inserting a space character, and getting the rect at the start of that.
-        // This avoids us instead getting a rect inside the note, which is what would otherwise
-        // happen if there was no adjacent text node outside the note.
-        if ((pos.node.nodeType == Node.ELEMENT_NODE)) {
-            var before = pos.node.childNodes[pos.offset-1];
-            var after = pos.node.childNodes[pos.offset];
-            if (((before != null) && isNoteNode(before)) ||
-                ((after != null) && isNoteNode(after))) {
-                var rect = tempSpaceRect(pos.node,pos.node.childNodes[pos.offset]);
-                if (rect != null)
-                    return zeroWidthLeftRect(rect);
-            }
-        }
-
-        var captionNode = Position_captionAncestor(pos);
-        if ((captionNode != null) && !nodeHasContent(captionNode)) {
-            // Even if an empty caption has generated content (e.g. "Figure X: ") preceding it,
-            // we can't directly get the rect of that generated content. So we temporarily insert
-            // a text node containing a single space character, get the position to the right of
-            // that character, and then remove the text node.
-            var rect = tempSpaceRect(captionNode,null);
-            if (rect != null)
-                return zeroWidthRightRect(rect);
-        }
-
-        var paragraph = Text_findParagraphBoundaries(pos);
-
-        var backRect = null;
-        for (var backPos = pos; backPos != null; backPos = Position_prev(backPos)) {
-            backRect = exactRectAtPos(backPos);
-            if ((backRect != null) || posAtStartOfParagraph(backPos,paragraph))
-                break;
-        }
-
-        var forwardRect = null;
-        for (var forwardPos = pos; forwardPos != null; forwardPos = Position_next(forwardPos)) {
-            forwardRect = exactRectAtPos(forwardPos);
-            if ((forwardRect != null) || posAtEndOfParagraph(forwardPos,paragraph))
-                break;
-        }
-
-        if (backRect != null) {
-            return backRect;
-        }
-        else if (forwardRect != null) {
-            return forwardRect;
-        }
-        else {
-            // Fallback, e.g. for empty LI elements
-            var node = pos.node;
-            if (node.nodeType == Node.TEXT_NODE)
-                node = node.parentNode;
-            return zeroWidthLeftRect(node.getBoundingClientRect());
-        }
-    }
-
-    Position_equal = function(a,b)
-    {
-        if ((a == null) && (b == null))
-            return true;
-        if ((a != null) && (b != null) &&
-            (a.node == b.node) && (a.offset == b.offset))
-            return true;
-        return false;
-    }
-
-    Position_preferTextPosition = function(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if (node.nodeType == Node.ELEMENT_NODE) {
-            var before = node.childNodes[offset-1];
-            var after = node.childNodes[offset];
-            if ((before != null) && (before.nodeType == Node.TEXT_NODE))
-                return new Position(before,before.nodeValue.length);
-            if ((after != null) && (after.nodeType == Node.TEXT_NODE))
-                return new Position(after,0);
-        }
-        return pos;
-    }
-
-    Position_preferElementPosition = function(pos)
-    {
-        if (pos.node.nodeType == Node.TEXT_NODE) {
-            if (pos.node.parentNode == null)
-                throw new Error("Position "+pos+" has no parent node");
-            if (pos.offset == 0)
-                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
-            if (pos.offset == pos.node.nodeValue.length)
-                return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
-        }
-        return pos;
-    }
-
-    Position_compare = function(first,second)
-    {
-        if ((first.node == second.node) && (first.offset == second.offset))
-            return 0;
-
-        var doc = first.node.ownerDocument;
-        if ((first.node.parentNode == null) && (first.node != doc.documentElement))
-            throw new Error("First node has been removed from document");
-        if ((second.node.parentNode == null) && (second.node != doc.documentElement))
-            throw new Error("Second node has been removed from document");
-
-        if (first.node == second.node)
-            return first.offset - second.offset;
-
-        var firstParent = null;
-        var firstChild = null;
-        var secondParent = null;
-        var secondChild = null;
-
-        if (second.node.nodeType == Node.ELEMENT_NODE) {
-            secondParent = second.node;
-            secondChild = second.node.childNodes[second.offset];
-        }
-        else {
-            secondParent = second.node.parentNode;
-            secondChild = second.node;
-        }
-
-        if (first.node.nodeType == Node.ELEMENT_NODE) {
-            firstParent = first.node;
-            firstChild = first.node.childNodes[first.offset];
-        }
-        else {
-            firstParent = first.node.parentNode;
-            firstChild = first.node;
-            if (firstChild == secondChild)
-                return 1;
-        }
-
-        var firstC = firstChild;
-        var firstP = firstParent;
-        while (firstP != null) {
-
-            var secondC = secondChild;
-            var secondP = secondParent;
-            while (secondP != null) {
-
-                if (firstP == secondC)
-                    return 1;
-
-                if (firstP == secondP) {
-                    // if secondC is last child, firstC must be secondC or come before it
-                    if (secondC == null)
-                        return -1;
-                    for (var n = firstC; n != null; n = n.nextSibling) {
-                        if (n == secondC)
-                            return -1;
-                    }
-                    return 1;
-                }
-
-                secondC = secondP;
-                secondP = secondP.parentNode;
-            }
-
-            firstC = firstP;
-            firstP = firstP.parentNode;
-        }
-        throw new Error("Could not find common ancestor");
-    }
-
-    // This function works around a bug in WebKit where caretRangeFromPoint sometimes returns an
-    // incorrect node (the last text node in the document). In a previous attempt to fix this bug,
-    // we first checked if the point was in the elements bounding rect, but this meant that it
-    // wasn't possible to place the cursor at the nearest node, if the click location was not
-    // exactly on a node.
-
-    // Now we instead check to see if the result of elementFromPoint is the same as the parent node
-    // of the text node returned by caretRangeFromPoint. If it isn't, then we assume that the latter
-    // result is incorrect, and return null.
-
-    // In the circumstances where this bug was observed, the last text node in the document was
-    // being returned from caretRangeFromPoint in some cases. In the typical case, this is going to
-    // be inside a paragraph node, but elementNodeFromPoint was returning the body element. The
-    // check we do now comparing the results of the two functions fixes this case, but won't work as
-    // intended if the document's last text node is a direct child of the body (as it may be in some
-    // HTML documents that users open).
-
-    function posOutsideSelection(pos)
-    {
-        pos = Position_preferElementPosition(pos);
-
-        if (!isSelectionSpan(pos.node))
-            return pos;
-
-        if (pos.offset == 0)
-            return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
-        else if (pos.offset == pos.node.childNodes.length)
-            return new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
-        else
-            return pos;
-    }
-
-    Position_atPoint = function(x,y)
-    {
-        // In general, we can use document.caretRangeFromPoint(x,y) to determine the location of the
-        // cursor based on screen coordinates. However, this doesn't work if the screen coordinates
-        // are outside the bounding box of the document's body. So when this is true, we find either
-        // the first or last non-whitespace text node, calculate a y value that is half-way between
-        // the top and bottom of its first or last rect (respectively), and use that instead. This
-        // results in the cursor being placed on the first or last line when the user taps outside
-        // the document bounds.
-
-        var bodyRect = document.body.getBoundingClientRect();
-        var boundaryRect = null;
-        if (y <= bodyRect.top)
-            boundaryRect = findFirstTextRect();
-        else if (y >= bodyRect.bottom)
-            boundaryRect = findLastTextRect();
-
-        if (boundaryRect != null)
-            y = boundaryRect.top + boundaryRect.height/2;
-
-        // We get here if the coordinates are inside the document's bounding rect, or if getting the
-        // position from the first or last rect failed for some reason.
-
-        var range = document.caretRangeFromPoint(x,y);
-        if (range == null)
-            return null;
-
-        var pos = new Position(range.startContainer,range.startOffset);
-        pos = Position_preferElementPosition(pos);
-
-        if (pos.node.nodeType == Node.ELEMENT_NODE) {
-            var outside = posOutsideSelection(pos);
-            var prev = outside.node.childNodes[outside.offset-1];
-            var next = outside.node.childNodes[outside.offset];
-
-            if ((prev != null) && nodeMayContainPos(prev) && elementContainsPoint(prev,x,y))
-                return new Position(prev,0);
-
-            if ((next != null) && nodeMayContainPos(next) && elementContainsPoint(next,x,y))
-                return new Position(next,0);
-
-            if (next != null) {
-                var nextNode = outside.node;
-                var nextOffset = outside.offset+1;
-
-                if (isSelectionSpan(next) && (next.firstChild != null)) {
-                    nextNode = next;
-                    nextOffset = 1;
-                    next = next.firstChild;
-                }
-
-                if ((next != null) && isEmptyNoteNode(next)) {
-                    var rect = next.getBoundingClientRect();
-                    if (x > rect.right)
-                        return new Position(nextNode,nextOffset);
-                }
-            }
-        }
-
-        pos = adjustPositionForFigure(pos);
-
-        return pos;
-    }
-
-    // This is used for nodes that can potentially be the right match for a hit test, but for
-    // which caretRangeFromPoint() returns the wrong result
-    function nodeMayContainPos(node)
-    {
-        return ((node._type == HTML_IMG) || isEmptyNoteNode(node));
-    }
-
-    function elementContainsPoint(element,x,y)
-    {
-        var rect = element.getBoundingClientRect();
-        return ((x >= rect.left) && (x <= rect.right) &&
-                (y >= rect.top) && (y <= rect.bottom));
-    }
-
-    function isEmptyParagraphNode(node)
-    {
-        return ((node._type == HTML_P) &&
-                (node.lastChild != null) &&
-                (node.lastChild._type == HTML_BR) &&
-                !nodeHasContent(node));
-    }
-
-    function findLastTextRect()
-    {
-        var node = lastDescendant(document.body);
-
-        while ((node != null) &&
-               ((node.nodeType != Node.TEXT_NODE) || isWhitespaceTextNode(node))) {
-            if (isEmptyParagraphNode(node))
-                return node.getBoundingClientRect();
-            node = prevNode(node);
-        }
-
-        if (node != null) {
-            var domRange = document.createRange();
-            domRange.setStart(node,0);
-            domRange.setEnd(node,node.nodeValue.length);
-            var rects = domRange.getClientRects();
-            if ((rects != null) && (rects.length > 0))
-                return rects[rects.length-1];
-        }
-        return null;
-    }
-
-    function findFirstTextRect()
-    {
-        var node = firstDescendant(document.body);
-
-        while ((node != null) &&
-               ((node.nodeType != Node.TEXT_NODE) || isWhitespaceTextNode(node))) {
-            if (isEmptyParagraphNode(node))
-                return node.getBoundingClientRect();
-            node = nextNode(node);
-        }
-
-        if (node != null) {
-            var domRange = document.createRange();
-            domRange.setStart(node,0);
-            domRange.setEnd(node,node.nodeValue.length);
-            var rects = domRange.getClientRects();
-            if ((rects != null) && (rects.length > 0))
-                return rects[0];
-        }
-        return null;
-    }
-
-    function adjustPositionForFigure(position)
-    {
-        if (position == null)
-            return null;
-        if (position.node._type == HTML_FIGURE) {
-            var prev = position.node.childNodes[position.offset-1];
-            var next = position.node.childNodes[position.offset];
-            if ((prev != null) && (prev._type == HTML_IMG)) {
-                position = new Position(position.node.parentNode,
-                                        DOM_nodeOffset(position.node)+1);
-            }
-            else if ((next != null) && (next._type == HTML_IMG)) {
-                position = new Position(position.node.parentNode,
-                                        DOM_nodeOffset(position.node));
-            }
-        }
-        return position;
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/PostponedActions.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/PostponedActions.js b/experiments/editorFramework/src/Layer0_Javascript/PostponedActions.js
deleted file mode 100644
index d445536..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/PostponedActions.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var PostponedActions_add;
-var PostponedActions_perform;
-
-(function() {
-
-    function PostponedAction(fun,undoDisabled)
-    {
-        this.fun = fun;
-        this.undoDisabled = undoDisabled;
-    }
-
-    var actions = new Array();
-
-    PostponedActions_add = function(action)
-    {
-        actions.push(new PostponedAction(action,UndoManager_isDisabled()));
-    }
-
-    PostponedActions_perform = function()
-    {
-        var count = 0;
-        while (actions.length > 0) {
-            if (count >= 10)
-                throw new Error("Too many postponed actions");
-            var actionsToPerform = actions;
-            actions = new Array();
-            for (var i = 0; i < actionsToPerform.length; i++) {
-                var action = actionsToPerform[i];
-                if (action.undoDisabled)
-                    UndoManager_disableWhileExecuting(action.fun);
-                else
-                    action.fun();
-            }
-            count++;
-        }
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Preview.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Preview.js b/experiments/editorFramework/src/Layer0_Javascript/Preview.js
deleted file mode 100644
index 97f9bf1..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Preview.js
+++ /dev/null
@@ -1,139 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Preview_showForStyle;
-
-(function(){
-
-    var previewText =
-        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in diam \n"+
-        "mauris. Integer in lorem sit amet dolor lacinia aliquet. Cras vehicula odio \n"+
-        "non enim euismod nec congue lorem varius. Sed eu libero arcu, eget tempus \n"+
-        "augue. Vivamus varius risus ac libero sagittis eu ultricies lectus \n"+
-        "consequat. Integer gravida accumsan fermentum. Morbi erat ligula, volutpat \n"+
-        "non accumsan sed, pellentesque quis purus. Vestibulum vestibulum tincidunt \n"+
-        "lectus non pellentesque. Quisque porttitor sollicitudin tellus, id porta \n"+
-        "velit interdum sit amet. Cras quis sem orci, vel convallis magna. \n"+
-        "Pellentesque congue, libero et iaculis volutpat, enim turpis sodales dui, \n"+
-        "lobortis pharetra lectus dolor at sem. Nullam aliquam, odio ac laoreet \n"+
-        "vulputate, ligula nunc euismod leo, vel bibendum magna leo ut orci. In \n"+
-        "tortor turpis, pellentesque nec cursus ut, consequat non ipsum. Praesent \n"+
-        "venenatis, leo in pulvinar pharetra, eros nisi convallis elit, vitae luctus \n"+
-        "magna velit ut lorem."
-
-    function setTableCellContents(node)
-    {
-        if (isTableCell(node)) {
-            DOM_deleteAllChildren(node);
-            DOM_appendChild(node,DOM_createTextNode(document,"Cell contents"));
-        }
-        else {
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                setTableCellContents(child);
-        }
-    }
-
-    function showForStyle(styleId,uiName,titleText)
-    {
-        var elementName = null;
-        var className = null;
-
-        var dotPos = styleId.indexOf(".");
-        if (dotPos >= 0) {
-            elementName = styleId.substring(0,dotPos);
-            className = styleId.substring(dotPos+1);
-        }
-        else {
-            elementName = styleId;
-            className = null;
-        }
-
-        var title = DOM_createTextNode(document,titleText);
-        var text = DOM_createTextNode(document,previewText);
-
-        Selection_clear();
-        DOM_deleteAllChildren(document.body);
-
-        if (PARAGRAPH_ELEMENTS[ElementTypes[elementName]]) {
-            var paragraph1 = createParagraphElement(elementName,className);
-            var paragraph2 = createParagraphElement(elementName,className);
-            DOM_appendChild(paragraph1,title);
-            DOM_appendChild(paragraph2,text);
-            DOM_appendChild(document.body,paragraph1);
-            DOM_appendChild(document.body,paragraph2);
-
-            if (className != null) {
-                DOM_setAttribute(paragraph1,"class",className);
-                DOM_setAttribute(paragraph2,"class",className);
-            }
-        }
-        else if (elementName == "span") {
-            var p1 = DOM_createElement(document,"P");
-            var p2 = DOM_createElement(document,"P");
-            var span1 = DOM_createElement(document,"SPAN");
-            var span2 = DOM_createElement(document,"SPAN");
-
-            if (className != null) {
-                DOM_setAttribute(span1,"class",className);
-                DOM_setAttribute(span2,"class",className);
-            }
-
-            DOM_appendChild(span1,title);
-            DOM_appendChild(span2,text);
-
-            DOM_appendChild(p1,span1);
-            DOM_appendChild(p2,span2);
-
-            DOM_appendChild(document.body,p1);
-            DOM_appendChild(document.body,p2);
-        }
-        else if ((elementName == "table") || (elementName == "caption")) {
-            // FIXME: cater for different table styles
-            Selection_selectAll();
-            Tables_insertTable(3,3,"66%",true,"Table caption");
-            Selection_clear();
-            var table = document.getElementsByTagName("TABLE")[0];
-            setTableCellContents(table);
-            if ((elementName == "table") && (className != null))
-                DOM_setAttribute(table,"class",className);
-        }
-        else if ((elementName == "figure") || (elementName == "figcaption")) {
-            Selection_selectAll();
-            Figures_insertFigure("SampleFigure.svg","75%",true,"TCP 3-way handshake");
-            Selection_clear();
-        }
-        else if (elementName == "body") {
-            // We use BR here instead of separate paragraphs, since we don't want the properties
-            // for the P element to be applied
-            DOM_appendChild(document.body,title);
-            DOM_appendChild(document.body,DOM_createElement(document,"BR"));
-            DOM_appendChild(document.body,DOM_createElement(document,"BR"));
-            DOM_appendChild(document.body,text);
-        }
-
-        function createParagraphElement(elementName,className)
-        {
-            var element = DOM_createElement(document,elementName);
-            if (className != null)
-                DOM_setAttribute(element,"class",className);
-            return element;
-        }
-    }
-
-    Preview_showForStyle = showForStyle;
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/README b/experiments/editorFramework/src/Layer0_Javascript/README
deleted file mode 100644
index 10fd5f9..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/README
+++ /dev/null
@@ -1 +0,0 @@
-the javascript files doing the actual in file editing and rendering.

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Range.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Range.js b/experiments/editorFramework/src/Layer0_Javascript/Range.js
deleted file mode 100644
index 8d7c655..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Range.js
+++ /dev/null
@@ -1,566 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Range;
-
-var Range_assertValid;
-var Range_isEmpty;
-var Range_trackWhileExecuting;
-var Range_expand;
-var Range_isForwards;
-var Range_getAllNodes;
-var Range_singleNode;
-var Range_ensureInlineNodesInParagraph;
-var Range_ensureValidHierarchy;
-var Range_forwards;
-var Range_detail;
-var Range_getOutermostNodes;
-var Range_getClientRects;
-var Range_cloneContents;
-var Range_hasContent;
-var Range_getText;
-
-(function() {
-
-    Range = function(startNode,startOffset,endNode,endOffset)
-    {
-        this.start = new Position(startNode,startOffset);
-        this.end = new Position(endNode,endOffset);
-    }
-
-    Range_assertValid = function(range,description)
-    {
-        if (description == null)
-            description = "Range";
-        if (range == null)
-            throw new Error(description+" is null");
-        Position_assertValid(range.start,description+" start");
-        Position_assertValid(range.end,description+" end");
-    }
-
-    Range_isEmpty = function(range)
-    {
-        return ((range.start.node == range.end.node) &&
-                (range.start.offset == range.end.offset));
-    }
-
-    Range.prototype.toString = function()
-    {
-        return this.start.toString() + " - " + this.end.toString();
-    }
-
-    Range_trackWhileExecuting = function(range,fun)
-    {
-        if (range == null)
-            return fun();
-        else
-            return Position_trackWhileExecuting([range.start,range.end],fun);
-    }
-
-    Range_expand = function(range)
-    {
-        var doc = range.start.node.ownerDocument;
-        while ((range.start.offset == 0) && (range.start.node != doc.body)) {
-            var offset = DOM_nodeOffset(range.start.node);
-            range.start.node = range.start.node.parentNode;
-            range.start.offset = offset;
-        }
-
-        while ((range.end.offset == DOM_maxChildOffset(range.end.node)) &&
-               (range.end.node != doc.body)) {
-            var offset = DOM_nodeOffset(range.end.node);
-            range.end.node = range.end.node.parentNode;
-            range.end.offset = offset+1;
-        }
-    }
-
-    Range_isForwards = function(range)
-    {
-        return (Position_compare(range.start,range.end) <= 0);
-    }
-
-    Range_getAllNodes = function(range,atLeastOne)
-    {
-        var result = new Array();
-        var outermost = Range_getOutermostNodes(range,atLeastOne);
-        for (var i = 0; i < outermost.length; i++)
-            addRecursive(outermost[i]);
-        return result;
-
-        function addRecursive(node)
-        {
-            result.push(node);
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                addRecursive(child);
-        }
-    }
-
-    Range_singleNode = function(range)
-    {
-        return Position_closestActualNode(range.start,true);
-    }
-
-    Range_ensureInlineNodesInParagraph = function(range)
-    {
-        Range_trackWhileExecuting(range,function() {
-            var nodes = Range_getAllNodes(range,true);
-            for (var i = 0; i < nodes.length; i++)
-                Hierarchy_ensureInlineNodesInParagraph(nodes[i]);
-        });
-    }
-
-    Range_ensureValidHierarchy = function(range,allowDirectInline)
-    {
-        Range_trackWhileExecuting(range,function() {
-            var nodes = Range_getAllNodes(range,true);
-            for (var i = nodes.length-1; i >= 0; i--)
-                Hierarchy_ensureValidHierarchy(nodes[i],true,allowDirectInline);
-        });
-    }
-
-    Range_forwards = function(range)
-    {
-        if (Range_isForwards(range)) {
-            return range;
-        }
-        else {
-            var reverse = new Range(range.end.node,range.end.offset,
-                                    range.start.node,range.start.offset);
-            if (!Range_isForwards(reverse))
-                throw new Error("Both range "+range+" and its reverse are not forwards");
-            return reverse;
-        }
-    }
-
-    Range_detail = function(range)
-    {
-        if (!Range_isForwards(range)) {
-            var reverse = new Range(range.end.node,range.end.offset,
-                                    range.start.node,range.start.offset);
-            if (!Range_isForwards(reverse))
-                throw new Error("Both range "+range+" and its reverse are not forwards");
-            return Range_detail(reverse);
-        }
-
-        var detail = new Object();
-        var start = range.start;
-        var end = range.end;
-
-        // Start location
-        if (start.node.nodeType == Node.ELEMENT_NODE) {
-            detail.startParent = start.node;
-            detail.startChild = start.node.childNodes[start.offset];
-        }
-        else {
-            detail.startParent = start.node.parentNode;
-            detail.startChild = start.node;
-        }
-
-        // End location
-        if (end.node.nodeType == Node.ELEMENT_NODE) {
-            detail.endParent = end.node;
-            detail.endChild = end.node.childNodes[end.offset];
-        }
-        else if (end.offset == 0) {
-            detail.endParent = end.node.parentNode;
-            detail.endChild = end.node;
-        }
-        else {
-            detail.endParent = end.node.parentNode;
-            detail.endChild = end.node.nextSibling;
-        }
-
-        // Common ancestor
-        var startP = detail.startParent;
-        var startC = detail.startChild;
-        while (startP != null) {
-            var endP = detail.endParent;
-            var endC = detail.endChild
-            while (endP != null) {
-                if (startP == endP) {
-                    detail.commonAncestor = startP;
-                    detail.startAncestor = startC;
-                    detail.endAncestor = endC;
-                    // Found it
-                    return detail;
-                }
-                endC = endP;
-                endP = endP.parentNode;
-            }
-            startC = startP;
-            startP = startP.parentNode;
-        }
-        throw new Error("Start and end of range have no common ancestor");
-    }
-
-    Range_getOutermostNodes = function(range,atLeastOne,info)
-    {
-        var beforeNodes = new Array();
-        var middleNodes = new Array();
-        var afterNodes = new Array();
-
-        if (info != null) {
-            info.beginning = beforeNodes;
-            info.middle = middleNodes;
-            info.end = afterNodes;
-        }
-
-        if (Range_isEmpty(range))
-            return atLeastOne ? [Range_singleNode(range)] : [];
-
-        // Note: start and end are *points* - they are always *in between* nodes or characters, never
-        // *at* a node or character.
-        // Everything after the end point is excluded from the selection
-        // Everything after the start point, but before the end point, is included in the selection
-
-        // We use (parent,child) pairs so that we have a way to represent a point that comes after all
-        // the child nodes in a container - in which case the child is null. The parent, however, is
-        // always non-null;
-
-        var detail = Range_detail(range);
-        if (detail.commonAncestor == null)
-            return atLeastOne ? [Range_singleNode(range)] : [];
-        var startParent = detail.startParent;
-        var startChild = detail.startChild;
-        var endParent = detail.endParent;
-        var endChild = detail.endChild;
-        var commonParent = detail.commonAncestor;
-        var startAncestor = detail.startAncestor;
-        var endAncestor = detail.endAncestor;
-
-        // Add start nodes
-        var topParent = startParent;
-        var topChild = startChild;
-        while (topParent != commonParent) {
-            if (topChild != null)
-                beforeNodes.push(topChild);
-
-            while (((topChild == null) || (topChild.nextSibling == null)) &&
-                   (topParent != commonParent)) {
-                topChild = topParent;
-                topParent = topParent.parentNode;
-            }
-            if (topParent != commonParent)
-                topChild = topChild.nextSibling;
-        }
-
-        // Add middle nodes
-        if (startAncestor != endAncestor) {
-            var c = startAncestor;
-            if ((c != null) && (c != startChild))
-                c = c.nextSibling;
-            for (; c != endAncestor; c = c.nextSibling)
-                middleNodes.push(c);
-        }
-
-        // Add end nodes
-        var bottomParent = endParent;
-        var bottomChild = endChild;
-        while (true) {
-
-            while ((getPreviousSibling(bottomParent,bottomChild) == null) &&
-                   (bottomParent != commonParent)) {
-                bottomChild = bottomParent;
-                bottomParent = bottomParent.parentNode;
-            }
-            if (bottomParent != commonParent)
-                bottomChild = getPreviousSibling(bottomParent,bottomChild);
-
-            if (bottomParent == commonParent)
-                break;
-
-            afterNodes.push(bottomChild);
-        }
-        afterNodes = afterNodes.reverse();
-
-        var result = new Array();
-
-        Array.prototype.push.apply(result,beforeNodes);
-        Array.prototype.push.apply(result,middleNodes);
-        Array.prototype.push.apply(result,afterNodes);
-
-        if (result.length == 0)
-            return atLeastOne ? [Range_singleNode(range)] : [];
-        else
-            return result;
-
-        function getPreviousSibling(parent,child)
-        {
-            if (child != null)
-                return child.previousSibling;
-            else if (parent.lastChild != null)
-                return parent.lastChild;
-            else
-                return null;
-        }
-
-        function isAncestorLocation(ancestorParent,ancestorChild,
-                                    descendantParent,descendantChild)
-        {
-            while ((descendantParent != null) &&
-                   ((descendantParent != ancestorParent) || (descendantChild != ancestorChild))) {
-                descendantChild = descendantParent;
-                descendantParent = descendantParent.parentNode;
-            }
-
-            return ((descendantParent == ancestorParent) &&
-                    (descendantChild == ancestorChild));
-        }
-    }
-
-    Range_getClientRects = function(range)
-    {
-        var nodes = Range_getOutermostNodes(range,true);
-
-        // WebKit in iOS 5.0 and 5.1 has a bug where if the selection spans multiple paragraphs,
-        // the complete rect for paragraphs other than the first is returned, instead of just the
-        // portions of it that are actually in the range. To get around this problem, we go through
-        // each text node individually and collect all the rects.
-        var result = new Array();
-        var doc = range.start.node.ownerDocument;
-        var domRange = doc.createRange();
-        for (var nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {
-            var node = nodes[nodeIndex];
-            if (node.nodeType == Node.TEXT_NODE) {
-                var startOffset = (node == range.start.node) ? range.start.offset : 0;
-                var endOffset = (node == range.end.node) ? range.end.offset : node.nodeValue.length;
-                domRange.setStart(node,startOffset);
-                domRange.setEnd(node,endOffset);
-                var rects = domRange.getClientRects();
-                for (var rectIndex = 0; rectIndex < rects.length; rectIndex++) {
-                    var rect = rects[rectIndex];
-                    if (Main_clientRectsBug) {
-                        // Apple Bug ID 14682166 - getClientRects() returns coordinates relative
-                        // to top of document, when it should instead return coordinates relative
-                        // to the current client view (that is, taking into account scroll offsets)
-                        result.push({ left: rect.left - window.scrollX,
-                                      right: rect.right - window.scrollX,
-                                      top: rect.top - window.scrollY,
-                                      bottom: rect.bottom - window.scrollY,
-                                      width: rect.width,
-                                      height: rect.height });
-                    }
-                    else {
-                        result.push(rect);
-                    }
-                }
-            }
-            else if (node.nodeType == Node.ELEMENT_NODE) {
-                result.push(node.getBoundingClientRect());
-            }
-        }
-        return result;
-    }
-
-    Range_cloneContents = function(range)
-    {
-        var nodeSet = new NodeSet();
-        var ancestorSet = new NodeSet();
-        var detail = Range_detail(range);
-        var outermost = Range_getOutermostNodes(range);
-
-        var haveContent = false;
-        for (var i = 0; i < outermost.length; i++) {
-            if (!isWhitespaceTextNode(outermost[i]))
-                haveContent = true;
-            nodeSet.add(outermost[i]);
-            for (var node = outermost[i]; node != null; node = node.parentNode)
-                ancestorSet.add(node);
-        }
-
-        if (!haveContent)
-            return new Array();
-
-        var clone = recurse(detail.commonAncestor);
-
-        var ancestor = detail.commonAncestor;
-        while (isInlineNode(ancestor)) {
-            var ancestorClone = DOM_cloneNode(ancestor.parentNode,false);
-            DOM_appendChild(ancestorClone,clone);
-            ancestor = ancestor.parentNode;
-            clone = ancestorClone;
-        }
-
-        var childArray = new Array();
-        switch (clone._type) {
-        case HTML_UL:
-        case HTML_OL:
-            childArray.push(clone);
-            break;
-        default:
-            for (var child = clone.firstChild; child != null; child = child.nextSibling)
-                childArray.push(child);
-            Formatting_pushDownInlineProperties(childArray);
-            break;
-        }
-
-        return childArray;
-
-        function recurse(parent)
-        {
-            var clone = DOM_cloneNode(parent,false);
-            for (var child = parent.firstChild; child != null; child = child.nextSibling) {
-                if (nodeSet.contains(child)) {
-                    if ((child.nodeType == Node.TEXT_NODE) &&
-                        (child == range.start.node) &&
-                        (child == range.end.node)) {
-                        var substring = child.nodeValue.substring(range.start.offset,
-                                                                  range.end.offset);
-                        DOM_appendChild(clone,DOM_createTextNode(document,substring));
-                    }
-                    else if ((child.nodeType == Node.TEXT_NODE) &&
-                             (child == range.start.node)) {
-                        var substring = child.nodeValue.substring(range.start.offset);
-                        DOM_appendChild(clone,DOM_createTextNode(document,substring));
-                    }
-                    else if ((child.nodeType == Node.TEXT_NODE) &&
-                             (child == range.end.node)) {
-                        var substring = child.nodeValue.substring(0,range.end.offset);
-                        DOM_appendChild(clone,DOM_createTextNode(document,substring));
-                    }
-                    else {
-                        DOM_appendChild(clone,DOM_cloneNode(child,true));
-                    }
-                }
-                else if (ancestorSet.contains(child)) {
-                    DOM_appendChild(clone,recurse(child));
-                }
-            }
-            return clone;
-        }
-    }
-
-    Range_hasContent = function(range)
-    {
-        var outermost = Range_getOutermostNodes(range);
-        for (var i = 0; i < outermost.length; i++) {
-            var node = outermost[i];
-            if (node.nodeType == Node.TEXT_NODE) {
-                var value = node.nodeValue;
-                if ((node == range.start.node) && (node == range.end.node)) {
-                    if (!isWhitespaceString(value.substring(range.start.offset,range.end.offset)))
-                        return true;
-                }
-                else if (node == range.start.node) {
-                    if (!isWhitespaceString(value.substring(range.start.offset)))
-                        return true;
-                }
-                else if (node == range.end.node) {
-                    if (!isWhitespaceString(value.substring(0,range.end.offset)))
-                        return true;
-                }
-                else {
-                    if (!isWhitespaceString(value))
-                        return true;
-                }
-            }
-            else if (node.nodeType == Node.ELEMENT_NODE) {
-                if (nodeHasContent(node))
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    Range_getText = function(range)
-    {
-        range = Range_forwards(range);
-
-        var start = range.start;
-        var end = range.end;
-
-        var startNode = start.node;
-        var startOffset = start.offset;
-
-        if (start.node.nodeType == Node.ELEMENT_NODE) {
-            if ((start.node.offset == start.node.childNodes.length) &&
-                (start.node.offset > 0))
-                startNode = nextNodeAfter(start.node);
-            else
-                startNode = start.node.childNodes[start.offset];
-            startOffset = 0;
-        }
-
-        var endNode = end.node;
-        var endOffset = end.offset;
-
-        if (end.node.nodeType == Node.ELEMENT_NODE) {
-            if ((end.node.offset == end.node.childNodes.length) &&
-                (end.node.offset > 0))
-                endNode = nextNodeAfter(end.node);
-            else
-                endNode = end.node.childNodes[end.offset];
-            endOffset = 0;
-        }
-
-        if ((startNode == null) || (endNode == null))
-            return "";
-
-        var components = new Array();
-        var node = startNode;
-        var significantParagraph = true;
-        while (true) {
-            if (node == null)
-                throw new Error("Cannot find end node");
-
-            if (node.nodeType == Node.TEXT_NODE) {
-
-                if (!significantParagraph && !isWhitespaceString(node.nodeValue)) {
-                    significantParagraph = true;
-                    components.push("\n");
-                }
-
-                if (significantParagraph) {
-                    var str;
-                    if ((node == startNode) && (node == endNode))
-                        str = node.nodeValue.substring(startOffset,endOffset);
-                    else if (node == startNode)
-                        str = node.nodeValue.substring(startOffset);
-                    else if (node == endNode)
-                        str = node.nodeValue.substring(0,endOffset);
-                    else
-                        str = node.nodeValue;
-                    str = str.replace(/\s+/g," ");
-                    components.push(str);
-                }
-            }
-
-            if (node == endNode)
-                break;
-
-
-            var next = nextNode(node,entering,exiting);
-            node = next;
-        }
-        return components.join("");
-
-        function entering(n)
-        {
-            if (isParagraphNode(n)) {
-                significantParagraph = true;
-                components.push("\n");
-            }
-        }
-
-        function exiting(n)
-        {
-            if (isParagraphNode(n))
-                significantParagraph = false;
-        }
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Scan.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Scan.js b/experiments/editorFramework/src/Layer0_Javascript/Scan.js
deleted file mode 100644
index e6cf4f5..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Scan.js
+++ /dev/null
@@ -1,179 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Scan_reset;
-var Scan_next;
-var Scan_addMatch;
-var Scan_showMatch;
-var Scan_replaceMatch;
-var Scan_removeMatch;
-var Scan_goToMatch;
-
-(function() {
-
-    function Match(matchId,startPos,endPos)
-    {
-        this.matchId = matchId;
-        this.startPos = startPos;
-        this.endPos = endPos;
-        this.spans = new Array();
-    }
-
-    var matchesById = new Object();
-    var nextMatchId = 1;
-
-    var curPos = null;
-    var curParagraph = null;
-
-    Scan_reset = function()
-    {
-        curPos = new Position(document.body,0);
-        curParagraph = null;
-        clearMatches();
-    }
-
-    Scan_next = function() {
-        if (curPos == null)
-            return null;
-        curPos = Text_toEndOfBoundary(curPos,"paragraph");
-        if (curPos == null)
-            return null;
-
-        curParagraph = Text_analyseParagraph(curPos);
-        if (curParagraph == null)
-            return null;
-
-        curPos = Position_nextMatch(curPos,Position_okForMovement);
-
-        var sectionId = null;
-        if (isHeadingNode(curParagraph.node) &&
-            (curParagraph.startOffset == 0) &&
-            (curParagraph.endOffset == curParagraph.node.childNodes.length)) {
-            sectionId = DOM_getAttribute(curParagraph.node,"id");
-        }
-
-        return { text: curParagraph.text,
-                 sectionId: sectionId };
-    }
-
-    Scan_addMatch = function(start,end) {
-        if (curParagraph == null)
-            throw new Error("curParagraph is null");
-        if ((start < 0) || (start > curParagraph.text.length))
-            throw new Error("invalid start");
-        if ((end < start) || (end > curParagraph.text.length))
-            throw new Error("invalid end");
-
-        var matchId = nextMatchId++;
-
-        var startRun = Paragraph_runFromOffset(curParagraph,start);
-        var endRun = Paragraph_runFromOffset(curParagraph,end);
-
-        if (startRun == null)
-            throw new Error("No start run");
-        if (endRun == null)
-            throw new Error("No end run");
-
-        var startPos = new Position(startRun.node,start - startRun.start);
-        var endPos = new Position(endRun.node,end - endRun.start);
-        Position_track(startPos);
-        Position_track(endPos);
-
-        var match = new Match(matchId,startPos,endPos);
-        matchesById[matchId] = match;
-        return matchId;
-    }
-
-    Scan_showMatch = function(matchId)
-    {
-        var match = matchesById[matchId];
-        if (match == null)
-            throw new Error("Match "+matchId+" not found");
-
-        var range = new Range(match.startPos.node,match.startPos.offset,
-                              match.endPos.node,match.endPos.offset);
-        var text = Range_getText(range);
-        Formatting_splitAroundSelection(range,true);
-        var outermost = Range_getOutermostNodes(range);
-        for (var i = 0; i < outermost.length; i++) {
-            var span = DOM_wrapNode(outermost[i],"SPAN");
-            DOM_setAttribute(span,"class",Keys.MATCH_CLASS);
-            match.spans.push(span);
-        }
-    }
-
-    Scan_replaceMatch = function(matchId,replacement)
-    {
-        var match = matchesById[matchId];
-        if (match == null)
-            throw new Error("Match "+matchId+" not found");
-
-        if (match.spans.length == 0)
-            return;
-
-        var span = match.spans[0];
-
-        Selection_preserveWhileExecuting(function() {
-            var replacementNode = DOM_createTextNode(document,replacement);
-            DOM_insertBefore(span.parentNode,replacementNode,span);
-
-            for (var i = 0; i < match.spans.length; i++)
-                DOM_deleteNode(match.spans[i]);
-
-            Formatting_mergeUpwards(replacementNode,Formatting_MERGEABLE_INLINE);
-        });
-
-        delete matchesById[matchId];
-    }
-
-    function removeSpansForMatch(match)
-    {
-        for (var i = 0; i < match.spans.length; i++)
-            DOM_removeNodeButKeepChildren(match.spans[i]);
-    }
-
-    Scan_removeMatch = function(matchId)
-    {
-        removeSpansForMatch(matchesById[matchId]);
-        delete matchesById[matchId];
-    }
-
-    Scan_goToMatch = function(matchId)
-    {
-        var match = matchesById[matchId];
-        if (match == null)
-            throw new Error("Match "+matchId+" not found");
-
-        Selection_set(match.startPos.node,match.startPos.offset,
-                      match.endPos.node,match.endPos.offset);
-        Cursor_ensurePositionVisible(match.startPos,true);
-    }
-
-    function clearMatches()
-    {
-        for (var matchId in matchesById) {
-            var match = matchesById[matchId];
-            removeSpansForMatch(match);
-            Position_untrack(match.startPos);
-            Position_untrack(match.endPos);
-        }
-
-        matchesById = new Object();
-        nextMatchId = 1;
-    }
-
-})();


[27/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/API_Layer_2/Layer2_interface.h
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/API_Layer_2/Layer2_interface.h b/experiments/editorFramework/src/API_Layer_2/Layer2_interface.h
new file mode 100644
index 0000000..042a1a7
--- /dev/null
+++ b/experiments/editorFramework/src/API_Layer_2/Layer2_interface.h
@@ -0,0 +1,480 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+#pragma once
+
+#include <QString>
+#include <QRect>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QTextStream>
+
+/**
+ * \file JSInterface.h
+ *
+ * C++ interface to the JavaScript editor library
+ *
+ * All of the core editing operations for Corinthia are implemented in the Editor library, which is
+ * written in JavaScript. This library can be used either from within a web browser, or, in the case
+ * of the Qt application, from an embedded web view. For this app, we use a QWebView instance which
+ * maintains the in-memory DOM tree of the document, and has injected into it all of the javascript
+ * code that is part of the editor library.
+ *
+ * The source code of the Editor library lives in (repository-root)/Editor/src. During build of the
+ * Qt app, all the javascript files are copied into (build-dir)/share/corinthia/js. If you wish to
+ * make changes to the javascript code, you should modify the files in the former location, as the
+ * latter files will be overwritten on every build.
+ *
+ * The purpose of JSInterface.h and JSInterface.cpp is to provide a C++ wrapper over this. All of
+ * the methods defined in the classes below (with the exception of callbacks) ultimately result in a
+ * call to QWebFrame's evaluateJavaScript() method. See the documentation for JSInterface.cpp for
+ * details.
+ *
+ * The editor library is divided into *modules*, each of which implements a specific aspect of
+ * editing functionality. For example, the Cursor module contains methods for moving the cursor
+ * around the document, and inserting or deleting text at the current cursor position. Similarly,
+ * the Tables module contains methods for inserting, deleting, and modifying tables. A separate C++
+ * class is defined for each module, and an instance of each class is maintained by the "container"
+ * class, JSInterface. When using the code here, you should do so via a JSInterface instance.
+ */
+
+#define JS_MODULE_COMMON(className) \
+Q_DISABLE_COPY(className) \
+public: \
+className(JSEvaluator *evaluator) : JSModule(evaluator) {}
+
+QTextStream& qStdOut();
+QString QRectString(QRect rect);
+
+/**
+ * Callback interface
+ *
+ * While the module classes are for making calls from C++ to JavaScript, the JSCallbacks abstract
+ * class is for responding to requests from JavaScript to invoke C++ code. This is declared here as
+ * an abstract class (that is, with all methods virtual and no implementations provided) to avoid
+ * dependencies between the code in this file and other parts of the application. The
+ * EditorJSCallbacks class in Editor.cpp provides a concrete implementation of this, which is where
+ * the actual callback functions are implemented.
+ *
+ * Callbacks are always invoked *after* the execution of a particular editor library API function,
+ * not during. The reason for this design design in the library was to enable support for web view
+ * classes that did not provide native support for callbacks (as was the case for iOS, at least at
+ * the time the library was originally written).
+ *
+ * The way that callbacks are invoked is that after each editor API call, a query is performed for a
+ * list of pending callback messages. The evaluation logic iterates through these and invokes the
+ * appropriate callback method for each. For this reason, callbacks method are all 'void' - they
+ * never return a value. Callbacks are for notification purposes only - typically telling the
+ * application to update the UI in some manner.
+ */
+class JSCallbacks
+{
+public:
+    virtual ~JSCallbacks() {}
+    virtual void debug(const QString &message) = 0;
+    virtual void addOutlineItem(const QString &itemId, const QString &type, const QString &title) = 0;
+    virtual void updateOutlineItem(const QString &itemId, const QString &title) = 0;
+    virtual void removeOutlineItem(const QString &itemId) = 0;
+    virtual void outlineUpdated() = 0;
+    virtual void setCursor(int x, int y, int width, int height) = 0;
+    virtual void setSelectionHandles(int x1, int y1, int height1, int x2, int y2, int height2) = 0;
+    virtual void setTableSelection(int x, int y, int width, int height) = 0;
+    virtual void setSelectionBounds(int left, int top, int right, int bottom) = 0;
+    virtual void clearSelectionHandlesAndCursor() = 0;
+    virtual void updateAutoCorrect() = 0;
+    virtual void error(const QString &message, const QString &operation) = 0;
+};
+
+/**
+ * The JSEvaluator abstract class provides an evaluate() method which is called (indirectly) by all
+ * of the individual module methods. As with JSCallbacks, it is defined as abstract to avoid a
+ * dependency on the code outside of this file. The EditorJSEvaluator class in Editor.cpp provides a
+ * concrete implementation of this; its evaluate() method simply calls through to the
+ * evaluateJavaScript() method of QWebView.
+ *
+ * JSEvaluator also has a callbacks() method, which must return an instance of JSCallbacks. This
+ * makes JSEvaluator the "central point of contact" between the JavaScript interface and the rest of
+ * the application, in that it provides the necessary access to call *in* to javascript, and to
+ * respond (via callbacks) to calls *out* of javascript. Upon initialisation of a document window,
+ * concrete implementations of both JSCallbacks and JSEvaluator are created, the latter maintaining
+ * a reference to the former. See Editor::Editor() for where ths is actually done.
+ */
+class JSEvaluator
+{
+public:
+    virtual ~JSEvaluator() {}
+    virtual QString evaluate(const QString &script) = 0;
+    virtual JSCallbacks *callbacks() = 0;
+};
+
+class JSAutoCorrect;
+class JSChangeTracking;
+class JSClipboard;
+class JSCursor;
+class JSEquations;
+class JSFigures;
+class JSFormatting;
+class JSInput;
+class JSLists;
+class JSMain;
+class JSMetadata;
+class JSOutline;
+class JSPreview;
+class JSScan;
+class JSSelection;
+class JSStyles;
+class JSTables;
+class JSUndoManager;
+class JSViewport;
+class EDScanParagraph;
+
+class JSError
+{
+public:
+    const QString &type() { return _type; }
+    const QString &message() { return _message; }
+    const QString &operation() { return _operation; }
+    const QString &html() { return _html; }
+
+private:
+
+    QString _type;
+    QString _message;
+    QString _operation;
+    QString _html;
+};
+
+class JSModule
+{
+    Q_DISABLE_COPY(JSModule)
+public:
+    JSModule(JSEvaluator *evaluator) : _evaluator(evaluator) {};
+protected:
+    JSEvaluator *_evaluator;
+};
+
+// Functions implemented in AutoCorrect.js
+
+class JSAutoCorrect : public JSModule
+{
+    JS_MODULE_COMMON(JSAutoCorrect)
+    void correctPrecedingWord(int numChars, const QString &replacement, bool confirmed);
+    QJsonObject getCorrection();
+    QJsonObject getCorrectionCoords();
+    void acceptCorrection();
+    void replaceCorrection(const QString &replacement);
+};
+
+// Functions implemented in ChangeTracking.js
+
+class JSChangeTracking : public JSModule
+{
+    JS_MODULE_COMMON(JSChangeTracking)
+    bool showChanges();
+    bool trackChanges();
+    void setShowChanges(bool showChanges);
+    void setTrackChanges(bool trackChanges);
+};
+
+// Functions implemented in Clipboard.js
+
+class JSClipboard : public JSModule
+{
+    JS_MODULE_COMMON(JSClipboard)
+    QJsonObject clipboardCut();
+    QJsonObject clipboardCopy();
+    void pasteHTML(const QString &html);
+    void pasteText(const QString &text);
+};
+
+// Functions implemented in Cursor.js
+
+class JSCursor : public JSModule
+{
+    JS_MODULE_COMMON(JSCursor)
+    QString positionCursor(int x, int y, bool wordBoundary);
+    QRect getCursorPosition();
+    void moveLeft();
+    void moveRight();
+    void moveToStartOfDocument();
+    void moveToEndOfDocument();
+    void insertReference(const QString &itemId);
+    void insertLink(const QString &text, const QString &url);
+    void insertCharacter(unsigned short character, bool allowInvalidPos);
+    void deleteCharacter();
+    void enterPressed();
+    QString getPrecedingWord();
+    QJsonObject getLinkProperties();
+    void setLinkProperties(QJsonObject properties);
+    void setReferenceTarget(const QString &itemId);
+    void insertFootnote(const QString &content);
+    void insertEndnote(const QString &content);
+};
+
+// Functions implemented in Equations.js
+
+class JSEquations : public JSModule
+{
+    JS_MODULE_COMMON(JSEquations)
+    void insertEquation();
+};
+
+// Functions implemented in Figures.js
+
+class JSFigures : public JSModule
+{
+    JS_MODULE_COMMON(JSFigures)
+    void insertFigure(const QString &filename, const QString &width,
+                      bool numbered, const QString &caption);
+    QString getSelectedFigureId();
+    QJsonObject getProperties(const QString &itemId);
+    void setProperties(const QString &itemId, const QString &width, const QString &src);
+    QJsonObject getGeometry(const QString &itemId);
+};
+
+// Functions implemented in Formatting.js
+
+class JSFormatting : public JSModule
+{
+    JS_MODULE_COMMON(JSFormatting)
+    QJsonObject getFormatting();
+    void applyFormattingChanges(const QString &style, QJsonObject properties);
+};
+
+// Functions implemented in Input.js
+
+class JSInput : public JSModule
+{
+    JS_MODULE_COMMON(JSInput)
+    void removePosition(int posId);
+
+    QString textInRange(int startId, int startAdjust, int endId, int endAdjust);
+    void replaceRange(int startId, int endId, const QString &text);
+    QJsonObject selectedTextRange();
+    void setSelectedTextRange(int startId, int endId);
+    QJsonObject markedTextRange();
+    void setMarkedText(const QString &text, int startOffset, int endOffset);
+    void unmarkText();
+    bool forwardSelectionAffinity();
+    void setForwardSelectionAffinity(bool forwardSelectionAffinity);
+    int positionFromPositionOffset(int posId, int offset);
+    int positionFromPositionInDirectionOffset(int posId, const QString &direction, int offset);
+    int comparePositionToPosition(int positionId, int otherId);
+    int offsetFromPositionToPosition(int fromPosition, int toPosition);
+    int positionWithinRangeFarthestInDirection(int startId, int endId, const QString &direction);
+    QJsonObject characterRangeByExtendingPositionInDirection(int positionId, const QString &direction);
+    QJsonObject firstRectForRange(int startId, int endId);
+    QJsonObject caretRectForPosition(int posId);
+    int closestPositionToPoint(int x, int y);
+    int closestPositionToPointWithinRange(int x, int y, int startId, int endId);
+    QJsonObject characterRangeAtPoint(int x, int y);
+    int positionWithinRangeAtCharacterOffset(int startId, int endId, int offset);
+    int characterOffsetOfPositionWithinRange(int positionId, int startId, int endId);
+
+    bool isPositionAtBoundaryGranularityInDirection(int posId, const QString &granularity,
+                                                    const QString &direction);
+    bool isPositionWithinTextUnitInDirection(int posId, const QString &granularity,
+                                             const QString &direction);
+    int positionFromPositionToBoundaryInDirection(int posId, const QString &granularity,
+                                                  const QString &direction);
+    QJsonObject rangeEnclosingPositionWithGranularityInDirection(int posId,
+                                                                 const QString &granularity,
+                                                                 const QString &direction);
+};
+
+// Functions implemented in Lists.js
+
+class JSLists : public JSModule
+{
+    JS_MODULE_COMMON(JSLists)
+    void increaseIndent();
+    void decreaseIndent();
+    void clearList();
+    void setUnorderedList();
+    void setOrderedList();
+};
+
+// Functions implemented in Main.js
+
+class JSMain : public JSModule
+{
+    JS_MODULE_COMMON(JSMain)
+    QString getLanguage();
+    void setLanguage(const QString &language);
+    QString setGenerator(const QString &generator);
+    bool prepareForSave();
+    QString getHTML();
+    bool isEmptyDocument();
+};
+
+// Functions implemented in Metadata.js
+
+class JSMetadata : public JSModule
+{
+    JS_MODULE_COMMON(JSMetadata)
+    QJsonObject getMetadata();
+    void setMetadata(const QJsonObject &metadata);
+};
+
+// Functions implemented in Outline.js
+
+class JSOutline : public JSModule
+{
+    JS_MODULE_COMMON(JSOutline)
+    QJsonObject getOutline();
+    void moveSection(const QString &sectionId, const QString &parentId, const QString &nextId);
+    void deleteItem(const QString &itemId);
+    void goToItem(const QString &itemId);
+    void scheduleUpdateStructure();
+    void setNumbered(const QString &itemId, bool numbered);
+    void setTitle(const QString &itemId, const QString &title);
+    void insertTableOfContents();
+    void insertListOfFigures();
+    void insertListOfTables();
+    void setPrintMode(bool printMode);
+    QJsonObject examinePrintLayout(int pageHeight);
+    bool detectSectionNumbering();
+    QJsonObject findUsedStyles();
+};
+
+// Functions implemented in Preview.js
+
+class JSPreview : public JSModule
+{
+    JS_MODULE_COMMON(JSPreview)
+    void showForStyle(const QString &styleId, const QString &uiName, const QString &title);
+};
+
+// Functions implemented in Scan.js
+
+class JSScan : public JSModule
+{
+    JS_MODULE_COMMON(JSScan)
+    void reset();
+    EDScanParagraph *next();
+    int addMatch(int start, int end);
+    void showMatch(int matchId);
+    void replaceMatch(int matchId, const QString &text);
+    void removeMatch(int matchId);
+    void goToMatch(int matchId);
+};
+
+// Functions implemented in Selection.js
+
+class JSSelection : public JSModule
+{
+    JS_MODULE_COMMON(JSSelection)
+    void update();
+    void selectAll();
+    void selectParagraph();
+    void selectWordAtCursor();
+    QString dragSelectionBegin(int x, int y, bool selectWord);
+    QString dragSelectionUpdate(int x, int y, bool selectWord);
+    QString moveStartLeft();
+    QString moveStartRight();
+    QString moveEndLeft();
+    QString moveEndRight();
+    void setSelectionStartAtCoords(int x, int y);
+    void setSelectionEndAtCoords(int x, int y);
+    void setTableSelectionEdgeAtCoords(const QString &edge, int x, int y);
+    void print();
+};
+
+// Functions implemented in Styles.js
+
+class JSStyles : public JSModule
+{
+    JS_MODULE_COMMON(JSStyles)
+    QString getCSSText();
+    void setCSSText(const QString &cssText, const QJsonObject &rules);
+    QString paragraphClass();
+    void setParagraphClass(const QString &paragraphClass);
+};
+
+// Functions implemented in Tables.js
+
+class JSTables : public JSModule
+{
+    JS_MODULE_COMMON(JSTables)
+    void insertTable(int rows, int cols, const QString &width, bool numbered,
+                     const QString &caption, const QString &className);
+    void addAdjacentRow();
+    void addAdjacentColumn();
+    void removeAdjacentRow();
+    void removeAdjacentColumn();
+    void clearCells();
+    void mergeCells();
+    void splitSelection();
+    QString getSelectedTableId();
+    QJsonObject getProperties(const QString &itemId);
+    void setProperties(const QString &itemId, const QString &width);
+    void setColWidths(const QString &itemId, const QJsonArray &colWidths);
+    QJsonObject getGeometry(const QString &itemId);
+};
+
+// Functions implemented in UndoManager.js
+
+class JSUndoManager : public JSModule
+{
+    JS_MODULE_COMMON(JSUndoManager)
+    int getLength();
+    int getIndex();
+    void setIndex(int index);
+    void undo();
+    void redo();
+    void newGroup(const QString &name);
+    QString groupType();
+};
+
+// Functions implemented in Viewport.js
+
+class JSViewport : public JSModule
+{
+    JS_MODULE_COMMON(JSViewport)
+    void setViewportWidth(int width);
+    void setTextScale(int textScale);
+};
+
+// All modules
+
+class JSInterface
+{
+    Q_DISABLE_COPY(JSInterface)
+public:
+    JSInterface(JSEvaluator *evaluator);
+    JSAutoCorrect autoCorrect;
+    JSChangeTracking changeTracking;
+    JSClipboard clipboard;
+    JSCursor cursor;
+    JSEquations equations;
+    JSFigures figures;
+    JSFormatting formatting;
+    JSInput input;
+    JSLists lists;
+    JSMain main;
+    JSMetadata metadata;
+    JSOutline outline;
+    JSPreview preview;
+    JSScan scan;
+    JSSelection selection;
+    JSStyles styles;
+    JSTables tables;
+    JSUndoManager undoManager;
+    JSViewport viewport;
+};
+
+void processCallbacks(JSEvaluator *evaluator);

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/API_Layer_2/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/API_Layer_2/README b/experiments/editorFramework/src/API_Layer_2/README
new file mode 100644
index 0000000..35baea8
--- /dev/null
+++ b/experiments/editorFramework/src/API_Layer_2/README
@@ -0,0 +1 @@
+The API will center around the current javascript

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Docformat_Layer_4/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Docformat_Layer_4/README b/experiments/editorFramework/src/Docformat_Layer_4/README
new file mode 100644
index 0000000..df39b72
--- /dev/null
+++ b/experiments/editorFramework/src/Docformat_Layer_4/README
@@ -0,0 +1 @@
+Connection to the DocFormat library

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Handling_Layer_3/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Handling_Layer_3/README b/experiments/editorFramework/src/Handling_Layer_3/README
new file mode 100644
index 0000000..b2451f3
--- /dev/null
+++ b/experiments/editorFramework/src/Handling_Layer_3/README
@@ -0,0 +1 @@
+handling is independent of the actual graphic representation.

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/license.txt
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/license.txt b/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/license.txt
new file mode 100644
index 0000000..e9c8672
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/license.txt
@@ -0,0 +1,34 @@
+Copyright (c) 2007, John Fraser  
+<http://www.attacklab.net/>  
+All rights reserved.
+
+Original Markdown copyright (c) 2004, John Gruber  
+<http://daringfireball.net/>  
+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.
+
+* Neither the name "Markdown" nor the names of its contributors may
+  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 the copyright owner
+or contributors 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.

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/showdown.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/showdown.js b/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/showdown.js
new file mode 100644
index 0000000..734dabb
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/3rdparty/showdown/showdown.js
@@ -0,0 +1,1302 @@
+//
+// showdown.js -- A javascript port of Markdown.
+//
+// Copyright (c) 2007 John Fraser.
+//
+// Original Markdown Copyright (c) 2004-2005 John Gruber
+//   <http://daringfireball.net/projects/markdown/>
+//
+// Redistributable under a BSD-style open source license.
+// See license.txt for more information.
+//
+// The full source distribution is at:
+//
+//				A A L
+//				T C A
+//				T K B
+//
+//   <http://www.attacklab.net/>
+//
+
+//
+// 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.
+//
+
+
+//
+// Showdown usage:
+//
+//   var text = "Markdown *rocks*.";
+//
+//   var converter = new Showdown.converter();
+//   var html = converter.makeHtml(text);
+//
+//   alert(html);
+//
+// Note: move the sample code to the bottom of this
+// file before uncommenting it.
+//
+
+
+//
+// Showdown namespace
+//
+var Showdown = {};
+
+//
+// converter
+//
+// Wraps all "globals" so that the only thing
+// exposed is makeHtml().
+//
+Showdown.converter = function() {
+
+//
+// Globals:
+//
+
+// 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 = 0;
+
+
+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.
+//
+
+	// Clear the global hashes. If we don't clear these, you get conflicts
+	// from other articles when generating a page which contains more than
+	// one article (e.g. an index page that shows the N most recent
+	// articles):
+	g_urls = new Array();
+	g_titles = new Array();
+	g_html_blocks = new Array();
+
+	// 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,"~");
+
+	return text;
+}
+
+
+var _StripLinkDefinitions = function(text) {
+//
+// Strips link definitions from text, stores the URLs and titles in
+// hash references.
+//
+
+	// Link defs are in the form: ^[id]: url "optional title"
+
+	/*
+		var text = text.replace(/
+				^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1
+				  [ \t]*
+				  \n?				// maybe *one* newline
+				  [ \t]*
+				<?(\S+?)>?			// url = $2
+				  [ \t]*
+				  \n?				// maybe one newline
+				  [ \t]*
+				(?:
+				  (\n*)				// any lines skipped = $3 attacklab: lookbehind removed
+				  ["(]
+				  (.+?)				// title = $4
+				  [")]
+				  [ \t]*
+				)?					// title is optional
+				(?:\n+|$)
+			  /gm,
+			  function(){...});
+	*/
+	var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,
+		function (wholeMatch,m1,m2,m3,m4) {
+			m1 = m1.toLowerCase();
+			g_urls[m1] = _EncodeAmpsAndAngles(m2);  // Link IDs are case-insensitive
+			if (m3) {
+				// Oops, found blank lines, so it's not a title.
+				// Put back the parenthetical statement we stole.
+				return m3+m4;
+			} else if (m4) {
+				g_titles[m1] = m4.replace(/"/g,"&quot;");
+			}
+			
+			// Completely remove the definition from the text
+			return "";
+		}
+	);
+
+	return text;
+}
+
+
+var _HashHTMLBlocks = function(text) {
+	// attacklab: Double up blank lines to reduce lookaround
+	text = text.replace(/\n/g,"\n\n");
+
+	// 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.
+	/*
+		var 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`
+	//
+
+	/*
+		var 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(/
+		(						// save in $1
+			\n\n				// Starting after a blank line
+			[ ]{0,3}
+			(<(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(/
+		(						// save in $1
+			\n\n				// Starting after a blank line
+			[ ]{0,3}			// attacklab: g_tab_width - 1
+			<!
+			(--[^\r]*?--\s*)+
+			>
+			[ \t]*
+			(?=\n{2,})			// followed by a blank line
+		)
+		/g,hashElement);
+	*/
+	text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \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);
+
+	// attacklab: Undo double lines (see comment at top of this function)
+	text = text.replace(/\n\n/g,"\n");
+	return text;
+}
+
+var hashElement = function(wholeMatch,m1) {
+	var blockText = m1;
+
+	// Undo double lines
+	blockText = blockText.replace(/\n\n/g,"\n");
+	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;
+};
+
+var _RunBlockGamut = function(text) {
+//
+// These are all the transformations that form block-level
+// tags like paragraphs, headers, and list items.
+//
+	text = _DoHeaders(text);
+
+	// Do Horizontal Rules:
+	var key = hashBlock("<hr />");
+	text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
+	text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);
+	text = text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);
+
+	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);
+
+	return text;
+}
+
+
+var _RunSpanGamut = function(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;
+}
+
+var _EscapeSpecialCharsWithinTagAttributes = function(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.
+	var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
+
+	text = text.replace(regex, function(wholeMatch) {
+		var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");
+		tag = escapeCharacters(tag,"\\`*_");
+		return tag;
+	});
+
+	return text;
+}
+
+var _DoAnchors = function(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,_DoAnchors_callback);
+	*/
+	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
+			[ \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;
+}
+
+var writeAnchorTag = function(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[link_id] != undefined) {
+			url = g_urls[link_id];
+			if (g_titles[link_id] != undefined) {
+				title = g_titles[link_id];
+			}
+		}
+		else {
+			if (whole_match.search(/\(\s*\)$/m)>-1) {
+				// Special case for explicit empty url
+				url = "";
+			} else {
+				return whole_match;
+			}
+		}
+	}	
+	
+	url = escapeCharacters(url,"*_");
+	var result = "<a href=\"" + url + "\"";
+	
+	if (title != "") {
+		title = title.replace(/"/g,"&quot;");
+		title = escapeCharacters(title,"*_");
+		result +=  " title=\"" + title + "\"";
+	}
+	
+	result += ">" + link_text + "</a>";
+	
+	return result;
+}
+
+
+var _DoImages = function(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;
+}
+
+var writeImageTag = function(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[link_id] != undefined) {
+			url = g_urls[link_id];
+			if (g_titles[link_id] != undefined) {
+				title = g_titles[link_id];
+			}
+		}
+		else {
+			return whole_match;
+		}
+	}	
+	
+	alt_text = alt_text.replace(/"/g,"&quot;");
+	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,"&quot;");
+		title = escapeCharacters(title,"*_");
+		result +=  " title=\"" + title + "\"";
+	//}
+	
+	result += " />";
+	
+	return result;
+}
+
+
+var _DoHeaders = function(text) {
+
+	// Setext-style headers:
+	//	Header 1
+	//	========
+	//  
+	//	Header 2
+	//	--------
+	//
+	text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+		function(wholeMatch,m1){return hashBlock('<h1 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h1>");});
+
+	text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
+		function(matchFound,m1){return hashBlock('<h2 id="' + headerId(m1) + '">' + _RunSpanGamut(m1) + "</h2>");});
+
+	// 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 hashBlock("<h" + h_level + ' id="' + headerId(m2) + '">' + _RunSpanGamut(m2) + "</h" + h_level + ">");
+		});
+
+	function headerId(m) {
+		return m.replace(/[^\w]/g, '').toLowerCase();
+	}
+	return text;
+}
+
+// This declaration keeps Dojo compressor from outputting garbage:
+var _ProcessListItems;
+
+var _DoLists = function(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";
+
+			// Turn double returns into triple returns, so that we can make a
+			// paragraph for the last item in a list, if necessary:
+			list = list.replace(/\n{2,}/g,"\n\n\n");;
+			var result = _ProcessListItems(list);
+	
+			// 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";
+			// Turn double returns into triple returns, so that we can make a
+			// paragraph for the last item in a list, if necessary:
+			var list = list.replace(/\n{2,}/g,"\n\n\n");;
+			var result = _ProcessListItems(list);
+			result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n";	
+			return result;
+		});
+	}
+
+	// attacklab: strip sentinel
+	text = text.replace(/~0/,"");
+
+	return text;
+}
+
+_ProcessListItems = function(list_str) {
+//
+//  Process the contents of a single ordered or unordered list, splitting it
+//  into individual list items.
+//
+	// 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";
+
+	/*
+		list_str = list_str.replace(/
+			(\n)?							// leading line = $1
+			(^[ \t]*)						// leading whitespace = $2
+			([*+-]|\d+[.]) [ \t]+			// list marker = $3
+			([^\r]+?						// list item text   = $4
+			(\n{1,2}))
+			(?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+))
+		/gm, function(){...});
+	*/
+	list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
+		function(wholeMatch,m1,m2,m3,m4){
+			var item = m4;
+			var leading_line = m1;
+			var leading_space = m2;
+
+			if (leading_line || (item.search(/\n{2,}/)>-1)) {
+				item = _RunBlockGamut(_Outdent(item));
+			}
+			else {
+				// Recursion for sub-lists:
+				item = _DoLists(_Outdent(item));
+				item = item.replace(/\n$/,""); // chomp(item)
+				item = _RunSpanGamut(item);
+			}
+
+			return  "<li>" + item + "</li>\n";
+		}
+	);
+
+	// attacklab: strip sentinel
+	list_str = list_str.replace(/~0/g,"");
+
+	g_list_level--;
+	return list_str;
+}
+
+
+var _DoCodeBlocks = function(text) {
+//
+//  Process Markdown `<pre><code>` blocks.
+//  
+
+	/*
+		text = text.replace(text,
+			/(?:\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 hashBlock(codeblock) + nextChar;
+		}
+	);
+
+	// attacklab: strip sentinel
+	text = text.replace(/~0/,"");
+
+	return text;
+}
+
+var hashBlock = function(text) {
+	text = text.replace(/(^\n+|\n+$)/g,"");
+	return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n";
+}
+
+
+var _DoCodeSpans = function(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;
+}
+
+
+var _EncodeCode = function(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,"&amp;");
+
+	// Do the angle bracket song and dance:
+	text = text.replace(/</g,"&lt;");
+	text = text.replace(/>/g,"&gt;");
+
+	// 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;
+}
+
+
+var _DoItalicsAndBold = function(text) {
+
+	// <strong> must go first:
+	text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,
+		"<strong>$2</strong>");
+
+	text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,
+		"<em>$2</em>");
+
+	return text;
+}
+
+
+var _DoBlockQuotes = function(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;
+}
+
+
+var _FormParagraphs = function(text) {
+//
+//  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 = new Array();
+
+	//
+	// 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
+	//
+	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");
+}
+
+
+var _EncodeAmpsAndAngles = function(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,"&amp;");
+	
+	// Encode naked <'s
+	text = text.replace(/<(?![a-z\/?\$!])/gi,"&lt;");
+	
+	return text;
+}
+
+
+var _EncodeBackslashEscapes = function(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;
+}
+
+
+var _DoAutoLinks = function(text) {
+
+	text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
+
+	// Email addresses: <ad...@domain.foo>
+
+	/*
+		text = text.replace(/
+			<
+			(?:mailto:)?
+			(
+				[-.\w]+
+				\@
+				[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+			)
+			>
+		/gi, _DoAutoLinks_callback());
+	*/
+	text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,
+		function(wholeMatch,m1) {
+			return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );
+		}
+	);
+
+	return text;
+}
+
+
+var _EncodeEmailAddress = function(addr) {
+//
+//  Input: an email address, e.g. "foo@example.com"
+//
+//  Output: the email address as a mailto link, with each character
+//	of the address encoded as either a decimal or hex entity, in
+//	the hopes of foiling most address harvesting spam bots. E.g.:
+//
+//	<a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
+//	   x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
+//	   &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
+//
+//  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
+//  mailing list: <http://tinyurl.com/yu7ue>
+//
+
+	// attacklab: why can't javascript speak hex?
+	function char2hex(ch) {
+		var hexDigits = '0123456789ABCDEF';
+		var dec = ch.charCodeAt(0);
+		return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15));
+	}
+
+	var encode = [
+		function(ch){return "&#"+ch.charCodeAt(0)+";";},
+		function(ch){return "&#x"+char2hex(ch)+";";},
+		function(ch){return ch;}
+	];
+
+	addr = "mailto:" + addr;
+
+	addr = addr.replace(/./g, function(ch) {
+		if (ch == "@") {
+		   	// this *must* be encoded. I insist.
+			ch = encode[Math.floor(Math.random()*2)](ch);
+		} else if (ch !=":") {
+			// leave ':' alone (to spot mailto: later)
+			var r = Math.random();
+			// roughly 10% raw, 45% hex, 45% dec
+			ch =  (
+					r > .9  ?	encode[2](ch)   :
+					r > .45 ?	encode[1](ch)   :
+								encode[0](ch)
+				);
+		}
+		return ch;
+	});
+
+	addr = "<a href=\"" + addr + "\">" + addr + "</a>";
+	addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part
+
+	return addr;
+}
+
+
+var _UnescapeSpecialChars = function(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;
+}
+
+
+var _Outdent = function(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;
+}
+
+var _Detab = function(text) {
+// attacklab: Detab's completely rewritten for speed.
+// In perl we could fix it by anchoring the regexp with \G.
+// In javascript we're less fortunate.
+
+	// expand first n-1 tabs
+	text = text.replace(/\t(?=\t)/g,"    "); // attacklab: g_tab_width
+
+	// replace the nth with two sentinels
+	text = text.replace(/\t/g,"~A~B");
+
+	// use the sentinel to anchor our regex so it doesn't explode
+	text = text.replace(/~B(.+?)~A/g,
+		function(wholeMatch,m1,m2) {
+			var leadingText = m1;
+			var numSpaces = 4 - leadingText.length % 4;  // attacklab: g_tab_width
+
+			// there *must* be a better way to do this:
+			for (var i=0; i<numSpaces; i++) leadingText+=" ";
+
+			return leadingText;
+		}
+	);
+
+	// clean up sentinels
+	text = text.replace(/~A/g,"    ");  // attacklab: g_tab_width
+	text = text.replace(/~B/g,"");
+
+	return text;
+}
+
+
+//
+//  attacklab: Utility functions
+//
+
+
+var escapeCharacters = function(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;
+}
+
+
+var escapeCharacters_callback = function(wholeMatch,m1) {
+	var charCodeToEscape = m1.charCodeAt(0);
+	return "~E"+charCodeToEscape+"E";
+}
+
+} // end of Showdown.converter
+
+// export
+if (typeof exports != 'undefined') exports.Showdown = Showdown;

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/AutoCorrect.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/AutoCorrect.js b/experiments/editorFramework/src/Javascript_Layer_0/AutoCorrect.js
new file mode 100644
index 0000000..a80e17d
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/AutoCorrect.js
@@ -0,0 +1,285 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var AutoCorrect_init;
+var AutoCorrect_removeListeners;
+var AutoCorrect_addCorrection;
+var AutoCorrect_removeCorrection;
+var AutoCorrect_getCorrections;
+
+var AutoCorrect_correctPrecedingWord;
+var AutoCorrect_getCorrection;
+var AutoCorrect_getCorrectionCoords;
+var AutoCorrect_acceptCorrection;
+var AutoCorrect_revertCorrection;
+var AutoCorrect_replaceCorrection;
+
+(function() {
+
+    function removeCorrectionSpan(span)
+    {
+        if (span.parentNode == null)
+            return;
+        Selection_preserveWhileExecuting(function() {
+            var firstChild = span.firstChild;
+            DOM_removeNodeButKeepChildren(span);
+            if (firstChild != null)
+                Formatting_mergeWithNeighbours(firstChild,{});
+        });
+    }
+
+    function Correction(span)
+    {
+        this.span = span;
+        this.modificationListener = function(event) {
+            if (DOM_getIgnoreMutations())
+                return;
+            PostponedActions_add(function() {
+                // This will trigger a removeCorrection() call
+                removeCorrectionSpan(span);
+            });
+        };
+    }
+
+    Correction.prototype.toString = function()
+    {
+        return this.span.getAttribute("original")+" -> "+getNodeText(this.span);
+    }
+
+    var correctionsByNode = null;
+    var correctionList = null;
+
+    // private
+    function docNodeInserted(event)
+    {
+        try {
+            recurse(event.target);
+        }
+        catch (e) {
+            Editor_error(e);
+        }
+
+        function recurse(node)
+        {
+            if (isAutoCorrectNode(node))
+                AutoCorrect_addCorrection(node);
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+    // private
+    function docNodeRemoved(event)
+    {
+        try {
+            recurse(event.target);
+        }
+        catch (e) {
+            Editor_error(e);
+        }
+
+        function recurse(node)
+        {
+            if (isAutoCorrectNode(node))
+                AutoCorrect_removeCorrection(node);
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+    AutoCorrect_init = function()
+    {
+        correctionsByNode = new NodeMap();
+        correctionList = new Array();
+        document.addEventListener("DOMNodeInserted",docNodeInserted);
+        document.addEventListener("DOMNodeRemoved",docNodeRemoved);
+    }
+
+    // public (for the undo tests, when they report results)
+    AutoCorrect_removeListeners = function()
+    {
+        document.removeEventListener("DOMNodeInserted",docNodeInserted);
+        document.removeEventListener("DOMNodeRemoved",docNodeRemoved);
+    }
+
+    AutoCorrect_addCorrection = function(span)
+    {
+        var correction = new Correction(span);
+        correctionsByNode.put(span,correction);
+        correctionList.push(correction);
+        Editor_updateAutoCorrect();
+
+        span.addEventListener("DOMSubtreeModified",correction.modificationListener);
+    }
+
+    AutoCorrect_removeCorrection = function(span)
+    {
+        var correction = correctionsByNode.get(span);
+        if (correction == null)
+            throw new Error("No autocorrect entry for "+JSON.stringify(getNodeText(span)));
+
+        var index = null;
+        for (var i = 0; i < correctionList.length; i++) {
+            if (correctionList[i].span == span) {
+                index = i;
+                break;
+            }
+        }
+        if (index == null)
+            throw new Error("Correction "+correction+" not found in correctionList");
+        correctionList.splice(index,1);
+        Editor_updateAutoCorrect();
+
+        span.removeEventListener("DOMSubtreeModified",correction.modificationListener);
+        correctionsByNode.remove(span);
+    }
+
+    AutoCorrect_getCorrections = function()
+    {
+        var result = new Array();
+        for (var i = 0; i < correctionList.length; i++) {
+            var correction = correctionList[i];
+            result.push({ original: correction.span.getAttribute("original"),
+                          replacement: getNodeText(correction.span)});
+        }
+        return result;
+    }
+
+    AutoCorrect_correctPrecedingWord = function(numChars,replacement,confirmed)
+    {
+        Selection_preserveWhileExecuting(function() {
+            var selRange = Selection_get();
+            if ((selRange == null) && !Range_isEmpty(selRange))
+                return;
+
+            var node = selRange.start.node;
+            var offset = selRange.start.offset;
+            if (node.nodeType != Node.TEXT_NODE)
+                return;
+
+            var original = node.nodeValue.substring(offset-numChars,offset);
+
+            if (confirmed) {
+                DOM_replaceCharacters(node,offset-numChars,offset,replacement);
+                return;
+            }
+
+            UndoManager_newGroup("Auto-correct");
+            var before = node.nodeValue.substring(0,offset-numChars);
+            var beforeText = DOM_createTextNode(document,before);
+            var replacementText = DOM_createTextNode(document,replacement);
+            var span = DOM_createElement(document,"SPAN");
+            DOM_setAttribute(span,"class",Keys.AUTOCORRECT_CLASS);
+            DOM_setAttribute(span,"original",original);
+            DOM_appendChild(span,replacementText);
+            DOM_insertBefore(node.parentNode,beforeText,node);
+            DOM_insertBefore(node.parentNode,span,node);
+            DOM_deleteCharacters(node,0,offset);
+            // Add the new group in a postponed action, so that the change to the style element
+            // is not counted as a separate action
+            PostponedActions_add(UndoManager_newGroup);
+        });
+    }
+
+    AutoCorrect_getCorrection = function()
+    {
+        var correction = getCurrent();
+        if (correction == null)
+            return null;
+
+        return { original: correction.span.getAttribute("original"),
+                 replacement: getNodeText(correction.span) };
+    }
+
+    AutoCorrect_getCorrectionCoords = function()
+    {
+        var correction = getCurrent();
+        if (correction == null)
+            return null;
+
+        var textNode = correction.span.firstChild;
+        if ((textNode == null) || (textNode.nodeType != Node.TEXT_NODE))
+            return null;
+
+        var offset = Math.floor(textNode.nodeValue.length/2);
+        Selection_set(textNode,offset,textNode,offset);
+        Cursor_ensureCursorVisible();
+        var rect = Position_displayRectAtPos(new Position(textNode,offset));
+
+        if (rect == null) // FIXME: pos
+            throw new Error("no rect for pos "+(new Position(textNode,offset)));
+
+        if (rect == null)
+            return null;
+
+        return { x: rect.left, y: rect.top };
+    }
+
+    function getCurrent()
+    {
+        var range = Selection_get();
+        if (range != null) {
+            var endNode = Position_closestActualNode(range.end);
+            for (; endNode != null; endNode = endNode.parentNode) {
+                if (isAutoCorrectNode(endNode))
+                    return correctionsByNode.get(endNode);
+            }
+        }
+
+        if (correctionList.length > 0)
+            return correctionList[correctionList.length-1];
+
+        return null;
+    }
+
+    AutoCorrect_acceptCorrection = function()
+    {
+        UndoManager_newGroup("Accept");
+        var correction = getCurrent();
+        if (correction == null)
+            return;
+
+        removeCorrectionSpan(correction.span);
+        UndoManager_newGroup();
+    }
+
+    AutoCorrect_revertCorrection = function()
+    {
+        var correction = getCurrent();
+        if (correction == null)
+            return;
+
+        AutoCorrect_replaceCorrection(correction.span.getAttribute("original"));
+    }
+
+    AutoCorrect_replaceCorrection = function(replacement)
+    {
+        UndoManager_newGroup("Replace");
+        var correction = getCurrent();
+        if (correction == null)
+            return;
+
+        Selection_preserveWhileExecuting(function() {
+            var text = DOM_createTextNode(document,replacement);
+            DOM_insertBefore(correction.span.parentNode,text,correction.span);
+            DOM_deleteNode(correction.span);
+            Formatting_mergeWithNeighbours(text,{});
+        });
+        UndoManager_newGroup();
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/ChangeTracking.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/ChangeTracking.js b/experiments/editorFramework/src/Javascript_Layer_0/ChangeTracking.js
new file mode 100644
index 0000000..ba25a44
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/ChangeTracking.js
@@ -0,0 +1,127 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var ChangeTracking_showChanges;
+var ChangeTracking_trackChanges;
+var ChangeTracking_setShowChanges;
+var ChangeTracking_setTrackChanges;
+var ChangeTracking_acceptSelectedChanges;
+
+(function() {
+
+    var showChangesEnabled = false;
+    var trackChangesEnabled = false;
+
+    ChangeTracking_showChanges = function()
+    {
+        return showChangesEnabled;
+    }
+
+    ChangeTracking_trackChanges = function()
+    {
+        return trackChangesEnabled;
+    }
+
+    ChangeTracking_setShowChanges = function(enabled)
+    {
+        showChangesEnabled = enabled;
+    }
+
+    ChangeTracking_setTrackChanges = function(enabled)
+    {
+        trackChangesEnabled = enabled;
+    }
+
+    ChangeTracking_acceptSelectedChanges = function()
+    {
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+
+        var outermost = Range_getOutermostNodes(selRange,true);
+        var checkEmpty = new Array();
+
+        Selection_preserveWhileExecuting(function() {
+            for (var i = 0; i < outermost.length; i++) {
+                recurse(outermost[i]);
+
+                var next;
+                for (ancestor = outermost[i].parentNode; ancestor != null; ancestor = next) {
+                    next = ancestor.parentNode;
+                    if (ancestor._type == HTML_DEL) {
+                        checkEmpty.push(ancestor.parentNode);
+                        DOM_deleteNode(ancestor);
+                    }
+                    else if (ancestor._type == HTML_INS)
+                        DOM_removeNodeButKeepChildren(ancestor);
+                }
+            }
+
+            for (var i = 0; i < checkEmpty.length; i++) {
+                var node = checkEmpty[i];
+                if (node == null)
+                    continue;
+                var empty = true;
+                for (var child = node.firstChild; child != null; child = child.nextSibling) {
+                    if (!isWhitespaceTextNode(child)) {
+                        empty = false;
+                        break;
+                    }
+                }
+                if (empty) {
+                    switch (node._type) {
+                    case HTML_LI:
+                    case HTML_UL:
+                    case HTML_OL:
+                        checkEmpty.push(node.parentNode);
+                        DOM_deleteNode(node);
+                        break;
+                    }
+                }
+            }
+        });
+
+        var selRange = Selection_get();
+        if (selRange != null) {
+            var start = Position_closestMatchForwards(selRange.start,Position_okForInsertion);
+            var end = Position_closestMatchBackwards(selRange.end,Position_okForInsertion);
+            if (!Range_isForwards(new Range(start.node,start.offset,end.node,end.offset)))
+                end = Position_closestMatchForwards(selRange.end,Position_okForInsertion);
+            Selection_set(start.node,start.offset,end.node,end.offset);
+        }
+
+        function recurse(node)
+        {
+            if (node._type == HTML_DEL) {
+                checkEmpty.push(node.parentNode);
+                DOM_deleteNode(node);
+                return;
+            }
+
+            var next;
+            for (var child = node.firstChild; child != null; child = next) {
+                next = child.nextSibling;
+                recurse(child);
+            }
+
+            if (node._type == HTML_INS) {
+                DOM_removeNodeButKeepChildren(node);
+            }
+        }
+    }
+
+})();


[07/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Tables.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Tables.js b/experiments/editorFramework/src/Layer0_Javascript/Tables.js
deleted file mode 100644
index f1f27be..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Tables.js
+++ /dev/null
@@ -1,1362 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Tables_insertTable;
-var Tables_addAdjacentRow;
-var Tables_addAdjacentColumn;
-var Tables_removeAdjacentRow;
-var Tables_removeAdjacentColumn;
-var Tables_deleteRegion;
-var Tables_clearCells;
-var Tables_mergeCells;
-var Tables_splitSelection;
-var Tables_cloneRegion;
-var Tables_analyseStructure;
-var Tables_findContainingCell;
-var Tables_findContainingTable;
-var Tables_regionFromRange;
-var Tables_getSelectedTableId;
-var Tables_getProperties;
-var Tables_setProperties;
-var Tables_getColWidths;
-var Tables_setColWidths;
-var Tables_getGeometry;
-
-var Table_get;
-var Table_set;
-var Table_setRegion;
-var Table_fix;
-var Table_fixColumnWidths;
-var TableRegion_splitCells;
-
-(function() {
-
-    function Cell(element,row,col)
-    {
-        this.element = element;
-        this.row = row;
-        this.col = col;
-
-        if (element.hasAttribute("colspan"))
-            this.colspan = parseInt(element.getAttribute("colspan"));
-        else
-            this.colspan = 1;
-        if (element.hasAttribute("rowspan"))
-            this.rowspan = parseInt(element.getAttribute("rowspan"));
-        else
-            this.rowspan = 1;
-
-        if (this.colspan < 1)
-            this.colspan = 1;
-        if (this.rowspan < 1)
-            this.rowspan = 1;
-
-        this.top = this.row;
-        this.bottom = this.top + this.rowspan - 1;
-        this.left = this.col;
-        this.right = this.left + this.colspan - 1;
-    }
-
-    function Cell_setRowspan(cell,rowspan)
-    {
-        if (rowspan < 1)
-            rowspan = 1;
-        cell.rowspan = rowspan;
-        cell.bottom = cell.top + cell.rowspan - 1;
-        if (rowspan == 1)
-            DOM_removeAttribute(cell.element,"rowspan");
-        else
-            DOM_setAttribute(cell.element,"rowspan",rowspan);
-    }
-
-    function Cell_setColspan(cell,colspan)
-    {
-        if (colspan < 1)
-            colspan = 1;
-        cell.colspan = colspan;
-        cell.right = cell.left + cell.colspan - 1;
-        if (colspan == 1)
-            DOM_removeAttribute(cell.element,"colspan");
-        else
-            DOM_setAttribute(cell.element,"colspan",colspan);
-    }
-
-    function Table(element)
-    {
-        this.element = element;
-        this.row = 0;
-        this.col = 0;
-        this.cells = new Array();
-        this.numRows = 0;
-        this.numCols = 0;
-        this.translated = false;
-        this.cellsByElement = new NodeMap();
-        Table_processTable(this,element);
-    }
-
-    // public
-    Table_get = function(table,row,col)
-    {
-        if (table.cells[row] == null)
-            return null;
-        return table.cells[row][col];
-    }
-
-    // public
-    Table_set = function(table,row,col,cell)
-    {
-        if (table.numRows < row+1)
-            table.numRows = row+1;
-        if (table.numCols < col+1)
-            table.numCols = col+1;
-        if (table.cells[row] == null)
-            table.cells[row] = new Array();
-        table.cells[row][col] = cell;
-    }
-
-    // public
-    Table_setRegion = function(table,top,left,bottom,right,cell)
-    {
-        for (var row = top; row <= bottom; row++) {
-            for (var col = left; col <= right; col++) {
-                var destCell = Table_get(table,row,col);
-                DOM_deleteNode(destCell.element);
-                Table_set(table,row,col,cell);
-            }
-        }
-    }
-
-    function Table_processTable(table,node)
-    {
-        var type = node._type;
-        switch (node._type) {
-        case HTML_TD:
-        case HTML_TH: {
-            while (Table_get(table,table.row,table.col) != null)
-                table.col++;
-
-            var cell = new Cell(node,table.row,table.col);
-            table.cellsByElement.put(node,cell);
-
-            for (var r = 0; r < cell.rowspan; r++) {
-                for (var c = 0; c < cell.colspan; c++) {
-                    Table_set(table,table.row+r,table.col+c,cell);
-                }
-            }
-            table.col += cell.colspan;
-            break;
-        }
-        case HTML_TR:
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                Table_processTable(table,child);
-            table.row++;
-            table.col = 0;
-            break;
-        default:
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                Table_processTable(table,child);
-            break;
-        }
-    }
-
-    // public
-    Tables_insertTable = function(rows,cols,width,numbered,caption,className)
-    {
-        UndoManager_newGroup("Insert table");
-
-        if (rows < 1)
-            rows = 1;
-        if (cols < 1)
-            cols = 1;
-
-        var haveCaption = (caption != null) && (caption != "");
-        var table = DOM_createElement(document,"TABLE");
-
-        if (width != null)
-            DOM_setStyleProperties(table,{"width": width});
-
-        if (className != null)
-            DOM_setAttribute(table,"class",className);
-
-        // Caption comes first
-        if (haveCaption) {
-            var tableCaption = DOM_createElement(document,"CAPTION");
-            DOM_appendChild(tableCaption,DOM_createTextNode(document,caption));
-            DOM_appendChild(table,tableCaption);
-        }
-
-        // Set equal column widths
-        var colWidth = Math.round(100/cols)+"%";
-        for (var c = 0; c < cols; c++) {
-            var col = DOM_createElement(document,"COL");
-            DOM_setAttribute(col,"width",colWidth);
-            DOM_appendChild(table,col);
-        }
-
-        var firstTD = null;
-
-        // Then the rows and columns
-        var tbody = DOM_createElement(document,"TBODY");
-        DOM_appendChild(table,tbody);
-        for (var r = 0; r < rows; r++) {
-            var tr = DOM_createElement(document,"TR");
-            DOM_appendChild(tbody,tr);
-            for (var c = 0; c < cols; c++) {
-                var td = DOM_createElement(document,"TD");
-                var p = DOM_createElement(document,"P");
-                var br = DOM_createElement(document,"BR");
-                DOM_appendChild(tr,td);
-                DOM_appendChild(td,p);
-                DOM_appendChild(p,br);
-
-                if (firstTD == null)
-                    firstTD = td;
-            }
-        }
-
-        Clipboard_pasteNodes([table]);
-
-        // Now that the table has been inserted into the DOM tree, the outline code will
-        // have noticed it and added an id attribute, as well as a caption giving the
-        // table number.
-        Outline_setNumbered(table.getAttribute("id"),numbered);
-
-        // Place the cursor at the start of the first cell on the first row
-        var pos = new Position(firstTD,0);
-        pos = Position_closestMatchForwards(pos,Position_okForMovement);
-        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-
-        PostponedActions_add(UndoManager_newGroup);
-    }
-
-    // private
-    function createEmptyTableCell(elementName)
-    {
-        var br = DOM_createElement(document,"BR");
-        var p = DOM_createElement(document,"P");
-        var td = DOM_createElement(document,elementName);
-        DOM_appendChild(p,br);
-        DOM_appendChild(td,p);
-        return td;
-    }
-
-    // private
-    function addEmptyTableCell(newTR,elementName)
-    {
-        var td = createEmptyTableCell(elementName);
-        DOM_appendChild(newTR,td);
-        return td;
-    }
-
-    // private
-    function populateNewRow(structure,newTR,newRow,oldRow)
-    {
-        var col = 0;
-        while (col < structure.numCols) {
-            var existingCell = Table_get(structure,oldRow,col);
-            if (((newRow > oldRow) && (newRow < existingCell.row + existingCell.rowspan)) ||
-                ((newRow < oldRow) && (newRow >= existingCell.row))) {
-                Cell_setRowspan(existingCell,existingCell.rowspan+1);
-            }
-            else {
-                var td = addEmptyTableCell(newTR,existingCell.element.nodeName); // check-ok
-                if (existingCell.colspan != 1)
-                    DOM_setAttribute(td,"colspan",existingCell.colspan);
-            }
-            col += existingCell.colspan;
-        }
-    }
-
-    function tableAtRightOfRange(range)
-    {
-        if (!Range_isEmpty(range))
-            return null;
-
-        var pos = Position_preferElementPosition(range.start);
-        if ((pos.node.nodeType == Node.ELEMENT_NODE) &&
-            (pos.offset < pos.node.childNodes.length) &&
-            (pos.node.childNodes[pos.offset]._type == HTML_TABLE)) {
-            var element = pos.node.childNodes[pos.offset];
-            var table = Tables_analyseStructure(element);
-            return table;
-        }
-        return null;
-    }
-
-    function tableAtLeftOfRange(range)
-    {
-        if (!Range_isEmpty(range))
-            return null;
-
-        var pos = Position_preferElementPosition(range.start);
-        if ((pos.node.nodeType == Node.ELEMENT_NODE) &&
-            (pos.offset > 0) &&
-            (pos.node.childNodes[pos.offset-1]._type == HTML_TABLE)) {
-            var element = pos.node.childNodes[pos.offset-1];
-            var table = Tables_analyseStructure(element);
-            return table;
-        }
-        return null;
-    }
-
-    function insertRowAbove(table,row)
-    {
-        var cell = Table_get(table,row,0);
-        var oldTR = cell.element.parentNode;
-        var newTR = DOM_createElement(document,"TR");
-        DOM_insertBefore(oldTR.parentNode,newTR,oldTR);
-        populateNewRow(table,newTR,row-1,row);
-    }
-
-    function insertRowBelow(table,row)
-    {
-        var cell = Table_get(table,row,0);
-        var oldTR = cell.element.parentNode;
-        var newTR = DOM_createElement(document,"TR");
-        DOM_insertBefore(oldTR.parentNode,newTR,oldTR.nextSibling);
-        populateNewRow(table,newTR,row+1,row);
-    }
-
-    function insertRowAdjacentToRange(range)
-    {
-        var table;
-
-        table = tableAtLeftOfRange(range);
-        if (table != null) {
-            insertRowBelow(table,table.numRows-1);
-            return;
-        }
-
-        table = tableAtRightOfRange(range);
-        if (table != null) {
-            insertRowAbove(table,0);
-            return;
-        }
-    }
-
-    // public
-    Tables_addAdjacentRow = function()
-    {
-        UndoManager_newGroup("Insert row below");
-        Selection_preserveWhileExecuting(function() {
-            var range = Selection_get();
-            var region = Tables_regionFromRange(range,true);
-            if (region != null)
-                insertRowBelow(region.structure,region.bottom);
-            else
-                insertRowAdjacentToRange(range);
-        });
-        UndoManager_newGroup();
-    }
-
-    // private
-    function getColElements(table)
-    {
-        var cols = new Array();
-        for (child = table.firstChild; child != null; child = child.nextSibling) {
-            switch (child._type) {
-            case HTML_COLGROUP:
-                for (var gc = child.firstChild; gc != null; gc = gc.nextSibling) {
-                    if (gc._type == HTML_COL)
-                        cols.push(gc);
-                }
-                break;
-            case HTML_COL:
-                cols.push(child);
-                break;
-            }
-        }
-        return cols;
-    }
-
-    // private
-    function getColWidths(colElements,expectedCount)
-    {
-        // FIXME: also handle the case where the width has been set as a CSS property in the
-        // style attribute. There's probably not much we can do if the width comes from a style
-        // rule elsewhere in the document though.
-        var colWidths = new Array();
-        for (var i = 0; i < colElements.length; i++) {
-            if (colElements[i].hasAttribute("width"))
-                colWidths.push(colElements[i].getAttribute("width"));
-            else
-                colWidths.push("");
-        }
-        return colWidths;
-    }
-
-    // private
-    function addMissingColElements(structure,colElements)
-    {
-        // If there are fewer COL elements than there are colums, add extra ones, copying the
-        // width value from the last one
-        // FIXME: handle col elements with colspan > 1, as well as colgroups with width set
-        // FIXME: What if there are 0 col elements?
-        while (colElements.length < structure.numCols) {
-            var newColElement = DOM_createElement(document,"COL");
-            var lastColElement = colElements[colElements.length-1];
-            DOM_insertBefore(lastColElement.parentNode,newColElement,lastColElement.nextSibling);
-            colElements.push(newColElement);
-            DOM_setAttribute(newColElement,"width",lastColElement.getAttribute("width"));
-        }
-    }
-
-    // private
-    function fixColPercentages(structure,colElements)
-    {
-        var colWidths = getColWidths(colElements,structure.numCols);
-
-        var percentages = colWidths.map(getPercentage);
-        if (percentages.every(notNull)) {
-            var colWidthTotal = 0;
-            for (var i = 0; i < percentages.length; i++)
-                colWidthTotal += percentages[i];
-
-            for (var i = 0; i < colElements.length; i++) {
-                var pct = 100*percentages[i]/colWidthTotal;
-                // Store value using at most two decimal places
-                pct = Math.round(100*pct)/100;
-                DOM_setAttribute(colElements[i],"width",pct+"%");
-            }
-        }
-
-        function notNull(arg)
-        {
-            return (arg != null);
-        }
-
-        function getPercentage(str)
-        {
-            if (str.match(/^\s*\d+(\.\d+)?\s*%\s*$/))
-                return parseInt(str.replace(/\s*%\s*$/,""));
-            else
-                return null;
-        }
-    }
-
-    // private
-    function addColElement(structure,oldIndex,right)
-    {
-        var table = structure.element;
-
-        var colElements = getColElements(table);
-        if (colElements.length == 0) {
-            // The table doesn't have any COL elements; don't add any
-            return;
-        }
-
-        addMissingColElements(structure,colElements);
-
-        var prevColElement = colElements[oldIndex];
-        var newColElement = DOM_createElement(document,"COL");
-        DOM_setAttribute(newColElement,"width",prevColElement.getAttribute("width"));
-        if (right)
-            DOM_insertBefore(prevColElement.parentNode,newColElement,prevColElement.nextSibling);
-        else
-            DOM_insertBefore(prevColElement.parentNode,newColElement,prevColElement);
-
-        if (right) {
-            colElements.splice(oldIndex+1,0,newColElement);
-        }
-        else {
-            colElements.splice(oldIndex+1,0,newColElement);
-        }
-
-        fixColPercentages(structure,colElements);
-    }
-
-    // private
-    function deleteColElements(structure,left,right)
-    {
-        var table = structure.element;
-
-        var colElements = getColElements(table);
-        if (colElements.length == 0) {
-            // The table doesn't have any COL elements
-            return;
-        }
-
-        addMissingColElements(structure,colElements);
-
-        for (var col = left; col <= right; col++)
-            DOM_deleteNode(colElements[col]);
-        colElements.splice(left,right-left+1);
-
-        fixColPercentages(structure,colElements);
-    }
-
-    // private
-    function addColumnCells(structure,oldIndex,right)
-    {
-        for (var row = 0; row < structure.numRows; row++) {
-            var cell = Table_get(structure,row,oldIndex);
-            var oldTD = cell.element;
-            if (cell.row == row) {
-
-                if (((right && (oldIndex+1 < cell.col + cell.colspan)) ||
-                    (!right && (oldIndex-1 >= cell.col))) &&
-                    (cell.colspan > 1)) {
-                    Cell_setColspan(cell,cell.colspan+1);
-                }
-                else {
-                    var newTD = createEmptyTableCell(oldTD.nodeName); // check-ok
-                    if (right)
-                        DOM_insertBefore(cell.element.parentNode,newTD,oldTD.nextSibling);
-                    else
-                        DOM_insertBefore(cell.element.parentNode,newTD,oldTD);
-                    if (cell.rowspan != 1)
-                        DOM_setAttribute(newTD,"rowspan",cell.rowspan);
-                }
-            }
-        }
-    }
-
-    function insertColumnAdjacentToRange(range)
-    {
-        var table;
-
-        table = tableAtLeftOfRange(range);
-        if (table != null) {
-            var right = table.numCols-1;
-            addColElement(table,right,right+1);
-            addColumnCells(table,right,true);
-            return;
-        }
-
-        table = tableAtRightOfRange(range);
-        if (table != null) {
-            var left = 0;
-            addColElement(table,left,left-1);
-            addColumnCells(table,left,false);
-            return;
-        }
-    }
-
-    // public
-    Tables_addAdjacentColumn = function()
-    {
-        UndoManager_newGroup("Insert column at right");
-        Selection_preserveWhileExecuting(function() {
-            var range = Selection_get();
-            var region = Tables_regionFromRange(range,true);
-            if (region != null) {
-                addColElement(region.structure,region.right,region.right+1);
-                addColumnCells(region.structure,region.right,true);
-            }
-            else {
-                insertColumnAdjacentToRange(range);
-            }
-        });
-        UndoManager_newGroup();
-    }
-
-    function columnHasContent(table,col)
-    {
-        for (var row = 0; row < table.numRows; row++) {
-            var cell = Table_get(table,row,col);
-            if ((cell != null) && (cell.col == col) && nodeHasContent(cell.element))
-                return true;
-        }
-        return false;
-    }
-
-    function rowHasContent(table,row)
-    {
-        for (var col = 0; col < table.numCols; col++) {
-            var cell = Table_get(table,row,col);
-            if ((cell != null) && (cell.row == row) && nodeHasContent(cell.element))
-                return true;
-        }
-        return false;
-    }
-
-    function selectRegion(table,top,bottom,left,right)
-    {
-        left = clampCol(table,left);
-        right = clampCol(table,right);
-        top = clampRow(table,top);
-        bottom = clampRow(table,bottom);
-
-        var tlCell = Table_get(table,top,left);
-        var brCell = Table_get(table,bottom,right);
-        if ((tlCell != null) && (brCell != null)) {
-            var tlPos = new Position(tlCell.element,0);
-            tlPos = Position_closestMatchForwards(tlPos,Position_okForMovement);
-
-            var brPos = new Position(brCell.element,brCell.element.childNodes.length);
-            brPos = Position_closestMatchBackwards(brPos,Position_okForMovement);
-
-            Selection_set(tlPos.node,tlPos.offset,brPos.node,brPos.offset);
-        }
-    }
-
-    function clampCol(table,col)
-    {
-        if (col > table.numCols-1)
-            col = table.numCols-1;
-        if (col < 0)
-            col = 0;
-        return col;
-    }
-
-    function clampRow(table,row)
-    {
-        if (row > table.numRows-1)
-            row = table.numRows-1;
-        if (row < 0)
-            row = 0;
-        return row;
-    }
-
-    function removeRowAdjacentToRange(range)
-    {
-        var table;
-
-        table = tableAtLeftOfRange(range);
-        if ((table != null) && (table.numRows >= 2)) {
-            UndoManager_newGroup("Delete one row");
-            var row = table.numRows-1;
-            Tables_deleteRegion(new TableRegion(table,row,row,0,table.numCols-1));
-            UndoManager_newGroup();
-            return;
-        }
-
-        table = tableAtRightOfRange(range);
-        if ((table != null) && (table.numRows >= 2)) {
-            UndoManager_newGroup("Delete one row");
-            Tables_deleteRegion(new TableRegion(table,0,0,0,table.numCols-1));
-            UndoManager_newGroup();
-            return;
-        }
-    }
-
-    Tables_removeAdjacentRow = function()
-    {
-        var range = Selection_get();
-        var region = Tables_regionFromRange(range,true);
-
-        if (region == null) {
-            removeRowAdjacentToRange(range);
-            return;
-        }
-
-        if (region.structure.numRows <= 1)
-            return;
-
-        UndoManager_newGroup("Delete one row");
-
-        var table = region.structure;
-        var left = region.left;
-        var right = region.right;
-        var top = region.top;
-        var bottom = region.bottom;
-
-        // Is there an empty row below the selection? If so, delete it
-        if ((bottom+1 < table.numRows) && !rowHasContent(table,bottom+1)) {
-            Selection_preserveWhileExecuting(function() {
-                Tables_deleteRegion(new TableRegion(table,bottom+1,bottom+1,0,table.numCols-1));
-            });
-        }
-
-        // Is there an empty row above the selection? If so, delete it
-        else if ((top-1 >= 0) && !rowHasContent(table,top-1)) {
-            Selection_preserveWhileExecuting(function() {
-                Tables_deleteRegion(new TableRegion(table,top-1,top-1,0,table.numCols-1));
-            });
-        }
-
-
-        // There are no empty rows adjacent to the selection. Delete the right-most row
-        // of the selection (which may be the only one)
-        else {
-            Selection_preserveWhileExecuting(function() {
-                Tables_deleteRegion(new TableRegion(table,bottom,bottom,0,table.numCols-1));
-            });
-
-            table = Tables_analyseStructure(table.element);
-            var multiple = (top != bottom);
-
-            if (multiple) {
-                selectRegion(table,top,bottom-1,left,right);
-            }
-            else {
-                var newRow = clampRow(table,bottom);
-                var newCell = Table_get(table,newRow,left);
-                if (newCell != null) {
-                    var pos = new Position(newCell.element,0);
-                    pos = Position_closestMatchForwards(pos,Position_okForMovement);
-                    Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-                }
-            }
-        }
-
-        UndoManager_newGroup();
-    }
-
-    function removeColumnAdjacentToRange(range)
-    {
-        var table;
-
-        table = tableAtLeftOfRange(range);
-        if ((table != null) && (table.numCols >= 2)) {
-            UndoManager_newGroup("Delete one column");
-            var col = table.numCols-1;
-            Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,col,col));
-            UndoManager_newGroup();
-            return;
-        }
-
-        table = tableAtRightOfRange(range);
-        if ((table != null) && (table.numCols >= 2)) {
-            UndoManager_newGroup("Delete one column");
-            Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,0,0));
-            UndoManager_newGroup();
-            return;
-        }
-    }
-
-    Tables_removeAdjacentColumn = function()
-    {
-        var range = Selection_get();
-        var region = Tables_regionFromRange(range,true);
-
-        if (region == null) {
-            removeColumnAdjacentToRange(range);
-            return;
-        }
-
-        if (region.structure.numCols <= 1)
-            return;
-
-        UndoManager_newGroup("Delete one column");
-
-        var table = region.structure;
-        var left = region.left;
-        var right = region.right;
-        var top = region.top;
-        var bottom = region.bottom;
-
-        // Is there an empty column to the right of the selection? If so, delete it
-        if ((right+1 < table.numCols) && !columnHasContent(table,right+1)) {
-            Selection_preserveWhileExecuting(function() {
-                Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,right+1,right+1));
-            });
-        }
-
-        // Is there an empty column to the left of the selection? If so, delete it
-        else if ((left-1 >= 0) && !columnHasContent(table,left-1)) {
-            Selection_preserveWhileExecuting(function() {
-                Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,left-1,left-1));
-            });
-        }
-
-        // There are no empty columns adjacent to the selection. Delete the right-most column
-        // of the selection (which may be the only one)
-        else {
-            Selection_preserveWhileExecuting(function() {
-                Tables_deleteRegion(new TableRegion(table,0,table.numRows-1,right,right));
-            });
-
-            table = Tables_analyseStructure(table.element);
-            var multiple = (left != right);
-
-            if (multiple) {
-                selectRegion(table,top,bottom,left,right-1);
-            }
-            else {
-                var newCol = clampCol(table,right);
-                var newCell = Table_get(table,top,newCol);
-                if (newCell != null) {
-                    var pos = new Position(newCell.element,0);
-                    pos = Position_closestMatchForwards(pos,Position_okForMovement);
-                    Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-                }
-            }
-        }
-
-        UndoManager_newGroup();
-    }
-
-    // private
-    function deleteTable(structure)
-    {
-        DOM_deleteNode(structure.element);
-    }
-
-    // private
-    function deleteRows(structure,top,bottom)
-    {
-        var trElements = new Array();
-        getTRs(structure.element,trElements);
-
-        for (var row = top; row <= bottom; row++)
-            DOM_deleteNode(trElements[row]);
-    }
-
-    // private
-    function getTRs(node,result)
-    {
-        if (node._type == HTML_TR) {
-            result.push(node);
-        }
-        else {
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                getTRs(child,result);
-        }
-    }
-
-    // private
-    function deleteColumns(structure,left,right)
-    {
-        var nodesToDelete = new NodeSet();
-        for (var row = 0; row < structure.numRows; row++) {
-            for (var col = left; col <= right; col++) {
-                var cell = Table_get(structure,row,col);
-                nodesToDelete.add(cell.element);
-            }
-        }
-        nodesToDelete.forEach(DOM_deleteNode);
-        deleteColElements(structure,left,right);
-    }
-
-    // private
-    function deleteCellContents(region)
-    {
-        var structure = region.structure;
-        for (var row = region.top; row <= region.bottom; row++) {
-            for (var col = region.left; col <= region.right; col++) {
-                var cell = Table_get(structure,row,col);
-                DOM_deleteAllChildren(cell.element);
-            }
-        }
-    }
-
-    // public
-    Tables_deleteRegion = function(region)
-    {
-        var structure = region.structure;
-
-        var coversEntireWidth = (region.left == 0) && (region.right == structure.numCols-1);
-        var coversEntireHeight = (region.top == 0) && (region.bottom == structure.numRows-1);
-
-        if (coversEntireWidth && coversEntireHeight)
-            deleteTable(region.structure);
-        else if (coversEntireWidth)
-            deleteRows(structure,region.top,region.bottom);
-        else if (coversEntireHeight)
-            deleteColumns(structure,region.left,region.right);
-        else
-            deleteCellContents(region);
-    }
-
-    // public
-    Tables_clearCells = function()
-    {
-    }
-
-    // public
-    Tables_mergeCells = function()
-    {
-        Selection_preserveWhileExecuting(function() {
-            var region = Tables_regionFromRange(Selection_get());
-            if (region == null)
-                return;
-
-            var structure = region.structure;
-
-            // FIXME: handle the case of missing cells
-            // (or even better, add cells where there are some missing)
-
-            for (var row = region.top; row <= region.bottom; row++) {
-                for (var col = region.left; col <= region.right; col++) {
-                    var cell = Table_get(structure,row,col);
-                    var cellFirstRow = cell.row;
-                    var cellLastRow = cell.row + cell.rowspan - 1;
-                    var cellFirstCol = cell.col;
-                    var cellLastCol = cell.col + cell.colspan - 1;
-
-                    if ((cellFirstRow < region.top) || (cellLastRow > region.bottom) ||
-                        (cellFirstCol < region.left) || (cellLastCol > region.right)) {
-                        debug("Can't merge this table: cell at "+row+","+col+
-                              " goes outside bounds of selection");
-                        return;
-                    }
-                }
-            }
-
-            var mergedCell = Table_get(structure,region.top,region.left);
-
-            for (var row = region.top; row <= region.bottom; row++) {
-                for (var col = region.left; col <= region.right; col++) {
-                    var cell = Table_get(structure,row,col);
-                    // parentNode will be null if we've already done this cell
-                    if ((cell != mergedCell) && (cell.element.parentNode != null)) {
-                        while (cell.element.firstChild != null)
-                            DOM_appendChild(mergedCell.element,cell.element.firstChild);
-                        DOM_deleteNode(cell.element);
-                    }
-                }
-            }
-
-            var totalRows = region.bottom - region.top + 1;
-            var totalCols = region.right - region.left + 1;
-            if (totalRows == 1)
-                DOM_removeAttribute(mergedCell.element,"rowspan");
-            else
-                DOM_setAttribute(mergedCell.element,"rowspan",totalRows);
-            if (totalCols == 1)
-                DOM_removeAttribute(mergedCell.element,"colspan");
-            else
-                DOM_setAttribute(mergedCell.element,"colspan",totalCols);
-        });
-    }
-
-    // public
-    Tables_splitSelection = function()
-    {
-        Selection_preserveWhileExecuting(function() {
-            var range = Selection_get();
-            Range_trackWhileExecuting(range,function() {
-                var region = Tables_regionFromRange(range,true);
-                if (region != null)
-                    TableRegion_splitCells(region);
-            });
-        });
-    }
-
-    // public
-    TableRegion_splitCells = function(region)
-    {
-        var structure = region.structure;
-        var trElements = new Array();
-        getTRs(structure.element,trElements);
-
-        for (var row = region.top; row <= region.bottom; row++) {
-            for (var col = region.left; col <= region.right; col++) {
-                var cell = Table_get(structure,row,col);
-                if ((cell.rowspan > 1) || (cell.colspan > 1)) {
-
-                    var original = cell.element;
-
-                    for (var r = cell.top; r <= cell.bottom; r++) {
-                        for (var c = cell.left; c <= cell.right; c++) {
-                            if ((r == cell.top) && (c == cell.left))
-                                continue;
-                            var newTD = createEmptyTableCell(original.nodeName); // check-ok
-                            var nextElement = null;
-
-                            var nextCol = cell.right+1;
-                            while (nextCol < structure.numCols) {
-                                var nextCell = Table_get(structure,r,nextCol);
-                                if ((nextCell != null) && (nextCell.row == r)) {
-                                    nextElement = nextCell.element;
-                                    break;
-                                }
-                                nextCol++;
-                            }
-
-                            DOM_insertBefore(trElements[r],newTD,nextElement);
-                            Table_set(structure,r,c,new Cell(newTD,r,c));
-                        }
-                    }
-                    DOM_removeAttribute(original,"rowspan");
-                    DOM_removeAttribute(original,"colspan");
-                }
-            }
-        }
-    }
-
-    // public
-    Tables_cloneRegion = function(region)
-    {
-        var cellNodesDone = new NodeSet();
-        var table = DOM_shallowCopyElement(region.structure.element);
-        for (var row = region.top; row <= region.bottom; row++) {
-            var tr = DOM_createElement(document,"TR");
-            DOM_appendChild(table,tr);
-            for (var col = region.left; col <= region.right; col++) {
-                var cell = Table_get(region.structure,row,col);
-                if (!cellNodesDone.contains(cell.element)) {
-                    DOM_appendChild(tr,DOM_cloneNode(cell.element,true));
-                    cellNodesDone.add(cell.element);
-                }
-            }
-        }
-        return table;
-    }
-
-    // private
-    function pasteCells(fromTableElement,toRegion)
-    {
-        // FIXME
-        var fromStructure = Tables_analyseStructure(fromTableElement);
-    }
-
-    // public
-    Table_fix = function(table)
-    {
-        var changed = false;
-
-        var tbody = null;
-        for (var child = table.element.firstChild; child != null; child = child.nextSibling) {
-            if (child._type == HTML_TBODY)
-                tbody = child;
-        }
-
-        if (tbody == null)
-            return table; // FIXME: handle presence of THEAD and TFOOT, and also a missing TBODY
-
-        var trs = new Array();
-        for (var child = tbody.firstChild; child != null; child = child.nextSibling) {
-            if (child._type == HTML_TR)
-                trs.push(child);
-        }
-
-        while (trs.length < table.numRows) {
-            var tr = DOM_createElement(document,"TR");
-            DOM_appendChild(tbody,tr);
-            trs.push(tr);
-        }
-
-        for (var row = 0; row < table.numRows; row++) {
-            for (var col = 0; col < table.numCols; col++) {
-                var cell = Table_get(table,row,col);
-                if (cell == null) {
-                    var td = createEmptyTableCell("TD");
-                    DOM_appendChild(trs[row],td);
-                    changed = true;
-                }
-            }
-        }
-
-        if (changed)
-            return new Table(table.element);
-        else
-            return table;
-    }
-
-    // public
-    Table_fixColumnWidths = function(structure)
-    {
-        var colElements = getColElements(structure.element);
-        if (colElements.length == 0)
-            return;
-        addMissingColElements(structure,colElements);
-
-        var widths = Tables_getColWidths(structure);
-        fixWidths(widths,structure.numCols);
-        colElements = getColElements(structure.element);
-        for (var i = 0; i < widths.length; i++)
-            DOM_setAttribute(colElements[i],"width",widths[i]+"%");
-    }
-
-    // public
-    Tables_analyseStructure = function(element)
-    {
-        // FIXME: we should probably be preserving the selection here, since we are modifying
-        // the DOM (though I think it's unlikely it would cause problems, becausing the fixup
-        // logic only adds elements). However this method is called (indirectly) from within
-        // Selection_update(), which causes unbounded recursion due to the subsequent Selecton_set()
-        // that occurs.
-        var initial = new Table(element);
-        var fixed = Table_fix(initial);
-        return fixed;
-    }
-
-    // public
-    Tables_findContainingCell = function(node)
-    {
-        for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) {
-            if (isTableCell(ancestor))
-                return ancestor;
-        }
-        return null;
-    }
-
-    // public
-    Tables_findContainingTable = function(node)
-    {
-        for (var ancestor = node; ancestor != null; ancestor = ancestor.parentNode) {
-            if (ancestor._type == HTML_TABLE)
-                return ancestor;
-        }
-        return null;
-    }
-
-    function TableRegion(structure,top,bottom,left,right)
-    {
-        this.structure = structure;
-        this.top = top;
-        this.bottom = bottom;
-        this.left = left;
-        this.right = right;
-    }
-
-    TableRegion.prototype.toString = function()
-    {
-        return "("+this.top+","+this.left+") - ("+this.bottom+","+this.right+")";
-    }
-
-    // public
-    Tables_regionFromRange = function(range,allowSameCell)
-    {
-        var region = null;
-
-        if (range == null)
-            return null;
-
-        var start = Position_closestActualNode(range.start,true);
-        var end = Position_closestActualNode(range.end,true);
-
-        var startTD = Tables_findContainingCell(start);
-        var endTD = Tables_findContainingCell(end);
-
-        if (!isTableCell(start) || !isTableCell(end)) {
-            if (!allowSameCell) {
-                if (startTD == endTD) // not in cell, or both in same cell
-                    return null;
-            }
-        }
-
-        if ((startTD == null) || (endTD == null))
-            return null;
-
-        var startTable = Tables_findContainingTable(startTD);
-        var endTable = Tables_findContainingTable(endTD);
-
-        if (startTable != endTable)
-            return null;
-
-        var structure = Tables_analyseStructure(startTable);
-
-        var startInfo = structure.cellsByElement.get(startTD);
-        var endInfo = structure.cellsByElement.get(endTD);
-
-        var startTopRow = startInfo.row;
-        var startBottomRow = startInfo.row + startInfo.rowspan - 1;
-        var startLeftCol = startInfo.col;
-        var startRightCol = startInfo.col + startInfo.colspan - 1;
-
-        var endTopRow = endInfo.row;
-        var endBottomRow = endInfo.row + endInfo.rowspan - 1;
-        var endLeftCol = endInfo.col;
-        var endRightCol = endInfo.col + endInfo.colspan - 1;
-
-        var top = (startTopRow < endTopRow) ? startTopRow : endTopRow;
-        var bottom = (startBottomRow > endBottomRow) ? startBottomRow : endBottomRow;
-        var left = (startLeftCol < endLeftCol) ? startLeftCol : endLeftCol;
-        var right = (startRightCol > endRightCol) ? startRightCol : endRightCol;
-
-        var region = new TableRegion(structure,top,bottom,left,right);
-        adjustRegionForSpannedCells(region);
-        return region;
-    }
-
-    // private
-    function adjustRegionForSpannedCells(region)
-    {
-        var structure = region.structure;
-        var boundariesOk;
-        var columnsOk;
-        do {
-            boundariesOk = true;
-            for (var row = region.top; row <= region.bottom; row++) {
-                var cell = Table_get(structure,row,region.left);
-                if (region.left > cell.left) {
-                    region.left = cell.left;
-                    boundariesOk = false;
-                }
-                cell = Table_get(structure,row,region.right);
-                if (region.right < cell.right) {
-                    region.right = cell.right;
-                    boundariesOk = false;
-                }
-            }
-
-            for (var col = region.left; col <= region.right; col++) {
-                var cell = Table_get(structure,region.top,col);
-                if (region.top > cell.top) {
-                    region.top = cell.top;
-                    boundariesOk = false;
-                }
-                cell = Table_get(structure,region.bottom,col);
-                if (region.bottom < cell.bottom) {
-                    region.bottom = cell.bottom;
-                    boundariesOk = false;
-                }
-            }
-        } while (!boundariesOk);
-    }
-
-    Tables_getSelectedTableId = function()
-    {
-        var element = Cursor_getAdjacentNodeWithType(HTML_TABLE);
-        return element ? element.getAttribute("id") : null;
-    }
-
-    Tables_getProperties = function(itemId)
-    {
-        var element = document.getElementById(itemId);
-        if ((element == null) || (element._type != HTML_TABLE))
-            return null;
-        var structure = Tables_analyseStructure(element);
-        var width = element.style.width;
-        return { width: width, rows: structure.numRows, cols: structure.numCols };
-    }
-
-    Tables_setProperties = function(itemId,width)
-    {
-        var table = document.getElementById(itemId);
-        if (table == null)
-            return null;
-        DOM_setStyleProperties(table,{ width: width });
-        Selection_update(); // ensure cursor/selection drawn in correct pos
-    }
-
-    // Returns an array of numbers representing the percentage widths (0 - 100) of each
-    // column. This works on the assumption that all tables are supposed to have all of
-    // their column widths specified, and in all cases as percentages. Any which do not
-    // are considered invalid, and have any non-percentage values filled in based on the
-    // average values of all valid percentage-based columns.
-    Tables_getColWidths = function(structure)
-    {
-        var colElements = getColElements(structure.element);
-        var colWidths = new Array();
-
-        for (var i = 0; i < structure.numCols; i++) {
-            var value = null;
-
-            if (i < colElements.length) {
-                var widthStr = DOM_getAttribute(colElements[i],"width");
-                if (widthStr != null) {
-                    value = parsePercentage(widthStr);
-                }
-            }
-
-            if ((value != null) && (value >= 1.0)) {
-                colWidths[i] = value;
-            }
-            else {
-                colWidths[i] = null;
-            }
-        }
-
-        fixWidths(colWidths,structure.numCols);
-
-        return colWidths;
-
-        function parsePercentage(str)
-        {
-            if (str.match(/^\s*\d+(\.\d+)?\s*%\s*$/))
-                return parseFloat(str.replace(/\s*%\s*$/,""));
-            else
-                return null;
-        }
-    }
-
-    function fixWidths(colWidths,numCols)
-    {
-        var totalWidth = 0;
-        var numValidCols = 0;
-        for (var i = 0; i < numCols; i++) {
-            if (colWidths[i] != null) {
-                totalWidth += colWidths[i];
-                numValidCols++;
-            }
-        }
-
-        var averageWidth = (numValidCols > 0) ? totalWidth/numValidCols : 1.0;
-        for (var i = 0; i < numCols; i++) {
-            if (colWidths[i] == null) {
-                colWidths[i] = averageWidth;
-                totalWidth += averageWidth;
-            }
-        }
-
-        // To cater for the case where the column widths do not all add up to 100%,
-        // recalculate all of them based on their value relative to the total width
-        // of all columns. For example, if there are three columns of 33%, 33%, and 33%,
-        // these will get rounded up to 33.33333.....%.
-        // If there are no column widths defined, each will have 100/numCols%.
-        if (totalWidth > 0) {
-            for (var i = 0; i < numCols; i++) {
-                colWidths[i] = 100.0*colWidths[i]/totalWidth;
-            }
-        }
-    }
-
-    // public
-    Tables_setColWidths = function(itemId,widths)
-    {
-        var element = document.getElementById(itemId);
-        if (element == null)
-            return null;
-
-        var structure = Tables_analyseStructure(element);
-
-        fixWidths(widths,structure.numCols);
-
-        var colElements = getColElements(element);
-        for (var i = 0; i < widths.length; i++)
-            DOM_setAttribute(colElements[i],"width",widths[i]+"%");
-
-        Selection_update();
-    }
-
-    // public
-    Tables_getGeometry = function(itemId)
-    {
-        var element = document.getElementById(itemId);
-        if ((element == null) || (element.parentNode == null))
-            return null;
-
-        var structure = Tables_analyseStructure(element);
-
-        var result = new Object();
-
-        // Calculate the rect based on the cells, not the whole table element;
-        // we want to ignore the caption
-        var topLeftCell = Table_get(structure,0,0);
-        var bottomRightCell = Table_get(structure,structure.numRows-1,structure.numCols-1);
-
-        if (topLeftCell == null)
-            throw new Error("No top left cell");
-        if (bottomRightCell == null)
-            throw new Error("No bottom right cell");
-
-        var topLeftRect = topLeftCell.element.getBoundingClientRect();
-        var bottomRightRect = bottomRightCell.element.getBoundingClientRect();
-
-        var left = topLeftRect.left + window.scrollX;
-        var right = bottomRightRect.right + window.scrollX;
-        var top = topLeftRect.top + window.scrollY;
-        var bottom = bottomRightRect.bottom + window.scrollY;
-
-        result.contentRect = { x: left, y: top, width: right - left, height: bottom - top };
-        result.fullRect = xywhAbsElementRect(element);
-        result.parentRect = xywhAbsElementRect(element.parentNode);
-
-        result.columnWidths = Tables_getColWidths(structure);
-
-        var caption = firstChildOfType(element,HTML_CAPTION);
-        result.hasCaption = (caption != null);
-
-        return result;
-
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Text.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Text.js b/experiments/editorFramework/src/Layer0_Javascript/Text.js
deleted file mode 100644
index 5a69feb..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Text.js
+++ /dev/null
@@ -1,543 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Text_findParagraphBoundaries;
-var Text_analyseParagraph;
-var Text_posAbove;
-var Text_posBelow;
-var Text_closestPosBackwards;
-var Text_closestPosForwards;
-var Text_closestPosInDirection;
-
-var Paragraph_runFromOffset;
-var Paragraph_runFromNode;
-var Paragraph_positionAtOffset;
-var Paragraph_offsetAtPosition;
-var Paragraph_getRunRects;
-var Paragraph_getRunOrFallbackRects;
-
-var Text_toStartOfBoundary;
-var Text_toEndOfBoundary;
-
-(function() {
-
-    function Paragraph(node,startOffset,endOffset,runs,text)
-    {
-        this.node = node;
-        this.startOffset = startOffset;
-        this.endOffset = endOffset;
-        this.runs = runs;
-        this.text = text;
-
-        Object.defineProperty(this,"first",{
-            get: function() { throw new Error("Attempt to access first property of Position") },
-            set: function() {},
-            enumerable: true });
-        Object.defineProperty(this,"last",{
-            get: function() { throw new Error("Attempt to access last property of Position") },
-            set: function() {},
-            enumerable: true });
-    }
-
-    function Run(node,start,end)
-    {
-        this.node = node;
-        this.start = start;
-        this.end = end;
-    }
-
-    // In this code, we represent a paragraph by its first and last node. Normally, this will be
-    // the first and last child of a paragraph-level element (e.g. p or h1), but this scheme also
-    // represent a sequence of inline nodes between two paragraph or container nodes, e.g.
-    //
-    // <p>...</p> Some <i>inline</i> nodes <p>...</p>
-
-    Text_findParagraphBoundaries = function(pos)
-    {
-        Position_assertValid(pos);
-        var startOffset = pos.offset;
-        var endOffset = pos.offset;
-        var node = pos.node;
-
-        while (isInlineNode(node)) {
-            startOffset = DOM_nodeOffset(node);
-            endOffset = DOM_nodeOffset(node)+1;
-            node = node.parentNode;
-        }
-
-        if (node.nodeType != Node.ELEMENT_NODE)
-            throw new Error("Not an element node: "+nodeString(node));
-
-        while ((startOffset > 0) && isInlineNode(node.childNodes[startOffset-1]))
-            startOffset--;
-        while ((endOffset < node.childNodes.length) && isInlineNode(node.childNodes[endOffset]))
-            endOffset++;
-
-        return { node: node, startOffset: startOffset, endOffset: endOffset };
-    }
-
-    Text_analyseParagraph = function(pos)
-    {
-        var initial = pos.node;
-        var strings = new Array();
-        var runs = new Array();
-        var offset = 0;
-
-        var boundaries = Text_findParagraphBoundaries(pos);
-        if (boundaries == null)
-            return null;
-
-        for (var off = boundaries.startOffset; off < boundaries.endOffset; off++)
-            recurse(boundaries.node.childNodes[off]);
-
-        var text = strings.join("");
-
-        return new Paragraph(boundaries.node,boundaries.startOffset,boundaries.endOffset,runs,text);
-
-        function recurse(node)
-        {
-            if (node.nodeType == Node.TEXT_NODE) {
-                strings.push(node.nodeValue);
-                var start = offset;
-                var end = offset + node.nodeValue.length;
-                runs.push(new Run(node,start,end));
-                offset += node.nodeValue.length;
-            }
-            for (var child = node.firstChild; child != null; child = child.nextSibling)
-                recurse(child);
-        }
-    }
-
-    Text_posAbove = function(pos,cursorRect,cursorX)
-    {
-        if (cursorX == null)
-            cursorX = pos.targetX;
-        pos = Position_closestMatchBackwards(pos,Position_okForMovement);
-        if (cursorRect == null) {
-            cursorRect = Position_rectAtPos(pos);
-            if (cursorRect == null)
-                return null;
-        }
-
-        if (cursorX == null) {
-            cursorX = cursorRect.left;
-        }
-
-        while (true) {
-            pos = Position_closestMatchBackwards(pos,Position_okForMovement);
-            if (pos == null)
-                return null;
-
-            var paragraph = Text_analyseParagraph(pos);
-            if (paragraph == null)
-                return null;
-
-            var rects = Paragraph_getRunOrFallbackRects(paragraph,pos);
-
-            rects = rects.filter(function (rect) {
-                return (rect.bottom <= cursorRect.top);
-            });
-
-
-
-            var bottom = findLowestBottom(rects);
-
-            rects = rects.filter(function (rect) { return (rect.bottom == bottom); });
-
-            // Scroll previous line into view, if necessary
-            var top = findHighestTop(rects);
-            if (top < 0) {
-                var offset = -top;
-                window.scrollBy(0,-offset);
-                rects = offsetRects(rects,0,offset);
-            }
-
-            for (var i = 0; i < rects.length; i++) {
-                if ((cursorX >= rects[i].left) && (cursorX <= rects[i].right)) {
-                    var newPos = Position_atPoint(cursorX,rects[i].top + rects[i].height/2);
-                    if (newPos != null) {
-                        newPos = Position_closestMatchBackwards(newPos,Position_okForInsertion);
-                        newPos.targetX = cursorX;
-                        return newPos;
-                    }
-                }
-            }
-
-            var rightMost = findRightMostRect(rects);
-            if (rightMost != null) {
-                var newPos = Position_atPoint(rightMost.right,rightMost.top + rightMost.height/2);
-                if (newPos != null) {
-                    newPos = Position_closestMatchBackwards(newPos,Position_okForInsertion);
-                    newPos.targetX = cursorX;
-                    return newPos;
-                }
-            }
-
-
-            pos = new Position(paragraph.node,paragraph.startOffset);
-            pos = Position_prevMatch(pos,Position_okForMovement);
-        }
-    }
-
-    var findHighestTop = function(rects)
-    {
-        var top = null;
-        for (var i = 0; i < rects.length; i++) {
-            if ((top == null) || (top > rects[i].top))
-                top = rects[i].top;
-        }
-        return top;
-    }
-
-    var findLowestBottom = function(rects)
-    {
-        var bottom = null;
-        for (var i = 0; i < rects.length; i++) {
-            if ((bottom == null) || (bottom < rects[i].bottom))
-                bottom = rects[i].bottom;
-        }
-        return bottom;
-    }
-
-    var findRightMostRect = function(rects)
-    {
-        var rightMost = null;
-        for (var i = 0; i < rects.length; i++) {
-            if ((rightMost == null) || (rightMost.right < rects[i].right))
-                rightMost = rects[i];
-        }
-        return rightMost;
-    }
-
-    var offsetRects = function(rects,offsetX,offsetY)
-    {
-        var result = new Array();
-        for (var i = 0; i < rects.length; i++) {
-            result.push({ top: rects[i].top + offsetY,
-                          bottom: rects[i].bottom + offsetY,
-                          left: rects[i].left + offsetX,
-                          right: rects[i].right + offsetX,
-                          width: rects[i].width,
-                          height: rects[i].height });
-        }
-        return result;
-    }
-
-    Text_posBelow = function(pos,cursorRect,cursorX)
-    {
-        if (cursorX == null)
-            cursorX = pos.targetX;
-        pos = Position_closestMatchForwards(pos,Position_okForMovement);
-        if (cursorRect == null) {
-            cursorRect = Position_rectAtPos(pos);
-            if (cursorRect == null)
-                return null;
-        }
-
-        if (cursorX == null) {
-            cursorX = cursorRect.left;
-        }
-
-
-        while (true) {
-            pos = Position_closestMatchForwards(pos,Position_okForMovement);
-            if (pos == null)
-                return null;
-
-            var paragraph = Text_analyseParagraph(pos);
-            if (paragraph == null)
-                return null;
-
-            var rects = Paragraph_getRunOrFallbackRects(paragraph,pos);
-
-            rects = rects.filter(function (rect) {
-                return (rect.top >= cursorRect.bottom);
-            });
-
-            var top = findHighestTop(rects);
-
-            rects = rects.filter(function (rect) { return (rect.top == top); });
-
-            // Scroll next line into view, if necessary
-            var bottom = findLowestBottom(rects);
-            if (bottom > window.innerHeight) {
-                var offset = window.innerHeight - bottom;
-                window.scrollBy(0,-offset);
-                rects = offsetRects(rects,0,offset);
-            }
-
-            for (var i = 0; i < rects.length; i++) {
-                if ((cursorX >= rects[i].left) && (cursorX <= rects[i].right)) {
-                    var newPos = Position_atPoint(cursorX,rects[i].top + rects[i].height/2);
-                    if (newPos != null) {
-                        newPos = Position_closestMatchForwards(newPos,Position_okForInsertion);
-                        newPos.targetX = cursorX;
-                        return newPos;
-                    }
-                }
-            }
-
-            var rightMost = findRightMostRect(rects);
-            if (rightMost != null) {
-                var newPos = Position_atPoint(rightMost.right,rightMost.top + rightMost.height/2);
-                if (newPos != null) {
-                    newPos = Position_closestMatchForwards(newPos,Position_okForInsertion);
-                    newPos.targetX = cursorX;
-                    return newPos;
-                }
-            }
-
-            pos = new Position(paragraph.node,paragraph.endOffset);
-            pos = Position_nextMatch(pos,Position_okForMovement);
-        }
-    }
-
-    Text_closestPosBackwards = function(pos)
-    {
-        if (isNonWhitespaceTextNode(pos.node))
-            return pos;
-        var node;
-        if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset > 0)) {
-            node = pos.node.childNodes[pos.offset-1];
-            while (node.lastChild != null)
-                node = node.lastChild;
-        }
-        else {
-            node = pos.node;
-        }
-        while ((node != null) && (node != document.body) && !isNonWhitespaceTextNode(node))
-            node = prevNode(node);
-
-        if ((node == null) || (node == document.body))
-            return null;
-        else
-            return new Position(node,node.nodeValue.length);
-    }
-
-    Text_closestPosForwards = function(pos)
-    {
-        if (isNonWhitespaceTextNode(pos.node))
-            return pos;
-        var node;
-        if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset < pos.node.childNodes.length)) {
-            node = pos.node.childNodes[pos.offset];
-            while (node.firstChild != null)
-                node = node.firstChild;
-        }
-        else {
-            node = nextNodeAfter(pos.node);
-        }
-        while ((node != null) && !isNonWhitespaceTextNode(node)) {
-            var old = nodeString(node);
-            node = nextNode(node);
-        }
-
-        if (node == null)
-            return null;
-        else
-            return new Position(node,0);
-    }
-
-    Text_closestPosInDirection = function(pos,direction)
-    {
-        if ((direction == "forward") ||
-            (direction == "right") ||
-            (direction == "down")) {
-            return Text_closestPosForwards(pos);
-        }
-        else {
-            return Text_closestPosBackwards(pos);
-        }
-    }
-
-    Paragraph_runFromOffset = function(paragraph,offset,end)
-    {
-        if (paragraph.runs.length == 0)
-            throw new Error("Paragraph has no runs");
-        if (!end) {
-
-            for (var i = 0; i < paragraph.runs.length; i++) {
-                var run = paragraph.runs[i];
-                if ((offset >= run.start) && (offset < run.end))
-                    return run;
-                if ((i == paragraph.runs.length-1) && (offset == run.end))
-                    return run;
-            }
-
-        }
-        else {
-
-            for (var i = 0; i < paragraph.runs.length; i++) {
-                var run = paragraph.runs[i];
-                if ((offset > run.start) && (offset <= run.end))
-                    return run;
-                if ((i == 0) && (offset == 0))
-                    return run;
-            }
-
-        }
-    }
-
-    Paragraph_runFromNode = function(paragraph,node)
-    {
-        for (var i = 0; i < paragraph.runs.length; i++) {
-            if (paragraph.runs[i].node == node)
-                return paragraph.runs[i];
-        }
-        throw new Error("Run for text node not found");
-    }
-
-    Paragraph_positionAtOffset = function(paragraph,offset,end)
-    {
-        var run = Paragraph_runFromOffset(paragraph,offset,end);
-        if (run == null)
-            throw new Error("Run at offset "+offset+" not found");
-        return new Position(run.node,offset-run.start);
-    }
-
-    Paragraph_offsetAtPosition = function(paragraph,pos)
-    {
-        var run = Paragraph_runFromNode(paragraph,pos.node);
-        return run.start + pos.offset;
-    }
-
-    Paragraph_getRunRects = function(paragraph)
-    {
-        var rects = new Array();
-        for (var i = 0; i < paragraph.runs.length; i++) {
-            var run = paragraph.runs[i];
-            var runRange = new Range(run.node,0,run.node,run.node.nodeValue.length);
-            var runRects = Range_getClientRects(runRange);
-            Array.prototype.push.apply(rects,runRects);
-        }
-        return rects;
-    }
-
-    Paragraph_getRunOrFallbackRects = function(paragraph,pos)
-    {
-        var rects = Paragraph_getRunRects(paragraph);
-        if ((rects.length == 0) && (paragraph.node.nodeType == Node.ELEMENT_NODE)) {
-            if (isBlockNode(paragraph.node) &&
-                (paragraph.startOffset == 0) &&
-                (paragraph.endOffset == paragraph.node.childNodes.length)) {
-                rects = [paragraph.node.getBoundingClientRect()];
-            }
-            else {
-                var beforeNode = paragraph.node.childNodes[paragraph.startOffset-1];
-                var afterNode = paragraph.node.childNodes[paragraph.endOffset];
-                if ((afterNode != null) && isBlockNode(afterNode)) {
-                    rects = [afterNode.getBoundingClientRect()];
-                }
-                else if ((beforeNode != null) && isBlockNode(beforeNode)) {
-                    rects = [beforeNode.getBoundingClientRect()];
-                }
-            }
-        }
-        return rects;
-    }
-
-    function toStartOfParagraph(pos)
-    {
-        pos = Position_closestMatchBackwards(pos,Position_okForMovement);
-        if (pos == null)
-            return null;
-        var paragraph = Text_analyseParagraph(pos);
-        if (paragraph == null)
-            return null;
-
-        var newPos = new Position(paragraph.node,paragraph.startOffset);
-        return Position_closestMatchForwards(newPos,Position_okForMovement);
-    }
-
-    function toEndOfParagraph(pos)
-    {
-        pos = Position_closestMatchForwards(pos,Position_okForMovement);
-        if (pos == null)
-            return null;
-        var paragraph = Text_analyseParagraph(pos);
-        if (paragraph == null)
-            return null;
-
-        var newPos = new Position(paragraph.node,paragraph.endOffset);
-        return Position_closestMatchBackwards(newPos,Position_okForMovement);
-    }
-
-    function toStartOfLine(pos)
-    {
-        var posRect = Position_rectAtPos(pos);
-        if (posRect == null) {
-            pos = Text_closestPosBackwards(pos);
-            posRect = Position_rectAtPos(pos);
-            if (posRect == null) {
-                return null;
-            }
-        }
-
-        while (true) {
-            var check = Position_prevMatch(pos,Position_okForMovement);
-            var checkRect = Position_rectAtPos(check); // handles check == null case
-            if (checkRect == null)
-                return pos;
-            if ((checkRect.bottom <= posRect.top) || (checkRect.top >= posRect.bottom))
-                return pos;
-            pos = check;
-        }
-    }
-
-    function toEndOfLine(pos)
-    {
-        var posRect = Position_rectAtPos(pos);
-        if (posRect == null) {
-            pos = Text_closestPosForwards(pos);
-            posRect = Position_rectAtPos(pos);
-            if (posRect == null) {
-                return null;
-            }
-        }
-
-        while (true) {
-            var check = Position_nextMatch(pos,Position_okForMovement);
-            var checkRect = Position_rectAtPos(check); // handles check == null case
-            if (checkRect == null)
-                return pos;
-            if ((checkRect.bottom <= posRect.top) || (checkRect.top >= posRect.bottom))
-                return pos;
-            pos = check;
-        }
-    }
-
-    Text_toStartOfBoundary = function(pos,boundary)
-    {
-        if (boundary == "paragraph")
-            return toStartOfParagraph(pos);
-        else if (boundary == "line")
-            return toStartOfLine(pos);
-        else
-            throw new Error("Unsupported boundary: "+boundary);
-    }
-
-    Text_toEndOfBoundary = function(pos,boundary)
-    {
-        if (boundary == "paragraph")
-            return toEndOfParagraph(pos);
-        else if (boundary == "line")
-            return toEndOfLine(pos);
-        else
-            throw new Error("Unsupported boundary: "+boundary);
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/UndoManager.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/UndoManager.js b/experiments/editorFramework/src/Layer0_Javascript/UndoManager.js
deleted file mode 100644
index 9f63c43..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/UndoManager.js
+++ /dev/null
@@ -1,270 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-// FIXME: place a limit on the number of undo steps recorded - say, 30-50?
-
-var UndoManager_getLength;
-var UndoManager_getIndex;
-var UndoManager_setIndex;
-var UndoManager_print;
-var UndoManager_undo;
-var UndoManager_redo;
-var UndoManager_addAction;
-var UndoManager_newGroup;
-var UndoManager_groupType;
-var UndoManager_disableWhileExecuting;
-var UndoManager_isActive;
-var UndoManager_isDisabled;
-var UndoManager_clear;
-var UndoManager_setProperty;
-var UndoManager_deleteProperty;
-
-(function() {
-
-    var UNDO_LIMIT = 50;
-
-    function UndoGroup(type,onClose)
-    {
-        this.type = type;
-        this.onClose = onClose;
-        this.actions = new Array();
-    }
-
-    function UndoAction(fun,args)
-    {
-        this.fun = fun;
-        this.args = args;
-    }
-
-    UndoAction.prototype.toString = function()
-    {
-        var name;
-        if (this.fun.wrappedName != null)
-            name = this.fun.wrappedName;
-        else
-            name = this.fun.name;
-
-        var argStrings = new Array();
-        for (var i = 0; i < this.args.length; i++) {
-            if (this.args[i] instanceof Node)
-                argStrings.push(nodeString(this.args[i]));
-            else if (this.args[i] == null)
-                argStrings.push("null");
-            else
-                argStrings.push(this.args[i].toString());
-        }
-
-        return name + "(" + argStrings.join(",") + ")";
-    }
-
-    var undoStack = new Array();
-    var redoStack = new Array();
-    var inUndo = false;
-    var inRedo = false;
-    var currentGroup = null;
-    var disabled = 0;
-
-    // public
-    UndoManager_getLength = function()
-    {
-        return undoStack.length + redoStack.length;
-    }
-
-    // public
-    UndoManager_getIndex = function()
-    {
-        return undoStack.length;
-    }
-
-    // public
-    UndoManager_setIndex = function(index)
-    {
-        while (undoStack.length > index)
-            UndoManager_undo();
-        while (undoStack.length < index)
-            UndoManager_redo();
-    }
-
-    // public
-    UndoManager_print = function()
-    {
-        debug("");
-        debug("--------------------------------------------------------------------");
-        debug("Undo stack:");
-        for (var groupIndex = 0; groupIndex < undoStack.length; groupIndex++) {
-            var group = undoStack[groupIndex];
-            debug("    "+group.type);
-            for (var actionIndex = 0; actionIndex < group.actions.length; actionIndex++) {
-                var action = group.actions[actionIndex];
-                debug("        "+action);
-            }
-        }
-        debug("Redo stack:");
-        for (var groupIndex = 0; groupIndex < redoStack.length; groupIndex++) {
-            var group = redoStack[groupIndex];
-            debug("    "+group.type);
-            for (var actionIndex = 0; actionIndex < group.actions.length; actionIndex++) {
-                var action = group.actions[actionIndex];
-                debug("        "+action);
-            }
-        }
-        debug("Current group = "+currentGroup);
-        debug("--------------------------------------------------------------------");
-        debug("");
-    }
-
-    function closeCurrentGroup()
-    {
-        if ((currentGroup != null) && (currentGroup.onClose != null))
-            currentGroup.onClose();
-        currentGroup = null;
-    }
-
-    // public
-    UndoManager_undo = function()
-    {
-        closeCurrentGroup();
-        if (undoStack.length > 0) {
-            var group = undoStack.pop();
-            inUndo = true;
-            for (var i = group.actions.length-1; i >= 0; i--)
-                group.actions[i].fun.apply(null,group.actions[i].args);
-            inUndo = false;
-        }
-        closeCurrentGroup();
-    }
-
-    // public
-    UndoManager_redo = function()
-    {
-        closeCurrentGroup();
-        if (redoStack.length > 0) {
-            var group = redoStack.pop();
-            inRedo = true;
-            for (var i = group.actions.length-1; i >= 0; i--)
-                group.actions[i].fun.apply(null,group.actions[i].args);
-            inRedo = false;
-        }
-        closeCurrentGroup();
-    }
-
-    // public
-    UndoManager_addAction = function(fun)
-    {
-        if (disabled > 0)
-            return;
-
-        // remaining parameters after fun are arguments to be supplied to fun
-        var args = new Array();
-        for (var i = 1; i < arguments.length; i++)
-            args.push(arguments[i]);
-
-        if (!inUndo && !inRedo && (redoStack.length > 0))
-            redoStack.length = 0;
-
-        var stack = inUndo ? redoStack : undoStack;
-        if (currentGroup == null)
-            UndoManager_newGroup(null);
-
-        // Only add a group to the undo stack one it has at least one action, to avoid having
-        // empty groups present.
-        if (currentGroup.actions.length == 0) {
-            if (!inUndo && !inRedo && (stack.length == UNDO_LIMIT))
-                stack.shift();
-            stack.push(currentGroup);
-        }
-
-        currentGroup.actions.push(new UndoAction(fun,args));
-    }
-
-    // public
-    UndoManager_newGroup = function(type,onClose)
-    {
-        if (disabled > 0)
-            return;
-
-        closeCurrentGroup();
-
-        // We don't actually add the group to the undo stack until the first request to add an
-        // action to it. This way we don't end up with empty groups in the undo stack, which
-        // simplifies logic for moving back and forward through the undo history.
-
-        if ((type == null) || (type == ""))
-            type = "Anonymous";
-        currentGroup = new UndoGroup(type,onClose);
-    }
-
-    // public
-    UndoManager_groupType = function()
-    {
-        if (undoStack.length > 0)
-            return undoStack[undoStack.length-1].type;
-        else
-            return null;
-    }
-
-    UndoManager_disableWhileExecuting = function(fun) {
-        disabled++;
-        try {
-            return fun();
-        }
-        finally {
-            disabled--;
-        }
-    }
-
-    UndoManager_isActive = function()
-    {
-        return (inUndo || inRedo);
-    }
-
-    UndoManager_isDisabled = function() {
-        return (disabled > 0);
-    }
-
-    UndoManager_clear = function() {
-        undoStack.length = 0;
-        redoStack.length = 0;
-    }
-
-    function saveProperty(obj,name)
-    {
-        if (obj.hasOwnProperty(name))
-            UndoManager_addAction(UndoManager_setProperty,obj,name,obj[name]);
-        else
-            UndoManager_addAction(UndoManager_deleteProperty,obj,name);
-    }
-
-    UndoManager_setProperty = function(obj,name,value)
-    {
-        if (obj.hasOwnProperty(name) && (obj[name] == value))
-            return; // no point in adding an undo action
-        saveProperty(obj,name);
-        obj[name] = value;
-    }
-
-    UndoManager_deleteProperty = function(obj,name)
-    {
-        if (!obj.hasOwnProperty(name))
-            return; // no point in adding an undo action
-        saveProperty(obj,name);
-        delete obj[name];
-    }
-
-})();
-
-window.undoSupported = true;

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Viewport.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Viewport.js b/experiments/editorFramework/src/Layer0_Javascript/Viewport.js
deleted file mode 100644
index 47fbdfd..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Viewport.js
+++ /dev/null
@@ -1,80 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Viewport_init;
-var Viewport_setViewportWidth;
-var Viewport_setTextScale;
-
-(function() {
-
-    var viewportMetaElement = null;
-
-    // public
-    Viewport_init = function(width,textScale)
-    {
-        var head = DOM_documentHead(document);
-        for (var child = head.firstChild; child != null; child = child.nextSibling) {
-            if ((child._type == HTML_META) && (child.getAttribute("name") == "viewport")) {
-                viewportMetaElement = child;
-                break;
-            }
-        }
-
-        if (viewportMetaElement == null) {
-            viewportMetaElement = DOM_createElement(document,"META");
-            DOM_setAttribute(viewportMetaElement,"name","viewport");
-            DOM_appendChild(head,viewportMetaElement);
-        }
-
-        if (width != 0) {
-            // Only set the width and text scale if they are not already set, to avoid triggering
-            // an extra layout at load time
-            var contentValue = "width = "+width+", user-scalable = no";
-            if (viewportMetaElement.getAttribute("content") != contentValue)
-                DOM_setAttribute(viewportMetaElement,"content",contentValue);
-        }
-
-        if (textScale != 0) {
-            var pct = textScale+"%";
-            if (document.documentElement.style.getPropertyValue("-webkit-text-size-adjust") != pct)
-                DOM_setStyleProperties(document.documentElement,{"-webkit-text-size-adjust": pct});
-        }
-    }
-
-    // public
-    Viewport_setViewportWidth = function(width)
-    {
-        var contentValue = "width = "+width+", user-scalable = no";
-        if (viewportMetaElement.getAttribute("content") != contentValue)
-            DOM_setAttribute(viewportMetaElement,"content",contentValue);
-
-        Selection_update();
-        Cursor_ensureCursorVisible();
-    }
-
-    // public
-    Viewport_setTextScale = function(textScale)
-    {
-        var pct = textScale+"%";
-        if (document.documentElement.style.getPropertyValue("-webkit-text-size-adjust") != pct)
-            DOM_setStyleProperties(document.documentElement,{"-webkit-text-size-adjust": pct});
-
-        Selection_update();
-        Cursor_ensureCursorVisible();
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/check-dom-methods.sh
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/check-dom-methods.sh b/experiments/editorFramework/src/Layer0_Javascript/check-dom-methods.sh
deleted file mode 100644
index 6e17a4e..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/check-dom-methods.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-jsgrep -F '.createElement' | grep -vF '// check-ok'
-jsgrep -F '.createTextNode' | grep -vF '// check-ok'
-jsgrep -F '.createComment' | grep -vF '// check-ok'
-jsgrep -F '.appendChild' | grep -vF '// check-ok'
-jsgrep -F '.insertBefore' | grep -vF '// check-ok'
-jsgrep -F '.removeChild' | grep -vF '// check-ok'
-jsgrep -F '.cloneNode' | grep -vF '// check-ok'
-jsgrep -F '.nodeName' | grep -vE '(dtdsource/|tests/|treevis/)' | grep -vF '// check-ok'
-jsgrep -F '.setAttribute' | grep -vE '(dtdsource/|treevis/|docx/)' | grep -vF '// check-ok'
-jsgrep -F '.removeAttribute' | grep -vE '(dtdsource/|treevis/|docx/)' | grep -vF '// check-ok'
-jsgrep -F '.setProperty' | grep -vE '(dtdsource/|treevis/)' | grep -vF '// check-ok'
-jsgrep -F '.removeProperty' | grep -vE '(dtdsource/|treevis/)' | grep -vF '// check-ok'
-jsgrep -E '\.style\[.* = ' | grep -vE '(treevis/|docx/)' | grep -vF '// check-ok'
-jsgrep -E '\.style\..* = ' | grep -vE '(treevis/|docx/)' | grep -vF '// check-ok'


[08/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Selection.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Selection.js b/experiments/editorFramework/src/Layer0_Javascript/Selection.js
deleted file mode 100644
index c4f8efb..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Selection.js
+++ /dev/null
@@ -1,1430 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-// FIXME: cursor does not display correctly if it is after a space at the end of the line
-
-var Selection_isMarked;
-var Selection_get;
-var Selection_set;
-var Selection_clear;
-
-var Selection_update;
-var Selection_selectAll;
-var Selection_selectParagraph;
-var Selection_selectWordAtCursor;
-var Selection_dragSelectionBegin;
-var Selection_dragSelectionUpdate;
-var Selection_moveStartLeft;
-var Selection_moveStartRight;
-var Selection_moveEndLeft;
-var Selection_moveEndRight;
-var Selection_setSelectionStartAtCoords;
-var Selection_setSelectionEndAtCoords;
-var Selection_setTableSelectionEdgeAtCoords;
-var Selection_setEmptySelectionAt;
-var Selection_deleteRangeContents;
-var Selection_deleteContents;
-var Selection_clearSelection;
-var Selection_preserveWhileExecuting;
-var Selection_posAtStartOfWord;
-var Selection_posAtEndOfWord;
-var Selection_preferElementPositions;
-var Selection_print;
-
-(function() {
-
-    var HANDLE_NONE = 0;
-    var HANDLE_START = 1;
-    var HANDLE_END = 2;
-
-    var activeHandle = HANDLE_NONE;
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    //                                                                                            //
-    //                                 Selection getter and setter                                //
-    //                                                                                            //
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-
-    var Selection_setInternal;
-
-    (function() {
-
-        var selection = new Object();
-
-        Selection_isMarked = function()
-        {
-            if (selection.value == null)
-                return null;
-            else
-                return selection.value.isMarked;
-        }
-
-        // public
-        Selection_get = function()
-        {
-            if (selection.value == null)
-                return null;
-            else
-                return new Range(selection.value.startNode,selection.value.startOffset,
-                                 selection.value.endNode,selection.value.endOffset);
-        }
-
-        // public
-        Selection_setInternal =
-            function(newStartNode,newStartOffset,newEndNode,newEndOffset,isMarked)
-        {
-            var range = new Range(newStartNode,newStartOffset,newEndNode,newEndOffset);
-            if (!Range_isForwards(range))
-                range = new Range(newEndNode,newEndOffset,newStartNode,newStartOffset);
-            range = boundaryCompliantRange(range);
-
-            UndoManager_setProperty(selection,"value",
-                                    { startNode: range.start.node,
-                                      startOffset: range.start.offset,
-                                      endNode: range.end.node,
-                                      endOffset: range.end.offset,
-                                      isMarked: isMarked });
-        }
-
-        Selection_set = function(newStartNode,newStartOffset,newEndNode,newEndOffset,
-                                 keepActiveHandle,isMarked)
-        {
-            Selection_setInternal(newStartNode,newStartOffset,newEndNode,newEndOffset,isMarked);
-            Selection_update();
-            if (!keepActiveHandle)
-                activeHandle = HANDLE_NONE;
-        }
-
-        // public
-        Selection_clear = function()
-        {
-            UndoManager_setProperty(selection,"value",null);
-            Selection_update();
-        }
-    })();
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-    //                                                                                            //
-    //                                  Other selection functions                                 //
-    //                                                                                            //
-    ////////////////////////////////////////////////////////////////////////////////////////////////
-
-    var selectionDivs = new Array();
-    var selectionHighlights = new Array();
-    var tableSelection = null;
-
-    // private
-    updateTableSelection = function(selRange)
-    {
-        tableSelection = Tables_regionFromRange(selRange);
-        if (tableSelection == null)
-            return false;
-
-        Range_trackWhileExecuting(selRange,function() {
-
-            removeSelectionHighlights(getRangeData(null));
-
-            var sel = tableSelection;
-
-            var topLeftTD = Table_get(sel.structure,sel.top,sel.left);
-            var bottomRightTD = Table_get(sel.structure,sel.bottom,sel.right);
-
-            var topLeftRect = topLeftTD.element.getBoundingClientRect();
-            var bottomRightRect = bottomRightTD.element.getBoundingClientRect();
-
-            var left = topLeftRect.left;
-            var top = topLeftRect.top;
-
-            var bottom = bottomRightRect.bottom;
-            var right = bottomRightRect.right;
-
-            var x = left;
-            var y = top;
-            var width = right - left;
-            var height = bottom - top;
-
-            x += window.scrollX;
-            y += window.scrollY;
-
-            var div = makeSelectionDiv();
-            DOM_setAttribute(div,"class",Keys.SELECTION_HIGHLIGHT);
-            DOM_setStyleProperties(div,{ "position": "absolute",
-                                         "left": x+"px",
-                                         "top": y+"px",
-                                         "width": width+"px",
-                                         "height": height+"px",
-                                         "background-color": "rgb(201,221,238)",
-                                         "z-index": -1 });
-
-            setTableEdges(x,y,width,height);
-            setEditorHandles({ type: "table", x: x, y: y, width: width, height: height });
-        });
-
-        Selection_setInternal(selRange.start.node,selRange.start.offset,
-                              selRange.end.node,selRange.end.offset);
-
-        return true;
-    }
-
-    function makeSelectionDiv()
-    {
-        var div = DOM_createElement(document,"DIV");
-        DOM_appendChild(document.body,div);
-        selectionDivs.push(div);
-        return div;
-    }
-
-    function setTableEdges(x,y,width,height)
-    {
-        var left = makeSelectionDiv();
-        var right = makeSelectionDiv();
-        var top = makeSelectionDiv();
-        var bottom = makeSelectionDiv();
-
-        var thick = 2;
-        width++;
-        height++;
-        setBoxCoords(left,x-thick,y-thick,thick,height+2*thick);
-        setBoxCoords(right,x+width,y-thick,thick,height+2*thick);
-        setBoxCoords(top,x-thick,y-thick,width+2*thick,thick);
-        setBoxCoords(bottom,x-thick,y+height,width+2*thick,thick);
-
-        function setBoxCoords(box,x,y,width,height)
-        {
-            DOM_setStyleProperties(box,{ "position": "absolute",
-                                         "left": x+"px",
-                                         "top": y+"px",
-                                         "width": width+"px",
-                                         "height": height+"px",
-                                         "background-color": "blue",
-                                         "z-index": 1 });
-        }
-    }
-
-    var editorHandles = { type: "none" };
-    function setEditorHandles(info)
-    {
-        var oldEditorHandles = editorHandles;
-        editorHandles = info;
-        UndoManager_addAction(function() {
-            setEditorHandles(oldEditorHandles);
-        });
-        if (info.type == "cursor") {
-            Editor_setCursor(info.left,info.top,info.width,info.height);
-        }
-        else if (info.type == "selection") {
-            if (!Selection_isMarked()) {
-                Editor_setSelectionHandles(info.x1,info.y1,
-                                           info.height1,info.x2,info.y2,info.height2);
-            }
-            Editor_setSelectionBounds(info.boundsLeft,info.boundsTop,
-                                      info.boundsRight,info.boundsBottom);
-        }
-        else if (info.type == "none") {
-            Editor_clearSelectionHandlesAndCursor();
-        }
-        else if (info.type == "table") {
-            Editor_setTableSelection(info.x,info.y,info.width,info.height);
-        }
-        else {
-            throw new Error("setEditorHandles: unknown type "+type);
-        }
-    }
-
-    function getPrevHighlightText(node)
-    {
-        if ((node.previousSibling != null) &&
-            isSelectionHighlight(node.previousSibling) &&
-            (node.previousSibling.lastChild != null) &&
-            (node.previousSibling.lastChild.nodeType == Node.TEXT_NODE))
-            return node.previousSibling.lastChild;
-        else
-            return null;
-    }
-
-    function getNextHighlightText(node)
-    {
-        if ((node.nextSibling != null) &&
-            isSelectionHighlight(node.nextSibling) &&
-            (node.nextSibling.firstChild != null) &&
-            (node.nextSibling.firstChild.nodeType == Node.TEXT_NODE))
-            return node.nextSibling.firstChild;
-        else
-            return null;
-    }
-
-    function getTextNodeBefore(node)
-    {
-        var prev = node.previousSibling;
-        if ((prev != null) && (prev.nodeType == Node.TEXT_NODE)) {
-            return prev;
-        }
-        else {
-            var text = DOM_createTextNode(document,"");
-            DOM_insertBefore(node.parentNode,text,node);
-            return text;
-        }
-    }
-
-    function getTextNodeAfter(node)
-    {
-        var next = node.nextSibling;
-        if ((next != null) && (next.nodeType == Node.TEXT_NODE)) {
-            return next;
-        }
-        else {
-            var text = DOM_createTextNode(document,"");
-            DOM_insertBefore(node.parentNode,text,node.nextSibling);
-            return text;
-        }
-    }
-
-    function setSelectionHighlights(highlights)
-    {
-        UndoManager_addAction(setSelectionHighlights,selectionHighlights);
-        selectionHighlights = highlights;
-    }
-
-    function createSelectionHighlights(data)
-    {
-        var newHighlights = arrayCopy(selectionHighlights);
-
-        var outermost = data.outermost;
-        for (var i = 0; i < outermost.length; i++) {
-            recurse(outermost[i]);
-        }
-
-        setSelectionHighlights(newHighlights);
-
-        function recurse(node)
-        {
-            if (isSpecialBlockNode(node)) {
-                if (!isSelectionHighlight(node.parentNode)) {
-                    var wrapped = DOM_wrapNode(node,"DIV");
-                    DOM_setAttribute(wrapped,"class",Keys.SELECTION_CLASS);
-                    newHighlights.push(wrapped);
-                }
-            }
-            else if (isNoteNode(node)) {
-                if (!isSelectionHighlight(node.parentNode)) {
-                    var wrapped = DOM_wrapNode(node,"SPAN");
-                    DOM_setAttribute(wrapped,"class",Keys.SELECTION_CLASS);
-                    newHighlights.push(wrapped);
-                }
-            }
-            else if (node.nodeType == Node.TEXT_NODE) {
-                createTextHighlight(node,data,newHighlights);
-            }
-            else {
-                var next;
-                for (var child = node.firstChild; child != null; child = next) {
-                    next = child.nextSibling;
-                    recurse(child);
-                }
-            }
-        }
-    }
-
-    function createTextHighlight(node,data,newHighlights)
-    {
-        var selRange = data.range;
-        if (isSelectionHighlight(node.parentNode)) {
-
-            if ((node == selRange.end.node) && (node.nodeValue.length > selRange.end.offset)) {
-                var destTextNode = getTextNodeAfter(node.parentNode);
-                DOM_moveCharacters(node,
-                                   selRange.end.offset,
-                                   node.nodeValue.length,
-                                   destTextNode,0,
-                                   true,false);
-            }
-            if ((node == selRange.start.node) && (selRange.start.offset > 0)) {
-                var destTextNode = getTextNodeBefore(node.parentNode);
-                DOM_moveCharacters(node,
-                                   0,
-                                   selRange.start.offset,
-                                   destTextNode,destTextNode.nodeValue.length,
-                                   false,true);
-            }
-
-            return;
-        }
-
-        var anext;
-        for (var a = node; a != null; a = anext) {
-            anext = a.parentNode;
-            if (isSelectionHighlight(a))
-                DOM_removeNodeButKeepChildren(a);
-        }
-
-        if (node == selRange.end.node) {
-            if (isWhitespaceString(node.nodeValue.substring(0,selRange.end.offset)))
-                return;
-            Formatting_splitTextAfter(selRange.end,
-                                      function() { return true; });a
-        }
-
-
-        if (node == selRange.start.node) {
-            if (isWhitespaceString(node.nodeValue.substring(selRange.start.offset)))
-                return;
-            Formatting_splitTextBefore(selRange.start,
-                                       function() { return true; });
-        }
-
-        var prevText = getPrevHighlightText(node);
-        var nextText = getNextHighlightText(node);
-
-        if ((prevText != null) && containsSelection(data.nodeSet,prevText)) {
-            DOM_moveCharacters(node,0,node.nodeValue.length,
-                               prevText,prevText.nodeValue.length,true,false);
-            DOM_deleteNode(node);
-        }
-        else if ((nextText != null) && containsSelection(data.nodeSet,nextText)) {
-            DOM_moveCharacters(node,0,node.nodeValue.length,
-                               nextText,0,false,true);
-            DOM_deleteNode(node);
-        }
-        else if (!isWhitespaceTextNode(node)) {
-            // Call moveCharacters() with an empty range, to force any tracked positions
-            // that are at the end of prevText or the start of nextText to move into this
-            // node
-            if (prevText != null) {
-                DOM_moveCharacters(prevText,
-                                   prevText.nodeValue.length,prevText.nodeValue.length,
-                                   node,0);
-            }
-            if (nextText != null) {
-                DOM_moveCharacters(nextText,0,0,node,node.nodeValue.length);
-            }
-
-            var wrapped = DOM_wrapNode(node,"SPAN");
-            DOM_setAttribute(wrapped,"class",Keys.SELECTION_CLASS);
-            newHighlights.push(wrapped);
-        }
-    }
-
-    function getRangeData(selRange)
-    {
-        var nodeSet = new NodeSet();
-        var nodes;
-        var outermost;
-        if (selRange != null) {
-            outermost = Range_getOutermostNodes(selRange);
-            nodes = Range_getAllNodes(selRange);
-            for (var i = 0; i < nodes.length; i++)
-                nodeSet.add(nodes[i]);
-        }
-        else {
-            nodes = new Array();
-            outermost = new Array();
-        }
-        return { range: selRange, nodeSet: nodeSet, nodes: nodes, outermost: outermost };
-    }
-
-    function removeSelectionHighlights(data,force)
-    {
-        var selectedSet = data.nodeSet;
-
-        var remainingHighlights = new Array();
-        var checkMerge = new Array();
-        for (var i = 0; i < selectionHighlights.length; i++) {
-            var span = selectionHighlights[i];
-            if ((span.parentNode != null) && (force || !containsSelection(selectedSet,span))) {
-                if (span.firstChild != null)
-                    checkMerge.push(span.firstChild);
-                if (span.lastChild != null)
-                    checkMerge.push(span.lastChild);
-
-                DOM_removeNodeButKeepChildren(span);
-            }
-            else if (span.parentNode != null) {
-                remainingHighlights.push(span);
-            }
-        }
-        setSelectionHighlights(remainingHighlights);
-
-        for (var i = 0; i < checkMerge.length; i++) {
-            // if not already merged
-            if ((checkMerge[i] != null) && (checkMerge[i].parentNode != null)) {
-                Formatting_mergeWithNeighbours(checkMerge[i],{});
-            }
-        }
-    }
-
-    function containsSelection(selectedSet,node)
-    {
-        if (selectedSet.contains(node))
-            return true;
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            if (containsSelection(selectedSet,child))
-                return true;
-        }
-        return false;
-    }
-
-    Selection_update = function()
-    {
-        var selRange = Selection_get();
-        var selMarked = Selection_isMarked();
-
-        Range_trackWhileExecuting(selRange,function() {
-            // Remove table selection DIVs
-            for (var i = 0; i < selectionDivs.length; i++)
-                DOM_deleteNode(selectionDivs[i]);
-            selectionDivs = new Array();
-        });
-
-        if (selRange == null) {
-            DOM_ignoreMutationsWhileExecuting(function() {
-                removeSelectionHighlights(getRangeData(null));
-            });
-            return;
-        }
-
-        Range_assertValid(selRange,"Selection");
-
-        if (Range_isEmpty(selRange)) {
-            // We just have a cursor
-
-            Range_trackWhileExecuting(selRange,function() {
-                DOM_ignoreMutationsWhileExecuting(function() {
-                    removeSelectionHighlights(getRangeData(selRange));
-                });
-            });
-            // Selection may have changed as a result of removeSelectionHighlights()
-            Selection_setInternal(selRange.start.node,selRange.start.offset,
-                                  selRange.end.node,selRange.end.offset,
-                                  selMarked);
-            selRange = Selection_get(); // since setInternal can theoretically change it
-
-            // If we can't find the cursor rect for some reason, just don't update the position.
-            // This is better than using an incorrect position or throwing an exception.
-            var rect = Position_displayRectAtPos(selRange.end);
-            if (rect != null) {
-                var left = rect.left + window.scrollX;
-                var top = rect.top + window.scrollY;
-                var height = rect.height;
-                var width = rect.width ? rect.width : 2;
-                setEditorHandles({ type: "cursor",
-                                   left: left,
-                                   top: top,
-                                   width: width,
-                                   height: height});
-            }
-            return;
-        }
-
-        if (updateTableSelection(selRange))
-            return;
-
-        var rects = Range_getClientRects(selRange);
-
-        if ((rects != null) && (rects.length > 0)) {
-            var boundsLeft = null;
-            var boundsRight = null;
-            var boundsTop = null;
-            var boundsBottom = null
-
-            for (var i = 0; i < rects.length; i++) {
-                var left = rects[i].left + window.scrollX;
-                var top = rects[i].top + window.scrollY;
-                var width = rects[i].width;
-                var height = rects[i].height;
-                var right = left + width;
-                var bottom = top + height;
-
-                if (boundsLeft == null) {
-                    boundsLeft = left;
-                    boundsTop = top;
-                    boundsRight = right;
-                    boundsBottom = bottom;
-                }
-                else {
-                    if (boundsLeft > left)
-                        boundsLeft = left;
-                    if (boundsRight < right)
-                        boundsRight = right;
-                    if (boundsTop > top)
-                        boundsTop = top;
-                    if (boundsBottom < bottom)
-                        boundsBottom = bottom;
-                }
-            }
-
-            Range_trackWhileExecuting(selRange,function() {
-                DOM_ignoreMutationsWhileExecuting(function() {
-                    var data = getRangeData(selRange);
-                    createSelectionHighlights(data);
-                    removeSelectionHighlights(data);
-                });
-            });
-
-            // Selection may have changed as a result of create/removeSelectionHighlights()
-            Selection_setInternal(selRange.start.node,selRange.start.offset,
-                                  selRange.end.node,selRange.end.offset,
-                                  selMarked);
-
-            var firstRect = rects[0];
-            var lastRect = rects[rects.length-1];
-
-            var x1 = firstRect.left + window.scrollX;
-            var y1 = firstRect.top + window.scrollY;
-            var height1 = firstRect.height;
-            var x2 = lastRect.right + window.scrollX;
-            var y2 = lastRect.top + window.scrollY;
-            var height2 = lastRect.height;
-
-            setEditorHandles({ type: "selection",
-                               x1: x1,
-                               y1: y1,
-                               height1: height1,
-                               x2: x2,
-                               y2: y2,
-                               height2: height2,
-                               boundsLeft: boundsLeft,
-                               boundsTop: boundsTop,
-                               boundsRight: boundsRight,
-                               boundsBottom: boundsBottom });;
-
-        }
-        else {
-            setEditorHandles({ type: "none" });
-        }
-        return;
-
-        function getAbsoluteOffset(node)
-        {
-            var offsetLeft = 0;
-            var offsetTop = 0;
-            for (; node != null; node = node.parentNode) {
-                if (node.offsetLeft != null)
-                    offsetLeft += node.offsetLeft;
-                if (node.offsetTop != null)
-                    offsetTop += node.offsetTop;
-            }
-            return { offsetLeft: offsetLeft, offsetTop: offsetTop };
-        }
-    }
-
-    // public
-    Selection_selectAll = function()
-    {
-        Selection_set(document.body,0,document.body,document.body.childNodes.length);
-    }
-
-    // public
-    Selection_selectParagraph = function()
-    {
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-        var startNode = Position_closestActualNode(selRange.start);
-        while (!isParagraphNode(startNode) && !isContainerNode(startNode))
-            startNode = startNode.parentNode;
-
-        var endNode = Position_closestActualNode(selRange.end);
-        while (!isParagraphNode(endNode) && !isContainerNode(endNode))
-            endNode = endNode.parentNode;
-
-        var startPos = new Position(startNode,0);
-        var endPos = new Position(endNode,DOM_maxChildOffset(endNode));
-        startPos = Position_closestMatchForwards(startPos,Position_okForMovement);
-        endPos = Position_closestMatchBackwards(endPos,Position_okForMovement);
-
-        Selection_set(startPos.node,startPos.offset,endPos.node,endPos.offset);
-    }
-
-    // private
-    function getPunctuationCharsForRegex()
-    {
-        var escaped = "^$\\.*+?()[]{}|"; // From ECMAScript regexp spec (PatternCharacter)
-        var unescaped = "";
-        for (var i = 32; i <= 127; i++) {
-            var c = String.fromCharCode(i);
-            if ((escaped.indexOf(c) < 0) && !c.match(/[\w\d]/))
-                unescaped += c;
-        }
-        return unescaped + escaped.replace(/(.)/g,"\\$1");
-    }
-
-    // The following regular expressions are used by selectWordAtCursor(). We initialise them at
-    // startup to avoid repeatedly initialising them.
-    var punctuation = getPunctuationCharsForRegex();
-    var wsPunctuation = "\\s"+punctuation;
-
-    // Note: We use a blacklist of punctuation characters here instead of a whitelist of "word"
-    // characters, as the \w character class in javascript regular expressions only matches
-    // characters in english words. By using a blacklist, and assuming every other character is
-    // part of a word, we can select words containing non-english characters. This isn't a perfect
-    // solution, because there are many unicode characters that represent punctuation as well, but
-    // at least we handle the common ones here.
-
-    var reOtherEnd = new RegExp("["+wsPunctuation+"]*$");
-    var reOtherStart = new RegExp("^["+wsPunctuation+"]*");
-    var reWordOtherEnd = new RegExp("[^"+wsPunctuation+"]*["+wsPunctuation+"]*$");
-    var reWordOtherStart = new RegExp("^["+wsPunctuation+"]*[^"+wsPunctuation+"]*");
-
-    var reWordStart = new RegExp("^[^"+wsPunctuation+"]+");
-    var reWordEnd = new RegExp("[^"+wsPunctuation+"]+$");
-
-    Selection_posAtStartOfWord = function(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if (node.nodeType == Node.TEXT_NODE) {
-            var before = node.nodeValue.substring(0,offset);
-            var matches = before.match(reWordEnd);
-            if (matches) {
-                var wordStart = offset - matches[0].length;
-                return new Position(node,wordStart);
-            }
-        }
-
-        return pos;
-    }
-
-    Selection_posAtEndOfWord = function(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if (node.nodeType == Node.TEXT_NODE) {
-            var after = node.nodeValue.substring(offset);
-            var matches = after.match(reWordStart);
-            if (matches) {
-                var wordEnd = offset + matches[0].length;
-                return new Position(node,wordEnd);
-            }
-        }
-
-        return pos;
-    }
-
-    function rangeOfWordAtPos(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if (node.nodeType == Node.TEXT_NODE) {
-            var before = node.nodeValue.substring(0,offset);
-            var after = node.nodeValue.substring(offset);
-
-            var otherBefore = before.match(reOtherEnd)[0];
-            var otherAfter = after.match(reOtherStart)[0];
-
-            var wordOtherBefore = before.match(reWordOtherEnd)[0];
-            var wordOtherAfter = after.match(reWordOtherStart)[0];
-
-            var startOffset = offset;
-            var endOffset = offset;
-
-            var haveWordBefore = (wordOtherBefore.length != otherBefore.length);
-            var haveWordAfter = (wordOtherAfter.length != otherAfter.length);
-
-            if ((otherBefore.length == 0) && (otherAfter.length == 0)) {
-                startOffset = offset - wordOtherBefore.length;
-                endOffset = offset + wordOtherAfter.length;
-            }
-            else if (haveWordBefore && !haveWordAfter) {
-                startOffset = offset - wordOtherBefore.length;
-            }
-            else if (haveWordAfter && !haveWordBefore) {
-                endOffset = offset + wordOtherAfter.length;
-            }
-            else if (otherBefore.length <= otherAfter.length) {
-                startOffset = offset - wordOtherBefore.length;
-            }
-            else {
-                endOffset = offset + wordOtherAfter.length;
-            }
-
-            return new Range(node,startOffset,node,endOffset);
-        }
-        else if (node.nodeType == Node.ELEMENT_NODE) {
-            var nodeBefore = node.childNodes[offset-1];
-            var nodeAfter = node.childNodes[offset];
-
-            if ((nodeBefore != null) && !isWhitespaceTextNode(nodeBefore))
-                return new Range(node,offset-1,node,offset);
-            else if ((nodeAfter != null) && !isWhitespaceTextNode(nodeAfter))
-                return new Range(node,offset,node,offset+1);
-        }
-
-        return null;
-    }
-
-    // public
-    Selection_selectWordAtCursor = function()
-    {
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-
-        var pos = Position_closestMatchBackwards(selRange.end,Position_okForMovement);
-        var range = rangeOfWordAtPos(pos);
-        if (range != null) {
-            Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
-        }
-    }
-
-    // public
-    Selection_dragSelectionBegin = function(x,y,selectWord)
-    {
-        var pos = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
-
-        if (pos == null) {
-            Selection_clear();
-            return "error";
-        }
-
-        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-
-        if (selectWord)
-            Selection_selectWordAtCursor();
-
-        return "end";
-    }
-
-    var selectionHandleEnd = true;
-
-    function toStartOfWord(pos)
-    {
-        if (Input_isAtWordBoundary(pos,"backward"))
-            return pos;
-        var boundary = Input_toWordBoundary(pos,"backward");
-        return (boundary != null) ? boundary : pos;
-    }
-
-    function toEndOfWord(pos)
-    {
-        if (Input_isAtWordBoundary(pos,"forward"))
-            return pos;
-        var boundary = Input_toWordBoundary(pos,"forward");
-        return (boundary != null) ? boundary : pos;
-    }
-
-    // public
-    Selection_dragSelectionUpdate = function(x,y,selectWord)
-    {
-        y = Cursor_scrollDocumentForY(y);
-
-        var pos = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
-        var selRange = Selection_get();
-        if ((pos == null) || (selRange == null))
-            return "none";
-
-        var start = selRange.start;
-        var end = selRange.end;
-
-        if (selectionHandleEnd) {
-            if (Position_compare(pos,start) < 0) {
-                if (selectWord)
-                    pos = toStartOfWord(pos);
-                selectionHandleEnd = false;
-            }
-            else {
-                if (selectWord)
-                    pos = toEndOfWord(pos);
-            }
-            Selection_set(start.node,start.offset,pos.node,pos.offset);
-        }
-        else {
-            if (Position_compare(pos,end) > 0) {
-                if (selectWord)
-                    pos = toEndOfWord(pos);
-                selectionHandleEnd = true;
-            }
-            else {
-                if (selectWord)
-                    pos = toStartOfWord(pos);
-            }
-            Selection_set(pos.node,pos.offset,end.node,end.offset);
-        }
-
-        return selectionHandleEnd ? "end" : "start";
-    }
-
-    function moveBoundary(command)
-    {
-        var range = Selection_get();
-        if (range == null)
-            return;
-
-        var pos = null;
-        if (command == "start-left")
-            range.start = pos = Position_prevMatch(range.start,Position_okForMovement);
-        else if (command == "start-right")
-            range.start = pos = Position_nextMatch(range.start,Position_okForMovement);
-        else if (command == "end-left")
-            range.end = pos = Position_prevMatch(range.end,Position_okForMovement);
-        else if (command == "end-right")
-            range.end = pos = Position_nextMatch(range.end,Position_okForMovement);
-
-        if ((range.start != null) && (range.end != null)) {
-            var result;
-            range = Range_forwards(range);
-            Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
-            if (range.end == pos)
-                return "end";
-            else if (range.end == pos)
-                return "start";
-        }
-        return null;
-    }
-
-    // public
-    Selection_moveStartLeft = function()
-    {
-        return moveBoundary("start-left");
-    }
-
-    // public
-    Selection_moveStartRight = function()
-    {
-        return moveBoundary("start-right");
-    }
-
-    // public
-    Selection_moveEndLeft = function()
-    {
-        return moveBoundary("end-left");
-    }
-
-    // public
-    Selection_moveEndRight = function()
-    {
-        return moveBoundary("end-right");
-    }
-
-    // public
-    Selection_setSelectionStartAtCoords = function(x,y)
-    {
-        var position = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
-        if (position != null) {
-            position = Position_closestMatchBackwards(position,Position_okForMovement);
-            var selRange = Selection_get();
-            var newRange = new Range(position.node,position.offset,
-                                     selRange.end.node,selRange.end.offset);
-            if (Range_isForwards(newRange)) {
-                Selection_set(newRange.start.node,newRange.start.offset,
-                              newRange.end.node,newRange.end.offset);
-            }
-        }
-    }
-
-    // public
-    Selection_setSelectionEndAtCoords = function(x,y)
-    {
-        var position = Position_closestMatchForwards(Position_atPoint(x,y),Position_okForMovement);
-        if (position != null) {
-            position = Position_closestMatchBackwards(position,Position_okForMovement);
-            var selRange = Selection_get();
-            var newRange = new Range(selRange.start.node,selRange.start.offset,
-                                     position.node,position.offset);
-            if (Range_isForwards(newRange)) {
-                Selection_set(newRange.start.node,newRange.start.offset,
-                              newRange.end.node,newRange.end.offset);
-            }
-        }
-    }
-
-    // public
-    Selection_setTableSelectionEdgeAtCoords = function(edge,x,y)
-    {
-        if (tableSelection == null)
-            return;
-
-        var structure = tableSelection.structure;
-        var pointInfo = findCellInTable(structure,x,y);
-        if (pointInfo == null)
-            return;
-
-        if (edge == "topLeft") {
-            if (pointInfo.row <= tableSelection.bottom)
-                tableSelection.top = pointInfo.row;
-            if (pointInfo.col <= tableSelection.right)
-                tableSelection.left = pointInfo.col;
-        }
-        else if (edge == "bottomRight") {
-            if (pointInfo.row >= tableSelection.top)
-                tableSelection.bottom = pointInfo.row;
-            if (pointInfo.col >= tableSelection.left)
-                tableSelection.right = pointInfo.col;
-        }
-
-        // FIXME: handle the case where there is no cell at the specified row and column
-        var topLeftCell = Table_get(structure,tableSelection.top,tableSelection.left);
-        var bottomRightCell = Table_get(structure,tableSelection.bottom,tableSelection.right);
-
-        var topLeftNode = topLeftCell.element.parentNode;
-        var topLeftOffset = DOM_nodeOffset(topLeftCell.element);
-        var bottomRightNode = bottomRightCell.element.parentNode;
-        var bottomRightOffset = DOM_nodeOffset(bottomRightCell.element)+1;
-
-        Selection_set(topLeftNode,topLeftOffset,bottomRightNode,bottomRightOffset);
-
-        // FIXME: this could possibly be optimised
-        function findCellInTable(structure,x,y)
-        {
-            for (var r = 0; r < structure.numRows; r++) {
-                for (var c = 0; c < structure.numCols; c++) {
-                    var cell = Table_get(structure,r,c);
-                    if (cell != null) {
-                        var rect = cell.element.getBoundingClientRect();
-                        if ((x >= rect.left) && (x <= rect.right) &&
-                            (y >= rect.top) && (y <= rect.bottom))
-                            return cell;
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    // public
-    Selection_setEmptySelectionAt = function(node,offset)
-    {
-        Selection_set(node,offset,node,offset);
-    }
-
-    // private
-    function deleteTextSelection(selRange,keepEmpty)
-    {
-        var nodes = Range_getOutermostNodes(selRange);
-        for (var i = 0; i < nodes.length; i++) {
-            var node = nodes[i];
-
-            var removeWholeNode = false;
-
-            if ((node == selRange.start.node) &&
-                (node == selRange.end.node)) {
-                var startOffset = selRange.start.offset;
-                var endOffset = selRange.end.offset;
-                if ((node.nodeType == Node.TEXT_NODE) &&
-                    ((startOffset > 0) || (endOffset < node.nodeValue.length))) {
-                    DOM_deleteCharacters(node,startOffset,endOffset);
-                }
-                else {
-                    removeWholeNode = true;
-                }
-            }
-            else if (node == selRange.start.node) {
-                var offset = selRange.start.offset;
-                if ((node.nodeType == Node.TEXT_NODE) && (offset > 0)) {
-                    DOM_deleteCharacters(node,offset);
-                }
-                else {
-                    removeWholeNode = true;
-                }
-            }
-            else if (node == selRange.end.node) {
-                var offset = selRange.end.offset;
-                if ((node.nodeType == Node.TEXT_NODE) && (offset < node.nodeValue.length)) {
-                    DOM_deleteCharacters(node,0,offset);
-                }
-                else {
-                    removeWholeNode = true;
-                }
-            }
-            else {
-                removeWholeNode = true;
-            }
-
-            if (removeWholeNode) {
-                switch (node._type) {
-                case HTML_TD:
-                case HTML_TH:
-                    DOM_deleteAllChildren(node);
-                    break;
-                default:
-                    DOM_deleteNode(node);
-                    break;
-                }
-            }
-        }
-
-        var detail = Range_detail(selRange);
-
-        var sameTextNode = (selRange.start.node == selRange.end.node) &&
-                           (selRange.start.node.nodeType == Node.TEXT_NODE);
-
-        if ((detail.startAncestor != null) && (detail.endAncestor != null) &&
-            (detail.startAncestor.nextSibling == detail.endAncestor) &&
-            !sameTextNode) {
-            prepareForMerge(detail);
-            DOM_mergeWithNextSibling(detail.startAncestor,
-                                          Formatting_MERGEABLE_BLOCK_AND_INLINE);
-            if (isParagraphNode(detail.startAncestor) &&
-                (detail.startAncestor._type != HTML_DIV))
-                removeParagraphDescendants(detail.startAncestor);
-        }
-
-        if (!keepEmpty) {
-            var startNode = selRange.start.node;
-            var endNode = selRange.end.node;
-            if (startNode.parentNode != null)
-                delEmpty(selRange,startNode);
-            if (endNode.parentNode != null)
-                delEmpty(selRange,endNode);
-        }
-
-        Cursor_updateBRAtEndOfParagraph(Range_singleNode(selRange));
-    }
-
-    function delEmpty(selRange,node)
-    {
-        while ((node != document.body) &&
-               (node.nodeType == Node.ELEMENT_NODE) &&
-               (node.firstChild == null)) {
-
-            if (isTableCell(node) || isTableCell(node.parentNode))
-                return;
-
-            if (!fixPositionOutside(selRange.start,node))
-                break;
-            if (!fixPositionOutside(selRange.end,node))
-                break;
-
-            var parent = node.parentNode;
-            Range_trackWhileExecuting(selRange,function() {
-                DOM_deleteNode(node);
-            });
-            node = parent;
-        }
-    }
-
-    function fixPositionOutside(pos,node)
-    {
-        if (pos.node == node) {
-            var before = new Position(node.parentNode,DOM_nodeOffset(node));
-            var after = new Position(node.parentNode,DOM_nodeOffset(node)+1);
-            before = Position_prevMatch(before,Position_okForMovement);
-            after = Position_nextMatch(after,Position_okForMovement);
-
-            if (before != null) {
-                pos.node = before.node;
-                pos.offset = before.offset;
-            }
-            else if (after != null) {
-                pos.node = after.node;
-                pos.offset = after.offset;
-            }
-            else {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    Selection_deleteRangeContents = function(range,keepEmpty)
-    {
-        Range_trackWhileExecuting(range,function() {
-            DOM_ignoreMutationsWhileExecuting(function() {
-                removeSelectionHighlights(getRangeData(range),true);
-            });
-
-            var region = Tables_regionFromRange(range);
-            if (region != null)
-                Tables_deleteRegion(region);
-            else
-                deleteTextSelection(range,keepEmpty);
-        });
-
-        Selection_set(range.start.node,range.start.offset,range.start.node,range.start.offset);
-    }
-
-    Selection_deleteContents = function(keepEmpty)
-    {
-        var range = Selection_get();
-        if (range == null)
-            return;
-        Selection_deleteRangeContents(range,keepEmpty);
-    }
-
-    // private
-    function removeParagraphDescendants(parent)
-    {
-        var next;
-        for (var child = parent.firstChild; child != null; child = next) {
-            next = child.nextSibling;
-            removeParagraphDescendants(child);
-            if (isParagraphNode(child))
-                DOM_removeNodeButKeepChildren(child);
-        }
-    }
-
-    // private
-    function findFirstParagraph(node)
-    {
-        if (isParagraphNode(node))
-            return node;
-        if (node._type == HTML_LI) {
-            var nonWhitespaceInline = false;
-
-            for (var child = node.firstChild; child != null; child = child.nextSibling) {
-                if (isInlineNode(child) && !isWhitespaceTextNode(child))
-                    nonWhitespaceInline = true;
-
-                if (isParagraphNode(child)) {
-                    if (nonWhitespaceInline)
-                        return putPrecedingSiblingsInParagraph(node,child);
-                    return child;
-                }
-                else if (isListNode(child)) {
-                    if (nonWhitespaceInline)
-                        return putPrecedingSiblingsInParagraph(node,child);
-                    return findFirstParagraph(child);
-                }
-            }
-            if (nonWhitespaceInline)
-                return putPrecedingSiblingsInParagraph(node,null);
-        }
-        return null;
-
-        function putPrecedingSiblingsInParagraph(parent,node)
-        {
-            var p = DOM_createElement(document,"P");
-            while (parent.firstChild != node)
-                DOM_appendChild(p,parent.firstChild);
-            return p;
-        }
-    }
-
-    // private
-    function prepareForMerge(detail)
-    {
-        if (isParagraphNode(detail.startAncestor) && isInlineNode(detail.endAncestor)) {
-            var name = detail.startAncestor.nodeName; // check-ok
-            var newParagraph = DOM_createElement(document,name);
-            DOM_insertBefore(detail.endAncestor.parentNode,newParagraph,detail.endAncestor);
-            DOM_appendChild(newParagraph,detail.endAncestor);
-            detail.endAncestor = newParagraph;
-        }
-        else if (isInlineNode(detail.startAncestor) && isParagraphNode(detail.endAncestor)) {
-            var name = detail.endAncestor.nodeName; // check-ok
-            var newParagraph = DOM_createElement(document,name);
-            DOM_insertBefore(detail.startAncestor.parentNode,newParagraph,
-                             detail.startAncestor.nextSibling);
-            DOM_appendChild(newParagraph,detail.startAncestor);
-            detail.startAncestor = newParagraph;
-        }
-        else if (isParagraphNode(detail.startAncestor) &&
-                 isListNode(detail.endAncestor) &&
-                 (detail.endAncestor.firstChild._type == HTML_LI)) {
-            var list = detail.endAncestor;
-            var li = detail.endAncestor.firstChild;
-
-            var paragraph = findFirstParagraph(li);
-            if (paragraph != null) {
-                DOM_insertBefore(list.parentNode,paragraph,list);
-                var name = detail.startAncestor.nodeName; // check-ok
-                DOM_replaceElement(paragraph,name);
-            }
-            if (!nodeHasContent(li))
-                DOM_deleteNode(li);
-            if (firstChildElement(list) == null)
-                DOM_deleteNode(list);
-        }
-        else if (isParagraphNode(detail.endAncestor) &&
-                 isListNode(detail.startAncestor) &&
-                 (detail.startAncestor.lastChild._type == HTML_LI)) {
-            var list = detail.startAncestor;
-            var li = detail.startAncestor.lastChild;
-            var p = detail.endAncestor;
-            var oldLastChild = li.lastChild;
-            while (p.firstChild != null)
-                DOM_insertBefore(li,p.firstChild,null);
-            DOM_deleteNode(p);
-            if (oldLastChild != null) {
-                DOM_mergeWithNextSibling(oldLastChild,
-                                              Formatting_MERGEABLE_BLOCK_AND_INLINE);
-            }
-        }
-
-        if ((detail.startAncestor.lastChild != null) && (detail.endAncestor.firstChild != null)) {
-            var childDetail = new Object();
-            childDetail.startAncestor = detail.startAncestor.lastChild;
-            childDetail.endAncestor = detail.endAncestor.firstChild;
-            prepareForMerge(childDetail);
-        }
-    }
-
-    // public
-    Selection_clearSelection = function()
-    {
-        Selection_clear();
-    }
-
-    // public
-    Selection_preserveWhileExecuting = function(fun)
-    {
-        var range = Selection_get();
-
-        // Since the selection may have changed as a result of changes to the document, we
-        // have to call clear() or set() so that undo history is saved
-        if (range == null) {
-            result = fun();
-            Selection_clear();
-        }
-        else {
-            result = Range_trackWhileExecuting(range,fun);
-            Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
-        }
-        return result;
-    }
-
-    Selection_preferElementPositions = function()
-    {
-        var range = Selection_get();
-        if (range == null)
-            return;
-        range.start = Position_preferElementPosition(range.start);
-        range.end = Position_preferElementPosition(range.end);
-        Selection_set(range.start.node,range.start.offset,
-                      range.end.node,range.end.offset);
-    }
-
-    function getBoundaryContainer(node,topAncestor)
-    {
-        var container = document.body;
-        for (; node != topAncestor.parentNode; node = node.parentNode) {
-            switch (node._type) {
-            case HTML_FIGURE:
-            case HTML_TABLE:
-                container = node;
-                break;
-            }
-        }
-        return container;
-    }
-
-    function boundaryCompliantRange(range)
-    {
-        if (range == null)
-            return null;
-
-        var detail = Range_detail(range);
-        var start = range.start;
-        var end = range.end;
-        var startNode = Position_closestActualNode(start);
-        var endNode = Position_closestActualNode(end);
-        var startContainer = getBoundaryContainer(startNode.parentNode,detail.commonAncestor);
-        var endContainer = getBoundaryContainer(endNode.parentNode,detail.commonAncestor);
-
-        if (startContainer != endContainer) {
-
-            var doStart = false;
-            var doEnd = false;
-
-            if (nodeHasAncestor(startContainer,endContainer)) {
-                doStart = true;
-            }
-            else if (nodeHasAncestor(endContainer,startContainer)) {
-                doEnd = true;
-            }
-            else {
-                doStart = true;
-                doEnd = true;
-            }
-
-            if (doStart && (startContainer != document.body))
-                start = new Position(startContainer.parentNode,DOM_nodeOffset(startContainer));
-            if (doEnd && (endContainer != document.body))
-                end = new Position(endContainer.parentNode,DOM_nodeOffset(endContainer)+1);
-        }
-        return new Range(start.node,start.offset,end.node,end.offset);
-
-        function nodeHasAncestor(node,ancestor)
-        {
-            for (; node != null; node = node.parentNode) {
-                if (node == ancestor)
-                    return true;
-            }
-            return false;
-        }
-    }
-
-    Selection_print = function()
-    {
-        debug("");
-        debug("");
-        debug("");
-        debug("================================================================================");
-
-        var sel = Selection_get();
-        if (sel == null) {
-            debug("No selection");
-            return;
-        }
-
-        printSelectionElement(document.body,"");
-
-        function printSelectionElement(node,indent)
-        {
-            var className = DOM_getAttribute(node,"class");
-            if (className != null)
-                debug(indent+node.nodeName+" ("+className+")");
-            else
-                debug(indent+node.nodeName);
-
-            var child = node.firstChild;
-            var offset = 0;
-            while (true) {
-
-                var isStart = ((sel.start.node == node) && (sel.start.offset == offset));
-                var isEnd = ((sel.end.node == node) && (sel.end.offset == offset));
-                if (isStart && isEnd)
-                    debug(indent+"    []");
-                else if (isStart)
-                    debug(indent+"    [");
-                else if (isEnd)
-                    debug(indent+"    ]");
-
-                if (child == null)
-                    break;
-
-                if (child.nodeType == Node.ELEMENT_NODE)
-                    printSelectionElement(child,indent+"    ");
-                else
-                    printSelectionText(child,indent+"    ");
-
-                child = child.nextSibling;
-                offset++;
-            }
-        }
-
-        function printSelectionText(node,indent)
-        {
-            var value = node.nodeValue;
-
-            if (sel.end.node == node) {
-                var afterSelection = value.substring(sel.end.offset);
-                value = value.substring(0,sel.end.offset) + "]" + afterSelection;
-            }
-
-            if (sel.start.node == node) {
-                var beforeSelection = value.substring(0,sel.start.offset);
-                value = beforeSelection + "[" + value.substring(sel.start.offset);
-            }
-
-            debug(indent+JSON.stringify(value));
-        }
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/StringBuilder.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/StringBuilder.js b/experiments/editorFramework/src/Layer0_Javascript/StringBuilder.js
deleted file mode 100644
index 9332b79..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/StringBuilder.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-function StringBuilder()
-{
-    this.str = "";
-}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Styles.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Styles.js b/experiments/editorFramework/src/Layer0_Javascript/Styles.js
deleted file mode 100644
index c09f41d..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Styles.js
+++ /dev/null
@@ -1,179 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Styles_getRule;
-var Styles_nextSelectorAfter;
-var Styles_getParagraphClass;
-var Styles_setParagraphClass;
-var Styles_headingNumbering;
-var Styles_getCSSText;
-var Styles_setCSSText;
-var Styles_getBuiltinCSSURL;
-var Styles_init;
-
-(function() {
-
-    var rules = new Object();
-    var paragraphClass = null;
-
-    Styles_getRule = function(selector)
-    {
-        return rules[selector];
-    }
-
-    Styles_nextSelectorAfter = function(element)
-    {
-        var selector = element.nodeName.toLowerCase();
-        var className = DOM_getAttribute(element,"class");
-        if (className != null)
-            selector = selector+"."+className;
-
-        var nextElementName = null;
-        var nextClassName = null;
-
-        var rule = Styles_getRule(selector);
-        if (rule != null) {
-            var nextSelector = rule["-uxwrite-next"];
-            if (nextSelector != null) {
-                try {
-                    nextSelector = JSON.parse(nextSelector);
-                    if (typeof(nextSelector) != "string")
-                        nextSelector = null;
-                }
-                catch (e) {
-                    nextSelector = null;
-                }
-            }
-            if (nextSelector != null) {
-                var dotIndex = nextSelector.indexOf(".");
-                if (dotIndex >= 0) {
-                    nextElementName = nextSelector.substring(0,dotIndex);
-                    nextClassName = nextSelector.substring(dotIndex+1);
-                }
-                else {
-                    nextElementName = nextSelector;
-                }
-            }
-        }
-
-        if ((nextElementName == null) ||
-            (ElementTypes[nextElementName] == null) ||
-            (!PARAGRAPH_ELEMENTS[ElementTypes[nextElementName]])) {
-            nextElementName = null;
-            nextClassName = null;
-        }
-
-        if (isHeadingNode(element)) {
-            nextElementName = "p";
-            nextClassName = Styles_getParagraphClass();
-        }
-
-        if (nextElementName == null)
-            return null;
-        else if (nextClassName == null)
-            return nextElementName;
-        else
-            return nextElementName+"."+nextClassName;
-    }
-
-    Styles_getParagraphClass = function()
-    {
-        return paragraphClass;
-    }
-
-    Styles_setParagraphClass = function(cls)
-    {
-        paragraphClass = cls;
-    }
-
-    Styles_headingNumbering = function()
-    {
-        return ((rules["h1::before"] != null) &&
-                (rules["h1::before"]["content"] != null));
-    }
-
-    Styles_getCSSText = function()
-    {
-        var head = DOM_documentHead(document);
-        var cssText = "";
-        for (var child = head.firstChild; child != null; child = child.nextSibling) {
-            if (child._type == HTML_STYLE) {
-                for (var t = child.firstChild; t != null; t = t.nextSibling) {
-                    if (t._type == HTML_TEXT)
-                        cssText += t.nodeValue;
-                }
-            }
-        }
-        return cssText;
-    }
-
-    Styles_setCSSText = function(cssText,cssRules)
-    {
-        UndoManager_newGroup("Update styles");
-        var head = DOM_documentHead(document);
-        var next;
-        for (var child = head.firstChild; child != null; child = next) {
-            next = child.nextSibling;
-            if (child._type == HTML_STYLE)
-                DOM_deleteNode(child);
-        }
-        var style = DOM_createElement(document,"STYLE");
-        DOM_appendChild(style,DOM_createTextNode(document,cssText));
-        DOM_appendChild(head,style);
-        rules = cssRules; // FIXME: undo support? (must coordinate with ObjC code)
-        Outline_scheduleUpdateStructure();
-        return {}; // Objective C caller expects JSON result
-    }
-
-    function addBuiltinStylesheet(cssURL)
-    {
-        var head = DOM_documentHead(document);
-        for (var child = head.firstChild; child != null; child = child.nextSibling) {
-            if ((child._type == HTML_LINK) &&
-                (child.getAttribute("rel") == "stylesheet") &&
-                (child.getAttribute("href") == cssURL)) {
-                // Link element was already added by HTMLInjectionProtocol
-                return;
-            }
-        }
-
-        // HTMLInjectionProtocol was unable to find <head> element and insert the stylesheet link,
-        // so add it ourselves
-        var link = DOM_createElement(document,"LINK");
-        DOM_setAttribute(link,"rel","stylesheet");
-        DOM_setAttribute(link,"href",cssURL);
-        DOM_insertBefore(head,link,head.firstChild);
-    }
-
-    var builtinCSSURL = null;
-
-    Styles_getBuiltinCSSURL = function()
-    {
-        return builtinCSSURL;
-    }
-
-    // public
-    Styles_init = function(cssURL)
-    {
-        if (cssURL != null)
-            builtinCSSURL = cssURL;
-
-        if (builtinCSSURL != null)
-            addBuiltinStylesheet(builtinCSSURL);
-    }
-
-})();


[26/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Clipboard.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Clipboard.js b/experiments/editorFramework/src/Javascript_Layer_0/Clipboard.js
new file mode 100644
index 0000000..03efdcc
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Clipboard.js
@@ -0,0 +1,757 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Markdown_htmlToMarkdown;
+var Clipboard_htmlToText;
+var Clipboard_cut;
+var Clipboard_copy;
+var Clipboard_pasteText;
+var Clipboard_pasteHTML;
+var Clipboard_pasteNodes;
+
+(function() {
+
+    // private
+    function blockToText(md,node,indent,nextIndent,listType,listNo)
+    {
+        var linesBetweenChildren = 1;
+        var childIndent = indent;
+        switch (node._type) {
+        case HTML_LI:
+            if (listType == "OL") {
+                var listMarker;
+                if (listNo.value < 10)
+                    listMarker = listNo.value+".  ";
+                else
+                    listMarker = listNo.value+". ";
+                beginParagraph(md,0,indent,nextIndent,listMarker);
+                nextIndent += "    ";
+            }
+            else {
+                beginParagraph(md,0,indent,nextIndent,"  - ");
+                nextIndent += "    ";
+            }
+            listNo.value++;
+            break;
+        case HTML_UL:
+            listType = "UL";
+            listNo = { value: 1 };
+            beginParagraph(md,1,indent,nextIndent);
+            linesBetweenChildren = 0;
+            break;
+        case HTML_OL:
+            listType = "OL";
+            listNo = { value: 1 };
+            beginParagraph(md,1,indent,nextIndent);
+            linesBetweenChildren = 0;
+            break;
+        case HTML_H1:
+            beginParagraph(md,1,indent,nextIndent,"# "," #");
+            break;
+        case HTML_H2:
+            beginParagraph(md,1,indent,nextIndent,"## "," ##");
+            break;
+        case HTML_H3:
+            beginParagraph(md,1,indent,nextIndent,"### "," ###");
+            break;
+        case HTML_H4:
+            beginParagraph(md,1,indent,nextIndent,"#### "," ####");
+            break;
+        case HTML_H5:
+            beginParagraph(md,1,indent,nextIndent,"##### "," #####");
+            break;
+        case HTML_H6:
+            beginParagraph(md,1,indent,nextIndent,"###### "," ######");
+            break;
+        case HTML_BLOCKQUOTE:
+            beginParagraph(md,1,indent,nextIndent,"> ");
+            nextIndent += "> ";
+            break;
+        case HTML_PRE:
+            md.preDepth++;
+            break;
+        }
+
+        var foundNonWhitespaceChild = false;
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            if (isContainerNode(child) || isParagraphNode(child)) {
+                beginParagraph(md,linesBetweenChildren,indent,nextIndent);
+                blockToText(md,child,indent,nextIndent,listType,listNo);
+                beginParagraph(md,linesBetweenChildren);
+                indent = nextIndent;
+                foundNonWhitespaceChild = false;
+            }
+            else {
+                if (!foundNonWhitespaceChild) {
+                    if (isWhitespaceTextNode(child))
+                        continue;
+                    beginParagraph(md,0,indent,nextIndent);
+                    indent = nextIndent;
+                    foundNonWhitespaceChild = true;
+                }
+
+                inlineToText(md,child);
+            }
+        }
+
+        if (node._type == HTML_PRE)
+            md.preDepth--;
+    }
+
+    // private
+    function shipOutParagraph(md)
+    {
+        var text = md.buildParagraph.join("");
+        if (md.buildPre) {
+            text = text.replace(/\n$/,"");
+            text = "    "+text.replace(/\n/g,"\n"+md.nextIndent+"    ");
+        }
+        else {
+            text = normalizeWhitespace(text);
+        }
+        if (md.allText.length > 0) {
+            for (var i = 0; i < md.buildLines; i++)
+                md.allText.push("\n");
+        }
+        md.allText.push(md.indent+md.buildPrefix+text+md.buildSuffix+"\n");
+        resetBuild(md);
+    }
+
+    // private
+    function beginParagraph(md,blankLines,indent,nextIndent,paraPrefix,paraSuffix)
+    {
+        if (blankLines == null)
+            blankLines = 1;
+        if (indent == null)
+            indent = "";
+        if (nextIndent == null)
+            nextIndent = "";
+        if (paraPrefix == null)
+            paraPrefix = "";
+        if (paraSuffix == null)
+            paraSuffix = "";
+
+        if (md == null)
+            throw new Error("beginParagraph: md is null");
+        if (md.buildParagraph == null)
+            throw new Error("beginParagraph: md.buildParagraph is null");
+
+        if (md.buildParagraph.length > 0) {
+            shipOutParagraph(md);
+        }
+
+        if (md.buildLines < blankLines)
+            md.buildLines = blankLines;
+        if (md.indent.length < indent.length)
+            md.indent = indent;
+        if (md.nextIndent.length < nextIndent.length)
+            md.nextIndent = nextIndent;
+        md.buildPrefix += paraPrefix;
+        md.buildSuffix = paraSuffix + md.buildSuffix;
+        if (md.preDepth > 0)
+            md.buildPre = true;
+    }
+
+    // private
+    function inlineToText(md,node)
+    {
+        switch (node._type) {
+        case HTML_TEXT: {
+            var text = node.nodeValue;
+            if (md.preDepth == 0) {
+                text = text.replace(/\\/g,"\\\\");
+                text = text.replace(/\*/g,"\\*");
+                text = text.replace(/\[/g,"\\[");
+                text = text.replace(/\]/g,"\\]");
+            }
+            md.buildParagraph.push(text);
+            break;
+        }
+        case HTML_I:
+        case HTML_EM:
+            md.buildParagraph.push("*");
+            processChildren();
+            md.buildParagraph.push("*");
+            break;
+        case HTML_B:
+        case HTML_STRONG:
+            md.buildParagraph.push("**");
+            processChildren();
+            md.buildParagraph.push("**");
+            break;
+        case HTML_A:
+            if (node.hasAttribute("href")) {
+                md.buildParagraph.push("[");
+                processChildren();
+                md.buildParagraph.push("]("+node.getAttribute("href")+")");
+            }
+            break;
+        default:
+            processChildren();
+            break;
+        }
+
+        function processChildren()
+        {
+            for (var child = node.firstChild; child != null; child = child.nextSibling) {
+                inlineToText(md,child);
+            }
+        }
+    }
+
+    // private
+    function resetBuild(md)
+    {
+        md.buildParagraph = new Array();
+        md.buildLines = 0;
+        md.buildPrefix = "";
+        md.buildSuffix = "";
+        md.buildPre = false;
+        md.indent = "";
+        md.nextIndent = "";
+    }
+
+    // private
+    function MarkdownBuilder()
+    {
+    }
+
+    // public
+    Markdown_htmlToMarkdown = function(node)
+    {
+        var md = new MarkdownBuilder();
+        md.allText = new Array();
+        md.preDepth = 0;
+        resetBuild(md);
+
+        if (isContainerNode(node) || isParagraphNode(node)) {
+            blockToText(md,node,"","","UL",{value: 1});
+            beginParagraph(md);
+            return md.allText.join("");
+        }
+        else {
+            inlineToText(md,node);
+            return normalizeWhitespace(md.buildParagraph.join(""));
+        }
+    }
+
+})();
+
+(function() {
+
+    function expandRangeForCopy(range)
+    {
+        if (range == null)
+            return range;
+
+        var startInLI = null;
+        for (var node = range.start.node; node != null; node = node.parentNode) {
+            if (node._type == HTML_LI)
+                startInLI = node;
+        }
+
+        var endInLI = null;
+        for (var node = range.end.node; node != null; node = node.parentNode) {
+            if (node._type == HTML_LI)
+                endInLI = node;
+        }
+
+        if ((startInLI != null) && (startInLI == endInLI)) {
+            var beforeRange = new Range(startInLI,0,
+                                        range.start.node,range.start.offset);
+            var afterRange = new Range(range.end.node,range.end.offset,
+                                       endInLI,DOM_maxChildOffset(endInLI));
+            var contentBefore = Range_hasContent(beforeRange);
+            var contentAfter = Range_hasContent(afterRange);
+
+            if (!contentBefore && !contentAfter) {
+                var li = startInLI;
+                var offset = DOM_nodeOffset(li);
+                range = new Range(li.parentNode,offset,li.parentNode,offset+1);
+            }
+        }
+        return range;
+    }
+
+    function copyRange(range)
+    {
+        var html = "";
+        var text = "";
+
+        if (range != null) {
+            var nodes;
+            var region = Tables_regionFromRange(range);
+            if (region != null) {
+                nodes = [Tables_cloneRegion(region)];
+            }
+            else {
+                nodes = Range_cloneContents(range);
+            };
+
+            var div = DOM_createElement(document,"DIV");
+            for (var i = 0; i < nodes.length; i++)
+                DOM_appendChild(div,nodes[i]);
+            Main_removeSpecial(div);
+
+            html = div.innerHTML;
+            text = Clipboard_htmlToText(div);
+        }
+
+        return { "text/html": html,
+                 "text/plain": text };
+    }
+
+    // public (FIXME: temp: for testing)
+    Clipboard_htmlToText = function(node)
+    {
+        return Markdown_htmlToMarkdown(node);
+    }
+
+    // public
+    Clipboard_cut = function()
+    {
+        UndoManager_newGroup("Cut");
+        var content;
+
+        var range = Selection_get();
+        range = expandRangeForCopy(range);
+        content = copyRange(range);
+
+        Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
+        Selection_deleteContents(false);
+        var selRange = Selection_get();
+        if (selRange != null) {
+            Range_trackWhileExecuting(selRange,function() {
+                var node = Position_closestActualNode(selRange.start);
+                while (node != null) {
+                    var parent = node.parentNode;
+                    switch (node._type) {
+                    case HTML_LI:
+                        if (!nodeHasContent(node))
+                            DOM_deleteNode(node);
+                        break;
+                    case HTML_UL:
+                    case HTML_OL: {
+                        var haveLI = false;
+                        for (var c = node.firstChild; c != null; c = c.nextSibling) {
+                            if (c._type == HTML_LI) {
+                                haveLI = true;
+                                break;
+                            }
+                        }
+                        if (!haveLI)
+                            DOM_deleteNode(node);
+                        break;
+                    }
+                    }
+                    node = parent;
+                }
+            });
+
+            var pos = Position_closestMatchForwards(selRange.start,Position_okForMovement);
+            Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+        }
+
+        Cursor_ensureCursorVisible();
+
+        PostponedActions_perform(UndoManager_newGroup);
+        return content;
+    }
+
+    // public
+    Clipboard_copy = function()
+    {
+        var range = Selection_get();
+        range = expandRangeForCopy(range);
+        return copyRange(range);
+    }
+
+    // public
+    Clipboard_pasteText = function(text)
+    {
+        var converter = new Showdown.converter();
+        var html = converter.makeHtml(text);
+        UndoManager_newGroup("Paste");
+        Clipboard_pasteHTML(html);
+        UndoManager_newGroup();
+    }
+
+    // public
+    Clipboard_pasteHTML = function(html)
+    {
+        if (html.match(/^\s*<thead/i))
+            html = "<table>" + html + "</table>";
+        else if (html.match(/^\s*<tbody/i))
+            html = "<table>" + html + "</table>";
+        else if (html.match(/^\s*<tfoot/i))
+            html = "<table>" + html + "</table>";
+        else if (html.match(/^\s*<tr/i))
+            html = "<table>" + html + "</table>";
+        else if (html.match(/^\s*<td/i))
+            html = "<table><tr>" + html + "</tr></table>";
+        else if (html.match(/^\s*<th/i))
+            html = "<table><tr>" + html + "</tr></table>";
+        else if (html.match(/^\s*<li/i))
+            html = "<ul>" + html + "</ul>";
+
+        var div = DOM_createElement(document,"DIV");
+        div.innerHTML = html;
+        for (var child = div.firstChild; child != null; child = child.nextSibling)
+            DOM_assignNodeIds(child);
+
+        var nodes = new Array();
+        for (var child = div.firstChild; child != null; child = child.nextSibling)
+            nodes.push(child);
+
+        UndoManager_newGroup("Paste");
+        var region = Tables_regionFromRange(Selection_get(),true);
+        if ((region != null) && (nodes.length == 1) && (nodes[0]._type == HTML_TABLE))
+            pasteTable(nodes[0],region);
+        else
+            Clipboard_pasteNodes(nodes);
+        UndoManager_newGroup();
+    }
+
+    function pasteTable(srcTable,dest)
+    {
+        var src = Tables_analyseStructure(srcTable);
+
+        // In the destination table, the region into which we will paste the cells will the
+        // the same size as that of the source table, regardless of how many rows and columns
+        // were selected - i.e. we only pay attention to the top-left most cell, ignoring
+        // whatever the bottom-right is set to
+        dest.bottom = dest.top + src.numRows - 1;
+        dest.right = dest.left + src.numCols - 1;
+
+        // Make sure the destination table is big enough to hold all the cells we want to paste.
+        // This will add rows and columns as appropriate, with empty cells that only contain a
+        // <p><br></p> (to ensure they have non-zero height)
+        if (dest.structure.numRows < dest.bottom + 1)
+            dest.structure.numRows = dest.bottom + 1;
+        if (dest.structure.numCols < dest.right + 1)
+            dest.structure.numCols = dest.right + 1;
+        dest.structure = Table_fix(dest.structure);
+
+        // To simplify the paste, split any merged cells that are in the region of the destination
+        // table we're pasting into. We have to re-analyse the table structure after this to
+        // get the correct cell array.
+        TableRegion_splitCells(dest);
+        dest.structure = Tables_analyseStructure(dest.structure.element);
+
+        // Do the actual paste
+        Selection_preserveWhileExecuting(function() {
+            replaceCells(src,dest.structure,dest.top,dest.left);
+        });
+
+        // If any new columns were added, calculate a width for them
+        Table_fixColumnWidths(dest.structure);
+
+        // Remove duplicate ids
+        var found = new Object();
+        removeDuplicateIds(dest.structure.element,found);
+
+        // Place the cursor in the bottom-right cell that was pasted
+        var bottomRightCell = Table_get(dest.structure,dest.bottom,dest.right);
+        var node = bottomRightCell.element;
+        Selection_set(node,node.childNodes.length,node,node.childNodes.length);
+    }
+
+    function replaceCells(src,dest,destRow,destCol)
+    {
+        // By this point, all of the cells have been split. So it is guaranteed that every cell
+        // in dest will have rowspan = 1 and colspan = 1.
+        for (var srcRow = 0; srcRow < src.numRows; srcRow++) {
+            for (var srcCol = 0; srcCol < src.numCols; srcCol++) {
+                var srcCell = Table_get(src,srcRow,srcCol);
+                var destCell = Table_get(dest,srcRow+destRow,srcCol+destCol);
+
+                if ((srcRow != srcCell.row) || (srcCol != srcCell.col))
+                    continue;
+
+                if (destCell.rowspan != 1)
+                    throw new Error("unexpected rowspan: "+destCell.rowspan);
+                if (destCell.colspan != 1)
+                    throw new Error("unexpected colspan: "+destCell.colspan);
+
+                DOM_insertBefore(destCell.element.parentNode,srcCell.element,destCell.element);
+
+                var destTop = destRow + srcRow;
+                var destLeft = destCol + srcCol;
+                var destBottom = destTop + srcCell.rowspan - 1;
+                var destRight = destLeft + srcCell.colspan - 1;
+                Table_setRegion(dest,destTop,destLeft,destBottom,destRight,srcCell);
+            }
+        }
+    }
+
+    function insertChildrenBefore(parent,child,nextSibling,pastedNodes)
+    {
+        var next;
+        for (var grandChild = child.firstChild; grandChild != null; grandChild = next) {
+            next = grandChild.nextSibling;
+            pastedNodes.push(grandChild);
+            DOM_insertBefore(parent,grandChild,nextSibling);
+        }
+    }
+
+    function fixParagraphStyles(node,paragraphClass)
+    {
+        if (isParagraphNode(node)) {
+            if (node._type == HTML_P) {
+                var className = DOM_getAttribute(node,"class");
+                if ((className == null) || (className == "")) {
+                    debug("Setting paragraph class to "+paragraphClass);
+                    DOM_setAttribute(node,"class",paragraphClass);
+                }
+            }
+        }
+        else {
+            for (var child = node.firstChild; child != null; child = child.nextSibling) {
+                fixParagraphStyles(child,paragraphClass);
+            }
+        }
+    }
+
+    // public
+    Clipboard_pasteNodes = function(nodes)
+    {
+        if (nodes.length == 0)
+            return;
+
+        var paragraphClass = Styles_getParagraphClass();
+        if (paragraphClass != null) {
+            for (var i = 0; i < nodes.length; i++) {
+                fixParagraphStyles(nodes[i],paragraphClass);
+            }
+        }
+
+        // Remove any elements which don't belong in the document body (in case an entire
+        // HTML document is being pasted in)
+        var i = 0;
+        while (i < nodes.length) {
+            switch (nodes[i]._type) {
+            case HTML_HTML:
+            case HTML_BODY:
+            case HTML_META:
+            case HTML_TITLE:
+            case HTML_SCRIPT:
+            case HTML_STYLE:
+                nodes.splice(i,1);
+                break;
+            default:
+                i++;
+            }
+        }
+
+        var found = new Object();
+        for (var i = 0; i < nodes.length; i++)
+            removeDuplicateIds(nodes[i],found);
+
+//        if ((nodes.length == 0) && (nodes[0]._type == HTML_TABLE)) {
+//            // FIXME: this won't work; selectionRange is not defined
+//            var fromRegion = Tables_getTableRegionFromTable(nodes[0]);
+//            var toRegion = Tables_regionFromRange(selectionRange);
+//            if (toRegion != null) {
+//                return;
+//            }
+//        }
+
+        Selection_deleteContents(true);
+        var range = Selection_get();
+        if (range == null)
+            throw new Error("No current selection");
+
+        var parent;
+        var previousSibling;
+        var nextSibling;
+
+        var start = range.start;
+        start = Position_preferElementPosition(start);
+        if (start.node.nodeType == Node.ELEMENT_NODE) {
+            parent = start.node;
+            nextSibling = start.node.childNodes[start.offset];
+            previousSibling = start.node.childNodes[start.offset-1];
+        }
+        else {
+            Formatting_splitTextAfter(start);
+            parent = start.node.parentNode;
+            nextSibling = start.node.nextSibling;
+            previousSibling = start.node;
+        }
+
+        var prevLI = null;
+        var inItem = null;
+        var inList = null;
+        var containerParent = null;
+
+        for (var temp = parent; temp != null; temp = temp.parentNode) {
+            if (isContainerNode(temp)) {
+                switch (temp._type) {
+                case HTML_LI:
+                    inItem = temp;
+                    break;
+                case HTML_UL:
+                case HTML_OL:
+                    inList = temp;
+                    break;
+                }
+                containerParent = temp.parentNode;
+                break;
+            }
+        }
+
+        var pastedNodes;
+        if (inItem) {
+            pastedNodes = new Array();
+            for (var i = 0; i < nodes.length; i++) {
+                var child = nodes[i];
+
+                var offset = DOM_nodeOffset(nextSibling,parent);
+
+                switch (child._type) {
+                case HTML_UL:
+                case HTML_OL:
+                    Formatting_movePreceding(new Position(parent,offset),
+                                             function(x) { return (x == containerParent); });
+                    insertChildrenBefore(inItem.parentNode,child,inItem,pastedNodes);
+                    break;
+                case HTML_LI:
+                    Formatting_movePreceding(new Position(parent,offset),
+                                             function(x) { return (x == containerParent); });
+                    DOM_insertBefore(inItem.parentNode,child,inItem);
+                    pastedNodes.push(child);
+                    break;
+                default:
+                    DOM_insertBefore(parent,child,nextSibling);
+                    pastedNodes.push(child);
+                    break;
+                }
+            }
+        }
+        else if (inList) {
+            pastedNodes = new Array();
+            for (var i = 0; i < nodes.length; i++) {
+                var child = nodes[i];
+
+                var offset = DOM_nodeOffset(nextSibling,parent);
+
+                switch (child._type) {
+                case HTML_UL:
+                case HTML_OL:
+                    insertChildrenBefore(parent,child,nextSibling,pastedNodes);
+                    prevLI = null;
+                    break;
+                case HTML_LI:
+                    DOM_insertBefore(parent,child,nextSibling);
+                    pastedNodes.push(child);
+                    prevLI = null;
+                    break;
+                default:
+                    if (!isWhitespaceTextNode(child)) {
+                        if (prevLI == null)
+                            prevLI = DOM_createElement(document,"LI");
+                        DOM_appendChild(prevLI,child);
+                        DOM_insertBefore(parent,prevLI,nextSibling);
+                        pastedNodes.push(child);
+                    }
+                }
+            }
+        }
+        else {
+            pastedNodes = nodes;
+            for (var i = 0; i < nodes.length; i++) {
+                var child = nodes[i];
+                DOM_insertBefore(parent,child,nextSibling);
+            }
+        }
+
+        var prevOffset;
+        if (previousSibling == null)
+            prevOffset = 0;
+        else
+            prevOffset = DOM_nodeOffset(previousSibling);
+        var nextOffset = DOM_nodeOffset(nextSibling,parent);
+
+        var origRange = new Range(parent,prevOffset,parent,nextOffset);
+
+        var firstPasted = pastedNodes[0];
+        var lastPasted = pastedNodes[pastedNodes.length-1];
+        var pastedRange = new Range(firstPasted,0,lastPasted,DOM_maxChildOffset(lastPasted));
+        Range_trackWhileExecuting(origRange,function() {
+        Range_trackWhileExecuting(pastedRange,function() {
+            if (previousSibling != null)
+                Formatting_mergeWithNeighbours(previousSibling,Formatting_MERGEABLE_INLINE);
+            if (nextSibling != null)
+                Formatting_mergeWithNeighbours(nextSibling,Formatting_MERGEABLE_INLINE);
+
+            Cursor_updateBRAtEndOfParagraph(parent);
+
+            Range_ensureValidHierarchy(pastedRange,true);
+        })});
+
+        var pos = new Position(origRange.end.node,origRange.end.offset);
+        Range_trackWhileExecuting(pastedRange,function() {
+        Position_trackWhileExecuting(pos,function() {
+            while (true) {
+                if (pos.node == document.body)
+                    break;
+                if (isContainerNode(pos.node) && (pos.node._type != HTML_LI))
+                    break;
+                if (!nodeHasContent(pos.node)) {
+                    var oldNode = pos.node;
+                    pos = new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
+                    DOM_deleteNode(oldNode);
+                }
+                else
+                    break;
+            }
+        });
+        });
+
+        pos = new Position(pastedRange.end.node,pastedRange.end.offset);
+        while (isOpaqueNode(pos.node))
+            pos = new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
+        pos = Position_closestMatchBackwards(pos,Position_okForInsertion);
+
+        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+        Cursor_ensureCursorVisible();
+    }
+
+    function removeDuplicateIds(node,found)
+    {
+        if ((node.nodeType == Node.ELEMENT_NODE) && node.hasAttribute("id")) {
+            var id = node.getAttribute("id");
+
+            var existing = document.getElementById(id);
+            if (existing == null)
+                existing = found[id];
+
+            if ((existing != null) && (existing != node))
+                DOM_removeAttribute(node,"id");
+            else
+                found[id] = node;
+        }
+        for (var child = node.firstChild; child != null; child = child.nextSibling)
+            removeDuplicateIds(child,found);
+    }
+
+    function pasteImage(href)
+    {
+        // FIXME
+    }
+
+})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Cursor.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Cursor.js b/experiments/editorFramework/src/Javascript_Layer_0/Cursor.js
new file mode 100644
index 0000000..7362a9e
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Cursor.js
@@ -0,0 +1,1050 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+var Cursor_ensurePositionVisible;
+var Cursor_ensureCursorVisible;
+var Cursor_scrollDocumentForY;
+var Cursor_positionCursor;
+var Cursor_getCursorPosition;
+var Cursor_moveLeft;
+var Cursor_moveRight;
+var Cursor_moveToStartOfDocument;
+var Cursor_moveToEndOfDocument;
+var Cursor_updateBRAtEndOfParagraph;
+var Cursor_insertReference;
+var Cursor_insertLink;
+var Cursor_insertCharacter;
+var Cursor_deleteCharacter;
+var Cursor_enterPressed;
+var Cursor_getPrecedingWord;
+var Cursor_getAdjacentNodeWithType;
+var Cursor_getLinkProperties;
+var Cursor_setLinkProperties;
+var Cursor_setReferenceTarget;
+var Cursor_makeContainerInsertionPoint;
+var Cursor_set;
+var Cursor_insertFootnote;
+var Cursor_insertEndnote;
+
+(function() {
+
+    var cursorX = null;
+
+    Cursor_ensurePositionVisible = function(pos,center)
+    {
+        // If we can't find the cursor rect for some reason, just don't do anything.
+        // This is better than using an incorrect position or throwing an exception.
+        var rect = Position_displayRectAtPos(pos)
+        if (rect != null) {
+            var extraSpace = 4;
+
+            var cursorTop = rect.top + window.scrollY - extraSpace;
+            var cursorBottom = rect.top + rect.height + window.scrollY + extraSpace;
+
+            var windowTop = window.scrollY;
+            var windowBottom = window.scrollY + window.innerHeight;
+
+            if (center) {
+                var newY = Math.floor(cursorTop + rect.height/2 - window.innerHeight/2);
+                window.scrollTo(window.scrollX,newY);
+            }
+            else if (cursorTop < windowTop) {
+                window.scrollTo(window.scrollX,cursorTop);
+            }
+            else if (cursorBottom > windowBottom) {
+                window.scrollTo(window.scrollX,cursorBottom - window.innerHeight);
+            }
+        }
+    }
+
+    // public
+    Cursor_ensureCursorVisible = function(center)
+    {
+        var selRange = Selection_get();
+        if (selRange != null)
+            Cursor_ensurePositionVisible(selRange.end,center);
+    }
+
+    Cursor_scrollDocumentForY = function(y)
+    {
+        var absY = window.scrollY + y;
+        if (absY-44 < window.scrollY) {
+            window.scrollTo(window.scrollX,absY-44);
+            y = absY - window.scrollY;
+        }
+        else if (absY+44 >= window.scrollY + window.innerHeight) {
+            window.scrollTo(window.scrollX,absY+44 - window.innerHeight);
+            y = absY - window.scrollY;
+        }
+        return y;
+    }
+
+    // public
+    Cursor_positionCursor = function(x,y,wordBoundary)
+    {
+        if (UndoManager_groupType() != "Cursor movement")
+            UndoManager_newGroup("Cursor movement");
+
+        y = Cursor_scrollDocumentForY(y);
+
+        var result = null;
+        var position = Position_atPoint(x,y);
+        if (position == null)
+            return null;
+
+        var node = Position_closestActualNode(position);
+        for (; node != null; node = node.parentNode) {
+            var type = node._type;
+            if ((type == HTML_A) &&
+                (node.hasAttribute("href")) &&
+                (result == null)) {
+
+                var arange = new Range(node,0,node,node.childNodes.length);
+                var rects = Range_getClientRects(arange);
+                var insideLink = false;
+                for (var i = 0; i < rects.length; i++) {
+                    if (rectContainsPoint(rects[i],x,y))
+                        insideLink = true;
+                }
+
+                if (insideLink) {
+                    var href = node.getAttribute("href");
+                    if ((href != null) && (href.charAt(0) == "#")) {
+                        if (isInTOC(node))
+                            result = "intocreference-"+href.substring(1);
+                        else
+                            result = "inreference";
+                    }
+                    else {
+                        result = "inlink";
+                    }
+                }
+            }
+            else if ((type == HTML_IMG) && (result == null)) {
+                for (var anc = node; anc != null; anc = anc.parentNode) {
+                    if (anc._type == HTML_FIGURE) {
+                        result = "infigure";
+                        break;
+                    }
+                }
+            }
+            else if (isAutoCorrectNode(node) && (result == null)) {
+                result = "incorrection";
+            }
+            else if (isTOCNode(node)) {
+                var rect = node.getBoundingClientRect();
+                if (x >= rect.left + rect.width/2)
+                    position = new Position(node.parentNode,DOM_nodeOffset(node)+1);
+                else
+                    position = new Position(node.parentNode,DOM_nodeOffset(node));
+                break;
+            }
+        }
+
+        var position = Position_closestMatchForwards(position,Position_okForMovement);
+        if ((position != null) && isOpaqueNode(position.node))
+            position = Position_nextMatch(position,Position_okForMovement);
+        if (position == null)
+            return false;
+
+        var selectionRange = Selection_get();
+        var samePosition = ((selectionRange != null) && Range_isEmpty(selectionRange) &&
+                            (position.node == selectionRange.start.node) &&
+                            (position.offset == selectionRange.start.offset));
+        if (samePosition && (result == null))
+            result = "same";
+
+        if (wordBoundary) {
+            var startOfWord = Selection_posAtStartOfWord(position);
+            var endOfWord = Selection_posAtEndOfWord(position);
+            if ((startOfWord.node != position.node) || (startOfWord.node != position.node))
+                throw new Error("Word boundary in different node");
+            var distanceBefore = position.offset - startOfWord.offset;
+            var distanceAfter = endOfWord.offset - position.offset;
+            if (distanceBefore <= distanceAfter)
+                position = startOfWord;
+            else
+                position = endOfWord;
+        }
+
+        Cursor_set(position.node,position.offset);
+        return result;
+    }
+
+    // public
+    Cursor_getCursorPosition = function()
+    {
+        var selRange = Selection_get();
+        if (selRange == null)
+            return null;
+
+        // FIXME: in the cases where this is called from Objective C, test what happens if we
+        // return a null rect
+        var rect = Position_displayRectAtPos(selRange.end);
+        if (rect == null)
+            return null;
+
+        var left = rect.left + window.scrollX;
+        var top = rect.top + window.scrollY;
+        var height = rect.height;
+        return { x: left, y: top, width: 0, height: height };
+    }
+
+    // public
+    Cursor_moveLeft = function()
+    {
+        var range = Selection_get();
+        if (range == null)
+            return;
+
+        var pos = Position_prevMatch(range.start,Position_okForMovement);
+        if (pos != null)
+            Cursor_set(pos.node,pos.offset);
+        Cursor_ensureCursorVisible();
+    }
+
+    // public
+    Cursor_moveRight = function()
+    {
+        var range = Selection_get();
+        if (range == null)
+            return;
+
+        var pos = Position_nextMatch(range.start,Position_okForMovement);
+        if (pos != null)
+            Cursor_set(pos.node,pos.offset);
+        Cursor_ensureCursorVisible();
+    }
+
+    // public
+    Cursor_moveToStartOfDocument = function()
+    {
+        var pos = new Position(document.body,0);
+        pos = Position_closestMatchBackwards(pos,Position_okForMovement);
+        Cursor_set(pos.node,pos.offset);
+        Cursor_ensureCursorVisible();
+    }
+
+    // public
+    Cursor_moveToEndOfDocument = function()
+    {
+        var pos = new Position(document.body,document.body.childNodes.length);
+        pos = Position_closestMatchForwards(pos,Position_okForMovement);
+        Cursor_set(pos.node,pos.offset);
+        Cursor_ensureCursorVisible();
+    }
+
+    // An empty paragraph does not get shown and cannot be edited. We can fix this by adding
+    // a BR element as a child
+    // public
+    Cursor_updateBRAtEndOfParagraph = function(node)
+    {
+        var paragraph = node;
+        while ((paragraph != null) && !isParagraphNode(paragraph))
+            paragraph = paragraph.parentNode;
+        if (paragraph != null) {
+
+            var br = null;
+            var last = paragraph;
+            do {
+
+                var child = last;
+                while ((child != null) && isWhitespaceTextNode(child))
+                    child = child.previousSibling;
+
+                if ((child != null) && (child._type == HTML_BR))
+                    br = child;
+
+                last = last.lastChild;
+
+            } while ((last != null) && isInlineNode(last));
+
+            if (nodeHasContent(paragraph)) {
+                // Paragraph has content: don't want BR at end
+                if (br != null) {
+                    DOM_deleteNode(br);
+                }
+            }
+            else {
+                // Paragraph consists only of whitespace: must have BR at end
+                if (br == null) {
+                    br = DOM_createElement(document,"BR");
+                    DOM_appendChild(paragraph,br);
+                }
+            }
+        }
+    }
+
+    // public
+    Cursor_insertReference = function(itemId)
+    {
+        var a = DOM_createElement(document,"A");
+        DOM_setAttribute(a,"href","#"+itemId);
+        Clipboard_pasteNodes([a]);
+    }
+
+    // public
+    Cursor_insertLink = function(text,url)
+    {
+        var a = DOM_createElement(document,"A");
+        DOM_setAttribute(a,"href",url);
+        DOM_appendChild(a,DOM_createTextNode(document,text));
+        Clipboard_pasteNodes([a]);
+    }
+
+    var nbsp = String.fromCharCode(160);
+
+    function spaceToNbsp(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if ((node.nodeType == Node.TEXT_NODE) && (offset > 0) &&
+            (isWhitespaceString(node.nodeValue.charAt(offset-1)))) {
+            // Insert first, to preserve any tracked positions
+            DOM_insertCharacters(node,offset-1,nbsp);
+            DOM_deleteCharacters(node,offset,offset+1);
+        }
+    }
+
+    function nbspToSpace(pos)
+    {
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if ((node.nodeType == Node.TEXT_NODE) && (offset > 0) &&
+            (node.nodeValue.charAt(offset-1) == nbsp)) {
+            // Insert first, to preserve any tracked positions
+            DOM_insertCharacters(node,offset-1," ");
+            DOM_deleteCharacters(node,offset,offset+1);
+        }
+    }
+
+    function checkNbsp()
+    {
+        Selection_preserveWhileExecuting(function() {
+            var selRange = Selection_get();
+            if (selRange != null)
+                nbspToSpace(selRange.end);
+        });
+    }
+
+    function isPosAtStartOfParagraph(pos)
+    {
+        if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset == 0) &&
+            !isInlineNode(pos.node)) {
+            return true;
+        }
+
+
+
+        while (pos != null) {
+            if (pos.node.nodeType == Node.ELEMENT_NODE) {
+                if ((pos.offset == 0) && !isInlineNode(pos.node))
+                    return true;
+                else
+                    pos = Position_prev(pos);
+            }
+            else if (pos.node.nodeType == Node.TEXT_NODE) {
+                if (pos.offset > 0)
+                    return false;
+                else
+                    pos = Position_prev(pos);
+            }
+            else {
+                return false;
+            }
+        }
+
+        return false;
+    }
+
+    // public
+    Cursor_insertCharacter = function(str,allowInvalidPos,allowNoParagraph)
+    {
+        var firstInsertion = (UndoManager_groupType() != "Insert text");
+
+        if (firstInsertion)
+            UndoManager_newGroup("Insert text",checkNbsp);
+
+        if (str == "-") {
+            var preceding = Cursor_getPrecedingWord();
+            if (preceding.match(/[0-9]\s*$/))
+                str = String.fromCharCode(0x2013); // en dash
+            else if (preceding.match(/\s+$/))
+                str = String.fromCharCode(0x2014); // em dash
+        }
+
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+
+        if (!Range_isEmpty(selRange)) {
+            Selection_deleteContents(true);
+            selRange = Selection_get();
+        }
+        var pos = selRange.start;
+        pos = Position_preferTextPosition(pos);
+        if ((str == " ") && isPosAtStartOfParagraph(pos))
+            return;
+        if (!allowInvalidPos && !Position_okForInsertion(pos)) {
+            var elemPos = Position_preferElementPosition(pos);
+            if (Position_okForInsertion(elemPos)) {
+                pos = elemPos;
+            }
+            else {
+                var oldPos = pos;
+                pos = Position_closestMatchForwards(selRange.start,Position_okForInsertion);
+                var difference = new Range(oldPos.node,oldPos.offset,pos.node,pos.offset);
+                difference = Range_forwards(difference);
+                Position_trackWhileExecuting([pos],function() {
+                    if (!Range_hasContent(difference)) {
+                        Selection_deleteRangeContents(difference,true);
+                    }
+                });
+            }
+        }
+        var node = pos.node;
+        var offset = pos.offset;
+
+        if ((str == " ") &&
+            !firstInsertion &&
+            (node.nodeType == Node.TEXT_NODE) &&
+            (offset > 0) &&
+            (node.nodeValue.charAt(offset-1) == nbsp)) {
+
+            if (!node.nodeValue.substring(0,offset).match(/\.\s+$/)) {
+                DOM_deleteCharacters(node,offset-1,offset);
+                DOM_insertCharacters(node,offset-1,".");
+            }
+        }
+
+        if (isWhitespaceString(str) && (node.nodeType == Node.TEXT_NODE) && (offset > 0)) {
+            var prevChar = node.nodeValue.charAt(offset-1);
+            if (isWhitespaceString(prevChar) || (prevChar == nbsp)) {
+                Selection_update();
+                Cursor_ensureCursorVisible();
+                return;
+            }
+        }
+
+        nbspToSpace(pos);
+
+        // If the user enters two double quotes in succession (open and close), replace them with
+        // just one plain double quote character
+        if ((str == "”") && (node.nodeType == Node.TEXT_NODE) &&
+            (offset > 0) && (node.nodeValue.charAt(offset-1) == "“")) {
+            DOM_deleteCharacters(node,offset-1,offset);
+            offset--;
+            str = "\"";
+        }
+
+        if (node.nodeType == Node.ELEMENT_NODE) {
+            var emptyTextNode = DOM_createTextNode(document,"");
+            if (offset >= node.childNodes.length)
+                DOM_appendChild(node,emptyTextNode);
+            else
+                DOM_insertBefore(node,emptyTextNode,node.childNodes[offset]);
+            node = emptyTextNode;
+            offset = 0;
+        }
+
+        if (str == " ")
+            DOM_insertCharacters(node,offset,nbsp);
+        else
+            DOM_insertCharacters(node,offset,str);
+
+                // must be done *after* inserting the text
+        if (!allowNoParagraph) {
+            switch (node.parentNode._type) {
+            case HTML_CAPTION:
+            case HTML_FIGCAPTION:
+                // Do nothing
+                break;
+            default:
+                Hierarchy_ensureInlineNodesInParagraph(node,true);
+                break;
+            }
+        }
+
+        offset += str.length;
+
+        pos = new Position(node,offset);
+        Position_trackWhileExecuting([pos],function() {
+            Formatting_mergeWithNeighbours(pos.node,Formatting_MERGEABLE_INLINE);
+        });
+
+        Cursor_set(pos.node,pos.offset);
+        Range_trackWhileExecuting(Selection_get(),function() {
+            Cursor_updateBRAtEndOfParagraph(pos.node);
+        });
+
+        Selection_update();
+        Cursor_ensureCursorVisible();
+    }
+
+    function tryDeleteEmptyCaption(pos)
+    {
+        var caption = Position_captionAncestor(pos);
+        if ((caption == null) || nodeHasContent(caption))
+            return false;
+
+        var container = Position_figureOrTableAncestor(pos);
+        if (container == null)
+            return false;
+
+        Cursor_set(container.parentNode,DOM_nodeOffset(container)+1);
+        Selection_preserveWhileExecuting(function() {
+            DOM_deleteNode(caption);
+        });
+
+        return true;
+    }
+
+    function tryDeleteEmptyNote(pos)
+    {
+        var note = Position_noteAncestor(pos);
+        if ((note == null) || nodeHasContent(note))
+            return false;
+
+        var parent = note.parentNode;
+        Cursor_set(note.parentNode,DOM_nodeOffset(note)+1);
+        Selection_preserveWhileExecuting(function() {
+            DOM_deleteNode(note);
+        });
+
+        return true;
+    }
+
+    // public
+    Cursor_deleteCharacter = function()
+    {
+        if (UndoManager_groupType() != "Delete text")
+            UndoManager_newGroup("Delete text",checkNbsp);
+
+        Selection_preferElementPositions();
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+
+        if (!Range_isEmpty(selRange)) {
+            Selection_deleteContents(true);
+        }
+        else {
+            var currentPos = selRange.start;
+
+            // Special cases of pressing backspace after a table, figure, TOC, hyperlink,
+            // footnote, or endnote. For each of these we delete the whole thing.
+            var back = Position_closestMatchBackwards(currentPos,Position_okForMovement);
+            if ((back != null) && (back.node.nodeType == Node.ELEMENT_NODE) && (back.offset > 0)) {
+                var prevNode = back.node.childNodes[back.offset-1];
+                if (isSpecialBlockNode(prevNode)) {
+                    var p = DOM_createElement(document,"P");
+                    DOM_insertBefore(prevNode.parentNode,p,prevNode);
+                    DOM_deleteNode(prevNode);
+                    Cursor_updateBRAtEndOfParagraph(p);
+                    Cursor_set(p,0);
+                    Cursor_ensureCursorVisible();
+                    return;
+                }
+                if ((prevNode._type == HTML_A) || isNoteNode(prevNode)) {
+                    Cursor_set(back.node,back.offset-1);
+                    Selection_preserveWhileExecuting(function() {
+                        DOM_deleteNode(prevNode);
+                    });
+                    return;
+                }
+            }
+
+            // Backspace inside an empty figure or table caption
+            if (tryDeleteEmptyCaption(currentPos))
+                return;
+
+            currentPos = Position_preferTextPosition(currentPos);
+            var prevPos = Position_prevMatch(currentPos,Position_okForMovement);
+
+            // Backspace inside or just after a footnote or endnote
+            if (tryDeleteEmptyNote(currentPos))
+                return;
+            if ((prevPos != null) && tryDeleteEmptyNote(prevPos))
+                return;
+
+            if (prevPos != null) {
+                var startBlock = firstBlockAncestor(Position_closestActualNode(prevPos));
+                var endBlock = firstBlockAncestor(Position_closestActualNode(selRange.end));
+                if ((startBlock != endBlock) &&
+                    isParagraphNode(startBlock) && !nodeHasContent(startBlock)) {
+                    DOM_deleteNode(startBlock);
+                    Cursor_set(selRange.end.node,selRange.end.offset)
+                }
+                else {
+                    var range = new Range(prevPos.node,prevPos.offset,
+                                          selRange.end.node,selRange.end.offset);
+                    Selection_deleteRangeContents(range,true);
+                }
+            }
+        }
+
+        selRange = Selection_get();
+        if (selRange != null)
+            spaceToNbsp(selRange.end);
+        Selection_update();
+        Cursor_ensureCursorVisible();
+
+        function firstBlockAncestor(node)
+        {
+            while (isInlineNode(node))
+                node = node.parentNode;
+            return node;
+        }
+    }
+
+    // public
+    Cursor_enterPressed = function()
+    {
+        UndoManager_newGroup("New paragraph");
+
+        Selection_preferElementPositions();
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+
+        Range_trackWhileExecuting(selRange,function() {
+            if (!Range_isEmpty(selRange))
+                Selection_deleteContents(true);
+        });
+
+        // Are we inside a figure or table caption? If so, put an empty paragraph directly after it
+        var inCaption = false;
+        var inFigCaption = false;
+        var closestNode = Position_closestActualNode(selRange.start);
+        for (var ancestor = closestNode; ancestor != null; ancestor = ancestor.parentNode) {
+            switch (ancestor._type) {
+            case HTML_CAPTION:
+                inCaption = true;
+                break;
+            case HTML_FIGCAPTION:
+                inFigCaption = true;
+                break;
+            case HTML_TABLE:
+            case HTML_FIGURE:
+                if ((inCaption && (ancestor._type == HTML_TABLE)) ||
+                    (inFigCaption && (ancestor._type == HTML_FIGURE))) {
+                    var p = DOM_createElement(document,"P");
+                    DOM_insertBefore(ancestor.parentNode,p,ancestor.nextSibling);
+                    Cursor_updateBRAtEndOfParagraph(p);
+                    Selection_set(p,0,p,0);
+                    return;
+                }
+                break;
+            }
+        }
+
+        // Are we inside a footnote or endnote? If so, move the cursor immediately after it
+        var note = null;
+        if (selRange.start.node.nodeType == Node.TEXT_NODE) {
+            note = Position_noteAncestor(selRange.start);
+        }
+        else {
+            // We can't use Position_noteAncestor in this case, because we want to to break
+            // the paragraph *before* the note, not after
+            var checkNode = selRange.start.node;
+            for (var anc = checkNode; anc != null; anc = anc.parentNode) {
+                if (isNoteNode(anc)) {
+                    note = anc;
+                    break;
+                }
+            }
+        }
+        if (note != null) {
+            var noteOffset = DOM_nodeOffset(note);
+            selRange = new Range(note.parentNode,noteOffset+1,note.parentNode,noteOffset+1);
+        }
+
+        var check = Position_preferElementPosition(selRange.start);
+        if (check.node.nodeType == Node.ELEMENT_NODE) {
+            var before = check.node.childNodes[check.offset-1];
+            var after = check.node.childNodes[check.offset];
+            if (((before != null) && isSpecialBlockNode(before)) ||
+                ((after != null) && isSpecialBlockNode(after))) {
+                var p = DOM_createElement(document,"P");
+                DOM_insertBefore(check.node,p,check.node.childNodes[check.offset]);
+                Cursor_updateBRAtEndOfParagraph(p);
+                Cursor_set(p,0);
+                Cursor_ensureCursorVisible();
+                return;
+            }
+        }
+
+        Range_trackWhileExecuting(selRange,function() {
+            Range_ensureInlineNodesInParagraph(selRange);
+            Range_ensureValidHierarchy(selRange);
+        });
+
+        var pos = selRange.start;
+
+        var detail = Range_detail(selRange);
+        switch (detail.startParent._type) {
+        case HTML_OL:
+        case HTML_UL: {
+            var li = DOM_createElement(document,"LI");
+            DOM_insertBefore(detail.startParent,li,detail.startChild);
+
+            Cursor_set(li,0);
+            Cursor_ensureCursorVisible();
+            return;
+        }
+        }
+
+        if (isAutoCorrectNode(pos.node)) {
+            pos = Position_preferTextPosition(pos);
+            selRange.start = selRange.end = pos;
+        }
+
+        Range_trackWhileExecuting(selRange,function() {
+
+            // If we're directly in a container node, add a paragraph, so we have something to
+            // split.
+            if (isContainerNode(pos.node) && (pos.node._type != HTML_LI)) {
+                var p = DOM_createElement(document,"P");
+                DOM_insertBefore(pos.node,p,pos.node.childNodes[pos.offset]);
+                pos = new Position(p,0);
+            }
+
+            var blockToSplit = getBlockToSplit(pos);
+            var stopAt = blockToSplit.parentNode;
+
+            if (positionAtStartOfHeading(pos)) {
+                var container = getContainerOrParagraph(pos.node);
+                pos = new Position(container,0);
+                pos = Formatting_movePreceding(pos,function(n) { return (n == stopAt); },true);
+            }
+            else if (pos.node.nodeType == Node.TEXT_NODE) {
+                pos = Formatting_splitTextAfter(pos,function(n) { return (n == stopAt); },true);
+            }
+            else {
+                pos = Formatting_moveFollowing(pos,function(n) { return (n == stopAt); },true);
+            }
+        });
+
+        Cursor_set(pos.node,pos.offset);
+        selRange = Selection_get();
+
+        Range_trackWhileExecuting(selRange,function() {
+            if ((pos.node.nodeType == Node.TEXT_NODE) && (pos.node.nodeValue.length == 0)) {
+                DOM_deleteNode(pos.node);
+            }
+
+            var detail = Range_detail(selRange);
+
+            // If a preceding paragraph has become empty as a result of enter being pressed
+            // while the cursor was in it, then update the BR at the end of the paragraph
+            var start = detail.startChild ? detail.startChild : detail.startParent;
+            for (var ancestor = start; ancestor != null; ancestor = ancestor.parentNode) {
+                var prev = ancestor.previousSibling;
+                if ((prev != null) && isParagraphNode(prev) && !nodeHasContent(prev)) {
+                    DOM_deleteAllChildren(prev);
+                    Cursor_updateBRAtEndOfParagraph(prev);
+                    break;
+                }
+                else if ((prev != null) && (prev._type == HTML_LI) && !nodeHasContent(prev)) {
+                    var next;
+                    for (var child = prev.firstChild; child != null; child = next) {
+                        next = child.nextSibling;
+                        if (isWhitespaceTextNode(child))
+                            DOM_deleteNode(child);
+                        else
+                            Cursor_updateBRAtEndOfParagraph(child);
+                    }
+                    break;
+                }
+            }
+
+            for (var ancestor = start; ancestor != null; ancestor = ancestor.parentNode) {
+
+                if (isParagraphNode(ancestor)) {
+                    var nextSelector = Styles_nextSelectorAfter(ancestor);
+                    if (nextSelector != null) {
+                        var nextElementName = null;
+                        var nextClassName = null;
+
+
+                        var dotIndex = nextSelector.indexOf(".");
+                        if (dotIndex >= 0) {
+                            nextElementName = nextSelector.substring(0,dotIndex);
+                            nextClassName = nextSelector.substring(dotIndex+1);
+                        }
+                        else {
+                            nextElementName = nextSelector;
+                        }
+
+                        ancestor = DOM_replaceElement(ancestor,nextElementName);
+                        DOM_removeAttribute(ancestor,"id");
+                        DOM_setAttribute(ancestor,"class",nextClassName);
+                    }
+                }
+
+                if (isParagraphNode(ancestor) && !nodeHasContent(ancestor)) {
+                    Cursor_updateBRAtEndOfParagraph(prev);
+                    break;
+                }
+                else if ((ancestor._type == HTML_LI) && !nodeHasContent(ancestor)) {
+                    DOM_deleteAllChildren(ancestor);
+                    break;
+                }
+            }
+
+            Cursor_updateBRAtEndOfParagraph(Range_singleNode(selRange));
+        });
+
+        Selection_set(selRange.start.node,selRange.start.offset,
+                      selRange.end.node,selRange.end.offset);
+        cursorX = null;
+        Cursor_ensureCursorVisible();
+
+        function getBlockToSplit(pos)
+        {
+            var blockToSplit = null;
+            for (var n = pos.node; n != null; n = n.parentNode) {
+                if (n._type == HTML_LI) {
+                    blockToSplit = n;
+                    break;
+                }
+            }
+            if (blockToSplit == null) {
+                blockToSplit = pos.node;
+                while (isInlineNode(blockToSplit))
+                    blockToSplit = blockToSplit.parentNode;
+            }
+            return blockToSplit;
+        }
+
+        function getContainerOrParagraph(node)
+        {
+            while ((node != null) && isInlineNode(node))
+                node = node.parentNode;
+            return node;
+        }
+
+        function positionAtStartOfHeading(pos)
+        {
+            var container = getContainerOrParagraph(pos.node);
+            if (isHeadingNode(container)) {
+                var startOffset = 0;
+                if (isOpaqueNode(container.firstChild))
+                    startOffset = 1;
+                var range = new Range(container,startOffset,pos.node,pos.offset);
+                return !Range_hasContent(range);
+            }
+            else
+                return false;
+        }
+    }
+
+    Cursor_getPrecedingWord = function() {
+        var selRange = Selection_get();
+        if ((selRange == null) && !Range_isEmpty(selRange))
+            return "";
+
+        var node = selRange.start.node;
+        var offset = selRange.start.offset;
+        if (node.nodeType != Node.TEXT_NODE)
+            return "";
+
+        return node.nodeValue.substring(0,offset);
+    }
+
+    Cursor_getAdjacentNodeWithType = function(type)
+    {
+        var selRange = Selection_get();
+        var pos = Position_preferElementPosition(selRange.start);
+        var node = pos.node;
+        var offset = pos.offset;
+
+        while (true) {
+
+            if (node._type == type)
+                return node;
+
+            if (node.nodeType == Node.ELEMENT_NODE) {
+                var before = node.childNodes[offset-1];
+                if ((before != null) && (before._type == type))
+                    return before;
+
+                var after = node.childNodes[offset];
+                if ((after != null) && (after._type == type))
+                    return after;
+            }
+
+            if (node.parentNode == null)
+                return null;
+
+            offset = DOM_nodeOffset(node);
+            node = node.parentNode;
+        }
+    }
+
+    Cursor_getLinkProperties = function()
+    {
+        var a = Cursor_getAdjacentNodeWithType(HTML_A);
+        if (a == null)
+            return null;
+
+        return { href: a.getAttribute("href"),
+                 text: getNodeText(a) };
+    }
+
+    Cursor_setLinkProperties = function(properties)
+    {
+        var a = Cursor_getAdjacentNodeWithType(HTML_A);
+        if (a == null)
+            return null;
+
+        Selection_preserveWhileExecuting(function() {
+            DOM_setAttribute(a,"href",properties.href);
+            DOM_deleteAllChildren(a);
+            DOM_appendChild(a,DOM_createTextNode(document,properties.text));
+        });
+    }
+
+    Cursor_setReferenceTarget = function(itemId)
+    {
+        var a = Cursor_getAdjacentNodeWithType(HTML_A);
+        if (a != null)
+            Outline_setReferenceTarget(a,itemId);
+    }
+
+    // Deletes the current selection contents and ensures that the cursor is located directly
+    // inside the nearest container element, i.e. not inside a paragraph or inline node. This
+    // is intended for preventing things like inserting a table of contants inside a heading
+    Cursor_makeContainerInsertionPoint = function()
+    {
+        var selRange = Selection_get();
+        if (selRange == null)
+            return;
+
+        if (!Range_isEmpty(selRange)) {
+            Selection_deleteContents();
+            selRange = Selection_get();
+        }
+
+        var parent;
+        var previousSibling;
+        var nextSibling;
+
+        if (selRange.start.node.nodeType == Node.ELEMENT_NODE) {
+            parent = selRange.start.node;
+            nextSibling = selRange.start.node.childNodes[selRange.start.offset];
+        }
+        else {
+            if (selRange.start.offset > 0)
+                Formatting_splitTextBefore(selRange.start);
+            parent = selRange.start.node.parentNode;
+            nextSibling = selRange.start.node;
+        }
+
+        var offset = DOM_nodeOffset(nextSibling,parent);
+
+        if (isContainerNode(parent)) {
+            Cursor_set(parent,offset);
+            return;
+        }
+
+        if ((offset > 0) && isItemNumber(parent.childNodes[offset-1]))
+            offset--;
+
+        Formatting_moveFollowing(new Position(parent,offset),isContainerNode);
+        Formatting_movePreceding(new Position(parent,offset),isContainerNode);
+
+        offset = 0;
+        while (!isContainerNode(parent)) {
+            var old = parent;
+            offset = DOM_nodeOffset(parent);
+            parent = parent.parentNode;
+            DOM_deleteNode(old);
+        }
+
+        Cursor_set(parent,offset);
+        cursorX = null;
+    }
+
+    Cursor_set = function(node,offset,keepCursorX)
+    {
+        Selection_set(node,offset,node,offset);
+        if (!keepCursorX)
+            cursorX = null;
+    }
+
+    function moveRangeOutsideOfNote(range)
+    {
+        var node = range.start.node;
+        var offset = range.start.offset;
+
+        for (var anc = node; anc != null; anc = anc.parentNode) {
+            if (isNoteNode(anc) && (anc.parentNode != null)) {
+                node = anc.parentNode;
+                offset = DOM_nodeOffset(anc)+1;
+                return new Range(node,offset,node,offset);
+            }
+        }
+
+        return range;
+    }
+
+    function insertNote(className,content)
+    {
+        var footnote = DOM_createElement(document,"span");
+        DOM_setAttribute(footnote,"class",className);
+        DOM_appendChild(footnote,DOM_createTextNode(document,content));
+
+        var range = Selection_get();
+        range = moveRangeOutsideOfNote(range);
+        Formatting_splitAroundSelection(range,false);
+
+        // If we're part-way through a text node, splitAroundSelection will give us an
+        // empty text node between the before and after text. For formatting purposes that's
+        // fine (not sure if necessary), but when inserting a footnote or endnote we want
+        // to avoid this as it causes problems with cursor movement - specifically, the cursor
+        // is allowed to go inside the empty text node, and this doesn't show up in the correct
+        // position on screen.
+        var pos = range.start;
+        if ((pos.node._type == HTML_TEXT) &&
+            (pos.node.nodeValue.length == 0)) {
+            var empty = pos.node;
+            pos = new Position(empty.parentNode,DOM_nodeOffset(empty));
+            DOM_deleteNode(empty);
+        }
+        else {
+            pos = Position_preferElementPosition(pos);
+        }
+
+        DOM_insertBefore(pos.node,footnote,pos.node.childNodes[pos.offset]);
+        Selection_set(footnote,0,footnote,footnote.childNodes.length);
+        Cursor_updateBRAtEndOfParagraph(footnote);
+    }
+
+    Cursor_insertFootnote = function(content)
+    {
+        insertNote("footnote",content);
+    }
+
+    Cursor_insertEndnote = function(content)
+    {
+        insertNote("endnote",content);
+    }
+
+})();


[06/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/dtdsource/dtd.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/dtd.js b/experiments/editorFramework/src/Layer0_Javascript/dtdsource/dtd.js
deleted file mode 100644
index 657cd82..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/dtd.js
+++ /dev/null
@@ -1,5562 +0,0 @@
-// Automatically generated from HTML 4.01 dtd using dtdparse and gen_dtd_data.html
-// See http://nwalsh.com/perl/dtdparse/
-
-var ALLOWED_CHILDREN = {
-    "S": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "INPUT": {
-    },
-    "ACRONYM": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "SPAN": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "FIELDSET": {
-        "LEGEND": true,
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "H3": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "OPTION": {
-    },
-    "OPTGROUP": {
-        "OPTION": true,
-    },
-    "DEL": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "SUB": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "META": {
-    },
-    "SUP": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "FONT": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "HR": {
-    },
-    "ISINDEX": {
-    },
-    "TITLE": {
-    },
-    "BODY": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-        "INS": true,
-        "DEL": true,
-    },
-    "NOSCRIPT": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "BASE": {
-    },
-    "EM": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "COL": {
-    },
-    "TABLE": {
-        "CAPTION": true,
-        "COL": true,
-        "COLGROUP": true,
-        "THEAD": true,
-        "TFOOT": true,
-        "TBODY": true,
-    },
-    "DIR": {
-        "LI": true,
-    },
-    "BUTTON": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "HR": true,
-        "TABLE": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-    },
-    "HEAD": {
-        "TITLE": true,
-        "ISINDEX": true,
-        "BASE": true,
-        "SCRIPT": true,
-        "STYLE": true,
-        "META": true,
-        "LINK": true,
-        "OBJECT": true,
-    },
-    "CAPTION": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "Q": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "TR": {
-        "TH": true,
-        "TD": true,
-    },
-    "OL": {
-        "LI": true,
-    },
-    "TBODY": {
-        "TR": true,
-    },
-    "IFRAME": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "LEGEND": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "P": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "CODE": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "DD": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "KBD": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "AREA": {
-    },
-    "H4": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "TH": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "STYLE": {
-    },
-    "INS": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "H6": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "CITE": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "BIG": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "ABBR": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "UL": {
-        "LI": true,
-    },
-    "IMG": {
-    },
-    "DL": {
-        "DT": true,
-        "DD": true,
-    },
-    "H5": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "SAMP": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "MAP": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "AREA": true,
-    },
-    "TFOOT": {
-        "TR": true,
-    },
-    "DFN": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "H1": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "SCRIPT": {
-    },
-    "LINK": {
-    },
-    "DIV": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "H2": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "B": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "ADDRESS": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-        "P": true,
-    },
-    "LI": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "SMALL": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "COLGROUP": {
-        "COL": true,
-    },
-    "VAR": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "THEAD": {
-        "TR": true,
-    },
-    "TEXTAREA": {
-    },
-    "I": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "NOFRAMES": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "SELECT": {
-        "OPTGROUP": true,
-        "OPTION": true,
-    },
-    "STRIKE": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "PARAM": {
-    },
-    "U": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "LABEL": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "BUTTON": true,
-    },
-    "OBJECT": {
-        "PARAM": true,
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "BLOCKQUOTE": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "MENU": {
-        "LI": true,
-    },
-    "DT": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "HTML": {
-        "HEAD": true,
-        "BODY": true,
-    },
-    "A": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "BDO": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "PRE": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "BR": {
-    },
-    "BASEFONT": {
-    },
-    "TT": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "STRONG": {
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "TD": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "APPLET": {
-        "PARAM": true,
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "FORM": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-    "CENTER": {
-        "P": true,
-        "H1": true,
-        "H2": true,
-        "H3": true,
-        "H4": true,
-        "H5": true,
-        "H6": true,
-        "UL": true,
-        "OL": true,
-        "DIR": true,
-        "MENU": true,
-        "PRE": true,
-        "DL": true,
-        "DIV": true,
-        "CENTER": true,
-        "NOSCRIPT": true,
-        "NOFRAMES": true,
-        "BLOCKQUOTE": true,
-        "FORM": true,
-        "ISINDEX": true,
-        "HR": true,
-        "TABLE": true,
-        "FIELDSET": true,
-        "ADDRESS": true,
-        "TT": true,
-        "I": true,
-        "B": true,
-        "U": true,
-        "S": true,
-        "STRIKE": true,
-        "BIG": true,
-        "SMALL": true,
-        "EM": true,
-        "STRONG": true,
-        "DFN": true,
-        "CODE": true,
-        "SAMP": true,
-        "KBD": true,
-        "VAR": true,
-        "CITE": true,
-        "ABBR": true,
-        "ACRONYM": true,
-        "A": true,
-        "IMG": true,
-        "APPLET": true,
-        "OBJECT": true,
-        "FONT": true,
-        "BASEFONT": true,
-        "BR": true,
-        "SCRIPT": true,
-        "MAP": true,
-        "Q": true,
-        "SUB": true,
-        "SUP": true,
-        "SPAN": true,
-        "BDO": true,
-        "IFRAME": true,
-        "INPUT": true,
-        "SELECT": true,
-        "TEXTAREA": true,
-        "LABEL": true,
-        "BUTTON": true,
-    },
-};
-
-var ALLOWED_PARENTS = {
-    "TT": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "I": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "B": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "U": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "S": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "STRIKE": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "BIG": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "SMALL": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "EM": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "STRONG": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "DFN": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "CODE": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "SAMP": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "KBD": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "VAR": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "CITE": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "ABBR": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "ACRONYM": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "A": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "BDO": true,
-        "PRE": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "IMG": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
-    },
-    "APPLET": {
-        "S": true,
-        "ACRONYM": true,
-        "SPAN": true,
-        "FIELDSET": true,
-        "H3": true,
-        "DEL": true,
-        "SUB": true,
-        "SUP": true,
-        "FONT": true,
-        "BODY": true,
-        "NOSCRIPT": true,
-        "EM": true,
-        "BUTTON": true,
-        "CAPTION": true,
-        "Q": true,
-        "IFRAME": true,
-        "LEGEND": true,
-        "P": true,
-        "CODE": true,
-        "DD": true,
-        "KBD": true,
-        "H4": true,
-        "TH": true,
-        "INS": true,
-        "H6": true,
-        "CITE": true,
-        "BIG": true,
-        "ABBR": true,
-        "H5": true,
-        "SAMP": true,
-        "DFN": true,
-        "H1": true,
-        "DIV": true,
-        "H2": true,
-        "B": true,
-        "ADDRESS": true,
-        "LI": true,
-        "SMALL": true,
-        "VAR": true,
-        "I": true,
-        "NOFRAMES": true,
-        "STRIKE": true,
-        "U": true,
-        "LABEL": true,
-        "OBJECT": true,
-        "BLOCKQUOTE": true,
-        "DT": true,
-        "A": true,
-        "BDO": true,
-        "TT": true,
-        "STRONG": true,
-        "TD": true,
-        "APPLET": true,
-        "FORM": true,
-        "CENTER": true,
- 

<TRUNCATED>


[03/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/elementtypes/elements.txt
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/elementtypes/elements.txt b/experiments/editorFramework/src/Layer0_Javascript/elementtypes/elements.txt
deleted file mode 100644
index bd23f64..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/elementtypes/elements.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-#document
-#text
-#comment
-a
-abbr
-address
-area
-article
-aside
-audio
-b
-base
-bdi
-bdo
-blockquote
-body
-br
-button
-canvas
-caption
-cite
-code
-col
-colgroup
-command
-data
-datalist
-dd
-del
-details
-dfn
-dialog
-div
-dl
-dt
-em
-embed
-fieldset
-figcaption
-figure
-footer
-form
-h1
-h2
-h3
-h4
-h5
-h6
-head
-header
-hgroup
-hr
-html
-i
-iframe
-img
-input
-ins
-kbd
-keygen
-label
-legend
-li
-link
-map
-mark
-menu
-meta
-meter
-nav
-noscript
-object
-ol
-optgroup
-option
-output
-p
-param
-pre
-progress
-q
-rp
-rt
-ruby
-s
-samp
-script
-section
-select
-small
-source
-span
-strong
-style
-sub
-summary
-sup
-table
-tbody
-td
-textarea
-tfoot
-th
-thead
-time
-title
-tr
-track
-u
-ul
-var
-video
-wbr

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/elementtypes/genelementtypes.pl
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/elementtypes/genelementtypes.pl b/experiments/editorFramework/src/Layer0_Javascript/elementtypes/genelementtypes.pl
deleted file mode 100644
index 46416e1..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/elementtypes/genelementtypes.pl
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/perl
-
-$filename = $ARGV[0];
-
-#print "filename $filename\n";
-
-@names = ();
-
-open($fh,"<",$filename) or die "Can't open $filename";
-while ($name = <$fh>) {
-  $name =~ s/\n$//;
-  push(@names,$name);
-}
-close($fh);
-
-print("// Automatically generated from $filename\n");
-print("ElementTypes = {\n");
-$nextId = 1;
-for $name (@names) {
-  $upper = uc($name);
-  $lower = lc($name);
-  print("  \"$upper\": $nextId,\n");
-  print("  \"$lower\": $nextId,\n");
-  $nextId++;
-}
-print("};\n");
-print("\n");
-$nextId = 1;
-for $name (@names) {
-  $temp = $name;
-  $temp =~ s/#//;
-  $upper = uc($temp);
-  print("HTML_$upper = $nextId;\n");
-  $nextId++;
-}
-print("HTML_COUNT = $nextId;\n");

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/empty.html
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/empty.html b/experiments/editorFramework/src/Layer0_Javascript/empty.html
deleted file mode 100644
index 42682b4..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/empty.html
+++ /dev/null
@@ -1 +0,0 @@
-<html><body></body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/first.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/first.js b/experiments/editorFramework/src/Layer0_Javascript/first.js
deleted file mode 100644
index 48cfd85..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/first.js
+++ /dev/null
@@ -1,45 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-// FIXME: The _PREFIX variables below must be replaced with functions that return the
-// appropriate namespace prefix for the document in question (since we can't rely on the
-// values that LibreOffice/MS Word happen to use by default)
-
-var XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
-
-// ODF
-
-var OFFICE_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
-var STYLE_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:style:1.0";
-var TEXT_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
-var TABLE_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
-var FO_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0";
-var SVG_NAMESPACE = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";
-var XLINK_NAMESPACE = "http://www.w3.org/1999/xlink";
-
-var OFFICE_PREFIX = "office:";
-var STYLE_PREFIX = "style:";
-var TEXT_PREFIX = "text:";
-var TABLE_PREFIX = "table:";
-var FO_PREFIX = "fo:";
-var SVG_PREFIX = "svg:";
-var XLINK_PREFIX = "xlink:";
-
-// OOXML
-
-var WORD_NAMESPACE = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
-var WORD_PREFIX = "w:";

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/traversal.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/traversal.js b/experiments/editorFramework/src/Layer0_Javascript/traversal.js
deleted file mode 100644
index 439870f..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/traversal.js
+++ /dev/null
@@ -1,184 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-function prevNode(node)
-{
-    if (node.previousSibling != null) {
-        node = node.previousSibling;
-        while (node.lastChild != null)
-            node = node.lastChild;
-        return node;
-    }
-    else {
-        return node.parentNode;
-    }
-}
-
-function nextNodeAfter(node,entering,exiting)
-{
-    while (node != null) {
-        if (node.nextSibling != null) {
-            if (exiting != null)
-                exiting(node);
-            node = node.nextSibling;
-            if (entering != null)
-                entering(node);
-            break;
-        }
-
-        if (exiting != null)
-            exiting(node);
-        node = node.parentNode;
-    }
-    return node;
-}
-
-function nextNode(node,entering,exiting)
-{
-    if (node.firstChild) {
-        node = node.firstChild;
-        if (entering != null)
-            entering(node);
-        return node;
-    }
-    else {
-        return nextNodeAfter(node,entering,exiting);
-    }
-}
-
-function prevTextNode(node)
-{
-    do {
-        node = prevNode(node);
-    } while ((node != null) && (node.nodeType != Node.TEXT_NODE));
-    return node;
-}
-
-function nextTextNode(node)
-{
-    do {
-        node = nextNode(node);
-    } while ((node != null) && (node.nodeType != Node.TEXT_NODE));
-    return node;
-}
-
-function firstChildElement(node)
-{
-    var first = node.firstChild;
-    while ((first != null) && (first.nodeType != Node.ELEMENT_NODE))
-        first = first.nextSibling;
-    return first;
-}
-
-function lastChildElement(node)
-{
-    var last = node.lastChild;
-    while ((last != null) && (last.nodeType != Node.ELEMENT_NODE))
-        last = last.previousSibling;
-    return last;
-}
-
-function firstDescendant(node)
-{
-    while (node.firstChild != null)
-        node = node.firstChild;
-    return node;
-}
-
-function lastDescendant(node)
-{
-    while (node.lastChild != null)
-        node = node.lastChild;
-    return node;
-}
-
-function firstDescendantOfType(node,type)
-{
-    if (node._type == type)
-        return node;
-
-    for (var child = node.firstChild; child != null; child = child.nextSibling) {
-        var result = firstDescendantOfType(child,type);
-        if (result != null)
-            return result;
-    }
-    return null;
-}
-
-function firstChildOfType(node,type)
-{
-    for (var child = node.firstChild; child != null; child = child.nextSibling) {
-        if (child._type == type)
-            return child;
-    }
-    return null;
-}
-
-function getNodeDepth(node)
-{
-    var depth = 0;
-    for (; node != null; node = node.parentNode)
-        depth++;
-    return depth;
-}
-
-function getNodeText(node)
-{
-    var strings = new Array();
-    recurse(node);
-    return strings.join("").replace(/\s+/g," ");
-
-    function recurse(node)
-    {
-        if (node.nodeType == Node.TEXT_NODE)
-            strings.push(node.nodeValue);
-
-        for (var child = node.firstChild; child != null; child = child.nextSibling)
-            recurse(child);
-    }
-}
-
-function isWhitespaceTextNode(node)
-{
-    if (node.nodeType != Node.TEXT_NODE)
-        return false;
-    return isWhitespaceString(node.nodeValue);
-}
-
-function isNonWhitespaceTextNode(node)
-{
-    if (node.nodeType != Node.TEXT_NODE)
-        return false;
-    return !isWhitespaceString(node.nodeValue);
-}
-
-function printTree(node,indent,offset)
-{
-    if (indent == null)
-        indent = "";
-    if (offset == null)
-        offset = "";
-    if ((node.nodeType == Node.ELEMENT_NODE) && node.hasAttribute("class"))
-        debug(indent+offset+nodeString(node)+"."+node.getAttribute("class"));
-    else
-        debug(indent+offset+nodeString(node));
-    var childOffset = 0;
-    for (var child = node.firstChild; child != null; child = child.nextSibling) {
-        printTree(child,indent+"    ",childOffset+" ");
-        childOffset++;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/types.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/types.js b/experiments/editorFramework/src/Layer0_Javascript/types.js
deleted file mode 100644
index b49a709..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/types.js
+++ /dev/null
@@ -1,280 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var CONTAINER_ELEMENTS = new Array(HTML_COUNT);
-CONTAINER_ELEMENTS[HTML_DOCUMENT] = true;
-CONTAINER_ELEMENTS[HTML_HTML] = true;
-CONTAINER_ELEMENTS[HTML_BODY] = true;
-CONTAINER_ELEMENTS[HTML_UL] = true;
-CONTAINER_ELEMENTS[HTML_OL] = true,
-CONTAINER_ELEMENTS[HTML_LI] = true;
-CONTAINER_ELEMENTS[HTML_TABLE] = true;
-CONTAINER_ELEMENTS[HTML_CAPTION] = true;
-CONTAINER_ELEMENTS[HTML_THEAD] = true;
-CONTAINER_ELEMENTS[HTML_TFOOT] = true;
-CONTAINER_ELEMENTS[HTML_TBODY] = true;
-CONTAINER_ELEMENTS[HTML_TR] = true;
-CONTAINER_ELEMENTS[HTML_TH] = true;
-CONTAINER_ELEMENTS[HTML_TD] = true;
-CONTAINER_ELEMENTS[HTML_COL] = true;
-CONTAINER_ELEMENTS[HTML_FIGURE] = true;
-CONTAINER_ELEMENTS[HTML_FIGCAPTION] = true;
-CONTAINER_ELEMENTS[HTML_NAV] = true;
-
-var PARAGRAPH_ELEMENTS = new Array(HTML_COUNT);
-PARAGRAPH_ELEMENTS[HTML_P] = true;
-PARAGRAPH_ELEMENTS[HTML_H1] = true;
-PARAGRAPH_ELEMENTS[HTML_H2] = true;
-PARAGRAPH_ELEMENTS[HTML_H3] = true;
-PARAGRAPH_ELEMENTS[HTML_H4] = true;
-PARAGRAPH_ELEMENTS[HTML_H5] = true;
-PARAGRAPH_ELEMENTS[HTML_H6] = true;
-PARAGRAPH_ELEMENTS[HTML_DIV] = true;
-PARAGRAPH_ELEMENTS[HTML_PRE] = true;
-PARAGRAPH_ELEMENTS[HTML_BLOCKQUOTE] = true;
-
-var BLOCK_ELEMENTS = new Array(HTML_COUNT);
-for (var i = 0; i < HTML_COUNT; i++)
-    BLOCK_ELEMENTS[i] = (CONTAINER_ELEMENTS[i] || PARAGRAPH_ELEMENTS[i]);
-
-var INLINE_ELEMENTS = new Array(HTML_COUNT);
-for (var i = 0; i < HTML_COUNT; i++)
-    INLINE_ELEMENTS[i] = !BLOCK_ELEMENTS[i];
-
-var HEADING_ELEMENTS = new Array(HTML_COUNT);
-HEADING_ELEMENTS[HTML_H1] = true;
-HEADING_ELEMENTS[HTML_H2] = true;
-HEADING_ELEMENTS[HTML_H3] = true;
-HEADING_ELEMENTS[HTML_H4] = true;
-HEADING_ELEMENTS[HTML_H5] = true;
-HEADING_ELEMENTS[HTML_H6] = true;
-
-var CONTAINERS_ALLOWING_CHILDREN = new Array(HTML_COUNT);
-CONTAINERS_ALLOWING_CHILDREN[HTML_BODY] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_LI] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_CAPTION] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_TH] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_TD] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_FIGURE] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_FIGCAPTION] = true;
-CONTAINERS_ALLOWING_CHILDREN[HTML_NAV] = true;
-
-var OUTLINE_TITLE_ELEMENTS = new Array(HTML_COUNT);
-OUTLINE_TITLE_ELEMENTS[HTML_H1] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_H2] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_H3] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_H4] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_H5] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_H6] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_FIGCAPTION] = true;
-OUTLINE_TITLE_ELEMENTS[HTML_CAPTION] = true;
-
-var Keys = {
-    HEADING_NUMBER: "uxwrite-heading-number",
-    FIGURE_NUMBER: "uxwrite-figure-number",
-    TABLE_NUMBER: "uxwrite-table-number",
-    SECTION_TOC: "tableofcontents",
-    FIGURE_TOC: "listoffigures",
-    TABLE_TOC: "listoftables",
-    SELECTION_HIGHLIGHT: "uxwrite-selection-highlight",
-    AUTOCORRECT_ENTRY: "uxwrite-autocorrect-entry",
-    UXWRITE_PREFIX: "uxwrite-",
-    NONE_STYLE: "__none",
-    AUTOCORRECT_CLASS: "uxwrite-autocorrect",
-    SELECTION_CLASS: "uxwrite-selection",
-    ABSTRACT_ELEMENT: "uxwrite-abstract",
-    SPELLING_CLASS: "uxwrite-spelling",
-    MATCH_CLASS: "uxwrite-match",
-};
-
-var ITEM_NUMBER_CLASSES = {
-    "uxwrite-heading-number": true,
-    "uxwrite-figure-number": true,
-    "uxwrite-table-number": true,
-};
-
-var OPAQUE_NODE_CLASSES = {
-    "uxwrite-heading-number": true,
-    "uxwrite-figure-number": true,
-    "uxwrite-table-number": true,
-    "tableofcontents": true,
-    "listoffigures": true,
-    "listoftables": true,
-    "uxwrite-selection-highlight": true,
-    "uxwrite-field": true,
-};
-
-function isContainerNode(node)
-{
-    return CONTAINER_ELEMENTS[node._type];
-}
-
-function isParagraphNode(node)
-{
-    return PARAGRAPH_ELEMENTS[node._type];
-}
-
-function isHeadingNode(node)
-{
-    return HEADING_ELEMENTS[node._type];
-}
-
-function isBlockNode(node)
-{
-    return BLOCK_ELEMENTS[node._type];
-}
-
-function isBlockOrNoteNode(node)
-{
-    return BLOCK_ELEMENTS[node._type] || isNoteNode(node);
-}
-
-function isInlineNode(node)
-{
-    return INLINE_ELEMENTS[node._type];
-}
-
-function isListNode(node)
-{
-    var type = node._type;
-    return ((type == HTML_UL) || (type == HTML_OL));
-}
-
-function isTableCell(node)
-{
-    switch (node._type) {
-    case HTML_TD:
-    case HTML_TH:
-        return true;
-    default:
-        return false;
-    }
-}
-
-function isRefNode(node)
-{
-    return ((node._type == HTML_A) &&
-            node.hasAttribute("href") &&
-            node.getAttribute("href").charAt(0) == "#");
-}
-
-function isNoteNode(node)
-{
-    if (node._type != HTML_SPAN)
-        return false;
-    var className = DOM_getAttribute(node,"class");
-    return ((className == "footnote") || (className == "endnote"));
-}
-
-function isEmptyNoteNode(node)
-{
-    return isNoteNode(node) && !nodeHasContent(node);
-}
-
-function isItemNumber(node)
-{
-    if (node.nodeType == Node.TEXT_NODE) {
-        return isItemNumber(node.parentNode);
-    }
-    else if (node.nodeType == Node.ELEMENT_NODE) {
-        if ((node._type == HTML_SPAN) && node.hasAttribute("class")) {
-            return ITEM_NUMBER_CLASSES[node.getAttribute("class")];
-        }
-    }
-    return false;
-}
-
-function isOpaqueNode(node)
-{
-    if (node == null)
-        return false;
-
-    switch (node._type) {
-    case HTML_TEXT:
-    case HTML_COMMENT:
-        return isOpaqueNode(node.parentNode);
-    case HTML_IMG:
-        return true;
-    case HTML_A:
-        return node.hasAttribute("href");
-    case HTML_DOCUMENT:
-        return false;
-    default:
-        if (node.hasAttribute("class") && OPAQUE_NODE_CLASSES[node.getAttribute("class")])
-            return true;
-        else
-            return isOpaqueNode(node.parentNode);
-    }
-}
-
-function isAutoCorrectNode(node)
-{
-    return ((node._type == HTML_SPAN) &&
-            (node.getAttribute("class") == Keys.AUTOCORRECT_CLASS));
-}
-
-function isSelectionHighlight(node)
-{
-    return ((node.nodeType == Node.ELEMENT_NODE) &&
-            node.getAttribute("class") == Keys.SELECTION_CLASS);
-}
-
-function isSelectionSpan(node)
-{
-    return ((node != null) &&
-            (node._type == HTML_SPAN) &&
-            (DOM_getAttribute(node,"class") == Keys.SELECTION_CLASS));
-};
-
-function isTOCNode(node)
-{
-    if (node._type == HTML_NAV) {
-        var cls = node.getAttribute("class");
-        if ((cls == Keys.SECTION_TOC) ||
-            (cls == Keys.FIGURE_TOC) ||
-            (cls == Keys.TABLE_TOC))
-            return true;
-    }
-    return false;
-}
-
-function isInTOC(node)
-{
-    if (isTOCNode(node))
-        return true;
-    if (node.parentNode != null)
-        return isInTOC(node.parentNode);
-    return false;
-}
-
-function isSpecialBlockNode(node)
-{
-    switch (node._type) {
-    case HTML_TABLE:
-    case HTML_FIGURE:
-        return true;
-    case HTML_NAV:
-        return isTOCNode(node);
-    default:
-        return false;
-    }
-}
-
-function isAbstractSpan(node)
-{
-    return ((node._type == HTML_SPAN) && node.hasAttribute(Keys.ABSTRACT_ELEMENT));
-}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/util.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/util.js b/experiments/editorFramework/src/Layer0_Javascript/util.js
deleted file mode 100644
index 191fc55..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/util.js
+++ /dev/null
@@ -1,365 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-function arrayContains(array,value)
-{
-    for (var i = 0; i < array.length; i++) {
-        if (array[i] == value)
-            return true;
-    }
-    return false;
-}
-
-// Note: you can use slice() to copy a real javascript array, but this function can be used to copy
-// DOM NodeLists (e.g. as returned by document.getElementsByTagName) as well, since they don't
-// support the slice method
-function arrayCopy(array)
-{
-    if (array == null)
-        return null;
-    var copy = new Array();
-    for (var i = 0; i < array.length; i++)
-        copy.push(array[i]);
-    return copy;
-}
-
-function quoteString(str)
-{
-    if (str == null)
-        return null;
-
-    if (str.indexOf('"') < 0)
-        return str;
-
-    var quoted = "";
-    for (var i = 0; i < str.length; i++) {
-        if (str.charAt(i) == '"')
-            quoted += "\\\"";
-        else
-            quoted += str.charAt(i);
-    }
-    return quoted;
-}
-
-function nodeString(node)
-{
-    if (node == null)
-        return "null";
-    var id = "";
-    if (window.debugIds)
-        id = node._nodeId+":";
-    if (node.nodeType == Node.TEXT_NODE) {
-        return id+JSON.stringify(node.nodeValue);
-    }
-    else if (node.nodeType == Node.ELEMENT_NODE) {
-        var name = (node.namespaceURI == null) ? node.nodeName.toUpperCase() : node.nodeName;
-        if (node.hasAttribute("id"))
-            return id+name+"#"+node.getAttribute("id");
-        else
-            return id+name;
-    }
-    else {
-        return id+node.toString();
-    }
-}
-
-function rectString(rect)
-{
-    if (rect == null)
-        return null;
-    else
-        return "("+rect.left+","+rect.top+") - ("+rect.right+","+rect.bottom+")";
-}
-
-function rectIsEmpty(rect)
-{
-    return ((rect == null) ||
-            ((rect.width == 0) && (rect.height == 0)));
-}
-
-function rectContainsPoint(rect,x,y)
-{
-    return ((x >= rect.left) && (x < rect.right) &&
-            (y >= rect.top) && (y < rect.bottom));
-}
-
-function clone(object)
-{
-    var result = new Object();
-    for (var name in object)
-        result[name] = object[name];
-    return result;
-}
-
-function nodeHasContent(node)
-{
-    switch (node._type) {
-    case HTML_TEXT:
-        return !isWhitespaceString(node.nodeValue);
-    case HTML_IMG:
-    case HTML_TABLE:
-        return true;
-    default:
-        if (isOpaqueNode(node))
-            return true;
-
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            if (nodeHasContent(child))
-                return true;
-        }
-        return false;
-    }
-}
-
-function isWhitespaceString(str)
-{
-    return (str.match(isWhitespaceString.regexp) != null);
-}
-
-isWhitespaceString.regexp = /^\s*$/;
-
-function normalizeWhitespace(str)
-{
-    str = str.replace(/^\s+/,"");
-    str = str.replace(/\s+$/,"");
-    str = str.replace(/\s+/g," ");
-    return str;
-}
-
-function DoublyLinkedList()
-{
-    this.first = null;
-    this.last = null;
-}
-
-DoublyLinkedList.prototype.insertAfter = function(item,after)
-{
-    item.prev = null;
-    item.next = null;
-
-    if (this.first == null) { // empty list
-        this.first = item;
-        this.last = item;
-    }
-    else if (after == null) { // insert at start
-        item.next = this.first;
-        this.first = item;
-    }
-    else {
-        item.next = after.next;
-        item.prev = after;
-        if (this.last == after)
-            this.last = item;
-    }
-
-    if (item.next != null)
-        item.next.prev = item;
-    if (item.prev != null)
-        item.prev.next = item;
-};
-
-DoublyLinkedList.prototype.remove = function(item)
-{
-    if (this.first == item)
-        this.first = this.first.next;
-    if (this.last == item)
-        this.last = this.last.prev;
-    if (item.prev != null)
-        item.prev.next = item.next;
-    if (item.next != null)
-        item.next.prev = item.prev;
-    item.prev = null;
-    item.next = null;
-};
-
-function diff(src,dest)
-{
-    var traces = new Array();
-
-    traces[1] = new DiffEntry(0,0,0,0,null);
-
-    for (var distance = 0; true; distance++) {
-        for (var k = -distance; k <= distance; k += 2) {
-            var srcEnd;
-            var prev;
-
-            var del = traces[k-1];
-            var ins = traces[k+1];
-
-            if (((k == -distance) && ins) ||
-                ((k != distance) && ins && del && (del.srcEnd < ins.srcEnd))) {
-                // Down - insertion
-                prev = ins;
-                srcEnd = prev.srcEnd;
-            }
-            else if (del) {
-                // Right - deletion
-                prev = del;
-                srcEnd = prev.srcEnd+1;
-            }
-            else {
-                traces[k] = null;
-                continue;
-            }
-
-            destEnd = srcEnd - k;
-            var srcStart = srcEnd;
-            var destStart = destEnd;
-            while ((srcEnd < src.length) && (destEnd < dest.length) &&
-                   (src[srcEnd] == dest[destEnd])) {
-                srcEnd++;
-                destEnd++;
-            }
-            if ((srcEnd > src.length) || (destEnd > dest.length))
-                traces[k] = null;
-            else
-                traces[k] = new DiffEntry(srcStart,destStart,srcEnd,destEnd,prev);
-            if ((srcEnd >= src.length) && (destEnd >= dest.length)) {
-                return entryToArray(src,dest,traces[k]);
-            }
-        }
-    }
-
-    function DiffEntry(srcStart,destStart,srcEnd,destEnd,prev)
-    {
-        this.srcStart = srcStart;
-        this.destStart = destStart;
-        this.srcEnd = srcEnd;
-        this.destEnd = destEnd;
-        this.prev = prev;
-    }
-
-    function entryToArray(src,dest,entry)
-    {
-        var results = new Array();
-        results.push(entry);
-        for (entry = entry.prev; entry != null; entry = entry.prev) {
-            if ((entry.srcStart != entry.srcEnd) || (entry.destStart != entry.destEnd))
-                results.push(entry);
-        }
-        return results.reverse();
-    }
-}
-
-function TimingEntry(name,time)
-{
-    this.name = name;
-    this.time = time;
-}
-
-function TimingInfo()
-{
-    this.entries = new Array();
-    this.total = 0;
-    this.lastTime = null;
-}
-
-TimingInfo.prototype.start = function()
-{
-    this.entries.length = 0;
-    this.lastTime = new Date();
-};
-
-TimingInfo.prototype.addEntry = function(name)
-{
-    if (this.lastTime == null)
-        this.start();
-
-    var now = new Date();
-    var interval = now - this.lastTime;
-    this.entries.push(new TimingEntry(name,interval));
-    this.total += interval;
-    this.lastTime = now;
-};
-
-TimingInfo.prototype.print = function(title)
-{
-    debug(title);
-    for (var i = 0; i < this.entries.length; i++) {
-        var entry = this.entries[i];
-        debug("    "+entry.name+": "+entry.time+"ms");
-    }
-};
-
-function readFileApp(filename)
-{
-    var req = new XMLHttpRequest("file:///read/"+filename);
-    req.open("POST","/read/"+encodeURI(filename),false);
-    req.send();
-    if (req.status == 404)
-        return null; // file not found
-    else if ((req.status != 200) && (req.status != 0))
-        throw new Error(req.status+": "+req.responseText);
-    var doc = req.responseXML;
-    if (doc != null)
-        DOM_assignNodeIds(doc);
-    return doc;
-}
-
-function readFileTest(filename)
-{
-    var req = new XMLHttpRequest();
-    req.open("GET",filename,false);
-    req.send();
-    var xml = req.responseXML;
-    if (xml == null)
-        return null;
-    DOM_assignNodeIds(xml.documentElement);
-    return xml;
-}
-
-function fromTokenList(value)
-{
-    var result = new Object();
-    if (value != null) {
-        var components = value.toLowerCase().split(/\s+/);
-        for (var i = 0; i < components.length; i++) {
-            if (components[i].length > 0)
-                result[components[i]] = true;
-        }
-    }
-    return result;
-}
-
-function toTokenList(properties)
-{
-    var tokens = new Array();
-
-    if (properties != null) {
-        // Sort the names to ensure deterministic results in test cases
-        var names = Object.getOwnPropertyNames(properties).sort();
-        for (var i = 0; i < names.length; i++) {
-            var name = names[i];
-            if (properties[name])
-                tokens.push(name);
-        }
-    }
-
-    if (tokens.length == null)
-        return null;
-    else
-        return tokens.join(" ");
-}
-
-function xywhAbsElementRect(element)
-{
-    var rect = element.getBoundingClientRect();
-    return { x: rect.left + window.scrollX,
-             y: rect.top + window.scrollY,
-             width: rect.width,
-             height: rect.height };
-}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/Layer1_interface.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/Layer1_interface.hpp b/experiments/editorFramework/src/Layer1_toolkit/Layer1_interface.hpp
deleted file mode 100644
index 042a1a7..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/Layer1_interface.hpp
+++ /dev/null
@@ -1,480 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-#pragma once
-
-#include <QString>
-#include <QRect>
-#include <QJsonObject>
-#include <QJsonArray>
-#include <QTextStream>
-
-/**
- * \file JSInterface.h
- *
- * C++ interface to the JavaScript editor library
- *
- * All of the core editing operations for Corinthia are implemented in the Editor library, which is
- * written in JavaScript. This library can be used either from within a web browser, or, in the case
- * of the Qt application, from an embedded web view. For this app, we use a QWebView instance which
- * maintains the in-memory DOM tree of the document, and has injected into it all of the javascript
- * code that is part of the editor library.
- *
- * The source code of the Editor library lives in (repository-root)/Editor/src. During build of the
- * Qt app, all the javascript files are copied into (build-dir)/share/corinthia/js. If you wish to
- * make changes to the javascript code, you should modify the files in the former location, as the
- * latter files will be overwritten on every build.
- *
- * The purpose of JSInterface.h and JSInterface.cpp is to provide a C++ wrapper over this. All of
- * the methods defined in the classes below (with the exception of callbacks) ultimately result in a
- * call to QWebFrame's evaluateJavaScript() method. See the documentation for JSInterface.cpp for
- * details.
- *
- * The editor library is divided into *modules*, each of which implements a specific aspect of
- * editing functionality. For example, the Cursor module contains methods for moving the cursor
- * around the document, and inserting or deleting text at the current cursor position. Similarly,
- * the Tables module contains methods for inserting, deleting, and modifying tables. A separate C++
- * class is defined for each module, and an instance of each class is maintained by the "container"
- * class, JSInterface. When using the code here, you should do so via a JSInterface instance.
- */
-
-#define JS_MODULE_COMMON(className) \
-Q_DISABLE_COPY(className) \
-public: \
-className(JSEvaluator *evaluator) : JSModule(evaluator) {}
-
-QTextStream& qStdOut();
-QString QRectString(QRect rect);
-
-/**
- * Callback interface
- *
- * While the module classes are for making calls from C++ to JavaScript, the JSCallbacks abstract
- * class is for responding to requests from JavaScript to invoke C++ code. This is declared here as
- * an abstract class (that is, with all methods virtual and no implementations provided) to avoid
- * dependencies between the code in this file and other parts of the application. The
- * EditorJSCallbacks class in Editor.cpp provides a concrete implementation of this, which is where
- * the actual callback functions are implemented.
- *
- * Callbacks are always invoked *after* the execution of a particular editor library API function,
- * not during. The reason for this design design in the library was to enable support for web view
- * classes that did not provide native support for callbacks (as was the case for iOS, at least at
- * the time the library was originally written).
- *
- * The way that callbacks are invoked is that after each editor API call, a query is performed for a
- * list of pending callback messages. The evaluation logic iterates through these and invokes the
- * appropriate callback method for each. For this reason, callbacks method are all 'void' - they
- * never return a value. Callbacks are for notification purposes only - typically telling the
- * application to update the UI in some manner.
- */
-class JSCallbacks
-{
-public:
-    virtual ~JSCallbacks() {}
-    virtual void debug(const QString &message) = 0;
-    virtual void addOutlineItem(const QString &itemId, const QString &type, const QString &title) = 0;
-    virtual void updateOutlineItem(const QString &itemId, const QString &title) = 0;
-    virtual void removeOutlineItem(const QString &itemId) = 0;
-    virtual void outlineUpdated() = 0;
-    virtual void setCursor(int x, int y, int width, int height) = 0;
-    virtual void setSelectionHandles(int x1, int y1, int height1, int x2, int y2, int height2) = 0;
-    virtual void setTableSelection(int x, int y, int width, int height) = 0;
-    virtual void setSelectionBounds(int left, int top, int right, int bottom) = 0;
-    virtual void clearSelectionHandlesAndCursor() = 0;
-    virtual void updateAutoCorrect() = 0;
-    virtual void error(const QString &message, const QString &operation) = 0;
-};
-
-/**
- * The JSEvaluator abstract class provides an evaluate() method which is called (indirectly) by all
- * of the individual module methods. As with JSCallbacks, it is defined as abstract to avoid a
- * dependency on the code outside of this file. The EditorJSEvaluator class in Editor.cpp provides a
- * concrete implementation of this; its evaluate() method simply calls through to the
- * evaluateJavaScript() method of QWebView.
- *
- * JSEvaluator also has a callbacks() method, which must return an instance of JSCallbacks. This
- * makes JSEvaluator the "central point of contact" between the JavaScript interface and the rest of
- * the application, in that it provides the necessary access to call *in* to javascript, and to
- * respond (via callbacks) to calls *out* of javascript. Upon initialisation of a document window,
- * concrete implementations of both JSCallbacks and JSEvaluator are created, the latter maintaining
- * a reference to the former. See Editor::Editor() for where ths is actually done.
- */
-class JSEvaluator
-{
-public:
-    virtual ~JSEvaluator() {}
-    virtual QString evaluate(const QString &script) = 0;
-    virtual JSCallbacks *callbacks() = 0;
-};
-
-class JSAutoCorrect;
-class JSChangeTracking;
-class JSClipboard;
-class JSCursor;
-class JSEquations;
-class JSFigures;
-class JSFormatting;
-class JSInput;
-class JSLists;
-class JSMain;
-class JSMetadata;
-class JSOutline;
-class JSPreview;
-class JSScan;
-class JSSelection;
-class JSStyles;
-class JSTables;
-class JSUndoManager;
-class JSViewport;
-class EDScanParagraph;
-
-class JSError
-{
-public:
-    const QString &type() { return _type; }
-    const QString &message() { return _message; }
-    const QString &operation() { return _operation; }
-    const QString &html() { return _html; }
-
-private:
-
-    QString _type;
-    QString _message;
-    QString _operation;
-    QString _html;
-};
-
-class JSModule
-{
-    Q_DISABLE_COPY(JSModule)
-public:
-    JSModule(JSEvaluator *evaluator) : _evaluator(evaluator) {};
-protected:
-    JSEvaluator *_evaluator;
-};
-
-// Functions implemented in AutoCorrect.js
-
-class JSAutoCorrect : public JSModule
-{
-    JS_MODULE_COMMON(JSAutoCorrect)
-    void correctPrecedingWord(int numChars, const QString &replacement, bool confirmed);
-    QJsonObject getCorrection();
-    QJsonObject getCorrectionCoords();
-    void acceptCorrection();
-    void replaceCorrection(const QString &replacement);
-};
-
-// Functions implemented in ChangeTracking.js
-
-class JSChangeTracking : public JSModule
-{
-    JS_MODULE_COMMON(JSChangeTracking)
-    bool showChanges();
-    bool trackChanges();
-    void setShowChanges(bool showChanges);
-    void setTrackChanges(bool trackChanges);
-};
-
-// Functions implemented in Clipboard.js
-
-class JSClipboard : public JSModule
-{
-    JS_MODULE_COMMON(JSClipboard)
-    QJsonObject clipboardCut();
-    QJsonObject clipboardCopy();
-    void pasteHTML(const QString &html);
-    void pasteText(const QString &text);
-};
-
-// Functions implemented in Cursor.js
-
-class JSCursor : public JSModule
-{
-    JS_MODULE_COMMON(JSCursor)
-    QString positionCursor(int x, int y, bool wordBoundary);
-    QRect getCursorPosition();
-    void moveLeft();
-    void moveRight();
-    void moveToStartOfDocument();
-    void moveToEndOfDocument();
-    void insertReference(const QString &itemId);
-    void insertLink(const QString &text, const QString &url);
-    void insertCharacter(unsigned short character, bool allowInvalidPos);
-    void deleteCharacter();
-    void enterPressed();
-    QString getPrecedingWord();
-    QJsonObject getLinkProperties();
-    void setLinkProperties(QJsonObject properties);
-    void setReferenceTarget(const QString &itemId);
-    void insertFootnote(const QString &content);
-    void insertEndnote(const QString &content);
-};
-
-// Functions implemented in Equations.js
-
-class JSEquations : public JSModule
-{
-    JS_MODULE_COMMON(JSEquations)
-    void insertEquation();
-};
-
-// Functions implemented in Figures.js
-
-class JSFigures : public JSModule
-{
-    JS_MODULE_COMMON(JSFigures)
-    void insertFigure(const QString &filename, const QString &width,
-                      bool numbered, const QString &caption);
-    QString getSelectedFigureId();
-    QJsonObject getProperties(const QString &itemId);
-    void setProperties(const QString &itemId, const QString &width, const QString &src);
-    QJsonObject getGeometry(const QString &itemId);
-};
-
-// Functions implemented in Formatting.js
-
-class JSFormatting : public JSModule
-{
-    JS_MODULE_COMMON(JSFormatting)
-    QJsonObject getFormatting();
-    void applyFormattingChanges(const QString &style, QJsonObject properties);
-};
-
-// Functions implemented in Input.js
-
-class JSInput : public JSModule
-{
-    JS_MODULE_COMMON(JSInput)
-    void removePosition(int posId);
-
-    QString textInRange(int startId, int startAdjust, int endId, int endAdjust);
-    void replaceRange(int startId, int endId, const QString &text);
-    QJsonObject selectedTextRange();
-    void setSelectedTextRange(int startId, int endId);
-    QJsonObject markedTextRange();
-    void setMarkedText(const QString &text, int startOffset, int endOffset);
-    void unmarkText();
-    bool forwardSelectionAffinity();
-    void setForwardSelectionAffinity(bool forwardSelectionAffinity);
-    int positionFromPositionOffset(int posId, int offset);
-    int positionFromPositionInDirectionOffset(int posId, const QString &direction, int offset);
-    int comparePositionToPosition(int positionId, int otherId);
-    int offsetFromPositionToPosition(int fromPosition, int toPosition);
-    int positionWithinRangeFarthestInDirection(int startId, int endId, const QString &direction);
-    QJsonObject characterRangeByExtendingPositionInDirection(int positionId, const QString &direction);
-    QJsonObject firstRectForRange(int startId, int endId);
-    QJsonObject caretRectForPosition(int posId);
-    int closestPositionToPoint(int x, int y);
-    int closestPositionToPointWithinRange(int x, int y, int startId, int endId);
-    QJsonObject characterRangeAtPoint(int x, int y);
-    int positionWithinRangeAtCharacterOffset(int startId, int endId, int offset);
-    int characterOffsetOfPositionWithinRange(int positionId, int startId, int endId);
-
-    bool isPositionAtBoundaryGranularityInDirection(int posId, const QString &granularity,
-                                                    const QString &direction);
-    bool isPositionWithinTextUnitInDirection(int posId, const QString &granularity,
-                                             const QString &direction);
-    int positionFromPositionToBoundaryInDirection(int posId, const QString &granularity,
-                                                  const QString &direction);
-    QJsonObject rangeEnclosingPositionWithGranularityInDirection(int posId,
-                                                                 const QString &granularity,
-                                                                 const QString &direction);
-};
-
-// Functions implemented in Lists.js
-
-class JSLists : public JSModule
-{
-    JS_MODULE_COMMON(JSLists)
-    void increaseIndent();
-    void decreaseIndent();
-    void clearList();
-    void setUnorderedList();
-    void setOrderedList();
-};
-
-// Functions implemented in Main.js
-
-class JSMain : public JSModule
-{
-    JS_MODULE_COMMON(JSMain)
-    QString getLanguage();
-    void setLanguage(const QString &language);
-    QString setGenerator(const QString &generator);
-    bool prepareForSave();
-    QString getHTML();
-    bool isEmptyDocument();
-};
-
-// Functions implemented in Metadata.js
-
-class JSMetadata : public JSModule
-{
-    JS_MODULE_COMMON(JSMetadata)
-    QJsonObject getMetadata();
-    void setMetadata(const QJsonObject &metadata);
-};
-
-// Functions implemented in Outline.js
-
-class JSOutline : public JSModule
-{
-    JS_MODULE_COMMON(JSOutline)
-    QJsonObject getOutline();
-    void moveSection(const QString &sectionId, const QString &parentId, const QString &nextId);
-    void deleteItem(const QString &itemId);
-    void goToItem(const QString &itemId);
-    void scheduleUpdateStructure();
-    void setNumbered(const QString &itemId, bool numbered);
-    void setTitle(const QString &itemId, const QString &title);
-    void insertTableOfContents();
-    void insertListOfFigures();
-    void insertListOfTables();
-    void setPrintMode(bool printMode);
-    QJsonObject examinePrintLayout(int pageHeight);
-    bool detectSectionNumbering();
-    QJsonObject findUsedStyles();
-};
-
-// Functions implemented in Preview.js
-
-class JSPreview : public JSModule
-{
-    JS_MODULE_COMMON(JSPreview)
-    void showForStyle(const QString &styleId, const QString &uiName, const QString &title);
-};
-
-// Functions implemented in Scan.js
-
-class JSScan : public JSModule
-{
-    JS_MODULE_COMMON(JSScan)
-    void reset();
-    EDScanParagraph *next();
-    int addMatch(int start, int end);
-    void showMatch(int matchId);
-    void replaceMatch(int matchId, const QString &text);
-    void removeMatch(int matchId);
-    void goToMatch(int matchId);
-};
-
-// Functions implemented in Selection.js
-
-class JSSelection : public JSModule
-{
-    JS_MODULE_COMMON(JSSelection)
-    void update();
-    void selectAll();
-    void selectParagraph();
-    void selectWordAtCursor();
-    QString dragSelectionBegin(int x, int y, bool selectWord);
-    QString dragSelectionUpdate(int x, int y, bool selectWord);
-    QString moveStartLeft();
-    QString moveStartRight();
-    QString moveEndLeft();
-    QString moveEndRight();
-    void setSelectionStartAtCoords(int x, int y);
-    void setSelectionEndAtCoords(int x, int y);
-    void setTableSelectionEdgeAtCoords(const QString &edge, int x, int y);
-    void print();
-};
-
-// Functions implemented in Styles.js
-
-class JSStyles : public JSModule
-{
-    JS_MODULE_COMMON(JSStyles)
-    QString getCSSText();
-    void setCSSText(const QString &cssText, const QJsonObject &rules);
-    QString paragraphClass();
-    void setParagraphClass(const QString &paragraphClass);
-};
-
-// Functions implemented in Tables.js
-
-class JSTables : public JSModule
-{
-    JS_MODULE_COMMON(JSTables)
-    void insertTable(int rows, int cols, const QString &width, bool numbered,
-                     const QString &caption, const QString &className);
-    void addAdjacentRow();
-    void addAdjacentColumn();
-    void removeAdjacentRow();
-    void removeAdjacentColumn();
-    void clearCells();
-    void mergeCells();
-    void splitSelection();
-    QString getSelectedTableId();
-    QJsonObject getProperties(const QString &itemId);
-    void setProperties(const QString &itemId, const QString &width);
-    void setColWidths(const QString &itemId, const QJsonArray &colWidths);
-    QJsonObject getGeometry(const QString &itemId);
-};
-
-// Functions implemented in UndoManager.js
-
-class JSUndoManager : public JSModule
-{
-    JS_MODULE_COMMON(JSUndoManager)
-    int getLength();
-    int getIndex();
-    void setIndex(int index);
-    void undo();
-    void redo();
-    void newGroup(const QString &name);
-    QString groupType();
-};
-
-// Functions implemented in Viewport.js
-
-class JSViewport : public JSModule
-{
-    JS_MODULE_COMMON(JSViewport)
-    void setViewportWidth(int width);
-    void setTextScale(int textScale);
-};
-
-// All modules
-
-class JSInterface
-{
-    Q_DISABLE_COPY(JSInterface)
-public:
-    JSInterface(JSEvaluator *evaluator);
-    JSAutoCorrect autoCorrect;
-    JSChangeTracking changeTracking;
-    JSClipboard clipboard;
-    JSCursor cursor;
-    JSEquations equations;
-    JSFigures figures;
-    JSFormatting formatting;
-    JSInput input;
-    JSLists lists;
-    JSMain main;
-    JSMetadata metadata;
-    JSOutline outline;
-    JSPreview preview;
-    JSScan scan;
-    JSSelection selection;
-    JSStyles styles;
-    JSTables tables;
-    JSUndoManager undoManager;
-    JSViewport viewport;
-};
-
-void processCallbacks(JSEvaluator *evaluator);

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/README b/experiments/editorFramework/src/Layer1_toolkit/README
deleted file mode 100644
index 8288d80..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/README
+++ /dev/null
@@ -1,3 +0,0 @@
-first example will be Qt
-
-Code will be moved in from other experiments

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/qt/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/qt/README b/experiments/editorFramework/src/Layer1_toolkit/qt/README
deleted file mode 100644
index 0c59bb8..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/qt/README
+++ /dev/null
@@ -1 +0,0 @@
-Qt example code

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.cpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.cpp b/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.cpp
deleted file mode 100644
index 4e1fba4..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.//
-// 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.
-
-#pragma once
-#include "windows.hpp"
-#include "qt_toolkit.hpp"
-
-
-
-toolkit * toolkit::createInstance(toolkit_callback *tk, int debug_level) {
-    return (toolkit *)new qt_toolkit();
-}
-
-
-
-bool qt_toolkit::startWindow() {
-    int    argc = 0;
-    char **argv = NULL;
-
-    app    = new QApplication(argc, argv);
-    window = new MainWindow(app);
-    return true;
-}
-
-
-
-void qt_toolkit::run() {
-    window->show();
-    app->exec();
-}
-
-
-
-bool qt_toolkit::callJavascript(const char *function) {
-    return true;
-}
-
-
-
-#if 0
-{
-}
-
-#endif
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.hpp b/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.hpp
deleted file mode 100644
index 84da8b2..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/qt/qt_toolkit.hpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-#pragma once
-#include "../toolkit.hpp"
-#include <QtWidgets/QApplication>
-
-/*
- * Implementation of toolkit generic interface in Qt
- *
- */
-
-
-class qt_toolkit : toolkit
-{
-    /* toolkit qt implementation */
-
-public:
-    /* Inherited functions */
-    bool startWindow();
-    void run();
-    bool callJavascript(const char *function);
-
-private: 
-    QApplication     *app;
-    MainWindow       *window;
-    toolkit_callback *callback;
-    int               debugLevel;
-};
-

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/qt/windows.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/qt/windows.hpp b/experiments/editorFramework/src/Layer1_toolkit/qt/windows.hpp
deleted file mode 100644
index cdf0ee7..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/qt/windows.hpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-#pragma once
-
-/******************** WINDOWS.HPP ********************
- * This file contain all the graphical classes 
- * inherited from Qt
- */
-
-#include <QtWidgets/QWidget>
-
-
-
-class MainWindow : public QWidget
-{
-    Q_OBJECT
-public:
-    MainWindow(QApplication *app);
-    virtual ~MainWindow();
-    public slots:
-    void insertTable();
-    void insertLink();
-    void insertCharacter();
-    void backspace();
-    void moveLeft();
-    void moveRight();
-    void undo();
-    void redo();
-private:
-    QApplication *_app;
-//    Toolbar *_toolbar;
-//    Editor *_editor;
-};

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/toolkit.hpp
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/toolkit.hpp b/experiments/editorFramework/src/Layer1_toolkit/toolkit.hpp
deleted file mode 100644
index 507ffc0..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/toolkit.hpp
+++ /dev/null
@@ -1,123 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-#pragma once
-
-/*
- * Interface between implementation dependent toolkit and the rest of corinthia.
- *
- * This file describes the smallest possible interface, in order to facilitate easier
- * implementation of other toolkits.
- *
- * The toolkit implementation has the following responsibilities:
- * - Make all graphic manipulation and event handling
- * - Generate the main window, with buttons and a text frame (to show the actual text). Layout is in the TK.
- * - Receive and pass events from the windows/buttons/javasscripts
- * - Manipulate the buttons (enable/disable etc)
- * - Handle dialog boxes, layout is in the TK
- * - Start Javascripts on the text
- * - Provide low level call back with results
- *
- * The toolkit generic part has the following responsibilities:
- * - Provide single calls for every javascript function
- * - Provide manipulation calls (enable, focus etc) for every button
- * - Provide high level call back for each javascript function and button
- *
- * Some of the TK implementations might have a license incompatible with a Apache release, as a consequence the toolkit class
- * makes a complete seperation between the apache world, and the potential non-apache world.
- *
- * The interface consist of 2 classes (each singletons)
- * the toolkit class is instanciated in Layer1 (in the individual implementations) and called from generic Layer1 to
- * activate actions.
- *
- * The toolkit_callback class is instanciated in the generic Layer1 and called from the toolkit implementation to pass results
- * back to the generic layer
- */
-
-
-
-class toolkit_callback {
-    /* Callback interface
-     *
-     * Callbacks are always invoked *after* the execution of a particular editor library API function,
-     * not during. The reason for this design design in the library was to enable support for web view
-     * classes that did not provide native support for callbacks (as was the case for iOS, at least at
-     * the time the library was originally written).
-     *
-     * The way that callbacks are invoked is that after each editor API call, a query is performed for a
-     * list of pending callback messages. The evaluation logic iterates through these and invokes the
-     * appropriate callback method for each. For this reason, callbacks method are all 'void' - they
-     * never return a value. Callbacks are for notification purposes only - typically telling layer2
-     * to update the UI in some manner.
-     */
-
-public:
-    // class is a singleton, so the destructor will only be called when terminating the application
-    ~toolkit_callback() {}
-
-    // Request a debug message to be passed to the log system 
-    // level can have values as defined in the toolkit class
-    void debug(int level, const char *message);
-
-    // pass back Javascript result
-    void notifyJavascript(const char *message);
-
-    // pass back Button action
-    // button can have values as defined in toolkit class
-    // (note windows actions are handled as special buttons)
-    void notifyButtonPressed(int button);
-
-    // pass back Dialogbox action
-    // dialog can have values as defined in toolkit class
-    virtual void notifyDialog(int dialog, const char *message) = 0;
-};
-
-
-
-class toolkit
-{
-    /* toolkit interface
-    *
-    * this class is pure virtual, to make sure it gets implemented in toolkit implementation without any dependencies
-    * from the generic layer.
-    *
-    * Methods in this class activate graphical functions
-    *
-    * A static createInstance() is supplied to allow the TK implementation to instanciate the derived class
-    */
-
-public:
-    // Create instance
-    static const enum {
-        DEBUG_NONE,
-        DEBUG_INFO,
-        DEBUG_WARNING,
-        DEBUG_DEBUG,
-        DEBUG_ERROR
-    };
-    static toolkit *createInstance(toolkit_callback *callback, int debugLevel);
-
-    // Start windows etc
-    virtual bool startWindow() = 0;
-
-    // Start message loop
-    virtual void run() = 0;
-
-    // Start Javascript
-    virtual bool callJavascript(const char *function) = 0;
-};
-

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer1_toolkit/web/README
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer1_toolkit/web/README b/experiments/editorFramework/src/Layer1_toolkit/web/README
deleted file mode 100644
index ffb28ff..0000000
--- a/experiments/editorFramework/src/Layer1_toolkit/web/README
+++ /dev/null
@@ -1 +0,0 @@
-Web server code

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer2_API/EDJSInterface.h
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer2_API/EDJSInterface.h b/experiments/editorFramework/src/Layer2_API/EDJSInterface.h
deleted file mode 100644
index bd6e0d5..0000000
--- a/experiments/editorFramework/src/Layer2_API/EDJSInterface.h
+++ /dev/null
@@ -1,349 +0,0 @@
-//
-//  EDJSInterface.h
-//  Editor
-//
-//  Created by Peter Kelly on 22/11/11.
-//  Copyright (c) 2011-2014 UX Productivity Pty Ltd. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <CoreGraphics/CoreGraphics.h>
-
-@class JSAutoCorrect;
-@class JSChangeTracking;
-@class JSClipboard;
-@class JSCursor;
-@class JSEquations;
-@class JSFigures;
-@class JSFormatting;
-@class JSInput;
-@class JSLists;
-@class JSMain;
-@class JSMetadata;
-@class JSOutline;
-@class JSPreview;
-@class JSScan;
-@class JSSelection;
-@class JSStyles;
-@class JSTables;
-@class JSUndoManager;
-@class JSViewport;
-@class EDScanParagraph;
-
-@interface JSError : NSError
-
-@property (copy, readonly) NSString *type;
-@property (copy, readonly) NSString *message;
-@property (copy, readonly) NSString *operation;
-@property (copy, readonly) NSString *html;
-
-@end
-
-@protocol JSInterfaceDelegate
-
-- (void)jsAddOutlineItem:(NSString *)itemId type:(NSString *)type title:(NSString *)title;
-- (void)jsUpdateOutlineItem:(NSString *)itemId title:(NSString *)title;
-- (void)jsRemoveOutlineItem:(NSString *)itemId;
-- (void)jsOutlineUpdated;
-- (void)jsSetCursorX:(int)x y:(int)y width:(int)width height:(int)height;
-- (void)jsSetSelectionHandlesX1:(int)x1 y1:(int)y1 height1:(int)height1
-                             x2:(int)x2 y2:(int)y2 height2:(int)height2;
-- (void)jsSetTableSelectionX:(int)x y:(int)y width:(int)width height:(int)height;
-- (void)jsSetSelectionBoundsLeft:(int)left top:(int)top right:(int)right bottom:(int)bottom;
-- (void)jsClearSelectionHandlesAndCursor;
-- (void)jsUpdateAutoCorrect;
-
-@end
-
-@protocol JSEvaluator
-
-- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
-
-@end
-
-@interface JSInterface : NSObject
-
-@property (weak) NSObject<JSEvaluator> *evaluator;
-@property (weak) NSObject<JSInterfaceDelegate> *delegate;
-@property (assign) BOOL jsInitialised;
-@property (strong) JSAutoCorrect *autoCorrect;
-@property (strong) JSChangeTracking *changeTracking;
-@property (strong) JSClipboard *clipboard;
-@property (strong) JSCursor *cursor;
-@property (strong) JSEquations *equations;
-@property (strong) JSFigures *figures;
-@property (strong) JSFormatting *formatting;
-@property (strong) JSInput *input;
-@property (strong) JSLists *lists;
-@property (strong) JSMain *main;
-@property (strong) JSMetadata *metadata;
-@property (strong) JSOutline *outline;
-@property (strong) JSPreview *preview;
-@property (strong) JSScan *scan;
-@property (strong) JSSelection *selection;
-@property (strong) JSStyles *styles;
-@property (strong) JSTables *tables;
-@property (strong) JSUndoManager *undoManager;
-@property (strong) JSViewport *viewport;
-@property (copy) NSString *currentOperation;
-@property (strong) JSError *error;
-@property (assign) BOOL documentModified;
-
-- (JSInterface *)initWithEvaluator:(NSObject<JSEvaluator> *)evaluator;
-- (BOOL)initJavaScriptWidth:(int)width textScale:(int)textScale cssURL:(NSString *)cssURL
-             clientRectsBug:(BOOL)clientRectsBug;
-- (void)printStatistics;
-
-@end
-
-@interface JSModule : NSObject
-
-@property (assign) JSInterface *js;
-
-- (JSModule *)initWithJS:(JSInterface *)js;
-
-@end
-
-// Functions implemented in AutoCorrect.js
-
-@interface JSAutoCorrect : JSModule
-
-- (void)correctPreceding:(int)numChars word:(NSString *)replacement confirmed:(BOOL)confirmed;
-- (NSDictionary *)getCorrection;
-- (NSDictionary *)getCorrectionCoords;
-- (void)acceptCorrection;
-- (void)replaceCorrection:(NSString *)replacement;
-
-@end
-
-// Functions implemented in ChangeTracking.js
-
-@interface JSChangeTracking : JSModule
-- (BOOL)showChanges;
-- (BOOL)trackChanges;
-- (void)setShowChanges:(BOOL)showChanges;
-- (void)setTrackChanges:(BOOL)trackChanges;
-@end
-
-// Functions implemented in Clipboard.js
-
-@interface JSClipboard : JSModule
-- (NSDictionary *)clipboardCut;
-- (NSDictionary *)clipboardCopy;
-- (void)pasteHTML:(NSString *)html;
-- (void)pasteText:(NSString *)text;
-@end
-
-// Functions implemented in Cursor.js
-
-@interface JSCursor : JSModule
-- (NSString *)positionCursorX:(int)x y:(int)y wordBoundary:(BOOL)wordBoundary;
-- (CGRect)getCursorPosition;
-- (void)moveLeft;
-- (void)moveRight;
-- (void)moveToStartOfDocument;
-- (void)moveToEndOfDocument;
-- (void)insertReference:(NSString *)itemId;
-- (void)insertLinkWithText:(NSString *)text URL:(NSString *)URL;
-- (void)insertCharacter:(unichar)character allowInvalidPos:(BOOL)allowInvalidPos;
-- (void)deleteCharacter;
-- (void)enterPressed;
-- (NSString *)getPrecedingWord;
-- (NSDictionary *)getLinkProperties;
-- (void)setLinkProperties:(NSDictionary *)properties;
-- (void)setReferenceTarget:(NSString *)itemId;
-- (void)insertFootnote:(NSString *)content;
-- (void)insertEndnote:(NSString *)content;
-@end
-
-// Functions implemented in Equations.js
-
-@interface JSEquations : JSModule
-- (void)insertEquation;
-@end
-
-// Functions implemented in Figures.js
-
-@interface JSFigures : JSModule
-- (void)insertFigure:(NSString *)filename width:(NSString *)width
-            numbered:(BOOL)numbered caption:(NSString *)caption;
-- (NSString *)getSelectedFigureId;
-- (NSDictionary *)getProperties:(NSString *)itemId;
-- (void)setProperties:(NSString *)itemId width:(NSString *)width src:(NSString *)src;
-- (NSDictionary *)getGeometry:(NSString *)itemId;
-@end
-
-// Functions implemented in Formatting.js
-
-@interface JSFormatting : JSModule
-- (NSDictionary *)getFormatting;
-- (void)applyFormattingChangesStyle:(NSString *)style properties:(NSDictionary *)properties;
-@end
-
-// Functions implemented in Input.js
-
-@interface JSInput : JSModule
-- (void)removePosition:(int)posId;
-
-// UITextInput methods
-- (NSString *)textInRangeStartId:(int)startId startAdjust:(int)startAdjust
-                           endId:(int)endId endAdjust:(int)endAdjust;
-- (void)replaceRangeStart:(int)startId end:(int)endId withText:(NSString *)text;
-- (NSDictionary *)selectedTextRange;
-- (void)setSelectedTextRangeStart:(int)startId end:(int)endId;
-- (NSDictionary *)markedTextRange;
-- (void)setMarkedText:(NSString *)text startOffset:(int)startOffset endOffset:(int)endOffset;
-- (void)unmarkText;
-- (BOOL)forwardSelectionAffinity;
-- (void)setForwardSelectionAffinity:(BOOL)forwardSelectionAffinity;
-- (int)positionFromPosition:(int)posId offset:(int)offset;
-- (int)positionFromPosition:(int)posId inDirection:(NSString *)direction offset:(int)offset;
-- (int)comparePosition:(int)positionId toPosition:(int)otherId;
-- (int)offsetFromPosition:(int)fromPosition toPosition:(int)toPosition;
-- (int)positionWithinRangeStart:(int)startId end:(int)endId farthestInDirection:(NSString *)direction;
-- (NSDictionary *)characterRangeByExtendingPosition:(int)positionId inDirection:(NSString *)direction;
-- (NSDictionary *)firstRectForRangeStart:(int)startId end:(int)endId;
-- (NSDictionary *)caretRectForPosition:(int)posId;
-- (int)closestPositionToPointX:(int)x y:(int)y;
-- (int)closestPositionToPointX:(int)x y:(int)y withinRangeStart:(int)startId end:(int)endId;
-- (NSDictionary *)characterRangeAtPointX:(int)x y:(int)y;
-- (int)positionWithinRangeStart:(int)startId end:(int)endId atCharacterOffset:(int)offset;
-- (int)characterOffsetOfPosition:(int)positionId withinRangeStart:(int)startId end:(int)endId;
-
-// UITextInputTokenizer methods
-- (BOOL)isPosition:(int)posId atBoundary:(NSString *)granularity inDirection:(NSString *)direction;
-- (BOOL)isPosition:(int)posId withinTextUnit:(NSString *)granularity inDirection:(NSString *)direction;
-- (int)positionFromPosition:(int)posId toBoundary:(NSString *)granularity inDirection:(NSString *)direction;
-- (NSDictionary *)rangeEnclosingPosition:(int)posId withGranularity:(NSString *)granularity inDirection:(NSString *)direction;
-@end
-
-// Functions implemented in Lists.js
-
-@interface JSLists : JSModule
-- (void)increaseIndent;
-- (void)decreaseIndent;
-- (void)clearList;
-- (void)setUnorderedList;
-- (void)setOrderedList;
-@end
-
-// Functions implemented in Main.js
-
-@interface JSMain : JSModule
-- (NSString *)getLanguage;
-- (void)setLanguage:(NSString *)language;
-- (NSString *)setGenerator:(NSString *)generator;
-- (BOOL)prepareForSave;
-- (NSString *)getHTML;
-- (BOOL)isEmptyDocument;
-@end
-
-// Functions implemented in Metadata.js
-
-@interface JSMetadata : JSModule
-- (NSDictionary *)getMetadata;
-- (void)setMetadata:(NSDictionary *)metadata;
-@end
-
-// Functions implemented in Outline.js
-
-@interface JSOutline : JSModule
-- (NSDictionary *)getOutline;
-- (void)moveSection:(NSString *)sectionId parentId:(NSString *)parentId nextId:(NSString *)nextId;
-- (void)deleteItem:(NSString *)itemId;
-- (void)goToItem:(NSString *)itemId;
-- (void)scheduleUpdateStructure;
-- (void)set:(NSString *)itemId numbered:(BOOL)numbered;
-- (void)set:(NSString *)itemId title:(NSString *)title;
-- (void)insertTableOfContents;
-- (void)insertListOfFigures;
-- (void)insertListOfTables;
-- (void)setPrintMode:(BOOL)printMode;
-- (NSDictionary *)examinePrintLayout:(int)pageHeight;
-- (BOOL)detectSectionNumbering;
-- (NSDictionary *)findUsedStyles;
-@end
-
-// Functions implemented in Preview.js
-
-@interface JSPreview : JSModule
-- (void)showForStyle:(NSString *)styleId uiName:(NSString *)uiName title:(NSString *)title;
-@end
-
-// Functions implemented in Scan.js
-
-@interface JSScan : JSModule
-- (void)reset;
-- (EDScanParagraph *)next;
-- (int)addMatchStart:(int)start end:(int)end;
-- (void)showMatch:(int)matchId;
-- (void)replaceMatch:(int)matchId with:(NSString *)text;
-- (void)removeMatch:(int)matchId;
-- (void)goToMatch:(int)matchId;
-@end
-
-// Functions implemented in Selection.js
-
-@interface JSSelection : JSModule
-- (void)update;
-- (void)selectAll;
-- (void)selectParagraph;
-- (void)selectWordAtCursor;
-- (NSString *)dragSelectionBeginX:(int)x y:(int)y selectWord:(BOOL)selectWord;
-- (NSString *)dragSelectionUpdateX:(int)x y:(int)y selectWord:(BOOL)selectWord;
-- (NSString *)moveStartLeft;
-- (NSString *)moveStartRight;
-- (NSString *)moveEndLeft;
-- (NSString *)moveEndRight;
-- (void)setSelectionStartAtCoordsX:(int)x y:(int)y;
-- (void)setSelectionEndAtCoordsX:(int)x y:(int)y;
-- (void)setTableSelectionEdge:(NSString *)edge atCoordsX:(int)x y:(int)y;
-- (void)print;
-@end
-
-// Functions implemented in Styles.js
-
-@interface JSStyles : JSModule
-- (NSString *)getCSSText;
-- (void)setCSSText:(NSString *)cssText rules:(NSDictionary *)rules;
-- (NSString *)paragraphClass;
-- (void)setParagraphClass:(NSString *)paragraphClass;
-@end
-
-// Functions implemented in Tables.js
-
-@interface JSTables : JSModule
-- (void)insertTableRows:(int)rows cols:(int)cols width:(NSString *)width numbered:(BOOL)numbered
-                caption:(NSString *)caption className:(NSString *)className;
-- (void)addAdjacentRow;
-- (void)addAdjacentColumn;
-- (void)removeAdjacentRow;
-- (void)removeAdjacentColumn;
-- (void)clearCells;
-- (void)mergeCells;
-- (void)splitSelection;
-- (NSString *)getSelectedTableId;
-- (NSDictionary *)getProperties:(NSString *)itemId;
-- (void)setProperties:(NSString *)itemId width:(NSString *)width;
-- (void)set:(NSString *)itemId colWidths:(NSArray *)colWidths;
-- (NSDictionary *)getGeometry:(NSString *)itemId;
-@end
-
-// Functions implemented in UndoManager.js
-
-@interface JSUndoManager : JSModule
-- (int)getLength;
-- (int)getIndex;
-- (void)setIndex:(int)index;
-- (void)undo;
-- (void)redo;
-- (void)newGroup:(NSString *)name;
-- (NSString *)groupType;
-@end
-
-// Functions implemented in Viewport.js
-
-@interface JSViewport : JSModule
-- (void)setViewportWidth:(int)width;
-- (void)setTextScale:(int)textScale;
-@end


[16/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.xml
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.xml b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.xml
new file mode 100644
index 0000000..79d31d6
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.xml
@@ -0,0 +1,11464 @@
+<!DOCTYPE dtd PUBLIC "-//Norman Walsh//DTD DTDParse V2.0//EN"
+              "dtd.dtd" [
+]>
+<dtd version='1.0'
+     unexpanded='1'
+     title="?untitled?"
+     namecase-general="1"
+     namecase-entity="0"
+     xml="0"
+     system-id="html4.dtd"
+     public-id=""
+     declaration=""
+     created-by="DTDParse V2.00"
+     created-on="Sat Feb  4 15:13:29 2012"
+>
+<entity name="ContentTypes"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="ContentType"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="Coords"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="heading"
+        type="param"
+>
+<text-expanded>H1|H2|H3|H4|H5|H6</text-expanded>
+<text>H1|H2|H3|H4|H5|H6</text>
+</entity>
+
+<entity name="HTML.Version"
+        type="param"
+>
+<text-expanded>-//W3C//DTD HTML 4.01 Transitional//EN</text-expanded>
+<text>-//W3C//DTD HTML 4.01 Transitional//EN</text>
+</entity>
+
+<entity name="Text"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="cellhalign"
+        type="param"
+>
+<text-expanded>align      (left|center|right|justify|char) #IMPLIED
+   char       CDATA    #IMPLIED  -- alignment char, e.g. char=':' --
+   charoff    CDATA       #IMPLIED  -- offset for alignment char --</text-expanded>
+<text>align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED  -- alignment char, e.g. char=':' --
+   charoff    %Length;       #IMPLIED  -- offset for alignment char --</text>
+</entity>
+
+<entity name="special"
+        type="param"
+>
+<text-expanded>A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME</text-expanded>
+<text>A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME</text>
+</entity>
+
+<entity name="LinkTypes"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="HTML.Frameset"
+        type="param"
+>
+<text-expanded>IGNORE</text-expanded>
+<text>IGNORE</text>
+</entity>
+
+<entity name="flow"
+        type="param"
+>
+<text-expanded>P | H1|H2|H3|H4|H5|H6 | UL | OL |  DIR | MENU | PRE | DL | DIV | CENTER |
+      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+      TABLE | FIELDSET | ADDRESS | #PCDATA | TT | I | B | U | S | STRIKE | BIG | SMALL | EM | STRONG | DFN | CODE |
+                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM | A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text-expanded>
+<text>%block; | %inline;</text>
+</entity>
+
+<entity name="HTML.Reserved"
+        type="param"
+>
+<text-expanded>IGNORE</text-expanded>
+<text>IGNORE</text>
+</entity>
+
+<entity name="Charsets"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="TFrame"
+        type="param"
+>
+<text-expanded>(void|above|below|hsides|lhs|rhs|vsides|box|border)</text-expanded>
+<text>(void|above|below|hsides|lhs|rhs|vsides|box|border)</text>
+</entity>
+
+<entity name="list"
+        type="param"
+>
+<text-expanded>UL | OL |  DIR | MENU</text-expanded>
+<text>UL | OL |  DIR | MENU</text>
+</entity>
+
+<entity name="inline"
+        type="param"
+>
+<text-expanded>#PCDATA | TT | I | B | U | S | STRIKE | BIG | SMALL | EM | STRONG | DFN | CODE |
+                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM | A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text-expanded>
+<text>#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;</text>
+</entity>
+
+<entity name="attrs"
+        type="param"
+>
+<text-expanded>id          ID             #IMPLIED  -- document-wide unique id --
+  class       CDATA          #IMPLIED  -- space-separated list of classes --
+  style       CDATA   #IMPLIED  -- associated style info --
+  title       CDATA         #IMPLIED  -- advisory title -- lang        NAME #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text -- onclick     CDATA       #IMPLIED  -- a pointer button was clicked --
+  ondblclick  CDATA       #IMPLIED  -- a pointer button was double clicked--
+  onmousedown CDATA       #IMPLIED  -- a pointer button was pressed down --
+  onmouseup   CDATA       #IMPLIED  -- a pointer button was released --
+  onmouseover CDATA       #IMPLIED  -- a pointer was moved onto --
+  onmousemove CDATA       #IMPLIED  -- a pointer was moved within --
+  onmouseout  CDATA       #IMPLIED  -- a pointer was moved away --
+  onkeypress  CDATA       #IMPLIED  -- a key was pressed and released --
+  onkeydown   CDATA       #IMPLIED  -- a key was pressed down --
+  onkeyup     CDATA       #IMPLIED  -- a key was released --</text-expanded>
+<text>%coreattrs; %i18n; %events;</text>
+</entity>
+
+<entity name="head.misc"
+        type="param"
+>
+<text-expanded>SCRIPT|STYLE|META|LINK|OBJECT</text-expanded>
+<text>SCRIPT|STYLE|META|LINK|OBJECT</text>
+</entity>
+
+<entity name="TRules"
+        type="param"
+>
+<text-expanded>(none | groups | rows | cols | all)</text-expanded>
+<text>(none | groups | rows | cols | all)</text>
+</entity>
+
+<entity name="align"
+        type="param"
+>
+<text-expanded>align (left|center|right|justify)  #IMPLIED</text-expanded>
+<text>align (left|center|right|justify)  #IMPLIED</text>
+</entity>
+
+<entity name="LAlign"
+        type="param"
+>
+<text-expanded>(top|bottom|left|right)</text-expanded>
+<text>(top|bottom|left|right)</text>
+</entity>
+
+<entity name="Shape"
+        type="param"
+>
+<text-expanded>(rect|circle|poly|default)</text-expanded>
+<text>(rect|circle|poly|default)</text>
+</entity>
+
+<entity name="head.content"
+        type="param"
+>
+<text-expanded>TITLE &amp; ISINDEX? &amp; BASE?</text-expanded>
+<text>TITLE &amp; ISINDEX? &amp; BASE?</text>
+</entity>
+
+<entity name="MultiLength"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="bodycolors"
+        type="param"
+>
+<text-expanded>
+  bgcolor     CDATA        #IMPLIED  -- document background color --
+  text        CDATA        #IMPLIED  -- document text color --
+  link        CDATA        #IMPLIED  -- color of links --
+  vlink       CDATA        #IMPLIED  -- color of visited links --
+  alink       CDATA        #IMPLIED  -- color of selected links --
+  </text-expanded>
+<text>
+  bgcolor     %Color;        #IMPLIED  -- document background color --
+  text        %Color;        #IMPLIED  -- document text color --
+  link        %Color;        #IMPLIED  -- color of links --
+  vlink       %Color;        #IMPLIED  -- color of visited links --
+  alink       %Color;        #IMPLIED  -- color of selected links --
+  </text>
+</entity>
+
+<entity name="Character"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="InputType"
+        type="param"
+>
+<text-expanded>(TEXT | PASSWORD | CHECKBOX |
+    RADIO | SUBMIT | RESET |
+    FILE | HIDDEN | IMAGE | BUTTON)</text-expanded>
+<text>(TEXT | PASSWORD | CHECKBOX |
+    RADIO | SUBMIT | RESET |
+    FILE | HIDDEN | IMAGE | BUTTON)</text>
+</entity>
+
+<entity name="reserved"
+        type="param"
+>
+<text-expanded></text-expanded>
+<text></text>
+</entity>
+
+<entity name="CAlign"
+        type="param"
+>
+<text-expanded>(top|bottom|left|right)</text-expanded>
+<text>(top|bottom|left|right)</text>
+</entity>
+
+<entity name="pre.exclusion"
+        type="param"
+>
+<text-expanded>IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT</text-expanded>
+<text>IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT</text>
+</entity>
+
+<entity name="coreattrs"
+        type="param"
+>
+<text-expanded>id          ID             #IMPLIED  -- document-wide unique id --
+  class       CDATA          #IMPLIED  -- space-separated list of classes --
+  style       CDATA   #IMPLIED  -- associated style info --
+  title       CDATA         #IMPLIED  -- advisory title --</text-expanded>
+<text>id          ID             #IMPLIED  -- document-wide unique id --
+  class       CDATA          #IMPLIED  -- space-separated list of classes --
+  style       %StyleSheet;   #IMPLIED  -- associated style info --
+  title       %Text;         #IMPLIED  -- advisory title --</text>
+</entity>
+
+<entity name="formctrl"
+        type="param"
+>
+<text-expanded>INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text-expanded>
+<text>INPUT | SELECT | TEXTAREA | LABEL | BUTTON</text>
+</entity>
+
+<entity name="LIStyle"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="noframes.content"
+        type="param"
+>
+<text-expanded>(P | H1|H2|H3|H4|H5|H6 | UL | OL |  DIR | MENU | PRE | DL | DIV | CENTER |
+      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+      TABLE | FIELDSET | ADDRESS | #PCDATA | TT | I | B | U | S | STRIKE | BIG | SMALL | EM | STRONG | DFN | CODE |
+                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM | A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME | INPUT | SELECT | TEXTAREA | LABEL | BUTTON)*</text-expanded>
+<text>(%flow;)*</text>
+</entity>
+
+<entity name="MediaDesc"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="Color"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="fontstyle"
+        type="param"
+>
+<text-expanded>TT | I | B | U | S | STRIKE | BIG | SMALL</text-expanded>
+<text>TT | I | B | U | S | STRIKE | BIG | SMALL</text>
+</entity>
+
+<entity name="Scope"
+        type="param"
+>
+<text-expanded>(row|col|rowgroup|colgroup)</text-expanded>
+<text>(row|col|rowgroup|colgroup)</text>
+</entity>
+
+<entity name="OLStyle"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="cellvalign"
+        type="param"
+>
+<text-expanded>valign     (top|middle|bottom|baseline) #IMPLIED</text-expanded>
+<text>valign     (top|middle|bottom|baseline) #IMPLIED</text>
+</entity>
+
+<entity name="Pixels"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="phrase"
+        type="param"
+>
+<text-expanded>EM | STRONG | DFN | CODE |
+                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM</text-expanded>
+<text>EM | STRONG | DFN | CODE |
+                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM</text>
+</entity>
+
+<entity name="Datetime"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="StyleSheet"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="preformatted"
+        type="param"
+>
+<text-expanded>PRE</text-expanded>
+<text>PRE</text>
+</entity>
+
+<entity name="ULStyle"
+        type="param"
+>
+<text-expanded>(disc|square|circle)</text-expanded>
+<text>(disc|square|circle)</text>
+</entity>
+
+<entity name="URI"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="IAlign"
+        type="param"
+>
+<text-expanded>(top|middle|bottom|left|right)</text-expanded>
+<text>(top|middle|bottom|left|right)</text>
+</entity>
+
+<entity name="html.content"
+        type="param"
+>
+<text-expanded>HEAD, BODY</text-expanded>
+<text>HEAD, BODY</text>
+</entity>
+
+<entity name="version"
+        type="param"
+>
+<text-expanded>version CDATA #FIXED '-//W3C//DTD HTML 4.01 Transitional//EN'</text-expanded>
+<text>version CDATA #FIXED '%HTML.Version;'</text>
+</entity>
+
+<entity name="Charset"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="i18n"
+        type="param"
+>
+<text-expanded>lang        NAME #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --</text-expanded>
+<text>lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --</text>
+</entity>
+
+<entity name="Length"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="FrameTarget"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="TAlign"
+        type="param"
+>
+<text-expanded>(left|center|right)</text-expanded>
+<text>(left|center|right)</text>
+</entity>
+
+<entity name="events"
+        type="param"
+>
+<text-expanded>onclick     CDATA       #IMPLIED  -- a pointer button was clicked --
+  ondblclick  CDATA       #IMPLIED  -- a pointer button was double clicked--
+  onmousedown CDATA       #IMPLIED  -- a pointer button was pressed down --
+  onmouseup   CDATA       #IMPLIED  -- a pointer button was released --
+  onmouseover CDATA       #IMPLIED  -- a pointer was moved onto --
+  onmousemove CDATA       #IMPLIED  -- a pointer was moved within --
+  onmouseout  CDATA       #IMPLIED  -- a pointer was moved away --
+  onkeypress  CDATA       #IMPLIED  -- a key was pressed and released --
+  onkeydown   CDATA       #IMPLIED  -- a key was pressed down --
+  onkeyup     CDATA       #IMPLIED  -- a key was released --</text-expanded>
+<text>onclick     %Script;       #IMPLIED  -- a pointer button was clicked --
+  ondblclick  %Script;       #IMPLIED  -- a pointer button was double clicked--
+  onmousedown %Script;       #IMPLIED  -- a pointer button was pressed down --
+  onmouseup   %Script;       #IMPLIED  -- a pointer button was released --
+  onmouseover %Script;       #IMPLIED  -- a pointer was moved onto --
+  onmousemove %Script;       #IMPLIED  -- a pointer was moved within --
+  onmouseout  %Script;       #IMPLIED  -- a pointer was moved away --
+  onkeypress  %Script;       #IMPLIED  -- a key was pressed and released --
+  onkeydown   %Script;       #IMPLIED  -- a key was pressed down --
+  onkeyup     %Script;       #IMPLIED  -- a key was released --</text>
+</entity>
+
+<entity name="block"
+        type="param"
+>
+<text-expanded>P | H1|H2|H3|H4|H5|H6 | UL | OL |  DIR | MENU | PRE | DL | DIV | CENTER |
+      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+      TABLE | FIELDSET | ADDRESS</text-expanded>
+<text>P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+      TABLE | FIELDSET | ADDRESS</text>
+</entity>
+
+<entity name="Script"
+        type="param"
+>
+<text-expanded>CDATA</text-expanded>
+<text>CDATA</text>
+</entity>
+
+<entity name="LanguageCode"
+        type="param"
+>
+<text-expanded>NAME</text-expanded>
+<text>NAME</text>
+</entity>
+
+<element name="S" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="S">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="INPUT" stagm="-" etagm="O"
+         content-type="element">
+<content-model-expanded>
+  <empty/>
+</content-model-expanded>
+<content-model>
+  <empty/>
+</content-model>
+</element>
+
+<attlist name="INPUT">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  type        %InputType;    TEXT      -- what kind of widget is needed --
+  name        CDATA          #IMPLIED  -- submit as part of form --
+  value       CDATA          #IMPLIED  -- Specify for radio buttons and checkboxes --
+  checked     (checked)      #IMPLIED  -- for radio buttons and check boxes --
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  readonly    (readonly)     #IMPLIED  -- for text and passwd --
+  size        CDATA          #IMPLIED  -- specific to each type of field --
+  maxlength   NUMBER         #IMPLIED  -- max chars for text fields --
+  src         %URI;          #IMPLIED  -- for fields with images --
+  alt         CDATA          #IMPLIED  -- short description --
+  usemap      %URI;          #IMPLIED  -- use client-side image map --
+  ismap       (ismap)        #IMPLIED  -- use server-side image map --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  onselect    %Script;       #IMPLIED  -- some text was selected --
+  onchange    %Script;       #IMPLIED  -- the element value was changed --
+  accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
+  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
+  %reserved;                           -- reserved for possible future use --
+  </attdecl>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onchange"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="readonly"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="readonly"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="align"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="top middle bottom left right"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="src"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="value"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="name"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="checked"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="checked"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="type"
+           type=""
+           enumeration="yes"
+           value="TEXT PASSWORD CHECKBOX RADIO SUBMIT RESET FILE HIDDEN IMAGE BUTTON"
+           default="TEXT"/>
+<attribute name="accesskey"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="disabled"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="disabled"
+           default=""/>
+<attribute name="usemap"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ismap"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ismap"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="size"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onblur"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onfocus"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="maxlength"
+           type="#IMPLIED"
+           value="NUMBER"
+           default=""/>
+<attribute name="onselect"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="accept"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="alt"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="tabindex"
+           type="#IMPLIED"
+           value="NUMBER"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="ACRONYM" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="ACRONYM">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="SPAN" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="SPAN">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %reserved;                   -- reserved for possible future use --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="FIELDSET" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <sequence-group>
+    <pcdata/>
+    <element-name name="LEGEND"/>
+    <or-group occurrence="*">
+      <element-name name="P"/>
+      <element-name name="H1"/>
+      <element-name name="H2"/>
+      <element-name name="H3"/>
+      <element-name name="H4"/>
+      <element-name name="H5"/>
+      <element-name name="H6"/>
+      <element-name name="UL"/>
+      <element-name name="OL"/>
+      <element-name name="DIR"/>
+      <element-name name="MENU"/>
+      <element-name name="PRE"/>
+      <element-name name="DL"/>
+      <element-name name="DIV"/>
+      <element-name name="CENTER"/>
+      <element-name name="NOSCRIPT"/>
+      <element-name name="NOFRAMES"/>
+      <element-name name="BLOCKQUOTE"/>
+      <element-name name="FORM"/>
+      <element-name name="ISINDEX"/>
+      <element-name name="HR"/>
+      <element-name name="TABLE"/>
+      <element-name name="FIELDSET"/>
+      <element-name name="ADDRESS"/>
+      <pcdata/>
+      <element-name name="TT"/>
+      <element-name name="I"/>
+      <element-name name="B"/>
+      <element-name name="U"/>
+      <element-name name="S"/>
+      <element-name name="STRIKE"/>
+      <element-name name="BIG"/>
+      <element-name name="SMALL"/>
+      <element-name name="EM"/>
+      <element-name name="STRONG"/>
+      <element-name name="DFN"/>
+      <element-name name="CODE"/>
+      <element-name name="SAMP"/>
+      <element-name name="KBD"/>
+      <element-name name="VAR"/>
+      <element-name name="CITE"/>
+      <element-name name="ABBR"/>
+      <element-name name="ACRONYM"/>
+      <element-name name="A"/>
+      <element-name name="IMG"/>
+      <element-name name="APPLET"/>
+      <element-name name="OBJECT"/>
+      <element-name name="FONT"/>
+      <element-name name="BASEFONT"/>
+      <element-name name="BR"/>
+      <element-name name="SCRIPT"/>
+      <element-name name="MAP"/>
+      <element-name name="Q"/>
+      <element-name name="SUB"/>
+      <element-name name="SUP"/>
+      <element-name name="SPAN"/>
+      <element-name name="BDO"/>
+      <element-name name="IFRAME"/>
+      <element-name name="INPUT"/>
+      <element-name name="SELECT"/>
+      <element-name name="TEXTAREA"/>
+      <element-name name="LABEL"/>
+      <element-name name="BUTTON"/>
+    </or-group>
+  </sequence-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group>
+    <pcdata/>
+    <element-name name="LEGEND"/>
+    <sequence-group occurrence="*">
+      <parament-name name="flow"/>
+    </sequence-group>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="FIELDSET">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="H3" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="H3">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %align;                              -- align, text alignment --
+  </attdecl>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="align"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="left center right justify"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="OPTION" stagm="-" etagm="O"
+         content-type="mixed">
+<content-model-expanded>
+  <sequence-group>
+    <pcdata/>
+  </sequence-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group>
+    <pcdata/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="OPTION">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  label       %Text;         #IMPLIED  -- for use in hierarchical menus --
+  value       CDATA          #IMPLIED  -- defaults to element content --
+  </attdecl>
+<attribute name="disabled"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="disabled"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="value"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="label"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="selected"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="selected"
+           default=""/>
+</attlist>
+
+<element name="OPTGROUP" stagm="-" etagm="-"
+         content-type="element">
+<content-model-expanded>
+  <sequence-group occurrence="+">
+    <element-name name="OPTION"/>
+  </sequence-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="+">
+    <element-name name="OPTION"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="OPTGROUP">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  label       %Text;         #REQUIRED -- for use in hierarchical menus --
+  </attdecl>
+<attribute name="disabled"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="disabled"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="label"
+           type="#REQUIRED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="DEL" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <element-name name="P"/>
+    <element-name name="H1"/>
+    <element-name name="H2"/>
+    <element-name name="H3"/>
+    <element-name name="H4"/>
+    <element-name name="H5"/>
+    <element-name name="H6"/>
+    <element-name name="UL"/>
+    <element-name name="OL"/>
+    <element-name name="DIR"/>
+    <element-name name="MENU"/>
+    <element-name name="PRE"/>
+    <element-name name="DL"/>
+    <element-name name="DIV"/>
+    <element-name name="CENTER"/>
+    <element-name name="NOSCRIPT"/>
+    <element-name name="NOFRAMES"/>
+    <element-name name="BLOCKQUOTE"/>
+    <element-name name="FORM"/>
+    <element-name name="ISINDEX"/>
+    <element-name name="HR"/>
+    <element-name name="TABLE"/>
+    <element-name name="FIELDSET"/>
+    <element-name name="ADDRESS"/>
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="flow"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="DEL">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  cite        %URI;          #IMPLIED  -- info on reason for change --
+  datetime    %Datetime;     #IMPLIED  -- date and time of change --
+  </attdecl>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="datetime"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="cite"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="SUB" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="SUB">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="META" stagm="-" etagm="O"
+         content-type="element">
+<content-model-expanded>
+  <empty/>
+</content-model-expanded>
+<content-model>
+  <empty/>
+</content-model>
+</element>
+
+<attlist name="META">
+<attdecl>
+  %i18n;                               -- lang, dir, for use with content --
+  http-equiv  NAME           #IMPLIED  -- HTTP response header name  --
+  name        NAME           #IMPLIED  -- metainformation name --
+  content     CDATA          #REQUIRED -- associated information --
+  scheme      CDATA          #IMPLIED  -- select form of content --
+  </attdecl>
+<attribute name="http-equiv"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="content"
+           type="#REQUIRED"
+           value="CDATA"
+           default=""/>
+<attribute name="name"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="scheme"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+</attlist>
+
+<element name="SUP" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="SUP">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="FONT" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="FONT">
+<attdecl>
+  %coreattrs;                          -- id, class, style, title --
+  %i18n;                       -- lang, dir --
+  size        CDATA          #IMPLIED  -- [+|-]nn e.g. size="+1", size="4" --
+  color       %Color;        #IMPLIED  -- text color --
+  face        CDATA          #IMPLIED  -- comma-separated list of font names --
+  </attdecl>
+<attribute name="face"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="color"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="size"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+</attlist>
+
+<element name="HR" stagm="-" etagm="O"
+         content-type="element">
+<content-model-expanded>
+  <empty/>
+</content-model-expanded>
+<content-model>
+  <empty/>
+</content-model>
+</element>
+
+<attlist name="HR">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  align       (left|center|right) #IMPLIED
+  noshade     (noshade)      #IMPLIED
+  size        %Pixels;       #IMPLIED
+  width       %Length;       #IMPLIED
+  </attdecl>
+<attribute name="width"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="size"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="align"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="left center right"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="noshade"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="noshade"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="ISINDEX" stagm="-" etagm="O"
+         content-type="element">
+<content-model-expanded>
+  <empty/>
+</content-model-expanded>
+<content-model>
+  <empty/>
+</content-model>
+</element>
+
+<attlist name="ISINDEX">
+<attdecl>
+  %coreattrs;                          -- id, class, style, title --
+  %i18n;                               -- lang, dir --
+  prompt      %Text;         #IMPLIED  -- prompt message --</attdecl>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="prompt"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+</attlist>
+
+<element name="TITLE" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <sequence-group>
+    <pcdata/>
+  </sequence-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group>
+    <pcdata/>
+  </sequence-group>
+</content-model>
+<exclusions>
+  <or-group>
+    <element-name name="SCRIPT"/>
+    <element-name name="STYLE"/>
+    <element-name name="META"/>
+    <element-name name="LINK"/>
+    <element-name name="OBJECT"/>
+  </or-group>
+</exclusions>
+</element>
+
+<attlist name="TITLE">
+<attdecl> %i18n</attdecl>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+</attlist>
+
+<element name="BODY" stagm="O" etagm="O"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <element-name name="P"/>
+    <element-name name="H1"/>
+    <element-name name="H2"/>
+    <element-name name="H3"/>
+    <element-name name="H4"/>
+    <element-name name="H5"/>
+    <element-name name="H6"/>
+    <element-name name="UL"/>
+    <element-name name="OL"/>
+    <element-name name="DIR"/>
+    <element-name name="MENU"/>
+    <element-name name="PRE"/>
+    <element-name name="DL"/>
+    <element-name name="DIV"/>
+    <element-name name="CENTER"/>
+    <element-name name="NOSCRIPT"/>
+    <element-name name="NOFRAMES"/>
+    <element-name name="BLOCKQUOTE"/>
+    <element-name name="FORM"/>
+    <element-name name="ISINDEX"/>
+    <element-name name="HR"/>
+    <element-name name="TABLE"/>
+    <element-name name="FIELDSET"/>
+    <element-name name="ADDRESS"/>
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="flow"/>
+  </sequence-group>
+</content-model>
+<inclusions>
+  <or-group>
+    <element-name name="INS"/>
+    <element-name name="DEL"/>
+  </or-group>
+</inclusions>
+</element>
+
+<attlist name="BODY">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  onload          %Script;   #IMPLIED  -- the document has been loaded --
+  onunload        %Script;   #IMPLIED  -- the document has been removed --
+  background      %URI;      #IMPLIED  -- texture tile for document
+                                          background --
+  %bodycolors;                         -- bgcolor, text, link, vlink, alink --
+  </attdecl>
+<attribute name="vlink"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="alink"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="bgcolor"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="text"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="link"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="background"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onunload"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onload"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="NOSCRIPT" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <element-name name="P"/>
+    <element-name name="H1"/>
+    <element-name name="H2"/>
+    <element-name name="H3"/>
+    <element-name name="H4"/>
+    <element-name name="H5"/>
+    <element-name name="H6"/>
+    <element-name name="UL"/>
+    <element-name name="OL"/>
+    <element-name name="DIR"/>
+    <element-name name="MENU"/>
+    <element-name name="PRE"/>
+    <element-name name="DL"/>
+    <element-name name="DIV"/>
+    <element-name name="CENTER"/>
+    <element-name name="NOSCRIPT"/>
+    <element-name name="NOFRAMES"/>
+    <element-name name="BLOCKQUOTE"/>
+    <element-name name="FORM"/>
+    <element-name name="ISINDEX"/>
+    <element-name name="HR"/>
+    <element-name name="TABLE"/>
+    <element-name name="FIELDSET"/>
+    <element-name name="ADDRESS"/>
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="flow"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="NOSCRIPT">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="BASE" stagm="-" etagm="O"
+         content-type="element">
+<content-model-expanded>
+  <empty/>
+</content-model-expanded>
+<content-model>
+  <empty/>
+</content-model>
+</element>
+
+<attlist name="BASE">
+<attdecl>
+  href        %URI;          #IMPLIED  -- URI that acts as base URI --
+  target      %FrameTarget;  #IMPLIED  -- render in this frame --
+  </attdecl>
+<attribute name="target"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="href"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="EM" stagm="-" etagm="-"
+         content-type="mixed">
+<content-model-expanded>
+  <or-group occurrence="*">
+    <pcdata/>
+    <element-name name="TT"/>
+    <element-name name="I"/>
+    <element-name name="B"/>
+    <element-name name="U"/>
+    <element-name name="S"/>
+    <element-name name="STRIKE"/>
+    <element-name name="BIG"/>
+    <element-name name="SMALL"/>
+    <element-name name="EM"/>
+    <element-name name="STRONG"/>
+    <element-name name="DFN"/>
+    <element-name name="CODE"/>
+    <element-name name="SAMP"/>
+    <element-name name="KBD"/>
+    <element-name name="VAR"/>
+    <element-name name="CITE"/>
+    <element-name name="ABBR"/>
+    <element-name name="ACRONYM"/>
+    <element-name name="A"/>
+    <element-name name="IMG"/>
+    <element-name name="APPLET"/>
+    <element-name name="OBJECT"/>
+    <element-name name="FONT"/>
+    <element-name name="BASEFONT"/>
+    <element-name name="BR"/>
+    <element-name name="SCRIPT"/>
+    <element-name name="MAP"/>
+    <element-name name="Q"/>
+    <element-name name="SUB"/>
+    <element-name name="SUP"/>
+    <element-name name="SPAN"/>
+    <element-name name="BDO"/>
+    <element-name name="IFRAME"/>
+    <element-name name="INPUT"/>
+    <element-name name="SELECT"/>
+    <element-name name="TEXTAREA"/>
+    <element-name name="LABEL"/>
+    <element-name name="BUTTON"/>
+  </or-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="*">
+    <parament-name name="inline"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="EM">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  </attdecl>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="COL" stagm="-" etagm="O"
+         content-type="element">
+<content-model-expanded>
+  <empty/>
+</content-model-expanded>
+<content-model>
+  <empty/>
+</content-model>
+</element>
+
+<attlist name="COL">
+<attdecl>                          -- column groups and properties --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  span        NUMBER         1         -- COL attributes affect N columns --
+  width       %MultiLength;  #IMPLIED  -- column width specification --
+  %cellhalign;                         -- horizontal alignment in cells --
+  %cellvalign;                         -- vertical alignment in cells --
+  </attdecl>
+<attribute name="width"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="charoff"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="align"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="left center right justify char"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="valign"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="top middle bottom baseline"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="char"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="span"
+           type=""
+           value="NUMBER"
+           default="1"/>
+</attlist>
+
+<element name="TABLE" stagm="-" etagm="-"
+         content-type="element">
+<content-model-expanded>
+  <sequence-group>
+    <element-name name="CAPTION" occurrence="?"/>
+    <or-group>
+      <element-name name="COL" occurrence="*"/>
+      <element-name name="COLGROUP" occurrence="*"/>
+    </or-group>
+    <element-name name="THEAD" occurrence="?"/>
+    <element-name name="TFOOT" occurrence="?"/>
+    <element-name name="TBODY" occurrence="+"/>
+  </sequence-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group>
+    <element-name name="CAPTION" occurrence="?"/>
+    <or-group>
+      <element-name name="COL" occurrence="*"/>
+      <element-name name="COLGROUP" occurrence="*"/>
+    </or-group>
+    <element-name name="THEAD" occurrence="?"/>
+    <element-name name="TFOOT" occurrence="?"/>
+    <element-name name="TBODY" occurrence="+"/>
+  </sequence-group>
+</content-model>
+</element>
+
+<attlist name="TABLE">
+<attdecl>                        -- table element --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  summary     %Text;         #IMPLIED  -- purpose/structure for speech output--
+  width       %Length;       #IMPLIED  -- table width --
+  border      %Pixels;       #IMPLIED  -- controls frame width around table --
+  frame       %TFrame;       #IMPLIED  -- which parts of frame to render --
+  rules       %TRules;       #IMPLIED  -- rulings between rows and cols --
+  cellspacing %Length;       #IMPLIED  -- spacing between cells --
+  cellpadding %Length;       #IMPLIED  -- spacing within cells --
+  align       %TAlign;       #IMPLIED  -- table position relative to window --
+  bgcolor     %Color;        #IMPLIED  -- background color for cells --
+  %reserved;                           -- reserved for possible future use --
+  datapagesize CDATA         #IMPLIED  -- reserved for possible future use --
+  </attdecl>
+<attribute name="width"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="frame"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="void above below hsides lhs rhs vsides box border"
+           default=""/>
+<attribute name="ondblclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="rules"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="none groups rows cols all"
+           default=""/>
+<attribute name="dir"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="ltr rtl"
+           default=""/>
+<attribute name="onkeydown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="datapagesize"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="bgcolor"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="summary"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeyup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="cellspacing"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseup"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="id"
+           type="#IMPLIED"
+           value="ID"
+           default=""/>
+<attribute name="onmouseover"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="align"
+           type="#IMPLIED"
+           enumeration="yes"
+           value="left center right"
+           default=""/>
+<attribute name="lang"
+           type="#IMPLIED"
+           value="NAME"
+           default=""/>
+<attribute name="style"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousemove"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmouseout"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="border"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onmousedown"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onkeypress"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="cellpadding"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="onclick"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="title"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+<attribute name="class"
+           type="#IMPLIED"
+           value="CDATA"
+           default=""/>
+</attlist>
+
+<element name="DIR" stagm="-" etagm="-"
+         content-type="element">
+<content-model-expanded>
+  <sequence-group occurrence="+">
+    <element-name name="LI"/>
+  </sequence-group>
+</content-model-expanded>
+<content-model>
+  <sequence-group occurrence="+">
+    <element-name name="LI"/>
+  </sequence-group>
+</content-model>
+<exclusions>
+  <or-group>
+    <element-name name="P"/>
+    <element-name name="H1"/>
+    <element-name name="H2"/>
+    <element-name name="H3"/>
+    <element-name name="H4"/>
+    <element-name name="H5"/>
+    <element-name name="H6"/>
+    <element-name name="UL"/>
+    <element-name name="OL"/>
+    <element-name name="DIR"/>
+    <element-name name="MENU"/>
+    <element-name name="PRE"/>
+    <element-name name="DL"/>
+    <element-name name="DIV"/>
+    <element-name name="CENTER"/>
+    <element-name name="NOSCRIPT"/>
+    <element-name name="NOFRAMES"/>
+    <element-name name="BLOCKQUOTE"/>
+    <element-name name="FORM"/>
+    <element-name name="ISINDEX"/>
+    <element-name name="HR"/>
+    <element-name name="TABLE"/>
+    <element-name name="FIELDSET"/>
+    <element-name name="ADDRESS"/>
+  </or-group>
+</exclusions>
+</element>
+
+<attlist name="DIR">
+<attdecl>
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  compact     (compact)      #I

<TRUNCATED>


[12/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Formatting.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Formatting.js b/experiments/editorFramework/src/Layer0_Javascript/Formatting.js
deleted file mode 100644
index 51bc5d3..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Formatting.js
+++ /dev/null
@@ -1,1281 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Formatting_splitTextBefore;
-var Formatting_splitTextAfter;
-var Formatting_movePreceding;
-var Formatting_moveFollowing;
-var Formatting_splitAroundSelection;
-var Formatting_mergeUpwards;
-var Formatting_mergeWithNeighbours;
-var Formatting_paragraphTextUpToPosition;
-var Formatting_getAllNodeProperties;
-var Formatting_getFormatting;
-var Formatting_pushDownInlineProperties;
-var Formatting_applyFormattingChanges;
-var Formatting_formatInlineNode;
-
-var Formatting_MERGEABLE_INLINE;
-var Formatting_MERGEABLE_BLOCK;
-var Formatting_MERGEABLE_BLOCK_AND_INLINE;
-
-(function() {
-
-    // Some properties in CSS, such as 'margin', 'border', and 'padding', are shorthands which
-    // set multiple, more fine-grained properties. The CSS spec outlines what these are - e.g.
-    // an assignment to the 'margin' property is considered a simultaneous assignment to
-    // 'margin-left', 'margin-right', 'margin-top', and 'margin-bottom' properties.
-
-    // However, Firefox contains a bug (https://bugzilla.mozilla.org/show_bug.cgi?id=241234),
-    // which has gone unfixed for more than six years, whereby it actually sets different
-    // properties for *-left and *-right, which are reflected when examining the style property
-    // of an element. Additionally, it also gives an error if you try to set these, so if you simply
-    // get all the style properties and try to set them again it won't work.
-
-    // To get around this problem, we record the following set of replacements. When getting the
-    // style properties of an element, we replace any properties with the names given below with
-    // their corresponding spec name. A null entry means that property should be ignored altogether.
-
-    // You should always use getStyleProperties() instead of accessing element.style directly.
-
-    var CSS_PROPERTY_REPLACEMENTS = {
-        "margin-left-value": "margin-left",
-        "margin-left-ltr-source": null,
-        "margin-left-rtl-source": null,
-        "margin-right-value": "margin-right",
-        "margin-right-ltr-source": null,
-        "margin-right-rtl-source": null,
-        "padding-left-value": "padding-left",
-        "padding-left-ltr-source": null,
-        "padding-left-rtl-source": null,
-        "padding-right-value": "padding-right",
-        "padding-right-ltr-source": null,
-        "padding-right-rtl-source": null,
-        "border-right-width-value": "border-right-width",
-        "border-right-width-ltr-source": null,
-        "border-right-width-rtl-source": null,
-        "border-left-width-value": "border-left-width",
-        "border-left-width-ltr-source": null,
-        "border-left-width-rtl-source": null,
-        "border-right-color-value": "border-right-color",
-        "border-right-color-ltr-source": null,
-        "border-right-color-rtl-source": null,
-        "border-left-color-value": "border-left-color",
-        "border-left-color-ltr-source": null,
-        "border-left-color-rtl-source": null,
-        "border-right-style-value": "border-right-style",
-        "border-right-style-ltr-source": null,
-        "border-right-style-rtl-source": null,
-        "border-left-style-value": "border-left-style",
-        "border-left-style-ltr-source": null,
-        "border-left-style-rtl-source": null,
-    };
-
-    // private
-    function getStyleProperties(element,dontReplace)
-    {
-        var properties = new Object();
-
-        for (var i = 0; i < element.style.length; i++) {
-            var name = element.style[i];
-            var value = element.style.getPropertyValue(name);
-
-            var replacement;
-            if (dontReplace) {
-                replacement = name;
-            }
-            else {
-                replacement = CSS_PROPERTY_REPLACEMENTS[name];
-                if (typeof(replacement) == "undefined")
-                    replacement = name;
-            }
-
-            if (replacement != null)
-                properties[replacement] = value;
-        }
-        return properties;
-    }
-
-    // public (for testing purposes only)
-    Formatting_splitAroundSelection = function(range,allowDirectInline)
-    {
-        Range_trackWhileExecuting(range,function() {
-            if (!allowDirectInline)
-                Range_ensureInlineNodesInParagraph(range);
-            Range_ensureValidHierarchy(range);
-
-            if ((range.start.node.nodeType == Node.TEXT_NODE) &&
-                (range.start.offset > 0)) {
-                Formatting_splitTextBefore(range.start);
-                if (range.end.node == range.start.node)
-                    range.end.offset -= range.start.offset;
-                range.start.offset = 0;
-            }
-            else if (range.start.node.nodeType == Node.ELEMENT_NODE) {
-                Formatting_movePreceding(range.start,isBlockOrNoteNode);
-            }
-            else {
-                Formatting_movePreceding(new Position(range.start.node.parentNode,
-                                                      DOM_nodeOffset(range.start.node)),
-                                         isBlockOrNoteNode);
-            }
-
-            // Save the start and end position of the range. The mutation listeners will move it
-            // when the following node is moved, which we don't actually want in this case.
-            var startNode = range.start.node;
-            var startOffset = range.start.offset;
-            var endNode = range.end.node;
-            var endOffset = range.end.offset;
-
-            if ((range.end.node.nodeType == Node.TEXT_NODE) &&
-                (range.end.offset < range.end.node.nodeValue.length)) {
-                Formatting_splitTextAfter(range.end);
-            }
-            else if (range.end.node.nodeType == Node.ELEMENT_NODE) {
-                Formatting_moveFollowing(range.end,isBlockOrNoteNode);
-            }
-            else {
-                Formatting_moveFollowing(new Position(range.end.node.parentNode,
-                                                      DOM_nodeOffset(range.end.node)+1),
-                                         isBlockOrNoteNode);
-            }
-
-            range.start.node = startNode;
-            range.start.offset = startOffset;
-            range.end.node = endNode;
-            range.end.offset = endOffset;
-        });
-    }
-
-    // public
-    Formatting_mergeUpwards = function(node,whiteList)
-    {
-        while ((node != null) && whiteList[node._type]) {
-            var parent = node.parentNode;
-            Formatting_mergeWithNeighbours(node,whiteList,true);
-            node = parent;
-        }
-    }
-
-    function isDiscardable(node)
-    {
-        if (node.nodeType != Node.ELEMENT_NODE)
-            return false;
-
-        if (!isInlineNode(node))
-            return false;
-
-        if (isOpaqueNode(node))
-            return false;
-
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            if (!isDiscardable(child))
-                return false;
-        }
-
-        return true;
-    }
-
-    // public (for use by tests)
-    Formatting_mergeWithNeighbours = function(node,whiteList,trim)
-    {
-        var parent = node.parentNode;
-        if (parent == null)
-            return;
-
-        var start = node;
-        var end = node;
-
-        while ((start.previousSibling != null) &&
-               DOM_nodesMergeable(start.previousSibling,start,whiteList))
-            start = start.previousSibling;
-
-        while ((end.nextSibling != null) &&
-               DOM_nodesMergeable(end,end.nextSibling,whiteList))
-            end = end.nextSibling;
-
-        if (trim) {
-            while ((start.previousSibling != null) && isDiscardable(start.previousSibling))
-                DOM_deleteNode(start.previousSibling);
-            while ((end.nextSibling != null) && isDiscardable(end.nextSibling))
-                DOM_deleteNode(end.nextSibling);
-        }
-
-        if (start != end) {
-            var lastMerge;
-            do {
-                lastMerge = (start.nextSibling == end);
-
-                var lastChild = null;
-                if (start.nodeType == Node.ELEMENT_NODE)
-                    lastChild = start.lastChild;
-
-                DOM_mergeWithNextSibling(start,whiteList);
-
-                if (lastChild != null)
-                    Formatting_mergeWithNeighbours(lastChild,whiteList);
-            } while (!lastMerge);
-        }
-    }
-
-    // private
-    function mergeRange(range,whiteList)
-    {
-        var nodes = Range_getAllNodes(range);
-        for (var i = 0; i < nodes.length; i++) {
-            var next;
-            for (var p = nodes[i]; p != null; p = next) {
-                next = p.parentNode;
-                Formatting_mergeWithNeighbours(p,whiteList);
-            }
-        }
-    }
-
-    // public (called from cursor.js)
-    Formatting_splitTextBefore = function(pos,parentCheckFn,force)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if (parentCheckFn == null)
-            parentCheckFn = isBlockNode;
-
-        if (force || (offset > 0)) {
-            var before = DOM_createTextNode(document,"");
-            DOM_insertBefore(node.parentNode,before,node);
-            DOM_moveCharacters(node,0,offset,before,0,false,true);
-            Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)),
-                                     parentCheckFn,force);
-            return new Position(before,before.nodeValue.length);
-        }
-        else {
-            Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)),
-                                     parentCheckFn,force);
-            return pos;
-        }
-    }
-
-    // public
-    Formatting_splitTextAfter = function(pos,parentCheckFn,force)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if (parentCheckFn == null)
-            parentCheckFn = isBlockNode;
-
-        if (force || (offset < pos.node.nodeValue.length)) {
-            var after = DOM_createTextNode(document,"");
-            DOM_insertBefore(node.parentNode,after,node.nextSibling);
-            DOM_moveCharacters(node,offset,node.nodeValue.length,after,0,true,false);
-            Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1),
-                                     parentCheckFn,force);
-            return new Position(after,0);
-        }
-        else {
-            Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1),
-                                     parentCheckFn,force);
-            return pos;
-        }
-    }
-
-    // FIXME: movePreceding and moveNext could possibly be optimised by passing in a (parent,child)
-    // pair instead of (node,offset), i.e. parent is the same as node, but rather than passing the
-    // index of a child, we pass the child itself (or null if the offset is equal to
-    // childNodes.length)
-    // public
-    Formatting_movePreceding = function(pos,parentCheckFn,force)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if (parentCheckFn(node) || (node == document.body))
-            return new Position(node,offset);
-
-        var toMove = new Array();
-        var justWhitespace = true;
-        var result = new Position(node,offset);
-        for (var i = 0; i < offset; i++) {
-            if (!isWhitespaceTextNode(node.childNodes[i]))
-                justWhitespace = false;
-            toMove.push(node.childNodes[i]);
-        }
-
-        if ((toMove.length > 0) || force) {
-            if (justWhitespace && !force) {
-                for (var i = 0; i < toMove.length; i++)
-                    DOM_insertBefore(node.parentNode,toMove[i],node);
-            }
-            else {
-                var copy = DOM_shallowCopyElement(node);
-                DOM_insertBefore(node.parentNode,copy,node);
-
-                for (var i = 0; i < toMove.length; i++)
-                    DOM_insertBefore(copy,toMove[i],null);
-                result = new Position(copy,copy.childNodes.length);
-            }
-        }
-
-        Formatting_movePreceding(new Position(node.parentNode,DOM_nodeOffset(node)),
-                                 parentCheckFn,force);
-        return result;
-    }
-
-    // public
-    Formatting_moveFollowing = function(pos,parentCheckFn,force)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-        if (parentCheckFn(node) || (node == document.body))
-            return new Position(node,offset);
-
-        var toMove = new Array();
-        var justWhitespace = true;
-        var result =  new Position(node,offset);
-        for (var i = offset; i < node.childNodes.length; i++) {
-            if (!isWhitespaceTextNode(node.childNodes[i]))
-                justWhitespace = false;
-            toMove.push(node.childNodes[i]);
-        }
-
-        if ((toMove.length > 0) || force) {
-            if (justWhitespace && !force) {
-                for (var i = 0; i < toMove.length; i++)
-                    DOM_insertBefore(node.parentNode,toMove[i],node.nextSibling);
-            }
-            else {
-                var copy = DOM_shallowCopyElement(node);
-                DOM_insertBefore(node.parentNode,copy,node.nextSibling);
-
-                for (var i = 0; i < toMove.length; i++)
-                    DOM_insertBefore(copy,toMove[i],null);
-                result = new Position(copy,0);
-            }
-        }
-
-        Formatting_moveFollowing(new Position(node.parentNode,DOM_nodeOffset(node)+1),
-                                 parentCheckFn,force);
-        return result;
-    }
-
-    // public
-    Formatting_paragraphTextUpToPosition = function(pos)
-    {
-        if (pos.node.nodeType == Node.TEXT_NODE) {
-            return stringToStartOfParagraph(pos.node,pos.offset);
-        }
-        else {
-            return stringToStartOfParagraph(Position_closestActualNode(pos),0);
-        }
-
-        function stringToStartOfParagraph(node,offset)
-        {
-            var start = node;
-            var components = new Array();
-            while (isInlineNode(node)) {
-                if (node.nodeType == Node.TEXT_NODE) {
-                    if (node == start)
-                        components.push(node.nodeValue.slice(0,offset));
-                    else
-                        components.push(node.nodeValue);
-                }
-
-                if (node.previousSibling != null) {
-                    node = node.previousSibling;
-                    while (isInlineNode(node) && (node.lastChild != null))
-                        node = node.lastChild;
-                }
-                else {
-                    node = node.parentNode;
-                }
-            }
-            return components.reverse().join("");
-        }
-    }
-
-    // public
-    Formatting_getFormatting = function()
-    {
-        // FIXME: implement a more efficient version of this algorithm which avoids duplicate checks
-
-        var range = Selection_get();
-        if (range == null)
-            return {};
-
-        Range_assertValid(range,"Selection");
-
-        var outermost = Range_getOutermostNodes(range,true);
-
-        var leafNodes = new Array();
-        for (var i = 0; i < outermost.length; i++) {
-            findLeafNodes(outermost[i],leafNodes);
-        }
-        var empty = Range_isEmpty(range);
-
-        var commonProperties = null;
-        for (var i = 0; i < leafNodes.length; i++) {
-            if (!isWhitespaceTextNode(leafNodes[i]) || empty) {
-                var leafNodeProperties = Formatting_getAllNodeProperties(leafNodes[i]);
-                if (leafNodeProperties["-uxwrite-paragraph-style"] == null)
-                    leafNodeProperties["-uxwrite-paragraph-style"] = Keys.NONE_STYLE;
-                if (commonProperties == null)
-                    commonProperties = leafNodeProperties;
-                else
-                    commonProperties = intersection(commonProperties,leafNodeProperties);
-            }
-        }
-
-        if (commonProperties == null)
-            commonProperties = {"-uxwrite-paragraph-style": Keys.NONE_STYLE};
-
-        for (var i = 0; i < leafNodes.length; i++) {
-            var leaf = leafNodes[i];
-            if (leaf._type == HTML_LI) {
-                switch (leaf.parentNode._type) {
-                case HTML_UL:
-                    commonProperties["-uxwrite-in-ul"] = "true";
-                    break;
-                case HTML_OL:
-                    commonProperties["-uxwrite-in-ol"] = "true";
-                    break;
-                }
-            }
-            else {
-                for (var ancestor = leaf;
-                     ancestor.parentNode != null;
-                     ancestor = ancestor.parentNode) {
-
-                    if (ancestor.parentNode._type == HTML_LI) {
-                        var havePrev = false;
-                        for (var c = ancestor.previousSibling; c != null; c = c.previousSibling) {
-                            if (!isWhitespaceTextNode(c)) {
-                                havePrev = true;
-                                break;
-                            }
-                        }
-                        if (!havePrev) {
-                            var listNode = ancestor.parentNode.parentNode;
-                            switch (listNode._type) {
-                            case HTML_UL:
-                                commonProperties["-uxwrite-in-ul"] = "true";
-                                break;
-                            case HTML_OL:
-                                commonProperties["-uxwrite-in-ol"] = "true";
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        getFlags(range.start,commonProperties);
-
-        return commonProperties;
-
-        function getFlags(pos,commonProperties)
-        {
-            var strBeforeCursor = Formatting_paragraphTextUpToPosition(pos);
-
-            if (isWhitespaceString(strBeforeCursor)) {
-                var firstInParagraph = true;
-                for (var p = pos.node; isInlineNode(p); p = p.parentNode) {
-                    if (p.previousSibling != null)
-                        firstInParagraph = false;
-                }
-                if (firstInParagraph)
-                    commonProperties["-uxwrite-shift"] = "true";
-            }
-            if (strBeforeCursor.match(/\.\s*$/))
-                commonProperties["-uxwrite-shift"] = "true";
-            if (strBeforeCursor.match(/\([^\)]*$/))
-                commonProperties["-uxwrite-in-brackets"] = "true";
-            if (strBeforeCursor.match(/\u201c[^\u201d]*$/))
-                commonProperties["-uxwrite-in-quotes"] = "true";
-        }
-
-        function intersection(a,b)
-        {
-            var result = new Object();
-            for (var name in a) {
-                if (a[name] == b[name])
-                    result[name] = a[name];
-            }
-            return result;
-        }
-
-        function findLeafNodes(node,result)
-        {
-            if (node.firstChild == null) {
-                result.push(node);
-            }
-            else {
-                for (var child = node.firstChild; child != null; child = child.nextSibling)
-                    findLeafNodes(child,result);
-            }
-        }
-    }
-
-    // public
-    Formatting_getAllNodeProperties = function(node)
-    {
-        if (node == null)
-            throw new Error("Node is not in tree");
-
-        if (node == node.ownerDocument.body)
-            return new Object();
-
-        var properties = Formatting_getAllNodeProperties(node.parentNode);
-
-        if (node.nodeType == Node.ELEMENT_NODE) {
-            // Note: Style names corresponding to element names must be in lowercase, because
-            // canonicaliseSelector() in Styles.js always converts selectors to lowercase.
-            if (node.hasAttribute("STYLE")) {
-                var nodeProperties = getStyleProperties(node);
-                for (var name in nodeProperties)
-                    properties[name] = nodeProperties[name];
-            }
-
-            var type = node._type;
-            switch (type) {
-            case HTML_B:
-                properties["font-weight"] = "bold";
-                break;
-            case HTML_I:
-                properties["font-style"] = "italic";
-                break;
-            case HTML_U: {
-                var components = [];
-                if (properties["text-decoration"] != null) {
-                    var components = properties["text-decoration"].toLowerCase().split(/\s+/);
-                    if (components.indexOf("underline") == -1)
-                        properties["text-decoration"] += " underline";
-                }
-                else {
-                    properties["text-decoration"] = "underline";
-                }
-                break;
-            }
-//            case HTML_TT:
-//                properties["-uxwrite-in-tt"] = "true";
-//                break;
-            case HTML_IMG:
-                properties["-uxwrite-in-image"] = "true";
-                break;
-            case HTML_FIGURE:
-                properties["-uxwrite-in-figure"] = "true";
-                break;
-            case HTML_TABLE:
-                properties["-uxwrite-in-table"] = "true";
-                break;
-            case HTML_A:
-                if (node.hasAttribute("href")) {
-                    var href = node.getAttribute("href");
-                    if (href.charAt(0) == "#")
-                        properties["-uxwrite-in-reference"] = "true";
-                    else
-                        properties["-uxwrite-in-link"] = "true";
-                }
-                break;
-            case HTML_NAV: {
-                var className = DOM_getAttribute(node,"class");
-                if ((className == Keys.SECTION_TOC) ||
-                    (className == Keys.FIGURE_TOC) ||
-                    (className == Keys.TABLE_TOC))
-                    properties["-uxwrite-in-toc"] = "true";
-                break;
-            }
-            default:
-                if (PARAGRAPH_ELEMENTS[type]) {
-                    var name = node.nodeName.toLowerCase();
-                    var selector;
-                    if (node.hasAttribute("class"))
-                        selector = name + "." + node.getAttribute("class");
-                    else
-                        selector = name;
-                    properties["-uxwrite-paragraph-style"] = selector;
-                }
-                break;
-            }
-
-            if (OUTLINE_TITLE_ELEMENTS[type] && node.hasAttribute("id"))
-                properties["-uxwrite-in-item-title"] = node.getAttribute("id");
-        }
-
-        return properties;
-    }
-
-    var PARAGRAPH_PROPERTIES = {
-        "margin-left": true,
-        "margin-right": true,
-        "margin-top": true,
-        "margin-bottom": true,
-
-        "padding-left": true,
-        "padding-right": true,
-        "padding-top": true,
-        "padding-bottom": true,
-
-        "border-left-width": true,
-        "border-right-width": true,
-        "border-top-width": true,
-        "border-bottom-width": true,
-
-        "border-left-style": true,
-        "border-right-style": true,
-        "border-top-style": true,
-        "border-bottom-style": true,
-
-        "border-left-color": true,
-        "border-right-color": true,
-        "border-top-color": true,
-        "border-bottom-color": true,
-
-        "border-top-left-radius": true,
-        "border-top-right-radius": true,
-        "border-bottom-left-radius": true,
-        "border-bottom-right-radius": true,
-
-        "text-align": true,
-        "text-indent": true,
-        "line-height": true,
-        "display": true,
-
-        "width": true,
-        "height": true,
-    };
-
-    var SPECIAL_PROPERTIES = {
-        "-webkit-text-size-adjust": true, // set on HTML element for text scaling purposes
-    };
-
-    function isParagraphProperty(name)
-    {
-        return PARAGRAPH_PROPERTIES[name];
-    }
-
-    function isInlineProperty(name)
-    {
-        return !PARAGRAPH_PROPERTIES[name] && !SPECIAL_PROPERTIES[name];
-    }
-
-    // private
-    function putDirectInlineChildrenInParagraphs(parent)
-    {
-        var inlineChildren = new Array();
-        for (var child = parent.firstChild; child != null; child = child.nextSibling)
-            if (isInlineNode(child))
-                inlineChildren.push(child);
-        for (var i = 0; i < inlineChildren.length; i++) {
-            if (inlineChildren[i].parentNode == parent) { // may already have been moved
-                if (!isWhitespaceTextNode(inlineChildren[i]))
-                    Hierarchy_wrapInlineNodesInParagraph(inlineChildren[i]);
-            }
-        }
-    }
-
-    // private
-    function getParagraphs(nodes)
-    {
-        var array = new Array();
-        var set = new NodeSet();
-        for (var i = 0; i < nodes.length; i++) {
-            for (var anc = nodes[i].parentNode; anc != null; anc = anc.parentNode) {
-                if (anc._type == HTML_LI)
-                    putDirectInlineChildrenInParagraphs(anc);
-            }
-            recurse(nodes[i]);
-        }
-
-        var remove = new NodeSet();
-        for (var i = 0; i < array.length; i++) {
-            for (var anc = array[i].parentNode; anc != null; anc = anc.parentNode)
-                remove.add(anc);
-        }
-
-        var modified = new Array();
-        for (var i = 0; i < array.length; i++) {
-            if (!remove.contains(array[i]))
-                modified.push(array[i]);
-        }
-
-        return modified;
-
-        function recurse(node)
-        {
-            if (node._type == HTML_LI)
-                putDirectInlineChildrenInParagraphs(node);
-            if (node.firstChild == null) {
-                // Leaf node
-                for (var anc = node; anc != null; anc = anc.parentNode)
-                    if (isParagraphNode(anc)) {
-                        add(anc);
-                    }
-            }
-            else {
-                for (var child = node.firstChild; child != null; child = child.nextSibling)
-                    recurse(child);
-            }
-        }
-
-        function add(node)
-        {
-            if (!set.contains(node)) {
-                array.push(node);
-                set.add(node);
-            }
-        }
-    }
-
-    // private
-    function setParagraphStyle(paragraph,selector)
-    {
-        var wasHeading = isHeadingNode(paragraph);
-        DOM_removeAttribute(paragraph,"class");
-        if (selector == "") {
-            if (paragraph._type != HTML_P)
-                paragraph = DOM_replaceElement(paragraph,"P");
-        }
-        else {
-            var elementClassRegex = /^([a-zA-Z0-9]+)?(\.(.+))?$/;
-            var result = elementClassRegex.exec(selector);
-            if ((result != null) && (result.length == 4)) {
-                var elementName = result[1];
-                var className = result[3];
-
-                if (elementName == null)
-                    elementName = "P";
-                else
-                    elementName = elementName.toUpperCase();
-
-                var elementType = ElementTypes[elementName];
-
-                if (!PARAGRAPH_ELEMENTS[elementType])
-                    return; // better than throwing an exception
-
-                if (paragraph._type != elementType)
-                    paragraph = DOM_replaceElement(paragraph,elementName);
-
-                if (className != null)
-                    DOM_setAttribute(paragraph,"class",className);
-                else
-                    DOM_removeAttribute(paragraph,"class");
-            }
-        }
-
-        // FIXME: this will need to change when we add Word/ODF support, because the ids serve
-        // a purpose other than simply being targets for references
-        var isHeading = isHeadingNode(paragraph);
-        if (wasHeading && !isHeading)
-            DOM_removeAttribute(paragraph,"id");
-    }
-
-    // public
-    Formatting_pushDownInlineProperties = function(outermost)
-    {
-        for (var i = 0; i < outermost.length; i++)
-            outermost[i] = pushDownInlinePropertiesSingle(outermost[i]);
-    }
-
-    // private
-    function pushDownInlinePropertiesSingle(target)
-    {
-        recurse(target.parentNode);
-        return target;
-
-        function recurse(node)
-        {
-            if (node.nodeType == Node.DOCUMENT_NODE)
-                return;
-
-            if (node.parentNode != null)
-                recurse(node.parentNode);
-
-            var inlineProperties = new Object();
-            var nodeProperties = getStyleProperties(node);
-            for (var name in nodeProperties) {
-                if (isInlineProperty(name)) {
-                    inlineProperties[name] = nodeProperties[name];
-                }
-            }
-
-            var remove = new Object();
-            for (var name in inlineProperties)
-                remove[name] = null;
-            DOM_setStyleProperties(node,remove);
-
-            var type = node._type;
-            switch (type) {
-            case HTML_B:
-                inlineProperties["font-weight"] = "bold";
-                break;
-            case HTML_I:
-                inlineProperties["font-style"] = "italic";
-                break;
-            case HTML_U:
-                if (inlineProperties["text-decoration"] != null)
-                    inlineProperties["text-decoration"] += " underline";
-                else
-                    inlineProperties["text-decoration"] = "underline";
-                break;
-            }
-
-            var special = extractSpecial(inlineProperties);
-            var count = Object.getOwnPropertyNames(inlineProperties).length;
-
-            if ((count > 0) || special.bold || special.italic || special.underline) {
-
-                var next;
-                for (var child = node.firstChild; child != null; child = next) {
-                    next = child.nextSibling;
-
-                    if (isWhitespaceTextNode(child))
-                        continue;
-
-                    var replacement = applyInlineFormatting(child,inlineProperties,special);
-                    if (target == child)
-                        target = replacement;
-                }
-            }
-
-            if (node.hasAttribute("style") && (node.style.length == 0))
-                DOM_removeAttribute(node,"style");
-
-            switch (type) {
-            case HTML_B:
-            case HTML_I:
-            case HTML_U:
-                DOM_removeNodeButKeepChildren(node);
-                break;
-            }
-        }
-    }
-
-    // private
-    function wrapInline(node,elementName)
-    {
-        if (!isInlineNode(node) || isAbstractSpan(node)) {
-            var next;
-            for (var child = node.firstChild; child != null; child = next) {
-                next = child.nextSibling;
-                wrapInline(child,elementName);
-            }
-            return node;
-        }
-        else {
-            return DOM_wrapNode(node,elementName);
-        }
-    }
-
-    // private
-    function applyInlineFormatting(target,inlineProperties,special,applyToWhitespace)
-    {
-        if (!applyToWhitespace && isWhitespaceTextNode(target))
-            return;
-
-        if (special.underline)
-            target = wrapInline(target,"U");
-        if (special.italic)
-            target = wrapInline(target,"I");
-        if (special.bold)
-            target = wrapInline(target,"B");
-
-        var isbiu = false;
-        switch (target._type) {
-        case HTML_B:
-        case HTML_I:
-        case HTML_U:
-            isbiu = true;
-            break;
-        }
-
-        if ((Object.getOwnPropertyNames(inlineProperties).length > 0) &&
-            ((target.nodeType != Node.ELEMENT_NODE) ||
-             isbiu || isSpecialSpan(target))) {
-            target = wrapInline(target,"SPAN");
-        }
-
-
-        var propertiesToSet = new Object();
-        for (var name in inlineProperties) {
-            var existing = target.style.getPropertyValue(name);
-            if ((existing == null) || (existing == ""))
-                propertiesToSet[name] = inlineProperties[name];
-        }
-        DOM_setStyleProperties(target,propertiesToSet);
-
-        return target;
-    }
-
-    // private
-    function extractSpecial(properties)
-    {
-        var special = { bold: null, italic: null, underline: null };
-        var fontWeight = properties["font-weight"];
-        var fontStyle = properties["font-style"];
-        var textDecoration = properties["text-decoration"];
-
-        if (typeof(fontWeight) != "undefined") {
-            special.bold = false;
-            if ((fontWeight != null) &&
-                (fontWeight.toLowerCase() == "bold")) {
-                special.bold = true;
-                delete properties["font-weight"];
-            }
-        }
-
-        if (typeof(fontStyle) != "undefined") {
-            special.italic = false;
-            if ((fontStyle != null) &&
-                (fontStyle.toLowerCase() == "italic")) {
-                special.italic = true;
-                delete properties["font-style"];
-            }
-        }
-
-        if (typeof(textDecoration) != "undefined") {
-            special.underline = false;
-            if (textDecoration != null) {
-                var values = textDecoration.toLowerCase().split(/\s+/);
-                var index;
-                while ((index = values.indexOf("underline")) >= 0) {
-                    values.splice(index,1);
-                    special.underline = true;
-                }
-                if (values.length == 0)
-                    delete properties["text-decoration"];
-                else
-                    properties["text-decoration"] = values.join(" ");
-            }
-        }
-        return special;
-    }
-
-    // private
-    function removeProperties(outermost,properties)
-    {
-        properties = clone(properties);
-        var special = extractSpecial(properties);
-        var remaining = new Array();
-        for (var i = 0; i < outermost.length; i++) {
-            removePropertiesSingle(outermost[i],properties,special,remaining);
-        }
-        return remaining;
-    }
-
-    // private
-    function getOutermostParagraphs(paragraphs)
-    {
-        var all = new NodeSet();
-        for (var i = 0; i < paragraphs.length; i++)
-            all.add(paragraphs[i]);
-
-        var result = new Array();
-        for (var i = 0; i < paragraphs.length; i++) {
-            var haveAncestor = false;
-            for (var p = paragraphs[i].parentNode; p != null; p = p.parentNode) {
-                if (all.contains(p)) {
-                    haveAncestor = true;
-                    break;
-                }
-            }
-            if (!haveAncestor)
-                result.push(paragraphs[i]);
-        }
-        return result;
-    }
-
-    // private
-    function removePropertiesSingle(node,properties,special,remaining)
-    {
-        if ((node.nodeType == Node.ELEMENT_NODE) && (node.hasAttribute("style"))) {
-            var remove = new Object();
-            for (var name in properties)
-                remove[name] = null;
-            DOM_setStyleProperties(node,remove);
-        }
-
-        var willRemove = false;
-        switch (node._type) {
-        case HTML_B:
-            willRemove = (special.bold != null);
-            break;
-        case HTML_I:
-            willRemove = (special.italic != null);
-            break;
-        case HTML_U:
-            willRemove = (special.underline != null);
-            break;
-        case HTML_SPAN:
-            willRemove = (!node.hasAttribute("style") && !isSpecialSpan(node));
-            break;
-        }
-
-        var childRemaining = willRemove ? remaining : null;
-
-        var next;
-        for (var child = node.firstChild; child != null; child = next) {
-            next = child.nextSibling;
-            removePropertiesSingle(child,properties,special,childRemaining);
-        }
-
-        if (willRemove)
-            DOM_removeNodeButKeepChildren(node);
-        else if (remaining != null)
-            remaining.push(node);
-    }
-
-    function isSpecialSpan(span)
-    {
-        if (span._type == HTML_SPAN) {
-            if (span.hasAttribute(Keys.ABSTRACT_ELEMENT))
-                return true;
-            var className = DOM_getStringAttribute(span,"class");
-            if (className.indexOf(Keys.UXWRITE_PREFIX) == 0)
-                return true;
-            if ((className == "footnote") || (className == "endnote"))
-                return true;
-        }
-        return false;
-    }
-
-    // private
-    function containsOnlyWhitespace(ancestor)
-    {
-        for (child = ancestor.firstChild; child != null; child = child.nextSibling) {
-            if (!isWhitespaceTextNode(child))
-                return false;
-        }
-        return true;
-    }
-
-    // public
-    Formatting_applyFormattingChanges = function(style,properties)
-    {
-        debug("JS: applyFormattingChanges: style = "+JSON.stringify(style));
-        if (properties != null) {
-            var names = Object.getOwnPropertyNames(properties).sort();
-            for (var i = 0; i < names.length; i++) {
-                debug("    "+names[i]+" = "+properties[names[i]]);
-            }
-        }
-        UndoManager_newGroup("Apply formatting changes");
-
-        if (properties == null)
-            properties = new Object();
-
-        if (style == Keys.NONE_STYLE)
-            style = null;
-
-        var paragraphProperties = new Object();
-        var inlineProperties = new Object();
-
-        for (var name in properties) {
-            if (isParagraphProperty(name))
-                paragraphProperties[name] = properties[name];
-            else if (isInlineProperty(name))
-                inlineProperties[name] = properties[name];
-        }
-
-        var selectionRange = Selection_get();
-        if (selectionRange == null)
-            return;
-
-        // If we're applying formatting properties to an empty selection, and the node of the
-        // selection start & end is an element, add an empty text node so that we have something
-        // to apply the formatting to.
-        if (Range_isEmpty(selectionRange) &&
-            (selectionRange.start.node.nodeType == Node.ELEMENT_NODE)) {
-            var node = selectionRange.start.node;
-            var offset = selectionRange.start.offset;
-            var text = DOM_createTextNode(document,"");
-            DOM_insertBefore(node,text,node.childNodes[offset]);
-            Selection_set(text,0,text,0);
-            selectionRange = Selection_get();
-        }
-
-        // If the cursor is in a container (such as BODY OR FIGCAPTION), and not inside a paragraph,
-        // put it in one so we can set a paragraph style
-
-        if ((style != null) && Range_isEmpty(selectionRange)) {
-            var node = Range_singleNode(selectionRange);
-            while (isInlineNode(node))
-                node = node.parentNode;
-            if (isContainerNode(node) && containsOnlyInlineChildren(node)) {
-                var p = DOM_createElement(document,"P");
-                DOM_appendChild(node,p);
-                while (node.firstChild != p)
-                    DOM_appendChild(p,node.firstChild);
-                Cursor_updateBRAtEndOfParagraph(p);
-            }
-        }
-
-
-        var range = new Range(selectionRange.start.node,selectionRange.start.offset,
-                              selectionRange.end.node,selectionRange.end.offset);
-        var positions = [selectionRange.start,selectionRange.end,
-                         range.start,range.end];
-
-        var allowDirectInline = (style == null);
-        Position_trackWhileExecuting(positions,function() {
-            Formatting_splitAroundSelection(range,allowDirectInline);
-            Range_expand(range);
-            if (!allowDirectInline)
-                Range_ensureInlineNodesInParagraph(range);
-            Range_ensureValidHierarchy(range);
-            Range_expand(range);
-            var outermost = Range_getOutermostNodes(range);
-            var target = null;
-
-            var paragraphs;
-            if (outermost.length > 0)
-                paragraphs = getParagraphs(outermost);
-            else
-                paragraphs = getParagraphs([Range_singleNode(range)]);
-
-            // Push down inline properties
-            Formatting_pushDownInlineProperties(outermost);
-
-            outermost = removeProperties(outermost,inlineProperties);
-
-            // Set properties on inline nodes
-            for (var i = 0; i < outermost.length; i++) {
-                var existing = Formatting_getAllNodeProperties(outermost[i]);
-                var toSet = new Object();
-                for (var name in inlineProperties) {
-                    if ((inlineProperties[name] != null) &&
-                        (existing[name] != inlineProperties[name])) {
-                        toSet[name] = inlineProperties[name];
-                    }
-                }
-
-                var special = extractSpecial(toSet);
-                var applyToWhitespace = (outermost.length == 1);
-                applyInlineFormatting(outermost[i],toSet,special,applyToWhitespace);
-            }
-
-            // Remove properties from paragraph nodes
-            paragraphs = removeProperties(paragraphs,paragraphProperties,{});
-
-            // Set properties on paragraph nodes
-            var paragraphPropertiesToSet = new Object();
-            for (var name in paragraphProperties) {
-                if (paragraphProperties[name] != null)
-                    paragraphPropertiesToSet[name] = paragraphProperties[name];
-            }
-
-            var outermostParagraphs = getOutermostParagraphs(paragraphs);
-            for (var i = 0; i < outermostParagraphs.length; i++)
-                DOM_setStyleProperties(outermostParagraphs[i],paragraphPropertiesToSet);
-
-            // Set style on paragraph nodes
-            if (style != null) {
-                for (var i = 0; i < paragraphs.length; i++) {
-                    setParagraphStyle(paragraphs[i],style);
-                }
-            }
-
-            mergeRange(range,Formatting_MERGEABLE_INLINE);
-
-            if (target != null) {
-                for (var p = target; p != null; p = next) {
-                    next = p.parentNode;
-                    Formatting_mergeWithNeighbours(p,Formatting_MERGEABLE_INLINE);
-                }
-            }
-        });
-
-        // The current cursor position may no longer be valid, e.g. if a heading span was inserted
-        // and the cursor is at a position that is now immediately before the span.
-        var start = Position_closestMatchForwards(selectionRange.start,Position_okForInsertion);
-        var end = Position_closestMatchBackwards(selectionRange.end,Position_okForInsertion);
-        var tempRange = new Range(start.node,start.offset,end.node,end.offset);
-        tempRange = Range_forwards(tempRange);
-        Range_ensureValidHierarchy(tempRange);
-        start = tempRange.start;
-        end = tempRange.end;
-        Selection_set(start.node,start.offset,end.node,end.offset);
-
-        function containsOnlyInlineChildren(node)
-        {
-            for (var child = node.firstChild; child != null; child = child.nextSibling) {
-                if (!isInlineNode(child))
-                    return false;
-            }
-            return true;
-        }
-    }
-
-    Formatting_formatInlineNode = function(node,properties)
-    {
-        properties = clone(properties);
-        var special = extractSpecial(properties);
-        return applyInlineFormatting(node,properties,special,true);
-    }
-
-    Formatting_MERGEABLE_INLINE = new Array(HTML_COUNT);
-
-    Formatting_MERGEABLE_INLINE[HTML_TEXT] = true;
-
-    Formatting_MERGEABLE_INLINE[HTML_SPAN] = true;
-    Formatting_MERGEABLE_INLINE[HTML_A] = true;
-    Formatting_MERGEABLE_INLINE[HTML_Q] = true;
-
-    // HTML 4.01 Section 9.2.1: Phrase elements
-    Formatting_MERGEABLE_INLINE[HTML_EM] = true;
-    Formatting_MERGEABLE_INLINE[HTML_STRONG] = true;
-    Formatting_MERGEABLE_INLINE[HTML_DFN] = true;
-    Formatting_MERGEABLE_INLINE[HTML_CODE] = true;
-    Formatting_MERGEABLE_INLINE[HTML_SAMP] = true;
-    Formatting_MERGEABLE_INLINE[HTML_KBD] = true;
-    Formatting_MERGEABLE_INLINE[HTML_VAR] = true;
-    Formatting_MERGEABLE_INLINE[HTML_CITE] = true;
-    Formatting_MERGEABLE_INLINE[HTML_ABBR] = true;
-
-    // HTML 4.01 Section 9.2.3: Subscripts and superscripts
-    Formatting_MERGEABLE_INLINE[HTML_SUB] = true;
-    Formatting_MERGEABLE_INLINE[HTML_SUP] = true;
-
-    // HTML 4.01 Section 15.2.1: Font style elements
-    Formatting_MERGEABLE_INLINE[HTML_I] = true;
-    Formatting_MERGEABLE_INLINE[HTML_B] = true;
-    Formatting_MERGEABLE_INLINE[HTML_SMALL] = true;
-    Formatting_MERGEABLE_INLINE[HTML_S] = true;
-    Formatting_MERGEABLE_INLINE[HTML_U] = true;
-
-    Formatting_MERGEABLE_BLOCK = new Array(HTML_COUNT);
-
-    Formatting_MERGEABLE_BLOCK[HTML_P] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_H1] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_H2] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_H3] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_H4] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_H5] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_H6] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_DIV] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_PRE] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_BLOCKQUOTE] = true;
-
-    Formatting_MERGEABLE_BLOCK[HTML_UL] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_OL] = true;
-    Formatting_MERGEABLE_BLOCK[HTML_LI] = true;
-
-    Formatting_MERGEABLE_BLOCK_AND_INLINE = new Array(HTML_COUNT);
-    for (var i = 0; i < HTML_COUNT; i++) {
-        if (Formatting_MERGEABLE_INLINE[i] || Formatting_MERGEABLE_BLOCK[i])
-            Formatting_MERGEABLE_BLOCK_AND_INLINE[i] = true;
-        Formatting_MERGEABLE_BLOCK_AND_INLINE["force"] = true;
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js b/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js
deleted file mode 100644
index 07c0526..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Hierarchy.js
+++ /dev/null
@@ -1,284 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Hierarchy_ensureValidHierarchy;
-var Hierarchy_ensureInlineNodesInParagraph;
-var Hierarchy_wrapInlineNodesInParagraph;
-var Hierarchy_avoidInlineChildren;
-
-(function() {
-
-    // private
-    function wrapInlineChildren(first,last,ancestors)
-    {
-        var haveNonWhitespace = false;
-        for (var node = first; node != last.nextSibling; node = node.nextSibling) {
-            if (!isWhitespaceTextNode(node))
-                haveNonWhitespace = true;
-        }
-        if (!haveNonWhitespace)
-            return false;
-
-        var parentNode = first.parentNode;
-        var nextSibling = first;
-        for (var i = ancestors.length-1; i >= 0; i--) {
-            var ancestorCopy = DOM_shallowCopyElement(ancestors[i]);
-            DOM_insertBefore(parentNode,ancestorCopy,nextSibling);
-            parentNode = ancestorCopy;
-            nextSibling = null;
-
-            var node = first;
-            while (true) {
-                var next = node.nextSibling;
-                DOM_insertBefore(parentNode,node,null);
-                if (node == last)
-                    break;
-                node = next;
-            }
-        }
-    }
-
-    // private
-    function wrapInlineChildrenInAncestors(node,ancestors)
-    {
-        var firstInline = null;
-        var lastInline = null;
-
-        var child = node.firstChild;
-        while (true) {
-            var next = (child != null) ? child.nextSibling : null;
-            if ((child == null) || !isInlineNode(child)) {
-
-                if ((firstInline != null) && (lastInline != null)) {
-                    wrapInlineChildren(firstInline,lastInline,ancestors);
-                }
-                firstInline = null;
-                lastInline = null;
-                if (child != null)
-                    wrapInlineChildrenInAncestors(child,ancestors);
-            }
-            else {
-                if (firstInline == null)
-                    firstInline = child;
-                lastInline = child;
-            }
-            if (child == null)
-                break;
-            child = next;
-        }
-    }
-
-    function checkInvalidNesting(node)
-    {
-        var parent = node.parentNode;
-        if ((parent._type == HTML_DIV) &&
-            (DOM_getAttribute(parent,"class") == Keys.SELECTION_CLASS)) {
-            parent = parent.parentNode;
-        }
-
-        var invalidNesting = !isContainerNode(parent);
-        switch (parent._type) {
-        case HTML_DIV:
-            if (isParagraphNode(node) || isListNode(node))
-                invalidNesting = false; // this case is ok
-            break;
-        case HTML_CAPTION:
-        case HTML_FIGCAPTION:
-        case HTML_TABLE:
-        case HTML_FIGURE:
-            switch (node._type) {
-            case HTML_FIGURE:
-            case HTML_TABLE:
-            case HTML_H1:
-            case HTML_H2:
-            case HTML_H3:
-            case HTML_H4:
-            case HTML_H5:
-            case HTML_H6:
-                return true;
-            }
-            break;
-        }
-
-        return invalidNesting;
-    }
-
-    function checkInvalidHeadingNesting(node)
-    {
-        switch (node._type) {
-        case HTML_H1:
-        case HTML_H2:
-        case HTML_H3:
-        case HTML_H4:
-        case HTML_H5:
-        case HTML_H6:
-            switch (node.parentNode._type) {
-            case HTML_BODY:
-            case HTML_NAV:
-            case HTML_DIV:
-                return false;
-            default:
-                return true;
-            }
-            break;
-        default:
-            return false;
-        }
-    }
-
-    function nodeHasSignificantChildren(node)
-    {
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            if (!isWhitespaceTextNode(child))
-                return true;
-        }
-        return false;
-    }
-
-    // Enforce the restriction that any path from the root to a given node must be of the form
-    //    container+ paragraph inline
-    // or container+ paragraph
-    // or container+
-    // public
-    Hierarchy_ensureValidHierarchy = function(node,recursive,allowDirectInline)
-    {
-        var count = 0;
-        while ((node != null) && (node.parentNode != null) && (node != document.body)) {
-            count++;
-            if (count > 200)
-                throw new Error("too many iterations");
-
-            if (checkInvalidHeadingNesting(node)) {
-                var offset = DOM_nodeOffset(node);
-                var parent = node.parentNode;
-                Formatting_moveFollowing(new Position(node.parentNode,offset+1),
-                                         function() { return false; });
-                DOM_insertBefore(node.parentNode.parentNode,
-                                 node,
-                                 node.parentNode.nextSibling);
-
-                while ((parent != document.body) && !nodeHasSignificantChildren(parent)) {
-                    var grandParent = parent.parentNode;
-                    DOM_deleteNode(parent);
-                    parent = grandParent;
-                }
-
-                continue;
-            }
-            else if (isContainerNode(node) || isParagraphNode(node)) {
-                var invalidNesting = checkInvalidNesting(node);
-                if (invalidNesting) {
-                    var ancestors = new Array();
-                    var child = node;
-                    while (!isContainerNode(child.parentNode)) {
-                        if (isInlineNode(child.parentNode)) {
-                            var keep = false;
-                            if (child.parentNode._type == HTML_SPAN) {
-                                for (var i = 0; i < child.attributes.length; i++) {
-                                    var attr = child.attributes[i];
-                                    if (attr.nodeName.toUpperCase() != "ID")
-                                        keep = true;
-                                }
-                                if (keep)
-                                    ancestors.push(child.parentNode);
-                            }
-                            else {
-                                ancestors.push(child.parentNode);
-                            }
-                        }
-                        child = child.parentNode;
-                    }
-
-                    while (checkInvalidNesting(node)) {
-                        var offset = DOM_nodeOffset(node);
-                        var parent = node.parentNode;
-                        Formatting_moveFollowing(new Position(node.parentNode,offset+1),
-                                                 isContainerNode);
-                        DOM_insertBefore(node.parentNode.parentNode,
-                                         node,
-                                         node.parentNode.nextSibling);
-                        if (!nodeHasSignificantChildren(parent))
-                            DOM_deleteNode(parent);
-
-                    }
-                    wrapInlineChildrenInAncestors(node,ancestors);
-                }
-            }
-
-            node = node.parentNode;
-        }
-    }
-
-    Hierarchy_ensureInlineNodesInParagraph = function(node,weak)
-    {
-        var count = 0;
-        while ((node != null) && (node.parentNode != null) && (node != document.body)) {
-            count++;
-            if (count > 200)
-                throw new Error("too many iterations");
-            if (isInlineNode(node) &&
-                isContainerNode(node.parentNode) && (node.parentNode._type != HTML_LI) &&
-                (!weak || !isTableCell(node.parentNode)) &&
-                !isWhitespaceTextNode(node)) {
-                Hierarchy_wrapInlineNodesInParagraph(node);
-                return;
-            }
-            node = node.parentNode;
-        }
-    }
-
-    // public
-    Hierarchy_wrapInlineNodesInParagraph = function(node)
-    {
-        var start = node;
-        var end = node;
-
-        while ((start.previousSibling != null) && isInlineNode(start.previousSibling))
-            start = start.previousSibling;
-        while ((end.nextSibling != null) && isInlineNode(end.nextSibling))
-            end = end.nextSibling;
-
-        return DOM_wrapSiblings(start,end,"P");
-    }
-
-    Hierarchy_avoidInlineChildren = function(parent)
-    {
-        var child = parent.firstChild;
-
-        while (child != null) {
-            if (isInlineNode(child)) {
-                var start = child;
-                var end = child;
-                var haveContent = nodeHasContent(end);
-                while ((end.nextSibling != null) && isInlineNode(end.nextSibling)) {
-                    end = end.nextSibling;
-                    if (nodeHasContent(end))
-                        haveContent = true;
-                }
-                child = DOM_wrapSiblings(start,end,"P");
-                var next = child.nextSibling;
-                if (!nodeHasContent(child))
-                    DOM_deleteNode(child);
-                child = next;
-            }
-            else {
-                child = child.nextSibling;
-            }
-        }
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Input.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Input.js b/experiments/editorFramework/src/Layer0_Javascript/Input.js
deleted file mode 100644
index db8cb99..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Input.js
+++ /dev/null
@@ -1,746 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Input_removePosition;
-var Input_addPosition;
-var Input_getPosition;
-var Input_textInRange;
-var Input_replaceRange;
-var Input_selectedTextRange;
-var Input_setSelectedTextRange;
-var Input_markedTextRange;
-var Input_setMarkedText;
-var Input_unmarkText;
-var Input_forwardSelectionAffinity;
-var Input_setForwardSelectionAffinity;
-var Input_positionFromPositionOffset;
-var Input_positionFromPositionInDirectionOffset;
-var Input_comparePositionToPosition;
-var Input_offsetFromPositionToPosition;
-var Input_positionWithinRangeFarthestInDirection;
-var Input_characterRangeByExtendingPositionInDirection;
-var Input_firstRectForRange;
-var Input_caretRectForPosition;
-var Input_closestPositionToPoint;
-var Input_closestPositionToPointWithinRange;
-var Input_characterRangeAtPoint;
-var Input_positionWithinRangeAtCharacterOffset;
-var Input_characterOffsetOfPositionWithinRange;
-
-var Input_isAtWordBoundary;
-var Input_isAtParagraphBoundary;
-var Input_isPositionAtBoundaryGranularityInDirection;
-var Input_isPositionWithinTextUnitInDirection;
-var Input_toWordBoundary;
-var Input_toParagraphBoundary;
-var Input_toLineBoundary;
-var Input_positionFromPositionToBoundaryInDirection;
-var Input_rangeEnclosingPositionWithGranularityInDirection;
-
-// FIXME: ensure updateFormatting() is called after any cursor/selection changes
-// FIXME: test capitalisation of on-screen keyboard at start of sentence
-
-(function() {
-
-    //function idebug(str)
-    //{
-    //    debug(str);
-    //}
-
-    var forwardSelection = true;
-    var positions = new Object();
-    var BaseIdNull = 0;
-    var BaseIdDocumentStart = 1;
-    var BaseIdDocumentEnd = 2;
-    var BaseIdSelectionStart = 3;
-    var BaseIdSelectionEnd = 4;
-    var firstDynamicPosId = 5;
-    var nextPosId = firstDynamicPosId;
-
-    function addPosition(pos)
-    {
-        if (pos == null)
-            return 0;
-        var copy = new Position(pos.node,pos.offset);
-        copy.targetX = pos.targetX;
-        pos = copy;
-        pos.posId = nextPosId++;
-        positions[pos.posId] = pos;
-        Position_track(pos);
-        return pos.posId;
-    }
-
-    Input_addPosition = addPosition;
-
-    function getPosition(posId)
-    {
-        if (posId instanceof Position) // for tests
-            return posId;
-        if (posId < firstDynamicPosId) {
-            switch (posId) {
-            case BaseIdNull: {
-                return null;
-            }
-            case BaseIdDocumentStart: {
-                var pos = new Position(document.body,0);
-                pos = Position_closestMatchForwards(pos,Position_okForMovement);
-                return pos;
-            }
-            case BaseIdDocumentEnd: {
-                var pos = new Position(document.body,document.body.childNodes.length);
-                pos = Position_closestMatchBackwards(pos,Position_okForMovement);
-                return pos;
-            }
-            case BaseIdSelectionStart: {
-                var range = Selection_get();
-                return (range != null) ? range.start : null;
-            }
-            case BaseIdSelectionEnd: {
-                var range = Selection_get();
-                return (range != null) ? range.end : null;
-            }
-            default:
-                return null;
-            }
-        }
-        if (positions[posId] == null)
-            throw new Error("No position for pos id "+posId);
-        return positions[posId];
-    }
-
-    Input_getPosition = getPosition;
-
-    // void
-    Input_removePosition = function(posId)
-    {
-        //idebug("Input_removePosition("+posId+")");
-        var pos = positions[posId];
-        if (pos == null) {
-            throw new Error("no position for id "+posId);
-        }
-        Position_untrack(pos);
-        delete positions[posId];
-    }
-
-    // string
-    Input_textInRange = function(startId,startAdjust,endId,endAdjust)
-    {
-        var start = getPosition(startId);
-        var end = getPosition(endId);
-        start = positionRight(start,startAdjust);
-        end = positionRight(end,endAdjust);
-        if ((start == null) || (end == null))
-            return "";
-
-        var range = new Range(start.node,start.offset,end.node,end.offset);
-        var result = Range_getText(range);
-        //idebug("Input_textInRange("+startId+","+startAdjust+","+endId+","+endAdjust+") = "+
-        //       JSON.stringify(result));
-        return result;
-    }
-
-    // void
-    Input_replaceRange = function(startId,endId,text)
-    {
-        //idebug("Input_replaceRange("+startId+","+endId+","+JSON.stringify(text)+")");
-        var start = getPosition(startId);
-        var end = getPosition(endId);
-        if (start == null)
-            throw new Error("start is null");
-        if (end == null)
-            throw new Error("end is null");
-
-        var range = new Range(start.node,start.offset,end.node,end.offset);
-        Range_trackWhileExecuting(range,function() {
-            Selection_deleteRangeContents(range,true);
-        });
-        range.start = Position_preferTextPosition(range.start);
-        var node = range.start.node;
-        var offset = range.start.offset;
-
-        if (node.nodeType == Node.TEXT_NODE) {
-            DOM_insertCharacters(node,offset,text);
-            Cursor_set(node,offset+text.length);
-        }
-        else if (node.nodeType == Node.ELEMENT_NODE) {
-            var textNode = DOM_createTextNode(document,text);
-            DOM_insertBefore(node,textNode,node.childNodes[offset]);
-            Cursor_set(node,offset+1);
-        }
-    }
-
-    // { startId, endId }
-    Input_selectedTextRange = function()
-    {
-        var range = Selection_get();
-        if (range == null) {
-            //idebug("Input_selectedTextRange = null");
-            return null;
-        }
-        else {
-            var startId = addPosition(range.start);
-            var endId = addPosition(range.end);
-            //idebug("Input_selectedTextRange = "+startId+", "+endId);
-            return { startId: startId,
-                     endId: endId };
-        }
-    }
-
-    // void
-    Input_setSelectedTextRange = function(startId,endId)
-    {
-        //idebug("Input_setSelectedTextRange("+startId+","+endId+")");
-        var start = getPosition(startId);
-        var end = getPosition(endId);
-
-        var oldSelection = Selection_get();
-        var oldStart = (oldSelection != null) ? oldSelection.start : null;
-        var oldEnd = (oldSelection != null) ? oldSelection.end : null;
-
-        Selection_set(start.node,start.offset,end.node,end.offset);
-
-        // The positions may have changed as a result of spans being added/removed
-        var newRange = Selection_get();
-        start = newRange.start;
-        end = newRange.end;
-
-        if (Position_equal(start,end))
-            Cursor_ensurePositionVisible(end);
-        else if (Position_equal(oldStart,start) && !Position_equal(oldEnd,end))
-            Cursor_ensurePositionVisible(end);
-        else if (Position_equal(oldEnd,end) && !Position_equal(oldStart,start))
-            Cursor_ensurePositionVisible(start);
-    }
-
-    // { startId, endId }
-    Input_markedTextRange = function()
-    {
-        //idebug("Input_markedTextRange");
-        return null;
-    }
-
-    // void
-    Input_setMarkedText = function(text,startOffset,endOffset)
-    {
-        Selection_deleteContents(true);
-        var oldSel = Selection_get();
-        Range_trackWhileExecuting(oldSel,function() {
-            Cursor_insertCharacter(text,false,false,true);
-        });
-        var newSel = Selection_get();
-
-        Selection_set(oldSel.start.node,oldSel.start.offset,
-                      newSel.end.node,newSel.end.offset,false,true);
-    }
-
-    // void
-    Input_unmarkText = function()
-    {
-        var range = Selection_get();
-        Cursor_set(range.end.node,range.end.offset);
-        //idebug("Input_unmarkText");
-    }
-
-    // boolean
-    Input_forwardSelectionAffinity = function()
-    {
-        //idebug("Input_forwardSelectionAffinity");
-        return forwardSelection;
-    }
-
-    // void
-    Input_setForwardSelectionAffinity = function(value)
-    {
-        //idebug("Input_setForwardSelectionAffinity");
-        forwardSelection = value;
-    }
-
-    function positionRight(pos,offset)
-    {
-        if (offset > 0) {
-            for (; offset > 0; offset--) {
-                var next = Position_nextMatch(pos,Position_okForMovement);
-                if (next == null)
-                    return pos;
-                pos = next;
-            }
-        }
-        else {
-            for (; offset < 0; offset++) {
-                var prev = Position_prevMatch(pos,Position_okForMovement);
-                if (prev == null)
-                    return pos;
-                pos = prev;
-            }
-        }
-        return pos;
-    }
-
-    function positionDown(pos,offset)
-    {
-        if (offset > 0) {
-            for (; offset > 0; offset--) {
-                var below = Text_posBelow(pos);
-                if (below == null)
-                    return pos;
-                pos = below;
-            }
-        }
-        else {
-            for (; offset < 0; offset++) {
-                var above = Text_posAbove(pos);
-                if (above == null)
-                    return pos;
-                pos = above;
-            }
-        }
-        return pos;
-    }
-
-    // posId
-    Input_positionFromPositionOffset = function(posId,offset)
-    {
-        var pos = getPosition(posId);
-        var res = addPosition(positionRight(pos,offset));
-        //idebug("Input_positionFromPositionOffset("+posId+","+offset+") = "+res);
-        return res;
-    }
-
-    // posId
-    Input_positionFromPositionInDirectionOffset = function(posId,direction,offset)
-    {
-        //idebug("Input_positionFromPositionInDirectionOffset("+posId+","+direction+","+offset+")");
-        var pos = getPosition(posId);
-        if (direction == "left")
-            return addPosition(positionRight(pos,-offset));
-        else if (direction == "right")
-            return addPosition(positionRight(pos,offset));
-        else if (direction == "up")
-            return addPosition(positionDown(pos,-offset));
-        else if (direction == "down")
-            return addPosition(positionDown(pos,offset));
-        else
-            throw new Error("unknown direction: "+direction);
-    }
-
-    // int
-    Input_comparePositionToPosition = function(posId1,posId2)
-    {
-        //idebug("Input_comparePositionToPosition("+posId1+","+posId2+")");
-        var pos1 = getPosition(posId1);
-        var pos2 = getPosition(posId2);
-        if (pos1 == null)
-            throw new Error("pos1 is null");
-        if (pos2 == null)
-            throw new Error("pos2 is null");
-        return Position_compare(pos1,pos2);
-    }
-
-    // int
-    Input_offsetFromPositionToPosition = function(fromId,toId)
-    {
-        //idebug("Input_offsetFromPositionToPosition("+fromId+","+toId+")");
-        throw new Error("offsetFromPositionToPosition: not implemented");
-    }
-
-    Input_positionWithinRangeFarthestInDirection = function(startId,endId,direction)
-    {
-        //idebug("Input_positionWithinRangeFarthestInDirection("+startId+","+endId+","+direction);
-        throw new Error("positionWithinRangeFarthestInDirection: not implemented");
-    }
-
-    // { startId, endId }
-    Input_characterRangeByExtendingPositionInDirection = function(posId,direction)
-    {
-        //idebug("Input_characterRangeByExtendingPositionInDirection("+posId+","+direction);
-        throw new Error("characterRangeByExtendingPositionInDirection: not implemented");
-    }
-
-    Input_firstRectForRange = function(startId,endId)
-    {
-        //idebug("Input_firstRectForRange("+startId+","+endId+")");
-        var start = getPosition(startId);
-        var end = getPosition(endId);
-        var range = new Range(start.node,start.offset,end.node,end.offset);
-        var rects = Range_getClientRects(range);
-        if (rects.length == 0)
-            return { x: 0, y: 0, width: 0, height: 0 };
-        else
-            return { x: rects[0].left, y: rects[0].top,
-                     width: rects[0].width, height: rects[0].height };
-    }
-
-    Input_caretRectForPosition = function(posId)
-    {
-        //idebug("Input_caretRectForPosition("+posId+")");
-        var pos = getPosition(posId);
-        var rect = Position_rectAtPos(pos);
-        if (rect == null)
-            return { x: 0, y: 0, width: 0, height: 0 };
-        else
-            return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
-    }
-
-    // posId
-    Input_closestPositionToPoint = function(x,y)
-    {
-        //idebug("Input_closestPositionToPoint("+x+","+y+")");
-        throw new Error("closestPositionToPoint: not implemented");
-    }
-
-    // posId
-    Input_closestPositionToPointWithinRange = function(x,y,startId,endId)
-    {
-        //idebug("Input_closestPositionToPointWithinRange("+x+","+y+")");
-        throw new Error("closestPositionToPointWithinRange: not implemented");
-    }
-
-    // { startId, endId }
-    Input_characterRangeAtPoint = function(x,y)
-    {
-        //idebug("Input_characterRangeAtPoint("+x+","+y+")");
-        throw new Error("characterRangeAtPoint: not implemented");
-    }
-
-    // posId
-    Input_positionWithinRangeAtCharacterOffset = function(startId,endId,offset)
-    {
-        //idebug("Input_positionWithinRangeAtCharacterOffset("+startId+","+endId+","+offset+")");
-        throw new Error("positionWithinRangeAtCharacterOffset: not implemented");
-    }
-
-    // int
-    Input_characterOffsetOfPositionWithinRange = function(posId,startId,endId)
-    {
-        //idebug("Input_characterOffsetOfPositionWithinRange("+posId+","+startId+","+endId+")");
-        throw new Error("characterOffsetOfPositionWithinRange: not implemented");
-    }
-
-    // UITextInputTokenizer methods
-
-    var punctuation = "!\"#%&',-/:;<=>@`~\\^\\$\\\\\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|";
-    var letterRE = new RegExp("[^\\s"+punctuation+"]");
-    var wordAtStartRE = new RegExp("^[^\\s"+punctuation+"]+");
-    var nonWordAtStartRE = new RegExp("^[\\s"+punctuation+"]+");
-    var wordAtEndRE = new RegExp("[^\\s"+punctuation+"]+$");
-    var nonWordAtEndRE = new RegExp("[\\s"+punctuation+"]+$");
-
-    function isForward(direction)
-    {
-        return ((direction == "forward") ||
-                (direction == "right") ||
-                (direction == "down"));
-    }
-
-    Input_isAtWordBoundary = function(pos,direction)
-    {
-        if (pos.node.nodeType != Node.TEXT_NODE)
-            return false;
-        var paragraph = Text_analyseParagraph(pos);
-        if (paragraph == null)
-            return false;
-        var offset = Paragraph_offsetAtPosition(paragraph,pos);
-        var before = paragraph.text.substring(0,offset);
-        var after = paragraph.text.substring(offset);
-        var text = paragraph.text;
-
-        var afterMatch = (offset < text.length) && (text.charAt(offset).match(letterRE));
-        var beforeMatch = (offset > 0) && (text.charAt(offset-1).match(letterRE));
-
-        // coerce to boolean
-        afterMatch = !!afterMatch;
-        beforeMatch = !!beforeMatch;
-
-        if (isForward(direction))
-            return beforeMatch && !afterMatch;
-        else
-            return !beforeMatch;
-    }
-
-    Input_isAtParagraphBoundary = function(pos,direction)
-    {
-    }
-
-    Input_isPositionAtBoundaryGranularityInDirection = function(posId,granularity,direction)
-    {
-        //idebug("Input_isPositionAtBoundaryGranularityInDirection("+
-        //       posId+","+granularity+","+direction+")");
-        var pos = getPosition(posId);
-        if (pos == null)
-            return false;
-
-        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
-        if ((granularity == "sentence") || (granularity == "document"))
-            return false;
-
-        if (granularity == "character") {
-            return true;
-        }
-        else if (granularity == "word") {
-            return Input_isAtWordBoundary(pos,direction);
-        }
-        else if ((granularity == "paragraph") || (granularity == "line")) {
-            if (isForward(direction))
-                return Position_equal(pos,Text_toEndOfBoundary(pos,granularity));
-            else
-                return Position_equal(pos,Text_toStartOfBoundary(pos,granularity));
-        }
-        else if (granularity == "sentence") {
-        }
-        else if (granularity == "document") {
-        }
-        throw new Error("unsupported granularity: "+granularity);
-    }
-
-    Input_isPositionWithinTextUnitInDirection = function(posId,granularity,direction)
-    {
-        //idebug("Input_isPositionWithinTextUnitInDirection("+
-        //       posId+","+granularity+","+direction+")");
-        var pos = getPosition(posId);
-        if (pos == null)
-            return false;
-
-        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
-        if ((granularity == "sentence") || (granularity == "document"))
-            return true;
-
-        if (granularity == "character") {
-            return true;
-        }
-        else if (granularity == "word") {
-            pos = Text_closestPosInDirection(pos,direction);
-            if (pos == null)
-                return false;
-            var paragraph = Text_analyseParagraph(pos);
-            if (paragraph == null)
-                return false;
-            if ((pos != null) && (pos.node.nodeType == Node.TEXT_NODE)) {
-                var offset = Paragraph_offsetAtPosition(paragraph,pos);
-                var text = paragraph.text;
-                if (isForward(direction))
-                    return !!((offset < text.length) && (text.charAt(offset).match(letterRE)));
-                else
-                    return !!((offset > 0) && (text.charAt(offset-1).match(letterRE)));
-            }
-            else {
-                return false;
-            }
-        }
-        else if (granularity == "sentence") {
-        }
-        else if ((granularity == "paragraph") || (granularity == "line")) {
-            var start = Text_toStartOfBoundary(pos,granularity);
-            var end = Text_toEndOfBoundary(pos,granularity);
-            start = start ? start : pos;
-            end = end ? end : pos;
-            if (isForward(direction)) {
-                return ((Position_compare(start,pos) <= 0) &&
-                        (Position_compare(pos,end) < 0));
-            }
-            else {
-                return ((Position_compare(start,pos) < 0) &&
-                        (Position_compare(pos,end) <= 0));
-            }
-        }
-        else if (granularity == "document") {
-        }
-        throw new Error("unsupported granularity: "+granularity);
-    }
-
-    Input_toWordBoundary = function(pos,direction)
-    {
-        pos = Text_closestPosInDirection(pos,direction);
-        if (pos == null)
-            return null;
-        var paragraph = Text_analyseParagraph(pos);
-        if (paragraph == null)
-            return null;
-        var run = Paragraph_runFromNode(paragraph,pos.node);
-        var offset = pos.offset + run.start;
-
-        if (isForward(direction)) {
-            var remaining = paragraph.text.substring(offset);
-            var afterWord = remaining.replace(wordAtStartRE,"");
-            var afterNonWord = remaining.replace(nonWordAtStartRE,"");
-
-            if (remaining.length == 0) {
-                return pos;
-            }
-            else if (afterWord.length < remaining.length) {
-                var newOffset = offset + (remaining.length - afterWord.length);
-                return Paragraph_positionAtOffset(paragraph,newOffset);
-            }
-            else {
-                var newOffset = offset + (remaining.length - afterNonWord.length);
-                return Paragraph_positionAtOffset(paragraph,newOffset);
-            }
-        }
-        else {
-            var remaining = paragraph.text.substring(0,offset);
-            var beforeWord = remaining.replace(wordAtEndRE,"");
-            var beforeNonWord = remaining.replace(nonWordAtEndRE,"");
-
-            if (remaining.length == 0) {
-                return pos;
-            }
-            else if (beforeWord.length < remaining.length) {
-                var newOffset = offset - (remaining.length - beforeWord.length);
-                return Paragraph_positionAtOffset(paragraph,newOffset);
-            }
-            else {
-                var newOffset = offset - (remaining.length - beforeNonWord.length);
-                return Paragraph_positionAtOffset(paragraph,newOffset);
-            }
-        }
-    }
-
-    Input_toParagraphBoundary = function(pos,direction)
-    {
-        if (isForward(direction)) {
-            var end = Text_toEndOfBoundary(pos,"paragraph");
-            if (Position_equal(pos,end)) {
-                end = Position_nextMatch(end,Position_okForMovement);
-                end = Text_toEndOfBoundary(end,"paragraph");
-                end = Text_toStartOfBoundary(end,"paragraph");
-            }
-            return end ? end : pos;
-        }
-        else {
-            var start = Text_toStartOfBoundary(pos,"paragraph");
-            if (Position_equal(pos,start)) {
-                start = Position_prevMatch(start,Position_okForMovement);
-                start = Text_toStartOfBoundary(start,"paragraph");
-                start = Text_toEndOfBoundary(start,"paragraph");
-            }
-            return start ? start : pos;
-        }
-    }
-
-    Input_toLineBoundary = function(pos,direction)
-    {
-        if (isForward(direction)) {
-            var end = Text_toEndOfBoundary(pos,"line");
-            return end ? end : pos;
-        }
-        else {
-            var start = Text_toStartOfBoundary(pos,"line");
-            return start ? start : pos;
-        }
-    }
-
-    Input_positionFromPositionToBoundaryInDirection = function(posId,granularity,direction)
-    {
-        //idebug("Input_positionFromPositionToBoundaryInDirection("+
-        //       posId+","+granularity+","+direction+")");
-        var pos = getPosition(posId);
-        if (pos == null)
-            return null;
-
-        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
-        if (granularity == "sentence")
-            granularity = "paragraph";
-
-        if (granularity == "word")
-            return addPosition(Input_toWordBoundary(pos,direction));
-        else if (granularity == "paragraph")
-            return addPosition(Input_toParagraphBoundary(pos,direction));
-        else if (granularity == "line")
-            return addPosition(Input_toLineBoundary(pos,direction));
-        else if (granularity == "character")
-            return Input_positionFromPositionInDirectionOffset(posId,direction,1);
-        else if (granularity == "document")
-            return isForward(direction) ? BaseIdDocumentEnd : BaseIdDocumentStart;
-        else
-            throw new Error("unsupported granularity: "+granularity);
-    }
-
-    Input_rangeEnclosingPositionWithGranularityInDirection = function(posId,granularity,direction)
-    {
-        //idebug("Input_rangeEnclosingPositionWithGranularityInDirection("+
-        //       posId+","+granularity+","+direction);
-        var pos = getPosition(posId);
-        if (pos == null)
-            return null;
-
-        // FIXME: Temporary hack to avoid exceptions when running under iOS 8
-        if (granularity == "sentence")
-            granularity = "paragraph";
-
-        if (granularity == "word") {
-            pos = Text_closestPosInDirection(pos,direction);
-            if (pos == null)
-                return null;
-            var paragraph = Text_analyseParagraph(pos);
-            if (pos == null)
-                return addPosition(null);
-            if (paragraph == null)
-                return addPosition(null);
-            var run = Paragraph_runFromNode(paragraph,pos.node);
-            var offset = pos.offset + run.start;
-
-            var before = paragraph.text.substring(0,offset);
-            var after = paragraph.text.substring(offset);
-            var beforeWord = before.replace(wordAtEndRE,"");
-            var afterWord = after.replace(wordAtStartRE,"");
-
-            var ok;
-
-            if (isForward(direction))
-                ok = (afterWord.length < after.length);
-            else
-                ok = (beforeWord.length < before.length);
-
-            if (ok) {
-                var charsBefore = (before.length - beforeWord.length);
-                var charsAfter = (after.length - afterWord.length);
-                var startOffset = offset - charsBefore;
-                var endOffset = offset + charsAfter;
-
-                var startPos = Paragraph_positionAtOffset(paragraph,startOffset);
-                var endPos = Paragraph_positionAtOffset(paragraph,endOffset);
-                return { startId: addPosition(startPos),
-                         endId: addPosition(endPos) };
-            }
-            else {
-                return null;
-            }
-        }
-        else if ((granularity == "paragraph") || (granularity == "line")) {
-            var start = Text_toStartOfBoundary(pos,granularity);
-            var end = Text_toEndOfBoundary(pos,granularity);
-            start = start ? start : pos;
-            end = end ? end : pos;
-
-            if ((granularity == "paragraph") || !isForward(direction)) {
-                if (isForward(direction)) {
-                    if (Position_equal(pos,Text_toEndOfBoundary(pos,granularity)))
-                        return null;
-                }
-                else {
-                    if (Position_equal(pos,Text_toStartOfBoundary(pos,granularity)))
-                        return null;
-                }
-            }
-            return { startId: addPosition(start),
-                     endId: addPosition(end) };
-        }
-        else {
-            throw new Error("unsupported granularity: "+granularity);
-        }
-    }
-
-})();


[05/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/dtdsource/gen_dtd_data.html
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/gen_dtd_data.html b/experiments/editorFramework/src/Layer0_Javascript/dtdsource/gen_dtd_data.html
deleted file mode 100644
index ac09ad2..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/gen_dtd_data.html
+++ /dev/null
@@ -1,247 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title></title>
-<script src="../DOM_js"></script>
-<script>
-
-function ElementDeclaration(name)
-{
-    this.name = name;
-    this.allowedChildren = new Object();
-}
-
-ElementDeclaration.prototype.addAllowedChild = function(name)
-{
-    this.allowedChildren[name] = true;
-}
-
-ElementDeclaration.prototype.removeAllowedChild = function(name)
-{
-    delete this.allowedChildren[name];
-}
-
-ElementDeclaration.prototype.print = function()
-{
-    for (var childName in this.allowedChildren)
-        println(this.name+" -> "+childName);
-}
-
-ElementDeclaration.prototype.printAllowedChildren = function()
-{
-    println("    \""+this.name+"\": {");
-    for (var childName in this.allowedChildren)
-        println("        \""+childName+"\": true,");
-    println("    },");
-}
-
-ElementDeclaration.prototype.setAllowedParents = function(allowedParents)
-{
-    for (var childName in this.allowedChildren) {
-        if (allowedParents[childName] == null)
-            allowedParents[childName] = new Object();
-        allowedParents[childName][this.name] = true;
-    }
-}
-
-function debug(str)
-{
-    console.log(str);
-}
-
-function println(str)
-{
-    var text = DOM_createTextNode(document,str+"\n");
-    var output = document.getElementById("output");
-    DOM_appendChild(output,text);
-}
-
-function readFile(filename)
-{
-    var req = new XMLHttpRequest();
-    req.open("GET",filename,false);
-    req.send();
-    return req.responseXML;
-}
-
-function printTree(node,indent)
-{
-    if (indent == null)
-        indent = "";
-    println(indent+node);
-    for (var child = node.firstChild; child != null; child = child.nextSibling)
-        printTree(child,indent+"    ");
-}
-
-function parseOrGroup(decl,element)
-{
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "element-name") {
-            decl.addAllowedChild(child.getAttribute("name"));
-        }
-        else if (child.nodeName == "pcdata") {
-        }
-        else if (child.nodeName == "or-group") {
-            parseOrGroup(decl,child);
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-}
-
-function parseSequenceGroup(decl,element)
-{
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "element-name") {
-            decl.addAllowedChild(child.getAttribute("name"));
-        }
-        else if (child.nodeName == "or-group") {
-            parseOrGroup(decl,child);
-        }
-        else if (child.nodeName == "pcdata") {
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-}
-
-function parseContentModelExpanded(decl,element)
-{
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "or-group") {
-            parseOrGroup(decl,child);
-        }
-        else if (child.nodeName == "and-group") {
-            parseOrGroup(decl,child);
-        }
-        else if (child.nodeName == "sequence-group") {
-            parseSequenceGroup(decl,child);
-        }
-        else if (child.nodeName == "empty") {
-        }
-        else if (child.nodeName == "cdata") {
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-}
-
-function parseInclusions(decl,element)
-{
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "or-group") {
-            parseOrGroup(decl,child);
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-}
-
-function parseOrGroupExclusions(decl,element)
-{
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "element-name") {
-            decl.removeAllowedChild(child.getAttribute("name"));
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-}
-
-function parseSequenceGroupExclusions(decl,element)
-{
-    parseOrGroupExclusions(decl,element);
-}
-
-function parseExclusions(decl,element)
-{
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "or-group") {
-            parseOrGroupExclusions(decl,child);
-        }
-        else if (child.nodeName == "sequence-group") {
-            parseSequenceGroupExclusions(decl,child);
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-}
-
-function parseElement(element)
-{
-    var decl = new ElementDeclaration(element.getAttribute("name"));
-
-    for (var child = element.firstChild; child != null; child = child.nextSibling) {
-        if (child.nodeName == "content-model-expanded") {
-            parseContentModelExpanded(decl,child);
-        }
-        else if (child.nodeName == "inclusions") {
-            parseInclusions(decl,child);
-        }
-        else if (child.nodeName == "exclusions") {
-            parseExclusions(decl,child);
-        }
-        else if (child.nodeName == "content-model") {
-        }
-        else if (child.nodeType == Node.ELEMENT_NODE) {
-            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
-        }
-    }
-
-//    decl.println();
-    return decl;
-}
-
-function loaded()
-{
-    var dtd = readFile("html4.xml");
-//    printTree(dtd);
-
-    var decls = new Array();
-    for (var node = dtd.documentElement.firstChild; node != null; node = node.nextSibling) {
-        if (node.nodeName == "element") {
-            decls.push(parseElement(node));
-        }
-    }
-
-    println("// Automatically generated from HTML 4.01 dtd using dtdparse and gen_dtd_data.html");
-    println("// See http://nwalsh.com/perl/dtdparse/");
-    println("");
-
-    println("var ALLOWED_CHILDREN = {");
-    for (var i = 0; i < decls.length; i++) {
-        decls[i].printAllowedChildren();
-    }
-    println("};");
-
-    println("");
-
-    var allowedParents = new Object();
-    for (var i = 0; i < decls.length; i++) {
-        decls[i].setAllowedParents(allowedParents);
-    }
-
-    println("var ALLOWED_PARENTS = {");
-    for (var childName in allowedParents) {
-        println("    \""+childName+"\": {");
-        for (var parentName in allowedParents[childName]) {
-            println("        \""+parentName+"\": true,");
-        }
-        println("    },");
-    }
-    println("};");
-
-}
-</script>
-</head>
-
-<body onload="loaded()">
-<pre id="output">
-</pre>
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.dtd
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.dtd b/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.dtd
deleted file mode 100644
index c5752ed..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/dtdsource/html4.dtd
+++ /dev/null
@@ -1,1078 +0,0 @@
-<!--
-    This is the HTML 4.01 Transitional DTD, which includes
-    presentation attributes and elements that W3C expects to phase out
-    as support for style sheets matures. Authors should use the Strict
-    DTD when possible, but may use the Transitional DTD when support
-    for presentation attribute and elements is required.
-
-    HTML 4 includes mechanisms for style sheets, scripting,
-    embedding objects, improved support for right to left and mixed
-    direction text, and enhancements to forms for improved
-    accessibility for people with disabilities.
-
-          Draft: $Date: 1999/12/24 23:37:50 $
-
-          Authors:
-              Dave Raggett <ds...@w3.org>
-              Arnaud Le Hors <le...@w3.org>
-              Ian Jacobs <ij...@w3.org>
-
-    Further information about HTML 4.01 is available at:
-
-        http://www.w3.org/TR/1999/REC-html401-19991224
-
-
-    The HTML 4.01 specification includes additional
-    syntactic constraints that cannot be expressed within
-    the DTDs.
-
--->
-<!ENTITY % HTML.Version "-//W3C//DTD HTML 4.01 Transitional//EN"
-  -- Typical usage:
-
-    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-            "http://www.w3.org/TR/html4/loose.dtd">
-    <html>
-    <head>
-    ...
-    </head>
-    <body>
-    ...
-    </body>
-    </html>
-
-    The URI used as a system identifier with the public identifier allows
-    the user agent to download the DTD and entity sets as needed.
-
-    The FPI for the Strict HTML 4.01 DTD is:
-
-        "-//W3C//DTD HTML 4.01//EN"
-
-    This version of the strict DTD is:
-
-        http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd
-
-    Authors should use the Strict DTD unless they need the
-    presentation control for user agents that don't (adequately)
-    support style sheets.
-
-    If you are writing a document that includes frames, use 
-    the following FPI:
-
-        "-//W3C//DTD HTML 4.01 Frameset//EN"
-
-    This version of the frameset DTD is:
-
-        http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd
-
-    Use the following (relative) URIs to refer to 
-    the DTDs and entity definitions of this specification:
-
-    "strict.dtd"
-    "loose.dtd"
-    "frameset.dtd"
-    "HTMLlat1.ent"
-    "HTMLsymbol.ent"
-    "HTMLspecial.ent"
-
--->
-
-<!--================== Imported Names ====================================-->
-<!-- Feature Switch for frameset documents -->
-<!ENTITY % HTML.Frameset "IGNORE">
-
-<!ENTITY % ContentType "CDATA"
-    -- media type, as per [RFC2045]
-    -->
-
-<!ENTITY % ContentTypes "CDATA"
-    -- comma-separated list of media types, as per [RFC2045]
-    -->
-
-<!ENTITY % Charset "CDATA"
-    -- a character encoding, as per [RFC2045]
-    -->
-
-<!ENTITY % Charsets "CDATA"
-    -- a space-separated list of character encodings, as per [RFC2045]
-    -->
-
-<!ENTITY % LanguageCode "NAME"
-    -- a language code, as per [RFC1766]
-    -->
-
-<!ENTITY % Character "CDATA"
-    -- a single character from [ISO10646] 
-    -->
-
-<!ENTITY % LinkTypes "CDATA"
-    -- space-separated list of link types
-    -->
-
-<!ENTITY % MediaDesc "CDATA"
-    -- single or comma-separated list of media descriptors
-    -->
-
-<!ENTITY % URI "CDATA"
-    -- a Uniform Resource Identifier,
-       see [URI]
-    -->
-
-<!ENTITY % Datetime "CDATA" -- date and time information. ISO date format -->
-
-
-<!ENTITY % Script "CDATA" -- script expression -->
-
-<!ENTITY % StyleSheet "CDATA" -- style sheet data -->
-
-<!ENTITY % FrameTarget "CDATA" -- render in this frame -->
-
-
-<!ENTITY % Text "CDATA">
-
-
-<!-- Parameter Entities -->
-
-<!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT" -- repeatable head elements -->
-
-<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
-
-<!ENTITY % list "UL | OL |  DIR | MENU">
-
-<!ENTITY % preformatted "PRE">
-
-<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
-
-<!-- There are also 16 widely known color names with their sRGB values:
-
-    Black  = #000000    Green  = #008000
-    Silver = #C0C0C0    Lime   = #00FF00
-    Gray   = #808080    Olive  = #808000
-    White  = #FFFFFF    Yellow = #FFFF00
-    Maroon = #800000    Navy   = #000080
-    Red    = #FF0000    Blue   = #0000FF
-    Purple = #800080    Teal   = #008080
-    Fuchsia= #FF00FF    Aqua   = #00FFFF
- -->
-
-<!ENTITY % bodycolors "
-  bgcolor     %Color;        #IMPLIED  -- document background color --
-  text        %Color;        #IMPLIED  -- document text color --
-  link        %Color;        #IMPLIED  -- color of links --
-  vlink       %Color;        #IMPLIED  -- color of visited links --
-  alink       %Color;        #IMPLIED  -- color of selected links --
-  ">
-
-<!--=================== Generic Attributes ===============================-->
-
-<!ENTITY % coreattrs
- "id          ID             #IMPLIED  -- document-wide unique id --
-  class       CDATA          #IMPLIED  -- space-separated list of classes --
-  style       %StyleSheet;   #IMPLIED  -- associated style info --
-  title       %Text;         #IMPLIED  -- advisory title --"
-  >
-
-<!ENTITY % i18n
- "lang        %LanguageCode; #IMPLIED  -- language code --
-  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --"
-  >
-
-<!ENTITY % events
- "onclick     %Script;       #IMPLIED  -- a pointer button was clicked --
-  ondblclick  %Script;       #IMPLIED  -- a pointer button was double clicked--
-  onmousedown %Script;       #IMPLIED  -- a pointer button was pressed down --
-  onmouseup   %Script;       #IMPLIED  -- a pointer button was released --
-  onmouseover %Script;       #IMPLIED  -- a pointer was moved onto --
-  onmousemove %Script;       #IMPLIED  -- a pointer was moved within --
-  onmouseout  %Script;       #IMPLIED  -- a pointer was moved away --
-  onkeypress  %Script;       #IMPLIED  -- a key was pressed and released --
-  onkeydown   %Script;       #IMPLIED  -- a key was pressed down --
-  onkeyup     %Script;       #IMPLIED  -- a key was released --"
-  >
-
-<!-- Reserved Feature Switch -->
-<!ENTITY % HTML.Reserved "IGNORE">
-
-<!-- The following attributes are reserved for possible future use -->
-<![ %HTML.Reserved; [
-<!ENTITY % reserved
- "datasrc     %URI;          #IMPLIED  -- a single or tabular Data Source --
-  datafld     CDATA          #IMPLIED  -- the property or column name --
-  dataformatas (plaintext|html) plaintext -- text or html --"
-  >
-]]>
-
-<!ENTITY % reserved "">
-
-<!ENTITY % attrs "%coreattrs; %i18n; %events;">
-
-<!ENTITY % align "align (left|center|right|justify)  #IMPLIED"
-                   -- default is left for ltr paragraphs, right for rtl --
-  >
-
-<!--=================== Text Markup ======================================-->
-
-<!ENTITY % fontstyle
- "TT | I | B | U | S | STRIKE | BIG | SMALL">
-
-<!ENTITY % phrase "EM | STRONG | DFN | CODE |
-                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >
-
-<!ENTITY % special
-   "A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
-    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME">
-
-<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">
-
-<!-- %inline; covers inline or "text-level" elements -->
-<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">
-
-<!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)*>
-<!ATTLIST (%fontstyle;|%phrase;)
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!ELEMENT (SUB|SUP) - - (%inline;)*    -- subscript, superscript -->
-<!ATTLIST (SUB|SUP)
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!ELEMENT SPAN - - (%inline;)*         -- generic language/style container -->
-<!ATTLIST SPAN
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %reserved;                   -- reserved for possible future use --
-  >
-
-<!ELEMENT BDO - - (%inline;)*          -- I18N BiDi over-ride -->
-<!ATTLIST BDO
-  %coreattrs;                          -- id, class, style, title --
-  lang        %LanguageCode; #IMPLIED  -- language code --
-  dir         (ltr|rtl)      #REQUIRED -- directionality --
-  >
-
-<!ELEMENT BASEFONT - O EMPTY           -- base font size -->
-<!ATTLIST BASEFONT
-  id          ID             #IMPLIED  -- document-wide unique id --
-  size        CDATA          #REQUIRED -- base font size for FONT elements --
-  color       %Color;        #IMPLIED  -- text color --
-  face        CDATA          #IMPLIED  -- comma-separated list of font names --
-  >
-
-<!ELEMENT FONT - - (%inline;)*         -- local change to font -->
-<!ATTLIST FONT
-  %coreattrs;                          -- id, class, style, title --
-  %i18n;                       -- lang, dir --
-  size        CDATA          #IMPLIED  -- [+|-]nn e.g. size="+1", size="4" --
-  color       %Color;        #IMPLIED  -- text color --
-  face        CDATA          #IMPLIED  -- comma-separated list of font names --
-  >
-
-<!ELEMENT BR - O EMPTY                 -- forced line break -->
-<!ATTLIST BR
-  %coreattrs;                          -- id, class, style, title --
-  clear       (left|all|right|none) none -- control of text flow --
-  >
-
-<!--================== HTML content models ===============================-->
-
-<!--
-    HTML has two basic content models:
-
-        %inline;     character level elements and text strings
-        %block;      block-like elements e.g. paragraphs and lists
--->
-
-<!ENTITY % block
-     "P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
-      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
-      TABLE | FIELDSET | ADDRESS">
-
-<!ENTITY % flow "%block; | %inline;">
-
-<!--=================== Document Body ====================================-->
-
-<!ELEMENT BODY O O (%flow;)* +(INS|DEL) -- document body -->
-<!ATTLIST BODY
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  onload          %Script;   #IMPLIED  -- the document has been loaded --
-  onunload        %Script;   #IMPLIED  -- the document has been removed --
-  background      %URI;      #IMPLIED  -- texture tile for document
-                                          background --
-  %bodycolors;                         -- bgcolor, text, link, vlink, alink --
-  >
-
-<!ELEMENT ADDRESS - - ((%inline;)|P)*  -- information on author -->
-<!ATTLIST ADDRESS
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!ELEMENT DIV - - (%flow;)*            -- generic language/style container -->
-<!ATTLIST DIV
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %align;                              -- align, text alignment --
-  %reserved;                           -- reserved for possible future use --
-  >
-
-<!ELEMENT CENTER - - (%flow;)*         -- shorthand for DIV align=center -->
-<!ATTLIST CENTER
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!--================== The Anchor Element ================================-->
-
-<!ENTITY % Shape "(rect|circle|poly|default)">
-<!ENTITY % Coords "CDATA" -- comma-separated list of lengths -->
-
-<!ELEMENT A - - (%inline;)* -(A)       -- anchor -->
-<!ATTLIST A
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
-  type        %ContentType;  #IMPLIED  -- advisory content type --
-  name        CDATA          #IMPLIED  -- named link end --
-  href        %URI;          #IMPLIED  -- URI for linked resource --
-  hreflang    %LanguageCode; #IMPLIED  -- language code --
-  target      %FrameTarget;  #IMPLIED  -- render in this frame --
-  rel         %LinkTypes;    #IMPLIED  -- forward link types --
-  rev         %LinkTypes;    #IMPLIED  -- reverse link types --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  shape       %Shape;        rect      -- for use with client-side image maps --
-  coords      %Coords;       #IMPLIED  -- for use with client-side image maps --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  >
-
-<!--================== Client-side image maps ============================-->
-
-<!-- These can be placed in the same document or grouped in a
-     separate document although this isn't yet widely supported -->
-
-<!ELEMENT MAP - - ((%block;) | AREA)+ -- client-side image map -->
-<!ATTLIST MAP
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  name        CDATA          #REQUIRED -- for reference by usemap --
-  >
-
-<!ELEMENT AREA - O EMPTY               -- client-side image map area -->
-<!ATTLIST AREA
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  shape       %Shape;        rect      -- controls interpretation of coords --
-  coords      %Coords;       #IMPLIED  -- comma-separated list of lengths --
-  href        %URI;          #IMPLIED  -- URI for linked resource --
-  target      %FrameTarget;  #IMPLIED  -- render in this frame --
-  nohref      (nohref)       #IMPLIED  -- this region has no action --
-  alt         %Text;         #REQUIRED -- short description --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  >
-
-<!--================== The LINK Element ==================================-->
-
-<!--
-  Relationship values can be used in principle:
-
-   a) for document specific toolbars/menus when used
-      with the LINK element in document head e.g.
-        start, contents, previous, next, index, end, help
-   b) to link to a separate style sheet (rel=stylesheet)
-   c) to make a link to a script (rel=script)
-   d) by stylesheets to control how collections of
-      html nodes are rendered into printed documents
-   e) to make a link to a printable version of this document
-      e.g. a postscript or pdf version (rel=alternate media=print)
--->
-
-<!ELEMENT LINK - O EMPTY               -- a media-independent link -->
-<!ATTLIST LINK
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
-  href        %URI;          #IMPLIED  -- URI for linked resource --
-  hreflang    %LanguageCode; #IMPLIED  -- language code --
-  type        %ContentType;  #IMPLIED  -- advisory content type --
-  rel         %LinkTypes;    #IMPLIED  -- forward link types --
-  rev         %LinkTypes;    #IMPLIED  -- reverse link types --
-  media       %MediaDesc;    #IMPLIED  -- for rendering on these media --
-  target      %FrameTarget;  #IMPLIED  -- render in this frame --
-  >
-
-<!--=================== Images ===========================================-->
-
-<!-- Length defined in strict DTD for cellpadding/cellspacing -->
-<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
-<!ENTITY % MultiLength "CDATA" -- pixel, percentage, or relative -->
-
-<![ %HTML.Frameset; [
-<!ENTITY % MultiLengths "CDATA" -- comma-separated list of MultiLength -->
-]]>
-
-<!ENTITY % Pixels "CDATA" -- integer representing length in pixels -->
-
-<!ENTITY % IAlign "(top|middle|bottom|left|right)" -- center? -->
-
-<!-- To avoid problems with text-only UAs as well as 
-   to make image content understandable and navigable 
-   to users of non-visual UAs, you need to provide
-   a description with ALT, and avoid server-side image maps -->
-<!ELEMENT IMG - O EMPTY                -- Embedded image -->
-<!ATTLIST IMG
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  src         %URI;          #REQUIRED -- URI of image to embed --
-  alt         %Text;         #REQUIRED -- short description --
-  longdesc    %URI;          #IMPLIED  -- link to long description
-                                          (complements alt) --
-  name        CDATA          #IMPLIED  -- name of image for scripting --
-  height      %Length;       #IMPLIED  -- override height --
-  width       %Length;       #IMPLIED  -- override width --
-  usemap      %URI;          #IMPLIED  -- use client-side image map --
-  ismap       (ismap)        #IMPLIED  -- use server-side image map --
-  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
-  border      %Pixels;       #IMPLIED  -- link border width --
-  hspace      %Pixels;       #IMPLIED  -- horizontal gutter --
-  vspace      %Pixels;       #IMPLIED  -- vertical gutter --
-  >
-
-<!-- USEMAP points to a MAP element which may be in this document
-  or an external document, although the latter is not widely supported -->
-
-<!--==================== OBJECT ======================================-->
-<!--
-  OBJECT is used to embed objects as part of HTML pages 
-  PARAM elements should precede other content. SGML mixed content
-  model technicality precludes specifying this formally ...
--->
-
-<!ELEMENT OBJECT - - (PARAM | %flow;)*
- -- generic embedded object -->
-<!ATTLIST OBJECT
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  declare     (declare)      #IMPLIED  -- declare but don't instantiate flag --
-  classid     %URI;          #IMPLIED  -- identifies an implementation --
-  codebase    %URI;          #IMPLIED  -- base URI for classid, data, archive--
-  data        %URI;          #IMPLIED  -- reference to object's data --
-  type        %ContentType;  #IMPLIED  -- content type for data --
-  codetype    %ContentType;  #IMPLIED  -- content type for code --
-  archive     CDATA          #IMPLIED  -- space-separated list of URIs --
-  standby     %Text;         #IMPLIED  -- message to show while loading --
-  height      %Length;       #IMPLIED  -- override height --
-  width       %Length;       #IMPLIED  -- override width --
-  usemap      %URI;          #IMPLIED  -- use client-side image map --
-  name        CDATA          #IMPLIED  -- submit as part of form --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
-  border      %Pixels;       #IMPLIED  -- link border width --
-  hspace      %Pixels;       #IMPLIED  -- horizontal gutter --
-  vspace      %Pixels;       #IMPLIED  -- vertical gutter --
-  %reserved;                           -- reserved for possible future use --
-  >
-
-<!ELEMENT PARAM - O EMPTY              -- named property value -->
-<!ATTLIST PARAM
-  id          ID             #IMPLIED  -- document-wide unique id --
-  name        CDATA          #REQUIRED -- property name --
-  value       CDATA          #IMPLIED  -- property value --
-  valuetype   (DATA|REF|OBJECT) DATA   -- How to interpret value --
-  type        %ContentType;  #IMPLIED  -- content type for value
-                                          when valuetype=ref --
-  >
-
-<!--=================== Java APPLET ==================================-->
-<!--
-  One of code or object attributes must be present.
-  Place PARAM elements before other content.
--->
-<!ELEMENT APPLET - - (PARAM | %flow;)* -- Java applet -->
-<!ATTLIST APPLET
-  %coreattrs;                          -- id, class, style, title --
-  codebase    %URI;          #IMPLIED  -- optional base URI for applet --
-  archive     CDATA          #IMPLIED  -- comma-separated archive list --
-  code        CDATA          #IMPLIED  -- applet class file --
-  object      CDATA          #IMPLIED  -- serialized applet file --
-  alt         %Text;         #IMPLIED  -- short description --
-  name        CDATA          #IMPLIED  -- allows applets to find each other --
-  width       %Length;       #REQUIRED -- initial width --
-  height      %Length;       #REQUIRED -- initial height --
-  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
-  hspace      %Pixels;       #IMPLIED  -- horizontal gutter --
-  vspace      %Pixels;       #IMPLIED  -- vertical gutter --
-  >
-
-<!--=================== Horizontal Rule ==================================-->
-
-<!ELEMENT HR - O EMPTY -- horizontal rule -->
-<!ATTLIST HR
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  align       (left|center|right) #IMPLIED
-  noshade     (noshade)      #IMPLIED
-  size        %Pixels;       #IMPLIED
-  width       %Length;       #IMPLIED
-  >
-
-<!--=================== Paragraphs =======================================-->
-
-<!ELEMENT P - O (%inline;)*            -- paragraph -->
-<!ATTLIST P
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %align;                              -- align, text alignment --
-  >
-
-<!--=================== Headings =========================================-->
-
-<!--
-  There are six levels of headings from H1 (the most important)
-  to H6 (the least important).
--->
-
-<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->
-<!ATTLIST (%heading;)
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %align;                              -- align, text alignment --
-  >
-
-<!--=================== Preformatted Text ================================-->
-
-<!-- excludes markup for images and changes in font size -->
-<!ENTITY % pre.exclusion "IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT">
-
-<!ELEMENT PRE - - (%inline;)* -(%pre.exclusion;) -- preformatted text -->
-<!ATTLIST PRE
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  width       NUMBER         #IMPLIED
-  >
-
-<!--===================== Inline Quotes ==================================-->
-
-<!ELEMENT Q - - (%inline;)*            -- short inline quotation -->
-<!ATTLIST Q
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  cite        %URI;          #IMPLIED  -- URI for source document or msg --
-  >
-
-<!--=================== Block-like Quotes ================================-->
-
-<!ELEMENT BLOCKQUOTE - - (%flow;)*     -- long quotation -->
-<!ATTLIST BLOCKQUOTE
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  cite        %URI;          #IMPLIED  -- URI for source document or msg --
-  >
-
-<!--=================== Inserted/Deleted Text ============================-->
-
-
-<!-- INS/DEL are handled by inclusion on BODY -->
-<!ELEMENT (INS|DEL) - - (%flow;)*      -- inserted text, deleted text -->
-<!ATTLIST (INS|DEL)
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  cite        %URI;          #IMPLIED  -- info on reason for change --
-  datetime    %Datetime;     #IMPLIED  -- date and time of change --
-  >
-
-<!--=================== Lists ============================================-->
-
-<!-- definition lists - DT for term, DD for its definition -->
-
-<!ELEMENT DL - - (DT|DD)+              -- definition list -->
-<!ATTLIST DL
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  compact     (compact)      #IMPLIED  -- reduced interitem spacing --
-  >
-
-<!ELEMENT DT - O (%inline;)*           -- definition term -->
-<!ELEMENT DD - O (%flow;)*             -- definition description -->
-<!ATTLIST (DT|DD)
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!-- Ordered lists (OL) Numbering style
-
-    1   arablic numbers     1, 2, 3, ...
-    a   lower alpha         a, b, c, ...
-    A   upper alpha         A, B, C, ...
-    i   lower roman         i, ii, iii, ...
-    I   upper roman         I, II, III, ...
-
-    The style is applied to the sequence number which by default
-    is reset to 1 for the first list item in an ordered list.
-
-    This can't be expressed directly in SGML due to case folding.
--->
-
-<!ENTITY % OLStyle "CDATA"      -- constrained to: "(1|a|A|i|I)" -->
-
-<!ELEMENT OL - - (LI)+                 -- ordered list -->
-<!ATTLIST OL
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  type        %OLStyle;      #IMPLIED  -- numbering style --
-  compact     (compact)      #IMPLIED  -- reduced interitem spacing --
-  start       NUMBER         #IMPLIED  -- starting sequence number --
-  >
-
-<!-- Unordered Lists (UL) bullet styles -->
-<!ENTITY % ULStyle "(disc|square|circle)">
-
-<!ELEMENT UL - - (LI)+                 -- unordered list -->
-<!ATTLIST UL
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  type        %ULStyle;      #IMPLIED  -- bullet style --
-  compact     (compact)      #IMPLIED  -- reduced interitem spacing --
-  >
-
-<!ELEMENT (DIR|MENU) - - (LI)+ -(%block;) -- directory list, menu list -->
-<!ATTLIST DIR
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  compact     (compact)      #IMPLIED -- reduced interitem spacing --
-  >
-<!ATTLIST MENU
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  compact     (compact)      #IMPLIED -- reduced interitem spacing --
-  >
-
-<!ENTITY % LIStyle "CDATA" -- constrained to: "(%ULStyle;|%OLStyle;)" -->
-
-<!ELEMENT LI - O (%flow;)*             -- list item -->
-<!ATTLIST LI
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  type        %LIStyle;      #IMPLIED  -- list item style --
-  value       NUMBER         #IMPLIED  -- reset sequence number --
-  >
-
-<!--================ Forms ===============================================-->
-<!ELEMENT FORM - - (%flow;)* -(FORM)   -- interactive form -->
-<!ATTLIST FORM
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  action      %URI;          #REQUIRED -- server-side form handler --
-  method      (GET|POST)     GET       -- HTTP method used to submit the form--
-  enctype     %ContentType;  "application/x-www-form-urlencoded"
-  accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
-  name        CDATA          #IMPLIED  -- name of form for scripting --
-  onsubmit    %Script;       #IMPLIED  -- the form was submitted --
-  onreset     %Script;       #IMPLIED  -- the form was reset --
-  target      %FrameTarget;  #IMPLIED  -- render in this frame --
-  accept-charset %Charsets;  #IMPLIED  -- list of supported charsets --
-  >
-
-<!-- Each label must not contain more than ONE field -->
-<!ELEMENT LABEL - - (%inline;)* -(LABEL) -- form field label text -->
-<!ATTLIST LABEL
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  for         IDREF          #IMPLIED  -- matches field ID value --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  >
-
-<!ENTITY % InputType
-  "(TEXT | PASSWORD | CHECKBOX |
-    RADIO | SUBMIT | RESET |
-    FILE | HIDDEN | IMAGE | BUTTON)"
-   >
-
-<!-- attribute name required for all but submit and reset -->
-<!ELEMENT INPUT - O EMPTY              -- form control -->
-<!ATTLIST INPUT
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  type        %InputType;    TEXT      -- what kind of widget is needed --
-  name        CDATA          #IMPLIED  -- submit as part of form --
-  value       CDATA          #IMPLIED  -- Specify for radio buttons and checkboxes --
-  checked     (checked)      #IMPLIED  -- for radio buttons and check boxes --
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  readonly    (readonly)     #IMPLIED  -- for text and passwd --
-  size        CDATA          #IMPLIED  -- specific to each type of field --
-  maxlength   NUMBER         #IMPLIED  -- max chars for text fields --
-  src         %URI;          #IMPLIED  -- for fields with images --
-  alt         CDATA          #IMPLIED  -- short description --
-  usemap      %URI;          #IMPLIED  -- use client-side image map --
-  ismap       (ismap)        #IMPLIED  -- use server-side image map --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  onselect    %Script;       #IMPLIED  -- some text was selected --
-  onchange    %Script;       #IMPLIED  -- the element value was changed --
-  accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
-  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
-  %reserved;                           -- reserved for possible future use --
-  >
-
-<!ELEMENT SELECT - - (OPTGROUP|OPTION)+ -- option selector -->
-<!ATTLIST SELECT
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  name        CDATA          #IMPLIED  -- field name --
-  size        NUMBER         #IMPLIED  -- rows visible --
-  multiple    (multiple)     #IMPLIED  -- default is single selection --
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  onchange    %Script;       #IMPLIED  -- the element value was changed --
-  %reserved;                           -- reserved for possible future use --
-  >
-
-<!ELEMENT OPTGROUP - - (OPTION)+ -- option group -->
-<!ATTLIST OPTGROUP
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  label       %Text;         #REQUIRED -- for use in hierarchical menus --
-  >
-
-<!ELEMENT OPTION - O (#PCDATA)         -- selectable choice -->
-<!ATTLIST OPTION
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  selected    (selected)     #IMPLIED
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  label       %Text;         #IMPLIED  -- for use in hierarchical menus --
-  value       CDATA          #IMPLIED  -- defaults to element content --
-  >
-
-<!ELEMENT TEXTAREA - - (#PCDATA)       -- multi-line text field -->
-<!ATTLIST TEXTAREA
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  name        CDATA          #IMPLIED
-  rows        NUMBER         #REQUIRED
-  cols        NUMBER         #REQUIRED
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  readonly    (readonly)     #IMPLIED
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  onselect    %Script;       #IMPLIED  -- some text was selected --
-  onchange    %Script;       #IMPLIED  -- the element value was changed --
-  %reserved;                           -- reserved for possible future use --
-  >
-
-<!--
-  #PCDATA is to solve the mixed content problem,
-  per specification only whitespace is allowed there!
- -->
-<!ELEMENT FIELDSET - - (#PCDATA,LEGEND,(%flow;)*) -- form control group -->
-<!ATTLIST FIELDSET
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!ELEMENT LEGEND - - (%inline;)*       -- fieldset legend -->
-<!ENTITY % LAlign "(top|bottom|left|right)">
-
-<!ATTLIST LEGEND
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  align       %LAlign;       #IMPLIED  -- relative to fieldset --
-  >
-
-<!ELEMENT BUTTON - -
-     (%flow;)* -(A|%formctrl;|FORM|ISINDEX|FIELDSET|IFRAME)
-     -- push button -->
-<!ATTLIST BUTTON
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  name        CDATA          #IMPLIED
-  value       CDATA          #IMPLIED  -- sent to server when submitted --
-  type        (button|submit|reset) submit -- for use as form button --
-  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
-  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
-  accesskey   %Character;    #IMPLIED  -- accessibility key character --
-  onfocus     %Script;       #IMPLIED  -- the element got the focus --
-  onblur      %Script;       #IMPLIED  -- the element lost the focus --
-  %reserved;                           -- reserved for possible future use --
-  >
-
-<!--======================= Tables =======================================-->
-
-<!-- IETF HTML table standard, see [RFC1942] -->
-
-<!--
- The BORDER attribute sets the thickness of the frame around the
- table. The default units are screen pixels.
-
- The FRAME attribute specifies which parts of the frame around
- the table should be rendered. The values are not the same as
- CALS to avoid a name clash with the VALIGN attribute.
-
- The value "border" is included for backwards compatibility with
- <TABLE BORDER> which yields frame=border and border=implied
- For <TABLE BORDER=1> you get border=1 and frame=implied. In this
- case, it is appropriate to treat this as frame=border for backwards
- compatibility with deployed browsers.
--->
-<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
-
-<!--
- The RULES attribute defines which rules to draw between cells:
-
- If RULES is absent then assume:
-     "none" if BORDER is absent or BORDER=0 otherwise "all"
--->
-
-<!ENTITY % TRules "(none | groups | rows | cols | all)">
-  
-<!-- horizontal placement of table relative to document -->
-<!ENTITY % TAlign "(left|center|right)">
-
-<!-- horizontal alignment attributes for cell contents -->
-<!ENTITY % cellhalign
-  "align      (left|center|right|justify|char) #IMPLIED
-   char       %Character;    #IMPLIED  -- alignment char, e.g. char=':' --
-   charoff    %Length;       #IMPLIED  -- offset for alignment char --"
-  >
-
-<!-- vertical alignment attributes for cell contents -->
-<!ENTITY % cellvalign
-  "valign     (top|middle|bottom|baseline) #IMPLIED"
-  >
-
-<!ELEMENT TABLE - -
-     (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
-<!ELEMENT CAPTION  - - (%inline;)*     -- table caption -->
-<!ELEMENT THEAD    - O (TR)+           -- table header -->
-<!ELEMENT TFOOT    - O (TR)+           -- table footer -->
-<!ELEMENT TBODY    O O (TR)+           -- table body -->
-<!ELEMENT COLGROUP - O (COL)*          -- table column group -->
-<!ELEMENT COL      - O EMPTY           -- table column -->
-<!ELEMENT TR       - O (TH|TD)+        -- table row -->
-<!ELEMENT (TH|TD)  - O (%flow;)*       -- table header cell, table data cell-->
-
-<!ATTLIST TABLE                        -- table element --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  summary     %Text;         #IMPLIED  -- purpose/structure for speech output--
-  width       %Length;       #IMPLIED  -- table width --
-  border      %Pixels;       #IMPLIED  -- controls frame width around table --
-  frame       %TFrame;       #IMPLIED  -- which parts of frame to render --
-  rules       %TRules;       #IMPLIED  -- rulings between rows and cols --
-  cellspacing %Length;       #IMPLIED  -- spacing between cells --
-  cellpadding %Length;       #IMPLIED  -- spacing within cells --
-  align       %TAlign;       #IMPLIED  -- table position relative to window --
-  bgcolor     %Color;        #IMPLIED  -- background color for cells --
-  %reserved;                           -- reserved for possible future use --
-  datapagesize CDATA         #IMPLIED  -- reserved for possible future use --
-  >
-
-<!ENTITY % CAlign "(top|bottom|left|right)">
-
-<!ATTLIST CAPTION
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  align       %CAlign;       #IMPLIED  -- relative to table --
-  >
-
-<!--
-COLGROUP groups a set of COL elements. It allows you to group
-several semantically related columns together.
--->
-<!ATTLIST COLGROUP
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  span        NUMBER         1         -- default number of columns in group --
-  width       %MultiLength;  #IMPLIED  -- default width for enclosed COLs --
-  %cellhalign;                         -- horizontal alignment in cells --
-  %cellvalign;                         -- vertical alignment in cells --
-  >
-
-<!--
- COL elements define the alignment properties for cells in
- one or more columns.
-
- The WIDTH attribute specifies the width of the columns, e.g.
-
-     width=64        width in screen pixels
-     width=0.5*      relative width of 0.5
-
- The SPAN attribute causes the attributes of one
- COL element to apply to more than one column.
--->
-<!ATTLIST COL                          -- column groups and properties --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  span        NUMBER         1         -- COL attributes affect N columns --
-  width       %MultiLength;  #IMPLIED  -- column width specification --
-  %cellhalign;                         -- horizontal alignment in cells --
-  %cellvalign;                         -- vertical alignment in cells --
-  >
-
-<!--
-    Use THEAD to duplicate headers when breaking table
-    across page boundaries, or for static headers when
-    TBODY sections are rendered in scrolling panel.
-
-    Use TFOOT to duplicate footers when breaking table
-    across page boundaries, or for static footers when
-    TBODY sections are rendered in scrolling panel.
-
-    Use multiple TBODY sections when rules are needed
-    between groups of table rows.
--->
-<!ATTLIST (THEAD|TBODY|TFOOT)          -- table section --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %cellhalign;                         -- horizontal alignment in cells --
-  %cellvalign;                         -- vertical alignment in cells --
-  >
-
-<!ATTLIST TR                           -- table row --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  %cellhalign;                         -- horizontal alignment in cells --
-  %cellvalign;                         -- vertical alignment in cells --
-  bgcolor     %Color;        #IMPLIED  -- background color for row --
-  >
-
-
-
-<!-- Scope is simpler than headers attribute for common tables -->
-<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
-
-<!-- TH is for headers, TD for data, but for cells acting as both use TD -->
-<!ATTLIST (TH|TD)                      -- header or data cell --
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  abbr        %Text;         #IMPLIED  -- abbreviation for header cell --
-  axis        CDATA          #IMPLIED  -- comma-separated list of related headers--
-  headers     IDREFS         #IMPLIED  -- list of id's for header cells --
-  scope       %Scope;        #IMPLIED  -- scope covered by header cells --
-  rowspan     NUMBER         1         -- number of rows spanned by cell --
-  colspan     NUMBER         1         -- number of cols spanned by cell --
-  %cellhalign;                         -- horizontal alignment in cells --
-  %cellvalign;                         -- vertical alignment in cells --
-  nowrap      (nowrap)       #IMPLIED  -- suppress word wrap --
-  bgcolor     %Color;        #IMPLIED  -- cell background color --
-  width       %Length;       #IMPLIED  -- width for cell --
-  height      %Length;       #IMPLIED  -- height for cell --
-  >
-
-<!--================== Document Frames ===================================-->
-
-<!--
-  The content model for HTML documents depends on whether the HEAD is
-  followed by a FRAMESET or BODY element. The widespread omission of
-  the BODY start tag makes it impractical to define the content model
-  without the use of a marked section.
--->
-
-<![ %HTML.Frameset; [
-<!ELEMENT FRAMESET - - ((FRAMESET|FRAME)+ & NOFRAMES?) -- window subdivision-->
-<!ATTLIST FRAMESET
-  %coreattrs;                          -- id, class, style, title --
-  rows        %MultiLengths; #IMPLIED  -- list of lengths,
-                                          default: 100% (1 row) --
-  cols        %MultiLengths; #IMPLIED  -- list of lengths,
-                                          default: 100% (1 col) --
-  onload      %Script;       #IMPLIED  -- all the frames have been loaded  -- 
-  onunload    %Script;       #IMPLIED  -- all the frames have been removed -- 
-  >
-]]>
-
-<![ %HTML.Frameset; [
-<!-- reserved frame names start with "_" otherwise starts with letter -->
-<!ELEMENT FRAME - O EMPTY              -- subwindow -->
-<!ATTLIST FRAME
-  %coreattrs;                          -- id, class, style, title --
-  longdesc    %URI;          #IMPLIED  -- link to long description
-                                          (complements title) --
-  name        CDATA          #IMPLIED  -- name of frame for targetting --
-  src         %URI;          #IMPLIED  -- source of frame content --
-  frameborder (1|0)          1         -- request frame borders? --
-  marginwidth %Pixels;       #IMPLIED  -- margin widths in pixels --
-  marginheight %Pixels;      #IMPLIED  -- margin height in pixels --
-  noresize    (noresize)     #IMPLIED  -- allow users to resize frames? --
-  scrolling   (yes|no|auto)  auto      -- scrollbar or none --
-  >
-]]>
-
-<!ELEMENT IFRAME - - (%flow;)*         -- inline subwindow -->
-<!ATTLIST IFRAME
-  %coreattrs;                          -- id, class, style, title --
-  longdesc    %URI;          #IMPLIED  -- link to long description
-                                          (complements title) --
-  name        CDATA          #IMPLIED  -- name of frame for targetting --
-  src         %URI;          #IMPLIED  -- source of frame content --
-  frameborder (1|0)          1         -- request frame borders? --
-  marginwidth %Pixels;       #IMPLIED  -- margin widths in pixels --
-  marginheight %Pixels;      #IMPLIED  -- margin height in pixels --
-  scrolling   (yes|no|auto)  auto      -- scrollbar or none --
-  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
-  height      %Length;       #IMPLIED  -- frame height --
-  width       %Length;       #IMPLIED  -- frame width --
-  >
-
-<![ %HTML.Frameset; [
-<!ENTITY % noframes.content "(BODY) -(NOFRAMES)">
-]]>
-
-<!ENTITY % noframes.content "(%flow;)*">
-
-<!ELEMENT NOFRAMES - - %noframes.content;
- -- alternate content container for non frame-based rendering -->
-<!ATTLIST NOFRAMES
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!--================ Document Head =======================================-->
-<!-- %head.misc; defined earlier on as "SCRIPT|STYLE|META|LINK|OBJECT" -->
-<!ENTITY % head.content "TITLE & ISINDEX? & BASE?">
-
-<!ELEMENT HEAD O O (%head.content;) +(%head.misc;) -- document head -->
-<!ATTLIST HEAD
-  %i18n;                               -- lang, dir --
-  profile     %URI;          #IMPLIED  -- named dictionary of meta info --
-  >
-
-<!-- The TITLE element is not considered part of the flow of text.
-       It should be displayed, for example as the page header or
-       window title. Exactly one title is required per document.
-    -->
-<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;) -- document title -->
-<!ATTLIST TITLE %i18n>
-
-<!ELEMENT ISINDEX - O EMPTY            -- single line prompt -->
-<!ATTLIST ISINDEX
-  %coreattrs;                          -- id, class, style, title --
-  %i18n;                               -- lang, dir --
-  prompt      %Text;         #IMPLIED  -- prompt message -->
-
-<!ELEMENT BASE - O EMPTY               -- document base URI -->
-<!ATTLIST BASE
-  href        %URI;          #IMPLIED  -- URI that acts as base URI --
-  target      %FrameTarget;  #IMPLIED  -- render in this frame --
-  >
-
-<!ELEMENT META - O EMPTY               -- generic metainformation -->
-<!ATTLIST META
-  %i18n;                               -- lang, dir, for use with content --
-  http-equiv  NAME           #IMPLIED  -- HTTP response header name  --
-  name        NAME           #IMPLIED  -- metainformation name --
-  content     CDATA          #REQUIRED -- associated information --
-  scheme      CDATA          #IMPLIED  -- select form of content --
-  >
-
-<!ELEMENT STYLE - - %StyleSheet        -- style info -->
-<!ATTLIST STYLE
-  %i18n;                               -- lang, dir, for use with title --
-  type        %ContentType;  #REQUIRED -- content type of style language --
-  media       %MediaDesc;    #IMPLIED  -- designed for use with these media --
-  title       %Text;         #IMPLIED  -- advisory title --
-  >
-
-<!ELEMENT SCRIPT - - %Script;          -- script statements -->
-<!ATTLIST SCRIPT
-  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
-  type        %ContentType;  #REQUIRED -- content type of script language --
-  language    CDATA          #IMPLIED  -- predefined script language name --
-  src         %URI;          #IMPLIED  -- URI for an external script --
-  defer       (defer)        #IMPLIED  -- UA may defer execution of script --
-  event       CDATA          #IMPLIED  -- reserved for possible future use --
-  for         %URI;          #IMPLIED  -- reserved for possible future use --
-  >
-
-<!ELEMENT NOSCRIPT - - (%flow;)*
-  -- alternate content container for non script-based rendering -->
-<!ATTLIST NOSCRIPT
-  %attrs;                              -- %coreattrs, %i18n, %events --
-  >
-
-<!--================ Document Structure ==================================-->
-<!ENTITY % version "version CDATA #FIXED '%HTML.Version;'">
-
-<![ %HTML.Frameset; [
-<!ENTITY % html.content "HEAD, FRAMESET">
-]]>
-
-<!ENTITY % html.content "HEAD, BODY">
-
-<!ELEMENT HTML O O (%html.content;)    -- document root element -->
-<!ATTLIST HTML
-  %i18n;                               -- lang, dir --
-  %version;
-  >


[22/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/Outline.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/Outline.js b/experiments/editorFramework/src/Javascript_Layer_0/Outline.js
new file mode 100644
index 0000000..9812041
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/Outline.js
@@ -0,0 +1,1434 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+// FIXME: The TOC/ItemList stuff won't work with Undo, because we're making DOM mutations in
+// response to other DOM mutations, so at undo time the changes will be made twice
+
+var Outline_init;
+var Outline_removeListeners;
+var Outline_moveSection;
+var Outline_deleteItem;
+var Outline_goToItem;
+var Outline_setTitle;
+var Outline_setNumbered;
+var Outline_getItemElement;
+var Outline_getOutline;
+var Outline_plainText;
+var Outline_insertTableOfContents;
+var Outline_insertListOfFigures;
+var Outline_insertListOfTables;
+var Outline_setPrintMode;
+var Outline_examinePrintLayout;
+var Outline_setReferenceTarget;
+var Outline_detectSectionNumbering;
+var Outline_findUsedStyles;
+var Outline_scheduleUpdateStructure;
+
+(function() {
+
+    var itemsByNode = null;
+    var refsById = null;
+    var nextItemId = 1;
+    var outlineDirty = false;
+    var ignoreModifications = 0;
+    var sectionNumberRegex = /^\s*(Chapter\s+)?\d+(\.\d+)*\.?\s+/i;
+    var figureNumberRegex = /^\s*Figure\s+\d+(\.\d+)*:?\s*/i;
+    var tableNumberRegex = /^\s*Table\s+\d+(\.\d+)*:?\s*/i;
+    var sections = null;
+    var figures = null;
+    var tables = null;
+    var doneInit = false;
+    var printMode = false;
+
+    function Category(type,nodeFilter,numberRegex)
+    {
+        this.type = type;
+        this.nodeFilter = nodeFilter;
+        this.numberRegex = numberRegex;
+        this.list = new DoublyLinkedList();
+        this.tocs = new NodeMap();
+    }
+
+    function addItemInternal(category,item,prevItem,title)
+    {
+        UndoManager_addAction(removeItemInternal,category,item);
+        category.list.insertAfter(item,prevItem);
+        item.title = title;
+        category.tocs.forEach(function(node,toc) { TOC_addOutlineItem(toc,item.id); });
+        Editor_addOutlineItem(item.id,category.type,title);
+    }
+
+    function removeItemInternal(category,item)
+    {
+        UndoManager_addAction(addItemInternal,category,item,item.prev,item.title);
+        category.list.remove(item);
+        category.tocs.forEach(function(node,toc) { TOC_removeOutlineItem(toc,item.id); });
+        item.title = null;
+        Editor_removeOutlineItem(item.id);
+    }
+
+    function Category_add(category,node)
+    {
+        var item = itemsByNode.get(node);
+        if (item == null)
+            item = new OutlineItem(category,node);
+
+        var prevItem = findPrevItemOfType(node,category.nodeFilter);
+        addItemInternal(category,item,prevItem,null);
+
+        // Register for notifications to changes to this item's node content. We may need to
+        // update the title when such a modification occurs.
+        node.addEventListener("DOMSubtreeModified",item.modificationListener);
+
+        OutlineItem_updateItemTitle(item);
+        scheduleUpdateStructure();
+        return item;
+
+        function findPrevItemOfType(node,typeFun)
+        {
+            do node = prevNode(node);
+            while ((node != null) && !typeFun(node));
+            return (node == null) ? null : itemsByNode.get(node);
+        }
+    }
+
+    function findFirstTextDescendant(node)
+    {
+        if (isWhitespaceTextNode(node))
+            return;
+        if (node.nodeType == Node.TEXT_NODE)
+            return node;
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            var result = findFirstTextDescendant(child);
+            if (result != null)
+                return result;
+        }
+        return null;
+    }
+
+    function Category_remove(category,node)
+    {
+        var item = itemsByNode.get(node);
+        if (item == null) {
+            throw new Error("Attempt to remove non-existant "+node.nodeName+
+                            " item "+node.getAttribute("id"));
+        }
+        removeItemInternal(category,item);
+        item.node.removeEventListener("DOMSubtreeModified",item.modificationListener);
+        var titleNode = OutlineItem_getTitleNode(item,false);
+        if ((titleNode != null) &&
+            ((item.type == "figure") || (item.type == "table")) &&
+            (titleNode.firstChild == null) &&
+            (titleNode.lastChild == null)) {
+            DOM_deleteNode(titleNode);
+        }
+        scheduleUpdateStructure();
+    }
+
+    function addTOCInternal(category,node,toc)
+    {
+        UndoManager_addAction(removeTOCInternal,category,node);
+        category.tocs.put(node,toc);
+    }
+
+    function removeTOCInternal(category,node)
+    {
+        var toc = category.tocs.get(node);
+        if (toc == null)
+            throw new Error("Attempt to remove ItemList that doesn't exist");
+
+        UndoManager_addAction(addTOCInternal,category,node,toc);
+
+        category.tocs.remove(node);
+    }
+
+    function Category_addTOC(category,node)
+    {
+        var toc = new TOC(node);
+        addTOCInternal(category,node,toc);
+
+        for (var item = category.list.first; item != null; item = item.next) {
+            TOC_addOutlineItem(toc,item.id);
+            TOC_updateOutlineItem(toc,item.id,item.title);
+        }
+
+        scheduleUpdateStructure();
+    }
+
+    function Category_removeTOC(category,node)
+    {
+        removeTOCInternal(category,node);
+    }
+
+    function TOC(node)
+    {
+        this.node = node;
+        this.textNodes = new Object();
+    }
+
+    function TOC_addOutlineItem(toc,id)
+    {
+        toc.textNodes[id] = DOM_createTextNode(document,"");
+    }
+
+    function TOC_removeOutlineItem(toc,id)
+    {
+        delete toc.textNodes[id];
+    }
+
+    function TOC_updateOutlineItem(toc,id,title)
+    {
+        DOM_setNodeValue(toc.textNodes[id],title);
+    }
+
+    function TOC_updateStructure(toc,structure,toplevelShadows,pageNumbers)
+    {
+        Hierarchy_ensureValidHierarchy(toc.node);
+        DOM_deleteAllChildren(toc.node);
+
+        var cls = toc.node.getAttribute("class");
+
+        if (toplevelShadows.length == 0) {
+            createEmptyTOC(toc.node);
+        }
+        else {
+            recurse(toplevelShadows,toc.node,1);
+        }
+
+        if (printMode) {
+            var brk = DOM_createElement(document,"DIV");
+            DOM_setStyleProperties(brk,{ "clear": "both" });
+            DOM_appendChild(toc.node,brk);
+        }
+
+        function createEmptyTOC(parent)
+        {
+            if (!printMode) {
+                var str = "";
+
+                if (cls == Keys.SECTION_TOC)
+                    str = "[No sections defined]";
+                else if (cls == Keys.FIGURE_TOC)
+                    str = "[No figures defined]";
+                else if (cls == Keys.TABLE_TOC)
+                    str = "[No tables defined]";
+
+                var text = DOM_createTextNode(document,str);
+
+                var div = DOM_createElement(document,"P");
+                DOM_setAttribute(div,"class","toc1");
+                DOM_appendChild(div,text);
+                DOM_appendChild(parent,div);
+            }
+        }
+
+        function recurse(shadows,parent,level)
+        {
+            if (level > 3)
+                return;
+
+            for (var i = 0; i < shadows.length; i++) {
+                var shadow = shadows[i];
+                var item = shadow.item;
+
+                if (printMode) {
+                    var div = DOM_createElement(document,"P");
+                    DOM_setAttribute(div,"class","toc"+level+"-print");
+                    DOM_appendChild(parent,div);
+
+                    var leftSpan = DOM_createElement(document,"SPAN");
+                    DOM_setAttribute(leftSpan,"class","toctitle");
+
+                    var rightSpan = DOM_createElement(document,"SPAN");
+                    DOM_setAttribute(rightSpan,"class","tocpageno");
+
+                    DOM_appendChild(div,leftSpan);
+                    DOM_appendChild(div,rightSpan);
+
+                    if (item.computedNumber != null) {
+                        var text = DOM_createTextNode(document,item.computedNumber+" ");
+                        DOM_appendChild(leftSpan,text);
+                    }
+
+                    DOM_appendChild(leftSpan,toc.textNodes[item.id]);
+                    var pageNo = pageNumbers ? pageNumbers.get(item.node) : null;
+                    if (pageNo == null)
+                        DOM_appendChild(rightSpan,DOM_createTextNode(document,"XXXX"));
+                    else
+                        DOM_appendChild(rightSpan,DOM_createTextNode(document,pageNo));
+                }
+                else {
+                    var div = DOM_createElement(document,"P");
+                    DOM_setAttribute(div,"class","toc"+level);
+                    DOM_appendChild(parent,div);
+
+                    var a = DOM_createElement(document,"A");
+                    DOM_setAttribute(a,"href","#"+item.id);
+                    DOM_appendChild(div,a);
+
+                    if (item.computedNumber != null)
+                        DOM_appendChild(a,DOM_createTextNode(document,item.computedNumber+" "));
+                    DOM_appendChild(a,toc.textNodes[item.id]);
+                }
+
+                recurse(shadow.children,parent,level+1);
+            }
+        }
+    }
+
+    function OutlineItem(category,node)
+    {
+        var type = category.type;
+        var item = this;
+        if ((node != null) && (node.hasAttribute("id"))) {
+            this.id = node.getAttribute("id");
+        }
+        else {
+            this.id = generateItemId();
+            if (node != null)
+                DOM_setAttribute(node,"id",this.id);
+        }
+        this.category = category;
+        this.type = type;
+        this.node = node;
+        this.title = null;
+        this.computedNumber = null;
+
+        this.spareSpan = DOM_createElement(document,"SPAN");
+        DOM_appendChild(this.spareSpan,DOM_createTextNode(document,""));
+        var spanClass = null;
+        if (this.type == "section")
+            spanClass = Keys.HEADING_NUMBER;
+        else if (this.type == "figure")
+            spanClass = Keys.FIGURE_NUMBER;
+        else if (this.type == "table")
+            spanClass = Keys.TABLE_NUMBER;
+        DOM_setAttribute(this.spareSpan,"class",spanClass);
+
+        // titleNode
+        if (this.type == "figure") {
+            this.spareTitle = DOM_createElement(document,"FIGCAPTION");
+        }
+        else if (this.type == "table") {
+            this.spareTitle = DOM_createElement(document,"CAPTION");
+        }
+
+        this.prev = null;
+        this.next = null;
+        this.modificationListener = function(event) { itemModified(item); }
+
+        itemsByNode.put(this.node,this);
+
+        Object.seal(this);
+        return;
+
+        function generateItemId()
+        {
+            var id;
+            do {
+                id = "item"+(nextItemId++);
+            } while (document.getElementById(id) != null);
+            return id;
+        }
+    }
+
+    function OutlineItem_getTitleNode(item,create)
+    {
+        if (item.type == "section") {
+            return item.node;
+        }
+        else if (item.type == "figure") {
+            var titleNode = findChild(item.node,HTML_FIGCAPTION);
+            if ((titleNode == null) && create) {
+                titleNode = item.spareTitle;
+                DOM_appendChild(item.node,titleNode);
+            }
+            return titleNode;
+        }
+        else if (item.type == "table") {
+            var titleNode = findChild(item.node,HTML_CAPTION);
+            if ((titleNode == null) && create) {
+                titleNode = item.spareTitle;
+                DOM_insertBefore(item.node,titleNode,item.node.firstChild);
+            }
+            return titleNode;
+        }
+
+        function findChild(node,type)
+        {
+            for (var child = node.firstChild; child != null; child = child.nextSibling) {
+                if (child._type == type)
+                    return child;
+            }
+            return null;
+        }
+    }
+
+    function OutlineItem_updateItemTitle(item)
+    {
+        var titleNode = OutlineItem_getTitleNode(item,false);
+        if (titleNode != null)
+            newTitle = normalizeWhitespace(getNodeText(titleNode));
+        else
+            newTitle = "";
+
+        if (item.title != newTitle) {
+            UndoManager_addAction(Editor_updateOutlineItem,item.id,item.title);
+            Editor_updateOutlineItem(item.id,newTitle);
+            item.title = newTitle;
+            item.category.tocs.forEach(function(node,toc) {
+                TOC_updateOutlineItem(toc,item.id,item.title);
+            });
+        }
+    }
+
+    function getNodeTextAfter(node)
+    {
+        var text = "";
+        for (var child = node.nextSibling; child != null; child = child.nextSibling)
+            text += getNodeText(child);
+        return text;
+    }
+
+    // private
+    function itemModified(item)
+    {
+        if (UndoManager_isActive())
+            return;
+        if (ignoreModifications > 0)
+            return;
+        OutlineItem_updateItemTitle(item);
+        updateRefsForItem(item);
+    }
+
+    function addRefForId(id,node)
+    {
+        UndoManager_addAction(removeRefForId,id,node);
+        if (refsById[id] == null)
+            refsById[id] = new Array();
+        refsById[id].push(node);
+    }
+
+    function removeRefForId(id,node)
+    {
+        UndoManager_addAction(addRefForId,id,node);
+        if (refsById[id] == null)
+            throw new Error("refRemoved: refsById["+id+"] is null");
+        var index = refsById[id].indexOf(node);
+        if (index < 0)
+            throw new Error("refRemoved: refsById["+id+"] does not contain node");
+        refsById[id].splice(index,1);
+        if (refsById[id] == null)
+            delete refsById[id];
+    }
+
+    // private
+    function refInserted(node)
+    {
+        var href = node.getAttribute("href");
+        if (href.charAt(0) != "#")
+            throw new Error("refInserted: not a # reference");
+        var id = href.substring(1);
+        addRefForId(id,node);
+        scheduleUpdateStructure();
+    }
+
+    // private
+    function refRemoved(node)
+    {
+        var href = node.getAttribute("href");
+        if (href.charAt(0) != "#")
+            throw new Error("refInserted: not a # reference");
+        var id = href.substring(1);
+        removeRefForId(id,node);
+    }
+
+    // private
+    function acceptNode(node)
+    {
+        for (var p = node; p != null; p = p.parentNode) {
+            if ((p._type == HTML_SPAN) && (p.getAttribute("class") == Keys.HEADING_NUMBER))
+                return false;
+        }
+        return true;
+    }
+
+    // private
+    function docNodeInserted(event)
+    {
+        if (UndoManager_isActive())
+            return;
+        if (DOM_getIgnoreMutations())
+            return;
+        try {
+            if (!acceptNode(event.target))
+                return;
+            recurse(event.target);
+        }
+        catch (e) {
+            Editor_error(e);
+        }
+
+        function recurse(node)
+        {
+            switch (node._type) {
+            case HTML_H1:
+            case HTML_H2:
+            case HTML_H3:
+            case HTML_H4:
+            case HTML_H5:
+            case HTML_H6: {
+                if (!isInTOC(node))
+                    Category_add(sections,node);
+                break;
+            }
+            case HTML_FIGURE:
+                Category_add(figures,node);
+                break;
+            case HTML_TABLE:
+                Category_add(tables,node);
+                break;
+            case HTML_A: {
+                if (isRefNode(node) && !isInTOC(node)) {
+                    refInserted(node);
+                }
+                break;
+            }
+            case HTML_NAV: {
+                var cls = node.getAttribute("class");
+                if (cls == Keys.SECTION_TOC)
+                    Category_addTOC(sections,node);
+                else if (cls == Keys.FIGURE_TOC)
+                    Category_addTOC(figures,node);
+                else if (cls == Keys.TABLE_TOC)
+                    Category_addTOC(tables,node);
+                break;
+            }
+            }
+
+            var next;
+            for (var child = node.firstChild; child != null; child = next) {
+                next = child.nextSibling;
+                recurse(child);
+            }
+        }
+    }
+
+    // private
+    function docNodeRemoved(event)
+    {
+        if (UndoManager_isActive())
+            return;
+        if (DOM_getIgnoreMutations())
+            return;
+        try {
+            if (!acceptNode(event.target))
+                return;
+            recurse(event.target);
+        }
+        catch (e) {
+            Editor_error(e);
+        }
+
+        function recurse(node)
+        {
+            switch (node._type) {
+            case HTML_H1:
+            case HTML_H2:
+            case HTML_H3:
+            case HTML_H4:
+            case HTML_H5:
+            case HTML_H6:
+                if (!isInTOC(node))
+                    Category_remove(sections,node);
+                break;
+            case HTML_FIGURE:
+                Category_remove(figures,node);
+                break;
+            case HTML_TABLE:
+                Category_remove(tables,node);
+                break;
+            case HTML_A:
+                if (isRefNode(node) && !isInTOC(node))
+                    refRemoved(node);
+                break;
+            case HTML_NAV:
+                var cls = node.getAttribute("class");
+                if (cls == Keys.SECTION_TOC)
+                    Category_removeTOC(sections,node);
+                else if (cls == Keys.FIGURE_TOC)
+                    Category_removeTOC(figures,node);
+                else if (cls == Keys.TABLE_TOC)
+                    Category_removeTOC(tables,node);
+                break;
+            }
+
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+    // private
+    function scheduleUpdateStructure()
+    {
+        if (UndoManager_isActive())
+            return;
+        if (!outlineDirty) {
+            outlineDirty = true;
+            PostponedActions_add(updateStructure);
+        }
+    }
+
+    Outline_scheduleUpdateStructure = scheduleUpdateStructure;
+
+    // private
+    function updateStructure()
+    {
+        if (!outlineDirty)
+            return;
+        outlineDirty = false;
+        if (UndoManager_isActive())
+            throw new Error("Structure update event while undo or redo active");
+        Selection_preserveWhileExecuting(function() {
+            updateStructureReal();
+        });
+    }
+
+    function Shadow(node)
+    {
+        this.node = node;
+        this.item = itemsByNode.get(node);
+        this.children = [];
+        this.parent = null;
+
+        switch (node._type) {
+        case HTML_H1:
+            this.level = 1;
+            break;
+        case HTML_H2:
+            this.level = 2;
+            break;
+        case HTML_H3:
+            this.level = 3;
+            break;
+        case HTML_H4:
+            this.level = 4;
+            break;
+        case HTML_H5:
+            this.level = 5;
+            break;
+        case HTML_H6:
+            this.level = 6;
+            break;
+        default:
+            this.level = 0;
+            break;
+        }
+    }
+
+    function Shadow_last(shadow)
+    {
+        if (shadow.children.length == 0)
+            return shadow;
+        else
+            return Shadow_last(shadow.children[shadow.children.length-1]);
+    }
+
+    function Shadow_outerNext(shadow,structure)
+    {
+        var last = Shadow_last(shadow);
+        if (last == null)
+            return null;
+        else if (last.item.next == null)
+            return null;
+        else
+            return structure.shadowsByNode.get(last.item.next.node);
+    }
+
+    function firstTextDescendant(node)
+    {
+        if (node.nodeType == Node.TEXT_NODE)
+            return node;
+        for (var child = node.firstChild; child != null; child = child.nextSibling) {
+            var result = firstTextDescendant(child);
+            if (result != null)
+                return result;
+        }
+        return null;
+    }
+
+    function Structure()
+    {
+        this.toplevelSections = new Array();
+        this.toplevelFigures = new Array();
+        this.toplevelTables = new Array();
+        this.shadowsByNode = new NodeMap();
+    }
+
+    function discoverStructure()
+    {
+        var structure = new Structure();
+        var nextToplevelSectionNumber = 1;
+        var nextFigureNumber = 1;
+        var nextTableNumber = 1;
+        var headingNumbering = Styles_headingNumbering();
+
+        var counters = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0, table: 0, figure: 0 };
+
+        var current = null;
+
+        for (var section = sections.list.first; section != null; section = section.next) {
+            structure.shadowsByNode.put(section.node,new Shadow(section.node));
+        }
+        for (var figure = figures.list.first; figure != null; figure = figure.next) {
+            structure.shadowsByNode.put(figure.node,new Shadow(figure.node));
+        }
+        for (var table = tables.list.first; table != null; table = table.next) {
+            structure.shadowsByNode.put(table.node,new Shadow(table.node));
+        }
+
+        for (var section = sections.list.first; section != null; section = section.next) {
+            var shadow = structure.shadowsByNode.get(section.node);
+            shadow.parent = null;
+            shadow.children = [];
+            shadow.nextChildSectionNumber = 1;
+        }
+
+        ignoreModifications++;
+
+        for (var section = sections.list.first; section != null; section = section.next) {
+            var shadow = structure.shadowsByNode.get(section.node);
+            var node = section.node;
+            var item = shadow.item;
+
+            if (!headingNumbering || (DOM_getAttribute(item.node,"class") == "Unnumbered")) {
+                item.computedNumber = null;
+            }
+            else {
+                var level = parseInt(node.nodeName.charAt(1));
+                counters[node.nodeName.toLowerCase()]++;
+                for (var inner = level+1; inner <= 6; inner++)
+                    counters["h"+inner] = 0;
+                item.computedNumber = "";
+                for (var i = 1; i <= level; i++) {
+                    if (i == 1)
+                        item.computedNumber += counters["h"+i];
+                    else
+                        item.computedNumber += "." + counters["h"+i];
+                }
+            }
+
+            while ((current != null) && (shadow.level < current.level+1))
+                current = current.parent;
+
+            shadow.parent = current;
+            if (current == null)
+                structure.toplevelSections.push(shadow);
+            else
+                current.children.push(shadow);
+
+            current = shadow;
+        }
+
+        for (var figure = figures.list.first; figure != null; figure = figure.next) {
+            var shadow = structure.shadowsByNode.get(figure.node);
+            var item = shadow.item;
+
+            var titleNode = OutlineItem_getTitleNode(item,false);
+            if ((titleNode == null) || DOM_getAttribute(titleNode,"class") == "Unnumbered") {
+                item.computedNumber = null;
+            }
+            else {
+                counters.figure++;
+                item.computedNumber = ""+counters.figure;
+            }
+
+            structure.toplevelFigures.push(shadow);
+        }
+
+        for (var table = tables.list.first; table != null; table = table.next) {
+            var shadow = structure.shadowsByNode.get(table.node);
+            var item = shadow.item;
+
+            var titleNode = OutlineItem_getTitleNode(item,false);
+            if ((titleNode == null) || DOM_getAttribute(titleNode,"class") == "Unnumbered") {
+                item.computedNumber = null;
+            }
+            else {
+                counters.table++;
+                item.computedNumber = ""+counters.table;
+            }
+
+            structure.toplevelTables.push(shadow);
+        }
+
+        ignoreModifications--;
+
+        return structure;
+    }
+
+    function updateStructureReal(pageNumbers)
+    {
+        var structure = discoverStructure();
+
+        for (var section = sections.list.first; section != null; section = section.next) {
+            var shadow = structure.shadowsByNode.get(section.node);
+            updateRefsForItem(shadow.item);
+        }
+
+        for (var figure = figures.list.first; figure != null; figure = figure.next) {
+            var shadow = structure.shadowsByNode.get(figure.node);
+            updateRefsForItem(shadow.item);
+        }
+
+        for (var table = tables.list.first; table != null; table = table.next) {
+            var shadow = structure.shadowsByNode.get(table.node);
+            updateRefsForItem(shadow.item);
+        }
+
+        sections.tocs.forEach(function (node,toc) {
+            TOC_updateStructure(toc,structure,structure.toplevelSections,pageNumbers);
+        });
+        figures.tocs.forEach(function (node,toc) {
+            TOC_updateStructure(toc,structure,structure.toplevelFigures,pageNumbers);
+        });
+        tables.tocs.forEach(function (node,toc) {
+            TOC_updateStructure(toc,structure,structure.toplevelTables,pageNumbers);
+        });
+
+        Editor_outlineUpdated();
+    }
+
+    Outline_getOutline = function()
+    {
+        var structure = discoverStructure();
+        var encSections = new Array();
+        var encFigures = new Array();
+        var encTables = new Array();
+
+        for (var i = 0; i < structure.toplevelSections.length; i++)
+            encodeShadow(structure.toplevelSections[i],encSections);
+        for (var i = 0; i < structure.toplevelFigures.length; i++)
+            encodeShadow(structure.toplevelFigures[i],encFigures);
+        for (var i = 0; i < structure.toplevelTables.length; i++)
+            encodeShadow(structure.toplevelTables[i],encTables);
+
+        return { sections: encSections,
+                 figures: encFigures,
+                 tables: encTables };
+
+        function encodeShadow(shadow,result)
+        {
+            var encChildren = new Array();
+            for (var i = 0; i < shadow.children.length; i++)
+                encodeShadow(shadow.children[i],encChildren);
+
+            var obj = { id: shadow.item.id,
+                        number: shadow.item.computedNumber ? shadow.item.computedNumber : "",
+                        children: encChildren };
+            result.push(obj);
+        }
+    }
+
+    function updateRefsForItem(item)
+    {
+        var id = item.node.getAttribute("id");
+        var refs = refsById[id];
+        if (refs == null)
+            return;
+        for (var i = 0; i < refs.length; i++) {
+            DOM_deleteAllChildren(refs[i]);
+            var text = null;
+
+            var className = DOM_getAttribute(refs[i],"class");
+            if (className == "uxwrite-ref-num") {
+                text = item.computedNumber;
+            }
+            else if (className == "uxwrite-ref-text") {
+                if (item.type == "section") {
+                    if (item.numberSpan != null)
+                        text = getNodeTextAfter(item.numberSpan);
+                    else
+                        text = normalizeWhitespace(getNodeText(item.node));
+                }
+                else if ((item.type == "figure") || (item.type == "table")) {
+                    var titleNode = OutlineItem_getTitleNode(item,false);
+                    if (titleNode != null) {
+                        text = getNodeText(titleNode);
+
+                        if ((item.computedNumber != null) && (item.type == "figure"))
+                            text = "Figure "+item.computedNumber+": "+text;
+                        else if ((item.computedNumber != null) && (item.type == "table"))
+                            text = "Table "+item.computedNumber+": "+text;
+                    }
+                }
+            }
+            else if (className == "uxwrite-ref-caption-text") {
+                if (item.type == "section") {
+                    if (item.numberSpan != null)
+                        text = getNodeTextAfter(item.numberSpan);
+                    else
+                        text = normalizeWhitespace(getNodeText(item.node));
+                }
+                else if ((item.type == "figure") || (item.type == "table")) {
+                    var titleNode = OutlineItem_getTitleNode(item,false);
+                    if (titleNode != null) {
+                        if (item.numberSpan != null)
+                            text = getNodeTextAfter(item.numberSpan);
+                        else
+                            text = normalizeWhitespace(getNodeText(titleNode));
+                    }
+                }
+            }
+            else if (className == "uxwrite-ref-label-num") {
+                if (item.computedNumber != null) {
+                    if (item.type == "section")
+                        text = "Section "+item.computedNumber;
+                    else if (item.type == "figure")
+                        text = "Figure "+item.computedNumber;
+                    else if (item.type == "table")
+                        text = "Table "+item.computedNumber;
+                }
+            }
+            else {
+                if (item.computedNumber != null)
+                    text = item.computedNumber;
+                else
+                    text = item.title;
+            }
+
+            if (text == null)
+                text = "?";
+
+            DOM_appendChild(refs[i],DOM_createTextNode(document,text));
+        }
+    }
+
+    Outline_plainText = function()
+    {
+        var strings = new Array();
+        var structure = discoverStructure();
+
+        strings.push("Sections:\n");
+        for (var section = sections.list.first; section != null; section = section.next) {
+            var shadow = structure.shadowsByNode.get(section.node);
+            if (shadow.level == 1)
+                printSectionRecursive(shadow,"    ");
+        }
+        strings.push("Figures:\n");
+        for (var figure = figures.list.first; figure != null; figure = figure.next) {
+            var shadow = structure.shadowsByNode.get(figure.node);
+            var titleNode = OutlineItem_getTitleNode(figure,false);
+            var title = titleNode ? getNodeText(titleNode) : "[no caption]";
+            if (shadow.item.computedNumber != null) {
+                if (title.length > 0)
+                    title = shadow.item.computedNumber+" "+title;
+                else
+                    title = shadow.item.computedNumber;
+            }
+            strings.push("    "+title+" ("+figure.id+")\n");
+        }
+        strings.push("Tables:\n");
+        for (var table = tables.list.first; table != null; table = table.next) {
+            var shadow = structure.shadowsByNode.get(table.node);
+            var titleNode = OutlineItem_getTitleNode(table,false);
+            var title = titleNode ? getNodeText(titleNode) : "[no caption]";
+            if (shadow.item.computedNumber != null) {
+                if (title.length > 0)
+                    title = shadow.item.computedNumber+" "+title;
+                else
+                    title = shadow.item.computedNumber;
+            }
+            strings.push("    "+title+" ("+table.id+")\n");
+        }
+        return strings.join("");
+
+        function printSectionRecursive(shadow,indent)
+        {
+            var titleNode = OutlineItem_getTitleNode(shadow.item,false);
+            var content = getNodeText(titleNode);
+            if (shadow.item.computedNumber != null)
+                content = shadow.item.computedNumber+" "+content;
+            if (isWhitespaceString(content))
+                content = "[empty]";
+            strings.push(indent+content+" ("+shadow.item.id+")\n");
+            for (var i = 0; i < shadow.children.length; i++)
+                printSectionRecursive(shadow.children[i],indent+"    ");
+        }
+    }
+
+    // public
+    Outline_init = function()
+    {
+        Selection_preserveWhileExecuting(function() {
+
+            function isTableNode(node)
+            {
+                return (node._type == HTML_TABLE);
+            }
+
+            function isFigureNode(node)
+            {
+                return (node._type == HTML_FIGURE);
+            }
+
+            function isNonTOCHeadingNode(node)
+            {
+                return (HEADING_ELEMENTS[node._type] && !isInTOC(node));
+            }
+
+            sections = new Category("section",isNonTOCHeadingNode,sectionNumberRegex);
+            figures = new Category("figure",isFigureNode,figureNumberRegex);
+            tables = new Category("table",isTableNode,tableNumberRegex);
+            itemsByNode = new NodeMap();
+            refsById = new Object();
+
+            DOM_ensureUniqueIds(document.documentElement);
+            document.addEventListener("DOMNodeInserted",docNodeInserted);
+            document.addEventListener("DOMNodeRemoved",docNodeRemoved);
+
+            docNodeInserted({target:document});
+        });
+        doneInit = true;
+    }
+
+    // public (for the undo tests, when they report results)
+    Outline_removeListeners = function()
+    {
+        document.removeEventListener("DOMNodeInserted",docNodeInserted);
+        document.removeEventListener("DOMNodeRemoved",docNodeRemoved);
+
+        removeCategoryListeners(sections);
+        removeCategoryListeners(figures);
+        removeCategoryListeners(tables);
+
+        function removeCategoryListeners(category)
+        {
+            for (var item = category.list.first; item != null; item = item.next)
+                item.node.removeEventListener("DOMSubtreeModified",item.modificationListener);
+        }
+    }
+
+    // private
+    function getShadowNodes(structure,shadow,result)
+    {
+        var endShadow = Shadow_outerNext(shadow,structure);
+        var endNode = endShadow ? endShadow.item.node : null;
+        for (var n = shadow.item.node; (n != null) && (n != endNode); n = n.nextSibling)
+            result.push(n);
+    }
+
+    // public
+    Outline_moveSection = function(sectionId,parentId,nextId)
+    {
+        UndoManager_newGroup("Move section");
+        Selection_clear();
+
+        updateStructure(); // make sure pointers are valid
+        // FIXME: I don't think we'll need the updateStructure() call now that we have
+        // discoverStructure(). In fact this function is a perfect illustration of why
+        // waiting till after the postponed action has been performed before relying on the
+        // pointer validity was a problem.
+
+
+        var structure = discoverStructure();
+
+        var node = document.getElementById(sectionId);
+        var section = itemsByNode.get(node);
+        var shadow = structure.shadowsByNode.get(node);
+
+        // FIXME: We should throw an exception if a parentId or nextId which does not exist
+        // in the document is specified. However there are currently some tests (like
+        // moveSection-nested*) which rely us interpreting such parameters as null.
+        var parentNode = parentId ? document.getElementById(parentId) : null;
+        var nextNode = nextId ? document.getElementById(nextId) : null;
+        var parent = parentNode ? structure.shadowsByNode.get(parentNode) : null;
+        var next = nextNode ? structure.shadowsByNode.get(nextNode) : null;
+
+        var sectionNodes = new Array();
+        getShadowNodes(structure,shadow,sectionNodes);
+
+        if ((next == null) && (parent != null))
+            next = Shadow_outerNext(parent,structure);
+
+        if (next == null) {
+            for (var i = 0; i < sectionNodes.length; i++)
+                DOM_appendChild(document.body,sectionNodes[i]);
+        }
+        else {
+            for (var i = 0; i < sectionNodes.length; i++)
+                DOM_insertBefore(next.item.node.parentNode,sectionNodes[i],next.item.node);
+        }
+
+        var pos = new Position(node,0,node,0);
+        pos = Position_closestMatchForwards(pos,Position_okForInsertion);
+        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
+
+        scheduleUpdateStructure();
+        PostponedActions_add(UndoManager_newGroup);
+    }
+
+    // public
+    Outline_deleteItem = function(itemId)
+    {
+        UndoManager_newGroup("Delete outline item");
+        var structure = discoverStructure();
+        Selection_preserveWhileExecuting(function() {
+            var node = document.getElementById(itemId);
+            var item = itemsByNode.get(node);
+            var shadow = structure.shadowsByNode.get(item.node);
+            if (item.type == "section") {
+                var sectionNodes = new Array();
+                getShadowNodes(structure,shadow,sectionNodes);
+                for (var i = 0; i < sectionNodes.length; i++)
+                    DOM_deleteNode(sectionNodes[i]);
+            }
+            else {
+                DOM_deleteNode(item.node);
+            }
+        });
+
+        // Ensure the cursor or selection start/end positions are valid positions that the
+        // user is allowed to move to. This ensures we get an accurate rect for each position,
+        // avoiding an ugly effect where the cursor occupies the entire height of the document
+        // and is displayed on the far-left edge of the editing area.
+        var selRange = Selection_get();
+        if (selRange != null) {
+            var start = Position_closestMatchForwards(selRange.start,Position_okForMovement);
+            var end = Position_closestMatchForwards(selRange.end,Position_okForMovement);
+            Selection_set(start.node,start.offset,end.node,end.offset);
+        }
+
+        scheduleUpdateStructure();
+        PostponedActions_add(Cursor_ensureCursorVisible);
+        PostponedActions_add(UndoManager_newGroup);
+    }
+
+    // public
+    Outline_goToItem = function(itemId)
+    {
+        if (itemId == null) {
+            window.scrollTo(0);
+        }
+        else {
+            var node = document.getElementById(itemId);
+            if (node == null) {
+                // FIXME: this can happen if the user added some headings, pressed undo one or
+                // more times (in which case the editor's view of the outline structure fails to
+                // be updated), and then they click on an item. This is really an error but we
+                // handle it gracefully for now rather than causing a null pointer exception to
+                // be thrown.
+                return;
+            }
+            var position = new Position(node,0);
+            position = Position_closestMatchForwards(position,Position_okForMovement);
+            Selection_set(position.node,position.offset,position.node,position.offset);
+
+            var section = document.getElementById(itemId);
+            var location = webkitConvertPointFromNodeToPage(section,new WebKitPoint(0,0));
+            window.scrollTo(0,location.y);
+        }
+    }
+
+    // public
+    Outline_getItemElement = function(itemId)
+    {
+        return document.getElementById(itemId);
+    }
+
+    // public
+    Outline_setNumbered = function(itemId,numbered)
+    {
+        var node = document.getElementById(itemId);
+        var item = itemsByNode.get(node);
+
+        Selection_preserveWhileExecuting(function() {
+            if (item.type == "section") {
+                if (numbered)
+                    DOM_removeAttribute(node,"class");
+                else
+                    DOM_setAttribute(node,"class","Unnumbered");
+            }
+            else if ((item.type == "figure") || (item.type == "table")) {
+                if (numbered) {
+                    var caption = OutlineItem_getTitleNode(item,true);
+                    DOM_removeAttribute(caption,"class");
+                }
+                else {
+                    var caption = OutlineItem_getTitleNode(item,false);
+                    if (caption != null) {
+                        if (nodeHasContent(caption))
+                            DOM_setAttribute(caption,"class","Unnumbered");
+                        else
+                            DOM_deleteNode(caption);
+                    }
+                }
+            }
+        });
+
+        scheduleUpdateStructure();
+    }
+
+    // public
+    Outline_setTitle = function(itemId,title)
+    {
+        var node = document.getElementById(itemId);
+        var item = itemsByNode.get(node);
+        Selection_preserveWhileExecuting(function() {
+            var titleNode = OutlineItem_getTitleNode(item,true);
+            var oldEmpty = (item.title == "");
+            var newEmpty = (title == "");
+            if (oldEmpty != newEmpty) {
+                // Add or remove the : at the end of table and figure numbers
+                scheduleUpdateStructure();
+            }
+            if (item.numberSpan != null) {
+                while (item.numberSpan.nextSibling != null)
+                    DOM_deleteNode(item.numberSpan.nextSibling);
+            }
+            else {
+                DOM_deleteAllChildren(titleNode);
+            }
+            DOM_appendChild(titleNode,DOM_createTextNode(document,title));
+            OutlineItem_updateItemTitle(item);
+        });
+    }
+
+    // private
+    // FIXME: prevent a TOC from being inserted inside a heading, figure, or table
+    function insertTOC(key,initialText)
+    {
+        var div = DOM_createElement(document,"NAV");
+        DOM_setAttribute(div,"class",key);
+        Cursor_makeContainerInsertionPoint();
+        Clipboard_pasteNodes([div]);
+    }
+
+    // public
+    Outline_insertTableOfContents = function()
+    {
+        insertTOC(Keys.SECTION_TOC);
+    }
+
+    // public
+    Outline_insertListOfFigures = function()
+    {
+        insertTOC(Keys.FIGURE_TOC);
+    }
+
+    // public
+    Outline_insertListOfTables = function()
+    {
+        insertTOC(Keys.TABLE_TOC);
+    }
+
+    // public
+    Outline_setPrintMode = function(newPrintMode)
+    {
+        printMode = newPrintMode;
+        scheduleUpdateStructure();
+    }
+
+    // public
+    Outline_examinePrintLayout = function(pageHeight)
+    {
+        var result = new Object();
+        var structure = discoverStructure();
+        var pageNumbers = new NodeMap();
+
+        result.destsByPage = new Object();
+        result.linksByPage = new Object();
+        result.leafRectsByPage = new Object();
+
+        itemsByNode.forEach(function(node,item) {
+            var rect = node.getBoundingClientRect();
+            var pageNo = 1+Math.floor(rect.top/pageHeight);
+            var pageTop = (pageNo-1)*pageHeight;
+            var id = node.getAttribute("id");
+            pageNumbers.put(node,pageNo);
+
+            if (result.destsByPage[pageNo] == null)
+                result.destsByPage[pageNo] = new Array();
+            result.destsByPage[pageNo].push({ itemId: id,
+                                              x: rect.left,
+                                              y: rect.top - pageTop});
+        });
+
+        var links = document.getElementsByTagName("A");
+        for (var i = 0; i < links.length; i++) {
+            var a = links[i];
+
+            if (!a.hasAttribute("href"))
+                continue;
+
+            var offset = DOM_nodeOffset(a);
+            var range = new Range(a.parentNode,offset,a.parentNode,offset+1);
+            var rects = Range_getClientRects(range);
+            for (var rectIndex = 0; rectIndex < rects.length; rectIndex++) {
+                var rect = rects[rectIndex];
+                var pageNo = 1+Math.floor(rect.top/pageHeight);
+                var pageTop = (pageNo-1)*pageHeight;
+
+                if (result.linksByPage[pageNo] == null)
+                    result.linksByPage[pageNo] = new Array();
+                result.linksByPage[pageNo].push({ pageNo: pageNo,
+                                                  left: rect.left,
+                                                  top: rect.top - pageTop,
+                                                  width: rect.width,
+                                                  height: rect.height,
+                                                  href: a.getAttribute("href"), });
+            }
+        }
+
+        recurse(document.body);
+
+        updateStructureReal(pageNumbers);
+        return result;
+
+
+        function recurse(node)
+        {
+            if (node.firstChild == null) {
+                var offset = DOM_nodeOffset(node);
+                var range = new Range(node.parentNode,offset,node.parentNode,offset+1);
+                var rects = Range_getClientRects(range);
+                for (var i = 0; i < rects.length; i++) {
+                    var rect = rects[i];
+
+                    var pageNo = 1+Math.floor(rect.top/pageHeight);
+                    var pageTop = (pageNo-1)*pageHeight;
+
+                    if (result.leafRectsByPage[pageNo] == null)
+                        result.leafRectsByPage[pageNo] = new Array();
+                    result.leafRectsByPage[pageNo].push({ left: rect.left,
+                                                          top: rect.top - pageTop,
+                                                          width: rect.width,
+                                                          height: rect.height });
+                }
+            }
+
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+    Outline_setReferenceTarget = function(node,itemId)
+    {
+        Selection_preserveWhileExecuting(function() {
+            refRemoved(node);
+            DOM_setAttribute(node,"href","#"+itemId);
+            refInserted(node);
+        });
+    }
+
+    Outline_detectSectionNumbering = function()
+    {
+        var sectionNumbering = detectNumbering(sections);
+        if (sectionNumbering)
+            makeNumberingExplicit(sections);
+        makeNumberingExplicit(figures);
+        makeNumberingExplicit(tables);
+        return sectionNumbering;
+    }
+
+    function detectNumbering(category)
+    {
+        for (var item = category.list.first; item != null; item = item.next) {
+
+            var firstText = null;
+            var titleNode = OutlineItem_getTitleNode(item);
+
+            if (titleNode != null)
+                firstText = findFirstTextDescendant(titleNode);
+            if (firstText != null) {
+                var regex = category.numberRegex;
+                var str = firstText.nodeValue;
+                if (str.match(category.numberRegex))
+                    return true;
+            }
+        }
+    }
+
+    function makeNumberingExplicit(category)
+    {
+        for (var item = category.list.first; item != null; item = item.next) {
+            var firstText = null;
+            var titleNode = OutlineItem_getTitleNode(item);
+
+            if (titleNode != null)
+                firstText = findFirstTextDescendant(titleNode);
+            if (firstText != null) {
+                var regex = category.numberRegex;
+                var str = firstText.nodeValue;
+                if (str.match(category.numberRegex)) {
+                    var oldValue = str;
+                    var newValue = str.replace(category.numberRegex,"");
+                    DOM_setNodeValue(firstText,newValue);
+                }
+                else {
+                    var titleNode = OutlineItem_getTitleNode(item,true);
+                    if (titleNode != null)
+                        DOM_setAttribute(titleNode,"class","Unnumbered");
+                }
+            }
+        }
+    }
+
+    // Search through the document for any elements corresponding to built-in styles that are
+    // normally latent (i.e. only included in the stylesheet if used)
+    Outline_findUsedStyles = function()
+    {
+        var used = new Object();
+        recurse(document.body);
+        return used;
+
+        function recurse(node)
+        {
+            switch (node._type) {
+            case HTML_NAV: {
+                var className = DOM_getAttribute(node,"class");
+                if ((className == "tableofcontents") ||
+                    (className == "listoffigures") ||
+                    (className == "listoftables")) {
+                    used["nav."+className] = true;
+                }
+                break;
+            }
+            case HTML_FIGCAPTION:
+            case HTML_CAPTION:
+            case HTML_H1:
+            case HTML_H2:
+            case HTML_H3:
+            case HTML_H4:
+            case HTML_H5:
+            case HTML_H6: {
+                var elementName = node.nodeName.toLowerCase();
+                var className = DOM_getAttribute(node,"class");
+                if ((className == null) || (className == ""))
+                    used[elementName] = true;
+                else if (className == "Unnumbered")
+                    used[elementName+".Unnumbered"] = true;
+                break;
+            }
+            }
+
+            for (var child = node.firstChild; child != null; child = child.nextSibling)
+                recurse(child);
+        }
+    }
+
+})();


[14/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Clipboard.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Clipboard.js b/experiments/editorFramework/src/Layer0_Javascript/Clipboard.js
deleted file mode 100644
index 03efdcc..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Clipboard.js
+++ /dev/null
@@ -1,757 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Markdown_htmlToMarkdown;
-var Clipboard_htmlToText;
-var Clipboard_cut;
-var Clipboard_copy;
-var Clipboard_pasteText;
-var Clipboard_pasteHTML;
-var Clipboard_pasteNodes;
-
-(function() {
-
-    // private
-    function blockToText(md,node,indent,nextIndent,listType,listNo)
-    {
-        var linesBetweenChildren = 1;
-        var childIndent = indent;
-        switch (node._type) {
-        case HTML_LI:
-            if (listType == "OL") {
-                var listMarker;
-                if (listNo.value < 10)
-                    listMarker = listNo.value+".  ";
-                else
-                    listMarker = listNo.value+". ";
-                beginParagraph(md,0,indent,nextIndent,listMarker);
-                nextIndent += "    ";
-            }
-            else {
-                beginParagraph(md,0,indent,nextIndent,"  - ");
-                nextIndent += "    ";
-            }
-            listNo.value++;
-            break;
-        case HTML_UL:
-            listType = "UL";
-            listNo = { value: 1 };
-            beginParagraph(md,1,indent,nextIndent);
-            linesBetweenChildren = 0;
-            break;
-        case HTML_OL:
-            listType = "OL";
-            listNo = { value: 1 };
-            beginParagraph(md,1,indent,nextIndent);
-            linesBetweenChildren = 0;
-            break;
-        case HTML_H1:
-            beginParagraph(md,1,indent,nextIndent,"# "," #");
-            break;
-        case HTML_H2:
-            beginParagraph(md,1,indent,nextIndent,"## "," ##");
-            break;
-        case HTML_H3:
-            beginParagraph(md,1,indent,nextIndent,"### "," ###");
-            break;
-        case HTML_H4:
-            beginParagraph(md,1,indent,nextIndent,"#### "," ####");
-            break;
-        case HTML_H5:
-            beginParagraph(md,1,indent,nextIndent,"##### "," #####");
-            break;
-        case HTML_H6:
-            beginParagraph(md,1,indent,nextIndent,"###### "," ######");
-            break;
-        case HTML_BLOCKQUOTE:
-            beginParagraph(md,1,indent,nextIndent,"> ");
-            nextIndent += "> ";
-            break;
-        case HTML_PRE:
-            md.preDepth++;
-            break;
-        }
-
-        var foundNonWhitespaceChild = false;
-        for (var child = node.firstChild; child != null; child = child.nextSibling) {
-            if (isContainerNode(child) || isParagraphNode(child)) {
-                beginParagraph(md,linesBetweenChildren,indent,nextIndent);
-                blockToText(md,child,indent,nextIndent,listType,listNo);
-                beginParagraph(md,linesBetweenChildren);
-                indent = nextIndent;
-                foundNonWhitespaceChild = false;
-            }
-            else {
-                if (!foundNonWhitespaceChild) {
-                    if (isWhitespaceTextNode(child))
-                        continue;
-                    beginParagraph(md,0,indent,nextIndent);
-                    indent = nextIndent;
-                    foundNonWhitespaceChild = true;
-                }
-
-                inlineToText(md,child);
-            }
-        }
-
-        if (node._type == HTML_PRE)
-            md.preDepth--;
-    }
-
-    // private
-    function shipOutParagraph(md)
-    {
-        var text = md.buildParagraph.join("");
-        if (md.buildPre) {
-            text = text.replace(/\n$/,"");
-            text = "    "+text.replace(/\n/g,"\n"+md.nextIndent+"    ");
-        }
-        else {
-            text = normalizeWhitespace(text);
-        }
-        if (md.allText.length > 0) {
-            for (var i = 0; i < md.buildLines; i++)
-                md.allText.push("\n");
-        }
-        md.allText.push(md.indent+md.buildPrefix+text+md.buildSuffix+"\n");
-        resetBuild(md);
-    }
-
-    // private
-    function beginParagraph(md,blankLines,indent,nextIndent,paraPrefix,paraSuffix)
-    {
-        if (blankLines == null)
-            blankLines = 1;
-        if (indent == null)
-            indent = "";
-        if (nextIndent == null)
-            nextIndent = "";
-        if (paraPrefix == null)
-            paraPrefix = "";
-        if (paraSuffix == null)
-            paraSuffix = "";
-
-        if (md == null)
-            throw new Error("beginParagraph: md is null");
-        if (md.buildParagraph == null)
-            throw new Error("beginParagraph: md.buildParagraph is null");
-
-        if (md.buildParagraph.length > 0) {
-            shipOutParagraph(md);
-        }
-
-        if (md.buildLines < blankLines)
-            md.buildLines = blankLines;
-        if (md.indent.length < indent.length)
-            md.indent = indent;
-        if (md.nextIndent.length < nextIndent.length)
-            md.nextIndent = nextIndent;
-        md.buildPrefix += paraPrefix;
-        md.buildSuffix = paraSuffix + md.buildSuffix;
-        if (md.preDepth > 0)
-            md.buildPre = true;
-    }
-
-    // private
-    function inlineToText(md,node)
-    {
-        switch (node._type) {
-        case HTML_TEXT: {
-            var text = node.nodeValue;
-            if (md.preDepth == 0) {
-                text = text.replace(/\\/g,"\\\\");
-                text = text.replace(/\*/g,"\\*");
-                text = text.replace(/\[/g,"\\[");
-                text = text.replace(/\]/g,"\\]");
-            }
-            md.buildParagraph.push(text);
-            break;
-        }
-        case HTML_I:
-        case HTML_EM:
-            md.buildParagraph.push("*");
-            processChildren();
-            md.buildParagraph.push("*");
-            break;
-        case HTML_B:
-        case HTML_STRONG:
-            md.buildParagraph.push("**");
-            processChildren();
-            md.buildParagraph.push("**");
-            break;
-        case HTML_A:
-            if (node.hasAttribute("href")) {
-                md.buildParagraph.push("[");
-                processChildren();
-                md.buildParagraph.push("]("+node.getAttribute("href")+")");
-            }
-            break;
-        default:
-            processChildren();
-            break;
-        }
-
-        function processChildren()
-        {
-            for (var child = node.firstChild; child != null; child = child.nextSibling) {
-                inlineToText(md,child);
-            }
-        }
-    }
-
-    // private
-    function resetBuild(md)
-    {
-        md.buildParagraph = new Array();
-        md.buildLines = 0;
-        md.buildPrefix = "";
-        md.buildSuffix = "";
-        md.buildPre = false;
-        md.indent = "";
-        md.nextIndent = "";
-    }
-
-    // private
-    function MarkdownBuilder()
-    {
-    }
-
-    // public
-    Markdown_htmlToMarkdown = function(node)
-    {
-        var md = new MarkdownBuilder();
-        md.allText = new Array();
-        md.preDepth = 0;
-        resetBuild(md);
-
-        if (isContainerNode(node) || isParagraphNode(node)) {
-            blockToText(md,node,"","","UL",{value: 1});
-            beginParagraph(md);
-            return md.allText.join("");
-        }
-        else {
-            inlineToText(md,node);
-            return normalizeWhitespace(md.buildParagraph.join(""));
-        }
-    }
-
-})();
-
-(function() {
-
-    function expandRangeForCopy(range)
-    {
-        if (range == null)
-            return range;
-
-        var startInLI = null;
-        for (var node = range.start.node; node != null; node = node.parentNode) {
-            if (node._type == HTML_LI)
-                startInLI = node;
-        }
-
-        var endInLI = null;
-        for (var node = range.end.node; node != null; node = node.parentNode) {
-            if (node._type == HTML_LI)
-                endInLI = node;
-        }
-
-        if ((startInLI != null) && (startInLI == endInLI)) {
-            var beforeRange = new Range(startInLI,0,
-                                        range.start.node,range.start.offset);
-            var afterRange = new Range(range.end.node,range.end.offset,
-                                       endInLI,DOM_maxChildOffset(endInLI));
-            var contentBefore = Range_hasContent(beforeRange);
-            var contentAfter = Range_hasContent(afterRange);
-
-            if (!contentBefore && !contentAfter) {
-                var li = startInLI;
-                var offset = DOM_nodeOffset(li);
-                range = new Range(li.parentNode,offset,li.parentNode,offset+1);
-            }
-        }
-        return range;
-    }
-
-    function copyRange(range)
-    {
-        var html = "";
-        var text = "";
-
-        if (range != null) {
-            var nodes;
-            var region = Tables_regionFromRange(range);
-            if (region != null) {
-                nodes = [Tables_cloneRegion(region)];
-            }
-            else {
-                nodes = Range_cloneContents(range);
-            };
-
-            var div = DOM_createElement(document,"DIV");
-            for (var i = 0; i < nodes.length; i++)
-                DOM_appendChild(div,nodes[i]);
-            Main_removeSpecial(div);
-
-            html = div.innerHTML;
-            text = Clipboard_htmlToText(div);
-        }
-
-        return { "text/html": html,
-                 "text/plain": text };
-    }
-
-    // public (FIXME: temp: for testing)
-    Clipboard_htmlToText = function(node)
-    {
-        return Markdown_htmlToMarkdown(node);
-    }
-
-    // public
-    Clipboard_cut = function()
-    {
-        UndoManager_newGroup("Cut");
-        var content;
-
-        var range = Selection_get();
-        range = expandRangeForCopy(range);
-        content = copyRange(range);
-
-        Selection_set(range.start.node,range.start.offset,range.end.node,range.end.offset);
-        Selection_deleteContents(false);
-        var selRange = Selection_get();
-        if (selRange != null) {
-            Range_trackWhileExecuting(selRange,function() {
-                var node = Position_closestActualNode(selRange.start);
-                while (node != null) {
-                    var parent = node.parentNode;
-                    switch (node._type) {
-                    case HTML_LI:
-                        if (!nodeHasContent(node))
-                            DOM_deleteNode(node);
-                        break;
-                    case HTML_UL:
-                    case HTML_OL: {
-                        var haveLI = false;
-                        for (var c = node.firstChild; c != null; c = c.nextSibling) {
-                            if (c._type == HTML_LI) {
-                                haveLI = true;
-                                break;
-                            }
-                        }
-                        if (!haveLI)
-                            DOM_deleteNode(node);
-                        break;
-                    }
-                    }
-                    node = parent;
-                }
-            });
-
-            var pos = Position_closestMatchForwards(selRange.start,Position_okForMovement);
-            Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-        }
-
-        Cursor_ensureCursorVisible();
-
-        PostponedActions_perform(UndoManager_newGroup);
-        return content;
-    }
-
-    // public
-    Clipboard_copy = function()
-    {
-        var range = Selection_get();
-        range = expandRangeForCopy(range);
-        return copyRange(range);
-    }
-
-    // public
-    Clipboard_pasteText = function(text)
-    {
-        var converter = new Showdown.converter();
-        var html = converter.makeHtml(text);
-        UndoManager_newGroup("Paste");
-        Clipboard_pasteHTML(html);
-        UndoManager_newGroup();
-    }
-
-    // public
-    Clipboard_pasteHTML = function(html)
-    {
-        if (html.match(/^\s*<thead/i))
-            html = "<table>" + html + "</table>";
-        else if (html.match(/^\s*<tbody/i))
-            html = "<table>" + html + "</table>";
-        else if (html.match(/^\s*<tfoot/i))
-            html = "<table>" + html + "</table>";
-        else if (html.match(/^\s*<tr/i))
-            html = "<table>" + html + "</table>";
-        else if (html.match(/^\s*<td/i))
-            html = "<table><tr>" + html + "</tr></table>";
-        else if (html.match(/^\s*<th/i))
-            html = "<table><tr>" + html + "</tr></table>";
-        else if (html.match(/^\s*<li/i))
-            html = "<ul>" + html + "</ul>";
-
-        var div = DOM_createElement(document,"DIV");
-        div.innerHTML = html;
-        for (var child = div.firstChild; child != null; child = child.nextSibling)
-            DOM_assignNodeIds(child);
-
-        var nodes = new Array();
-        for (var child = div.firstChild; child != null; child = child.nextSibling)
-            nodes.push(child);
-
-        UndoManager_newGroup("Paste");
-        var region = Tables_regionFromRange(Selection_get(),true);
-        if ((region != null) && (nodes.length == 1) && (nodes[0]._type == HTML_TABLE))
-            pasteTable(nodes[0],region);
-        else
-            Clipboard_pasteNodes(nodes);
-        UndoManager_newGroup();
-    }
-
-    function pasteTable(srcTable,dest)
-    {
-        var src = Tables_analyseStructure(srcTable);
-
-        // In the destination table, the region into which we will paste the cells will the
-        // the same size as that of the source table, regardless of how many rows and columns
-        // were selected - i.e. we only pay attention to the top-left most cell, ignoring
-        // whatever the bottom-right is set to
-        dest.bottom = dest.top + src.numRows - 1;
-        dest.right = dest.left + src.numCols - 1;
-
-        // Make sure the destination table is big enough to hold all the cells we want to paste.
-        // This will add rows and columns as appropriate, with empty cells that only contain a
-        // <p><br></p> (to ensure they have non-zero height)
-        if (dest.structure.numRows < dest.bottom + 1)
-            dest.structure.numRows = dest.bottom + 1;
-        if (dest.structure.numCols < dest.right + 1)
-            dest.structure.numCols = dest.right + 1;
-        dest.structure = Table_fix(dest.structure);
-
-        // To simplify the paste, split any merged cells that are in the region of the destination
-        // table we're pasting into. We have to re-analyse the table structure after this to
-        // get the correct cell array.
-        TableRegion_splitCells(dest);
-        dest.structure = Tables_analyseStructure(dest.structure.element);
-
-        // Do the actual paste
-        Selection_preserveWhileExecuting(function() {
-            replaceCells(src,dest.structure,dest.top,dest.left);
-        });
-
-        // If any new columns were added, calculate a width for them
-        Table_fixColumnWidths(dest.structure);
-
-        // Remove duplicate ids
-        var found = new Object();
-        removeDuplicateIds(dest.structure.element,found);
-
-        // Place the cursor in the bottom-right cell that was pasted
-        var bottomRightCell = Table_get(dest.structure,dest.bottom,dest.right);
-        var node = bottomRightCell.element;
-        Selection_set(node,node.childNodes.length,node,node.childNodes.length);
-    }
-
-    function replaceCells(src,dest,destRow,destCol)
-    {
-        // By this point, all of the cells have been split. So it is guaranteed that every cell
-        // in dest will have rowspan = 1 and colspan = 1.
-        for (var srcRow = 0; srcRow < src.numRows; srcRow++) {
-            for (var srcCol = 0; srcCol < src.numCols; srcCol++) {
-                var srcCell = Table_get(src,srcRow,srcCol);
-                var destCell = Table_get(dest,srcRow+destRow,srcCol+destCol);
-
-                if ((srcRow != srcCell.row) || (srcCol != srcCell.col))
-                    continue;
-
-                if (destCell.rowspan != 1)
-                    throw new Error("unexpected rowspan: "+destCell.rowspan);
-                if (destCell.colspan != 1)
-                    throw new Error("unexpected colspan: "+destCell.colspan);
-
-                DOM_insertBefore(destCell.element.parentNode,srcCell.element,destCell.element);
-
-                var destTop = destRow + srcRow;
-                var destLeft = destCol + srcCol;
-                var destBottom = destTop + srcCell.rowspan - 1;
-                var destRight = destLeft + srcCell.colspan - 1;
-                Table_setRegion(dest,destTop,destLeft,destBottom,destRight,srcCell);
-            }
-        }
-    }
-
-    function insertChildrenBefore(parent,child,nextSibling,pastedNodes)
-    {
-        var next;
-        for (var grandChild = child.firstChild; grandChild != null; grandChild = next) {
-            next = grandChild.nextSibling;
-            pastedNodes.push(grandChild);
-            DOM_insertBefore(parent,grandChild,nextSibling);
-        }
-    }
-
-    function fixParagraphStyles(node,paragraphClass)
-    {
-        if (isParagraphNode(node)) {
-            if (node._type == HTML_P) {
-                var className = DOM_getAttribute(node,"class");
-                if ((className == null) || (className == "")) {
-                    debug("Setting paragraph class to "+paragraphClass);
-                    DOM_setAttribute(node,"class",paragraphClass);
-                }
-            }
-        }
-        else {
-            for (var child = node.firstChild; child != null; child = child.nextSibling) {
-                fixParagraphStyles(child,paragraphClass);
-            }
-        }
-    }
-
-    // public
-    Clipboard_pasteNodes = function(nodes)
-    {
-        if (nodes.length == 0)
-            return;
-
-        var paragraphClass = Styles_getParagraphClass();
-        if (paragraphClass != null) {
-            for (var i = 0; i < nodes.length; i++) {
-                fixParagraphStyles(nodes[i],paragraphClass);
-            }
-        }
-
-        // Remove any elements which don't belong in the document body (in case an entire
-        // HTML document is being pasted in)
-        var i = 0;
-        while (i < nodes.length) {
-            switch (nodes[i]._type) {
-            case HTML_HTML:
-            case HTML_BODY:
-            case HTML_META:
-            case HTML_TITLE:
-            case HTML_SCRIPT:
-            case HTML_STYLE:
-                nodes.splice(i,1);
-                break;
-            default:
-                i++;
-            }
-        }
-
-        var found = new Object();
-        for (var i = 0; i < nodes.length; i++)
-            removeDuplicateIds(nodes[i],found);
-
-//        if ((nodes.length == 0) && (nodes[0]._type == HTML_TABLE)) {
-//            // FIXME: this won't work; selectionRange is not defined
-//            var fromRegion = Tables_getTableRegionFromTable(nodes[0]);
-//            var toRegion = Tables_regionFromRange(selectionRange);
-//            if (toRegion != null) {
-//                return;
-//            }
-//        }
-
-        Selection_deleteContents(true);
-        var range = Selection_get();
-        if (range == null)
-            throw new Error("No current selection");
-
-        var parent;
-        var previousSibling;
-        var nextSibling;
-
-        var start = range.start;
-        start = Position_preferElementPosition(start);
-        if (start.node.nodeType == Node.ELEMENT_NODE) {
-            parent = start.node;
-            nextSibling = start.node.childNodes[start.offset];
-            previousSibling = start.node.childNodes[start.offset-1];
-        }
-        else {
-            Formatting_splitTextAfter(start);
-            parent = start.node.parentNode;
-            nextSibling = start.node.nextSibling;
-            previousSibling = start.node;
-        }
-
-        var prevLI = null;
-        var inItem = null;
-        var inList = null;
-        var containerParent = null;
-
-        for (var temp = parent; temp != null; temp = temp.parentNode) {
-            if (isContainerNode(temp)) {
-                switch (temp._type) {
-                case HTML_LI:
-                    inItem = temp;
-                    break;
-                case HTML_UL:
-                case HTML_OL:
-                    inList = temp;
-                    break;
-                }
-                containerParent = temp.parentNode;
-                break;
-            }
-        }
-
-        var pastedNodes;
-        if (inItem) {
-            pastedNodes = new Array();
-            for (var i = 0; i < nodes.length; i++) {
-                var child = nodes[i];
-
-                var offset = DOM_nodeOffset(nextSibling,parent);
-
-                switch (child._type) {
-                case HTML_UL:
-                case HTML_OL:
-                    Formatting_movePreceding(new Position(parent,offset),
-                                             function(x) { return (x == containerParent); });
-                    insertChildrenBefore(inItem.parentNode,child,inItem,pastedNodes);
-                    break;
-                case HTML_LI:
-                    Formatting_movePreceding(new Position(parent,offset),
-                                             function(x) { return (x == containerParent); });
-                    DOM_insertBefore(inItem.parentNode,child,inItem);
-                    pastedNodes.push(child);
-                    break;
-                default:
-                    DOM_insertBefore(parent,child,nextSibling);
-                    pastedNodes.push(child);
-                    break;
-                }
-            }
-        }
-        else if (inList) {
-            pastedNodes = new Array();
-            for (var i = 0; i < nodes.length; i++) {
-                var child = nodes[i];
-
-                var offset = DOM_nodeOffset(nextSibling,parent);
-
-                switch (child._type) {
-                case HTML_UL:
-                case HTML_OL:
-                    insertChildrenBefore(parent,child,nextSibling,pastedNodes);
-                    prevLI = null;
-                    break;
-                case HTML_LI:
-                    DOM_insertBefore(parent,child,nextSibling);
-                    pastedNodes.push(child);
-                    prevLI = null;
-                    break;
-                default:
-                    if (!isWhitespaceTextNode(child)) {
-                        if (prevLI == null)
-                            prevLI = DOM_createElement(document,"LI");
-                        DOM_appendChild(prevLI,child);
-                        DOM_insertBefore(parent,prevLI,nextSibling);
-                        pastedNodes.push(child);
-                    }
-                }
-            }
-        }
-        else {
-            pastedNodes = nodes;
-            for (var i = 0; i < nodes.length; i++) {
-                var child = nodes[i];
-                DOM_insertBefore(parent,child,nextSibling);
-            }
-        }
-
-        var prevOffset;
-        if (previousSibling == null)
-            prevOffset = 0;
-        else
-            prevOffset = DOM_nodeOffset(previousSibling);
-        var nextOffset = DOM_nodeOffset(nextSibling,parent);
-
-        var origRange = new Range(parent,prevOffset,parent,nextOffset);
-
-        var firstPasted = pastedNodes[0];
-        var lastPasted = pastedNodes[pastedNodes.length-1];
-        var pastedRange = new Range(firstPasted,0,lastPasted,DOM_maxChildOffset(lastPasted));
-        Range_trackWhileExecuting(origRange,function() {
-        Range_trackWhileExecuting(pastedRange,function() {
-            if (previousSibling != null)
-                Formatting_mergeWithNeighbours(previousSibling,Formatting_MERGEABLE_INLINE);
-            if (nextSibling != null)
-                Formatting_mergeWithNeighbours(nextSibling,Formatting_MERGEABLE_INLINE);
-
-            Cursor_updateBRAtEndOfParagraph(parent);
-
-            Range_ensureValidHierarchy(pastedRange,true);
-        })});
-
-        var pos = new Position(origRange.end.node,origRange.end.offset);
-        Range_trackWhileExecuting(pastedRange,function() {
-        Position_trackWhileExecuting(pos,function() {
-            while (true) {
-                if (pos.node == document.body)
-                    break;
-                if (isContainerNode(pos.node) && (pos.node._type != HTML_LI))
-                    break;
-                if (!nodeHasContent(pos.node)) {
-                    var oldNode = pos.node;
-                    pos = new Position(pos.node.parentNode,DOM_nodeOffset(pos.node));
-                    DOM_deleteNode(oldNode);
-                }
-                else
-                    break;
-            }
-        });
-        });
-
-        pos = new Position(pastedRange.end.node,pastedRange.end.offset);
-        while (isOpaqueNode(pos.node))
-            pos = new Position(pos.node.parentNode,DOM_nodeOffset(pos.node)+1);
-        pos = Position_closestMatchBackwards(pos,Position_okForInsertion);
-
-        Selection_set(pos.node,pos.offset,pos.node,pos.offset);
-        Cursor_ensureCursorVisible();
-    }
-
-    function removeDuplicateIds(node,found)
-    {
-        if ((node.nodeType == Node.ELEMENT_NODE) && node.hasAttribute("id")) {
-            var id = node.getAttribute("id");
-
-            var existing = document.getElementById(id);
-            if (existing == null)
-                existing = found[id];
-
-            if ((existing != null) && (existing != node))
-                DOM_removeAttribute(node,"id");
-            else
-                found[id] = node;
-        }
-        for (var child = node.firstChild; child != null; child = child.nextSibling)
-            removeDuplicateIds(child,found);
-    }
-
-    function pasteImage(href)
-    {
-        // FIXME
-    }
-
-})();

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Layer0_Javascript/Cursor.js
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Layer0_Javascript/Cursor.js b/experiments/editorFramework/src/Layer0_Javascript/Cursor.js
deleted file mode 100644
index 7362a9e..0000000
--- a/experiments/editorFramework/src/Layer0_Javascript/Cursor.js
+++ /dev/null
@@ -1,1050 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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.
-
-var Cursor_ensurePositionVisible;
-var Cursor_ensureCursorVisible;
-var Cursor_scrollDocumentForY;
-var Cursor_positionCursor;
-var Cursor_getCursorPosition;
-var Cursor_moveLeft;
-var Cursor_moveRight;
-var Cursor_moveToStartOfDocument;
-var Cursor_moveToEndOfDocument;
-var Cursor_updateBRAtEndOfParagraph;
-var Cursor_insertReference;
-var Cursor_insertLink;
-var Cursor_insertCharacter;
-var Cursor_deleteCharacter;
-var Cursor_enterPressed;
-var Cursor_getPrecedingWord;
-var Cursor_getAdjacentNodeWithType;
-var Cursor_getLinkProperties;
-var Cursor_setLinkProperties;
-var Cursor_setReferenceTarget;
-var Cursor_makeContainerInsertionPoint;
-var Cursor_set;
-var Cursor_insertFootnote;
-var Cursor_insertEndnote;
-
-(function() {
-
-    var cursorX = null;
-
-    Cursor_ensurePositionVisible = function(pos,center)
-    {
-        // If we can't find the cursor rect for some reason, just don't do anything.
-        // This is better than using an incorrect position or throwing an exception.
-        var rect = Position_displayRectAtPos(pos)
-        if (rect != null) {
-            var extraSpace = 4;
-
-            var cursorTop = rect.top + window.scrollY - extraSpace;
-            var cursorBottom = rect.top + rect.height + window.scrollY + extraSpace;
-
-            var windowTop = window.scrollY;
-            var windowBottom = window.scrollY + window.innerHeight;
-
-            if (center) {
-                var newY = Math.floor(cursorTop + rect.height/2 - window.innerHeight/2);
-                window.scrollTo(window.scrollX,newY);
-            }
-            else if (cursorTop < windowTop) {
-                window.scrollTo(window.scrollX,cursorTop);
-            }
-            else if (cursorBottom > windowBottom) {
-                window.scrollTo(window.scrollX,cursorBottom - window.innerHeight);
-            }
-        }
-    }
-
-    // public
-    Cursor_ensureCursorVisible = function(center)
-    {
-        var selRange = Selection_get();
-        if (selRange != null)
-            Cursor_ensurePositionVisible(selRange.end,center);
-    }
-
-    Cursor_scrollDocumentForY = function(y)
-    {
-        var absY = window.scrollY + y;
-        if (absY-44 < window.scrollY) {
-            window.scrollTo(window.scrollX,absY-44);
-            y = absY - window.scrollY;
-        }
-        else if (absY+44 >= window.scrollY + window.innerHeight) {
-            window.scrollTo(window.scrollX,absY+44 - window.innerHeight);
-            y = absY - window.scrollY;
-        }
-        return y;
-    }
-
-    // public
-    Cursor_positionCursor = function(x,y,wordBoundary)
-    {
-        if (UndoManager_groupType() != "Cursor movement")
-            UndoManager_newGroup("Cursor movement");
-
-        y = Cursor_scrollDocumentForY(y);
-
-        var result = null;
-        var position = Position_atPoint(x,y);
-        if (position == null)
-            return null;
-
-        var node = Position_closestActualNode(position);
-        for (; node != null; node = node.parentNode) {
-            var type = node._type;
-            if ((type == HTML_A) &&
-                (node.hasAttribute("href")) &&
-                (result == null)) {
-
-                var arange = new Range(node,0,node,node.childNodes.length);
-                var rects = Range_getClientRects(arange);
-                var insideLink = false;
-                for (var i = 0; i < rects.length; i++) {
-                    if (rectContainsPoint(rects[i],x,y))
-                        insideLink = true;
-                }
-
-                if (insideLink) {
-                    var href = node.getAttribute("href");
-                    if ((href != null) && (href.charAt(0) == "#")) {
-                        if (isInTOC(node))
-                            result = "intocreference-"+href.substring(1);
-                        else
-                            result = "inreference";
-                    }
-                    else {
-                        result = "inlink";
-                    }
-                }
-            }
-            else if ((type == HTML_IMG) && (result == null)) {
-                for (var anc = node; anc != null; anc = anc.parentNode) {
-                    if (anc._type == HTML_FIGURE) {
-                        result = "infigure";
-                        break;
-                    }
-                }
-            }
-            else if (isAutoCorrectNode(node) && (result == null)) {
-                result = "incorrection";
-            }
-            else if (isTOCNode(node)) {
-                var rect = node.getBoundingClientRect();
-                if (x >= rect.left + rect.width/2)
-                    position = new Position(node.parentNode,DOM_nodeOffset(node)+1);
-                else
-                    position = new Position(node.parentNode,DOM_nodeOffset(node));
-                break;
-            }
-        }
-
-        var position = Position_closestMatchForwards(position,Position_okForMovement);
-        if ((position != null) && isOpaqueNode(position.node))
-            position = Position_nextMatch(position,Position_okForMovement);
-        if (position == null)
-            return false;
-
-        var selectionRange = Selection_get();
-        var samePosition = ((selectionRange != null) && Range_isEmpty(selectionRange) &&
-                            (position.node == selectionRange.start.node) &&
-                            (position.offset == selectionRange.start.offset));
-        if (samePosition && (result == null))
-            result = "same";
-
-        if (wordBoundary) {
-            var startOfWord = Selection_posAtStartOfWord(position);
-            var endOfWord = Selection_posAtEndOfWord(position);
-            if ((startOfWord.node != position.node) || (startOfWord.node != position.node))
-                throw new Error("Word boundary in different node");
-            var distanceBefore = position.offset - startOfWord.offset;
-            var distanceAfter = endOfWord.offset - position.offset;
-            if (distanceBefore <= distanceAfter)
-                position = startOfWord;
-            else
-                position = endOfWord;
-        }
-
-        Cursor_set(position.node,position.offset);
-        return result;
-    }
-
-    // public
-    Cursor_getCursorPosition = function()
-    {
-        var selRange = Selection_get();
-        if (selRange == null)
-            return null;
-
-        // FIXME: in the cases where this is called from Objective C, test what happens if we
-        // return a null rect
-        var rect = Position_displayRectAtPos(selRange.end);
-        if (rect == null)
-            return null;
-
-        var left = rect.left + window.scrollX;
-        var top = rect.top + window.scrollY;
-        var height = rect.height;
-        return { x: left, y: top, width: 0, height: height };
-    }
-
-    // public
-    Cursor_moveLeft = function()
-    {
-        var range = Selection_get();
-        if (range == null)
-            return;
-
-        var pos = Position_prevMatch(range.start,Position_okForMovement);
-        if (pos != null)
-            Cursor_set(pos.node,pos.offset);
-        Cursor_ensureCursorVisible();
-    }
-
-    // public
-    Cursor_moveRight = function()
-    {
-        var range = Selection_get();
-        if (range == null)
-            return;
-
-        var pos = Position_nextMatch(range.start,Position_okForMovement);
-        if (pos != null)
-            Cursor_set(pos.node,pos.offset);
-        Cursor_ensureCursorVisible();
-    }
-
-    // public
-    Cursor_moveToStartOfDocument = function()
-    {
-        var pos = new Position(document.body,0);
-        pos = Position_closestMatchBackwards(pos,Position_okForMovement);
-        Cursor_set(pos.node,pos.offset);
-        Cursor_ensureCursorVisible();
-    }
-
-    // public
-    Cursor_moveToEndOfDocument = function()
-    {
-        var pos = new Position(document.body,document.body.childNodes.length);
-        pos = Position_closestMatchForwards(pos,Position_okForMovement);
-        Cursor_set(pos.node,pos.offset);
-        Cursor_ensureCursorVisible();
-    }
-
-    // An empty paragraph does not get shown and cannot be edited. We can fix this by adding
-    // a BR element as a child
-    // public
-    Cursor_updateBRAtEndOfParagraph = function(node)
-    {
-        var paragraph = node;
-        while ((paragraph != null) && !isParagraphNode(paragraph))
-            paragraph = paragraph.parentNode;
-        if (paragraph != null) {
-
-            var br = null;
-            var last = paragraph;
-            do {
-
-                var child = last;
-                while ((child != null) && isWhitespaceTextNode(child))
-                    child = child.previousSibling;
-
-                if ((child != null) && (child._type == HTML_BR))
-                    br = child;
-
-                last = last.lastChild;
-
-            } while ((last != null) && isInlineNode(last));
-
-            if (nodeHasContent(paragraph)) {
-                // Paragraph has content: don't want BR at end
-                if (br != null) {
-                    DOM_deleteNode(br);
-                }
-            }
-            else {
-                // Paragraph consists only of whitespace: must have BR at end
-                if (br == null) {
-                    br = DOM_createElement(document,"BR");
-                    DOM_appendChild(paragraph,br);
-                }
-            }
-        }
-    }
-
-    // public
-    Cursor_insertReference = function(itemId)
-    {
-        var a = DOM_createElement(document,"A");
-        DOM_setAttribute(a,"href","#"+itemId);
-        Clipboard_pasteNodes([a]);
-    }
-
-    // public
-    Cursor_insertLink = function(text,url)
-    {
-        var a = DOM_createElement(document,"A");
-        DOM_setAttribute(a,"href",url);
-        DOM_appendChild(a,DOM_createTextNode(document,text));
-        Clipboard_pasteNodes([a]);
-    }
-
-    var nbsp = String.fromCharCode(160);
-
-    function spaceToNbsp(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if ((node.nodeType == Node.TEXT_NODE) && (offset > 0) &&
-            (isWhitespaceString(node.nodeValue.charAt(offset-1)))) {
-            // Insert first, to preserve any tracked positions
-            DOM_insertCharacters(node,offset-1,nbsp);
-            DOM_deleteCharacters(node,offset,offset+1);
-        }
-    }
-
-    function nbspToSpace(pos)
-    {
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if ((node.nodeType == Node.TEXT_NODE) && (offset > 0) &&
-            (node.nodeValue.charAt(offset-1) == nbsp)) {
-            // Insert first, to preserve any tracked positions
-            DOM_insertCharacters(node,offset-1," ");
-            DOM_deleteCharacters(node,offset,offset+1);
-        }
-    }
-
-    function checkNbsp()
-    {
-        Selection_preserveWhileExecuting(function() {
-            var selRange = Selection_get();
-            if (selRange != null)
-                nbspToSpace(selRange.end);
-        });
-    }
-
-    function isPosAtStartOfParagraph(pos)
-    {
-        if ((pos.node.nodeType == Node.ELEMENT_NODE) && (pos.offset == 0) &&
-            !isInlineNode(pos.node)) {
-            return true;
-        }
-
-
-
-        while (pos != null) {
-            if (pos.node.nodeType == Node.ELEMENT_NODE) {
-                if ((pos.offset == 0) && !isInlineNode(pos.node))
-                    return true;
-                else
-                    pos = Position_prev(pos);
-            }
-            else if (pos.node.nodeType == Node.TEXT_NODE) {
-                if (pos.offset > 0)
-                    return false;
-                else
-                    pos = Position_prev(pos);
-            }
-            else {
-                return false;
-            }
-        }
-
-        return false;
-    }
-
-    // public
-    Cursor_insertCharacter = function(str,allowInvalidPos,allowNoParagraph)
-    {
-        var firstInsertion = (UndoManager_groupType() != "Insert text");
-
-        if (firstInsertion)
-            UndoManager_newGroup("Insert text",checkNbsp);
-
-        if (str == "-") {
-            var preceding = Cursor_getPrecedingWord();
-            if (preceding.match(/[0-9]\s*$/))
-                str = String.fromCharCode(0x2013); // en dash
-            else if (preceding.match(/\s+$/))
-                str = String.fromCharCode(0x2014); // em dash
-        }
-
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-
-        if (!Range_isEmpty(selRange)) {
-            Selection_deleteContents(true);
-            selRange = Selection_get();
-        }
-        var pos = selRange.start;
-        pos = Position_preferTextPosition(pos);
-        if ((str == " ") && isPosAtStartOfParagraph(pos))
-            return;
-        if (!allowInvalidPos && !Position_okForInsertion(pos)) {
-            var elemPos = Position_preferElementPosition(pos);
-            if (Position_okForInsertion(elemPos)) {
-                pos = elemPos;
-            }
-            else {
-                var oldPos = pos;
-                pos = Position_closestMatchForwards(selRange.start,Position_okForInsertion);
-                var difference = new Range(oldPos.node,oldPos.offset,pos.node,pos.offset);
-                difference = Range_forwards(difference);
-                Position_trackWhileExecuting([pos],function() {
-                    if (!Range_hasContent(difference)) {
-                        Selection_deleteRangeContents(difference,true);
-                    }
-                });
-            }
-        }
-        var node = pos.node;
-        var offset = pos.offset;
-
-        if ((str == " ") &&
-            !firstInsertion &&
-            (node.nodeType == Node.TEXT_NODE) &&
-            (offset > 0) &&
-            (node.nodeValue.charAt(offset-1) == nbsp)) {
-
-            if (!node.nodeValue.substring(0,offset).match(/\.\s+$/)) {
-                DOM_deleteCharacters(node,offset-1,offset);
-                DOM_insertCharacters(node,offset-1,".");
-            }
-        }
-
-        if (isWhitespaceString(str) && (node.nodeType == Node.TEXT_NODE) && (offset > 0)) {
-            var prevChar = node.nodeValue.charAt(offset-1);
-            if (isWhitespaceString(prevChar) || (prevChar == nbsp)) {
-                Selection_update();
-                Cursor_ensureCursorVisible();
-                return;
-            }
-        }
-
-        nbspToSpace(pos);
-
-        // If the user enters two double quotes in succession (open and close), replace them with
-        // just one plain double quote character
-        if ((str == "”") && (node.nodeType == Node.TEXT_NODE) &&
-            (offset > 0) && (node.nodeValue.charAt(offset-1) == "“")) {
-            DOM_deleteCharacters(node,offset-1,offset);
-            offset--;
-            str = "\"";
-        }
-
-        if (node.nodeType == Node.ELEMENT_NODE) {
-            var emptyTextNode = DOM_createTextNode(document,"");
-            if (offset >= node.childNodes.length)
-                DOM_appendChild(node,emptyTextNode);
-            else
-                DOM_insertBefore(node,emptyTextNode,node.childNodes[offset]);
-            node = emptyTextNode;
-            offset = 0;
-        }
-
-        if (str == " ")
-            DOM_insertCharacters(node,offset,nbsp);
-        else
-            DOM_insertCharacters(node,offset,str);
-
-                // must be done *after* inserting the text
-        if (!allowNoParagraph) {
-            switch (node.parentNode._type) {
-            case HTML_CAPTION:
-            case HTML_FIGCAPTION:
-                // Do nothing
-                break;
-            default:
-                Hierarchy_ensureInlineNodesInParagraph(node,true);
-                break;
-            }
-        }
-
-        offset += str.length;
-
-        pos = new Position(node,offset);
-        Position_trackWhileExecuting([pos],function() {
-            Formatting_mergeWithNeighbours(pos.node,Formatting_MERGEABLE_INLINE);
-        });
-
-        Cursor_set(pos.node,pos.offset);
-        Range_trackWhileExecuting(Selection_get(),function() {
-            Cursor_updateBRAtEndOfParagraph(pos.node);
-        });
-
-        Selection_update();
-        Cursor_ensureCursorVisible();
-    }
-
-    function tryDeleteEmptyCaption(pos)
-    {
-        var caption = Position_captionAncestor(pos);
-        if ((caption == null) || nodeHasContent(caption))
-            return false;
-
-        var container = Position_figureOrTableAncestor(pos);
-        if (container == null)
-            return false;
-
-        Cursor_set(container.parentNode,DOM_nodeOffset(container)+1);
-        Selection_preserveWhileExecuting(function() {
-            DOM_deleteNode(caption);
-        });
-
-        return true;
-    }
-
-    function tryDeleteEmptyNote(pos)
-    {
-        var note = Position_noteAncestor(pos);
-        if ((note == null) || nodeHasContent(note))
-            return false;
-
-        var parent = note.parentNode;
-        Cursor_set(note.parentNode,DOM_nodeOffset(note)+1);
-        Selection_preserveWhileExecuting(function() {
-            DOM_deleteNode(note);
-        });
-
-        return true;
-    }
-
-    // public
-    Cursor_deleteCharacter = function()
-    {
-        if (UndoManager_groupType() != "Delete text")
-            UndoManager_newGroup("Delete text",checkNbsp);
-
-        Selection_preferElementPositions();
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-
-        if (!Range_isEmpty(selRange)) {
-            Selection_deleteContents(true);
-        }
-        else {
-            var currentPos = selRange.start;
-
-            // Special cases of pressing backspace after a table, figure, TOC, hyperlink,
-            // footnote, or endnote. For each of these we delete the whole thing.
-            var back = Position_closestMatchBackwards(currentPos,Position_okForMovement);
-            if ((back != null) && (back.node.nodeType == Node.ELEMENT_NODE) && (back.offset > 0)) {
-                var prevNode = back.node.childNodes[back.offset-1];
-                if (isSpecialBlockNode(prevNode)) {
-                    var p = DOM_createElement(document,"P");
-                    DOM_insertBefore(prevNode.parentNode,p,prevNode);
-                    DOM_deleteNode(prevNode);
-                    Cursor_updateBRAtEndOfParagraph(p);
-                    Cursor_set(p,0);
-                    Cursor_ensureCursorVisible();
-                    return;
-                }
-                if ((prevNode._type == HTML_A) || isNoteNode(prevNode)) {
-                    Cursor_set(back.node,back.offset-1);
-                    Selection_preserveWhileExecuting(function() {
-                        DOM_deleteNode(prevNode);
-                    });
-                    return;
-                }
-            }
-
-            // Backspace inside an empty figure or table caption
-            if (tryDeleteEmptyCaption(currentPos))
-                return;
-
-            currentPos = Position_preferTextPosition(currentPos);
-            var prevPos = Position_prevMatch(currentPos,Position_okForMovement);
-
-            // Backspace inside or just after a footnote or endnote
-            if (tryDeleteEmptyNote(currentPos))
-                return;
-            if ((prevPos != null) && tryDeleteEmptyNote(prevPos))
-                return;
-
-            if (prevPos != null) {
-                var startBlock = firstBlockAncestor(Position_closestActualNode(prevPos));
-                var endBlock = firstBlockAncestor(Position_closestActualNode(selRange.end));
-                if ((startBlock != endBlock) &&
-                    isParagraphNode(startBlock) && !nodeHasContent(startBlock)) {
-                    DOM_deleteNode(startBlock);
-                    Cursor_set(selRange.end.node,selRange.end.offset)
-                }
-                else {
-                    var range = new Range(prevPos.node,prevPos.offset,
-                                          selRange.end.node,selRange.end.offset);
-                    Selection_deleteRangeContents(range,true);
-                }
-            }
-        }
-
-        selRange = Selection_get();
-        if (selRange != null)
-            spaceToNbsp(selRange.end);
-        Selection_update();
-        Cursor_ensureCursorVisible();
-
-        function firstBlockAncestor(node)
-        {
-            while (isInlineNode(node))
-                node = node.parentNode;
-            return node;
-        }
-    }
-
-    // public
-    Cursor_enterPressed = function()
-    {
-        UndoManager_newGroup("New paragraph");
-
-        Selection_preferElementPositions();
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-
-        Range_trackWhileExecuting(selRange,function() {
-            if (!Range_isEmpty(selRange))
-                Selection_deleteContents(true);
-        });
-
-        // Are we inside a figure or table caption? If so, put an empty paragraph directly after it
-        var inCaption = false;
-        var inFigCaption = false;
-        var closestNode = Position_closestActualNode(selRange.start);
-        for (var ancestor = closestNode; ancestor != null; ancestor = ancestor.parentNode) {
-            switch (ancestor._type) {
-            case HTML_CAPTION:
-                inCaption = true;
-                break;
-            case HTML_FIGCAPTION:
-                inFigCaption = true;
-                break;
-            case HTML_TABLE:
-            case HTML_FIGURE:
-                if ((inCaption && (ancestor._type == HTML_TABLE)) ||
-                    (inFigCaption && (ancestor._type == HTML_FIGURE))) {
-                    var p = DOM_createElement(document,"P");
-                    DOM_insertBefore(ancestor.parentNode,p,ancestor.nextSibling);
-                    Cursor_updateBRAtEndOfParagraph(p);
-                    Selection_set(p,0,p,0);
-                    return;
-                }
-                break;
-            }
-        }
-
-        // Are we inside a footnote or endnote? If so, move the cursor immediately after it
-        var note = null;
-        if (selRange.start.node.nodeType == Node.TEXT_NODE) {
-            note = Position_noteAncestor(selRange.start);
-        }
-        else {
-            // We can't use Position_noteAncestor in this case, because we want to to break
-            // the paragraph *before* the note, not after
-            var checkNode = selRange.start.node;
-            for (var anc = checkNode; anc != null; anc = anc.parentNode) {
-                if (isNoteNode(anc)) {
-                    note = anc;
-                    break;
-                }
-            }
-        }
-        if (note != null) {
-            var noteOffset = DOM_nodeOffset(note);
-            selRange = new Range(note.parentNode,noteOffset+1,note.parentNode,noteOffset+1);
-        }
-
-        var check = Position_preferElementPosition(selRange.start);
-        if (check.node.nodeType == Node.ELEMENT_NODE) {
-            var before = check.node.childNodes[check.offset-1];
-            var after = check.node.childNodes[check.offset];
-            if (((before != null) && isSpecialBlockNode(before)) ||
-                ((after != null) && isSpecialBlockNode(after))) {
-                var p = DOM_createElement(document,"P");
-                DOM_insertBefore(check.node,p,check.node.childNodes[check.offset]);
-                Cursor_updateBRAtEndOfParagraph(p);
-                Cursor_set(p,0);
-                Cursor_ensureCursorVisible();
-                return;
-            }
-        }
-
-        Range_trackWhileExecuting(selRange,function() {
-            Range_ensureInlineNodesInParagraph(selRange);
-            Range_ensureValidHierarchy(selRange);
-        });
-
-        var pos = selRange.start;
-
-        var detail = Range_detail(selRange);
-        switch (detail.startParent._type) {
-        case HTML_OL:
-        case HTML_UL: {
-            var li = DOM_createElement(document,"LI");
-            DOM_insertBefore(detail.startParent,li,detail.startChild);
-
-            Cursor_set(li,0);
-            Cursor_ensureCursorVisible();
-            return;
-        }
-        }
-
-        if (isAutoCorrectNode(pos.node)) {
-            pos = Position_preferTextPosition(pos);
-            selRange.start = selRange.end = pos;
-        }
-
-        Range_trackWhileExecuting(selRange,function() {
-
-            // If we're directly in a container node, add a paragraph, so we have something to
-            // split.
-            if (isContainerNode(pos.node) && (pos.node._type != HTML_LI)) {
-                var p = DOM_createElement(document,"P");
-                DOM_insertBefore(pos.node,p,pos.node.childNodes[pos.offset]);
-                pos = new Position(p,0);
-            }
-
-            var blockToSplit = getBlockToSplit(pos);
-            var stopAt = blockToSplit.parentNode;
-
-            if (positionAtStartOfHeading(pos)) {
-                var container = getContainerOrParagraph(pos.node);
-                pos = new Position(container,0);
-                pos = Formatting_movePreceding(pos,function(n) { return (n == stopAt); },true);
-            }
-            else if (pos.node.nodeType == Node.TEXT_NODE) {
-                pos = Formatting_splitTextAfter(pos,function(n) { return (n == stopAt); },true);
-            }
-            else {
-                pos = Formatting_moveFollowing(pos,function(n) { return (n == stopAt); },true);
-            }
-        });
-
-        Cursor_set(pos.node,pos.offset);
-        selRange = Selection_get();
-
-        Range_trackWhileExecuting(selRange,function() {
-            if ((pos.node.nodeType == Node.TEXT_NODE) && (pos.node.nodeValue.length == 0)) {
-                DOM_deleteNode(pos.node);
-            }
-
-            var detail = Range_detail(selRange);
-
-            // If a preceding paragraph has become empty as a result of enter being pressed
-            // while the cursor was in it, then update the BR at the end of the paragraph
-            var start = detail.startChild ? detail.startChild : detail.startParent;
-            for (var ancestor = start; ancestor != null; ancestor = ancestor.parentNode) {
-                var prev = ancestor.previousSibling;
-                if ((prev != null) && isParagraphNode(prev) && !nodeHasContent(prev)) {
-                    DOM_deleteAllChildren(prev);
-                    Cursor_updateBRAtEndOfParagraph(prev);
-                    break;
-                }
-                else if ((prev != null) && (prev._type == HTML_LI) && !nodeHasContent(prev)) {
-                    var next;
-                    for (var child = prev.firstChild; child != null; child = next) {
-                        next = child.nextSibling;
-                        if (isWhitespaceTextNode(child))
-                            DOM_deleteNode(child);
-                        else
-                            Cursor_updateBRAtEndOfParagraph(child);
-                    }
-                    break;
-                }
-            }
-
-            for (var ancestor = start; ancestor != null; ancestor = ancestor.parentNode) {
-
-                if (isParagraphNode(ancestor)) {
-                    var nextSelector = Styles_nextSelectorAfter(ancestor);
-                    if (nextSelector != null) {
-                        var nextElementName = null;
-                        var nextClassName = null;
-
-
-                        var dotIndex = nextSelector.indexOf(".");
-                        if (dotIndex >= 0) {
-                            nextElementName = nextSelector.substring(0,dotIndex);
-                            nextClassName = nextSelector.substring(dotIndex+1);
-                        }
-                        else {
-                            nextElementName = nextSelector;
-                        }
-
-                        ancestor = DOM_replaceElement(ancestor,nextElementName);
-                        DOM_removeAttribute(ancestor,"id");
-                        DOM_setAttribute(ancestor,"class",nextClassName);
-                    }
-                }
-
-                if (isParagraphNode(ancestor) && !nodeHasContent(ancestor)) {
-                    Cursor_updateBRAtEndOfParagraph(prev);
-                    break;
-                }
-                else if ((ancestor._type == HTML_LI) && !nodeHasContent(ancestor)) {
-                    DOM_deleteAllChildren(ancestor);
-                    break;
-                }
-            }
-
-            Cursor_updateBRAtEndOfParagraph(Range_singleNode(selRange));
-        });
-
-        Selection_set(selRange.start.node,selRange.start.offset,
-                      selRange.end.node,selRange.end.offset);
-        cursorX = null;
-        Cursor_ensureCursorVisible();
-
-        function getBlockToSplit(pos)
-        {
-            var blockToSplit = null;
-            for (var n = pos.node; n != null; n = n.parentNode) {
-                if (n._type == HTML_LI) {
-                    blockToSplit = n;
-                    break;
-                }
-            }
-            if (blockToSplit == null) {
-                blockToSplit = pos.node;
-                while (isInlineNode(blockToSplit))
-                    blockToSplit = blockToSplit.parentNode;
-            }
-            return blockToSplit;
-        }
-
-        function getContainerOrParagraph(node)
-        {
-            while ((node != null) && isInlineNode(node))
-                node = node.parentNode;
-            return node;
-        }
-
-        function positionAtStartOfHeading(pos)
-        {
-            var container = getContainerOrParagraph(pos.node);
-            if (isHeadingNode(container)) {
-                var startOffset = 0;
-                if (isOpaqueNode(container.firstChild))
-                    startOffset = 1;
-                var range = new Range(container,startOffset,pos.node,pos.offset);
-                return !Range_hasContent(range);
-            }
-            else
-                return false;
-        }
-    }
-
-    Cursor_getPrecedingWord = function() {
-        var selRange = Selection_get();
-        if ((selRange == null) && !Range_isEmpty(selRange))
-            return "";
-
-        var node = selRange.start.node;
-        var offset = selRange.start.offset;
-        if (node.nodeType != Node.TEXT_NODE)
-            return "";
-
-        return node.nodeValue.substring(0,offset);
-    }
-
-    Cursor_getAdjacentNodeWithType = function(type)
-    {
-        var selRange = Selection_get();
-        var pos = Position_preferElementPosition(selRange.start);
-        var node = pos.node;
-        var offset = pos.offset;
-
-        while (true) {
-
-            if (node._type == type)
-                return node;
-
-            if (node.nodeType == Node.ELEMENT_NODE) {
-                var before = node.childNodes[offset-1];
-                if ((before != null) && (before._type == type))
-                    return before;
-
-                var after = node.childNodes[offset];
-                if ((after != null) && (after._type == type))
-                    return after;
-            }
-
-            if (node.parentNode == null)
-                return null;
-
-            offset = DOM_nodeOffset(node);
-            node = node.parentNode;
-        }
-    }
-
-    Cursor_getLinkProperties = function()
-    {
-        var a = Cursor_getAdjacentNodeWithType(HTML_A);
-        if (a == null)
-            return null;
-
-        return { href: a.getAttribute("href"),
-                 text: getNodeText(a) };
-    }
-
-    Cursor_setLinkProperties = function(properties)
-    {
-        var a = Cursor_getAdjacentNodeWithType(HTML_A);
-        if (a == null)
-            return null;
-
-        Selection_preserveWhileExecuting(function() {
-            DOM_setAttribute(a,"href",properties.href);
-            DOM_deleteAllChildren(a);
-            DOM_appendChild(a,DOM_createTextNode(document,properties.text));
-        });
-    }
-
-    Cursor_setReferenceTarget = function(itemId)
-    {
-        var a = Cursor_getAdjacentNodeWithType(HTML_A);
-        if (a != null)
-            Outline_setReferenceTarget(a,itemId);
-    }
-
-    // Deletes the current selection contents and ensures that the cursor is located directly
-    // inside the nearest container element, i.e. not inside a paragraph or inline node. This
-    // is intended for preventing things like inserting a table of contants inside a heading
-    Cursor_makeContainerInsertionPoint = function()
-    {
-        var selRange = Selection_get();
-        if (selRange == null)
-            return;
-
-        if (!Range_isEmpty(selRange)) {
-            Selection_deleteContents();
-            selRange = Selection_get();
-        }
-
-        var parent;
-        var previousSibling;
-        var nextSibling;
-
-        if (selRange.start.node.nodeType == Node.ELEMENT_NODE) {
-            parent = selRange.start.node;
-            nextSibling = selRange.start.node.childNodes[selRange.start.offset];
-        }
-        else {
-            if (selRange.start.offset > 0)
-                Formatting_splitTextBefore(selRange.start);
-            parent = selRange.start.node.parentNode;
-            nextSibling = selRange.start.node;
-        }
-
-        var offset = DOM_nodeOffset(nextSibling,parent);
-
-        if (isContainerNode(parent)) {
-            Cursor_set(parent,offset);
-            return;
-        }
-
-        if ((offset > 0) && isItemNumber(parent.childNodes[offset-1]))
-            offset--;
-
-        Formatting_moveFollowing(new Position(parent,offset),isContainerNode);
-        Formatting_movePreceding(new Position(parent,offset),isContainerNode);
-
-        offset = 0;
-        while (!isContainerNode(parent)) {
-            var old = parent;
-            offset = DOM_nodeOffset(parent);
-            parent = parent.parentNode;
-            DOM_deleteNode(old);
-        }
-
-        Cursor_set(parent,offset);
-        cursorX = null;
-    }
-
-    Cursor_set = function(node,offset,keepCursorX)
-    {
-        Selection_set(node,offset,node,offset);
-        if (!keepCursorX)
-            cursorX = null;
-    }
-
-    function moveRangeOutsideOfNote(range)
-    {
-        var node = range.start.node;
-        var offset = range.start.offset;
-
-        for (var anc = node; anc != null; anc = anc.parentNode) {
-            if (isNoteNode(anc) && (anc.parentNode != null)) {
-                node = anc.parentNode;
-                offset = DOM_nodeOffset(anc)+1;
-                return new Range(node,offset,node,offset);
-            }
-        }
-
-        return range;
-    }
-
-    function insertNote(className,content)
-    {
-        var footnote = DOM_createElement(document,"span");
-        DOM_setAttribute(footnote,"class",className);
-        DOM_appendChild(footnote,DOM_createTextNode(document,content));
-
-        var range = Selection_get();
-        range = moveRangeOutsideOfNote(range);
-        Formatting_splitAroundSelection(range,false);
-
-        // If we're part-way through a text node, splitAroundSelection will give us an
-        // empty text node between the before and after text. For formatting purposes that's
-        // fine (not sure if necessary), but when inserting a footnote or endnote we want
-        // to avoid this as it causes problems with cursor movement - specifically, the cursor
-        // is allowed to go inside the empty text node, and this doesn't show up in the correct
-        // position on screen.
-        var pos = range.start;
-        if ((pos.node._type == HTML_TEXT) &&
-            (pos.node.nodeValue.length == 0)) {
-            var empty = pos.node;
-            pos = new Position(empty.parentNode,DOM_nodeOffset(empty));
-            DOM_deleteNode(empty);
-        }
-        else {
-            pos = Position_preferElementPosition(pos);
-        }
-
-        DOM_insertBefore(pos.node,footnote,pos.node.childNodes[pos.offset]);
-        Selection_set(footnote,0,footnote,footnote.childNodes.length);
-        Cursor_updateBRAtEndOfParagraph(footnote);
-    }
-
-    Cursor_insertFootnote = function(content)
-    {
-        insertNote("footnote",content);
-    }
-
-    Cursor_insertEndnote = function(content)
-    {
-        insertNote("endnote",content);
-    }
-
-})();


[17/28] incubator-corinthia git commit: included MOC compiler for Qt implementation

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/gen_dtd_data.html
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/gen_dtd_data.html b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/gen_dtd_data.html
new file mode 100644
index 0000000..ac09ad2
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/gen_dtd_data.html
@@ -0,0 +1,247 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title></title>
+<script src="../DOM_js"></script>
+<script>
+
+function ElementDeclaration(name)
+{
+    this.name = name;
+    this.allowedChildren = new Object();
+}
+
+ElementDeclaration.prototype.addAllowedChild = function(name)
+{
+    this.allowedChildren[name] = true;
+}
+
+ElementDeclaration.prototype.removeAllowedChild = function(name)
+{
+    delete this.allowedChildren[name];
+}
+
+ElementDeclaration.prototype.print = function()
+{
+    for (var childName in this.allowedChildren)
+        println(this.name+" -> "+childName);
+}
+
+ElementDeclaration.prototype.printAllowedChildren = function()
+{
+    println("    \""+this.name+"\": {");
+    for (var childName in this.allowedChildren)
+        println("        \""+childName+"\": true,");
+    println("    },");
+}
+
+ElementDeclaration.prototype.setAllowedParents = function(allowedParents)
+{
+    for (var childName in this.allowedChildren) {
+        if (allowedParents[childName] == null)
+            allowedParents[childName] = new Object();
+        allowedParents[childName][this.name] = true;
+    }
+}
+
+function debug(str)
+{
+    console.log(str);
+}
+
+function println(str)
+{
+    var text = DOM_createTextNode(document,str+"\n");
+    var output = document.getElementById("output");
+    DOM_appendChild(output,text);
+}
+
+function readFile(filename)
+{
+    var req = new XMLHttpRequest();
+    req.open("GET",filename,false);
+    req.send();
+    return req.responseXML;
+}
+
+function printTree(node,indent)
+{
+    if (indent == null)
+        indent = "";
+    println(indent+node);
+    for (var child = node.firstChild; child != null; child = child.nextSibling)
+        printTree(child,indent+"    ");
+}
+
+function parseOrGroup(decl,element)
+{
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "element-name") {
+            decl.addAllowedChild(child.getAttribute("name"));
+        }
+        else if (child.nodeName == "pcdata") {
+        }
+        else if (child.nodeName == "or-group") {
+            parseOrGroup(decl,child);
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+}
+
+function parseSequenceGroup(decl,element)
+{
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "element-name") {
+            decl.addAllowedChild(child.getAttribute("name"));
+        }
+        else if (child.nodeName == "or-group") {
+            parseOrGroup(decl,child);
+        }
+        else if (child.nodeName == "pcdata") {
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+}
+
+function parseContentModelExpanded(decl,element)
+{
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "or-group") {
+            parseOrGroup(decl,child);
+        }
+        else if (child.nodeName == "and-group") {
+            parseOrGroup(decl,child);
+        }
+        else if (child.nodeName == "sequence-group") {
+            parseSequenceGroup(decl,child);
+        }
+        else if (child.nodeName == "empty") {
+        }
+        else if (child.nodeName == "cdata") {
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+}
+
+function parseInclusions(decl,element)
+{
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "or-group") {
+            parseOrGroup(decl,child);
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+}
+
+function parseOrGroupExclusions(decl,element)
+{
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "element-name") {
+            decl.removeAllowedChild(child.getAttribute("name"));
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+}
+
+function parseSequenceGroupExclusions(decl,element)
+{
+    parseOrGroupExclusions(decl,element);
+}
+
+function parseExclusions(decl,element)
+{
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "or-group") {
+            parseOrGroupExclusions(decl,child);
+        }
+        else if (child.nodeName == "sequence-group") {
+            parseSequenceGroupExclusions(decl,child);
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+}
+
+function parseElement(element)
+{
+    var decl = new ElementDeclaration(element.getAttribute("name"));
+
+    for (var child = element.firstChild; child != null; child = child.nextSibling) {
+        if (child.nodeName == "content-model-expanded") {
+            parseContentModelExpanded(decl,child);
+        }
+        else if (child.nodeName == "inclusions") {
+            parseInclusions(decl,child);
+        }
+        else if (child.nodeName == "exclusions") {
+            parseExclusions(decl,child);
+        }
+        else if (child.nodeName == "content-model") {
+        }
+        else if (child.nodeType == Node.ELEMENT_NODE) {
+            println("ERROR: unexpected element: "+child.nodeName+" (parent "+element.nodeName+")");
+        }
+    }
+
+//    decl.println();
+    return decl;
+}
+
+function loaded()
+{
+    var dtd = readFile("html4.xml");
+//    printTree(dtd);
+
+    var decls = new Array();
+    for (var node = dtd.documentElement.firstChild; node != null; node = node.nextSibling) {
+        if (node.nodeName == "element") {
+            decls.push(parseElement(node));
+        }
+    }
+
+    println("// Automatically generated from HTML 4.01 dtd using dtdparse and gen_dtd_data.html");
+    println("// See http://nwalsh.com/perl/dtdparse/");
+    println("");
+
+    println("var ALLOWED_CHILDREN = {");
+    for (var i = 0; i < decls.length; i++) {
+        decls[i].printAllowedChildren();
+    }
+    println("};");
+
+    println("");
+
+    var allowedParents = new Object();
+    for (var i = 0; i < decls.length; i++) {
+        decls[i].setAllowedParents(allowedParents);
+    }
+
+    println("var ALLOWED_PARENTS = {");
+    for (var childName in allowedParents) {
+        println("    \""+childName+"\": {");
+        for (var parentName in allowedParents[childName]) {
+            println("        \""+parentName+"\": true,");
+        }
+        println("    },");
+    }
+    println("};");
+
+}
+</script>
+</head>
+
+<body onload="loaded()">
+<pre id="output">
+</pre>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/9bf02bb2/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.dtd
----------------------------------------------------------------------
diff --git a/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.dtd b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.dtd
new file mode 100644
index 0000000..c5752ed
--- /dev/null
+++ b/experiments/editorFramework/src/Javascript_Layer_0/dtdsource/html4.dtd
@@ -0,0 +1,1078 @@
+<!--
+    This is the HTML 4.01 Transitional DTD, which includes
+    presentation attributes and elements that W3C expects to phase out
+    as support for style sheets matures. Authors should use the Strict
+    DTD when possible, but may use the Transitional DTD when support
+    for presentation attribute and elements is required.
+
+    HTML 4 includes mechanisms for style sheets, scripting,
+    embedding objects, improved support for right to left and mixed
+    direction text, and enhancements to forms for improved
+    accessibility for people with disabilities.
+
+          Draft: $Date: 1999/12/24 23:37:50 $
+
+          Authors:
+              Dave Raggett <ds...@w3.org>
+              Arnaud Le Hors <le...@w3.org>
+              Ian Jacobs <ij...@w3.org>
+
+    Further information about HTML 4.01 is available at:
+
+        http://www.w3.org/TR/1999/REC-html401-19991224
+
+
+    The HTML 4.01 specification includes additional
+    syntactic constraints that cannot be expressed within
+    the DTDs.
+
+-->
+<!ENTITY % HTML.Version "-//W3C//DTD HTML 4.01 Transitional//EN"
+  -- Typical usage:
+
+    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+            "http://www.w3.org/TR/html4/loose.dtd">
+    <html>
+    <head>
+    ...
+    </head>
+    <body>
+    ...
+    </body>
+    </html>
+
+    The URI used as a system identifier with the public identifier allows
+    the user agent to download the DTD and entity sets as needed.
+
+    The FPI for the Strict HTML 4.01 DTD is:
+
+        "-//W3C//DTD HTML 4.01//EN"
+
+    This version of the strict DTD is:
+
+        http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd
+
+    Authors should use the Strict DTD unless they need the
+    presentation control for user agents that don't (adequately)
+    support style sheets.
+
+    If you are writing a document that includes frames, use 
+    the following FPI:
+
+        "-//W3C//DTD HTML 4.01 Frameset//EN"
+
+    This version of the frameset DTD is:
+
+        http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd
+
+    Use the following (relative) URIs to refer to 
+    the DTDs and entity definitions of this specification:
+
+    "strict.dtd"
+    "loose.dtd"
+    "frameset.dtd"
+    "HTMLlat1.ent"
+    "HTMLsymbol.ent"
+    "HTMLspecial.ent"
+
+-->
+
+<!--================== Imported Names ====================================-->
+<!-- Feature Switch for frameset documents -->
+<!ENTITY % HTML.Frameset "IGNORE">
+
+<!ENTITY % ContentType "CDATA"
+    -- media type, as per [RFC2045]
+    -->
+
+<!ENTITY % ContentTypes "CDATA"
+    -- comma-separated list of media types, as per [RFC2045]
+    -->
+
+<!ENTITY % Charset "CDATA"
+    -- a character encoding, as per [RFC2045]
+    -->
+
+<!ENTITY % Charsets "CDATA"
+    -- a space-separated list of character encodings, as per [RFC2045]
+    -->
+
+<!ENTITY % LanguageCode "NAME"
+    -- a language code, as per [RFC1766]
+    -->
+
+<!ENTITY % Character "CDATA"
+    -- a single character from [ISO10646] 
+    -->
+
+<!ENTITY % LinkTypes "CDATA"
+    -- space-separated list of link types
+    -->
+
+<!ENTITY % MediaDesc "CDATA"
+    -- single or comma-separated list of media descriptors
+    -->
+
+<!ENTITY % URI "CDATA"
+    -- a Uniform Resource Identifier,
+       see [URI]
+    -->
+
+<!ENTITY % Datetime "CDATA" -- date and time information. ISO date format -->
+
+
+<!ENTITY % Script "CDATA" -- script expression -->
+
+<!ENTITY % StyleSheet "CDATA" -- style sheet data -->
+
+<!ENTITY % FrameTarget "CDATA" -- render in this frame -->
+
+
+<!ENTITY % Text "CDATA">
+
+
+<!-- Parameter Entities -->
+
+<!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT" -- repeatable head elements -->
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+<!ENTITY % list "UL | OL |  DIR | MENU">
+
+<!ENTITY % preformatted "PRE">
+
+<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+    Black  = #000000    Green  = #008000
+    Silver = #C0C0C0    Lime   = #00FF00
+    Gray   = #808080    Olive  = #808000
+    White  = #FFFFFF    Yellow = #FFFF00
+    Maroon = #800000    Navy   = #000080
+    Red    = #FF0000    Blue   = #0000FF
+    Purple = #800080    Teal   = #008080
+    Fuchsia= #FF00FF    Aqua   = #00FFFF
+ -->
+
+<!ENTITY % bodycolors "
+  bgcolor     %Color;        #IMPLIED  -- document background color --
+  text        %Color;        #IMPLIED  -- document text color --
+  link        %Color;        #IMPLIED  -- color of links --
+  vlink       %Color;        #IMPLIED  -- color of visited links --
+  alink       %Color;        #IMPLIED  -- color of selected links --
+  ">
+
+<!--=================== Generic Attributes ===============================-->
+
+<!ENTITY % coreattrs
+ "id          ID             #IMPLIED  -- document-wide unique id --
+  class       CDATA          #IMPLIED  -- space-separated list of classes --
+  style       %StyleSheet;   #IMPLIED  -- associated style info --
+  title       %Text;         #IMPLIED  -- advisory title --"
+  >
+
+<!ENTITY % i18n
+ "lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #IMPLIED  -- direction for weak/neutral text --"
+  >
+
+<!ENTITY % events
+ "onclick     %Script;       #IMPLIED  -- a pointer button was clicked --
+  ondblclick  %Script;       #IMPLIED  -- a pointer button was double clicked--
+  onmousedown %Script;       #IMPLIED  -- a pointer button was pressed down --
+  onmouseup   %Script;       #IMPLIED  -- a pointer button was released --
+  onmouseover %Script;       #IMPLIED  -- a pointer was moved onto --
+  onmousemove %Script;       #IMPLIED  -- a pointer was moved within --
+  onmouseout  %Script;       #IMPLIED  -- a pointer was moved away --
+  onkeypress  %Script;       #IMPLIED  -- a key was pressed and released --
+  onkeydown   %Script;       #IMPLIED  -- a key was pressed down --
+  onkeyup     %Script;       #IMPLIED  -- a key was released --"
+  >
+
+<!-- Reserved Feature Switch -->
+<!ENTITY % HTML.Reserved "IGNORE">
+
+<!-- The following attributes are reserved for possible future use -->
+<![ %HTML.Reserved; [
+<!ENTITY % reserved
+ "datasrc     %URI;          #IMPLIED  -- a single or tabular Data Source --
+  datafld     CDATA          #IMPLIED  -- the property or column name --
+  dataformatas (plaintext|html) plaintext -- text or html --"
+  >
+]]>
+
+<!ENTITY % reserved "">
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!ENTITY % align "align (left|center|right|justify)  #IMPLIED"
+                   -- default is left for ltr paragraphs, right for rtl --
+  >
+
+<!--=================== Text Markup ======================================-->
+
+<!ENTITY % fontstyle
+ "TT | I | B | U | S | STRIKE | BIG | SMALL">
+
+<!ENTITY % phrase "EM | STRONG | DFN | CODE |
+                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >
+
+<!ENTITY % special
+   "A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+    MAP | Q | SUB | SUP | SPAN | BDO | IFRAME">
+
+<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">
+
+<!-- %inline; covers inline or "text-level" elements -->
+<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">
+
+<!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)*>
+<!ATTLIST (%fontstyle;|%phrase;)
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!ELEMENT (SUB|SUP) - - (%inline;)*    -- subscript, superscript -->
+<!ATTLIST (SUB|SUP)
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!ELEMENT SPAN - - (%inline;)*         -- generic language/style container -->
+<!ATTLIST SPAN
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %reserved;                   -- reserved for possible future use --
+  >
+
+<!ELEMENT BDO - - (%inline;)*          -- I18N BiDi over-ride -->
+<!ATTLIST BDO
+  %coreattrs;                          -- id, class, style, title --
+  lang        %LanguageCode; #IMPLIED  -- language code --
+  dir         (ltr|rtl)      #REQUIRED -- directionality --
+  >
+
+<!ELEMENT BASEFONT - O EMPTY           -- base font size -->
+<!ATTLIST BASEFONT
+  id          ID             #IMPLIED  -- document-wide unique id --
+  size        CDATA          #REQUIRED -- base font size for FONT elements --
+  color       %Color;        #IMPLIED  -- text color --
+  face        CDATA          #IMPLIED  -- comma-separated list of font names --
+  >
+
+<!ELEMENT FONT - - (%inline;)*         -- local change to font -->
+<!ATTLIST FONT
+  %coreattrs;                          -- id, class, style, title --
+  %i18n;                       -- lang, dir --
+  size        CDATA          #IMPLIED  -- [+|-]nn e.g. size="+1", size="4" --
+  color       %Color;        #IMPLIED  -- text color --
+  face        CDATA          #IMPLIED  -- comma-separated list of font names --
+  >
+
+<!ELEMENT BR - O EMPTY                 -- forced line break -->
+<!ATTLIST BR
+  %coreattrs;                          -- id, class, style, title --
+  clear       (left|all|right|none) none -- control of text flow --
+  >
+
+<!--================== HTML content models ===============================-->
+
+<!--
+    HTML has two basic content models:
+
+        %inline;     character level elements and text strings
+        %block;      block-like elements e.g. paragraphs and lists
+-->
+
+<!ENTITY % block
+     "P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+      NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+      TABLE | FIELDSET | ADDRESS">
+
+<!ENTITY % flow "%block; | %inline;">
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT BODY O O (%flow;)* +(INS|DEL) -- document body -->
+<!ATTLIST BODY
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  onload          %Script;   #IMPLIED  -- the document has been loaded --
+  onunload        %Script;   #IMPLIED  -- the document has been removed --
+  background      %URI;      #IMPLIED  -- texture tile for document
+                                          background --
+  %bodycolors;                         -- bgcolor, text, link, vlink, alink --
+  >
+
+<!ELEMENT ADDRESS - - ((%inline;)|P)*  -- information on author -->
+<!ATTLIST ADDRESS
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!ELEMENT DIV - - (%flow;)*            -- generic language/style container -->
+<!ATTLIST DIV
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %align;                              -- align, text alignment --
+  %reserved;                           -- reserved for possible future use --
+  >
+
+<!ELEMENT CENTER - - (%flow;)*         -- shorthand for DIV align=center -->
+<!ATTLIST CENTER
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!--================== The Anchor Element ================================-->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+<!ENTITY % Coords "CDATA" -- comma-separated list of lengths -->
+
+<!ELEMENT A - - (%inline;)* -(A)       -- anchor -->
+<!ATTLIST A
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
+  type        %ContentType;  #IMPLIED  -- advisory content type --
+  name        CDATA          #IMPLIED  -- named link end --
+  href        %URI;          #IMPLIED  -- URI for linked resource --
+  hreflang    %LanguageCode; #IMPLIED  -- language code --
+  target      %FrameTarget;  #IMPLIED  -- render in this frame --
+  rel         %LinkTypes;    #IMPLIED  -- forward link types --
+  rev         %LinkTypes;    #IMPLIED  -- reverse link types --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  shape       %Shape;        rect      -- for use with client-side image maps --
+  coords      %Coords;       #IMPLIED  -- for use with client-side image maps --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  >
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+     separate document although this isn't yet widely supported -->
+
+<!ELEMENT MAP - - ((%block;) | AREA)+ -- client-side image map -->
+<!ATTLIST MAP
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  name        CDATA          #REQUIRED -- for reference by usemap --
+  >
+
+<!ELEMENT AREA - O EMPTY               -- client-side image map area -->
+<!ATTLIST AREA
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  shape       %Shape;        rect      -- controls interpretation of coords --
+  coords      %Coords;       #IMPLIED  -- comma-separated list of lengths --
+  href        %URI;          #IMPLIED  -- URI for linked resource --
+  target      %FrameTarget;  #IMPLIED  -- render in this frame --
+  nohref      (nohref)       #IMPLIED  -- this region has no action --
+  alt         %Text;         #REQUIRED -- short description --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  >
+
+<!--================== The LINK Element ==================================-->
+
+<!--
+  Relationship values can be used in principle:
+
+   a) for document specific toolbars/menus when used
+      with the LINK element in document head e.g.
+        start, contents, previous, next, index, end, help
+   b) to link to a separate style sheet (rel=stylesheet)
+   c) to make a link to a script (rel=script)
+   d) by stylesheets to control how collections of
+      html nodes are rendered into printed documents
+   e) to make a link to a printable version of this document
+      e.g. a postscript or pdf version (rel=alternate media=print)
+-->
+
+<!ELEMENT LINK - O EMPTY               -- a media-independent link -->
+<!ATTLIST LINK
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
+  href        %URI;          #IMPLIED  -- URI for linked resource --
+  hreflang    %LanguageCode; #IMPLIED  -- language code --
+  type        %ContentType;  #IMPLIED  -- advisory content type --
+  rel         %LinkTypes;    #IMPLIED  -- forward link types --
+  rev         %LinkTypes;    #IMPLIED  -- reverse link types --
+  media       %MediaDesc;    #IMPLIED  -- for rendering on these media --
+  target      %FrameTarget;  #IMPLIED  -- render in this frame --
+  >
+
+<!--=================== Images ===========================================-->
+
+<!-- Length defined in strict DTD for cellpadding/cellspacing -->
+<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+<!ENTITY % MultiLength "CDATA" -- pixel, percentage, or relative -->
+
+<![ %HTML.Frameset; [
+<!ENTITY % MultiLengths "CDATA" -- comma-separated list of MultiLength -->
+]]>
+
+<!ENTITY % Pixels "CDATA" -- integer representing length in pixels -->
+
+<!ENTITY % IAlign "(top|middle|bottom|left|right)" -- center? -->
+
+<!-- To avoid problems with text-only UAs as well as 
+   to make image content understandable and navigable 
+   to users of non-visual UAs, you need to provide
+   a description with ALT, and avoid server-side image maps -->
+<!ELEMENT IMG - O EMPTY                -- Embedded image -->
+<!ATTLIST IMG
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  src         %URI;          #REQUIRED -- URI of image to embed --
+  alt         %Text;         #REQUIRED -- short description --
+  longdesc    %URI;          #IMPLIED  -- link to long description
+                                          (complements alt) --
+  name        CDATA          #IMPLIED  -- name of image for scripting --
+  height      %Length;       #IMPLIED  -- override height --
+  width       %Length;       #IMPLIED  -- override width --
+  usemap      %URI;          #IMPLIED  -- use client-side image map --
+  ismap       (ismap)        #IMPLIED  -- use server-side image map --
+  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
+  border      %Pixels;       #IMPLIED  -- link border width --
+  hspace      %Pixels;       #IMPLIED  -- horizontal gutter --
+  vspace      %Pixels;       #IMPLIED  -- vertical gutter --
+  >
+
+<!-- USEMAP points to a MAP element which may be in this document
+  or an external document, although the latter is not widely supported -->
+
+<!--==================== OBJECT ======================================-->
+<!--
+  OBJECT is used to embed objects as part of HTML pages 
+  PARAM elements should precede other content. SGML mixed content
+  model technicality precludes specifying this formally ...
+-->
+
+<!ELEMENT OBJECT - - (PARAM | %flow;)*
+ -- generic embedded object -->
+<!ATTLIST OBJECT
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  declare     (declare)      #IMPLIED  -- declare but don't instantiate flag --
+  classid     %URI;          #IMPLIED  -- identifies an implementation --
+  codebase    %URI;          #IMPLIED  -- base URI for classid, data, archive--
+  data        %URI;          #IMPLIED  -- reference to object's data --
+  type        %ContentType;  #IMPLIED  -- content type for data --
+  codetype    %ContentType;  #IMPLIED  -- content type for code --
+  archive     CDATA          #IMPLIED  -- space-separated list of URIs --
+  standby     %Text;         #IMPLIED  -- message to show while loading --
+  height      %Length;       #IMPLIED  -- override height --
+  width       %Length;       #IMPLIED  -- override width --
+  usemap      %URI;          #IMPLIED  -- use client-side image map --
+  name        CDATA          #IMPLIED  -- submit as part of form --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
+  border      %Pixels;       #IMPLIED  -- link border width --
+  hspace      %Pixels;       #IMPLIED  -- horizontal gutter --
+  vspace      %Pixels;       #IMPLIED  -- vertical gutter --
+  %reserved;                           -- reserved for possible future use --
+  >
+
+<!ELEMENT PARAM - O EMPTY              -- named property value -->
+<!ATTLIST PARAM
+  id          ID             #IMPLIED  -- document-wide unique id --
+  name        CDATA          #REQUIRED -- property name --
+  value       CDATA          #IMPLIED  -- property value --
+  valuetype   (DATA|REF|OBJECT) DATA   -- How to interpret value --
+  type        %ContentType;  #IMPLIED  -- content type for value
+                                          when valuetype=ref --
+  >
+
+<!--=================== Java APPLET ==================================-->
+<!--
+  One of code or object attributes must be present.
+  Place PARAM elements before other content.
+-->
+<!ELEMENT APPLET - - (PARAM | %flow;)* -- Java applet -->
+<!ATTLIST APPLET
+  %coreattrs;                          -- id, class, style, title --
+  codebase    %URI;          #IMPLIED  -- optional base URI for applet --
+  archive     CDATA          #IMPLIED  -- comma-separated archive list --
+  code        CDATA          #IMPLIED  -- applet class file --
+  object      CDATA          #IMPLIED  -- serialized applet file --
+  alt         %Text;         #IMPLIED  -- short description --
+  name        CDATA          #IMPLIED  -- allows applets to find each other --
+  width       %Length;       #REQUIRED -- initial width --
+  height      %Length;       #REQUIRED -- initial height --
+  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
+  hspace      %Pixels;       #IMPLIED  -- horizontal gutter --
+  vspace      %Pixels;       #IMPLIED  -- vertical gutter --
+  >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT HR - O EMPTY -- horizontal rule -->
+<!ATTLIST HR
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  align       (left|center|right) #IMPLIED
+  noshade     (noshade)      #IMPLIED
+  size        %Pixels;       #IMPLIED
+  width       %Length;       #IMPLIED
+  >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT P - O (%inline;)*            -- paragraph -->
+<!ATTLIST P
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %align;                              -- align, text alignment --
+  >
+
+<!--=================== Headings =========================================-->
+
+<!--
+  There are six levels of headings from H1 (the most important)
+  to H6 (the least important).
+-->
+
+<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->
+<!ATTLIST (%heading;)
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %align;                              -- align, text alignment --
+  >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- excludes markup for images and changes in font size -->
+<!ENTITY % pre.exclusion "IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT">
+
+<!ELEMENT PRE - - (%inline;)* -(%pre.exclusion;) -- preformatted text -->
+<!ATTLIST PRE
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  width       NUMBER         #IMPLIED
+  >
+
+<!--===================== Inline Quotes ==================================-->
+
+<!ELEMENT Q - - (%inline;)*            -- short inline quotation -->
+<!ATTLIST Q
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  cite        %URI;          #IMPLIED  -- URI for source document or msg --
+  >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT BLOCKQUOTE - - (%flow;)*     -- long quotation -->
+<!ATTLIST BLOCKQUOTE
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  cite        %URI;          #IMPLIED  -- URI for source document or msg --
+  >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+
+<!-- INS/DEL are handled by inclusion on BODY -->
+<!ELEMENT (INS|DEL) - - (%flow;)*      -- inserted text, deleted text -->
+<!ATTLIST (INS|DEL)
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  cite        %URI;          #IMPLIED  -- info on reason for change --
+  datetime    %Datetime;     #IMPLIED  -- date and time of change --
+  >
+
+<!--=================== Lists ============================================-->
+
+<!-- definition lists - DT for term, DD for its definition -->
+
+<!ELEMENT DL - - (DT|DD)+              -- definition list -->
+<!ATTLIST DL
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  compact     (compact)      #IMPLIED  -- reduced interitem spacing --
+  >
+
+<!ELEMENT DT - O (%inline;)*           -- definition term -->
+<!ELEMENT DD - O (%flow;)*             -- definition description -->
+<!ATTLIST (DT|DD)
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!-- Ordered lists (OL) Numbering style
+
+    1   arablic numbers     1, 2, 3, ...
+    a   lower alpha         a, b, c, ...
+    A   upper alpha         A, B, C, ...
+    i   lower roman         i, ii, iii, ...
+    I   upper roman         I, II, III, ...
+
+    The style is applied to the sequence number which by default
+    is reset to 1 for the first list item in an ordered list.
+
+    This can't be expressed directly in SGML due to case folding.
+-->
+
+<!ENTITY % OLStyle "CDATA"      -- constrained to: "(1|a|A|i|I)" -->
+
+<!ELEMENT OL - - (LI)+                 -- ordered list -->
+<!ATTLIST OL
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  type        %OLStyle;      #IMPLIED  -- numbering style --
+  compact     (compact)      #IMPLIED  -- reduced interitem spacing --
+  start       NUMBER         #IMPLIED  -- starting sequence number --
+  >
+
+<!-- Unordered Lists (UL) bullet styles -->
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!ELEMENT UL - - (LI)+                 -- unordered list -->
+<!ATTLIST UL
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  type        %ULStyle;      #IMPLIED  -- bullet style --
+  compact     (compact)      #IMPLIED  -- reduced interitem spacing --
+  >
+
+<!ELEMENT (DIR|MENU) - - (LI)+ -(%block;) -- directory list, menu list -->
+<!ATTLIST DIR
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  compact     (compact)      #IMPLIED -- reduced interitem spacing --
+  >
+<!ATTLIST MENU
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  compact     (compact)      #IMPLIED -- reduced interitem spacing --
+  >
+
+<!ENTITY % LIStyle "CDATA" -- constrained to: "(%ULStyle;|%OLStyle;)" -->
+
+<!ELEMENT LI - O (%flow;)*             -- list item -->
+<!ATTLIST LI
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  type        %LIStyle;      #IMPLIED  -- list item style --
+  value       NUMBER         #IMPLIED  -- reset sequence number --
+  >
+
+<!--================ Forms ===============================================-->
+<!ELEMENT FORM - - (%flow;)* -(FORM)   -- interactive form -->
+<!ATTLIST FORM
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  action      %URI;          #REQUIRED -- server-side form handler --
+  method      (GET|POST)     GET       -- HTTP method used to submit the form--
+  enctype     %ContentType;  "application/x-www-form-urlencoded"
+  accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
+  name        CDATA          #IMPLIED  -- name of form for scripting --
+  onsubmit    %Script;       #IMPLIED  -- the form was submitted --
+  onreset     %Script;       #IMPLIED  -- the form was reset --
+  target      %FrameTarget;  #IMPLIED  -- render in this frame --
+  accept-charset %Charsets;  #IMPLIED  -- list of supported charsets --
+  >
+
+<!-- Each label must not contain more than ONE field -->
+<!ELEMENT LABEL - - (%inline;)* -(LABEL) -- form field label text -->
+<!ATTLIST LABEL
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  for         IDREF          #IMPLIED  -- matches field ID value --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  >
+
+<!ENTITY % InputType
+  "(TEXT | PASSWORD | CHECKBOX |
+    RADIO | SUBMIT | RESET |
+    FILE | HIDDEN | IMAGE | BUTTON)"
+   >
+
+<!-- attribute name required for all but submit and reset -->
+<!ELEMENT INPUT - O EMPTY              -- form control -->
+<!ATTLIST INPUT
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  type        %InputType;    TEXT      -- what kind of widget is needed --
+  name        CDATA          #IMPLIED  -- submit as part of form --
+  value       CDATA          #IMPLIED  -- Specify for radio buttons and checkboxes --
+  checked     (checked)      #IMPLIED  -- for radio buttons and check boxes --
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  readonly    (readonly)     #IMPLIED  -- for text and passwd --
+  size        CDATA          #IMPLIED  -- specific to each type of field --
+  maxlength   NUMBER         #IMPLIED  -- max chars for text fields --
+  src         %URI;          #IMPLIED  -- for fields with images --
+  alt         CDATA          #IMPLIED  -- short description --
+  usemap      %URI;          #IMPLIED  -- use client-side image map --
+  ismap       (ismap)        #IMPLIED  -- use server-side image map --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  onselect    %Script;       #IMPLIED  -- some text was selected --
+  onchange    %Script;       #IMPLIED  -- the element value was changed --
+  accept      %ContentTypes; #IMPLIED  -- list of MIME types for file upload --
+  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
+  %reserved;                           -- reserved for possible future use --
+  >
+
+<!ELEMENT SELECT - - (OPTGROUP|OPTION)+ -- option selector -->
+<!ATTLIST SELECT
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  name        CDATA          #IMPLIED  -- field name --
+  size        NUMBER         #IMPLIED  -- rows visible --
+  multiple    (multiple)     #IMPLIED  -- default is single selection --
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  onchange    %Script;       #IMPLIED  -- the element value was changed --
+  %reserved;                           -- reserved for possible future use --
+  >
+
+<!ELEMENT OPTGROUP - - (OPTION)+ -- option group -->
+<!ATTLIST OPTGROUP
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  label       %Text;         #REQUIRED -- for use in hierarchical menus --
+  >
+
+<!ELEMENT OPTION - O (#PCDATA)         -- selectable choice -->
+<!ATTLIST OPTION
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  selected    (selected)     #IMPLIED
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  label       %Text;         #IMPLIED  -- for use in hierarchical menus --
+  value       CDATA          #IMPLIED  -- defaults to element content --
+  >
+
+<!ELEMENT TEXTAREA - - (#PCDATA)       -- multi-line text field -->
+<!ATTLIST TEXTAREA
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  name        CDATA          #IMPLIED
+  rows        NUMBER         #REQUIRED
+  cols        NUMBER         #REQUIRED
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  readonly    (readonly)     #IMPLIED
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  onselect    %Script;       #IMPLIED  -- some text was selected --
+  onchange    %Script;       #IMPLIED  -- the element value was changed --
+  %reserved;                           -- reserved for possible future use --
+  >
+
+<!--
+  #PCDATA is to solve the mixed content problem,
+  per specification only whitespace is allowed there!
+ -->
+<!ELEMENT FIELDSET - - (#PCDATA,LEGEND,(%flow;)*) -- form control group -->
+<!ATTLIST FIELDSET
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!ELEMENT LEGEND - - (%inline;)*       -- fieldset legend -->
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ATTLIST LEGEND
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  align       %LAlign;       #IMPLIED  -- relative to fieldset --
+  >
+
+<!ELEMENT BUTTON - -
+     (%flow;)* -(A|%formctrl;|FORM|ISINDEX|FIELDSET|IFRAME)
+     -- push button -->
+<!ATTLIST BUTTON
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  name        CDATA          #IMPLIED
+  value       CDATA          #IMPLIED  -- sent to server when submitted --
+  type        (button|submit|reset) submit -- for use as form button --
+  disabled    (disabled)     #IMPLIED  -- unavailable in this context --
+  tabindex    NUMBER         #IMPLIED  -- position in tabbing order --
+  accesskey   %Character;    #IMPLIED  -- accessibility key character --
+  onfocus     %Script;       #IMPLIED  -- the element got the focus --
+  onblur      %Script;       #IMPLIED  -- the element lost the focus --
+  %reserved;                           -- reserved for possible future use --
+  >
+
+<!--======================= Tables =======================================-->
+
+<!-- IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The BORDER attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The FRAME attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the VALIGN attribute.
+
+ The value "border" is included for backwards compatibility with
+ <TABLE BORDER> which yields frame=border and border=implied
+ For <TABLE BORDER=1> you get border=1 and frame=implied. In this
+ case, it is appropriate to treat this as frame=border for backwards
+ compatibility with deployed browsers.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The RULES attribute defines which rules to draw between cells:
+
+ If RULES is absent then assume:
+     "none" if BORDER is absent or BORDER=0 otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+  
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents -->
+<!ENTITY % cellhalign
+  "align      (left|center|right|justify|char) #IMPLIED
+   char       %Character;    #IMPLIED  -- alignment char, e.g. char=':' --
+   charoff    %Length;       #IMPLIED  -- offset for alignment char --"
+  >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+  "valign     (top|middle|bottom|baseline) #IMPLIED"
+  >
+
+<!ELEMENT TABLE - -
+     (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
+<!ELEMENT CAPTION  - - (%inline;)*     -- table caption -->
+<!ELEMENT THEAD    - O (TR)+           -- table header -->
+<!ELEMENT TFOOT    - O (TR)+           -- table footer -->
+<!ELEMENT TBODY    O O (TR)+           -- table body -->
+<!ELEMENT COLGROUP - O (COL)*          -- table column group -->
+<!ELEMENT COL      - O EMPTY           -- table column -->
+<!ELEMENT TR       - O (TH|TD)+        -- table row -->
+<!ELEMENT (TH|TD)  - O (%flow;)*       -- table header cell, table data cell-->
+
+<!ATTLIST TABLE                        -- table element --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  summary     %Text;         #IMPLIED  -- purpose/structure for speech output--
+  width       %Length;       #IMPLIED  -- table width --
+  border      %Pixels;       #IMPLIED  -- controls frame width around table --
+  frame       %TFrame;       #IMPLIED  -- which parts of frame to render --
+  rules       %TRules;       #IMPLIED  -- rulings between rows and cols --
+  cellspacing %Length;       #IMPLIED  -- spacing between cells --
+  cellpadding %Length;       #IMPLIED  -- spacing within cells --
+  align       %TAlign;       #IMPLIED  -- table position relative to window --
+  bgcolor     %Color;        #IMPLIED  -- background color for cells --
+  %reserved;                           -- reserved for possible future use --
+  datapagesize CDATA         #IMPLIED  -- reserved for possible future use --
+  >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST CAPTION
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  align       %CAlign;       #IMPLIED  -- relative to table --
+  >
+
+<!--
+COLGROUP groups a set of COL elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST COLGROUP
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  span        NUMBER         1         -- default number of columns in group --
+  width       %MultiLength;  #IMPLIED  -- default width for enclosed COLs --
+  %cellhalign;                         -- horizontal alignment in cells --
+  %cellvalign;                         -- vertical alignment in cells --
+  >
+
+<!--
+ COL elements define the alignment properties for cells in
+ one or more columns.
+
+ The WIDTH attribute specifies the width of the columns, e.g.
+
+     width=64        width in screen pixels
+     width=0.5*      relative width of 0.5
+
+ The SPAN attribute causes the attributes of one
+ COL element to apply to more than one column.
+-->
+<!ATTLIST COL                          -- column groups and properties --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  span        NUMBER         1         -- COL attributes affect N columns --
+  width       %MultiLength;  #IMPLIED  -- column width specification --
+  %cellhalign;                         -- horizontal alignment in cells --
+  %cellvalign;                         -- vertical alignment in cells --
+  >
+
+<!--
+    Use THEAD to duplicate headers when breaking table
+    across page boundaries, or for static headers when
+    TBODY sections are rendered in scrolling panel.
+
+    Use TFOOT to duplicate footers when breaking table
+    across page boundaries, or for static footers when
+    TBODY sections are rendered in scrolling panel.
+
+    Use multiple TBODY sections when rules are needed
+    between groups of table rows.
+-->
+<!ATTLIST (THEAD|TBODY|TFOOT)          -- table section --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %cellhalign;                         -- horizontal alignment in cells --
+  %cellvalign;                         -- vertical alignment in cells --
+  >
+
+<!ATTLIST TR                           -- table row --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  %cellhalign;                         -- horizontal alignment in cells --
+  %cellvalign;                         -- vertical alignment in cells --
+  bgcolor     %Color;        #IMPLIED  -- background color for row --
+  >
+
+
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- TH is for headers, TD for data, but for cells acting as both use TD -->
+<!ATTLIST (TH|TD)                      -- header or data cell --
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  abbr        %Text;         #IMPLIED  -- abbreviation for header cell --
+  axis        CDATA          #IMPLIED  -- comma-separated list of related headers--
+  headers     IDREFS         #IMPLIED  -- list of id's for header cells --
+  scope       %Scope;        #IMPLIED  -- scope covered by header cells --
+  rowspan     NUMBER         1         -- number of rows spanned by cell --
+  colspan     NUMBER         1         -- number of cols spanned by cell --
+  %cellhalign;                         -- horizontal alignment in cells --
+  %cellvalign;                         -- vertical alignment in cells --
+  nowrap      (nowrap)       #IMPLIED  -- suppress word wrap --
+  bgcolor     %Color;        #IMPLIED  -- cell background color --
+  width       %Length;       #IMPLIED  -- width for cell --
+  height      %Length;       #IMPLIED  -- height for cell --
+  >
+
+<!--================== Document Frames ===================================-->
+
+<!--
+  The content model for HTML documents depends on whether the HEAD is
+  followed by a FRAMESET or BODY element. The widespread omission of
+  the BODY start tag makes it impractical to define the content model
+  without the use of a marked section.
+-->
+
+<![ %HTML.Frameset; [
+<!ELEMENT FRAMESET - - ((FRAMESET|FRAME)+ & NOFRAMES?) -- window subdivision-->
+<!ATTLIST FRAMESET
+  %coreattrs;                          -- id, class, style, title --
+  rows        %MultiLengths; #IMPLIED  -- list of lengths,
+                                          default: 100% (1 row) --
+  cols        %MultiLengths; #IMPLIED  -- list of lengths,
+                                          default: 100% (1 col) --
+  onload      %Script;       #IMPLIED  -- all the frames have been loaded  -- 
+  onunload    %Script;       #IMPLIED  -- all the frames have been removed -- 
+  >
+]]>
+
+<![ %HTML.Frameset; [
+<!-- reserved frame names start with "_" otherwise starts with letter -->
+<!ELEMENT FRAME - O EMPTY              -- subwindow -->
+<!ATTLIST FRAME
+  %coreattrs;                          -- id, class, style, title --
+  longdesc    %URI;          #IMPLIED  -- link to long description
+                                          (complements title) --
+  name        CDATA          #IMPLIED  -- name of frame for targetting --
+  src         %URI;          #IMPLIED  -- source of frame content --
+  frameborder (1|0)          1         -- request frame borders? --
+  marginwidth %Pixels;       #IMPLIED  -- margin widths in pixels --
+  marginheight %Pixels;      #IMPLIED  -- margin height in pixels --
+  noresize    (noresize)     #IMPLIED  -- allow users to resize frames? --
+  scrolling   (yes|no|auto)  auto      -- scrollbar or none --
+  >
+]]>
+
+<!ELEMENT IFRAME - - (%flow;)*         -- inline subwindow -->
+<!ATTLIST IFRAME
+  %coreattrs;                          -- id, class, style, title --
+  longdesc    %URI;          #IMPLIED  -- link to long description
+                                          (complements title) --
+  name        CDATA          #IMPLIED  -- name of frame for targetting --
+  src         %URI;          #IMPLIED  -- source of frame content --
+  frameborder (1|0)          1         -- request frame borders? --
+  marginwidth %Pixels;       #IMPLIED  -- margin widths in pixels --
+  marginheight %Pixels;      #IMPLIED  -- margin height in pixels --
+  scrolling   (yes|no|auto)  auto      -- scrollbar or none --
+  align       %IAlign;       #IMPLIED  -- vertical or horizontal alignment --
+  height      %Length;       #IMPLIED  -- frame height --
+  width       %Length;       #IMPLIED  -- frame width --
+  >
+
+<![ %HTML.Frameset; [
+<!ENTITY % noframes.content "(BODY) -(NOFRAMES)">
+]]>
+
+<!ENTITY % noframes.content "(%flow;)*">
+
+<!ELEMENT NOFRAMES - - %noframes.content;
+ -- alternate content container for non frame-based rendering -->
+<!ATTLIST NOFRAMES
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!--================ Document Head =======================================-->
+<!-- %head.misc; defined earlier on as "SCRIPT|STYLE|META|LINK|OBJECT" -->
+<!ENTITY % head.content "TITLE & ISINDEX? & BASE?">
+
+<!ELEMENT HEAD O O (%head.content;) +(%head.misc;) -- document head -->
+<!ATTLIST HEAD
+  %i18n;                               -- lang, dir --
+  profile     %URI;          #IMPLIED  -- named dictionary of meta info --
+  >
+
+<!-- The TITLE element is not considered part of the flow of text.
+       It should be displayed, for example as the page header or
+       window title. Exactly one title is required per document.
+    -->
+<!ELEMENT TITLE - - (#PCDATA) -(%head.misc;) -- document title -->
+<!ATTLIST TITLE %i18n>
+
+<!ELEMENT ISINDEX - O EMPTY            -- single line prompt -->
+<!ATTLIST ISINDEX
+  %coreattrs;                          -- id, class, style, title --
+  %i18n;                               -- lang, dir --
+  prompt      %Text;         #IMPLIED  -- prompt message -->
+
+<!ELEMENT BASE - O EMPTY               -- document base URI -->
+<!ATTLIST BASE
+  href        %URI;          #IMPLIED  -- URI that acts as base URI --
+  target      %FrameTarget;  #IMPLIED  -- render in this frame --
+  >
+
+<!ELEMENT META - O EMPTY               -- generic metainformation -->
+<!ATTLIST META
+  %i18n;                               -- lang, dir, for use with content --
+  http-equiv  NAME           #IMPLIED  -- HTTP response header name  --
+  name        NAME           #IMPLIED  -- metainformation name --
+  content     CDATA          #REQUIRED -- associated information --
+  scheme      CDATA          #IMPLIED  -- select form of content --
+  >
+
+<!ELEMENT STYLE - - %StyleSheet        -- style info -->
+<!ATTLIST STYLE
+  %i18n;                               -- lang, dir, for use with title --
+  type        %ContentType;  #REQUIRED -- content type of style language --
+  media       %MediaDesc;    #IMPLIED  -- designed for use with these media --
+  title       %Text;         #IMPLIED  -- advisory title --
+  >
+
+<!ELEMENT SCRIPT - - %Script;          -- script statements -->
+<!ATTLIST SCRIPT
+  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
+  type        %ContentType;  #REQUIRED -- content type of script language --
+  language    CDATA          #IMPLIED  -- predefined script language name --
+  src         %URI;          #IMPLIED  -- URI for an external script --
+  defer       (defer)        #IMPLIED  -- UA may defer execution of script --
+  event       CDATA          #IMPLIED  -- reserved for possible future use --
+  for         %URI;          #IMPLIED  -- reserved for possible future use --
+  >
+
+<!ELEMENT NOSCRIPT - - (%flow;)*
+  -- alternate content container for non script-based rendering -->
+<!ATTLIST NOSCRIPT
+  %attrs;                              -- %coreattrs, %i18n, %events --
+  >
+
+<!--================ Document Structure ==================================-->
+<!ENTITY % version "version CDATA #FIXED '%HTML.Version;'">
+
+<![ %HTML.Frameset; [
+<!ENTITY % html.content "HEAD, FRAMESET">
+]]>
+
+<!ENTITY % html.content "HEAD, BODY">
+
+<!ELEMENT HTML O O (%html.content;)    -- document root element -->
+<!ATTLIST HTML
+  %i18n;                               -- lang, dir --
+  %version;
+  >