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:50:20 UTC

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

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