From be6848a549d9d5c5fdc224dfd1e22a416d8048a7 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Sat, 9 Jun 2012 23:18:56 +0200 Subject: [PATCH] =?UTF-8?q?let=C2=B4s=20put=20the=20files=5Fodfviewer=20ap?= =?UTF-8?q?plication=20into=20the=20stable4=20branch=20for=20convinience.?= =?UTF-8?q?=20We=20release=20it=20as=20part=20of=20ownCloud=204.0.x=20anyw?= =?UTF-8?q?ays.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/files_odfviewer/appinfo/app.php | 5 + apps/files_odfviewer/appinfo/info.xml | 12 + apps/files_odfviewer/css/odfviewer.css | 20 + apps/files_odfviewer/css/webodf.css | 196 + apps/files_odfviewer/js/viewer.js | 60 + apps/files_odfviewer/js/webodf-debug.js | 7124 ++++++ apps/files_odfviewer/js/webodf.js | 343 + apps/files_odfviewer/src/.gitignore | 1 + apps/files_odfviewer/src/update.sh | 9 + apps/files_odfviewer/src/webodf/.gitignore | 17 + apps/files_odfviewer/src/webodf/.gitmodules | 9 + .../files_odfviewer/src/webodf/CMakeLists.txt | 160 + .../src/webodf/JSCoverage.patch | 13 + apps/files_odfviewer/src/webodf/packwebodf.js | 93 + .../src/webodf/programs/CMakeLists.txt | 30 + .../programs/android/AndroidManifest.xml | 42 + .../webodf/programs/android/CMakeLists.txt | 41 + .../programs/android/assets/www/config.xml | 25 + .../programs/android/assets/www/icon.png | Bin 0 -> 3793 bytes .../programs/android/assets/www/index.html | 46 + .../android/assets/www/phonegap-1.4.1.js | 4586 ++++ .../programs/android/assets/www/scripts.js | 4123 ++++ .../programs/android/libs/phonegap-1.4.1.jar | Bin 0 -> 155233 bytes .../android/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 4147 bytes .../android/res/drawable-ldpi/ic_launcher.png | Bin 0 -> 1723 bytes .../android/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 2574 bytes .../programs/android/res/drawable/icon.png | Bin 0 -> 3535 bytes .../programs/android/res/layout/listitem.xml | 7 + .../programs/android/res/layout/main.xml | 12 + .../programs/android/res/layout/selector.xml | 17 + .../programs/android/res/values/strings.xml | 7 + .../programs/android/res/xml/phonegap.xml | 5 + .../programs/android/res/xml/plugins.xml | 19 + .../src/org/webodf/WebODFActivity.java | 33 + .../webodf/programs/android/updateWebODF.sh | 3 + .../webodf/programs/docnosis/CMakeLists.txt | 0 .../OpenDocument-manifest-schema-v1.0-os.rng | 111 + .../OpenDocument-manifest-schema-v1.1.rng | 111 + .../docnosis/OpenDocument-schema-v1.0-os.rng | 17666 +++++++++++++++ .../docnosis/OpenDocument-schema-v1.1.rng | 17891 +++++++++++++++ .../OpenDocument-strict-schema-v1.0-os.rng | 61 + .../OpenDocument-strict-schema-v1.1.rng | 61 + .../OpenDocument-v1.2-cos01-dsig-schema.rng | 84 + ...penDocument-v1.2-cos01-manifest-schema.rng | 224 + .../OpenDocument-v1.2-cos01-schema.rng | 18127 ++++++++++++++++ ...on-vnd.oasis.opendocument.presentation.png | Bin 0 -> 6617 bytes ...ion-vnd.oasis.opendocument.spreadsheet.png | Bin 0 -> 7002 bytes ...pplication-vnd.oasis.opendocument.text.png | Bin 0 -> 6723 bytes .../src/webodf/programs/docnosis/docnosis.js | 779 + .../src/webodf/programs/docnosis/index.html | 27 + .../programs/firefoxextension/CMakeLists.txt | 35 + .../programs/firefoxextension/bootstrap.js | 36 + .../programs/firefoxextension/chrome.manifest | 13 + .../components/odfContentHandler.js | 196 + .../firefoxextension/content/odf.html | 89 + .../programs/firefoxextension/install.rdf.in | 34 + .../firefoxextension/packextension.js | 77 + .../firefoxextension/skin/default/icon.png | Bin 0 -> 44606 bytes .../programs/ios/Default-Landscape~ipad.png | Bin 0 -> 52135 bytes .../programs/ios/Default-Portrait~ipad.png | Bin 0 -> 51794 bytes .../ios/WebODF.xcodeproj/project.pbxproj | 512 + .../programs/ios/WebODF/Classes/AppDelegate.h | 52 + .../programs/ios/WebODF/Classes/AppDelegate.m | 202 + .../ios/WebODF/Classes/MainViewController.h | 17 + .../ios/WebODF/Classes/MainViewController.m | 47 + .../ios/WebODF/Classes/MainViewController.xib | 118 + .../ios/WebODF/Classes/NSData+Base64.h | 33 + .../ios/WebODF/Classes/NSData+Base64.m | 299 + .../programs/ios/WebODF/Classes/NativeZip.h | 13 + .../programs/ios/WebODF/Classes/NativeZip.m | 79 + .../ios/WebODF/Classes/WebViewCache.h | 15 + .../ios/WebODF/Classes/WebViewCache.m | 72 + .../ios/WebODF/Classes/minizip/crypt.h | 132 + .../ios/WebODF/Classes/minizip/ioapi.c | 177 + .../ios/WebODF/Classes/minizip/ioapi.h | 75 + .../ios/WebODF/Classes/minizip/mztools.c | 28 + .../ios/WebODF/Classes/minizip/mztools.h | 31 + .../ios/WebODF/Classes/minizip/unzip.c | 1597 ++ .../ios/WebODF/Classes/minizip/unzip.h | 354 + .../webodf/programs/ios/WebODF/Classes/zip.h | 15 + .../webodf/programs/ios/WebODF/PhoneGap.plist | 57 + .../Resources/en.lproj/Localizable.strings | 25 + .../ios/WebODF/Resources/icons/icon-72.png | Bin 0 -> 8844 bytes .../ios/WebODF/Resources/icons/icon.png | Bin 0 -> 6106 bytes .../ios/WebODF/Resources/icons/icon@2x.png | Bin 0 -> 19269 bytes .../splash/Default-Landscape~ipad.png | Bin 0 -> 52135 bytes .../splash/Default-Portrait~ipad.png | Bin 0 -> 51794 bytes .../ios/WebODF/Resources/splash/Default.png | Bin 0 -> 46308 bytes .../WebODF/Resources/splash/Default@2x.png | Bin 0 -> 50982 bytes .../programs/ios/WebODF/WebODF-Info.plist | 122 + .../programs/ios/WebODF/WebODF-Prefix.pch | 7 + .../ios/WebODF/en.lproj/InfoPlist.strings | 2 + .../src/webodf/programs/ios/WebODF/main.m | 32 + .../src/webodf/programs/ios/www/index.html | 52 + .../src/webodf/programs/ios/www/nativezip.js | 84 + .../webodf/programs/ios/www/phonegap-1.4.1.js | 4123 ++++ .../programs/nativeQtClient/CMakeLists.txt | 39 + .../src/webodf/programs/nativeQtClient/README | 1 + .../programs/nativeQtClient/application.qrc | 18 + .../webodf/programs/nativeQtClient/main.cpp | 10 + .../programs/nativeQtClient/mainwindow.cpp | 173 + .../programs/nativeQtClient/mainwindow.h | 46 + .../programs/nativeQtClient/mainwindow.ui | 46 + .../programs/nativeQtClient/odfpage.cpp | 1 + .../webodf/programs/nativeQtClient/odfpage.h | 15 + .../programs/nativeQtClient/odfview.cpp | 83 + .../webodf/programs/nativeQtClient/odfview.h | 29 + .../webodf/programs/nativeQtClient/scripts.js | 93 + .../webodf/programs/playbook/CMakeLists.txt | 0 .../webodf/programs/playbook/build_sign.bat | 23 + .../src/webodf/programs/playbook/config.xml | 26 + .../js/common/custom_filereader_dispatcher.js | 17 + .../js/common/custom_filereader_ns.js | 8 + .../blackberry.custom.filereader/library.xml | 22 + .../custom/filereader/CustomFileReader.as | 34 + .../src/webodf/programs/playbook/icon.png | Bin 0 -> 19269 bytes .../src/webodf/programs/playbook/index.html | 28 + .../src/webodf/programs/playbook/scripts.js | 146 + .../programs/qtjsruntime/CMakeLists.txt | 4 + .../src/webodf/programs/qtjsruntime/nam.h | 48 + .../webodf/programs/qtjsruntime/nativeio.cpp | 106 + .../webodf/programs/qtjsruntime/nativeio.h | 41 + .../programs/qtjsruntime/pagerunner.cpp | 191 + .../webodf/programs/qtjsruntime/pagerunner.h | 68 + .../programs/qtjsruntime/qtjsruntime.cpp | 20 + .../webodf/programs/touchui/CMakeLists.txt | 7 + .../src/webodf/programs/touchui/ZoomIn.png | Bin 0 -> 670 bytes .../src/webodf/programs/touchui/ZoomOut.png | Bin 0 -> 607 bytes .../src/webodf/programs/touchui/app/app.js | 40 + .../programs/touchui/app/controller/Files.js | 82 + .../programs/touchui/app/model/FileSystem.js | 265 + .../programs/touchui/app/store/FileStore.js | 30 + .../programs/touchui/app/views/FileDetail.js | 122 + .../programs/touchui/app/views/FilesList.js | 47 + .../programs/touchui/app/views/OdfView.js | 170 + .../programs/touchui/app/views/Viewport.js | 54 + .../src/webodf/programs/touchui/go-next.png | Bin 0 -> 1473 bytes .../webodf/programs/touchui/go-previous.png | Bin 0 -> 1536 bytes .../src/webodf/programs/touchui/index.html | 22 + .../src/webodf/programs/touchui/scripts.js | 130 + .../webodf/programs/touchui/sencha-touch.css | 1 + .../webodf/programs/touchui/sencha-touch.js | 15 + .../src/webodf/programs/touchui/welcome.odt | Bin 0 -> 62780 bytes .../webodf/programs/touchui/zoom-fit-best.png | Bin 0 -> 932 bytes .../programs/touchui/zoom-fit-height.png | Bin 0 -> 947 bytes .../programs/touchui/zoom-fit-width.png | Bin 0 -> 934 bytes .../simplerevisionserver/webdavserver.py | 77 + .../src/webodf/webodf/APPNOTE.txt | 3218 +++ .../src/webodf/webodf/CMakeLists.txt | 201 + apps/files_odfviewer/src/webodf/webodf/README | 43 + .../src/webodf/webodf/compare.html | 34 + .../src/webodf/webodf/compare.js | 45 + .../src/webodf/webodf/deflateinmozilla.txt | 69 + .../src/webodf/webodf/embedodf.html | 2 + .../src/webodf/webodf/filelist.js | 66 + .../src/webodf/webodf/filelister.html | 42 + .../src/webodf/webodf/filelister.js | 200 + .../src/webodf/webodf/flashput/Makefile | 2 + .../src/webodf/webodf/flashput/PUT.as | 18 + .../src/webodf/webodf/flashput/PUT.swf | Bin 0 -> 18031 bytes .../src/webodf/webodf/flashput/Request.as | 83 + .../src/webodf/webodf/flashput/test.html | 96 + apps/files_odfviewer/src/webodf/webodf/gui.js | 263 + .../src/webodf/webodf/httpserver.js | 213 + .../src/webodf/webodf/index.html | 17 + .../src/webodf/webodf/lib/core/Async.js | 65 + .../src/webodf/webodf/lib/core/Base64.js | 362 + .../src/webodf/webodf/lib/core/ByteArray.js | 68 + .../webodf/webodf/lib/core/ByteArrayWriter.js | 101 + .../src/webodf/webodf/lib/core/Cursor.js | 213 + .../src/webodf/webodf/lib/core/JSLint.js | 6403 ++++++ .../src/webodf/webodf/lib/core/PointWalker.js | 197 + .../src/webodf/webodf/lib/core/RawDeflate.js | 1833 ++ .../src/webodf/webodf/lib/core/RawInflate.js | 790 + .../src/webodf/webodf/lib/core/UnitTester.js | 255 + .../src/webodf/webodf/lib/core/Zip.js | 600 + .../webodf/webodf/lib/core/dummyxmlmodel.js_ | 21 + .../src/webodf/webodf/lib/export.js | 39 + .../src/webodf/webodf/lib/gui/Caret.js | 65 + .../src/webodf/webodf/lib/gui/PresenterUI.js | 246 + .../webodf/webodf/lib/gui/SelectionMover.js | 217 + .../src/webodf/webodf/lib/gui/XMLEdit.js | 330 + .../src/webodf/webodf/lib/manifest.js | 34 + .../src/webodf/webodf/lib/odf/FontLoader.js | 135 + .../src/webodf/webodf/lib/odf/Formatting.js | 153 + .../src/webodf/webodf/lib/odf/OdfCanvas.js | 912 + .../src/webodf/webodf/lib/odf/OdfContainer.js | 672 + .../src/webodf/webodf/lib/odf/Style2CSS.js | 632 + .../src/webodf/webodf/lib/odf/StyleInfo.js | 424 + .../src/webodf/webodf/lib/packages.js | 48 + .../src/webodf/webodf/lib/runtime.js | 1117 + .../webodf/webodf/lib/xmldom/LSSerializer.js | 197 + .../webodf/lib/xmldom/LSSerializerFilter.js | 40 + .../lib/xmldom/OperationalTransformDOM.js | 115 + .../xmldom/OperationalTransformInterface.js | 97 + .../src/webodf/webodf/lib/xmldom/RelaxNG.js | 691 + .../src/webodf/webodf/lib/xmldom/RelaxNG2.js | 416 + .../webodf/webodf/lib/xmldom/RelaxNGParser.js | 452 + .../src/webodf/webodf/lib/xmldom/XPath.js | 383 + .../webodf/webodf/misctests/carettest.html | 135 + .../webodf/webodf/misctests/selection.html | 27 + .../webodf/misctests/testselection.html | 61 + .../src/webodf/webodf/misctests/testzip.js | 181 + .../src/webodf/webodf/misctests/writetest.zip | Bin 0 -> 153 bytes apps/files_odfviewer/src/webodf/webodf/notes | 137 + .../src/webodf/webodf/odf.html | 44 + .../src/webodf/webodf/odfedit.html | 27 + .../src/webodf/webodf/odfedit.js | 314 + .../src/webodf/webodf/relaxngToCPP.js | 463 + .../src/webodf/webodf/relaxngtests/test01.rng | 36 + .../src/webodf/webodf/relaxngtests/test01.xml | 8 + .../src/webodf/webodf/relaxngtests/test02.rng | 80 + .../src/webodf/webodf/relaxngtests/test02.xml | 12 + .../src/webodf/webodf/relaxngtests/test03.rng | 16 + .../src/webodf/webodf/relaxngtests/test03.xml | 6 + .../src/webodf/webodf/relaxngtests/test04.rng | 18 + .../src/webodf/webodf/relaxngtests/test04.xml | 5 + .../src/webodf/webodf/relaxngtests/test05.rng | 42 + .../src/webodf/webodf/relaxngtests/test05.xml | 9 + .../src/webodf/webodf/relaxngtests/test06.rng | 11 + .../src/webodf/webodf/relaxngtests/test06.xml | 4 + .../src/webodf/webodf/relaxngtests/test07.rng | 52 + .../src/webodf/webodf/relaxngtests/test07.xml | 14 + .../src/webodf/webodf/relaxngtests/test08.rng | 52 + .../src/webodf/webodf/relaxngtests/test08.xml | 14 + .../src/webodf/webodf/relaxngtests/test09.rng | 30 + .../src/webodf/webodf/relaxngtests/test09.xml | 14 + .../src/webodf/webodf/relaxngtests/test10.rng | 50 + .../src/webodf/webodf/relaxngtests/test10.xml | 13 + .../src/webodf/webodf/relaxngtests/test11.rng | 75 + .../src/webodf/webodf/relaxngtests/test11.xml | 12 + .../src/webodf/webodf/relaxngtests/test12.rng | 97 + .../src/webodf/webodf/relaxngtests/test12.xml | 15 + .../src/webodf/webodf/relaxngtests/test13.rng | 71 + .../src/webodf/webodf/relaxngtests/test13.xml | 17 + .../src/webodf/webodf/relaxngtests/test14.rng | 45 + .../src/webodf/webodf/relaxngtests/test14.xml | 12 + .../src/webodf/webodf/relaxngtests/test15.rng | 47 + .../src/webodf/webodf/relaxngtests/test15.xml | 18 + .../src/webodf/webodf/relaxngtests/test16.rng | 46 + .../src/webodf/webodf/relaxngtests/test16.xml | 18 + .../src/webodf/webodf/relaxngtests/test17.rng | 51 + .../src/webodf/webodf/relaxngtests/test17.xml | 17 + .../src/webodf/webodf/relaxngtests/test18.rng | 25 + .../src/webodf/webodf/relaxngtests/test18.xml | 6 + .../src/webodf/webodf/relaxngtests/test19.rng | 43 + .../src/webodf/webodf/relaxngtests/test19.xml | 11 + .../src/webodf/webodf/relaxngtests/test20.rng | 32 + .../src/webodf/webodf/relaxngtests/test20.xml | 11 + .../src/webodf/webodf/relaxngtests/test21.rng | 47 + .../src/webodf/webodf/relaxngtests/test21.xml | 11 + .../src/webodf/webodf/relaxngtests/test22.rng | 32 + .../src/webodf/webodf/relaxngtests/test22.xml | 11 + .../src/webodf/webodf/relaxngtests/test23.rng | 33 + .../src/webodf/webodf/relaxngtests/test23.xml | 4 + .../src/webodf/webodf/roundtripodf.js | 71 + .../src/webodf/webodf/roundtripzip.js | 64 + .../src/webodf/webodf/styleNameRef | 272 + .../src/webodf/webodf/styleNameRefs | 57 + .../src/webodf/webodf/testrelaxng.js | 91 + .../webodf/webodf/tests/core/Base64Tests.js | 105 + .../webodf/webodf/tests/core/CursorTests.js | 238 + .../webodf/tests/core/PointWalkerTests.js | 135 + .../webodf/webodf/tests/core/RuntimeTests.js | 119 + .../src/webodf/webodf/tests/core/ZipTests.js | 141 + .../webodf/tests/core/hi-compressed.zip | Bin 0 -> 172 bytes .../webodf/tests/core/hi-uncompressed.zip | Bin 0 -> 176 bytes .../src/webodf/webodf/tests/gui/CaretTests.js | 82 + .../webodf/tests/gui/SelectionMoverTests.js | 109 + .../webodf/webodf/tests/gui/XMLEditTests.js | 156 + .../src/webodf/webodf/tests/manifest.js | 16 + .../webodf/tests/resources/js-test-style.css | 12 + .../src/webodf/webodf/tests/tests.html | 22 + .../src/webodf/webodf/tests/tests.js | 94 + .../xmldom/OperationalTransformDOMTests.js | 79 + .../webodf/webodf/tests/xmldom/XPathTests.js | 112 + .../webodf/tools/clippingTestImage.html | 39 + .../src/webodf/webodf/tools/externs.js | 348 + .../src/webodf/webodf/tools/extjsexterns.js | 171 + .../src/webodf/webodf/tools/fixLicenses.py | 81 + .../webodf/tools/refcheck/bootstrap.xsl | 193 + .../webodf/webodf/tools/refcheck/odfkeys.xml | 455 + .../src/webodf/webodf/tools/runjslint.js | 98 + .../src/webodf/webodf/webodf.css | 200 + .../src/webodf/webodf/xmledit/gui.js | 119 + .../src/webodf/webodf/xmledit/index.html | 16 + .../webodf/webodf/xmledit/requirements.dtd | 12 + .../webodf/webodf/xmledit/requirements.xml | 22 + .../src/webodf/webodf/xmledit/test.xml | 22 + 289 files changed, 112818 insertions(+) create mode 100644 apps/files_odfviewer/appinfo/app.php create mode 100644 apps/files_odfviewer/appinfo/info.xml create mode 100644 apps/files_odfviewer/css/odfviewer.css create mode 100644 apps/files_odfviewer/css/webodf.css create mode 100644 apps/files_odfviewer/js/viewer.js create mode 100644 apps/files_odfviewer/js/webodf-debug.js create mode 100644 apps/files_odfviewer/js/webodf.js create mode 100644 apps/files_odfviewer/src/.gitignore create mode 100755 apps/files_odfviewer/src/update.sh create mode 100644 apps/files_odfviewer/src/webodf/.gitignore create mode 100644 apps/files_odfviewer/src/webodf/.gitmodules create mode 100644 apps/files_odfviewer/src/webodf/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/JSCoverage.patch create mode 100644 apps/files_odfviewer/src/webodf/packwebodf.js create mode 100644 apps/files_odfviewer/src/webodf/programs/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/android/AndroidManifest.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/android/assets/www/config.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/assets/www/icon.png create mode 100644 apps/files_odfviewer/src/webodf/programs/android/assets/www/index.html create mode 100644 apps/files_odfviewer/src/webodf/programs/android/assets/www/phonegap-1.4.1.js create mode 100644 apps/files_odfviewer/src/webodf/programs/android/assets/www/scripts.js create mode 100644 apps/files_odfviewer/src/webodf/programs/android/libs/phonegap-1.4.1.jar create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/drawable-hdpi/ic_launcher.png create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/drawable-ldpi/ic_launcher.png create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/drawable-mdpi/ic_launcher.png create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/drawable/icon.png create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/layout/listitem.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/layout/main.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/layout/selector.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/values/strings.xml create mode 100755 apps/files_odfviewer/src/webodf/programs/android/res/xml/phonegap.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/res/xml/plugins.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/android/src/org/webodf/WebODFActivity.java create mode 100755 apps/files_odfviewer/src/webodf/programs/android/updateWebODF.sh create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.0-os.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.1.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.0-os.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.1.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.0-os.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.1.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-dsig-schema.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-manifest-schema.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-schema.rng create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/application-vnd.oasis.opendocument.presentation.png create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/application-vnd.oasis.opendocument.spreadsheet.png create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/application-vnd.oasis.opendocument.text.png create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/docnosis.js create mode 100644 apps/files_odfviewer/src/webodf/programs/docnosis/index.html create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/bootstrap.js create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/chrome.manifest create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/components/odfContentHandler.js create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/content/odf.html create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/install.rdf.in create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/packextension.js create mode 100644 apps/files_odfviewer/src/webodf/programs/firefoxextension/skin/default/icon.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/Default-Landscape~ipad.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/Default-Portrait~ipad.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF.xcodeproj/project.pbxproj create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/AppDelegate.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/AppDelegate.m create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.m create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.xib create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.m create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.m create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.m create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/crypt.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.c create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.c create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.c create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/zip.h create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/PhoneGap.plist create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/en.lproj/Localizable.strings create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon-72.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon@2x.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default-Landscape~ipad.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default-Portrait~ipad.png create mode 100755 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default.png create mode 100755 apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default@2x.png create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Info.plist create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Prefix.pch create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/en.lproj/InfoPlist.strings create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/WebODF/main.m create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/www/index.html create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/www/nativezip.js create mode 100644 apps/files_odfviewer/src/webodf/programs/ios/www/phonegap-1.4.1.js create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/README create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/application.qrc create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/main.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.h create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.ui create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.h create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.h create mode 100644 apps/files_odfviewer/src/webodf/programs/nativeQtClient/scripts.js create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/build_sign.bat create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/config.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_dispatcher.js create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_ns.js create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/library.xml create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/src/AIR/CustomFileReader/src/blackberry/custom/filereader/CustomFileReader.as create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/icon.png create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/index.html create mode 100644 apps/files_odfviewer/src/webodf/programs/playbook/scripts.js create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/nam.h create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.h create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.h create mode 100644 apps/files_odfviewer/src/webodf/programs/qtjsruntime/qtjsruntime.cpp create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/ZoomIn.png create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/ZoomOut.png create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/app.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/controller/Files.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/model/FileSystem.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/store/FileStore.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/views/FileDetail.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/views/FilesList.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/views/OdfView.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/app/views/Viewport.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/go-next.png create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/go-previous.png create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/index.html create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/scripts.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.css create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.js create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/welcome.odt create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-best.png create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-height.png create mode 100644 apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-width.png create mode 100755 apps/files_odfviewer/src/webodf/simplerevisionserver/webdavserver.py create mode 100644 apps/files_odfviewer/src/webodf/webodf/APPNOTE.txt create mode 100644 apps/files_odfviewer/src/webodf/webodf/CMakeLists.txt create mode 100644 apps/files_odfviewer/src/webodf/webodf/README create mode 100644 apps/files_odfviewer/src/webodf/webodf/compare.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/compare.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/deflateinmozilla.txt create mode 100644 apps/files_odfviewer/src/webodf/webodf/embedodf.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/filelist.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/filelister.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/filelister.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/flashput/Makefile create mode 100644 apps/files_odfviewer/src/webodf/webodf/flashput/PUT.as create mode 100644 apps/files_odfviewer/src/webodf/webodf/flashput/PUT.swf create mode 100644 apps/files_odfviewer/src/webodf/webodf/flashput/Request.as create mode 100644 apps/files_odfviewer/src/webodf/webodf/flashput/test.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/gui.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/httpserver.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/index.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/Async.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/Base64.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArray.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArrayWriter.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/Cursor.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/JSLint.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/PointWalker.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/RawDeflate.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/RawInflate.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/UnitTester.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/Zip.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/core/dummyxmlmodel.js_ create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/export.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/gui/Caret.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/gui/PresenterUI.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/gui/SelectionMover.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/gui/XMLEdit.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/manifest.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/odf/FontLoader.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/odf/Formatting.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfCanvas.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfContainer.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/odf/Style2CSS.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/odf/StyleInfo.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/packages.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/runtime.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializer.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializerFilter.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformDOM.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformInterface.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG2.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNGParser.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/lib/xmldom/XPath.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/misctests/carettest.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/misctests/selection.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/misctests/testselection.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/misctests/testzip.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/misctests/writetest.zip create mode 100644 apps/files_odfviewer/src/webodf/webodf/notes create mode 100644 apps/files_odfviewer/src/webodf/webodf/odf.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/odfedit.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/odfedit.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngToCPP.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.rng create mode 100644 apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/roundtripodf.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/roundtripzip.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/styleNameRef create mode 100644 apps/files_odfviewer/src/webodf/webodf/styleNameRefs create mode 100644 apps/files_odfviewer/src/webodf/webodf/testrelaxng.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/Base64Tests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/CursorTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/PointWalkerTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/RuntimeTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/ZipTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/hi-compressed.zip create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/core/hi-uncompressed.zip create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/gui/CaretTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/gui/SelectionMoverTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/gui/XMLEditTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/manifest.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/resources/js-test-style.css create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/tests.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/tests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/xmldom/OperationalTransformDOMTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tests/xmldom/XPathTests.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tools/clippingTestImage.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/tools/externs.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/tools/extjsexterns.js create mode 100755 apps/files_odfviewer/src/webodf/webodf/tools/fixLicenses.py create mode 100644 apps/files_odfviewer/src/webodf/webodf/tools/refcheck/bootstrap.xsl create mode 100644 apps/files_odfviewer/src/webodf/webodf/tools/refcheck/odfkeys.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/tools/runjslint.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/webodf.css create mode 100644 apps/files_odfviewer/src/webodf/webodf/xmledit/gui.js create mode 100644 apps/files_odfviewer/src/webodf/webodf/xmledit/index.html create mode 100644 apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.dtd create mode 100644 apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.xml create mode 100644 apps/files_odfviewer/src/webodf/webodf/xmledit/test.xml diff --git a/apps/files_odfviewer/appinfo/app.php b/apps/files_odfviewer/appinfo/app.php new file mode 100644 index 0000000000..f5fe338c0e --- /dev/null +++ b/apps/files_odfviewer/appinfo/app.php @@ -0,0 +1,5 @@ + + + files_odfviewer + ODF Viewer + Simple ODF viewer for owncloud + 0.1 + AGPL + Thomas Müller + 4 + true + + diff --git a/apps/files_odfviewer/css/odfviewer.css b/apps/files_odfviewer/css/odfviewer.css new file mode 100644 index 0000000000..097276a00f --- /dev/null +++ b/apps/files_odfviewer/css/odfviewer.css @@ -0,0 +1,20 @@ +#odf-canvas{ + position: relative; + top: 37px; + left: 1px; + border:1px solid darkgray; + box-shadow: 0px 4px 10px #000; + -moz-box-shadow: 0px 4px 10px #000; + -webkit-box-shadow: 0px 4px 10px #000; +} + +#odf_close{ + margin-left: auto; + margin-right: 167px; + float: right; +} + +#odf-toolbar{ + padding: 0 0 0 1em +} + diff --git a/apps/files_odfviewer/css/webodf.css b/apps/files_odfviewer/css/webodf.css new file mode 100644 index 0000000000..0ceca2f851 --- /dev/null +++ b/apps/files_odfviewer/css/webodf.css @@ -0,0 +1,196 @@ +@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0); +@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0); +@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0); +@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0); +@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0); +@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0); +@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0); +@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0); +@namespace runtimens url(urn:webodf); /* namespace for runtime only */ + +office|document > *, office|document-content > * { + display: none; +} +office|body, office|document { + display: inline-block; + position: relative; +} + +text|p, text|h { + display: block; + padding: 3px 3px 3px 3px; + margin: 5px 5px 5px 5px; +} +text|h { + font-weight: bold; +} +*[runtimens|containsparagraphanchor] { + position: relative; +} +text|s:before { /* this needs to be the number of spaces given by text:c */ + content: ' '; +} +text|tab:before { + display: inline; + content: ' '; +} +text|line-break { + content: " "; + display: block; +} +text|tracked-changes { + /*Consumers that do not support change tracking, should ignore changes.*/ + display: none; +} +office|binary-data { + display: none; +} +office|text { + display: block; + width: 216mm; /* default to A4 width */ + min-height: 279mm; + padding-left: 32mm; + padding-right: 32mm; + padding-top: 25mm; + padding-bottom: 13mm; + margin: 2px; + text-align: left; + overflow: hidden; +} +office|spreadsheet { + display: block; + border-collapse: collapse; + empty-cells: show; + font-family: sans-serif; + font-size: 10pt; + text-align: left; + page-break-inside: avoid; + overflow: hidden; +} +office|presentation { + display: inline-block; + text-align: left; +} +draw|page { + display: block; + height: 21cm; + width: 28cm; + margin: 3px; + position: relative; + overflow: hidden; +} +presentation|notes { + display: none; +} +@media print { + draw|page { + border: 1pt solid black; + page-break-inside: avoid; + } + presentation|notes { + /*TODO*/ + } +} +office|spreadsheet text|p { + border: 0px; + padding: 1px; + margin: 0px; +} +office|spreadsheet table|table { + margin: 3px; +} +office|spreadsheet table|table:after { + /* show sheet name the end of the sheet */ + /*content: attr(table|name);*/ /* gives parsing error in opera */ +} +office|spreadsheet table|table-row { + counter-increment: row; +} +office|spreadsheet table|table-row:before { + width: 3em; + background: #cccccc; + border: 1px solid black; + text-align: center; + content: counter(row); +} +office|spreadsheet table|table-cell { + border: 1px solid #cccccc; +} +table|table { + display: table; +} +draw|frame table|table { + width: 100%; + height: 100%; + background: white; +} +table|table-row { + display: table-row; +} +table|table-column { + display: table-column; +} +table|table-cell { + display: table-cell; +} +draw|frame { + display: block; +} +draw|image { + display: block; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + background-repeat: no-repeat; + background-size: 100% 100%; + -moz-background-size: 100% 100%; +} +/* only show the first image in frame */ +draw|frame > draw|image:nth-of-type(n+2) { + display: none; +} +text|list { + display: block; + padding-left: 1.5em; + counter-reset: list; +} +text|list-item { + display: block; +} +text|list-item:before { + display: inline-block; + content: '•'; + counter-increment: list; + width: 0.5em; + margin-left: -0.5em; + padding: 0px; + border: 0px; +} +text|list-item > *:first-child { + display: inline-block; +} +text|a { + color: blue; + text-decoration: underline; +} +text|note-citation { + vertical-align: super; + font-size: smaller; +} +text|note-body { + display: none; +} +text|note:hover text|note-citation { + background: #dddddd; +} +text|note:hover text|note-body { + display: block; + left:1em; + max-width: 80%; + position: absolute; + background: #ffffaa; +} +svg|title, svg|desc { + display: none; +} diff --git a/apps/files_odfviewer/js/viewer.js b/apps/files_odfviewer/js/viewer.js new file mode 100644 index 0000000000..586da12687 --- /dev/null +++ b/apps/files_odfviewer/js/viewer.js @@ -0,0 +1,60 @@ +function viewOdf(dir, file) { + var location=OC.filePath('files','ajax','download.php')+'?files='+file+'&dir='+dir; + + // fade out files menu and add odf menu + $('.actions,#file_action_panel').fadeOut('slow').promise().done(function() { + // odf action toolbar + var odfToolbarHtml = + '
' + + '' + + '
'; + $('#controls').append(odfToolbarHtml); + + }); + + // fade out file list and show pdf canvas + $('table').fadeOut('slow').promise().done(function(){; + var canvashtml = '
'; + $('table').after(canvashtml); + + var odfelement = document.getElementById("odf-canvas"); + var odfcanvas = new odf.OdfCanvas(odfelement); + odfcanvas.load(location); + }); +} + +function closeOdfViewer(){ + // Fade out odf-toolbar + $('#odf-toolbar').fadeOut('slow'); + // Fade out editor + $('#odf-canvas').fadeOut('slow', function(){ + $('#odf-toolbar').remove(); + $('#odf-canvas').remove(); + $('.actions,#file_access_panel').fadeIn('slow'); + $('table').fadeIn('slow'); + }); + is_editor_shown = false; +} + +$(document).ready(function() { + if(typeof FileActions!=='undefined'){ + + var supportedMimes = new Array( + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.graphics', + 'application/vnd.oasis.opendocument.presentation'); + for (var i = 0; i < supportedMimes.length; ++i){ + var mime = supportedMimes[i]; + FileActions.register(mime,'View','',function(filename){ + viewOdf($('#dir').val(),filename); + }); + FileActions.setDefault(mime,'View'); + } + } + + $('#odf_close').live('click',function() { + closeOdfViewer(); + }); +}); + diff --git a/apps/files_odfviewer/js/webodf-debug.js b/apps/files_odfviewer/js/webodf-debug.js new file mode 100644 index 0000000000..6c7c7e1d6f --- /dev/null +++ b/apps/files_odfviewer/js/webodf-debug.js @@ -0,0 +1,7124 @@ +/* + + @licstart + The JavaScript code in this page is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License + (GNU AGPL) as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. The code is distributed + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + + As additional permission under GNU AGPL version 3 section 7, you + may distribute non-source (e.g., minimized or compacted) forms of + that code without the copy of the GNU GPL normally required by + section 4, provided you include this license notice and a URL + through which recipients can access the Corresponding Source. + + As a special exception to the AGPL, any HTML file which merely makes function + calls to this code, and for that purpose includes it by reference shall be + deemed a separate work for copyright law purposes. In addition, the copyright + holders of this code give you permission to combine this code with free + software libraries that are released under the GNU LGPL. You may copy and + distribute such a system following the terms of the GNU AGPL for this code + and the LGPL for the libraries. If you modify this code, you may extend this + exception to your version of the code, but you are not obligated to do so. + If you do not wish to do so, delete this exception statement from your + version. + + This license applies to this entire compilation. + @licend + @source: http://www.webodf.org/ + @source: http://gitorious.org/odfkit/webodf/ +*/ +var core = {}; +var gui = {}; +var xmldom = {}; +var odf = {}; +function Runtime() { +} +Runtime.ByteArray = function(size) { +}; +Runtime.ByteArray.prototype.slice = function(start, end) { +}; +Runtime.prototype.byteArrayFromArray = function(array) { +}; +Runtime.prototype.byteArrayFromString = function(string, encoding) { +}; +Runtime.prototype.byteArrayToString = function(bytearray, encoding) { +}; +Runtime.prototype.concatByteArrays = function(bytearray1, bytearray2) { +}; +Runtime.prototype.read = function(path, offset, length, callback) { +}; +Runtime.prototype.readFile = function(path, encoding, callback) { +}; +Runtime.prototype.readFileSync = function(path, encoding) { +}; +Runtime.prototype.loadXML = function(path, callback) { +}; +Runtime.prototype.writeFile = function(path, data, callback) { +}; +Runtime.prototype.isFile = function(path, callback) { +}; +Runtime.prototype.getFileSize = function(path, callback) { +}; +Runtime.prototype.deleteFile = function(path, callback) { +}; +Runtime.prototype.log = function(msgOrCategory, msg) { +}; +Runtime.prototype.setTimeout = function(callback, milliseconds) { +}; +Runtime.prototype.libraryPaths = function() { +}; +Runtime.prototype.type = function() { +}; +Runtime.prototype.getDOMImplementation = function() { +}; +Runtime.prototype.getWindow = function() { +}; +var IS_COMPILED_CODE = false; +Runtime.byteArrayToString = function(bytearray, encoding) { + function byteArrayToString(bytearray) { + var s = "", i, l = bytearray.length; + for(i = 0;i < l;i += 1) { + s += String.fromCharCode(bytearray[i] & 255) + } + return s + } + function utf8ByteArrayToString(bytearray) { + var s = "", i, l = bytearray.length, c0, c1, c2; + for(i = 0;i < l;i += 1) { + c0 = bytearray[i]; + if(c0 < 128) { + s += String.fromCharCode(c0) + }else { + i += 1; + c1 = bytearray[i]; + if(c0 < 224) { + s += String.fromCharCode((c0 & 31) << 6 | c1 & 63) + }else { + i += 1; + c2 = bytearray[i]; + s += String.fromCharCode((c0 & 15) << 12 | (c1 & 63) << 6 | c2 & 63) + } + } + } + return s + } + var result; + if(encoding === "utf8") { + result = utf8ByteArrayToString(bytearray) + }else { + if(encoding !== "binary") { + this.log("Unsupported encoding: " + encoding) + } + result = byteArrayToString(bytearray) + } + return result +}; +Runtime.getFunctionName = function getFunctionName(f) { + var m; + if(f.name === undefined) { + m = (new RegExp("function\\s+(\\w+)")).exec(f); + return m && m[1] + } + return f.name +}; +function BrowserRuntime(logoutput) { + var self = this, cache = {}, useNativeArray = window.ArrayBuffer && window.Uint8Array; + this.ByteArray = useNativeArray ? function ByteArray(size) { + Uint8Array.prototype.slice = function(begin, end) { + if(end === undefined) { + if(begin === undefined) { + begin = 0 + } + end = this.length + } + var view = this.subarray(begin, end), array, i; + end -= begin; + array = new Uint8Array(new ArrayBuffer(end)); + for(i = 0;i < end;i += 1) { + array[i] = view[i] + } + return array + }; + return new Uint8Array(new ArrayBuffer(size)) + } : function ByteArray(size) { + var a = []; + a.length = size; + return a + }; + this.concatByteArrays = useNativeArray ? function(bytearray1, bytearray2) { + var i, l1 = bytearray1.length, l2 = bytearray2.length, a = new this.ByteArray(l1 + l2); + for(i = 0;i < l1;i += 1) { + a[i] = bytearray1[i] + } + for(i = 0;i < l2;i += 1) { + a[i + l1] = bytearray2[i] + } + return a + } : function(bytearray1, bytearray2) { + return bytearray1.concat(bytearray2) + }; + function utf8ByteArrayFromString(string) { + var l = string.length, bytearray, i, n, j = 0; + for(i = 0;i < l;i += 1) { + n = string.charCodeAt(i); + j += 1 + (n > 128) + (n > 2048) + } + bytearray = new self.ByteArray(j); + j = 0; + for(i = 0;i < l;i += 1) { + n = string.charCodeAt(i); + if(n < 128) { + bytearray[j] = n; + j += 1 + }else { + if(n < 2048) { + bytearray[j] = 192 | n >>> 6; + bytearray[j + 1] = 128 | n & 63; + j += 2 + }else { + bytearray[j] = 224 | n >>> 12 & 15; + bytearray[j + 1] = 128 | n >>> 6 & 63; + bytearray[j + 2] = 128 | n & 63; + j += 3 + } + } + } + return bytearray + } + function byteArrayFromString(string) { + var l = string.length, a = new self.ByteArray(l), i; + for(i = 0;i < l;i += 1) { + a[i] = string.charCodeAt(i) & 255 + } + return a + } + this.byteArrayFromArray = function(array) { + return array.slice() + }; + this.byteArrayFromString = function(string, encoding) { + var result; + if(encoding === "utf8") { + result = utf8ByteArrayFromString(string) + }else { + if(encoding !== "binary") { + self.log("unknown encoding: " + encoding) + } + result = byteArrayFromString(string) + } + return result + }; + this.byteArrayToString = Runtime.byteArrayToString; + function log(msgOrCategory, msg) { + var node, doc, category; + if(msg) { + category = msgOrCategory + }else { + msg = msgOrCategory + } + if(logoutput) { + doc = logoutput.ownerDocument; + if(category) { + node = doc.createElement("span"); + node.className = category; + node.appendChild(doc.createTextNode(category)); + logoutput.appendChild(node); + logoutput.appendChild(doc.createTextNode(" ")) + } + node = doc.createElement("span"); + node.appendChild(doc.createTextNode(msg)); + logoutput.appendChild(node); + logoutput.appendChild(doc.createElement("br")) + }else { + if(console) { + console.log(msg) + } + } + } + function readFile(path, encoding, callback) { + if(cache.hasOwnProperty(path)) { + callback(null, cache[path]); + return + } + var xhr = new XMLHttpRequest; + function handleResult() { + var data; + if(xhr.readyState === 4) { + if(xhr.status === 0 && !xhr.responseText) { + callback("File " + path + " is empty.") + }else { + if(xhr.status === 200 || xhr.status === 0) { + if(encoding === "binary") { + if(typeof VBArray !== "undefined") { + data = (new VBArray(xhr.responseBody)).toArray() + }else { + data = self.byteArrayFromString(xhr.responseText, "binary") + } + }else { + data = xhr.responseText + } + cache[path] = data; + callback(null, data) + }else { + callback(xhr.responseText || xhr.statusText) + } + } + } + } + xhr.open("GET", path, true); + xhr.onreadystatechange = handleResult; + if(xhr.overrideMimeType) { + if(encoding !== "binary") { + xhr.overrideMimeType("text/plain; charset=" + encoding) + }else { + xhr.overrideMimeType("text/plain; charset=x-user-defined") + } + } + try { + xhr.send(null) + }catch(e) { + callback(e.message) + } + } + function read(path, offset, length, callback) { + if(cache.hasOwnProperty(path)) { + callback(null, cache[path].slice(offset, offset + length)); + return + } + var xhr = new XMLHttpRequest; + function handleResult() { + var data; + if(xhr.readyState === 4) { + if(xhr.status === 0 && !xhr.responseText) { + callback("File " + path + " is empty.") + }else { + if(xhr.status === 200 || xhr.status === 0) { + if(typeof VBArray !== "undefined") { + data = (new VBArray(xhr.responseBody)).toArray() + }else { + data = self.byteArrayFromString(xhr.responseText, "binary") + } + cache[path] = data; + callback(null, data.slice(offset, offset + length)) + }else { + callback(xhr.responseText || xhr.statusText) + } + } + } + } + xhr.open("GET", path, true); + xhr.onreadystatechange = handleResult; + if(xhr.overrideMimeType) { + xhr.overrideMimeType("text/plain; charset=x-user-defined") + } + try { + xhr.send(null) + }catch(e) { + callback(e.message) + } + } + function readFileSync(path, encoding) { + var xhr = new XMLHttpRequest, result; + xhr.open("GET", path, false); + if(xhr.overrideMimeType) { + if(encoding !== "binary") { + xhr.overrideMimeType("text/plain; charset=" + encoding) + }else { + xhr.overrideMimeType("text/plain; charset=x-user-defined") + } + } + try { + xhr.send(null); + if(xhr.status === 200 || xhr.status === 0) { + result = xhr.responseText + } + }catch(e) { + } + return result + } + function writeFile(path, data, callback) { + cache[path] = data; + var xhr = new XMLHttpRequest; + function handleResult() { + if(xhr.readyState === 4) { + if(xhr.status === 0 && !xhr.responseText) { + callback("File " + path + " is empty.") + }else { + if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 0) { + callback(null) + }else { + callback("Status " + String(xhr.status) + ": " + xhr.responseText || xhr.statusText) + } + } + } + } + xhr.open("PUT", path, true); + xhr.onreadystatechange = handleResult; + if(data.buffer && !xhr.sendAsBinary) { + data = data.buffer + }else { + data = self.byteArrayToString(data, "binary") + } + try { + if(xhr.sendAsBinary) { + xhr.sendAsBinary(data) + }else { + xhr.send(data) + } + }catch(e) { + self.log("HUH? " + e + " " + data); + callback(e.message) + } + } + function deleteFile(path, callback) { + var xhr = new XMLHttpRequest; + xhr.open("DELETE", path, true); + xhr.onreadystatechange = function() { + if(xhr.readyState === 4) { + if(xhr.status < 200 && xhr.status >= 300) { + callback(xhr.responseText) + }else { + callback(null) + } + } + }; + xhr.send(null) + } + function loadXML(path, callback) { + var xhr = new XMLHttpRequest; + function handleResult() { + if(xhr.readyState === 4) { + if(xhr.status === 0 && !xhr.responseText) { + callback("File " + path + " is empty.") + }else { + if(xhr.status === 200 || xhr.status === 0) { + callback(null, xhr.responseXML) + }else { + callback(xhr.responseText) + } + } + } + } + xhr.open("GET", path, true); + if(xhr.overrideMimeType) { + xhr.overrideMimeType("text/xml") + } + xhr.onreadystatechange = handleResult; + try { + xhr.send(null) + }catch(e) { + callback(e.message) + } + } + function isFile(path, callback) { + self.getFileSize(path, function(size) { + callback(size !== -1) + }) + } + function getFileSize(path, callback) { + var xhr = new XMLHttpRequest; + xhr.open("HEAD", path, true); + xhr.onreadystatechange = function() { + if(xhr.readyState !== 4) { + return + } + var cl = xhr.getResponseHeader("Content-Length"); + if(cl) { + callback(parseInt(cl, 10)) + }else { + callback(-1) + } + }; + xhr.send(null) + } + function wrap(nativeFunction, nargs) { + if(!nativeFunction) { + return null + } + return function() { + cache = {}; + var callback = arguments[nargs], args = Array.prototype.slice.call(arguments, 0, nargs), callbackname = "callback" + String(Math.random()).substring(2); + window[callbackname] = function() { + delete window[callbackname]; + callback.apply(this, arguments) + }; + args.push(callbackname); + nativeFunction.apply(this, args) + } + } + this.readFile = readFile; + this.read = read; + this.readFileSync = readFileSync; + this.writeFile = writeFile; + this.deleteFile = deleteFile; + this.loadXML = loadXML; + this.isFile = isFile; + this.getFileSize = getFileSize; + this.log = log; + this.setTimeout = function(f, msec) { + setTimeout(function() { + f() + }, msec) + }; + this.libraryPaths = function() { + return["lib"] + }; + this.setCurrentDirectory = function(dir) { + }; + this.type = function() { + return"BrowserRuntime" + }; + this.getDOMImplementation = function() { + return window.document.implementation + }; + this.exit = function(exitCode) { + log("Calling exit with code " + String(exitCode) + ", but exit() is not implemented.") + }; + this.getWindow = function() { + return window + } +} +function NodeJSRuntime() { + var self = this, fs = require("fs"), currentDirectory = ""; + this.ByteArray = function(size) { + return new Buffer(size) + }; + this.byteArrayFromArray = function(array) { + var ba = new Buffer(array.length), i, l = array.length; + for(i = 0;i < l;i += 1) { + ba[i] = array[i] + } + return ba + }; + this.concatByteArrays = function(a, b) { + var ba = new Buffer(a.length + b.length); + a.copy(ba, 0, 0); + b.copy(ba, a.length, 0); + return ba + }; + this.byteArrayFromString = function(string, encoding) { + return new Buffer(string, encoding) + }; + this.byteArrayToString = function(bytearray, encoding) { + return bytearray.toString(encoding) + }; + function isFile(path, callback) { + if(currentDirectory) { + path = currentDirectory + "/" + path + } + fs.stat(path, function(err, stats) { + callback(!err && stats.isFile()) + }) + } + function loadXML(path, callback) { + throw"Not implemented."; + } + this.readFile = function(path, encoding, callback) { + if(encoding !== "binary") { + fs.readFile(path, encoding, callback) + }else { + fs.readFile(path, null, callback) + } + }; + this.writeFile = function(path, data, callback) { + fs.writeFile(path, data, "binary", function(err) { + callback(err || null) + }) + }; + this.deleteFile = fs.unlink; + this.read = function(path, offset, length, callback) { + if(currentDirectory) { + path = currentDirectory + "/" + path + } + fs.open(path, "r+", 666, function(err, fd) { + if(err) { + callback(err); + return + } + var buffer = new Buffer(length); + fs.read(fd, buffer, 0, length, offset, function(err, bytesRead) { + fs.close(fd); + callback(err, buffer) + }) + }) + }; + this.readFileSync = function(path, encoding) { + if(!encoding) { + return"" + } + return fs.readFileSync(path, encoding) + }; + this.loadXML = loadXML; + this.isFile = isFile; + this.getFileSize = function(path, callback) { + if(currentDirectory) { + path = currentDirectory + "/" + path + } + fs.stat(path, function(err, stats) { + if(err) { + callback(-1) + }else { + callback(stats.size) + } + }) + }; + this.log = function(msg) { + process.stderr.write(msg + "\n") + }; + this.setTimeout = function(f, msec) { + setTimeout(function() { + f() + }, msec) + }; + this.libraryPaths = function() { + return[__dirname] + }; + this.setCurrentDirectory = function(dir) { + currentDirectory = dir + }; + this.currentDirectory = function() { + return currentDirectory + }; + this.type = function() { + return"NodeJSRuntime" + }; + this.getDOMImplementation = function() { + return null + }; + this.exit = process.exit; + this.getWindow = function() { + return null + } +} +function RhinoRuntime() { + var self = this, dom = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(), builder, entityresolver, currentDirectory = ""; + dom.setValidating(false); + dom.setNamespaceAware(true); + dom.setExpandEntityReferences(false); + dom.setSchema(null); + entityresolver = Packages.org.xml.sax.EntityResolver({resolveEntity:function(publicId, systemId) { + var file, open = function(path) { + var reader = new Packages.java.io.FileReader(path), source = new Packages.org.xml.sax.InputSource(reader); + return source + }; + file = systemId; + return open(file) + }}); + builder = dom.newDocumentBuilder(); + builder.setEntityResolver(entityresolver); + this.ByteArray = function ByteArray(size) { + return[size] + }; + this.byteArrayFromArray = function(array) { + return array + }; + this.byteArrayFromString = function(string, encoding) { + var a = [], i, l = string.length; + for(i = 0;i < l;i += 1) { + a[i] = string.charCodeAt(i) & 255 + } + return a + }; + this.byteArrayToString = Runtime.byteArrayToString; + this.concatByteArrays = function(bytearray1, bytearray2) { + return bytearray1.concat(bytearray2) + }; + function loadXML(path, callback) { + var file = new Packages.java.io.File(path), document; + try { + document = builder.parse(file) + }catch(err) { + print(err); + callback(err); + return + } + callback(null, document) + } + function runtimeReadFile(path, encoding, callback) { + var file = new Packages.java.io.File(path), data, rhinoencoding = encoding === "binary" ? "latin1" : encoding; + if(!file.isFile()) { + callback(path + " is not a file.") + }else { + data = readFile(path, rhinoencoding); + if(encoding === "binary") { + data = self.byteArrayFromString(data, "binary") + } + callback(null, data) + } + } + function runtimeReadFileSync(path, encoding) { + var file = new Packages.java.io.File(path), data, i; + if(!file.isFile()) { + return null + } + if(encoding === "binary") { + encoding = "latin1" + } + return readFile(path, encoding) + } + function isFile(path, callback) { + if(currentDirectory) { + path = currentDirectory + "/" + path + } + var file = new Packages.java.io.File(path); + callback(file.isFile()) + } + this.loadXML = loadXML; + this.readFile = runtimeReadFile; + this.writeFile = function(path, data, callback) { + var out = new Packages.java.io.FileOutputStream(path), i, l = data.length; + for(i = 0;i < l;i += 1) { + out.write(data[i]) + } + out.close(); + callback(null) + }; + this.deleteFile = function(path, callback) { + var file = new Packages.java.io.File(path); + if(file["delete"]()) { + callback(null) + }else { + callback("Could not delete " + path) + } + }; + this.read = function(path, offset, length, callback) { + if(currentDirectory) { + path = currentDirectory + "/" + path + } + var data = runtimeReadFileSync(path, "binary"); + if(data) { + callback(null, this.byteArrayFromString(data.substring(offset, offset + length), "binary")) + }else { + callback("Cannot read " + path) + } + }; + this.readFileSync = function(path, encoding) { + if(!encoding) { + return"" + } + return readFile(path, encoding) + }; + this.isFile = isFile; + this.getFileSize = function(path, callback) { + if(currentDirectory) { + path = currentDirectory + "/" + path + } + var file = new Packages.java.io.File(path); + callback(file.length()) + }; + this.log = print; + this.setTimeout = function(f, msec) { + f() + }; + this.libraryPaths = function() { + return["lib"] + }; + this.setCurrentDirectory = function(dir) { + currentDirectory = dir + }; + this.currentDirectory = function() { + return currentDirectory + }; + this.type = function() { + return"RhinoRuntime" + }; + this.getDOMImplementation = function() { + return builder.getDOMImplementation() + }; + this.exit = quit; + this.getWindow = function() { + return null + } +} +var runtime = function() { + var result; + if(typeof window !== "undefined") { + result = new BrowserRuntime(window.document.getElementById("logoutput")) + }else { + if(typeof require !== "undefined") { + result = new NodeJSRuntime + }else { + result = new RhinoRuntime + } + } + return result +}(); +(function() { + var cache = {}, dircontents = {}; + function getOrDefinePackage(packageNameComponents) { + var topname = packageNameComponents[0], i, pkg; + pkg = eval("if (typeof " + topname + " === 'undefined') {" + "eval('" + topname + " = {};');}" + topname); + for(i = 1;i < packageNameComponents.length - 1;i += 1) { + if(!pkg.hasOwnProperty(packageNameComponents[i])) { + pkg = pkg[packageNameComponents[i]] = {} + } + } + return pkg[packageNameComponents[packageNameComponents.length - 1]] + } + runtime.loadClass = function(classpath) { + if(IS_COMPILED_CODE) { + return + } + if(cache.hasOwnProperty(classpath)) { + return + } + var names = classpath.split("."), impl; + impl = getOrDefinePackage(names); + if(impl) { + cache[classpath] = true; + return + } + function getPathFromManifests(classpath) { + var path = classpath.replace(".", "/") + ".js", dirs = runtime.libraryPaths(), i, dir, code; + if(runtime.currentDirectory) { + dirs.push(runtime.currentDirectory()) + } + for(i = 0;i < dirs.length;i += 1) { + dir = dirs[i]; + if(!dircontents.hasOwnProperty(dir)) { + code = runtime.readFileSync(dirs[i] + "/manifest.js", "utf8"); + if(code && code.length) { + try { + dircontents[dir] = eval(code) + }catch(e1) { + dircontents[dir] = null; + runtime.log("Cannot load manifest for " + dir + ".") + } + }else { + dircontents[dir] = null + } + } + code = null; + dir = dircontents[dir]; + if(dir && dir.indexOf && dir.indexOf(path) !== -1) { + return dirs[i] + "/" + path + } + } + return null + } + function load(classpath) { + var code, path; + path = getPathFromManifests(classpath); + if(!path) { + throw classpath + " is not listed in any manifest.js."; + } + try { + code = runtime.readFileSync(path, "utf8") + }catch(e2) { + runtime.log("Error loading " + classpath + " " + e2); + throw e2; + } + if(code === undefined) { + throw"Cannot load class " + classpath; + } + try { + code = eval(classpath + " = eval(code);") + }catch(e4) { + runtime.log("Error loading " + classpath + " " + e4); + throw e4; + } + return code + } + impl = load(classpath); + if(!impl || Runtime.getFunctionName(impl) !== names[names.length - 1]) { + runtime.log("Loaded code is not for " + names[names.length - 1]); + throw"Loaded code is not for " + names[names.length - 1]; + } + cache[classpath] = true + } +})(); +(function(args) { + args = Array.prototype.slice.call(args); + function run(argv) { + if(!argv.length) { + return + } + var script = argv[0]; + runtime.readFile(script, "utf8", function(err, code) { + var path = "", paths = runtime.libraryPaths(); + if(script.indexOf("/") !== -1) { + path = script.substring(0, script.indexOf("/")) + } + runtime.setCurrentDirectory(path); + function run() { + var script, path, paths, args, argv, result; + result = eval(code); + if(result) { + runtime.exit(result) + } + return + } + if(err) { + runtime.log(err); + runtime.exit(1) + }else { + run.apply(null, argv) + } + }) + } + if(runtime.type() === "NodeJSRuntime") { + run(process.argv.slice(2)) + }else { + if(runtime.type() === "RhinoRuntime") { + run(args) + }else { + run(args.slice(1)) + } + } +})(typeof arguments !== "undefined" && arguments); +core.Base64 = function() { + var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", b64charcodes = function() { + var a = [], i, codeA = "A".charCodeAt(0), codea = "a".charCodeAt(0), code0 = "0".charCodeAt(0); + for(i = 0;i < 26;i += 1) { + a.push(codeA + i) + } + for(i = 0;i < 26;i += 1) { + a.push(codea + i) + } + for(i = 0;i < 10;i += 1) { + a.push(code0 + i) + } + a.push("+".charCodeAt(0)); + a.push("/".charCodeAt(0)); + return a + }(), b64tab = function(bin) { + var t = {}, i, l; + for(i = 0, l = bin.length;i < l;i += 1) { + t[bin.charAt(i)] = i + } + return t + }(b64chars), convertUTF16StringToBase64, convertBase64ToUTF16String, btoa, atob; + function stringToArray(s) { + var a = [], i, l = s.length; + for(i = 0;i < l;i += 1) { + a[i] = s.charCodeAt(i) & 255 + } + return a + } + function convertUTF8ArrayToBase64(bin) { + var n, b64 = "", i, l = bin.length - 2; + for(i = 0;i < l;i += 3) { + n = bin[i] << 16 | bin[i + 1] << 8 | bin[i + 2]; + b64 += b64chars[n >>> 18]; + b64 += b64chars[n >>> 12 & 63]; + b64 += b64chars[n >>> 6 & 63]; + b64 += b64chars[n & 63] + } + if(i === l + 1) { + n = bin[i] << 4; + b64 += b64chars[n >>> 6]; + b64 += b64chars[n & 63]; + b64 += "==" + }else { + if(i === l) { + n = bin[i] << 10 | bin[i + 1] << 2; + b64 += b64chars[n >>> 12]; + b64 += b64chars[n >>> 6 & 63]; + b64 += b64chars[n & 63]; + b64 += "=" + } + } + return b64 + } + function convertBase64ToUTF8Array(b64) { + b64 = b64.replace(/[^A-Za-z0-9+\/]+/g, ""); + var bin = [], padlen = b64.length % 4, i, l = b64.length, n; + for(i = 0;i < l;i += 4) { + n = (b64tab[b64.charAt(i)] || 0) << 18 | (b64tab[b64.charAt(i + 1)] || 0) << 12 | (b64tab[b64.charAt(i + 2)] || 0) << 6 | (b64tab[b64.charAt(i + 3)] || 0); + bin.push(n >> 16, n >> 8 & 255, n & 255) + } + bin.length -= [0, 0, 2, 1][padlen]; + return bin + } + function convertUTF16ArrayToUTF8Array(uni) { + var bin = [], i, l = uni.length, n; + for(i = 0;i < l;i += 1) { + n = uni[i]; + if(n < 128) { + bin.push(n) + }else { + if(n < 2048) { + bin.push(192 | n >>> 6, 128 | n & 63) + }else { + bin.push(224 | n >>> 12 & 15, 128 | n >>> 6 & 63, 128 | n & 63) + } + } + } + return bin + } + function convertUTF8ArrayToUTF16Array(bin) { + var uni = [], i, l = bin.length, c0, c1, c2; + for(i = 0;i < l;i += 1) { + c0 = bin[i]; + if(c0 < 128) { + uni.push(c0) + }else { + i += 1; + c1 = bin[i]; + if(c0 < 224) { + uni.push((c0 & 31) << 6 | c1 & 63) + }else { + i += 1; + c2 = bin[i]; + uni.push((c0 & 15) << 12 | (c1 & 63) << 6 | c2 & 63) + } + } + } + return uni + } + function convertUTF8StringToBase64(bin) { + return convertUTF8ArrayToBase64(stringToArray(bin)) + } + function convertBase64ToUTF8String(b64) { + return String.fromCharCode.apply(String, convertBase64ToUTF8Array(b64)) + } + function convertUTF8StringToUTF16Array(bin) { + return convertUTF8ArrayToUTF16Array(stringToArray(bin)) + } + function convertUTF8ArrayToUTF16String(bin) { + var b = convertUTF8ArrayToUTF16Array(bin), r = "", i = 0, chunksize = 45E3; + while(i < b.length) { + r += String.fromCharCode.apply(String, b.slice(i, i + chunksize)); + i += chunksize + } + return r + } + function convertUTF8StringToUTF16String_internal(bin, i, end) { + var str = "", c0, c1, c2, j; + for(j = i;j < end;j += 1) { + c0 = bin.charCodeAt(j) & 255; + if(c0 < 128) { + str += String.fromCharCode(c0) + }else { + j += 1; + c1 = bin.charCodeAt(j) & 255; + if(c0 < 224) { + str += String.fromCharCode((c0 & 31) << 6 | c1 & 63) + }else { + j += 1; + c2 = bin.charCodeAt(j) & 255; + str += String.fromCharCode((c0 & 15) << 12 | (c1 & 63) << 6 | c2 & 63) + } + } + } + return str + } + function convertUTF8StringToUTF16String(bin, callback) { + var partsize = 1E5, numparts = bin.length / partsize, str = "", pos = 0; + if(bin.length < partsize) { + callback(convertUTF8StringToUTF16String_internal(bin, 0, bin.length), true); + return + } + if(typeof bin !== "string") { + bin = bin.slice() + } + function f() { + var end = pos + partsize; + if(end > bin.length) { + end = bin.length + } + str += convertUTF8StringToUTF16String_internal(bin, pos, end); + pos = end; + end = pos === bin.length; + if(callback(str, end) && !end) { + runtime.setTimeout(f, 0) + } + } + f() + } + function convertUTF16StringToUTF8Array(uni) { + return convertUTF16ArrayToUTF8Array(stringToArray(uni)) + } + function convertUTF16ArrayToUTF8String(uni) { + return String.fromCharCode.apply(String, convertUTF16ArrayToUTF8Array(uni)) + } + function convertUTF16StringToUTF8String(uni) { + return String.fromCharCode.apply(String, convertUTF16ArrayToUTF8Array(stringToArray(uni))) + } + btoa = runtime.getWindow() && runtime.getWindow().btoa; + if(btoa) { + convertUTF16StringToBase64 = function(uni) { + return btoa(convertUTF16StringToUTF8String(uni)) + } + }else { + btoa = convertUTF8StringToBase64; + convertUTF16StringToBase64 = function(uni) { + return convertUTF8ArrayToBase64(convertUTF16StringToUTF8Array(uni)) + } + } + atob = runtime.getWindow() && runtime.getWindow().atob; + if(atob) { + convertBase64ToUTF16String = function(b64) { + var b = atob(b64); + return convertUTF8StringToUTF16String_internal(b, 0, b.length) + } + }else { + atob = convertBase64ToUTF8String; + convertBase64ToUTF16String = function(b64) { + return convertUTF8ArrayToUTF16String(convertBase64ToUTF8Array(b64)) + } + } + function Base64() { + this.convertUTF8ArrayToBase64 = convertUTF8ArrayToBase64; + this.convertByteArrayToBase64 = convertUTF8ArrayToBase64; + this.convertBase64ToUTF8Array = convertBase64ToUTF8Array; + this.convertBase64ToByteArray = convertBase64ToUTF8Array; + this.convertUTF16ArrayToUTF8Array = convertUTF16ArrayToUTF8Array; + this.convertUTF16ArrayToByteArray = convertUTF16ArrayToUTF8Array; + this.convertUTF8ArrayToUTF16Array = convertUTF8ArrayToUTF16Array; + this.convertByteArrayToUTF16Array = convertUTF8ArrayToUTF16Array; + this.convertUTF8StringToBase64 = convertUTF8StringToBase64; + this.convertBase64ToUTF8String = convertBase64ToUTF8String; + this.convertUTF8StringToUTF16Array = convertUTF8StringToUTF16Array; + this.convertUTF8ArrayToUTF16String = convertUTF8ArrayToUTF16String; + this.convertByteArrayToUTF16String = convertUTF8ArrayToUTF16String; + this.convertUTF8StringToUTF16String = convertUTF8StringToUTF16String; + this.convertUTF16StringToUTF8Array = convertUTF16StringToUTF8Array; + this.convertUTF16StringToByteArray = convertUTF16StringToUTF8Array; + this.convertUTF16ArrayToUTF8String = convertUTF16ArrayToUTF8String; + this.convertUTF16StringToUTF8String = convertUTF16StringToUTF8String; + this.convertUTF16StringToBase64 = convertUTF16StringToBase64; + this.convertBase64ToUTF16String = convertBase64ToUTF16String; + this.fromBase64 = convertBase64ToUTF8String; + this.toBase64 = convertUTF8StringToBase64; + this.atob = atob; + this.btoa = btoa; + this.utob = convertUTF16StringToUTF8String; + this.btou = convertUTF8StringToUTF16String; + this.encode = convertUTF16StringToBase64; + this.encodeURI = function(u) { + return convertUTF16StringToBase64(u).replace(/[+\/]/g, function(m0) { + return m0 === "+" ? "-" : "_" + }).replace(/\\=+$/, "") + }; + this.decode = function(a) { + return convertBase64ToUTF16String(a.replace(/[\-_]/g, function(m0) { + return m0 === "-" ? "+" : "/" + })) + } + } + return Base64 +}(); +core.RawDeflate = function() { + var zip_WSIZE = 32768, zip_STORED_BLOCK = 0, zip_STATIC_TREES = 1, zip_DYN_TREES = 2, zip_DEFAULT_LEVEL = 6, zip_FULL_SEARCH = true, zip_INBUFSIZ = 32768, zip_INBUF_EXTRA = 64, zip_OUTBUFSIZ = 1024 * 8, zip_window_size = 2 * zip_WSIZE, zip_MIN_MATCH = 3, zip_MAX_MATCH = 258, zip_BITS = 16, zip_LIT_BUFSIZE = 8192, zip_HASH_BITS = 13, zip_DIST_BUFSIZE = zip_LIT_BUFSIZE, zip_HASH_SIZE = 1 << zip_HASH_BITS, zip_HASH_MASK = zip_HASH_SIZE - 1, zip_WMASK = zip_WSIZE - 1, zip_NIL = 0, zip_TOO_FAR = 4096, + zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1, zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD, zip_SMALLEST = 1, zip_MAX_BITS = 15, zip_MAX_BL_BITS = 7, zip_LENGTH_CODES = 29, zip_LITERALS = 256, zip_END_BLOCK = 256, zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES, zip_D_CODES = 30, zip_BL_CODES = 19, zip_REP_3_6 = 16, zip_REPZ_3_10 = 17, zip_REPZ_11_138 = 18, zip_HEAP_SIZE = 2 * zip_L_CODES + 1, zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / zip_MIN_MATCH, 10), zip_free_queue, + zip_qhead, zip_qtail, zip_initflag, zip_outbuf = null, zip_outcnt, zip_outoff, zip_complete, zip_window, zip_d_buf, zip_l_buf, zip_prev, zip_bi_buf, zip_bi_valid, zip_block_start, zip_ins_h, zip_hash_head, zip_prev_match, zip_match_available, zip_match_length, zip_prev_length, zip_strstart, zip_match_start, zip_eofile, zip_lookahead, zip_max_chain_length, zip_max_lazy_match, zip_compr_level, zip_good_match, zip_nice_match, zip_dyn_ltree, zip_dyn_dtree, zip_static_ltree, zip_static_dtree, zip_bl_tree, + zip_l_desc, zip_d_desc, zip_bl_desc, zip_bl_count, zip_heap, zip_heap_len, zip_heap_max, zip_depth, zip_length_code, zip_dist_code, zip_base_length, zip_base_dist, zip_flag_buf, zip_last_lit, zip_last_dist, zip_last_flags, zip_flags, zip_flag_bit, zip_opt_len, zip_static_len, zip_deflate_data, zip_deflate_pos, zip_extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], zip_extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, + 9, 10, 10, 11, 11, 12, 12, 13, 13], zip_extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], zip_bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], zip_configuration_table; + if(zip_LIT_BUFSIZE > zip_INBUFSIZ) { + runtime.log("error: zip_INBUFSIZ is too small") + } + if(zip_WSIZE << 1 > 1 << zip_BITS) { + runtime.log("error: zip_WSIZE is too large") + } + if(zip_HASH_BITS > zip_BITS - 1) { + runtime.log("error: zip_HASH_BITS is too large") + } + if(zip_HASH_BITS < 8 || zip_MAX_MATCH !== 258) { + runtime.log("error: Code too clever") + } + function Zip_DeflateCT() { + this.fc = 0; + this.dl = 0 + } + function Zip_DeflateTreeDesc() { + this.dyn_tree = null; + this.static_tree = null; + this.extra_bits = null; + this.extra_base = 0; + this.elems = 0; + this.max_length = 0; + this.max_code = 0 + } + function Zip_DeflateConfiguration(a, b, c, d) { + this.good_length = a; + this.max_lazy = b; + this.nice_length = c; + this.max_chain = d + } + function Zip_DeflateBuffer() { + this.next = null; + this.len = 0; + this.ptr = []; + this.ptr.length = zip_OUTBUFSIZ; + this.off = 0 + } + zip_configuration_table = [new Zip_DeflateConfiguration(0, 0, 0, 0), new Zip_DeflateConfiguration(4, 4, 8, 4), new Zip_DeflateConfiguration(4, 5, 16, 8), new Zip_DeflateConfiguration(4, 6, 32, 32), new Zip_DeflateConfiguration(4, 4, 16, 16), new Zip_DeflateConfiguration(8, 16, 32, 32), new Zip_DeflateConfiguration(8, 16, 128, 128), new Zip_DeflateConfiguration(8, 32, 128, 256), new Zip_DeflateConfiguration(32, 128, 258, 1024), new Zip_DeflateConfiguration(32, 258, 258, 4096)]; + function zip_deflate_start(level) { + var i; + if(!level) { + level = zip_DEFAULT_LEVEL + }else { + if(level < 1) { + level = 1 + }else { + if(level > 9) { + level = 9 + } + } + } + zip_compr_level = level; + zip_initflag = false; + zip_eofile = false; + if(zip_outbuf !== null) { + return + } + zip_free_queue = zip_qhead = zip_qtail = null; + zip_outbuf = []; + zip_outbuf.length = zip_OUTBUFSIZ; + zip_window = []; + zip_window.length = zip_window_size; + zip_d_buf = []; + zip_d_buf.length = zip_DIST_BUFSIZE; + zip_l_buf = []; + zip_l_buf.length = zip_INBUFSIZ + zip_INBUF_EXTRA; + zip_prev = []; + zip_prev.length = 1 << zip_BITS; + zip_dyn_ltree = []; + zip_dyn_ltree.length = zip_HEAP_SIZE; + for(i = 0;i < zip_HEAP_SIZE;i++) { + zip_dyn_ltree[i] = new Zip_DeflateCT + } + zip_dyn_dtree = []; + zip_dyn_dtree.length = 2 * zip_D_CODES + 1; + for(i = 0;i < 2 * zip_D_CODES + 1;i++) { + zip_dyn_dtree[i] = new Zip_DeflateCT + } + zip_static_ltree = []; + zip_static_ltree.length = zip_L_CODES + 2; + for(i = 0;i < zip_L_CODES + 2;i++) { + zip_static_ltree[i] = new Zip_DeflateCT + } + zip_static_dtree = []; + zip_static_dtree.length = zip_D_CODES; + for(i = 0;i < zip_D_CODES;i++) { + zip_static_dtree[i] = new Zip_DeflateCT + } + zip_bl_tree = []; + zip_bl_tree.length = 2 * zip_BL_CODES + 1; + for(i = 0;i < 2 * zip_BL_CODES + 1;i++) { + zip_bl_tree[i] = new Zip_DeflateCT + } + zip_l_desc = new Zip_DeflateTreeDesc; + zip_d_desc = new Zip_DeflateTreeDesc; + zip_bl_desc = new Zip_DeflateTreeDesc; + zip_bl_count = []; + zip_bl_count.length = zip_MAX_BITS + 1; + zip_heap = []; + zip_heap.length = 2 * zip_L_CODES + 1; + zip_depth = []; + zip_depth.length = 2 * zip_L_CODES + 1; + zip_length_code = []; + zip_length_code.length = zip_MAX_MATCH - zip_MIN_MATCH + 1; + zip_dist_code = []; + zip_dist_code.length = 512; + zip_base_length = []; + zip_base_length.length = zip_LENGTH_CODES; + zip_base_dist = []; + zip_base_dist.length = zip_D_CODES; + zip_flag_buf = []; + zip_flag_buf.length = parseInt(zip_LIT_BUFSIZE / 8, 10) + } + var zip_deflate_end = function() { + zip_free_queue = zip_qhead = zip_qtail = null; + zip_outbuf = null; + zip_window = null; + zip_d_buf = null; + zip_l_buf = null; + zip_prev = null; + zip_dyn_ltree = null; + zip_dyn_dtree = null; + zip_static_ltree = null; + zip_static_dtree = null; + zip_bl_tree = null; + zip_l_desc = null; + zip_d_desc = null; + zip_bl_desc = null; + zip_bl_count = null; + zip_heap = null; + zip_depth = null; + zip_length_code = null; + zip_dist_code = null; + zip_base_length = null; + zip_base_dist = null; + zip_flag_buf = null + }; + var zip_reuse_queue = function(p) { + p.next = zip_free_queue; + zip_free_queue = p + }; + var zip_new_queue = function() { + var p; + if(zip_free_queue !== null) { + p = zip_free_queue; + zip_free_queue = zip_free_queue.next + }else { + p = new Zip_DeflateBuffer + } + p.next = null; + p.len = p.off = 0; + return p + }; + var zip_head1 = function(i) { + return zip_prev[zip_WSIZE + i] + }; + var zip_head2 = function(i, val) { + zip_prev[zip_WSIZE + i] = val; + return val + }; + var zip_qoutbuf = function() { + var q, i; + if(zip_outcnt !== 0) { + q = zip_new_queue(); + if(zip_qhead === null) { + zip_qhead = zip_qtail = q + }else { + zip_qtail = zip_qtail.next = q + } + q.len = zip_outcnt - zip_outoff; + for(i = 0;i < q.len;i++) { + q.ptr[i] = zip_outbuf[zip_outoff + i] + } + zip_outcnt = zip_outoff = 0 + } + }; + var zip_put_byte = function(c) { + zip_outbuf[zip_outoff + zip_outcnt++] = c; + if(zip_outoff + zip_outcnt === zip_OUTBUFSIZ) { + zip_qoutbuf() + } + }; + var zip_put_short = function(w) { + w &= 65535; + if(zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) { + zip_outbuf[zip_outoff + zip_outcnt++] = w & 255; + zip_outbuf[zip_outoff + zip_outcnt++] = w >>> 8 + }else { + zip_put_byte(w & 255); + zip_put_byte(w >>> 8) + } + }; + var zip_INSERT_STRING = function() { + zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + zip_MIN_MATCH - 1] & 255) & zip_HASH_MASK; + zip_hash_head = zip_head1(zip_ins_h); + zip_prev[zip_strstart & zip_WMASK] = zip_hash_head; + zip_head2(zip_ins_h, zip_strstart) + }; + var zip_Buf_size = 16; + var zip_send_bits = function(value, length) { + if(zip_bi_valid > zip_Buf_size - length) { + zip_bi_buf |= value << zip_bi_valid; + zip_put_short(zip_bi_buf); + zip_bi_buf = value >> zip_Buf_size - zip_bi_valid; + zip_bi_valid += length - zip_Buf_size + }else { + zip_bi_buf |= value << zip_bi_valid; + zip_bi_valid += length + } + }; + var zip_SEND_CODE = function(c, tree) { + zip_send_bits(tree[c].fc, tree[c].dl) + }; + var zip_D_CODE = function(dist) { + return(dist < 256 ? zip_dist_code[dist] : zip_dist_code[256 + (dist >> 7)]) & 255 + }; + var zip_SMALLER = function(tree, n, m) { + return tree[n].fc < tree[m].fc || tree[n].fc === tree[m].fc && zip_depth[n] <= zip_depth[m] + }; + var zip_read_buff = function(buff, offset, n) { + var i; + for(i = 0;i < n && zip_deflate_pos < zip_deflate_data.length;i++) { + buff[offset + i] = zip_deflate_data.charCodeAt(zip_deflate_pos++) & 255 + } + return i + }; + var zip_fill_window = function() { + var n, m; + var more = zip_window_size - zip_lookahead - zip_strstart; + if(more === -1) { + more-- + }else { + if(zip_strstart >= zip_WSIZE + zip_MAX_DIST) { + for(n = 0;n < zip_WSIZE;n++) { + zip_window[n] = zip_window[n + zip_WSIZE] + } + zip_match_start -= zip_WSIZE; + zip_strstart -= zip_WSIZE; + zip_block_start -= zip_WSIZE; + for(n = 0;n < zip_HASH_SIZE;n++) { + m = zip_head1(n); + zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL) + } + for(n = 0;n < zip_WSIZE;n++) { + m = zip_prev[n]; + zip_prev[n] = m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL + } + more += zip_WSIZE + } + } + if(!zip_eofile) { + n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more); + if(n <= 0) { + zip_eofile = true + }else { + zip_lookahead += n + } + } + }; + var zip_lm_init = function() { + var j; + for(j = 0;j < zip_HASH_SIZE;j++) { + zip_prev[zip_WSIZE + j] = 0 + } + zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy; + zip_good_match = zip_configuration_table[zip_compr_level].good_length; + if(!zip_FULL_SEARCH) { + zip_nice_match = zip_configuration_table[zip_compr_level].nice_length + } + zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain; + zip_strstart = 0; + zip_block_start = 0; + zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE); + if(zip_lookahead <= 0) { + zip_eofile = true; + zip_lookahead = 0; + return + } + zip_eofile = false; + while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) { + zip_fill_window() + } + zip_ins_h = 0; + for(j = 0;j < zip_MIN_MATCH - 1;j++) { + zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[j] & 255) & zip_HASH_MASK + } + }; + var zip_longest_match = function(cur_match) { + var chain_length = zip_max_chain_length; + var scanp = zip_strstart; + var matchp; + var len; + var best_len = zip_prev_length; + var limit = zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL; + var strendp = zip_strstart + zip_MAX_MATCH; + var scan_end1 = zip_window[scanp + best_len - 1]; + var scan_end = zip_window[scanp + best_len]; + if(zip_prev_length >= zip_good_match) { + chain_length >>= 2 + } + do { + matchp = cur_match; + if(zip_window[matchp + best_len] !== scan_end || zip_window[matchp + best_len - 1] !== scan_end1 || zip_window[matchp] !== zip_window[scanp] || zip_window[++matchp] !== zip_window[scanp + 1]) { + continue + } + scanp += 2; + matchp++; + do { + ++scanp + }while(zip_window[scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && zip_window[++scanp] === zip_window[++matchp] && scanp < strendp); + len = zip_MAX_MATCH - (strendp - scanp); + scanp = strendp - zip_MAX_MATCH; + if(len > best_len) { + zip_match_start = cur_match; + best_len = len; + if(zip_FULL_SEARCH) { + if(len >= zip_MAX_MATCH) { + break + } + }else { + if(len >= zip_nice_match) { + break + } + } + scan_end1 = zip_window[scanp + best_len - 1]; + scan_end = zip_window[scanp + best_len] + } + }while((cur_match = zip_prev[cur_match & zip_WMASK]) > limit && --chain_length !== 0); + return best_len + }; + var zip_ct_tally = function(dist, lc) { + zip_l_buf[zip_last_lit++] = lc; + if(dist === 0) { + zip_dyn_ltree[lc].fc++ + }else { + dist--; + zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++; + zip_dyn_dtree[zip_D_CODE(dist)].fc++; + zip_d_buf[zip_last_dist++] = dist; + zip_flags |= zip_flag_bit + } + zip_flag_bit <<= 1; + if((zip_last_lit & 7) === 0) { + zip_flag_buf[zip_last_flags++] = zip_flags; + zip_flags = 0; + zip_flag_bit = 1 + } + if(zip_compr_level > 2 && (zip_last_lit & 4095) === 0) { + var out_length = zip_last_lit * 8; + var in_length = zip_strstart - zip_block_start; + var dcode; + for(dcode = 0;dcode < zip_D_CODES;dcode++) { + out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode]) + } + out_length >>= 3; + if(zip_last_dist < parseInt(zip_last_lit / 2, 10) && out_length < parseInt(in_length / 2, 10)) { + return true + } + } + return zip_last_lit === zip_LIT_BUFSIZE - 1 || zip_last_dist === zip_DIST_BUFSIZE + }; + var zip_pqdownheap = function(tree, k) { + var v = zip_heap[k]; + var j = k << 1; + while(j <= zip_heap_len) { + if(j < zip_heap_len && zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j])) { + j++ + } + if(zip_SMALLER(tree, v, zip_heap[j])) { + break + } + zip_heap[k] = zip_heap[j]; + k = j; + j <<= 1 + } + zip_heap[k] = v + }; + var zip_gen_bitlen = function(desc) { + var tree = desc.dyn_tree; + var extra = desc.extra_bits; + var base = desc.extra_base; + var max_code = desc.max_code; + var max_length = desc.max_length; + var stree = desc.static_tree; + var h; + var n, m; + var bits; + var xbits; + var f; + var overflow = 0; + for(bits = 0;bits <= zip_MAX_BITS;bits++) { + zip_bl_count[bits] = 0 + } + tree[zip_heap[zip_heap_max]].dl = 0; + for(h = zip_heap_max + 1;h < zip_HEAP_SIZE;h++) { + n = zip_heap[h]; + bits = tree[tree[n].dl].dl + 1; + if(bits > max_length) { + bits = max_length; + overflow++ + } + tree[n].dl = bits; + if(n > max_code) { + continue + } + zip_bl_count[bits]++; + xbits = 0; + if(n >= base) { + xbits = extra[n - base] + } + f = tree[n].fc; + zip_opt_len += f * (bits + xbits); + if(stree !== null) { + zip_static_len += f * (stree[n].dl + xbits) + } + } + if(overflow === 0) { + return + } + do { + bits = max_length - 1; + while(zip_bl_count[bits] === 0) { + bits-- + } + zip_bl_count[bits]--; + zip_bl_count[bits + 1] += 2; + zip_bl_count[max_length]--; + overflow -= 2 + }while(overflow > 0); + for(bits = max_length;bits !== 0;bits--) { + n = zip_bl_count[bits]; + while(n !== 0) { + m = zip_heap[--h]; + if(m > max_code) { + continue + } + if(tree[m].dl !== bits) { + zip_opt_len += (bits - tree[m].dl) * tree[m].fc; + tree[m].fc = bits + } + n-- + } + } + }; + var zip_bi_reverse = function(code, len) { + var res = 0; + do { + res |= code & 1; + code >>= 1; + res <<= 1 + }while(--len > 0); + return res >> 1 + }; + var zip_gen_codes = function(tree, max_code) { + var next_code = []; + next_code.length = zip_MAX_BITS + 1; + var code = 0; + var bits; + var n; + for(bits = 1;bits <= zip_MAX_BITS;bits++) { + code = code + zip_bl_count[bits - 1] << 1; + next_code[bits] = code + } + for(n = 0;n <= max_code;n++) { + var len = tree[n].dl; + if(len === 0) { + continue + } + tree[n].fc = zip_bi_reverse(next_code[len]++, len) + } + }; + var zip_build_tree = function(desc) { + var tree = desc.dyn_tree; + var stree = desc.static_tree; + var elems = desc.elems; + var n, m; + var max_code = -1; + var node = elems; + zip_heap_len = 0; + zip_heap_max = zip_HEAP_SIZE; + for(n = 0;n < elems;n++) { + if(tree[n].fc !== 0) { + zip_heap[++zip_heap_len] = max_code = n; + zip_depth[n] = 0 + }else { + tree[n].dl = 0 + } + } + while(zip_heap_len < 2) { + var xnew = zip_heap[++zip_heap_len] = max_code < 2 ? ++max_code : 0; + tree[xnew].fc = 1; + zip_depth[xnew] = 0; + zip_opt_len--; + if(stree !== null) { + zip_static_len -= stree[xnew].dl + } + } + desc.max_code = max_code; + for(n = zip_heap_len >> 1;n >= 1;n--) { + zip_pqdownheap(tree, n) + } + do { + n = zip_heap[zip_SMALLEST]; + zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--]; + zip_pqdownheap(tree, zip_SMALLEST); + m = zip_heap[zip_SMALLEST]; + zip_heap[--zip_heap_max] = n; + zip_heap[--zip_heap_max] = m; + tree[node].fc = tree[n].fc + tree[m].fc; + if(zip_depth[n] > zip_depth[m] + 1) { + zip_depth[node] = zip_depth[n] + }else { + zip_depth[node] = zip_depth[m] + 1 + } + tree[n].dl = tree[m].dl = node; + zip_heap[zip_SMALLEST] = node++; + zip_pqdownheap(tree, zip_SMALLEST) + }while(zip_heap_len >= 2); + zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST]; + zip_gen_bitlen(desc); + zip_gen_codes(tree, max_code) + }; + var zip_scan_tree = function(tree, max_code) { + var n; + var prevlen = -1; + var curlen; + var nextlen = tree[0].dl; + var count = 0; + var max_count = 7; + var min_count = 4; + if(nextlen === 0) { + max_count = 138; + min_count = 3 + } + tree[max_code + 1].dl = 65535; + for(n = 0;n <= max_code;n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if(++count < max_count && curlen === nextlen) { + continue + }else { + if(count < min_count) { + zip_bl_tree[curlen].fc += count + }else { + if(curlen !== 0) { + if(curlen !== prevlen) { + zip_bl_tree[curlen].fc++ + } + zip_bl_tree[zip_REP_3_6].fc++ + }else { + if(count <= 10) { + zip_bl_tree[zip_REPZ_3_10].fc++ + }else { + zip_bl_tree[zip_REPZ_11_138].fc++ + } + } + } + } + count = 0; + prevlen = curlen; + if(nextlen === 0) { + max_count = 138; + min_count = 3 + }else { + if(curlen === nextlen) { + max_count = 6; + min_count = 3 + }else { + max_count = 7; + min_count = 4 + } + } + } + }; + var zip_build_bl_tree = function() { + var max_blindex; + zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code); + zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code); + zip_build_tree(zip_bl_desc); + for(max_blindex = zip_BL_CODES - 1;max_blindex >= 3;max_blindex--) { + if(zip_bl_tree[zip_bl_order[max_blindex]].dl !== 0) { + break + } + } + zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + return max_blindex + }; + var zip_bi_windup = function() { + if(zip_bi_valid > 8) { + zip_put_short(zip_bi_buf) + }else { + if(zip_bi_valid > 0) { + zip_put_byte(zip_bi_buf) + } + } + zip_bi_buf = 0; + zip_bi_valid = 0 + }; + var zip_compress_block = function(ltree, dtree) { + var dist; + var lc; + var lx = 0; + var dx = 0; + var fx = 0; + var flag = 0; + var code; + var extra; + if(zip_last_lit !== 0) { + do { + if((lx & 7) === 0) { + flag = zip_flag_buf[fx++] + } + lc = zip_l_buf[lx++] & 255; + if((flag & 1) === 0) { + zip_SEND_CODE(lc, ltree) + }else { + code = zip_length_code[lc]; + zip_SEND_CODE(code + zip_LITERALS + 1, ltree); + extra = zip_extra_lbits[code]; + if(extra !== 0) { + lc -= zip_base_length[code]; + zip_send_bits(lc, extra) + } + dist = zip_d_buf[dx++]; + code = zip_D_CODE(dist); + zip_SEND_CODE(code, dtree); + extra = zip_extra_dbits[code]; + if(extra !== 0) { + dist -= zip_base_dist[code]; + zip_send_bits(dist, extra) + } + } + flag >>= 1 + }while(lx < zip_last_lit) + } + zip_SEND_CODE(zip_END_BLOCK, ltree) + }; + var zip_send_tree = function(tree, max_code) { + var n; + var prevlen = -1; + var curlen; + var nextlen = tree[0].dl; + var count = 0; + var max_count = 7; + var min_count = 4; + if(nextlen === 0) { + max_count = 138; + min_count = 3 + } + for(n = 0;n <= max_code;n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if(++count < max_count && curlen === nextlen) { + continue + }else { + if(count < min_count) { + do { + zip_SEND_CODE(curlen, zip_bl_tree) + }while(--count !== 0) + }else { + if(curlen !== 0) { + if(curlen !== prevlen) { + zip_SEND_CODE(curlen, zip_bl_tree); + count-- + } + zip_SEND_CODE(zip_REP_3_6, zip_bl_tree); + zip_send_bits(count - 3, 2) + }else { + if(count <= 10) { + zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree); + zip_send_bits(count - 3, 3) + }else { + zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree); + zip_send_bits(count - 11, 7) + } + } + } + } + count = 0; + prevlen = curlen; + if(nextlen === 0) { + max_count = 138; + min_count = 3 + }else { + if(curlen === nextlen) { + max_count = 6; + min_count = 3 + }else { + max_count = 7; + min_count = 4 + } + } + } + }; + var zip_send_all_trees = function(lcodes, dcodes, blcodes) { + var rank; + zip_send_bits(lcodes - 257, 5); + zip_send_bits(dcodes - 1, 5); + zip_send_bits(blcodes - 4, 4); + for(rank = 0;rank < blcodes;rank++) { + zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3) + } + zip_send_tree(zip_dyn_ltree, lcodes - 1); + zip_send_tree(zip_dyn_dtree, dcodes - 1) + }; + var zip_init_block = function() { + var n; + for(n = 0;n < zip_L_CODES;n++) { + zip_dyn_ltree[n].fc = 0 + } + for(n = 0;n < zip_D_CODES;n++) { + zip_dyn_dtree[n].fc = 0 + } + for(n = 0;n < zip_BL_CODES;n++) { + zip_bl_tree[n].fc = 0 + } + zip_dyn_ltree[zip_END_BLOCK].fc = 1; + zip_opt_len = zip_static_len = 0; + zip_last_lit = zip_last_dist = zip_last_flags = 0; + zip_flags = 0; + zip_flag_bit = 1 + }; + var zip_flush_block = function(eof) { + var opt_lenb, static_lenb; + var max_blindex; + var stored_len; + stored_len = zip_strstart - zip_block_start; + zip_flag_buf[zip_last_flags] = zip_flags; + zip_build_tree(zip_l_desc); + zip_build_tree(zip_d_desc); + max_blindex = zip_build_bl_tree(); + opt_lenb = zip_opt_len + 3 + 7 >> 3; + static_lenb = zip_static_len + 3 + 7 >> 3; + if(static_lenb <= opt_lenb) { + opt_lenb = static_lenb + } + if(stored_len + 4 <= opt_lenb && zip_block_start >= 0) { + var i; + zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3); + zip_bi_windup(); + zip_put_short(stored_len); + zip_put_short(~stored_len); + for(i = 0;i < stored_len;i++) { + zip_put_byte(zip_window[zip_block_start + i]) + } + }else { + if(static_lenb === opt_lenb) { + zip_send_bits((zip_STATIC_TREES << 1) + eof, 3); + zip_compress_block(zip_static_ltree, zip_static_dtree) + }else { + zip_send_bits((zip_DYN_TREES << 1) + eof, 3); + zip_send_all_trees(zip_l_desc.max_code + 1, zip_d_desc.max_code + 1, max_blindex + 1); + zip_compress_block(zip_dyn_ltree, zip_dyn_dtree) + } + } + zip_init_block(); + if(eof !== 0) { + zip_bi_windup() + } + }; + var zip_deflate_fast = function() { + while(zip_lookahead !== 0 && zip_qhead === null) { + var flush; + zip_INSERT_STRING(); + if(zip_hash_head !== zip_NIL && zip_strstart - zip_hash_head <= zip_MAX_DIST) { + zip_match_length = zip_longest_match(zip_hash_head); + if(zip_match_length > zip_lookahead) { + zip_match_length = zip_lookahead + } + } + if(zip_match_length >= zip_MIN_MATCH) { + flush = zip_ct_tally(zip_strstart - zip_match_start, zip_match_length - zip_MIN_MATCH); + zip_lookahead -= zip_match_length; + if(zip_match_length <= zip_max_lazy_match) { + zip_match_length--; + do { + zip_strstart++; + zip_INSERT_STRING() + }while(--zip_match_length !== 0); + zip_strstart++ + }else { + zip_strstart += zip_match_length; + zip_match_length = 0; + zip_ins_h = zip_window[zip_strstart] & 255; + zip_ins_h = (zip_ins_h << zip_H_SHIFT ^ zip_window[zip_strstart + 1] & 255) & zip_HASH_MASK + } + }else { + flush = zip_ct_tally(0, zip_window[zip_strstart] & 255); + zip_lookahead--; + zip_strstart++ + } + if(flush) { + zip_flush_block(0); + zip_block_start = zip_strstart + } + while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) { + zip_fill_window() + } + } + }; + var zip_deflate_better = function() { + while(zip_lookahead !== 0 && zip_qhead === null) { + zip_INSERT_STRING(); + zip_prev_length = zip_match_length; + zip_prev_match = zip_match_start; + zip_match_length = zip_MIN_MATCH - 1; + if(zip_hash_head !== zip_NIL && zip_prev_length < zip_max_lazy_match && zip_strstart - zip_hash_head <= zip_MAX_DIST) { + zip_match_length = zip_longest_match(zip_hash_head); + if(zip_match_length > zip_lookahead) { + zip_match_length = zip_lookahead + } + if(zip_match_length === zip_MIN_MATCH && zip_strstart - zip_match_start > zip_TOO_FAR) { + zip_match_length-- + } + } + if(zip_prev_length >= zip_MIN_MATCH && zip_match_length <= zip_prev_length) { + var flush; + flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, zip_prev_length - zip_MIN_MATCH); + zip_lookahead -= zip_prev_length - 1; + zip_prev_length -= 2; + do { + zip_strstart++; + zip_INSERT_STRING() + }while(--zip_prev_length !== 0); + zip_match_available = 0; + zip_match_length = zip_MIN_MATCH - 1; + zip_strstart++; + if(flush) { + zip_flush_block(0); + zip_block_start = zip_strstart + } + }else { + if(zip_match_available !== 0) { + if(zip_ct_tally(0, zip_window[zip_strstart - 1] & 255)) { + zip_flush_block(0); + zip_block_start = zip_strstart + } + zip_strstart++; + zip_lookahead-- + }else { + zip_match_available = 1; + zip_strstart++; + zip_lookahead-- + } + } + while(zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) { + zip_fill_window() + } + } + }; + var zip_ct_init = function() { + var n; + var bits; + var length; + var code; + var dist; + if(zip_static_dtree[0].dl !== 0) { + return + } + zip_l_desc.dyn_tree = zip_dyn_ltree; + zip_l_desc.static_tree = zip_static_ltree; + zip_l_desc.extra_bits = zip_extra_lbits; + zip_l_desc.extra_base = zip_LITERALS + 1; + zip_l_desc.elems = zip_L_CODES; + zip_l_desc.max_length = zip_MAX_BITS; + zip_l_desc.max_code = 0; + zip_d_desc.dyn_tree = zip_dyn_dtree; + zip_d_desc.static_tree = zip_static_dtree; + zip_d_desc.extra_bits = zip_extra_dbits; + zip_d_desc.extra_base = 0; + zip_d_desc.elems = zip_D_CODES; + zip_d_desc.max_length = zip_MAX_BITS; + zip_d_desc.max_code = 0; + zip_bl_desc.dyn_tree = zip_bl_tree; + zip_bl_desc.static_tree = null; + zip_bl_desc.extra_bits = zip_extra_blbits; + zip_bl_desc.extra_base = 0; + zip_bl_desc.elems = zip_BL_CODES; + zip_bl_desc.max_length = zip_MAX_BL_BITS; + zip_bl_desc.max_code = 0; + length = 0; + for(code = 0;code < zip_LENGTH_CODES - 1;code++) { + zip_base_length[code] = length; + for(n = 0;n < 1 << zip_extra_lbits[code];n++) { + zip_length_code[length++] = code + } + } + zip_length_code[length - 1] = code; + dist = 0; + for(code = 0;code < 16;code++) { + zip_base_dist[code] = dist; + for(n = 0;n < 1 << zip_extra_dbits[code];n++) { + zip_dist_code[dist++] = code + } + } + dist >>= 7; + n = code; + for(code = n;code < zip_D_CODES;code++) { + zip_base_dist[code] = dist << 7; + for(n = 0;n < 1 << zip_extra_dbits[code] - 7;n++) { + zip_dist_code[256 + dist++] = code + } + } + for(bits = 0;bits <= zip_MAX_BITS;bits++) { + zip_bl_count[bits] = 0 + } + n = 0; + while(n <= 143) { + zip_static_ltree[n++].dl = 8; + zip_bl_count[8]++ + } + while(n <= 255) { + zip_static_ltree[n++].dl = 9; + zip_bl_count[9]++ + } + while(n <= 279) { + zip_static_ltree[n++].dl = 7; + zip_bl_count[7]++ + } + while(n <= 287) { + zip_static_ltree[n++].dl = 8; + zip_bl_count[8]++ + } + zip_gen_codes(zip_static_ltree, zip_L_CODES + 1); + for(n = 0;n < zip_D_CODES;n++) { + zip_static_dtree[n].dl = 5; + zip_static_dtree[n].fc = zip_bi_reverse(n, 5) + } + zip_init_block() + }; + var zip_init_deflate = function() { + if(zip_eofile) { + return + } + zip_bi_buf = 0; + zip_bi_valid = 0; + zip_ct_init(); + zip_lm_init(); + zip_qhead = null; + zip_outcnt = 0; + zip_outoff = 0; + if(zip_compr_level <= 3) { + zip_prev_length = zip_MIN_MATCH - 1; + zip_match_length = 0 + }else { + zip_match_length = zip_MIN_MATCH - 1; + zip_match_available = 0 + } + zip_complete = false + }; + var zip_qcopy = function(buff, off, buff_size) { + var n, i, j; + n = 0; + while(zip_qhead !== null && n < buff_size) { + i = buff_size - n; + if(i > zip_qhead.len) { + i = zip_qhead.len + } + for(j = 0;j < i;j++) { + buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j] + } + zip_qhead.off += i; + zip_qhead.len -= i; + n += i; + if(zip_qhead.len === 0) { + var p; + p = zip_qhead; + zip_qhead = zip_qhead.next; + zip_reuse_queue(p) + } + } + if(n === buff_size) { + return n + } + if(zip_outoff < zip_outcnt) { + i = buff_size - n; + if(i > zip_outcnt - zip_outoff) { + i = zip_outcnt - zip_outoff + } + for(j = 0;j < i;j++) { + buff[off + n + j] = zip_outbuf[zip_outoff + j] + } + zip_outoff += i; + n += i; + if(zip_outcnt === zip_outoff) { + zip_outcnt = zip_outoff = 0 + } + } + return n + }; + var zip_deflate_internal = function(buff, off, buff_size) { + var n; + if(!zip_initflag) { + zip_init_deflate(); + zip_initflag = true; + if(zip_lookahead === 0) { + zip_complete = true; + return 0 + } + } + if((n = zip_qcopy(buff, off, buff_size)) === buff_size) { + return buff_size + } + if(zip_complete) { + return n + } + if(zip_compr_level <= 3) { + zip_deflate_fast() + }else { + zip_deflate_better() + } + if(zip_lookahead === 0) { + if(zip_match_available !== 0) { + zip_ct_tally(0, zip_window[zip_strstart - 1] & 255) + } + zip_flush_block(1); + zip_complete = true + } + return n + zip_qcopy(buff, n + off, buff_size - n) + }; + var zip_deflate = function(str, level) { + var i, j; + zip_deflate_data = str; + zip_deflate_pos = 0; + if(typeof level === "undefined") { + level = zip_DEFAULT_LEVEL + } + zip_deflate_start(level); + var buff = new Array(1024); + var aout = []; + while((i = zip_deflate_internal(buff, 0, buff.length)) > 0) { + var cbuf = []; + cbuf.length = i; + for(j = 0;j < i;j++) { + cbuf[j] = String.fromCharCode(buff[j]) + } + aout[aout.length] = cbuf.join("") + } + zip_deflate_data = null; + return aout.join("") + }; + this.deflate = zip_deflate +}; +core.ByteArray = function ByteArray(data) { + this.pos = 0; + this.data = data; + this.readUInt32LE = function() { + var data = this.data, pos = this.pos += 4; + return data[--pos] << 24 | data[--pos] << 16 | data[--pos] << 8 | data[--pos] + }; + this.readUInt16LE = function() { + var data = this.data, pos = this.pos += 2; + return data[--pos] << 8 | data[--pos] + } +}; +core.ByteArrayWriter = function ByteArrayWriter(encoding) { + var self = this, data = new runtime.ByteArray(0); + this.appendByteArrayWriter = function(writer) { + data = runtime.concatByteArrays(data, writer.getByteArray()) + }; + this.appendByteArray = function(array) { + data = runtime.concatByteArrays(data, array) + }; + this.appendArray = function(array) { + data = runtime.concatByteArrays(data, runtime.byteArrayFromArray(array)) + }; + this.appendUInt16LE = function(value) { + self.appendArray([value & 255, value >> 8 & 255]) + }; + this.appendUInt32LE = function(value) { + self.appendArray([value & 255, value >> 8 & 255, value >> 16 & 255, value >> 24 & 255]) + }; + this.appendString = function(string) { + data = runtime.concatByteArrays(data, runtime.byteArrayFromString(string, encoding)) + }; + this.getLength = function() { + return data.length + }; + this.getByteArray = function() { + return data + } +}; +core.RawInflate = function RawInflate() { + var zip_WSIZE = 32768; + var zip_STORED_BLOCK = 0; + var zip_STATIC_TREES = 1; + var zip_DYN_TREES = 2; + var zip_lbits = 9; + var zip_dbits = 6; + var zip_INBUFSIZ = 32768; + var zip_INBUF_EXTRA = 64; + var zip_slide; + var zip_wp; + var zip_fixed_tl = null; + var zip_fixed_td; + var zip_fixed_bl, fixed_bd; + var zip_bit_buf; + var zip_bit_len; + var zip_method; + var zip_eof; + var zip_copy_leng; + var zip_copy_dist; + var zip_tl, zip_td; + var zip_bl, zip_bd; + var zip_inflate_data; + var zip_inflate_pos; + var zip_MASK_BITS = new Array(0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535); + var zip_cplens = new Array(3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0); + var zip_cplext = new Array(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99); + var zip_cpdist = new Array(1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577); + var zip_cpdext = new Array(0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13); + var zip_border = new Array(16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15); + var zip_HuftList = function() { + this.next = null; + this.list = null + }; + var zip_HuftNode = function() { + this.e = 0; + this.b = 0; + this.n = 0; + this.t = null + }; + var zip_HuftBuild = function(b, n, s, d, e, mm) { + this.BMAX = 16; + this.N_MAX = 288; + this.status = 0; + this.root = null; + this.m = 0; + var a; + var c = new Array(this.BMAX + 1); + var el; + var f; + var g; + var h; + var i; + var j; + var k; + var lx = new Array(this.BMAX + 1); + var p; + var pidx; + var q; + var r = new zip_HuftNode; + var u = new Array(this.BMAX); + var v = new Array(this.N_MAX); + var w; + var x = new Array(this.BMAX + 1); + var xp; + var y; + var z; + var o; + var tail; + tail = this.root = null; + for(i = 0;i < c.length;i++) { + c[i] = 0 + } + for(i = 0;i < lx.length;i++) { + lx[i] = 0 + } + for(i = 0;i < u.length;i++) { + u[i] = null + } + for(i = 0;i < v.length;i++) { + v[i] = 0 + } + for(i = 0;i < x.length;i++) { + x[i] = 0 + } + el = n > 256 ? b[256] : this.BMAX; + p = b; + pidx = 0; + i = n; + do { + c[p[pidx]]++; + pidx++ + }while(--i > 0); + if(c[0] == n) { + this.root = null; + this.m = 0; + this.status = 0; + return + } + for(j = 1;j <= this.BMAX;j++) { + if(c[j] != 0) { + break + } + } + k = j; + if(mm < j) { + mm = j + } + for(i = this.BMAX;i != 0;i--) { + if(c[i] != 0) { + break + } + } + g = i; + if(mm > i) { + mm = i + } + for(y = 1 << j;j < i;j++, y <<= 1) { + if((y -= c[j]) < 0) { + this.status = 2; + this.m = mm; + return + } + } + if((y -= c[i]) < 0) { + this.status = 2; + this.m = mm; + return + } + c[i] += y; + x[1] = j = 0; + p = c; + pidx = 1; + xp = 2; + while(--i > 0) { + x[xp++] = j += p[pidx++] + } + p = b; + pidx = 0; + i = 0; + do { + if((j = p[pidx++]) != 0) { + v[x[j]++] = i + } + }while(++i < n); + n = x[g]; + x[0] = i = 0; + p = v; + pidx = 0; + h = -1; + w = lx[0] = 0; + q = null; + z = 0; + for(;k <= g;k++) { + a = c[k]; + while(a-- > 0) { + while(k > w + lx[1 + h]) { + w += lx[1 + h]; + h++; + z = (z = g - w) > mm ? mm : z; + if((f = 1 << (j = k - w)) > a + 1) { + f -= a + 1; + xp = k; + while(++j < z) { + if((f <<= 1) <= c[++xp]) { + break + } + f -= c[xp] + } + } + if(w + j > el && w < el) { + j = el - w + } + z = 1 << j; + lx[1 + h] = j; + q = new Array(z); + for(o = 0;o < z;o++) { + q[o] = new zip_HuftNode + } + if(tail == null) { + tail = this.root = new zip_HuftList + }else { + tail = tail.next = new zip_HuftList + } + tail.next = null; + tail.list = q; + u[h] = q; + if(h > 0) { + x[h] = i; + r.b = lx[h]; + r.e = 16 + j; + r.t = q; + j = (i & (1 << w) - 1) >> w - lx[h]; + u[h - 1][j].e = r.e; + u[h - 1][j].b = r.b; + u[h - 1][j].n = r.n; + u[h - 1][j].t = r.t + } + } + r.b = k - w; + if(pidx >= n) { + r.e = 99 + }else { + if(p[pidx] < s) { + r.e = p[pidx] < 256 ? 16 : 15; + r.n = p[pidx++] + }else { + r.e = e[p[pidx] - s]; + r.n = d[p[pidx++] - s] + } + } + f = 1 << k - w; + for(j = i >> w;j < z;j += f) { + q[j].e = r.e; + q[j].b = r.b; + q[j].n = r.n; + q[j].t = r.t + } + for(j = 1 << k - 1;(i & j) != 0;j >>= 1) { + i ^= j + } + i ^= j; + while((i & (1 << w) - 1) != x[h]) { + w -= lx[h]; + h-- + } + } + } + this.m = lx[1]; + this.status = y != 0 && g != 1 ? 1 : 0 + }; + var zip_GET_BYTE = function() { + if(zip_inflate_data.length == zip_inflate_pos) { + return-1 + } + return zip_inflate_data[zip_inflate_pos++] + }; + var zip_NEEDBITS = function(n) { + while(zip_bit_len < n) { + zip_bit_buf |= zip_GET_BYTE() << zip_bit_len; + zip_bit_len += 8 + } + }; + var zip_GETBITS = function(n) { + return zip_bit_buf & zip_MASK_BITS[n] + }; + var zip_DUMPBITS = function(n) { + zip_bit_buf >>= n; + zip_bit_len -= n + }; + var zip_inflate_codes = function(buff, off, size) { + var e; + var t; + var n; + if(size == 0) { + return 0 + } + n = 0; + for(;;) { + zip_NEEDBITS(zip_bl); + t = zip_tl.list[zip_GETBITS(zip_bl)]; + e = t.e; + while(e > 16) { + if(e == 99) { + return-1 + } + zip_DUMPBITS(t.b); + e -= 16; + zip_NEEDBITS(e); + t = t.t[zip_GETBITS(e)]; + e = t.e + } + zip_DUMPBITS(t.b); + if(e == 16) { + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = t.n; + if(n == size) { + return size + } + continue + } + if(e == 15) { + break + } + zip_NEEDBITS(e); + zip_copy_leng = t.n + zip_GETBITS(e); + zip_DUMPBITS(e); + zip_NEEDBITS(zip_bd); + t = zip_td.list[zip_GETBITS(zip_bd)]; + e = t.e; + while(e > 16) { + if(e == 99) { + return-1 + } + zip_DUMPBITS(t.b); + e -= 16; + zip_NEEDBITS(e); + t = t.t[zip_GETBITS(e)]; + e = t.e + } + zip_DUMPBITS(t.b); + zip_NEEDBITS(e); + zip_copy_dist = zip_wp - t.n - zip_GETBITS(e); + zip_DUMPBITS(e); + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_copy_dist &= zip_WSIZE - 1; + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++] + } + if(n == size) { + return size + } + } + zip_method = -1; + return n + }; + var zip_inflate_stored = function(buff, off, size) { + var n; + n = zip_bit_len & 7; + zip_DUMPBITS(n); + zip_NEEDBITS(16); + n = zip_GETBITS(16); + zip_DUMPBITS(16); + zip_NEEDBITS(16); + if(n != (~zip_bit_buf & 65535)) { + return-1 + } + zip_DUMPBITS(16); + zip_copy_leng = n; + n = 0; + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_wp &= zip_WSIZE - 1; + zip_NEEDBITS(8); + buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); + zip_DUMPBITS(8) + } + if(zip_copy_leng == 0) { + zip_method = -1 + } + return n + }; + var zip_fixed_bd; + var zip_inflate_fixed = function(buff, off, size) { + if(zip_fixed_tl == null) { + var i; + var l = new Array(288); + var h; + for(i = 0;i < 144;i++) { + l[i] = 8 + } + for(;i < 256;i++) { + l[i] = 9 + } + for(;i < 280;i++) { + l[i] = 7 + } + for(;i < 288;i++) { + l[i] = 8 + } + zip_fixed_bl = 7; + h = new zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, zip_fixed_bl); + if(h.status != 0) { + alert("HufBuild error: " + h.status); + return-1 + } + zip_fixed_tl = h.root; + zip_fixed_bl = h.m; + for(i = 0;i < 30;i++) { + l[i] = 5 + } + zip_fixed_bd = 5; + h = new zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd); + if(h.status > 1) { + zip_fixed_tl = null; + alert("HufBuild error: " + h.status); + return-1 + } + zip_fixed_td = h.root; + zip_fixed_bd = h.m + } + zip_tl = zip_fixed_tl; + zip_td = zip_fixed_td; + zip_bl = zip_fixed_bl; + zip_bd = zip_fixed_bd; + return zip_inflate_codes(buff, off, size) + }; + var zip_inflate_dynamic = function(buff, off, size) { + var i; + var j; + var l; + var n; + var t; + var nb; + var nl; + var nd; + var ll = new Array(286 + 30); + var h; + for(i = 0;i < ll.length;i++) { + ll[i] = 0 + } + zip_NEEDBITS(5); + nl = 257 + zip_GETBITS(5); + zip_DUMPBITS(5); + zip_NEEDBITS(5); + nd = 1 + zip_GETBITS(5); + zip_DUMPBITS(5); + zip_NEEDBITS(4); + nb = 4 + zip_GETBITS(4); + zip_DUMPBITS(4); + if(nl > 286 || nd > 30) { + return-1 + } + for(j = 0;j < nb;j++) { + zip_NEEDBITS(3); + ll[zip_border[j]] = zip_GETBITS(3); + zip_DUMPBITS(3) + } + for(;j < 19;j++) { + ll[zip_border[j]] = 0 + } + zip_bl = 7; + h = new zip_HuftBuild(ll, 19, 19, null, null, zip_bl); + if(h.status != 0) { + return-1 + } + zip_tl = h.root; + zip_bl = h.m; + n = nl + nd; + i = l = 0; + while(i < n) { + zip_NEEDBITS(zip_bl); + t = zip_tl.list[zip_GETBITS(zip_bl)]; + j = t.b; + zip_DUMPBITS(j); + j = t.n; + if(j < 16) { + ll[i++] = l = j + }else { + if(j == 16) { + zip_NEEDBITS(2); + j = 3 + zip_GETBITS(2); + zip_DUMPBITS(2); + if(i + j > n) { + return-1 + } + while(j-- > 0) { + ll[i++] = l + } + }else { + if(j == 17) { + zip_NEEDBITS(3); + j = 3 + zip_GETBITS(3); + zip_DUMPBITS(3); + if(i + j > n) { + return-1 + } + while(j-- > 0) { + ll[i++] = 0 + } + l = 0 + }else { + zip_NEEDBITS(7); + j = 11 + zip_GETBITS(7); + zip_DUMPBITS(7); + if(i + j > n) { + return-1 + } + while(j-- > 0) { + ll[i++] = 0 + } + l = 0 + } + } + } + } + zip_bl = zip_lbits; + h = new zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl); + if(zip_bl == 0) { + h.status = 1 + } + if(h.status != 0) { + return-1 + } + zip_tl = h.root; + zip_bl = h.m; + for(i = 0;i < nd;i++) { + ll[i] = ll[i + nl] + } + zip_bd = zip_dbits; + h = new zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd); + zip_td = h.root; + zip_bd = h.m; + if(zip_bd == 0 && nl > 257) { + return-1 + } + if(h.status != 0) { + return-1 + } + return zip_inflate_codes(buff, off, size) + }; + var zip_inflate_start = function() { + var i; + if(zip_slide == null) { + zip_slide = new Array(2 * zip_WSIZE) + } + zip_wp = 0; + zip_bit_buf = 0; + zip_bit_len = 0; + zip_method = -1; + zip_eof = false; + zip_copy_leng = zip_copy_dist = 0; + zip_tl = null + }; + var zip_inflate_internal = function(buff, off, size) { + var n, i; + n = 0; + while(n < size) { + if(zip_eof && zip_method == -1) { + return n + } + if(zip_copy_leng > 0) { + if(zip_method != zip_STORED_BLOCK) { + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_copy_dist &= zip_WSIZE - 1; + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = zip_slide[zip_copy_dist++] + } + }else { + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_wp &= zip_WSIZE - 1; + zip_NEEDBITS(8); + buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); + zip_DUMPBITS(8) + } + if(zip_copy_leng == 0) { + zip_method = -1 + } + } + if(n == size) { + return n + } + } + if(zip_method == -1) { + if(zip_eof) { + break + } + zip_NEEDBITS(1); + if(zip_GETBITS(1) != 0) { + zip_eof = true + } + zip_DUMPBITS(1); + zip_NEEDBITS(2); + zip_method = zip_GETBITS(2); + zip_DUMPBITS(2); + zip_tl = null; + zip_copy_leng = 0 + } + switch(zip_method) { + case 0: + i = zip_inflate_stored(buff, off + n, size - n); + break; + case 1: + if(zip_tl != null) { + i = zip_inflate_codes(buff, off + n, size - n) + }else { + i = zip_inflate_fixed(buff, off + n, size - n) + } + break; + case 2: + if(zip_tl != null) { + i = zip_inflate_codes(buff, off + n, size - n) + }else { + i = zip_inflate_dynamic(buff, off + n, size - n) + } + break; + default: + i = -1; + break + } + if(i == -1) { + if(zip_eof) { + return 0 + } + return-1 + } + n += i + } + return n + }; + var zip_inflate = function(data, size) { + var i, j; + zip_inflate_start(); + zip_inflate_data = data; + zip_inflate_pos = 0; + var buff = new runtime.ByteArray(size); + zip_inflate_internal(buff, 0, size); + zip_inflate_data = null; + return buff + }; + this.inflate = zip_inflate +}; +core.Cursor = function Cursor(selection, document) { + var cursorns, cursorNode; + cursorns = "urn:webodf:names:cursor"; + cursorNode = document.createElementNS(cursorns, "cursor"); + function putCursorIntoTextNode(container, offset) { + var len, ref, textnode, parent; + parent = container.parentNode; + if(offset === 0) { + parent.insertBefore(cursorNode, container) + }else { + if(offset === container.length) { + parent.appendChild(cursorNode) + }else { + len = container.length; + ref = container.nextSibling; + textnode = document.createTextNode(container.substringData(offset, len)); + container.deleteData(offset, len); + if(ref) { + parent.insertBefore(textnode, ref) + }else { + parent.appendChild(textnode) + } + parent.insertBefore(cursorNode, textnode) + } + } + } + function putCursorIntoContainer(container, offset) { + var node; + node = container.firstChild; + while(node && offset) { + node = node.nextSibling; + offset -= 1 + } + container.insertBefore(cursorNode, node) + } + function getPotentialParentOrNode(parent, node) { + var n = node; + while(n && n !== parent) { + n = n.parentNode + } + return n || node + } + function removeCursorFromSelectionRange(range, cursorpos) { + var cursorParent, start, end; + cursorParent = cursorNode.parentNode; + start = getPotentialParentOrNode(cursorNode, range.startContainer); + end = getPotentialParentOrNode(cursorNode, range.endContainer); + if(start === cursorNode) { + range.setStart(cursorParent, cursorpos) + }else { + if(start === cursorParent && range.startOffset > cursorpos) { + range.setStart(cursorParent, range.startOffset - 1) + } + } + if(range.endContainer === cursorNode) { + range.setEnd(cursorParent, cursorpos) + }else { + if(range.endContainer === cursorParent && range.endOffset > cursorpos) { + range.setEnd(cursorParent, range.endOffset - 1) + } + } + } + function adaptRangeToMergedText(range, prev, textnodetomerge, cursorpos) { + var diff = prev.length - textnodetomerge.length; + if(range.startContainer === textnodetomerge) { + range.setStart(prev, diff + range.startOffset) + }else { + if(range.startContainer === prev.parentNode && range.startOffset === cursorpos) { + range.setStart(prev, diff) + } + } + if(range.endContainer === textnodetomerge) { + range.setEnd(prev, diff + range.endOffset) + }else { + if(range.endContainer === prev.parentNode && range.endOffset === cursorpos) { + range.setEnd(prev, diff) + } + } + } + function removeCursor() { + var i, cursorpos, node, textnodetoremove, range; + if(!cursorNode.parentNode) { + return + } + cursorpos = 0; + node = cursorNode.parentNode.firstChild; + while(node && node !== cursorNode) { + cursorpos += 1; + node = node.nextSibling + } + if(cursorNode.previousSibling && cursorNode.previousSibling.nodeType === 3 && cursorNode.nextSibling && cursorNode.nextSibling.nodeType === 3) { + textnodetoremove = cursorNode.nextSibling; + cursorNode.previousSibling.appendData(textnodetoremove.nodeValue) + } + for(i = 0;i < selection.rangeCount;i += 1) { + removeCursorFromSelectionRange(selection.getRangeAt(i), cursorpos) + } + if(textnodetoremove) { + for(i = 0;i < selection.rangeCount;i += 1) { + adaptRangeToMergedText(selection.getRangeAt(i), cursorNode.previousSibling, textnodetoremove, cursorpos) + } + textnodetoremove.parentNode.removeChild(textnodetoremove) + } + cursorNode.parentNode.removeChild(cursorNode) + } + function putCursor(container, offset) { + if(container.nodeType === 3) { + putCursorIntoTextNode(container, offset) + }else { + if(container.nodeType !== 9) { + putCursorIntoContainer(container, offset) + } + } + } + this.getNode = function() { + return cursorNode + }; + this.updateToSelection = function() { + var range; + removeCursor(); + if(selection.focusNode) { + putCursor(selection.focusNode, selection.focusOffset) + } + }; + this.remove = function() { + removeCursor() + } +}; +core.UnitTest = function UnitTest() { +}; +core.UnitTest.prototype.setUp = function() { +}; +core.UnitTest.prototype.tearDown = function() { +}; +core.UnitTest.prototype.description = function() { +}; +core.UnitTest.prototype.tests = function() { +}; +core.UnitTest.prototype.asyncTests = function() { +}; +core.UnitTestRunner = function UnitTestRunner() { + var failedTests = 0; + function debug(msg) { + runtime.log(msg) + } + function testFailed(msg) { + failedTests += 1; + runtime.log("fail", msg) + } + function testPassed(msg) { + runtime.log("pass", msg) + } + function areArraysEqual(a, b) { + var i; + try { + if(a.length !== b.length) { + return false + } + for(i = 0;i < a.length;i += 1) { + if(a[i] !== b[i]) { + return false + } + } + }catch(ex) { + return false + } + return true + } + function isResultCorrect(actual, expected) { + if(expected === 0) { + return actual === expected && 1 / actual === 1 / expected + } + if(actual === expected) { + return true + } + if(typeof expected === "number" && isNaN(expected)) { + return typeof actual === "number" && isNaN(actual) + } + if(Object.prototype.toString.call(expected) === Object.prototype.toString.call([])) { + return areArraysEqual(actual, expected) + } + return false + } + function stringify(v) { + if(v === 0 && 1 / v < 0) { + return"-0" + } + return String(v) + } + function shouldBe(t, a, b) { + if(typeof a !== "string" || typeof b !== "string") { + debug("WARN: shouldBe() expects string arguments") + } + var exception, av, bv; + try { + av = eval(a) + }catch(e) { + exception = e + } + bv = eval(b); + if(exception) { + testFailed(a + " should be " + bv + ". Threw exception " + exception) + }else { + if(isResultCorrect(av, bv)) { + testPassed(a + " is " + b) + }else { + if(typeof av === typeof bv) { + testFailed(a + " should be " + bv + ". Was " + stringify(av) + ".") + }else { + testFailed(a + " should be " + bv + " (of type " + typeof bv + "). Was " + av + " (of type " + typeof av + ").") + } + } + } + } + function shouldBeNonNull(t, a) { + var exception, av; + try { + av = eval(a) + }catch(e) { + exception = e + } + if(exception) { + testFailed(a + " should be non-null. Threw exception " + exception) + }else { + if(av !== null) { + testPassed(a + " is non-null.") + }else { + testFailed(a + " should be non-null. Was " + av) + } + } + } + function shouldBeNull(t, a) { + shouldBe(t, a, "null") + } + this.shouldBeNull = shouldBeNull; + this.shouldBeNonNull = shouldBeNonNull; + this.shouldBe = shouldBe; + this.countFailedTests = function() { + return failedTests + } +}; +core.UnitTester = function UnitTester() { + var failedTests = 0, results = {}; + this.runTests = function(TestClass, callback) { + var testName = Runtime.getFunctionName(TestClass), tname, runner = new core.UnitTestRunner, test = new TestClass(runner), testResults = {}, i, t, tests, lastFailCount; + if(testName.hasOwnProperty(results)) { + runtime.log("Test " + testName + " has already run."); + return + } + runtime.log("Running " + testName + ": " + test.description()); + tests = test.tests(); + for(i = 0;i < tests.length;i += 1) { + t = tests[i]; + tname = Runtime.getFunctionName(t); + runtime.log("Running " + tname); + lastFailCount = runner.countFailedTests(); + test.setUp(); + t(); + test.tearDown(); + testResults[tname] = lastFailCount === runner.countFailedTests() + } + function runAsyncTests(todo) { + if(todo.length === 0) { + results[testName] = testResults; + failedTests += runner.countFailedTests(); + callback(); + return + } + t = todo[0]; + var tname = Runtime.getFunctionName(t); + runtime.log("Running " + tname); + lastFailCount = runner.countFailedTests(); + test.setUp(); + t(function() { + test.tearDown(); + testResults[tname] = lastFailCount === runner.countFailedTests(); + runAsyncTests(todo.slice(1)) + }) + } + runAsyncTests(test.asyncTests()) + }; + this.countFailedTests = function() { + return failedTests + }; + this.results = function() { + return results + } +}; +core.PointWalker = function PointWalker(node) { + var currentNode = node, before = null, after = node && node.firstChild, root = node, pos = 0; + function getPosition(node) { + var p = -1, n = node; + while(n) { + n = n.previousSibling; + p += 1 + } + return p + } + this.setPoint = function(node, position) { + currentNode = node; + pos = position; + if(currentNode.nodeType === 3) { + after = null; + before = null + }else { + after = currentNode.firstChild; + while(position) { + position -= 1; + after = after.nextSibling + } + if(after) { + before = after.previousSibling + }else { + before = currentNode.lastChild + } + } + }; + this.stepForward = function() { + var len; + if(currentNode.nodeType === 3) { + if(typeof currentNode.nodeValue.length === "number") { + len = currentNode.nodeValue.length + }else { + len = currentNode.nodeValue.length() + } + if(pos < len) { + pos += 1; + return true + } + } + if(after) { + if(after.nodeType === 1) { + currentNode = after; + before = null; + after = currentNode.firstChild; + pos = 0 + }else { + if(after.nodeType === 3) { + currentNode = after; + before = null; + after = null; + pos = 0 + }else { + before = after; + after = after.nextSibling; + pos += 1 + } + } + return true + } + if(currentNode !== root) { + before = currentNode; + after = before.nextSibling; + currentNode = currentNode.parentNode; + pos = getPosition(before) + 1; + return true + } + return false + }; + this.stepBackward = function() { + if(currentNode.nodeType === 3) { + if(pos > 0) { + pos -= 1; + return true + } + } + if(before) { + if(before.nodeType === 1) { + currentNode = before; + before = currentNode.lastChild; + after = null; + pos = getPosition(before) + 1 + }else { + if(before.nodeType === 3) { + currentNode = before; + before = null; + after = null; + if(typeof currentNode.nodeValue.length === "number") { + pos = currentNode.nodeValue.length + }else { + pos = currentNode.nodeValue.length() + } + }else { + after = before; + before = before.previousSibling; + pos -= 1 + } + } + return true + } + if(currentNode !== root) { + after = currentNode; + before = after.previousSibling; + currentNode = currentNode.parentNode; + pos = getPosition(after); + return true + } + return false + }; + this.node = function() { + return currentNode + }; + this.position = function() { + return pos + }; + this.precedingSibling = function() { + return before + }; + this.followingSibling = function() { + return after + } +}; +core.Async = function Async() { + this.forEach = function(items, f, callback) { + var i, l = items.length, itemsDone = 0; + function end(err) { + if(itemsDone !== l) { + if(err) { + itemsDone = l; + callback(err) + }else { + itemsDone += 1; + if(itemsDone === l) { + callback(null) + } + } + } + } + for(i = 0;i < l;i += 1) { + f(items[i], end) + } + } +}; +runtime.loadClass("core.RawInflate"); +runtime.loadClass("core.ByteArray"); +runtime.loadClass("core.ByteArrayWriter"); +runtime.loadClass("core.Base64"); +core.Zip = function Zip(url, entriesReadCallback) { + var entries, filesize, nEntries, inflate = (new core.RawInflate).inflate, zip = this, base64 = new core.Base64; + function crc32(data) { + var table = [0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, + 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, + 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, + 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, + 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, + 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918E3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117], crc = + 0, i, iTop = data.length, x = 0, y = 0; + crc = crc ^ -1; + for(i = 0;i < iTop;i += 1) { + y = (crc ^ data[i]) & 255; + x = table[y]; + crc = crc >>> 8 ^ x + } + return crc ^ -1 + } + function dosTime2Date(dostime) { + var year = (dostime >> 25 & 127) + 1980, month = (dostime >> 21 & 15) - 1, mday = dostime >> 16 & 31, hour = dostime >> 11 & 15, min = dostime >> 5 & 63, sec = (dostime & 31) << 1, d = new Date(year, month, mday, hour, min, sec); + return d + } + function date2DosTime(date) { + var y = date.getFullYear(); + return y < 1980 ? 0 : y - 1980 << 25 | date.getMonth() + 1 << 21 | date.getDate() << 16 | date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1 + } + function ZipEntry(url, stream) { + var sig, namelen, extralen, commentlen, compressionMethod, compressedSize, uncompressedSize, offset, crc, entry = this; + function handleEntryData(data, callback) { + var stream = new core.ByteArray(data), sig = stream.readUInt32LE(), filenamelen, extralen; + if(sig !== 67324752) { + callback("File entry signature is wrong." + sig.toString() + " " + data.length.toString(), null); + return + } + stream.pos += 22; + filenamelen = stream.readUInt16LE(); + extralen = stream.readUInt16LE(); + stream.pos += filenamelen + extralen; + if(compressionMethod) { + data = data.slice(stream.pos, stream.pos + compressedSize); + if(compressedSize !== data.length) { + callback("The amount of compressed bytes read was " + data.length.toString() + " instead of " + compressedSize.toString() + " for " + entry.filename + " in " + url + ".", null); + return + } + data = inflate(data, uncompressedSize) + }else { + data = data.slice(stream.pos, stream.pos + uncompressedSize) + } + if(uncompressedSize !== data.length) { + callback("The amount of bytes read was " + data.length.toString() + " instead of " + uncompressedSize.toString() + " for " + entry.filename + " in " + url + ".", null); + return + } + entry.data = data; + callback(null, data) + } + function load(callback) { + if(entry.data !== undefined) { + callback(null, entry.data); + return + } + var size = compressedSize + 34 + namelen + extralen + 256; + if(size + offset > filesize) { + size = filesize - offset + } + runtime.read(url, offset, size, function(err, data) { + if(err) { + callback(err, data) + }else { + handleEntryData(data, callback) + } + }) + } + this.load = load; + function set(filename, data, compressed, date) { + entry.filename = filename; + entry.data = data; + entry.compressed = compressed; + entry.date = date + } + this.set = set; + this.error = null; + if(!stream) { + return + } + sig = stream.readUInt32LE(); + if(sig !== 33639248) { + this.error = "Central directory entry has wrong signature at position " + (stream.pos - 4).toString() + ' for file "' + url + '": ' + stream.data.length.toString(); + return + } + stream.pos += 6; + compressionMethod = stream.readUInt16LE(); + this.date = dosTime2Date(stream.readUInt32LE()); + crc = stream.readUInt32LE(); + compressedSize = stream.readUInt32LE(); + uncompressedSize = stream.readUInt32LE(); + namelen = stream.readUInt16LE(); + extralen = stream.readUInt16LE(); + commentlen = stream.readUInt16LE(); + stream.pos += 8; + offset = stream.readUInt32LE(); + this.filename = runtime.byteArrayToString(stream.data.slice(stream.pos, stream.pos + namelen), "utf8"); + stream.pos += namelen + extralen + commentlen + } + function handleCentralDirectory(data, callback) { + var stream = new core.ByteArray(data), i, e; + entries = []; + for(i = 0;i < nEntries;i += 1) { + e = new ZipEntry(url, stream); + if(e.error) { + callback(e.error, zip); + return + } + entries[entries.length] = e + } + callback(null, zip) + } + function handleCentralDirectoryEnd(data, callback) { + if(data.length !== 22) { + callback("Central directory length should be 22.", zip); + return + } + var stream = new core.ByteArray(data), sig, disk, cddisk, diskNEntries, cdsSize, cdsOffset; + sig = stream.readUInt32LE(); + if(sig !== 101010256) { + callback("Central directory signature is wrong: " + sig.toString(), zip); + return + } + disk = stream.readUInt16LE(); + if(disk !== 0) { + callback("Zip files with non-zero disk numbers are not supported.", zip); + return + } + cddisk = stream.readUInt16LE(); + if(cddisk !== 0) { + callback("Zip files with non-zero disk numbers are not supported.", zip); + return + } + diskNEntries = stream.readUInt16LE(); + nEntries = stream.readUInt16LE(); + if(diskNEntries !== nEntries) { + callback("Number of entries is inconsistent.", zip); + return + } + cdsSize = stream.readUInt32LE(); + cdsOffset = stream.readUInt16LE(); + cdsOffset = filesize - 22 - cdsSize; + runtime.read(url, cdsOffset, filesize - cdsOffset, function(err, data) { + handleCentralDirectory(data, callback) + }) + } + function load(filename, callback) { + var entry = null, end = filesize, e, i; + for(i = 0;i < entries.length;i += 1) { + e = entries[i]; + if(e.filename === filename) { + entry = e; + break + } + } + if(entry) { + if(entry.data) { + callback(null, entry.data) + }else { + entry.load(callback) + } + }else { + callback(filename + " not found.", null) + } + } + function loadAsString(filename, callback) { + load(filename, function(err, data) { + if(err) { + return callback(err, null) + } + data = runtime.byteArrayToString(data, "utf8"); + callback(null, data) + }) + } + function loadContentXmlAsFragments(filename, handler) { + loadAsString(filename, function(err, data) { + if(err) { + return handler.rootElementReady(err) + } + handler.rootElementReady(null, data, true) + }) + } + function loadAsDataURL(filename, mimetype, callback) { + load(filename, function(err, data) { + if(err) { + return callback(err, null) + } + var p = data, chunksize = 45E3, i = 0, url; + if(!mimetype) { + if(p[1] === 80 && p[2] === 78 && p[3] === 71) { + mimetype = "image/png" + }else { + if(p[0] === 255 && p[1] === 216 && p[2] === 255) { + mimetype = "image/jpeg" + }else { + if(p[0] === 71 && p[1] === 73 && p[2] === 70) { + mimetype = "image/gif" + }else { + mimetype = "" + } + } + } + } + url = "data:" + mimetype + ";base64,"; + while(i < data.length) { + url += base64.convertUTF8ArrayToBase64(p.slice(i, Math.min(i + chunksize, p.length))); + i += chunksize + } + callback(null, url) + }) + } + function loadAsDOM(filename, callback) { + loadAsString(filename, function(err, xmldata) { + if(err) { + callback(err, null); + return + } + var parser = new DOMParser; + xmldata = parser.parseFromString(xmldata, "text/xml"); + callback(null, xmldata) + }) + } + function save(filename, data, compressed, date) { + var i, entry; + for(i = 0;i < entries.length;i += 1) { + entry = entries[i]; + if(entry.filename === filename) { + entry.set(filename, data, compressed, date); + return + } + } + entry = new ZipEntry(url); + entry.set(filename, data, compressed, date); + entries.push(entry) + } + function writeEntry(entry) { + var data = new core.ByteArrayWriter("utf8"), length = 0; + data.appendArray([80, 75, 3, 4, 20, 0, 0, 0, 0, 0]); + if(entry.data) { + length = entry.data.length + } + data.appendUInt32LE(date2DosTime(entry.date)); + data.appendUInt32LE(crc32(entry.data)); + data.appendUInt32LE(length); + data.appendUInt32LE(length); + data.appendUInt16LE(entry.filename.length); + data.appendUInt16LE(0); + data.appendString(entry.filename); + if(entry.data) { + data.appendByteArray(entry.data) + } + return data + } + function writeCODEntry(entry, offset) { + var data = new core.ByteArrayWriter("utf8"), length = 0; + data.appendArray([80, 75, 1, 2, 20, 0, 20, 0, 0, 0, 0, 0]); + if(entry.data) { + length = entry.data.length + } + data.appendUInt32LE(date2DosTime(entry.date)); + data.appendUInt32LE(crc32(entry.data)); + data.appendUInt32LE(length); + data.appendUInt32LE(length); + data.appendUInt16LE(entry.filename.length); + data.appendArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + data.appendUInt32LE(offset); + data.appendString(entry.filename); + return data + } + function loadAllEntries(position, callback) { + if(position === entries.length) { + callback(null); + return + } + var entry = entries[position]; + if(entry.data !== undefined) { + loadAllEntries(position + 1, callback); + return + } + entry.load(function(err) { + if(err) { + callback(err); + return + } + loadAllEntries(position + 1, callback) + }) + } + function write(callback) { + loadAllEntries(0, function(err) { + if(err) { + callback(err); + return + } + var data = new core.ByteArrayWriter("utf8"), i, e, codoffset, codsize, offsets = [0]; + for(i = 0;i < entries.length;i += 1) { + data.appendByteArrayWriter(writeEntry(entries[i])); + offsets.push(data.getLength()) + } + codoffset = data.getLength(); + for(i = 0;i < entries.length;i += 1) { + e = entries[i]; + data.appendByteArrayWriter(writeCODEntry(e, offsets[i])) + } + codsize = data.getLength() - codoffset; + data.appendArray([80, 75, 5, 6, 0, 0, 0, 0]); + data.appendUInt16LE(entries.length); + data.appendUInt16LE(entries.length); + data.appendUInt32LE(codsize); + data.appendUInt32LE(codoffset); + data.appendArray([0, 0]); + runtime.writeFile(url, data.getByteArray(), callback) + }) + } + this.load = load; + this.save = save; + this.write = write; + this.loadContentXmlAsFragments = loadContentXmlAsFragments; + this.loadAsString = loadAsString; + this.loadAsDOM = loadAsDOM; + this.loadAsDataURL = loadAsDataURL; + this.getEntries = function() { + return entries.slice() + }; + filesize = -1; + if(entriesReadCallback === null) { + entries = []; + return + } + runtime.getFileSize(url, function(size) { + filesize = size; + if(filesize < 0) { + entriesReadCallback("File '" + url + "' cannot be read.", zip) + }else { + runtime.read(url, filesize - 22, 22, function(err, data) { + if(err || entriesReadCallback === null) { + entriesReadCallback(err, zip) + }else { + handleCentralDirectoryEnd(data, entriesReadCallback) + } + }) + } + }) +}; +xmldom.LSSerializerFilter = function LSSerializerFilter() { +}; +if(typeof Object.create !== "function") { + Object["create"] = function(o) { + var F = function() { + }; + F.prototype = o; + return new F + } +} +xmldom.LSSerializer = function LSSerializer() { + var self = this; + function serializeAttribute(prefix, attr) { + var s = prefix + attr.localName + '="' + attr.nodeValue + '"'; + return s + } + function attributePrefix(nsmap, prefix, ns) { + if(nsmap.hasOwnProperty(ns)) { + return nsmap[ns] + ":" + } + if(nsmap[ns] !== prefix) { + nsmap[ns] = prefix + } + return prefix + ":" + } + function startNode(nsmap, node) { + var s = "", atts = node.attributes, length, i, attr, attstr = "", accept, prefix; + if(atts) { + if(nsmap[node.namespaceURI] !== node.prefix) { + nsmap[node.namespaceURI] = node.prefix + } + s += "<" + node.nodeName; + length = atts.length; + for(i = 0;i < length;i += 1) { + attr = atts.item(i); + if(attr.namespaceURI !== "http://www.w3.org/2000/xmlns/") { + accept = self.filter ? self.filter.acceptNode(attr) : 1; + if(accept === 1) { + if(attr.namespaceURI) { + prefix = attributePrefix(nsmap, attr.prefix, attr.namespaceURI) + }else { + prefix = "" + } + attstr += " " + serializeAttribute(prefix, attr) + } + } + } + for(i in nsmap) { + if(nsmap.hasOwnProperty(i)) { + prefix = nsmap[i]; + if(!prefix) { + s += ' xmlns="' + i + '"' + }else { + if(prefix !== "xmlns") { + s += " xmlns:" + nsmap[i] + '="' + i + '"' + } + } + } + } + s += attstr + ">" + } + return s + } + function endNode(node) { + var s = ""; + if(node.nodeType === 1) { + s += "" + } + return s + } + function serializeNode(parentnsmap, node) { + var s = "", nsmap = Object.create(parentnsmap), accept = self.filter ? self.filter.acceptNode(node) : 1, child; + if(accept === 1) { + s += startNode(nsmap, node) + } + if(accept === 1 || accept === 3) { + child = node.firstChild; + while(child) { + s += serializeNode(nsmap, child); + child = child.nextSibling + } + if(node.nodeValue) { + s += node.nodeValue + } + } + if(accept === 1) { + s += endNode(node) + } + return s + } + function invertMap(map) { + var m = {}, i; + for(i in map) { + if(map.hasOwnProperty(i)) { + m[map[i]] = i + } + } + return m + } + this.filter = null; + this.writeToString = function(node, nsmap) { + if(!node) { + return"" + } + nsmap = nsmap ? invertMap(nsmap) : {}; + return serializeNode(nsmap, node) + } +}; +xmldom.RelaxNGParser = function RelaxNGParser() { + var self = this, rngns = "http://relaxng.org/ns/structure/1.0", xmlnsns = "http://www.w3.org/2000/xmlns/", start, nsmap = {"http://www.w3.org/XML/1998/namespace":"xml"}, parse; + function RelaxNGParseError(error, context) { + this.message = function() { + if(context) { + error += context.nodeType === 1 ? " Element " : " Node "; + error += context.nodeName; + if(context.nodeValue) { + error += " with value '" + context.nodeValue + "'" + } + error += "." + } + return error + } + } + function splitToDuos(e) { + if(e.e.length <= 2) { + return e + } + var o = {name:e.name, e:e.e.slice(0, 2)}; + return splitToDuos({name:e.name, e:[o].concat(e.e.slice(2))}) + } + function splitQName(name) { + var r = name.split(":", 2), prefix = "", i; + if(r.length === 1) { + r = ["", r[0]] + }else { + prefix = r[0] + } + for(i in nsmap) { + if(nsmap[i] === prefix) { + r[0] = i + } + } + return r + } + function splitQNames(def) { + var i, l = def.names ? def.names.length : 0, name, localnames = def.localnames = [l], namespaces = def.namespaces = [l]; + for(i = 0;i < l;i += 1) { + name = splitQName(def.names[i]); + namespaces[i] = name[0]; + localnames[i] = name[1] + } + } + function trim(str) { + str = str.replace(/^\s\s*/, ""); + var ws = /\s/, i = str.length - 1; + while(ws.test(str.charAt(i))) { + i -= 1 + } + return str.slice(0, i + 1) + } + function copyAttributes(atts, name, names) { + var a = {}, i, att; + for(i = 0;i < atts.length;i += 1) { + att = atts.item(i); + if(!att.namespaceURI) { + if(att.localName === "name" && (name === "element" || name === "attribute")) { + names.push(att.value) + } + if(att.localName === "name" || att.localName === "combine" || att.localName === "type") { + att.value = trim(att.value) + } + a[att.localName] = att.value + }else { + if(att.namespaceURI === xmlnsns) { + nsmap[att.value] = att.localName + } + } + } + return a + } + function parseChildren(c, e, elements, names) { + var text = "", ce; + while(c) { + if(c.nodeType === 1 && c.namespaceURI === rngns) { + ce = parse(c, elements, e); + if(ce) { + if(ce.name === "name") { + names.push(nsmap[ce.a.ns] + ":" + ce.text); + e.push(ce) + }else { + if(ce.name === "choice" && ce.names && ce.names.length) { + names = names.concat(ce.names); + delete ce.names; + e.push(ce) + }else { + e.push(ce) + } + } + } + }else { + if(c.nodeType === 3) { + text += c.nodeValue + } + } + c = c.nextSibling + } + return text + } + function combineDefines(combine, name, e, siblings) { + var i, ce; + for(i = 0;siblings && i < siblings.length;i += 1) { + ce = siblings[i]; + if(ce.name === "define" && ce.a && ce.a.name === name) { + ce.e = [{name:combine, e:ce.e.concat(e)}]; + return ce + } + } + return null + } + parse = function parse(element, elements, siblings) { + var e = [], a, ce, i, text, name = element.localName, names = []; + a = copyAttributes(element.attributes, name, names); + a.combine = a.combine || undefined; + text = parseChildren(element.firstChild, e, elements, names); + if(name !== "value" && name !== "param") { + text = /^\s*([\s\S]*\S)?\s*$/.exec(text)[1] + } + if(name === "value" && a.type === undefined) { + a.type = "token"; + a.datatypeLibrary = "" + } + if((name === "attribute" || name === "element") && a.name !== undefined) { + i = splitQName(a.name); + e = [{name:"name", text:i[1], a:{ns:i[0]}}].concat(e); + delete a.name + } + if(name === "name" || name === "nsName" || name === "value") { + if(a.ns === undefined) { + a.ns = "" + } + }else { + delete a.ns + } + if(name === "name") { + i = splitQName(text); + a.ns = i[0]; + text = i[1] + } + if(e.length > 1 && (name === "define" || name === "oneOrMore" || name === "zeroOrMore" || name === "optional" || name === "list" || name === "mixed")) { + e = [{name:"group", e:splitToDuos({name:"group", e:e}).e}] + } + if(e.length > 2 && name === "element") { + e = [e[0]].concat({name:"group", e:splitToDuos({name:"group", e:e.slice(1)}).e}) + } + if(e.length === 1 && name === "attribute") { + e.push({name:"text", text:text}) + } + if(e.length === 1 && (name === "choice" || name === "group" || name === "interleave")) { + name = e[0].name; + names = e[0].names; + a = e[0].a; + text = e[0].text; + e = e[0].e + }else { + if(e.length > 2 && (name === "choice" || name === "group" || name === "interleave")) { + e = splitToDuos({name:name, e:e}).e + } + } + if(name === "mixed") { + name = "interleave"; + e = [e[0], {name:"text"}] + } + if(name === "optional") { + name = "choice"; + e = [e[0], {name:"empty"}] + } + if(name === "zeroOrMore") { + name = "choice"; + e = [{name:"oneOrMore", e:[e[0]]}, {name:"empty"}] + } + if(name === "define" && a.combine) { + ce = combineDefines(a.combine, a.name, e, siblings); + if(ce) { + return + } + } + ce = {name:name}; + if(e && e.length > 0) { + ce.e = e + } + for(i in a) { + if(a.hasOwnProperty(i)) { + ce.a = a; + break + } + } + if(text !== undefined) { + ce.text = text + } + if(names && names.length > 0) { + ce.names = names + } + if(name === "element") { + ce.id = elements.length; + elements.push(ce); + ce = {name:"elementref", id:ce.id} + } + return ce + }; + function resolveDefines(def, defines) { + var i = 0, e, defs, end, name = def.name; + while(def.e && i < def.e.length) { + e = def.e[i]; + if(e.name === "ref") { + defs = defines[e.a.name]; + if(!defs) { + throw e.a.name + " was not defined."; + } + end = def.e.slice(i + 1); + def.e = def.e.slice(0, i); + def.e = def.e.concat(defs.e); + def.e = def.e.concat(end) + }else { + i += 1; + resolveDefines(e, defines) + } + } + e = def.e; + if(name === "choice") { + if(!e || !e[1] || e[1].name === "empty") { + if(!e || !e[0] || e[0].name === "empty") { + delete def.e; + def.name = "empty" + }else { + e[1] = e[0]; + e[0] = {name:"empty"} + } + } + } + if(name === "group" || name === "interleave") { + if(e[0].name === "empty") { + if(e[1].name === "empty") { + delete def.e; + def.name = "empty" + }else { + name = def.name = e[1].name; + def.names = e[1].names; + e = def.e = e[1].e + } + }else { + if(e[1].name === "empty") { + name = def.name = e[0].name; + def.names = e[0].names; + e = def.e = e[0].e + } + } + } + if(name === "oneOrMore" && e[0].name === "empty") { + delete def.e; + def.name = "empty" + } + if(name === "attribute") { + splitQNames(def) + } + if(name === "interleave") { + if(e[0].name === "interleave") { + if(e[1].name === "interleave") { + e = def.e = e[0].e.concat(e[1].e) + }else { + e = def.e = [e[1]].concat(e[0].e) + } + }else { + if(e[1].name === "interleave") { + e = def.e = [e[0]].concat(e[1].e) + } + } + } + } + function resolveElements(def, elements) { + var i = 0, e, name; + while(def.e && i < def.e.length) { + e = def.e[i]; + if(e.name === "elementref") { + e.id = e.id || 0; + def.e[i] = elements[e.id] + }else { + if(e.name !== "element") { + resolveElements(e, elements) + } + } + i += 1 + } + } + function main(dom, callback) { + var elements = [], grammar = parse(dom && dom.documentElement, elements, undefined), i, e, defines = {}; + for(i = 0;i < grammar.e.length;i += 1) { + e = grammar.e[i]; + if(e.name === "define") { + defines[e.a.name] = e + }else { + if(e.name === "start") { + start = e + } + } + } + if(!start) { + return[new RelaxNGParseError("No Relax NG start element was found.")] + } + resolveDefines(start, defines); + for(i in defines) { + if(defines.hasOwnProperty(i)) { + resolveDefines(defines[i], defines) + } + } + for(i = 0;i < elements.length;i += 1) { + resolveDefines(elements[i], defines) + } + if(callback) { + self.rootPattern = callback(start.e[0], elements) + } + resolveElements(start, elements); + for(i = 0;i < elements.length;i += 1) { + resolveElements(elements[i], elements) + } + self.start = start; + self.elements = elements; + self.nsmap = nsmap; + return null + } + this.parseRelaxNGDOM = main +}; +runtime.loadClass("xmldom.RelaxNGParser"); +xmldom.RelaxNG = function RelaxNG() { + var xmlnsns = "http://www.w3.org/2000/xmlns/", createChoice, createInterleave, createGroup, createAfter, createOneOrMore, createValue, createAttribute, createNameClass, createData, makePattern, notAllowed = {type:"notAllowed", nullable:false, hash:"notAllowed", textDeriv:function() { + return notAllowed + }, startTagOpenDeriv:function() { + return notAllowed + }, attDeriv:function() { + return notAllowed + }, startTagCloseDeriv:function() { + return notAllowed + }, endTagDeriv:function() { + return notAllowed + }}, empty = {type:"empty", nullable:true, hash:"empty", textDeriv:function() { + return notAllowed + }, startTagOpenDeriv:function() { + return notAllowed + }, attDeriv:function(context, attribute) { + return notAllowed + }, startTagCloseDeriv:function() { + return empty + }, endTagDeriv:function() { + return notAllowed + }}, text = {type:"text", nullable:true, hash:"text", textDeriv:function() { + return text + }, startTagOpenDeriv:function() { + return notAllowed + }, attDeriv:function() { + return notAllowed + }, startTagCloseDeriv:function() { + return text + }, endTagDeriv:function() { + return notAllowed + }}, applyAfter, childDeriv, rootPattern; + function memoize0arg(func) { + return function() { + var cache; + return function() { + if(cache === undefined) { + cache = func() + } + return cache + } + }() + } + function memoize1arg(type, func) { + return function() { + var cache = {}, cachecount = 0; + return function(a) { + var ahash = a.hash || a.toString(), v; + v = cache[ahash]; + if(v !== undefined) { + return v + } + cache[ahash] = v = func(a); + v.hash = type + cachecount.toString(); + cachecount += 1; + return v + } + }() + } + function memoizeNode(func) { + return function() { + var cache = {}; + return function(node) { + var v, m; + m = cache[node.localName]; + if(m === undefined) { + cache[node.localName] = m = {} + }else { + v = m[node.namespaceURI]; + if(v !== undefined) { + return v + } + } + m[node.namespaceURI] = v = func(node); + return v + } + }() + } + function memoize2arg(type, fastfunc, func) { + return function() { + var cache = {}, cachecount = 0; + return function(a, b) { + var v = fastfunc && fastfunc(a, b), ahash, bhash, m; + if(v !== undefined) { + return v + } + ahash = a.hash || a.toString(); + bhash = b.hash || b.toString(); + m = cache[ahash]; + if(m === undefined) { + cache[ahash] = m = {} + }else { + v = m[bhash]; + if(v !== undefined) { + return v + } + } + m[bhash] = v = func(a, b); + v.hash = type + cachecount.toString(); + cachecount += 1; + return v + } + }() + } + function unorderedMemoize2arg(type, fastfunc, func) { + return function() { + var cache = {}, cachecount = 0; + return function(a, b) { + var v = fastfunc && fastfunc(a, b), ahash, bhash, m; + if(v !== undefined) { + return v + } + ahash = a.hash || a.toString(); + bhash = b.hash || b.toString(); + if(ahash < bhash) { + m = ahash; + ahash = bhash; + bhash = m; + m = a; + a = b; + b = m + } + m = cache[ahash]; + if(m === undefined) { + cache[ahash] = m = {} + }else { + v = m[bhash]; + if(v !== undefined) { + return v + } + } + m[bhash] = v = func(a, b); + v.hash = type + cachecount.toString(); + cachecount += 1; + return v + } + }() + } + function getUniqueLeaves(leaves, pattern) { + if(pattern.p1.type === "choice") { + getUniqueLeaves(leaves, pattern.p1) + }else { + leaves[pattern.p1.hash] = pattern.p1 + } + if(pattern.p2.type === "choice") { + getUniqueLeaves(leaves, pattern.p2) + }else { + leaves[pattern.p2.hash] = pattern.p2 + } + } + createChoice = memoize2arg("choice", function(p1, p2) { + if(p1 === notAllowed) { + return p2 + } + if(p2 === notAllowed) { + return p1 + } + if(p1 === p2) { + return p1 + } + }, function(p1, p2) { + function makeChoice(p1, p2) { + return{type:"choice", p1:p1, p2:p2, nullable:p1.nullable || p2.nullable, textDeriv:function(context, text) { + return createChoice(p1.textDeriv(context, text), p2.textDeriv(context, text)) + }, startTagOpenDeriv:memoizeNode(function(node) { + return createChoice(p1.startTagOpenDeriv(node), p2.startTagOpenDeriv(node)) + }), attDeriv:function(context, attribute) { + return createChoice(p1.attDeriv(context, attribute), p2.attDeriv(context, attribute)) + }, startTagCloseDeriv:memoize0arg(function() { + return createChoice(p1.startTagCloseDeriv(), p2.startTagCloseDeriv()) + }), endTagDeriv:memoize0arg(function() { + return createChoice(p1.endTagDeriv(), p2.endTagDeriv()) + })} + } + var leaves = {}, i; + getUniqueLeaves(leaves, {p1:p1, p2:p2}); + p1 = undefined; + p2 = undefined; + for(i in leaves) { + if(leaves.hasOwnProperty(i)) { + if(p1 === undefined) { + p1 = leaves[i] + }else { + if(p2 === undefined) { + p2 = leaves[i] + }else { + p2 = createChoice(p2, leaves[i]) + } + } + } + } + return makeChoice(p1, p2) + }); + createInterleave = unorderedMemoize2arg("interleave", function(p1, p2) { + if(p1 === notAllowed || p2 === notAllowed) { + return notAllowed + } + if(p1 === empty) { + return p2 + } + if(p2 === empty) { + return p1 + } + }, function(p1, p2) { + return{type:"interleave", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) { + return createChoice(createInterleave(p1.textDeriv(context, text), p2), createInterleave(p1, p2.textDeriv(context, text))) + }, startTagOpenDeriv:memoizeNode(function(node) { + return createChoice(applyAfter(function(p) { + return createInterleave(p, p2) + }, p1.startTagOpenDeriv(node)), applyAfter(function(p) { + return createInterleave(p1, p) + }, p2.startTagOpenDeriv(node))) + }), attDeriv:function(context, attribute) { + return createChoice(createInterleave(p1.attDeriv(context, attribute), p2), createInterleave(p1, p2.attDeriv(context, attribute))) + }, startTagCloseDeriv:memoize0arg(function() { + return createInterleave(p1.startTagCloseDeriv(), p2.startTagCloseDeriv()) + })} + }); + createGroup = memoize2arg("group", function(p1, p2) { + if(p1 === notAllowed || p2 === notAllowed) { + return notAllowed + } + if(p1 === empty) { + return p2 + } + if(p2 === empty) { + return p1 + } + }, function(p1, p2) { + return{type:"group", p1:p1, p2:p2, nullable:p1.nullable && p2.nullable, textDeriv:function(context, text) { + var p = createGroup(p1.textDeriv(context, text), p2); + if(p1.nullable) { + return createChoice(p, p2.textDeriv(context, text)) + } + return p + }, startTagOpenDeriv:function(node) { + var x = applyAfter(function(p) { + return createGroup(p, p2) + }, p1.startTagOpenDeriv(node)); + if(p1.nullable) { + return createChoice(x, p2.startTagOpenDeriv(node)) + } + return x + }, attDeriv:function(context, attribute) { + return createChoice(createGroup(p1.attDeriv(context, attribute), p2), createGroup(p1, p2.attDeriv(context, attribute))) + }, startTagCloseDeriv:memoize0arg(function() { + return createGroup(p1.startTagCloseDeriv(), p2.startTagCloseDeriv()) + })} + }); + createAfter = memoize2arg("after", function(p1, p2) { + if(p1 === notAllowed || p2 === notAllowed) { + return notAllowed + } + }, function(p1, p2) { + return{type:"after", p1:p1, p2:p2, nullable:false, textDeriv:function(context, text) { + return createAfter(p1.textDeriv(context, text), p2) + }, startTagOpenDeriv:memoizeNode(function(node) { + return applyAfter(function(p) { + return createAfter(p, p2) + }, p1.startTagOpenDeriv(node)) + }), attDeriv:function(context, attribute) { + return createAfter(p1.attDeriv(context, attribute), p2) + }, startTagCloseDeriv:memoize0arg(function() { + return createAfter(p1.startTagCloseDeriv(), p2) + }), endTagDeriv:memoize0arg(function() { + return p1.nullable ? p2 : notAllowed + })} + }); + createOneOrMore = memoize1arg("oneormore", function(p) { + if(p === notAllowed) { + return notAllowed + } + return{type:"oneOrMore", p:p, nullable:p.nullable, textDeriv:function(context, text) { + return createGroup(p.textDeriv(context, text), createChoice(this, empty)) + }, startTagOpenDeriv:function(node) { + var oneOrMore = this; + return applyAfter(function(pf) { + return createGroup(pf, createChoice(oneOrMore, empty)) + }, p.startTagOpenDeriv(node)) + }, attDeriv:function(context, attribute) { + var oneOrMore = this; + return createGroup(p.attDeriv(context, attribute), createChoice(oneOrMore, empty)) + }, startTagCloseDeriv:memoize0arg(function() { + return createOneOrMore(p.startTagCloseDeriv()) + })} + }); + function createElement(nc, p) { + return{type:"element", nc:nc, nullable:false, textDeriv:function() { + return notAllowed + }, startTagOpenDeriv:function(node) { + if(nc.contains(node)) { + return createAfter(p, empty) + } + return notAllowed + }, attDeriv:function(context, attribute) { + return notAllowed + }, startTagCloseDeriv:function() { + return this + }} + } + function valueMatch(context, pattern, text) { + return pattern.nullable && /^\s+$/.test(text) || pattern.textDeriv(context, text).nullable + } + createAttribute = memoize2arg("attribute", undefined, function(nc, p) { + return{type:"attribute", nullable:false, nc:nc, p:p, attDeriv:function(context, attribute) { + if(nc.contains(attribute) && valueMatch(context, p, attribute.nodeValue)) { + return empty + } + return notAllowed + }, startTagCloseDeriv:function() { + return notAllowed + }} + }); + function createList() { + return{type:"list", nullable:false, hash:"list", textDeriv:function(context, text) { + return empty + }} + } + createValue = memoize1arg("value", function(value) { + return{type:"value", nullable:false, value:value, textDeriv:function(context, text) { + return text === value ? empty : notAllowed + }, attDeriv:function() { + return notAllowed + }, startTagCloseDeriv:function() { + return this + }} + }); + createData = memoize1arg("data", function(type) { + return{type:"data", nullable:false, dataType:type, textDeriv:function() { + return empty + }, attDeriv:function() { + return notAllowed + }, startTagCloseDeriv:function() { + return this + }} + }); + function createDataExcept() { + return{type:"dataExcept", nullable:false, hash:"dataExcept"} + } + applyAfter = function applyAfter(f, p) { + var result; + if(p.type === "after") { + result = createAfter(p.p1, f(p.p2)) + }else { + if(p.type === "choice") { + result = createChoice(applyAfter(f, p.p1), applyAfter(f, p.p2)) + }else { + result = p + } + } + return result + }; + function attsDeriv(context, pattern, attributes, position) { + if(pattern === notAllowed) { + return notAllowed + } + if(position >= attributes.length) { + return pattern + } + if(position === 0) { + position = 0 + } + var a = attributes.item(position); + while(a.namespaceURI === xmlnsns) { + position += 1; + if(position >= attributes.length) { + return pattern + } + a = attributes.item(position) + } + a = attsDeriv(context, pattern.attDeriv(context, attributes.item(position)), attributes, position + 1); + return a + } + function childrenDeriv(context, pattern, walker) { + var element = walker.currentNode, childNode = walker.firstChild(), numberOfTextNodes = 0, childNodes = [], i, p; + while(childNode) { + if(childNode.nodeType === 1) { + childNodes.push(childNode) + }else { + if(childNode.nodeType === 3 && !/^\s*$/.test(childNode.nodeValue)) { + childNodes.push(childNode.nodeValue); + numberOfTextNodes += 1 + } + } + childNode = walker.nextSibling() + } + if(childNodes.length === 0) { + childNodes = [""] + } + p = pattern; + for(i = 0;p !== notAllowed && i < childNodes.length;i += 1) { + childNode = childNodes[i]; + if(typeof childNode === "string") { + if(/^\s*$/.test(childNode)) { + p = createChoice(p, p.textDeriv(context, childNode)) + }else { + p = p.textDeriv(context, childNode) + } + }else { + walker.currentNode = childNode; + p = childDeriv(context, p, walker) + } + } + walker.currentNode = element; + return p + } + childDeriv = function childDeriv(context, pattern, walker) { + var childNode = walker.currentNode, p; + p = pattern.startTagOpenDeriv(childNode); + p = attsDeriv(context, p, childNode.attributes, 0); + p = p.startTagCloseDeriv(); + p = childrenDeriv(context, p, walker); + p = p.endTagDeriv(); + return p + }; + function addNames(name, ns, pattern) { + if(pattern.e[0].a) { + name.push(pattern.e[0].text); + ns.push(pattern.e[0].a.ns) + }else { + addNames(name, ns, pattern.e[0]) + } + if(pattern.e[1].a) { + name.push(pattern.e[1].text); + ns.push(pattern.e[1].a.ns) + }else { + addNames(name, ns, pattern.e[1]) + } + } + createNameClass = function createNameClass(pattern) { + var name, ns, hash, i, result; + if(pattern.name === "name") { + name = pattern.text; + ns = pattern.a.ns; + result = {name:name, ns:ns, hash:"{" + ns + "}" + name, contains:function(node) { + return node.namespaceURI === ns && node.localName === name + }} + }else { + if(pattern.name === "choice") { + name = []; + ns = []; + addNames(name, ns, pattern); + hash = ""; + for(i = 0;i < name.length;i += 1) { + hash += "{" + ns[i] + "}" + name[i] + "," + } + result = {hash:hash, contains:function(node) { + var i; + for(i = 0;i < name.length;i += 1) { + if(name[i] === node.localName && ns[i] === node.namespaceURI) { + return true + } + } + return false + }} + }else { + result = {hash:"anyName", contains:function() { + return true + }} + } + } + return result + }; + function resolveElement(pattern, elements) { + var element, p, i, hash; + hash = "element" + pattern.id.toString(); + p = elements[pattern.id] = {hash:hash}; + element = createElement(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements)); + for(i in element) { + if(element.hasOwnProperty(i)) { + p[i] = element[i] + } + } + return p + } + makePattern = function makePattern(pattern, elements) { + var p, i; + if(pattern.name === "elementref") { + p = pattern.id || 0; + pattern = elements[p]; + if(pattern.name !== undefined) { + return resolveElement(pattern, elements) + } + return pattern + } + switch(pattern.name) { + case "empty": + return empty; + case "notAllowed": + return notAllowed; + case "text": + return text; + case "choice": + return createChoice(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements)); + case "interleave": + p = makePattern(pattern.e[0], elements); + for(i = 1;i < pattern.e.length;i += 1) { + p = createInterleave(p, makePattern(pattern.e[i], elements)) + } + return p; + case "group": + return createGroup(makePattern(pattern.e[0], elements), makePattern(pattern.e[1], elements)); + case "oneOrMore": + return createOneOrMore(makePattern(pattern.e[0], elements)); + case "attribute": + return createAttribute(createNameClass(pattern.e[0]), makePattern(pattern.e[1], elements)); + case "value": + return createValue(pattern.text); + case "data": + p = pattern.a && pattern.a.type; + if(p === undefined) { + p = "" + } + return createData(p); + case "list": + return createList() + } + throw"No support for " + pattern.name; + }; + this.makePattern = function(pattern, elements) { + var copy = {}, i; + for(i in elements) { + if(elements.hasOwnProperty(i)) { + copy[i] = elements[i] + } + } + i = makePattern(pattern, copy); + return i + }; + this.validate = function validate(walker, callback) { + var errors; + walker.currentNode = walker.root; + errors = childDeriv(null, rootPattern, walker); + if(!errors.nullable) { + runtime.log("Error in Relax NG validation: " + errors); + callback(["Error in Relax NG validation: " + errors]) + }else { + callback(null) + } + }; + this.init = function init(rootPattern1) { + rootPattern = rootPattern1 + } +}; +runtime.loadClass("xmldom.RelaxNGParser"); +xmldom.RelaxNG2 = function RelaxNG2() { + var start, validateNonEmptyPattern, nsmap, depth = 0, p = " "; + function RelaxNGParseError(error, context) { + this.message = function() { + if(context) { + error += context.nodeType === 1 ? " Element " : " Node "; + error += context.nodeName; + if(context.nodeValue) { + error += " with value '" + context.nodeValue + "'" + } + error += "." + } + return error + } + } + function validateOneOrMore(elementdef, walker, element) { + var node, i = 0, err; + do { + node = walker.currentNode; + err = validateNonEmptyPattern(elementdef.e[0], walker, element); + i += 1 + }while(!err && node !== walker.currentNode); + if(i > 1) { + walker.currentNode = node; + return null + } + return err + } + function qName(node) { + return nsmap[node.namespaceURI] + ":" + node.localName + } + function isWhitespace(node) { + return node && node.nodeType === 3 && /^\s+$/.test(node.nodeValue) + } + function validatePattern(elementdef, walker, element, data) { + if(elementdef.name === "empty") { + return null + } + return validateNonEmptyPattern(elementdef, walker, element, data) + } + function validateAttribute(elementdef, walker, element) { + if(elementdef.e.length !== 2) { + throw"Attribute with wrong # of elements: " + elementdef.e.length; + } + var att, a, l = elementdef.localnames.length, i; + for(i = 0;i < l;i += 1) { + a = element.getAttributeNS(elementdef.namespaces[i], elementdef.localnames[i]); + if(a === "" && !element.hasAttributeNS(elementdef.namespaces[i], elementdef.localnames[i])) { + a = undefined + } + if(att !== undefined && a !== undefined) { + return[new RelaxNGParseError("Attribute defined too often.", element)] + } + att = a + } + if(att === undefined) { + return[new RelaxNGParseError("Attribute not found: " + elementdef.names, element)] + } + return validatePattern(elementdef.e[1], walker, element, att) + } + function validateTop(elementdef, walker, element) { + return validatePattern(elementdef, walker, element) + } + function validateElement(elementdef, walker, element) { + if(elementdef.e.length !== 2) { + throw"Element with wrong # of elements: " + elementdef.e.length; + } + depth += 1; + var node = walker.currentNode, type = node ? node.nodeType : 0, error = null; + while(type > 1) { + if(type !== 8 && (type !== 3 || !/^\s+$/.test(walker.currentNode.nodeValue))) { + depth -= 1; + return[new RelaxNGParseError("Not allowed node of type " + type + ".")] + } + node = walker.nextSibling(); + type = node ? node.nodeType : 0 + } + if(!node) { + depth -= 1; + return[new RelaxNGParseError("Missing element " + elementdef.names)] + } + if(elementdef.names && elementdef.names.indexOf(qName(node)) === -1) { + depth -= 1; + return[new RelaxNGParseError("Found " + node.nodeName + " instead of " + elementdef.names + ".", node)] + } + if(walker.firstChild()) { + error = validateTop(elementdef.e[1], walker, node); + while(walker.nextSibling()) { + type = walker.currentNode.nodeType; + if(!isWhitespace(walker.currentNode) && type !== 8) { + depth -= 1; + return[new RelaxNGParseError("Spurious content.", walker.currentNode)] + } + } + if(walker.parentNode() !== node) { + depth -= 1; + return[new RelaxNGParseError("Implementation error.")] + } + }else { + error = validateTop(elementdef.e[1], walker, node) + } + depth -= 1; + node = walker.nextSibling(); + return error + } + function validateChoice(elementdef, walker, element, data) { + if(elementdef.e.length !== 2) { + throw"Choice with wrong # of options: " + elementdef.e.length; + } + var node = walker.currentNode, err; + if(elementdef.e[0].name === "empty") { + err = validateNonEmptyPattern(elementdef.e[1], walker, element, data); + if(err) { + walker.currentNode = node + } + return null + } + err = validatePattern(elementdef.e[0], walker, element, data); + if(err) { + walker.currentNode = node; + err = validateNonEmptyPattern(elementdef.e[1], walker, element, data) + } + return err + } + function validateInterleave(elementdef, walker, element) { + var l = elementdef.e.length, n = [l], err, i, todo = l, donethisround, node, subnode, e; + while(todo > 0) { + donethisround = 0; + node = walker.currentNode; + for(i = 0;i < l;i += 1) { + subnode = walker.currentNode; + if(n[i] !== true && n[i] !== subnode) { + e = elementdef.e[i]; + err = validateNonEmptyPattern(e, walker, element); + if(err) { + walker.currentNode = subnode; + if(n[i] === undefined) { + n[i] = false + } + }else { + if(subnode === walker.currentNode || e.name === "oneOrMore" || e.name === "choice" && (e.e[0].name === "oneOrMore" || e.e[1].name === "oneOrMore")) { + donethisround += 1; + n[i] = subnode + }else { + donethisround += 1; + n[i] = true + } + } + } + } + if(node === walker.currentNode && donethisround === todo) { + return null + } + if(donethisround === 0) { + for(i = 0;i < l;i += 1) { + if(n[i] === false) { + return[new RelaxNGParseError("Interleave does not match.", element)] + } + } + return null + } + todo = 0; + for(i = 0;i < l;i += 1) { + if(n[i] !== true) { + todo += 1 + } + } + } + return null + } + function validateGroup(elementdef, walker, element) { + if(elementdef.e.length !== 2) { + throw"Group with wrong # of members: " + elementdef.e.length; + } + return validateNonEmptyPattern(elementdef.e[0], walker, element) || validateNonEmptyPattern(elementdef.e[1], walker, element) + } + function validateText(elementdef, walker, element) { + var node = walker.currentNode, type = node ? node.nodeType : 0, error = null; + while(node !== element && type !== 3) { + if(type === 1) { + return[new RelaxNGParseError("Element not allowed here.", node)] + } + node = walker.nextSibling(); + type = node ? node.nodeType : 0 + } + walker.nextSibling(); + return null + } + validateNonEmptyPattern = function validateNonEmptyPattern(elementdef, walker, element, data) { + var name = elementdef.name, err = null; + if(name === "text") { + err = validateText(elementdef, walker, element) + }else { + if(name === "data") { + err = null + }else { + if(name === "value") { + if(data !== elementdef.text) { + err = [new RelaxNGParseError("Wrong value, should be '" + elementdef.text + "', not '" + data + "'", element)] + } + }else { + if(name === "list") { + err = null + }else { + if(name === "attribute") { + err = validateAttribute(elementdef, walker, element) + }else { + if(name === "element") { + err = validateElement(elementdef, walker, element) + }else { + if(name === "oneOrMore") { + err = validateOneOrMore(elementdef, walker, element) + }else { + if(name === "choice") { + err = validateChoice(elementdef, walker, element, data) + }else { + if(name === "group") { + err = validateGroup(elementdef, walker, element) + }else { + if(name === "interleave") { + err = validateInterleave(elementdef, walker, element) + }else { + throw name + " not allowed in nonEmptyPattern."; + } + } + } + } + } + } + } + } + } + } + return err + }; + this.validate = function validate(walker, callback) { + walker.currentNode = walker.root; + var errors = validatePattern(start.e[0], walker, walker.root); + callback(errors) + }; + this.init = function init(start1, nsmap1) { + start = start1; + nsmap = nsmap1 + } +}; +xmldom.OperationalTransformInterface = function() { +}; +xmldom.OperationalTransformInterface.prototype.retain = function(amount) { +}; +xmldom.OperationalTransformInterface.prototype.insertCharacters = function(chars) { +}; +xmldom.OperationalTransformInterface.prototype.insertElementStart = function(tagname, attributes) { +}; +xmldom.OperationalTransformInterface.prototype.insertElementEnd = function() { +}; +xmldom.OperationalTransformInterface.prototype.deleteCharacters = function(amount) { +}; +xmldom.OperationalTransformInterface.prototype.deleteElementStart = function() { +}; +xmldom.OperationalTransformInterface.prototype.deleteElementEnd = function() { +}; +xmldom.OperationalTransformInterface.prototype.replaceAttributes = function(atts) { +}; +xmldom.OperationalTransformInterface.prototype.updateAttributes = function(atts) { +}; +xmldom.OperationalTransformDOM = function OperationalTransformDOM(root, serializer) { + var pos, length; + function retain(amount) { + } + function insertCharacters(chars) { + } + function insertElementStart(tagname, attributes) { + } + function insertElementEnd() { + } + function deleteCharacters(amount) { + } + function deleteElementStart() { + } + function deleteElementEnd() { + } + function replaceAttributes(atts) { + } + function updateAttributes(atts) { + } + function atEnd() { + return pos === length + } + this.retain = retain; + this.insertCharacters = insertCharacters; + this.insertElementStart = insertElementStart; + this.insertElementEnd = insertElementEnd; + this.deleteCharacters = deleteCharacters; + this.deleteElementStart = deleteElementStart; + this.deleteElementEnd = deleteElementEnd; + this.replaceAttributes = replaceAttributes; + this.updateAttributes = updateAttributes; + this.atEnd = atEnd +}; +xmldom.XPath = function() { + var createXPathPathIterator, parsePredicates; + function isSmallestPositive(a, b, c) { + return a !== -1 && (a < b || b === -1) && (a < c || c === -1) + } + function parseXPathStep(xpath, pos, end, steps) { + var location = "", predicates = [], value, brapos = xpath.indexOf("[", pos), slapos = xpath.indexOf("/", pos), eqpos = xpath.indexOf("=", pos), depth = 0, start = 0; + if(isSmallestPositive(slapos, brapos, eqpos)) { + location = xpath.substring(pos, slapos); + pos = slapos + 1 + }else { + if(isSmallestPositive(brapos, slapos, eqpos)) { + location = xpath.substring(pos, brapos); + pos = parsePredicates(xpath, brapos, predicates) + }else { + if(isSmallestPositive(eqpos, slapos, brapos)) { + location = xpath.substring(pos, eqpos); + pos = eqpos + }else { + location = xpath.substring(pos, end); + pos = end + } + } + } + steps.push({location:location, predicates:predicates}); + return pos + } + function parseXPath(xpath) { + var steps = [], p = 0, end = xpath.length, value; + while(p < end) { + p = parseXPathStep(xpath, p, end, steps); + if(p < end && xpath[p] === "=") { + value = xpath.substring(p + 1, end); + if(value.length > 2 && (value[0] === "'" || value[0] === '"')) { + value = value.slice(1, value.length - 1) + }else { + try { + value = parseInt(value, 10) + }catch(e) { + } + } + p = end + } + } + return{steps:steps, value:value} + } + parsePredicates = function parsePredicates(xpath, start, predicates) { + var pos = start, l = xpath.length, selector, depth = 0; + while(pos < l) { + if(xpath[pos] === "]") { + depth -= 1; + if(depth <= 0) { + predicates.push(parseXPath(xpath.substring(start, pos))) + } + }else { + if(xpath[pos] === "[") { + if(depth <= 0) { + start = pos + 1 + } + depth += 1 + } + } + pos += 1 + } + return pos + }; + function XPathIterator() { + } + XPathIterator.prototype.next = function() { + }; + XPathIterator.prototype.reset = function() { + }; + function NodeIterator() { + var node, done = false; + this.setNode = function setNode(n) { + node = n + }; + this.reset = function() { + done = false + }; + this.next = function next() { + var val = done ? null : node; + done = true; + return val + } + } + function AttributeIterator(it, namespace, localName) { + this.reset = function reset() { + it.reset() + }; + this.next = function next() { + var node = it.next(), attr; + while(node) { + node = node.getAttributeNodeNS(namespace, localName); + if(node) { + return node + } + node = it.next() + } + return node + } + } + function AllChildElementIterator(it, recurse) { + var root = it.next(), node = null; + this.reset = function reset() { + it.reset(); + root = it.next(); + node = null + }; + this.next = function next() { + while(root) { + if(node) { + if(recurse && node.firstChild) { + node = node.firstChild + }else { + while(!node.nextSibling && node !== root) { + node = node.parentNode + } + if(node === root) { + root = it.next() + }else { + node = node.nextSibling + } + } + }else { + do { + node = root.firstChild; + if(!node) { + root = it.next() + } + }while(root && !node) + } + if(node && node.nodeType === 1) { + return node + } + } + return null + } + } + function ConditionIterator(it, condition) { + this.reset = function reset() { + it.reset() + }; + this.next = function next() { + var n = it.next(); + while(n && !condition(n)) { + n = it.next() + } + return n + } + } + function createNodenameFilter(it, name, namespaceResolver) { + var s = name.split(":", 2), namespace = namespaceResolver(s[0]), localName = s[1]; + return new ConditionIterator(it, function(node) { + return node.localName === localName && node.namespaceURI === namespace + }) + } + function createPredicateFilteredIterator(it, p, namespaceResolver) { + var nit = new NodeIterator, pit = createXPathPathIterator(nit, p, namespaceResolver), value = p.value; + if(value === undefined) { + return new ConditionIterator(it, function(node) { + nit.setNode(node); + pit.reset(); + return pit.next() + }) + } + return new ConditionIterator(it, function(node) { + nit.setNode(node); + pit.reset(); + var n = pit.next(); + return n && n.nodeValue === value + }) + } + createXPathPathIterator = function createXPathPathIterator(it, xpath, namespaceResolver) { + var i, j, step, location, namespace, localName, prefix, p; + for(i = 0;i < xpath.steps.length;i += 1) { + step = xpath.steps[i]; + location = step.location; + if(location === "") { + it = new AllChildElementIterator(it, false) + }else { + if(location[0] === "@") { + p = location.slice(1).split(":", 2); + it = new AttributeIterator(it, namespaceResolver(p[0]), p[1]) + }else { + if(location !== ".") { + it = new AllChildElementIterator(it, false); + if(location.indexOf(":") !== -1) { + it = createNodenameFilter(it, location, namespaceResolver) + } + } + } + } + for(j = 0;j < step.predicates.length;j += 1) { + p = step.predicates[j]; + it = createPredicateFilteredIterator(it, p, namespaceResolver) + } + } + return it + }; + function fallback(node, xpath, namespaceResolver) { + var it = new NodeIterator, i, nodelist, parsedXPath, pos; + it.setNode(node); + parsedXPath = parseXPath(xpath); + it = createXPathPathIterator(it, parsedXPath, namespaceResolver); + nodelist = []; + i = it.next(); + while(i) { + nodelist.push(i); + i = it.next() + } + return nodelist + } + function getODFElementsWithXPath(node, xpath, namespaceResolver) { + var doc = node.ownerDocument, nodes, elements = [], n = null; + if(!doc || !doc.evaluate || !n) { + elements = fallback(node, xpath, namespaceResolver) + }else { + nodes = doc.evaluate(xpath, node, namespaceResolver, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); + n = nodes.iterateNext(); + while(n !== null) { + if(n.nodeType === 1) { + elements.push(n) + } + n = nodes.iterateNext() + } + } + return elements + } + xmldom.XPath = function XPath() { + this.getODFElementsWithXPath = getODFElementsWithXPath + }; + return xmldom.XPath +}(); +odf.StyleInfo = function StyleInfo() { + var chartns = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0", dbns = "urn:oasis:names:tc:opendocument:xmlns:database:1.0", dr3dns = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", fons = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", formns = "urn:oasis:names:tc:opendocument:xmlns:form:1.0", numberns = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", + presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0", svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", elementstyles = {"text":[{ens:stylens, en:"tab-stop", ans:stylens, a:"leader-text-style"}, {ens:stylens, en:"drop-cap", ans:stylens, a:"style-name"}, {ens:textns, en:"notes-configuration", + ans:textns, a:"citation-body-style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"citation-style-name"}, {ens:textns, en:"a", ans:textns, a:"style-name"}, {ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"linenumbering-configuration", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-number", ans:textns, a:"style-name"}, {ens:textns, en:"ruby-text", ans:textns, a:"style-name"}, {ens:textns, en:"span", ans:textns, a:"style-name"}, {ens:textns, + en:"a", ans:textns, a:"visited-style-name"}, {ens:stylens, en:"text-properties", ans:stylens, a:"text-line-through-text-style"}, {ens:textns, en:"alphabetical-index-source", ans:textns, a:"main-entry-style-name"}, {ens:textns, en:"index-entry-bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-chapter", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-end", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-link-start", ans:textns, a:"style-name"}, {ens:textns, + en:"index-entry-page-number", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-span", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-tab-stop", ans:textns, a:"style-name"}, {ens:textns, en:"index-entry-text", ans:textns, a:"style-name"}, {ens:textns, en:"index-title-template", ans:textns, a:"style-name"}, {ens:textns, en:"list-level-style-bullet", ans:textns, a:"style-name"}, {ens:textns, en:"outline-level-style", ans:textns, a:"style-name"}], "paragraph":[{ens:drawns, en:"caption", + ans:drawns, a:"text-style-name"}, {ens:drawns, en:"circle", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"control", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"custom-shape", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"ellipse", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"line", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"measure", ans:drawns, + a:"text-style-name"}, {ens:drawns, en:"path", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"polygon", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"polyline", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"rect", ans:drawns, a:"text-style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"text-style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"text-style-name"}, {ens:formns, en:"column", ans:formns, a:"text-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"next-style-name"}, + {ens:tablens, en:"body", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"even-rows", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, + en:"odd-columns", ans:tablens, a:"paragraph-style-name"}, {ens:tablens, en:"odd-rows", ans:tablens, a:"paragraph-style-name"}, {ens:textns, en:"notes-configuration", ans:textns, a:"default-style-name"}, {ens:textns, en:"alphabetical-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"h", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, + en:"index-source-style", ans:textns, a:"style-name"}, {ens:textns, en:"object-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"p", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"table-index-entry-template", ans:textns, a:"style-name"}, {ens:textns, en:"user-index-entry-template", ans:textns, a:"style-name"}, {ens:stylens, en:"page-layout-properties", + ans:stylens, a:"register-truth-ref-style-name"}], "chart":[{ens:chartns, en:"axis", ans:chartns, a:"style-name"}, {ens:chartns, en:"chart", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-label", ans:chartns, a:"style-name"}, {ens:chartns, en:"data-point", ans:chartns, a:"style-name"}, {ens:chartns, en:"equation", ans:chartns, a:"style-name"}, {ens:chartns, en:"error-indicator", ans:chartns, a:"style-name"}, {ens:chartns, en:"floor", ans:chartns, a:"style-name"}, {ens:chartns, en:"footer", + ans:chartns, a:"style-name"}, {ens:chartns, en:"grid", ans:chartns, a:"style-name"}, {ens:chartns, en:"legend", ans:chartns, a:"style-name"}, {ens:chartns, en:"mean-value", ans:chartns, a:"style-name"}, {ens:chartns, en:"plot-area", ans:chartns, a:"style-name"}, {ens:chartns, en:"regression-curve", ans:chartns, a:"style-name"}, {ens:chartns, en:"series", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-gain-marker", ans:chartns, a:"style-name"}, {ens:chartns, en:"stock-loss-marker", ans:chartns, + a:"style-name"}, {ens:chartns, en:"stock-range-line", ans:chartns, a:"style-name"}, {ens:chartns, en:"subtitle", ans:chartns, a:"style-name"}, {ens:chartns, en:"title", ans:chartns, a:"style-name"}, {ens:chartns, en:"wall", ans:chartns, a:"style-name"}], "section":[{ens:textns, en:"alphabetical-index", ans:textns, a:"style-name"}, {ens:textns, en:"bibliography", ans:textns, a:"style-name"}, {ens:textns, en:"illustration-index", ans:textns, a:"style-name"}, {ens:textns, en:"index-title", ans:textns, + a:"style-name"}, {ens:textns, en:"object-index", ans:textns, a:"style-name"}, {ens:textns, en:"section", ans:textns, a:"style-name"}, {ens:textns, en:"table-of-content", ans:textns, a:"style-name"}, {ens:textns, en:"table-index", ans:textns, a:"style-name"}, {ens:textns, en:"user-index", ans:textns, a:"style-name"}], "ruby":[{ens:textns, en:"ruby", ans:textns, a:"style-name"}], "table":[{ens:dbns, en:"query", ans:dbns, a:"style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"style-name"}, + {ens:tablens, en:"background", ans:tablens, a:"style-name"}, {ens:tablens, en:"table", ans:tablens, a:"style-name"}], "table-column":[{ens:dbns, en:"column", ans:dbns, a:"style-name"}, {ens:tablens, en:"table-column", ans:tablens, a:"style-name"}], "table-row":[{ens:dbns, en:"query", ans:dbns, a:"default-row-style-name"}, {ens:dbns, en:"table-representation", ans:dbns, a:"default-row-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"style-name"}], "table-cell":[{ens:dbns, en:"column", + ans:dbns, a:"default-cell-style-name"}, {ens:tablens, en:"table-column", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"table-row", ans:tablens, a:"default-cell-style-name"}, {ens:tablens, en:"body", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"covered-table-cell", ans:tablens, a:"style-name"}, {ens:tablens, en:"even-columns", ans:tablens, a:"style-name"}, + {ens:tablens, en:"even-rows", ans:tablens, a:"style-name"}, {ens:tablens, en:"first-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"first-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-column", ans:tablens, a:"style-name"}, {ens:tablens, en:"last-row", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-columns", ans:tablens, a:"style-name"}, {ens:tablens, en:"odd-rows", ans:tablens, a:"style-name"}, {ens:tablens, en:"table-cell", ans:tablens, a:"style-name"}], "graphic":[{ens:dr3dns, + en:"cube", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"extrude", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:drawns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:drawns, a:"style-name"}, {ens:drawns, en:"caption", ans:drawns, a:"style-name"}, {ens:drawns, en:"circle", ans:drawns, a:"style-name"}, {ens:drawns, en:"connector", ans:drawns, a:"style-name"}, {ens:drawns, en:"control", ans:drawns, a:"style-name"}, {ens:drawns, en:"custom-shape", + ans:drawns, a:"style-name"}, {ens:drawns, en:"ellipse", ans:drawns, a:"style-name"}, {ens:drawns, en:"frame", ans:drawns, a:"style-name"}, {ens:drawns, en:"g", ans:drawns, a:"style-name"}, {ens:drawns, en:"line", ans:drawns, a:"style-name"}, {ens:drawns, en:"measure", ans:drawns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:drawns, a:"style-name"}, {ens:drawns, en:"path", ans:drawns, a:"style-name"}, {ens:drawns, en:"polygon", ans:drawns, a:"style-name"}, {ens:drawns, en:"polyline", ans:drawns, + a:"style-name"}, {ens:drawns, en:"rect", ans:drawns, a:"style-name"}, {ens:drawns, en:"regular-polygon", ans:drawns, a:"style-name"}, {ens:officens, en:"annotation", ans:drawns, a:"style-name"}], "presentation":[{ens:dr3dns, en:"cube", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"extrude", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"rotate", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"scene", ans:presentationns, a:"style-name"}, {ens:dr3dns, en:"sphere", ans:presentationns, + a:"style-name"}, {ens:drawns, en:"caption", ans:presentationns, a:"style-name"}, {ens:drawns, en:"circle", ans:presentationns, a:"style-name"}, {ens:drawns, en:"connector", ans:presentationns, a:"style-name"}, {ens:drawns, en:"control", ans:presentationns, a:"style-name"}, {ens:drawns, en:"custom-shape", ans:presentationns, a:"style-name"}, {ens:drawns, en:"ellipse", ans:presentationns, a:"style-name"}, {ens:drawns, en:"frame", ans:presentationns, a:"style-name"}, {ens:drawns, en:"g", ans:presentationns, + a:"style-name"}, {ens:drawns, en:"line", ans:presentationns, a:"style-name"}, {ens:drawns, en:"measure", ans:presentationns, a:"style-name"}, {ens:drawns, en:"page-thumbnail", ans:presentationns, a:"style-name"}, {ens:drawns, en:"path", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polygon", ans:presentationns, a:"style-name"}, {ens:drawns, en:"polyline", ans:presentationns, a:"style-name"}, {ens:drawns, en:"rect", ans:presentationns, a:"style-name"}, {ens:drawns, en:"regular-polygon", + ans:presentationns, a:"style-name"}, {ens:officens, en:"annotation", ans:presentationns, a:"style-name"}], "drawing-page":[{ens:drawns, en:"page", ans:drawns, a:"style-name"}, {ens:presentationns, en:"notes", ans:drawns, a:"style-name"}, {ens:stylens, en:"handout-master", ans:drawns, a:"style-name"}, {ens:stylens, en:"master-page", ans:drawns, a:"style-name"}], "list-style":[{ens:textns, en:"list", ans:textns, a:"style-name"}, {ens:textns, en:"numbered-paragraph", ans:textns, a:"style-name"}, {ens:textns, + en:"list-item", ans:textns, a:"style-override"}, {ens:stylens, en:"style", ans:stylens, a:"list-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"data-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"percentage-data-style-name"}, {ens:presentationns, en:"date-time-decl", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"database-display", ans:stylens, + a:"data-style-name"}, {ens:textns, en:"date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"editing-duration", ans:stylens, a:"data-style-name"}, {ens:textns, en:"expression", ans:stylens, a:"data-style-name"}, {ens:textns, en:"meta-field", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-date", ans:stylens, a:"data-style-name"}, {ens:textns, + en:"print-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"table-formula", ans:stylens, a:"data-style-name"}, {ens:textns, en:"time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-defined", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-input", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-input", ans:stylens, + a:"data-style-name"}, {ens:textns, en:"variable-set", ans:stylens, a:"data-style-name"}], "data":[{ens:stylens, en:"style", ans:stylens, a:"data-style-name"}, {ens:stylens, en:"style", ans:stylens, a:"percentage-data-style-name"}, {ens:presentationns, en:"date-time-decl", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"creation-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"database-display", ans:stylens, a:"data-style-name"}, + {ens:textns, en:"date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"editing-duration", ans:stylens, a:"data-style-name"}, {ens:textns, en:"expression", ans:stylens, a:"data-style-name"}, {ens:textns, en:"meta-field", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"modification-time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-date", ans:stylens, a:"data-style-name"}, {ens:textns, en:"print-time", + ans:stylens, a:"data-style-name"}, {ens:textns, en:"table-formula", ans:stylens, a:"data-style-name"}, {ens:textns, en:"time", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-defined", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"user-field-input", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-get", ans:stylens, a:"data-style-name"}, {ens:textns, en:"variable-input", ans:stylens, a:"data-style-name"}, + {ens:textns, en:"variable-set", ans:stylens, a:"data-style-name"}], "page-layout":[{ens:presentationns, en:"notes", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"handout-master", ans:stylens, a:"page-layout-name"}, {ens:stylens, en:"master-page", ans:stylens, a:"page-layout-name"}]}, elements; + function canElementHaveStyle(family, element) { + var elname = elements[element.localName], elns = elname && elname[element.namespaceURI], length = elns ? elns.length : 0, i; + return elns && elns.length > 0 + } + function getStyleRef(family, element) { + var elname = elements[element.localName], elns = elname && elname[element.namespaceURI], length = elns ? elns.length : 0, i, attr; + for(i = 0;i < length;i += 1) { + attr = element.getAttributeNS(elns[i].ns, elns[i].localname) + } + return null + } + function getUsedStylesForAutomatic(element, keys) { + var elname = elements[element.localName], elns = elname && elname[element.namespaceURI], length = elns ? elns.length : 0, i, attr, group, map, e; + for(i = 0;i < length;i += 1) { + attr = element.getAttributeNS(elns[i].ns, elns[i].localname); + if(attr) { + group = elns[i].keygroup; + map = keys[group]; + if(!map) { + map = keys[group] = {} + } + map[attr] = 1 + } + } + i = element.firstChild; + while(i) { + if(i.nodeType === 1) { + e = i; + getUsedStylesForAutomatic(e, keys) + } + i = i.nextSibling + } + } + function inverse(elementstyles) { + var keyname, i, list, item, l, elements = {}, map, array; + for(keyname in elementstyles) { + if(elementstyles.hasOwnProperty(keyname)) { + list = elementstyles[keyname]; + l = list.length; + for(i = 0;i < l;i += 1) { + item = list[i]; + map = elements[item.en] = elements[item.en] || {}; + array = map[item.ens] = map[item.ens] || []; + array.push({ns:item.ans, localname:item.a, keygroup:keyname}) + } + } + } + return elements + } + this.UsedKeysList = function(element) { + var usedKeys = {}; + this.uses = function(element) { + var localName = element.localName, name = element.getAttributeNS(drawns, "name") || element.getAttributeNS(stylens, "name"), keyName, map; + if(localName === "style") { + keyName = element.getAttributeNS(stylens, "family") + }else { + if(element.namespaceURI === numberns) { + keyName = "data" + }else { + keyName = localName + } + } + map = usedKeys[keyName]; + return map ? map[name] > 0 : false + }; + getUsedStylesForAutomatic(element, usedKeys) + }; + this.canElementHaveStyle = canElementHaveStyle; + elements = inverse(elementstyles) +}; +odf.Style2CSS = function Style2CSS() { + var xlinkns = "http://www.w3.org/1999/xlink", drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", fons = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0", svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", + textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", namespaces = {"draw":drawns, "fo":fons, "office":officens, "presentation":presentationns, "style":stylens, "svg":svgns, "table":tablens, "text":textns, "xlink":xlinkns}, familynamespaceprefixes = {"graphic":"draw", "paragraph":"text", "presentation":"presentation", "ruby":"text", "section":"text", "table":"table", "table-cell":"table", "table-column":"table", "table-row":"table", "text":"text", "list":"text"}, familytagnames = {"graphic":["circle", + "connected", "control", "custom-shape", "ellipse", "frame", "g", "line", "measure", "page", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "paragraph":["alphabetical-index-entry-template", "h", "illustration-index-entry-template", "index-source-style", "object-index-entry-template", "p", "table-index-entry-template", "table-of-content-entry-template", "user-index-entry-template"], "presentation":["caption", "circle", "connector", "control", "custom-shape", "ellipse", + "frame", "g", "line", "measure", "page-thumbnail", "path", "polygon", "polyline", "rect", "regular-polygon"], "ruby":["ruby", "ruby-text"], "section":["alphabetical-index", "bibliography", "illustration-index", "index-title", "object-index", "section", "table-of-content", "table-index", "user-index"], "table":["background", "table"], "table-cell":["body", "covered-table-cell", "even-columns", "even-rows", "first-column", "first-row", "last-column", "last-row", "odd-columns", "odd-rows", "table-cell"], + "table-column":["table-column"], "table-row":["table-row"], "text":["a", "index-entry-chapter", "index-entry-link-end", "index-entry-link-start", "index-entry-page-number", "index-entry-span", "index-entry-tab-stop", "index-entry-text", "index-title-template", "linenumbering-configuration", "list-level-style-number", "list-level-style-bullet", "outline-level-style", "span"], "list":["list-item"]}, textPropertySimpleMapping = [[fons, "color", "color"], [fons, "background-color", "background-color"], + [fons, "font-weight", "font-weight"], [fons, "font-style", "font-style"], [fons, "font-size", "font-size"]], bgImageSimpleMapping = [[stylens, "repeat", "background-repeat"]], paragraphPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "text-align", "text-align"], [fons, "padding-left", "padding-left"], [fons, "padding-right", "padding-right"], [fons, "padding-top", "padding-top"], [fons, "padding-bottom", "padding-bottom"], [fons, "border-left", "border-left"], [fons, + "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"], [fons, "margin-left", "margin-left"], [fons, "margin-right", "margin-right"], [fons, "margin-top", "margin-top"], [fons, "margin-bottom", "margin-bottom"], [fons, "border", "border"]], graphicPropertySimpleMapping = [[drawns, "fill-color", "background-color"], [drawns, "fill", "background"], [fons, "min-height", "min-height"], [drawns, "stroke", "border"], [svgns, "stroke-color", "border-color"]], + tablecellPropertySimpleMapping = [[fons, "background-color", "background-color"], [fons, "border-left", "border-left"], [fons, "border-right", "border-right"], [fons, "border-top", "border-top"], [fons, "border-bottom", "border-bottom"]]; + function namespaceResolver(prefix) { + return namespaces[prefix] || null + } + function getStyleMap(doc, stylesnode) { + var stylemap = {}, node, name, family, map; + if(!stylesnode) { + return stylemap + } + node = stylesnode.firstChild; + while(node) { + if(node.namespaceURI === stylens && node.localName === "style") { + family = node.getAttributeNS(stylens, "family") + }else { + if(node.namespaceURI === textns && node.localName === "list-style") { + family = "list" + } + } + name = family && node.getAttributeNS && node.getAttributeNS(stylens, "name"); + if(name) { + if(!stylemap[family]) { + stylemap[family] = {} + } + stylemap[family][name] = node + } + node = node.nextSibling + } + return stylemap + } + function findStyle(stylestree, name) { + if(!name || !stylestree) { + return null + } + if(stylestree[name]) { + return stylestree[name] + } + var derivedStyles = stylestree.derivedStyles, n, style; + for(n in stylestree) { + if(stylestree.hasOwnProperty(n)) { + style = findStyle(stylestree[n].derivedStyles, name); + if(style) { + return style + } + } + } + return null + } + function addStyleToStyleTree(stylename, stylesmap, stylestree) { + var style = stylesmap[stylename], parentname, parentstyle; + if(!style) { + return + } + parentname = style.getAttributeNS(stylens, "parent-style-name"); + parentstyle = null; + if(parentname) { + parentstyle = findStyle(stylestree, parentname); + if(!parentstyle && stylesmap[parentname]) { + addStyleToStyleTree(parentname, stylesmap, stylestree); + parentstyle = stylesmap[parentname]; + stylesmap[parentname] = null + } + } + if(parentstyle) { + if(!parentstyle.derivedStyles) { + parentstyle.derivedStyles = {} + } + parentstyle.derivedStyles[stylename] = style + }else { + stylestree[stylename] = style + } + } + function addStyleMapToStyleTree(stylesmap, stylestree) { + var name; + for(name in stylesmap) { + if(stylesmap.hasOwnProperty(name)) { + addStyleToStyleTree(name, stylesmap, stylestree); + stylesmap[name] = null + } + } + } + function createSelector(family, name) { + var prefix = familynamespaceprefixes[family], namepart, selector = "", first = true; + if(prefix === null) { + return null + } + namepart = "[" + prefix + '|style-name="' + name + '"]'; + if(prefix === "presentation") { + prefix = "draw"; + namepart = '[presentation|style-name="' + name + '"]' + } + return prefix + "|" + familytagnames[family].join(namepart + "," + prefix + "|") + namepart + } + function getSelectors(family, name, node) { + var selectors = [], n, ss, s; + selectors.push(createSelector(family, name)); + for(n in node.derivedStyles) { + if(node.derivedStyles.hasOwnProperty(n)) { + ss = getSelectors(family, n, node.derivedStyles[n]); + for(s in ss) { + if(ss.hasOwnProperty(s)) { + selectors.push(ss[s]) + } + } + } + } + return selectors + } + function getDirectChild(node, ns, name) { + if(!node) { + return null + } + var c = node.firstChild, e; + while(c) { + if(c.namespaceURI === ns && c.localName === name) { + e = c; + return e + } + c = c.nextSibling + } + return null + } + function applySimpleMapping(props, mapping) { + var rule = "", r, value; + for(r in mapping) { + if(mapping.hasOwnProperty(r)) { + r = mapping[r]; + value = props.getAttributeNS(r[0], r[1]); + if(value) { + rule += r[2] + ":" + value + ";" + } + } + } + return rule + } + function getFontDeclaration(name) { + return'"' + name + '"' + } + function getTextProperties(props) { + var rule = "", value; + rule += applySimpleMapping(props, textPropertySimpleMapping); + value = props.getAttributeNS(stylens, "text-underline-style"); + if(value === "solid") { + rule += "text-decoration: underline;" + } + value = props.getAttributeNS(stylens, "font-name"); + if(value) { + value = getFontDeclaration(value); + if(value) { + rule += "font-family: " + value + ";" + } + } + return rule + } + function getParagraphProperties(props) { + var rule = "", imageProps, url, element; + rule += applySimpleMapping(props, paragraphPropertySimpleMapping); + imageProps = props.getElementsByTagNameNS(stylens, "background-image"); + if(imageProps.length > 0) { + url = imageProps.item(0).getAttributeNS(xlinkns, "href"); + if(url) { + rule += "background-image: url('odfkit:" + url + "');"; + element = imageProps.item(0); + rule += applySimpleMapping(element, bgImageSimpleMapping) + } + } + return rule + } + function getGraphicProperties(props) { + var rule = ""; + rule += applySimpleMapping(props, graphicPropertySimpleMapping); + return rule + } + function getTableCellProperties(props) { + var rule = ""; + rule += applySimpleMapping(props, tablecellPropertySimpleMapping); + return rule + } + function addStyleRule(sheet, family, name, node) { + var selectors = getSelectors(family, name, node), selector = selectors.join(","), rule = "", properties = getDirectChild(node, stylens, "text-properties"); + if(properties) { + rule += getTextProperties(properties) + } + properties = getDirectChild(node, stylens, "paragraph-properties"); + if(properties) { + rule += getParagraphProperties(properties) + } + properties = getDirectChild(node, stylens, "graphic-properties"); + if(properties) { + rule += getGraphicProperties(properties) + } + properties = getDirectChild(node, stylens, "table-cell-properties"); + if(properties) { + rule += getTableCellProperties(properties) + } + if(rule.length === 0) { + return + } + rule = selector + "{" + rule + "}"; + try { + sheet.insertRule(rule, sheet.cssRules.length) + }catch(e) { + throw e; + } + } + function getNumberRule(node) { + var style = node.getAttributeNS(stylens, "num-format"), suffix = node.getAttributeNS(stylens, "num-suffix"), prefix = node.getAttributeNS(stylens, "num-prefix"), rule = "", stylemap = {1:"decimal", "a":"lower-latin", "A":"upper-latin", "i":"lower-roman", "I":"upper-roman"}, content = ""; + content = prefix || ""; + if(stylemap.hasOwnProperty(style)) { + content += " counter(list, " + stylemap[style] + ")" + }else { + if(style) { + content += "'" + style + "';" + }else { + content += " ''" + } + } + if(suffix) { + content += " '" + suffix + "'" + } + rule = "content: " + content + ";"; + return rule + } + function getImageRule(node) { + var rule = "content: none;"; + return rule + } + function getBulletRule(node) { + var rule = "", bulletChar = node.getAttributeNS(textns, "bullet-char"); + return"content: '" + bulletChar + "';" + } + function addListStyleRule(sheet, name, node, itemrule) { + var selector = 'text|list[text|style-name="' + name + '"]', level = node.getAttributeNS(textns, "level"), rule = ""; + level = level && parseInt(level, 10); + while(level > 1) { + selector += " > text|list-item > text|list"; + level -= 1 + } + selector += " > list-item:before"; + rule = itemrule; + rule = selector + "{" + rule + "}"; + try { + sheet.insertRule(rule, sheet.cssRules.length) + }catch(e) { + throw e; + } + } + function addListStyleRules(sheet, name, node) { + var n = node.firstChild, e, itemrule; + while(n) { + if(n.namespaceURI === textns) { + e = n; + if(n.localName === "list-level-style-number") { + itemrule = getNumberRule(e); + addListStyleRule(sheet, name, e, itemrule) + }else { + if(n.localName === "list-level-style-image") { + itemrule = getImageRule(e); + addListStyleRule(sheet, name, e, itemrule) + }else { + if(n.localName === "list-level-style-bullet") { + itemrule = getBulletRule(e); + addListStyleRule(sheet, name, e, itemrule) + } + } + } + } + n = n.nextSibling + } + } + function addRule(sheet, family, name, node) { + if(family === "list") { + addListStyleRules(sheet, name, node) + }else { + addStyleRule(sheet, family, name, node) + } + } + function addRules(sheet, family, name, node) { + addRule(sheet, family, name, node); + var n; + for(n in node.derivedStyles) { + if(node.derivedStyles.hasOwnProperty(n)) { + addRules(sheet, family, n, node.derivedStyles[n]) + } + } + } + this.namespaces = namespaces; + this.namespaceResolver = namespaceResolver; + this.namespaceResolver.lookupNamespaceURI = this.namespaceResolver; + this.style2css = function(stylesheet, styles, autostyles) { + var doc, prefix, styletree, tree, name, rule, family, stylenodes, styleautonodes; + while(stylesheet.cssRules.length) { + stylesheet.deleteRule(stylesheet.cssRules.length - 1) + } + doc = null; + if(styles) { + doc = styles.ownerDocument + } + if(autostyles) { + doc = autostyles.ownerDocument + } + if(!doc) { + return + } + for(prefix in namespaces) { + if(namespaces.hasOwnProperty(prefix)) { + rule = "@namespace " + prefix + " url(" + namespaces[prefix] + ");"; + try { + stylesheet.insertRule(rule, stylesheet.cssRules.length) + }catch(e) { + } + } + } + stylenodes = getStyleMap(doc, styles); + styleautonodes = getStyleMap(doc, autostyles); + styletree = {}; + for(family in familynamespaceprefixes) { + if(familynamespaceprefixes.hasOwnProperty(family)) { + tree = styletree[family] = {}; + addStyleMapToStyleTree(stylenodes[family], tree); + addStyleMapToStyleTree(styleautonodes[family], tree); + for(name in tree) { + if(tree.hasOwnProperty(name)) { + addRules(stylesheet, family, name, tree[name]) + } + } + } + } + } +}; +runtime.loadClass("core.Base64"); +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.Style2CSS"); +odf.FontLoader = function() { + var style2CSS = new odf.Style2CSS, xpath = new xmldom.XPath, base64 = new core.Base64; + function getEmbeddedFontDeclarations(fontFaceDecls) { + var decls = {}, fonts, i, font, name, uris, href; + if(!fontFaceDecls) { + return decls + } + fonts = xpath.getODFElementsWithXPath(fontFaceDecls, "style:font-face[svg:font-face-src]", style2CSS.namespaceResolver); + for(i = 0;i < fonts.length;i += 1) { + font = fonts[i]; + name = font.getAttributeNS(style2CSS.namespaces["style"], "name"); + uris = xpath.getODFElementsWithXPath(font, "svg:font-face-src/svg:font-face-uri", style2CSS.namespaceResolver); + if(uris.length > 0) { + href = uris[0].getAttributeNS(style2CSS.namespaces["xlink"], "href"); + decls[name] = {href:href} + } + } + return decls + } + function addFontToCSS(name, font, fontdata, stylesheet) { + stylesheet = document.styleSheets[0]; + var rule = '@font-face { font-family: "' + name + '"; src: ' + "url(data:application/x-font-ttf;charset=binary;base64," + base64.convertUTF8ArrayToBase64(fontdata) + ') format("truetype"); }'; + try { + stylesheet.insertRule(rule, stylesheet.cssRules.length) + }catch(e) { + runtime.log("Problem inserting rule in CSS: " + rule) + } + } + function loadFontIntoCSS(embeddedFontDeclarations, zip, pos, stylesheet, callback) { + var name, i = 0, n; + for(n in embeddedFontDeclarations) { + if(embeddedFontDeclarations.hasOwnProperty(n)) { + if(i === pos) { + name = n + } + i += 1 + } + } + if(!name) { + return callback() + } + zip.load(embeddedFontDeclarations[name].href, function(err, fontdata) { + if(err) { + runtime.log(err) + }else { + addFontToCSS(name, embeddedFontDeclarations[name], fontdata, stylesheet) + } + return loadFontIntoCSS(embeddedFontDeclarations, zip, pos + 1, stylesheet, callback) + }) + } + function loadFontsIntoCSS(embeddedFontDeclarations, zip, stylesheet) { + loadFontIntoCSS(embeddedFontDeclarations, zip, 0, stylesheet, function() { + }) + } + odf.FontLoader = function FontLoader() { + var self = this; + this.loadFonts = function(fontFaceDecls, zip, stylesheet) { + var embeddedFontDeclarations = getEmbeddedFontDeclarations(fontFaceDecls); + loadFontsIntoCSS(embeddedFontDeclarations, zip, stylesheet) + } + }; + return odf.FontLoader +}(); +runtime.loadClass("core.Base64"); +runtime.loadClass("core.Zip"); +runtime.loadClass("xmldom.LSSerializer"); +runtime.loadClass("odf.StyleInfo"); +runtime.loadClass("odf.Style2CSS"); +runtime.loadClass("odf.FontLoader"); +odf.OdfContainer = function() { + var styleInfo = new odf.StyleInfo, style2CSS = new odf.Style2CSS, namespaces = style2CSS.namespaces, officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", nodeorder = ["meta", "settings", "scripts", "font-face-decls", "styles", "automatic-styles", "master-styles", "body"], base64 = new core.Base64, fontLoader = new odf.FontLoader, partMimetypes = {}; + function getDirectChild(node, ns, name) { + node = node ? node.firstChild : null; + while(node) { + if(node.localName === name && node.namespaceURI === ns) { + return node + } + node = node.nextSibling + } + return null + } + function getNodePosition(child) { + var childpos = 0, i, l = nodeorder.length; + for(i = 0;i < l;i += 1) { + if(child.namespaceURI === officens && child.localName === nodeorder[i]) { + return i + } + } + return-1 + } + function OdfNodeFilter(odfroot, usedStylesElement) { + var automaticStyles = odfroot.automaticStyles, usedKeysList; + if(usedStylesElement) { + usedKeysList = new styleInfo.UsedKeysList(usedStylesElement) + } + this.acceptNode = function(node) { + var styleName, styleFamily, result; + if(node.namespaceURI === "http://www.w3.org/1999/xhtml") { + result = 3 + }else { + if(usedKeysList && node.parentNode === automaticStyles && node.nodeType === 1) { + if(usedKeysList.uses(node)) { + result = 1 + }else { + result = 2 + } + }else { + result = 1 + } + } + return result + } + } + function setChild(node, child) { + if(!child) { + return + } + var childpos = getNodePosition(child), pos, c = node.firstChild; + if(childpos === -1) { + return + } + while(c) { + pos = getNodePosition(c); + if(pos !== -1 && pos > childpos) { + break + } + c = c.nextSibling + } + node.insertBefore(child, c) + } + function ODFElement() { + } + function ODFDocumentElement(odfcontainer) { + this.OdfContainer = odfcontainer + } + ODFDocumentElement.prototype = new ODFElement; + ODFDocumentElement.prototype.constructor = ODFDocumentElement; + ODFDocumentElement.namespaceURI = officens; + ODFDocumentElement.localName = "document"; + function OdfPart(name, container, zip) { + var self = this, privatedata; + this.size = 0; + this.type = null; + this.name = name; + this.container = container; + this.url = null; + this.mimetype = null; + this.document = null; + this.onreadystatechange = null; + this.onchange = null; + this.EMPTY = 0; + this.LOADING = 1; + this.DONE = 2; + this.state = this.EMPTY; + this.load = function() { + var mimetype = partMimetypes[name]; + this.mimetype = mimetype; + zip.loadAsDataURL(name, mimetype, function(err, url) { + self.url = url; + if(self.onchange) { + self.onchange(self) + } + if(self.onstatereadychange) { + self.onstatereadychange(self) + } + }) + }; + this.abort = function() { + } + } + OdfPart.prototype.load = function() { + }; + OdfPart.prototype.getUrl = function() { + if(this.data) { + return"data:;base64," + base64.toBase64(this.data) + } + return null + }; + function OdfPartList(odfcontainer) { + var self = this; + this.length = 0; + this.item = function(index) { + } + } + odf.OdfContainer = function OdfContainer(url, onstatereadychange) { + var self = this, zip = null, contentXmlCompletelyLoaded = false; + this.onstatereadychange = onstatereadychange; + this.onchange = null; + this.state = null; + this.rootElement = null; + this.parts = null; + function removeProcessingInstructions(element) { + var n = element.firstChild, next, e; + while(n) { + next = n.nextSibling; + if(n.nodeType === 1) { + e = n; + removeProcessingInstructions(e) + }else { + if(n.nodeType === 7) { + element.removeChild(n) + } + } + n = next + } + } + function importRootNode(xmldoc) { + var doc = self.rootElement.ownerDocument, node; + if(xmldoc) { + removeProcessingInstructions(xmldoc.documentElement); + try { + node = doc.importNode(xmldoc.documentElement, true) + }catch(e) { + } + } + return node + } + function setState(state) { + self.state = state; + if(self.onchange) { + self.onchange(self) + } + if(self.onstatereadychange) { + self.onstatereadychange(self) + } + } + function handleFlatXml(xmldoc) { + var root = importRootNode(xmldoc); + if(!root || root.localName !== "document" || root.namespaceURI !== officens) { + setState(OdfContainer.INVALID); + return + } + self.rootElement = root; + root.fontFaceDecls = getDirectChild(root, officens, "font-face-decls"); + root.styles = getDirectChild(root, officens, "styles"); + root.automaticStyles = getDirectChild(root, officens, "automatic-styles"); + root.masterStyles = getDirectChild(root, officens, "master-styles"); + root.body = getDirectChild(root, officens, "body"); + root.meta = getDirectChild(root, officens, "meta"); + setState(OdfContainer.DONE) + } + function handleStylesXml(xmldoc) { + var node = importRootNode(xmldoc), root = self.rootElement; + if(!node || node.localName !== "document-styles" || node.namespaceURI !== officens) { + setState(OdfContainer.INVALID); + return + } + root.fontFaceDecls = getDirectChild(node, officens, "font-face-decls"); + setChild(root, root.fontFaceDecls); + root.styles = getDirectChild(node, officens, "styles"); + setChild(root, root.styles); + root.automaticStyles = getDirectChild(node, officens, "automatic-styles"); + setChild(root, root.automaticStyles); + root.masterStyles = getDirectChild(node, officens, "master-styles"); + setChild(root, root.masterStyles); + fontLoader.loadFonts(root.fontFaceDecls, zip, null) + } + function handleContentXml(xmldoc) { + var node = importRootNode(xmldoc), root, automaticStyles, fontFaceDecls, c; + if(!node || node.localName !== "document-content" || node.namespaceURI !== officens) { + setState(OdfContainer.INVALID); + return + } + root = self.rootElement; + fontFaceDecls = getDirectChild(node, officens, "font-face-decls"); + if(root.fontFaceDecls && fontFaceDecls) { + c = fontFaceDecls.firstChild; + while(c) { + root.fontFaceDecls.appendChild(c); + c = fontFaceDecls.firstChild + } + }else { + if(fontFaceDecls) { + root.fontFaceDecls = fontFaceDecls; + setChild(root, fontFaceDecls) + } + } + automaticStyles = getDirectChild(node, officens, "automatic-styles"); + if(root.automaticStyles && automaticStyles) { + c = automaticStyles.firstChild; + while(c) { + root.automaticStyles.appendChild(c); + c = automaticStyles.firstChild + } + }else { + if(automaticStyles) { + root.automaticStyles = automaticStyles; + setChild(root, automaticStyles) + } + } + root.body = getDirectChild(node, officens, "body"); + setChild(root, root.body) + } + function handleMetaXml(xmldoc) { + var node = importRootNode(xmldoc), root; + if(!node || node.localName !== "document-meta" || node.namespaceURI !== officens) { + return + } + root = self.rootElement; + root.meta = getDirectChild(node, officens, "meta"); + setChild(root, root.meta) + } + function handleSettingsXml(xmldoc) { + var node = importRootNode(xmldoc), root; + if(!node || node.localName !== "document-settings" || node.namespaceURI !== officens) { + return + } + root = self.rootElement; + root.settings = getDirectChild(node, officens, "settings"); + setChild(root, root.settings) + } + function handleManifestXml(xmldoc) { + var node = importRootNode(xmldoc), root, n; + if(!node || node.localName !== "manifest" || node.namespaceURI !== manifestns) { + return + } + root = self.rootElement; + root.manifest = node; + n = root.manifest.firstChild; + while(n) { + if(n.nodeType === 1 && n.localName === "file-entry" && n.namespaceURI === manifestns) { + partMimetypes[n.getAttributeNS(manifestns, "full-path")] = n.getAttributeNS(manifestns, "media-type") + } + n = n.nextSibling + } + } + function getContentXmlNode(callback) { + var handler = {rootElementReady:function(err, rootxml, done) { + contentXmlCompletelyLoaded = err || done; + if(err) { + return callback(err, null) + } + var parser = new DOMParser; + rootxml = parser.parseFromString(rootxml, "text/xml"); + callback(null, rootxml) + }, bodyChildElementsReady:function(err, nodes, done) { + }}; + zip.loadContentXmlAsFragments("content.xml", handler) + } + function getXmlNode(filepath, callback) { + zip.loadAsDOM(filepath, callback) + } + function loadComponents() { + getXmlNode("styles.xml", function(err, xmldoc) { + handleStylesXml(xmldoc); + if(self.state === OdfContainer.INVALID) { + return + } + getXmlNode("content.xml", function(err, xmldoc) { + handleContentXml(xmldoc); + if(self.state === OdfContainer.INVALID) { + return + } + getXmlNode("meta.xml", function(err, xmldoc) { + handleMetaXml(xmldoc); + if(self.state === OdfContainer.INVALID) { + return + } + getXmlNode("settings.xml", function(err, xmldoc) { + if(xmldoc) { + handleSettingsXml(xmldoc) + } + getXmlNode("META-INF/manifest.xml", function(err, xmldoc) { + if(xmldoc) { + handleManifestXml(xmldoc) + } + if(self.state !== OdfContainer.INVALID) { + setState(OdfContainer.DONE) + } + }) + }) + }) + }) + }) + } + function documentElement(name, map) { + var s = "", i; + for(i in map) { + if(map.hasOwnProperty(i)) { + s += " xmlns:" + i + '="' + map[i] + '"' + } + } + return'' + } + function serializeMetaXml() { + var nsmap = style2CSS.namespaces, serializer = new xmldom.LSSerializer, s = documentElement("document-meta", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement); + s += serializer.writeToString(self.rootElement.meta, nsmap); + s += ""; + return s + } + function serializeSettingsXml() { + var nsmap = style2CSS.namespaces, serializer = new xmldom.LSSerializer, s = documentElement("document-settings", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement); + s += serializer.writeToString(self.rootElement.settings, nsmap); + s += ""; + return s + } + function serializeStylesXml() { + var nsmap = style2CSS.namespaces, serializer = new xmldom.LSSerializer, s = documentElement("document-styles", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement, self.rootElement.masterStyles); + s += serializer.writeToString(self.rootElement.fontFaceDecls, nsmap); + s += serializer.writeToString(self.rootElement.styles, nsmap); + s += serializer.writeToString(self.rootElement.automaticStyles, nsmap); + s += serializer.writeToString(self.rootElement.masterStyles, nsmap); + s += ""; + return s + } + function serializeContentXml() { + var nsmap = style2CSS.namespaces, serializer = new xmldom.LSSerializer, s = documentElement("document-content", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement, self.rootElement.body); + s += serializer.writeToString(self.rootElement.automaticStyles, nsmap); + s += serializer.writeToString(self.rootElement.body, nsmap); + s += ""; + return s + } + function createElement(Type) { + var original = document.createElementNS(Type.namespaceURI, Type.localName), method, iface = new Type; + for(method in iface) { + if(iface.hasOwnProperty(method)) { + original[method] = iface[method] + } + } + return original + } + function loadFromXML(url, callback) { + runtime.loadXML(url, function(err, dom) { + if(err) { + callback(err) + }else { + handleFlatXml(dom) + } + }) + } + this.getPart = function(partname) { + return new OdfPart(partname, self, zip) + }; + this.save = function(callback) { + var data; + data = runtime.byteArrayFromString(serializeSettingsXml(), "utf8"); + zip.save("settings.xml", data, true, new Date); + data = runtime.byteArrayFromString(serializeMetaXml(), "utf8"); + zip.save("meta.xml", data, true, new Date); + data = runtime.byteArrayFromString(serializeStylesXml(), "utf8"); + zip.save("styles.xml", data, true, new Date); + data = runtime.byteArrayFromString(serializeContentXml(), "utf8"); + zip.save("content.xml", data, true, new Date); + zip.write(function(err) { + callback(err) + }) + }; + this.state = OdfContainer.LOADING; + this.rootElement = createElement(ODFDocumentElement); + this.parts = new OdfPartList(this); + zip = new core.Zip(url, function(err, zipobject) { + zip = zipobject; + if(err) { + loadFromXML(url, function(xmlerr) { + if(err) { + zip.error = err + "\n" + xmlerr; + setState(OdfContainer.INVALID) + } + }) + }else { + loadComponents() + } + }) + }; + odf.OdfContainer.EMPTY = 0; + odf.OdfContainer.LOADING = 1; + odf.OdfContainer.DONE = 2; + odf.OdfContainer.INVALID = 3; + odf.OdfContainer.SAVING = 4; + odf.OdfContainer.MODIFIED = 5; + odf.OdfContainer.getContainer = function(url) { + return new odf.OdfContainer(url, null) + }; + return odf.OdfContainer +}(); +odf.Formatting = function Formatting() { + var odfContainer, styleInfo = new odf.StyleInfo; + function RangeElementIterator(range) { + function getNthChild(parent, n) { + var c = parent && parent.firstChild; + while(c && n) { + c = c.nextSibling; + n -= 1 + } + return c + } + var start = getNthChild(range.startContainer, range.startOffset), end = getNthChild(range.endContainer, range.endOffset), current = start; + this.next = function() { + var c = current; + if(c === null) { + return c + } + return null + } + } + function getParentStyle(element) { + var n = element.firstChild, e; + if(n.nodeType === 1) { + e = n; + return e + } + return null + } + function getParagraphStyles(range) { + var iter = new RangeElementIterator(range), e, styles = []; + e = iter.next(); + while(e) { + if(styleInfo.canElementHaveStyle("paragraph", e)) { + styles.push(e) + } + } + return styles + } + this.setOdfContainer = function(odfcontainer) { + odfContainer = odfcontainer + }; + this.isCompletelyBold = function(selection) { + return false + }; + this.getAlignment = function(selection) { + var styles = this.getParagraphStyles(selection), i, l = styles.length; + return undefined + }; + this.getParagraphStyles = function(selection) { + var i, j, s, styles = []; + for(i = 0;i < selection.length;i += 0) { + s = getParagraphStyles(selection[i]); + for(j = 0;j < s.length;j += 1) { + if(styles.indexOf(s[j]) === -1) { + styles.push(s[j]) + } + } + } + return styles + }; + this.getTextStyles = function(selection) { + return[] + } +}; +runtime.loadClass("odf.OdfContainer"); +runtime.loadClass("odf.Formatting"); +runtime.loadClass("xmldom.XPath"); +odf.OdfCanvas = function() { + function LoadingQueue() { + var queue = [], taskRunning = false; + function run(task) { + taskRunning = true; + runtime.setTimeout(function() { + try { + task() + }catch(e) { + runtime.log(e) + } + taskRunning = false; + if(queue.length > 0) { + run(queue.pop()) + } + }, 10) + } + this.clearQueue = function() { + queue.length = 0 + }; + this.addToQueue = function(loadingTask) { + if(queue.length === 0 && !taskRunning) { + return run(loadingTask) + } + queue.push(loadingTask) + } + } + function PageSwitcher(css) { + var sheet = css.sheet, position = 1; + function updateCSS() { + while(sheet.cssRules.length > 0) { + sheet.deleteRule(0) + } + sheet.insertRule("office|presentation draw|page {display:none;}", 0); + sheet.insertRule("office|presentation draw|page:nth-child(" + position + ") {display:block;}", 1) + } + this.showNextPage = function() { + position += 1; + updateCSS() + }; + this.showPreviousPage = function() { + if(position > 1) { + position -= 1; + updateCSS() + } + }; + this.css = css + } + function listenEvent(eventTarget, eventType, eventHandler) { + if(eventTarget.addEventListener) { + eventTarget.addEventListener(eventType, eventHandler, false) + }else { + if(eventTarget.attachEvent) { + eventType = "on" + eventType; + eventTarget.attachEvent(eventType, eventHandler) + }else { + eventTarget["on" + eventType] = eventHandler + } + } + } + function SelectionWatcher(element) { + var selection = [], count = 0, listeners = []; + function isAncestorOf(ancestor, descendant) { + while(descendant) { + if(descendant === ancestor) { + return true + } + descendant = descendant.parentNode + } + return false + } + function fallsWithin(element, range) { + return isAncestorOf(element, range.startContainer) && isAncestorOf(element, range.endContainer) + } + function getCurrentSelection() { + var s = [], selection = runtime.getWindow().getSelection(), i, r; + for(i = 0;i < selection.rangeCount;i += 1) { + r = selection.getRangeAt(i); + if(r !== null && fallsWithin(element, r)) { + s.push(r) + } + } + return s + } + function rangesNotEqual(rangeA, rangeB) { + if(rangeA === rangeB) { + return false + } + if(rangeA === null || rangeB === null) { + return true + } + return rangeA.startContainer !== rangeB.startContainer || rangeA.startOffset !== rangeB.startOffset || rangeA.endContainer !== rangeB.endContainer || rangeA.endOffset !== rangeB.endOffset + } + function emitNewSelection() { + var i, l = listeners.length; + for(i = 0;i < l;i += 1) { + listeners[i](element, selection) + } + } + function copySelection(selection) { + var s = [selection.length], i, oldr, r, doc = element.ownerDocument; + for(i = 0;i < selection.length;i += 1) { + oldr = selection[i]; + r = doc.createRange(); + r.setStart(oldr.startContainer, oldr.startOffset); + r.setEnd(oldr.endContainer, oldr.endOffset); + s[i] = r + } + return s + } + function checkSelection() { + var s = getCurrentSelection(), i; + if(s.length === selection.length) { + for(i = 0;i < s.length;i += 1) { + if(rangesNotEqual(s[i], selection[i])) { + break + } + } + if(i === s.length) { + return + } + } + selection = s; + selection = copySelection(s); + emitNewSelection() + } + this.addListener = function(eventName, handler) { + var i, l = listeners.length; + for(i = 0;i < l;i += 1) { + if(listeners[i] === handler) { + return + } + } + listeners.push(handler) + }; + listenEvent(element, "mouseup", checkSelection); + listenEvent(element, "keyup", checkSelection); + listenEvent(element, "keydown", checkSelection) + } + var style2CSS = new odf.Style2CSS, namespaces = style2CSS.namespaces, drawns = namespaces.draw, fons = namespaces.fo, officens = namespaces.office, svgns = namespaces.svg, textns = namespaces.text, xlinkns = namespaces.xlink, window = runtime.getWindow(), xpath = new xmldom.XPath, eventHandlers = {}, editparagraph, loadingQueue = new LoadingQueue; + function addEventListener(eventType, eventHandler) { + var handlers = eventHandlers[eventType]; + if(handlers === undefined) { + handlers = eventHandlers[eventType] = [] + } + if(eventHandler && handlers.indexOf(eventHandler) === -1) { + handlers.push(eventHandler) + } + } + function fireEvent(eventType, args) { + if(!eventHandlers.hasOwnProperty(eventType)) { + return + } + var handlers = eventHandlers[eventType], i; + for(i = 0;i < handlers.length;i += 1) { + handlers[i](args) + } + } + function clear(element) { + while(element.firstChild) { + element.removeChild(element.firstChild) + } + } + function handleStyles(odfelement, stylesxmlcss) { + var style2css = new odf.Style2CSS; + style2css.style2css(stylesxmlcss.sheet, odfelement.styles, odfelement.automaticStyles) + } + function setFramePosition(id, frame, stylesheet) { + frame.setAttribute("styleid", id); + var rule, anchor = frame.getAttributeNS(textns, "anchor-type"), x = frame.getAttributeNS(svgns, "x"), y = frame.getAttributeNS(svgns, "y"), width = frame.getAttributeNS(svgns, "width"), height = frame.getAttributeNS(svgns, "height"), minheight = frame.getAttributeNS(fons, "min-height"), minwidth = frame.getAttributeNS(fons, "min-width"); + if(anchor === "as-char") { + rule = "display: inline-block;" + }else { + if(anchor || x || y) { + rule = "position: absolute;" + }else { + if(width || height || minheight || minwidth) { + rule = "display: block;" + } + } + } + if(x) { + rule += "left: " + x + ";" + } + if(y) { + rule += "top: " + y + ";" + } + if(width) { + rule += "width: " + width + ";" + } + if(height) { + rule += "height: " + height + ";" + } + if(minheight) { + rule += "min-height: " + minheight + ";" + } + if(minwidth) { + rule += "min-width: " + minwidth + ";" + } + if(rule) { + rule = "draw|" + frame.localName + '[styleid="' + id + '"] {' + rule + "}"; + stylesheet.insertRule(rule, stylesheet.cssRules.length) + } + } + function getUrlFromBinaryDataElement(image) { + var node = image.firstChild; + while(node) { + if(node.namespaceURI === officens && node.localName === "binary-data") { + return"data:image/png;base64," + node.textContent + } + node = node.nextSibling + } + return"" + } + function setImage(id, container, image, stylesheet) { + image.setAttribute("styleid", id); + var url = image.getAttributeNS(xlinkns, "href"), part, node; + function callback(url) { + var rule = "background-image: url(" + url + ");"; + rule = 'draw|image[styleid="' + id + '"] {' + rule + "}"; + stylesheet.insertRule(rule, stylesheet.cssRules.length) + } + if(url) { + try { + if(container.getPartUrl) { + url = container.getPartUrl(url); + callback(url) + }else { + part = container.getPart(url); + part.onchange = function(part) { + callback(part.url) + }; + part.load() + } + }catch(e) { + runtime.log("slight problem: " + e) + } + }else { + url = getUrlFromBinaryDataElement(image); + callback(url) + } + } + function formatParagraphAnchors(odfbody) { + var runtimens = "urn:webodf", n, i, nodes = xpath.getODFElementsWithXPath(odfbody, ".//*[*[@text:anchor-type='paragraph']]", style2CSS.namespaceResolver); + for(i = 0;i < nodes.length;i += 1) { + n = nodes[i]; + if(n.setAttributeNS) { + n.setAttributeNS(runtimens, "containsparagraphanchor", true) + } + } + } + function modifyImages(container, odfbody, stylesheet) { + var node, frames, i, images; + function namespaceResolver(prefix) { + return namespaces[prefix] + } + frames = []; + node = odfbody.firstChild; + while(node && node !== odfbody) { + if(node.namespaceURI === drawns) { + frames[frames.length] = node + } + if(node.firstChild) { + node = node.firstChild + }else { + while(node && node !== odfbody && !node.nextSibling) { + node = node.parentNode + } + if(node && node.nextSibling) { + node = node.nextSibling + } + } + } + for(i = 0;i < frames.length;i += 1) { + node = frames[i]; + setFramePosition("frame" + String(i), node, stylesheet) + } + formatParagraphAnchors(odfbody) + } + function loadImages(container, odffragment, stylesheet) { + var i, images, node; + function loadImage(name, container, node, stylesheet) { + loadingQueue.addToQueue(function() { + setImage(name, container, node, stylesheet) + }) + } + images = odffragment.getElementsByTagNameNS(drawns, "image"); + for(i = 0;i < images.length;i += 1) { + node = images.item(i); + loadImage("image" + String(i), container, node, stylesheet) + } + } + function setVideo(id, container, plugin, stylesheet) { + var video, source, url, videoType, doc = plugin.ownerDocument, part, node; + url = plugin.getAttributeNS(xlinkns, "href"); + function callback(url, mimetype) { + if(mimetype.substr(0, 6) === "video/") { + video = doc.createElementNS(doc.documentElement.namespaceURI, "video"); + video.setAttribute("controls", "controls"); + source = doc.createElement("source"); + source.setAttribute("src", url); + source.setAttribute("type", mimetype); + video.appendChild(source); + plugin.parentNode.appendChild(video) + }else { + plugin.innerHtml = "Unrecognised Plugin" + } + } + if(url) { + try { + if(container.getPartUrl) { + url = container.getPartUrl(url); + callback(url, "video/mp4") + }else { + part = container.getPart(url); + part.onchange = function(part) { + callback(part.url, part.mimetype) + }; + part.load() + } + }catch(e) { + runtime.log("slight problem: " + e) + } + }else { + runtime.log("using MP4 data fallback"); + url = getUrlFromBinaryDataElement(plugin); + callback(url, "video/mp4") + } + } + function loadVideos(container, odffragment, stylesheet) { + var i, plugins, node; + function loadVideo(name, container, node, stylesheet) { + loadingQueue.addToQueue(function() { + setVideo(name, container, node, stylesheet) + }) + } + plugins = odffragment.getElementsByTagNameNS(drawns, "plugin"); + runtime.log("Loading Videos:"); + for(i = 0;i < plugins.length;i += 1) { + runtime.log("...Found a video."); + node = plugins.item(i); + loadVideo("video" + String(i), container, node, stylesheet) + } + } + function addStyleSheet(document) { + var styles = document.getElementsByTagName("style"), head = document.getElementsByTagName("head")[0], text = "", prefix, a = "", b; + if(styles && styles.length > 0) { + styles = styles[0].cloneNode(false) + }else { + styles = document.createElement("style") + } + for(prefix in namespaces) { + if(namespaces.hasOwnProperty(prefix) && prefix) { + text += "@namespace " + prefix + " url(" + namespaces[prefix] + ");\n" + } + } + styles.appendChild(document.createTextNode(text)); + head.appendChild(styles); + return styles + } + odf.OdfCanvas = function OdfCanvas(element) { + var self = this, document = element.ownerDocument, odfcontainer, formatting = new odf.Formatting, selectionWatcher = new SelectionWatcher(element), slidecssindex = 0, pageSwitcher = new PageSwitcher(addStyleSheet(document)), stylesxmlcss = addStyleSheet(document), positioncss = addStyleSheet(document), editable = false, zoomLevel = 1; + function fixContainerSize() { + var sizer = element.firstChild, odfdoc = sizer.firstChild; + if(!odfdoc) { + return + } + element.style.WebkitTransform = "scale(" + zoomLevel + ")"; + element.style.WebkitTransformOrigin = "left top"; + element.style.width = Math.round(zoomLevel * odfdoc.offsetWidth) + "px"; + element.style.height = Math.round(zoomLevel * odfdoc.offsetHeight) + "px" + } + function handleContent(container, odfnode) { + var css = positioncss.sheet, sizer; + modifyImages(container, odfnode.body, css); + css.insertRule("draw|page { background-color:#fff; }", css.cssRules.length); + clear(element); + sizer = document.createElement("div"); + sizer.style.display = "inline-block"; + sizer.style.background = "white"; + sizer.appendChild(odfnode); + element.appendChild(sizer); + loadImages(container, odfnode.body, css); + loadVideos(container, odfnode.body, css); + fixContainerSize() + } + function refreshOdf(container) { + if(odfcontainer !== container) { + return + } + function callback() { + clear(element); + element.style.display = "inline-block"; + var odfnode = container.rootElement; + element.ownerDocument.importNode(odfnode, true); + formatting.setOdfContainer(container); + handleStyles(odfnode, stylesxmlcss); + handleContent(container, odfnode); + fireEvent("statereadychange") + } + if(odfcontainer.state === odf.OdfContainer.DONE) { + callback() + }else { + odfcontainer.onchange = callback + } + } + this.odfContainer = function() { + return odfcontainer + }; + this.slidevisibilitycss = function() { + return pageSwitcher.css + }; + this["load"] = this.load = function(url) { + loadingQueue.clearQueue(); + element.innerHTML = "loading " + url; + odfcontainer = new odf.OdfContainer(url, function(container) { + odfcontainer = container; + refreshOdf(container) + }); + odfcontainer.onstatereadychange = refreshOdf + }; + function stopEditing() { + if(!editparagraph) { + return + } + var fragment = editparagraph.ownerDocument.createDocumentFragment(); + while(editparagraph.firstChild) { + fragment.insertBefore(editparagraph.firstChild, null) + } + editparagraph.parentNode.replaceChild(fragment, editparagraph) + } + this.save = function(callback) { + stopEditing(); + odfcontainer.save(callback) + }; + function cancelPropagation(event) { + if(event.stopPropagation) { + event.stopPropagation() + }else { + event.cancelBubble = true + } + } + function cancelEvent(event) { + if(event.preventDefault) { + event.preventDefault(); + event.stopPropagation() + }else { + event.returnValue = false; + event.cancelBubble = true + } + } + this.setEditable = function(iseditable) { + editable = iseditable; + if(!editable) { + stopEditing() + } + }; + function processClick(evt) { + evt = evt || window.event; + var e = evt.target, selection = window.getSelection(), range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null, startContainer = range && range.startContainer, startOffset = range && range.startOffset, endContainer = range && range.endContainer, endOffset = range && range.endOffset; + while(e && !((e.localName === "p" || e.localName === "h") && e.namespaceURI === textns)) { + e = e.parentNode + } + if(!editable) { + return + } + if(!e || e.parentNode === editparagraph) { + return + } + if(!editparagraph) { + editparagraph = e.ownerDocument.createElement("p"); + if(!editparagraph.style) { + editparagraph = e.ownerDocument.createElementNS("http://www.w3.org/1999/xhtml", "p") + } + editparagraph.style.margin = "0px"; + editparagraph.style.padding = "0px"; + editparagraph.style.border = "0px"; + editparagraph.setAttribute("contenteditable", true) + }else { + if(editparagraph.parentNode) { + stopEditing() + } + } + e.parentNode.replaceChild(editparagraph, e); + editparagraph.appendChild(e); + editparagraph.focus(); + if(range) { + selection.removeAllRanges(); + range = e.ownerDocument.createRange(); + range.setStart(startContainer, startOffset); + range.setEnd(endContainer, endOffset); + selection.addRange(range) + } + cancelEvent(evt) + } + this.addListener = function(eventName, handler) { + if(eventName === "selectionchange") { + selectionWatcher.addListener(eventName, handler) + }else { + addEventListener(eventName, handler) + } + }; + this.getFormatting = function() { + return formatting + }; + this.setZoomLevel = function(zoom) { + zoomLevel = zoom; + fixContainerSize() + }; + this.getZoomLevel = function() { + return zoomLevel + }; + this.fitToContainingElement = function(width, height) { + var realWidth = element.offsetWidth / zoomLevel, realHeight = element.offsetHeight / zoomLevel; + zoomLevel = width / realWidth; + if(height / realHeight < zoomLevel) { + zoomLevel = height / realHeight + } + fixContainerSize() + }; + this.fitToWidth = function(width) { + var realWidth = element.offsetWidth / zoomLevel; + zoomLevel = width / realWidth; + fixContainerSize() + }; + this.fitToHeight = function(height) { + var realHeight = element.offsetHeight / zoomLevel; + zoomLevel = height / realHeight; + fixContainerSize() + }; + this.showNextPage = function() { + pageSwitcher.showNextPage() + }; + this.showPreviousPage = function() { + pageSwitcher.showPreviousPage() + }; + this.showAllPages = function() { + }; + listenEvent(element, "click", processClick) + }; + return odf.OdfCanvas +}(); +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.Style2CSS"); +gui.PresenterUI = function() { + var s2css = new odf.Style2CSS, xpath = new xmldom.XPath, nsResolver = s2css.namespaceResolver; + return function PresenterUI(odf_element) { + var self = this; + self.setInitialSlideMode = function() { + self.startSlideMode("single") + }; + self.keyDownHandler = function(ev) { + if(ev.target.isContentEditable) { + return + } + if(ev.target.nodeName === "input") { + return + } + switch(ev.keyCode) { + case 84: + self.toggleToolbar(); + break; + case 37: + ; + case 8: + self.prevSlide(); + break; + case 39: + ; + case 32: + self.nextSlide(); + break; + case 36: + self.firstSlide(); + break; + case 35: + self.lastSlide(); + break + } + }; + self.root = function() { + return self.odf_canvas.odfContainer().rootElement + }; + self.firstSlide = function() { + self.slideChange(function(old, pc) { + return 0 + }) + }; + self.lastSlide = function() { + self.slideChange(function(old, pc) { + return pc - 1 + }) + }; + self.nextSlide = function() { + self.slideChange(function(old, pc) { + return old + 1 < pc ? old + 1 : -1 + }) + }; + self.prevSlide = function() { + self.slideChange(function(old, pc) { + return old < 1 ? -1 : old - 1 + }) + }; + self.slideChange = function(indexChanger) { + var pages = self.getPages(self.odf_canvas.odfContainer().rootElement), last = -1, i = 0, newidx, pagelist; + pages.forEach(function(tuple) { + var name = tuple[0], node = tuple[1]; + if(node.hasAttribute("slide_current")) { + last = i; + node.removeAttribute("slide_current") + } + i += 1 + }); + newidx = indexChanger(last, pages.length); + if(newidx === -1) { + newidx = last + } + pages[newidx][1].setAttribute("slide_current", "1"); + pagelist = document.getElementById("pagelist"); + pagelist.selectedIndex = newidx; + if(self.slide_mode === "cont") { + window.scrollBy(0, pages[newidx][1].getBoundingClientRect().top - 30) + } + }; + self.selectSlide = function(idx) { + self.slideChange(function(old, pc) { + if(idx >= pc) { + return-1 + } + if(idx < 0) { + return-1 + } + return idx + }) + }; + self.scrollIntoContView = function(idx) { + var pages = self.getPages(self.odf_canvas.odfContainer().rootElement); + if(pages.length === 0) { + return + } + window.scrollBy(0, pages[idx][1].getBoundingClientRect().top - 30) + }; + self.getPages = function(root) { + var pagenodes = root.getElementsByTagNameNS(nsResolver("draw"), "page"), pages = [], i; + for(i = 0;i < pagenodes.length;i += 1) { + pages.push([pagenodes[i].getAttribute("draw:name"), pagenodes[i]]) + } + return pages + }; + self.fillPageList = function(odfdom_root, html_select) { + var pages = self.getPages(odfdom_root), i, html_option, res, page_denom; + while(html_select.firstChild) { + html_select.removeChild(html_select.firstChild) + } + for(i = 0;i < pages.length;i += 1) { + html_option = document.createElement("option"); + res = xpath.getODFElementsWithXPath(pages[i][1], './draw:frame[@presentation:class="title"]//draw:text-box/text:p', xmldom.XPath); + page_denom = res.length > 0 ? res[0].textContent : pages[i][0]; + html_option.textContent = i + 1 + ": " + page_denom; + html_select.appendChild(html_option) + } + }; + self.startSlideMode = function(mode) { + var pagelist = document.getElementById("pagelist"), css = self.odf_canvas.slidevisibilitycss().sheet; + self.slide_mode = mode; + while(css.cssRules.length > 0) { + css.deleteRule(0) + } + self.selectSlide(0); + if(self.slide_mode === "single") { + css.insertRule("draw|page { position:fixed; left:0px;top:30px; z-index:1; }", 0); + css.insertRule("draw|page[slide_current] { z-index:2;}", 1); + css.insertRule("draw|page { -webkit-transform: scale(1);}", 2); + self.fitToWindow(); + window.addEventListener("resize", self.fitToWindow, false) + }else { + if(self.slide_mode === "cont") { + window.removeEventListener("resize", self.fitToWindow, false) + } + } + self.fillPageList(self.odf_canvas.odfContainer().rootElement, pagelist) + }; + self.toggleToolbar = function() { + var css, found, i; + css = self.odf_canvas.slidevisibilitycss().sheet; + found = -1; + for(i = 0;i < css.cssRules.length;i += 1) { + if(css.cssRules[i].cssText.substring(0, 8) === ".toolbar") { + found = i; + break + } + } + if(found > -1) { + css.deleteRule(found) + }else { + css.insertRule(".toolbar { position:fixed; left:0px;top:-200px; z-index:0; }", 0) + } + }; + self.fitToWindow = function() { + function ruleByFactor(f) { + return"draw|page { \n" + "-moz-transform: scale(" + f + "); \n" + "-moz-transform-origin: 0% 0%; " + "-webkit-transform-origin: 0% 0%; -webkit-transform: scale(" + f + "); " + "-o-transform-origin: 0% 0%; -o-transform: scale(" + f + "); " + "-ms-transform-origin: 0% 0%; -ms-transform: scale(" + f + "); " + "}" + } + var pages = self.getPages(self.root()), factorVert = (window.innerHeight - 40) / pages[0][1].clientHeight, factorHoriz = (window.innerWidth - 10) / pages[0][1].clientWidth, factor = factorVert < factorHoriz ? factorVert : factorHoriz, css = self.odf_canvas.slidevisibilitycss().sheet; + css.deleteRule(2); + css.insertRule(ruleByFactor(factor), 2) + }; + self.load = function(url) { + self.odf_canvas.load(url) + }; + self.odf_element = odf_element; + self.odf_canvas = new odf.OdfCanvas(self.odf_element); + self.odf_canvas.addListener("statereadychange", self.setInitialSlideMode); + self.slide_mode = "undefined"; + document.addEventListener("keydown", self.keyDownHandler, false) + } +}(); +gui.Caret = function Caret(selection, rootNode) { + var document = rootNode.ownerDocument, cursorns, cursorNode; + cursorns = "urn:webodf:names:cursor"; + cursorNode = document.createElementNS(cursorns, "cursor"); + this.updateToSelection = function() { + var range; + if(selection.rangeCount === 1) { + range = selection.getRangeAt(0) + } + } +}; +runtime.loadClass("core.Cursor"); +gui.SelectionMover = function SelectionMover(selection, pointWalker) { + var doc = pointWalker.node().ownerDocument, cursor = new core.Cursor(selection, doc); + function getActiveRange(node) { + var range; + if(selection.rangeCount === 0) { + selection.addRange(node.ownerDocument.createRange()) + } + return selection.getRangeAt(selection.rangeCount - 1) + } + function setStart(node, offset) { + var ranges = [], i, range; + for(i = 0;i < selection.rangeCount;i += 1) { + ranges[i] = selection.getRangeAt(i) + } + selection.removeAllRanges(); + if(ranges.length === 0) { + ranges[0] = node.ownerDocument.createRange() + } + ranges[ranges.length - 1].setStart(pointWalker.node(), pointWalker.position()); + for(i = 0;i < ranges.length;i += 1) { + selection.addRange(ranges[i]) + } + } + function doMove(extend, move) { + if(selection.rangeCount === 0) { + return + } + var range = selection.getRangeAt(0), element; + if(!range.startContainer || range.startContainer.nodeType !== 1) { + return + } + element = range.startContainer; + pointWalker.setPoint(element, range.startOffset); + move(); + setStart(pointWalker.node(), pointWalker.position()) + } + function doMoveForward(extend, move) { + if(selection.rangeCount === 0) { + return + } + move(); + var range = selection.getRangeAt(0), element; + if(!range.startContainer || range.startContainer.nodeType !== 1) { + return + } + element = range.startContainer; + pointWalker.setPoint(element, range.startOffset) + } + function moveCursor(node, offset, selectMode) { + if(selectMode) { + selection.extend(node, offset) + }else { + selection.collapse(node, offset) + } + cursor.updateToSelection() + } + function moveCursorLeft() { + var element; + if(!selection.focusNode || selection.focusNode.nodeType !== 1) { + return + } + element = selection.focusNode; + pointWalker.setPoint(element, selection.focusOffset); + pointWalker.stepBackward(); + moveCursor(pointWalker.node(), pointWalker.position(), false) + } + function moveCursorRight() { + cursor.remove(); + var element; + if(!selection.focusNode || selection.focusNode.nodeType !== 1) { + return + } + element = selection.focusNode; + pointWalker.setPoint(element, selection.focusOffset); + pointWalker.stepForward(); + moveCursor(pointWalker.node(), pointWalker.position(), false) + } + function moveCursorUp() { + var rect = cursor.getNode().getBoundingClientRect(), x = rect.left, y = rect.top, arrived = false, left = 200; + while(!arrived && left) { + left -= 1; + moveCursorLeft(); + rect = cursor.getNode().getBoundingClientRect(); + arrived = rect.top !== y && rect.left < x + } + } + function moveCursorDown() { + cursor.updateToSelection(); + var rect = cursor.getNode().getBoundingClientRect(), x = rect.left, y = rect.top, arrived = false, left = 200; + while(!arrived) { + left -= 1; + moveCursorRight(); + rect = cursor.getNode().getBoundingClientRect(); + arrived = rect.top !== y && rect.left > x + } + } + this.movePointForward = function(extend) { + doMove(extend, pointWalker.stepForward) + }; + this.movePointBackward = function(extend) { + doMove(extend, pointWalker.stepBackward) + }; + this.moveLineForward = function(extend) { + if(selection.modify) { + selection.modify(extend ? "extend" : "move", "forward", "line") + }else { + doMove(extend, moveCursorDown) + } + }; + this.moveLineBackward = function(extend) { + if(selection.modify) { + selection.modify(extend ? "extend" : "move", "backward", "line") + }else { + doMove(extend, function() { + }) + } + }; + return this +}; +runtime.loadClass("core.PointWalker"); +runtime.loadClass("core.Cursor"); +gui.XMLEdit = function XMLEdit(element, stylesheet) { + var simplecss, cssprefix, documentElement, customNS = "customns", walker = null; + if(!element.id) { + element.id = "xml" + String(Math.random()).substring(2) + } + cssprefix = "#" + element.id + " "; + function installHandlers() { + } + simplecss = cssprefix + "*," + cssprefix + ":visited, " + cssprefix + ":link {display:block; margin: 0px; margin-left: 10px; font-size: medium; color: black; background: white; font-variant: normal; font-weight: normal; font-style: normal; font-family: sans-serif; text-decoration: none; white-space: pre-wrap; height: auto; width: auto}\n" + cssprefix + ":before {color: blue; content: '<' attr(customns_name) attr(customns_atts) '>';}\n" + cssprefix + ":after {color: blue; content: '';}\n" + + cssprefix + "{overflow: auto;}\n"; + function listenEvent(eventTarget, eventType, eventHandler) { + if(eventTarget.addEventListener) { + eventTarget.addEventListener(eventType, eventHandler, false) + }else { + if(eventTarget.attachEvent) { + eventType = "on" + eventType; + eventTarget.attachEvent(eventType, eventHandler) + }else { + eventTarget["on" + eventType] = eventHandler + } + } + } + function cancelEvent(event) { + if(event.preventDefault) { + event.preventDefault() + }else { + event.returnValue = false + } + } + function isCaretMoveCommand(charCode) { + if(charCode >= 16 && charCode <= 20) { + return true + } + if(charCode >= 33 && charCode <= 40) { + return true + } + return false + } + function syncSelectionWithWalker() { + var sel = element.ownerDocument.defaultView.getSelection(), r; + if(!sel || sel.rangeCount <= 0 || !walker) { + return + } + r = sel.getRangeAt(0); + walker.setPoint(r.startContainer, r.startOffset) + } + function syncWalkerWithSelection() { + var sel = element.ownerDocument.defaultView.getSelection(), n, r; + sel.removeAllRanges(); + if(!walker || !walker.node()) { + return + } + n = walker.node(); + r = n.ownerDocument.createRange(); + r.setStart(n, walker.position()); + r.collapse(true); + sel.addRange(r) + } + function handleKeyDown(event) { + var charCode = event.charCode || event.keyCode; + walker = null; + if(walker && charCode === 39) { + syncSelectionWithWalker(); + walker.stepForward(); + syncWalkerWithSelection() + }else { + if(walker && charCode === 37) { + syncSelectionWithWalker(); + walker.stepBackward(); + syncWalkerWithSelection() + }else { + if(isCaretMoveCommand(charCode)) { + return + } + } + } + cancelEvent(event) + } + function handleKeyPress(event) { + } + function handleClick(event) { + var sel = element.ownerDocument.defaultView.getSelection(), r = sel.getRangeAt(0), n = r.startContainer; + cancelEvent(event) + } + function initElement(element) { + listenEvent(element, "click", handleClick); + listenEvent(element, "keydown", handleKeyDown); + listenEvent(element, "keypress", handleKeyPress); + listenEvent(element, "drop", cancelEvent); + listenEvent(element, "dragend", cancelEvent); + listenEvent(element, "beforepaste", cancelEvent); + listenEvent(element, "paste", cancelEvent) + } + function cleanWhitespace(node) { + var n = node.firstChild, p, re = /^\s*$/; + while(n && n !== node) { + p = n; + n = n.nextSibling || n.parentNode; + if(p.nodeType === 3 && re.test(p.nodeValue)) { + p.parentNode.removeChild(p) + } + } + } + function setCssHelperAttributes(node) { + var atts, attsv, a, i; + atts = node.attributes; + attsv = ""; + for(i = atts.length - 1;i >= 0;i -= 1) { + a = atts.item(i); + attsv = attsv + " " + a.nodeName + '="' + a.nodeValue + '"' + } + node.setAttribute("customns_name", node.nodeName); + node.setAttribute("customns_atts", attsv) + } + function addExplicitAttributes(node) { + var n = node.firstChild; + while(n && n !== node) { + if(n.nodeType === 1) { + addExplicitAttributes(n) + } + n = n.nextSibling || n.parentNode + } + setCssHelperAttributes(node); + cleanWhitespace(node) + } + function getNamespacePrefixes(node, prefixes) { + var n = node.firstChild, atts, att, i; + while(n && n !== node) { + if(n.nodeType === 1) { + getNamespacePrefixes(n, prefixes); + atts = n.attributes; + for(i = atts.length - 1;i >= 0;i -= 1) { + att = atts.item(i); + if(att.namespaceURI === "http://www.w3.org/2000/xmlns/") { + if(!prefixes[att.nodeValue]) { + prefixes[att.nodeValue] = att.localName + } + } + } + } + n = n.nextSibling || n.parentNode + } + } + function generateUniquePrefixes(prefixes) { + var taken = {}, ns, p, n = 0; + for(ns in prefixes) { + if(prefixes.hasOwnProperty(ns) && ns) { + p = prefixes[ns]; + if(!p || taken.hasOwnProperty(p) || p === "xmlns") { + do { + p = "ns" + n; + n += 1 + }while(taken.hasOwnProperty(p)); + prefixes[ns] = p + } + taken[p] = true + } + } + } + function createCssFromXmlInstance(node) { + var prefixes = {}, css = "@namespace customns url(customns);\n", name, pre, ns, names, csssel; + getNamespacePrefixes(node, prefixes); + generateUniquePrefixes(prefixes); + return css + } + function updateCSS() { + var css = element.ownerDocument.createElement("style"), text = createCssFromXmlInstance(element); + css.type = "text/css"; + text = text + simplecss; + css.appendChild(element.ownerDocument.createTextNode(text)); + stylesheet = stylesheet.parentNode.replaceChild(css, stylesheet) + } + function getXML() { + return documentElement + } + function setXML(xml) { + var node = xml.documentElement || xml; + node = element.ownerDocument.importNode(node, true); + documentElement = node; + addExplicitAttributes(node); + while(element.lastChild) { + element.removeChild(element.lastChild) + } + element.appendChild(node); + updateCSS(); + walker = new core.PointWalker(node) + } + initElement(element); + this.updateCSS = updateCSS; + this.setXML = setXML; + this.getXML = getXML +}; +(function() { + return["core/Async.js", "core/Base64.js", "core/ByteArray.js", "core/ByteArrayWriter.js", "core/Cursor.js", "core/JSLint.js", "core/PointWalker.js", "core/RawDeflate.js", "core/RawInflate.js", "core/UnitTester.js", "core/Zip.js", "gui/Caret.js", "gui/SelectionMover.js", "gui/XMLEdit.js", "gui/PresenterUI.js", "odf/FontLoader.js", "odf/Formatting.js", "odf/OdfCanvas.js", "odf/OdfContainer.js", "odf/Style2CSS.js", "odf/StyleInfo.js", "xmldom/LSSerializer.js", "xmldom/LSSerializerFilter.js", "xmldom/OperationalTransformDOM.js", + "xmldom/OperationalTransformInterface.js", "xmldom/RelaxNG.js", "xmldom/RelaxNG2.js", "xmldom/RelaxNGParser.js", "xmldom/XPath.js"] +})(); + diff --git a/apps/files_odfviewer/js/webodf.js b/apps/files_odfviewer/js/webodf.js new file mode 100644 index 0000000000..1b85527260 --- /dev/null +++ b/apps/files_odfviewer/js/webodf.js @@ -0,0 +1,343 @@ +// Input 0 +/* + + @licstart + The JavaScript code in this page is free software: you can redistribute it + and/or modify it under the terms of the GNU Affero General Public License + (GNU AGPL) as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. The code is distributed + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + + As additional permission under GNU AGPL version 3 section 7, you + may distribute non-source (e.g., minimized or compacted) forms of + that code without the copy of the GNU GPL normally required by + section 4, provided you include this license notice and a URL + through which recipients can access the Corresponding Source. + + As a special exception to the AGPL, any HTML file which merely makes function + calls to this code, and for that purpose includes it by reference shall be + deemed a separate work for copyright law purposes. In addition, the copyright + holders of this code give you permission to combine this code with free + software libraries that are released under the GNU LGPL. You may copy and + distribute such a system following the terms of the GNU AGPL for this code + and the LGPL for the libraries. If you modify this code, you may extend this + exception to your version of the code, but you are not obligated to do so. + If you do not wish to do so, delete this exception statement from your + version. + + This license applies to this entire compilation. + @licend + @source: http://www.webodf.org/ + @source: http://gitorious.org/odfkit/webodf/ +*/ +var core={},gui={},xmldom={},odf={}; +// Input 1 +function Runtime(){}Runtime.ByteArray=function(){};Runtime.ByteArray.prototype.slice=function(){};Runtime.prototype.byteArrayFromArray=function(){};Runtime.prototype.byteArrayFromString=function(){};Runtime.prototype.byteArrayToString=function(){};Runtime.prototype.concatByteArrays=function(){};Runtime.prototype.read=function(){};Runtime.prototype.readFile=function(){};Runtime.prototype.readFileSync=function(){};Runtime.prototype.loadXML=function(){};Runtime.prototype.writeFile=function(){}; +Runtime.prototype.isFile=function(){};Runtime.prototype.getFileSize=function(){};Runtime.prototype.deleteFile=function(){};Runtime.prototype.log=function(){};Runtime.prototype.setTimeout=function(){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};Runtime.prototype.getWindow=function(){};var IS_COMPILED_CODE=!0; +Runtime.byteArrayToString=function(j,l){function f(c){var b="",d,a=c.length;for(d=0;de?b+=String.fromCharCode(e):(d+=1,i=c[d],224>e?b+=String.fromCharCode((e&31)<<6|i&63):(d+=1,h=c[d],b+=String.fromCharCode((e&15)<<12|(i&63)<<6|h&63)));return b}var a;"utf8"===l?a=g(j):("binary"!==l&&this.log("Unsupported encoding: "+l),a=f(j));return a}; +Runtime.getFunctionName=function(j){return void 0===j.name?(j=/function\s+(\w+)/.exec(j))&&j[1]:j.name}; +function BrowserRuntime(j){function l(c,b){var d,a,e;b?e=c:b=c;j?(a=j.ownerDocument,e&&(d=a.createElement("span"),d.className=e,d.appendChild(a.createTextNode(e)),j.appendChild(d),j.appendChild(a.createTextNode(" "))),d=a.createElement("span"),d.appendChild(a.createTextNode(b)),j.appendChild(d),j.appendChild(a.createElement("br"))):console&&console.log(b)}var f=this,g={},a=window.ArrayBuffer&&window.Uint8Array;this.ByteArray=a?function(c){Uint8Array.prototype.slice=function(b,c){void 0===c&&(void 0=== +b&&(b=0),c=this.length);var a=this.subarray(b,c),e,i,c=c-b;e=new Uint8Array(new ArrayBuffer(c));for(i=0;ii?(a[h]=i,h+=1):2048>i?(a[h]=192|i>>>6,a[h+1]=128|i&63,h+=2):(a[h]=224|i>>>12&15,a[h+1]=128|i>>>6&63,a[h+2]=128|i&63,h+=3)}else{"binary"!==b&&f.log("unknown encoding: "+b);d=c.length;a=new f.ByteArray(d);for(e=0;ek.status||0===k.status?a(null):a("Status "+k.status+": "+k.responseText||k.statusText))};b=b.buffer&&!k.sendAsBinary?b.buffer:f.byteArrayToString(b,"binary");try{k.sendAsBinary?k.sendAsBinary(b):k.send(b)}catch(e){f.log("HUH? "+e+" "+b),a(e.message)}};this.deleteFile=function(a,b){var d=new XMLHttpRequest;d.open("DELETE",a,!0);d.onreadystatechange=function(){4===d.readyState&&(200>d.status&&300<= +d.status?b(d.responseText):b(null))};d.send(null)};this.loadXML=function(a,b){var d=new XMLHttpRequest;d.open("GET",a,!0);d.overrideMimeType&&d.overrideMimeType("text/xml");d.onreadystatechange=function(){4===d.readyState&&(0===d.status&&!d.responseText?b("File "+a+" is empty."):200===d.status||0===d.status?b(null,d.responseXML):b(d.responseText))};try{d.send(null)}catch(k){b(k.message)}};this.isFile=function(a,b){f.getFileSize(a,function(a){b(-1!==a)})};this.getFileSize=function(a,b){var d=new XMLHttpRequest; +d.open("HEAD",a,!0);d.onreadystatechange=function(){if(4===d.readyState){var a=d.getResponseHeader("Content-Length");a?b(parseInt(a,10)):b(-1)}};d.send(null)};this.log=l;this.setTimeout=function(a,b){setTimeout(function(){a()},b)};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.exit=function(a){l("Calling exit with code "+a+", but exit() is not implemented.")}; +this.getWindow=function(){return window}} +function NodeJSRuntime(){var j=require("fs"),l="";this.ByteArray=function(f){return new Buffer(f)};this.byteArrayFromArray=function(f){var g=new Buffer(f.length),a,c=f.length;for(a=0;a>>18],c+=u[b>>>12&63],c+=u[b>>>6&63],c+=u[b&63];e===d+1?(b=a[e]<<4,c+=u[b>>>6],c+=u[b&63],c+="=="):e===d&&(b=a[e]<<10|a[e+1]<<2,c+=u[b>>>12],c+=u[b>>>6&63],c+=u[b&63],c+="=");return c}function f(a){var a=a.replace(/[^A-Za-z0-9+\/]+/g,""),b=[],c=a.length%4,e,d=a.length,i;for(e=0;e>16,i>>8&255,i&255);b.length-=[0,0,2,1][c];return b}function g(a){var b=[],c,e=a.length,d;for(c=0;cd?b.push(d):2048>d?b.push(192|d>>>6,128|d&63):b.push(224|d>>>12&15,128|d>>>6&63,128|d&63);return b}function a(a){var b=[],c,e=a.length,d,i,m;for(c=0;cd?b.push(d):(c+=1,i=a[c],224>d?b.push((d&31)<<6|i&63):(c+=1,m=a[c],b.push((d&15)<<12|(i&63)<<6|m&63)));return b}function c(a){return l(j(a))} +function b(a){return String.fromCharCode.apply(String,f(a))}function d(b){return a(j(b))}function k(b){for(var b=a(b),c="",e=0;eb?e+=String.fromCharCode(b):(m+=1,d=a.charCodeAt(m)&255,224>b?e+=String.fromCharCode((b&31)<<6|d&63):(m+=1,i=a.charCodeAt(m)&255,e+=String.fromCharCode((b&15)<<12|(d&63)<<6|i&63)));return e}function i(a,b){function c(){var m= +n+d;m>a.length&&(m=a.length);i+=e(a,n,m);n=m;m=n===a.length;b(i,m)&&!m&&runtime.setTimeout(c,0)}var d=1E5,i="",n=0;a.lengthb;b+=1)a.push(65+b);for(b=0;26>b;b+=1)a.push(97+b);for(b= +0;10>b;b+=1)a.push(48+b);a.push(43);a.push(47);return a})();var s=function(a){var b={},c,e;c=0;for(e=a.length;c>>8):(la(b&255),la(b>>>8))},na=function(){q=(q<<5^o[m+3-1]&255)&8191;x=p[32768+q];p[m&32767]=x;p[32768+q]=m},Q=function(a,b){B>16-b?(w|=a<>16-B,B+=b-16):(w|=a<a;a++)o[a]=o[a+32768];t-=32768;m-=32768;A-=32768;for(a=0;8192>a;a++)b=p[32768+a],p[32768+a]=32768<=b?b-32768:0;for(a=0;32768>a;a++)b=p[a],p[a]=32768<=b?b-32768:0;c+=32768}r||(a=xa(o,m+y,c),0>=a?r=!0:y+=a)},ya=function(a){var b=L,c=m,e,d=F,i=32506=N&&(b>>=2);do if(e=a,!(o[e+d]!==h||o[e+d-1]!==n||o[e]!==o[c]||o[++e]!==o[c+1])){c+=2;e++;do++c; +while(o[c]===o[++e]&&o[++c]===o[++e]&&o[++c]===o[++e]&&o[++c]===o[++e]&&o[++c]===o[++e]&&o[++c]===o[++e]&&o[++c]===o[++e]&&o[++c]===o[++e]&&cd){t=a;d=e;if(258<=e)break;n=o[c+d-1];h=o[c+d]}}while((a=p[a&32767])>i&&0!==--b);return d},ga=function(a,b){s[P++]=b;0===a?v[b].fc++:(a--,v[$[b]+256+1].fc++,J[(256>a?Y[a]:Y[256+(a>>7)])&255].fc++,u[ia++]=a,aa|=ea);ea<<=1;0===(P&7)&&(da[pa++]=aa,aa=0,ea=1);if(2d;d++)c+=J[d].fc*(5+fa[d]); +c>>=3;if(ia>=1,c<<=1;while(0<--b);return c>>1},Aa=function(a,b){var c=[];c.length=16;var e=0,d;for(d=1;15>=d;d++)e=e+M[d-1]<<1,c[d]=e;for(e=0;e<=b;e++)d=a[e].dl,0!==d&&(a[e].fc=za(c[d]++,d))},ua=function(a){var b=a.dyn_tree,c=a.static_tree,e=a.elems,d,m=-1,i=e;V=0; +Z=573;for(d=0;dV;)d=I[++V]=2>m?++m:0,b[d].fc=1,S[d]=0,W--,null!==c&&(ba-=c[d].dl);a.max_code=m;for(d=V>>1;1<=d;d--)ta(b,d);do d=I[1],I[1]=I[V--],ta(b,1),c=I[1],I[--Z]=d,I[--Z]=c,b[i].fc=b[d].fc+b[c].fc,S[i]=S[d]>S[c]+1?S[d]:S[c]+1,b[d].dl=b[c].dl=i,I[1]=i++,ta(b,1);while(2<=V);I[--Z]=I[1];i=a.dyn_tree;d=a.extra_bits;var e=a.extra_base,c=a.max_code,r=a.max_length,n=a.static_tree,t,h,f,k,q=0;for(h=0;15>=h;h++)M[h]=0;i[I[Z]].dl=0;for(a=Z+1;573> +a;a++)if(t=I[a],h=i[i[t].dl].dl+1,h>r&&(h=r,q++),i[t].dl=h,!(t>c))M[h]++,f=0,t>=e&&(f=d[t-e]),k=i[t].fc,W+=k*(h+f),null!==n&&(ba+=k*(n[t].dl+f));if(0!==q){do{for(h=r-1;0===M[h];)h--;M[h]--;M[h+1]+=2;M[r]--;q-=2}while(0c||(i[d].dl!==h&&(W+=(h-i[d].dl)*i[d].fc,i[d].fc=h),t--)}Aa(b,m)},Ba=function(a,b){var c,e=-1,d,m=a[0].dl,i=0,h=7,r=4;0===m&&(h=138,r=3);a[b+1].dl=65535;for(c=0;c<=b;c++)if(d=m,m=a[c+1].dl,!(++i=i?K[17].fc++:K[18].fc++,i=0,e=d,0===m)?(h=138,r=3):d===m?(h=6,r=3):(h=7,r=4)},Ca=function(){8c?Y[c]:Y[256+(c>>7)])&255,X(h,b),r=fa[h],0!==r)c-=ca[h],Q(c,r);i>>=1}while(e=i?(X(17,K),Q(i-3,3)):(X(18,K),Q(i-11,7));i=0;e=d;0===m?(h=138,r=3):d===m?(h=6,r=3):(h=7,r=4)}},Fa=function(){var a;for(a=0;286>a;a++)v[a].fc=0;for(a=0;30>a;a++)J[a].fc=0;for(a=0;19>a;a++)K[a].fc=0;v[256].fc=1;aa=P=ia=pa=W=ba=0;ea=1},oa=function(a){var b,c,e,d;d=m-A;da[pa]=aa;ua(H);ua(D);Ba(v,H.max_code);Ba(J,D.max_code);ua(U);for(e=18;3<=e&&0===K[va[e]].dl;e--);W+= +3*(e+1)+14;b=W+3+7>>3;c=ba+3+7>>3;c<=b&&(b=c);if(d+4<=b&&0<=A){Q(0+a,3);Ca();ma(d);ma(~d);for(e=0;eb.len&&(t=b.len);for(n=0;ni-h&&(t=i-h);for(n=0;ng;g++){ha[g]=f;for(d= +0;d<1<g;g++){ca[g]=f;for(d=0;d<1<>=7;30>g;g++){ca[g]=f<<7;for(d=0;d<1<=d;d++)M[d]=0;for(d=0;143>=d;)G[d++].dl=8,M[8]++;for(;255>=d;)G[d++].dl=9,M[9]++;for(;279>=d;)G[d++].dl=7,M[7]++;for(;287>=d;)G[d++].dl=8,M[8]++;Aa(G,287);for(d=0;30>d;d++)R[d].dl=5,R[d].fc=za(d,5);Fa()}for(d=0;8192>d;d++)p[32768+d]=0;T=ka[O].max_lazy;N=ka[O].good_length;L=ka[O].max_chain;A=m=0;y=xa(o,0,65536);if(0>=y)r=!0,y= +0;else{for(r=!1;262>y&&!r;)sa();for(d=q=0;2>d;d++)q=(q<<5^o[d]&255)&8191}b=null;h=i=0;3>=O?(F=2,z=0):(z=2,C=0);n=!1}k=!0;if(0===y)return n=!0,0}if((d=Ga(a,c,e))===e)return e;if(n)return d;if(3>=O)for(;0!==y&&null===b;){na();0!==x&&32506>=m-x&&(z=ya(x),z>y&&(z=y));if(3<=z)if(g=ga(m-t,z-3),y-=z,z<=T){z--;do m++,na();while(0!==--z);m++}else m+=z,z=0,q=o[m]&255,q=(q<<5^o[m+1]&255)&8191;else g=ga(0,o[m]&255),y--,m++;g&&(oa(0),A=m);for(;262>y&&!r;)sa()}else for(;0!==y&&null===b;){na();F=z;E=t;z=2;0!==x&& +F=m-x&&(z=ya(x),z>y&&(z=y),3===z&&4096y&&!r;)sa()}0===y&&(0!==C&&ga(0,o[m-1]&255),oa(1),n=!0);return d+Ga(a,d+c,e-d)};this.deflate=function(m,i){var h,t;ja=m;qa=0;"undefined"===typeof i&&(i=6);(h=i)?1>h?h=1:9h;h++)v[h]=new j;J=[];J.length=61;for(h=0;61>h;h++)J[h]=new j;G=[];G.length=288;for(h=0;288>h;h++)G[h]=new j;R=[];R.length=30;for(h=0;30>h;h++)R[h]=new j;K=[];K.length=39;for(h=0;39>h;h++)K[h]=new j;H=new l;D=new l;U=new l;M=[];M.length=16;I=[];I.length=573;S=[];S.length=573;$=[];$.length=256;Y=[];Y.length=512;ha=[];ha.length=29;ca=[];ca.length=30;da=[];da.length=1024}for(var n=Array(1024),f=[];0<(h=Ia(n,0,n.length));){var g=[];g.length=h;for(t= +0;t>8&255])};this.appendUInt32LE=function(f){l.appendArray([f&255,f>>8&255,f>>16&255,f>>24&255])};this.appendString=function(g){f=runtime.concatByteArrays(f, +runtime.byteArrayFromString(g,j))};this.getLength=function(){return f.length};this.getByteArray=function(){return f}}; +// Input 6 +core.RawInflate=function(){var j,l,f=null,g,a,c,b,d,k,e,i,h,n,o,u,s,p,w=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],B=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],A=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],q=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],x=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],E=[16,17,18, +0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],C=function(){this.list=this.next=null},z=function(){this.n=this.b=this.e=0;this.t=null},F=function(a,b,c,d,e,m){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var h=Array(this.BMAX+1),i,r,t,n,f,k,g,q=Array(this.BMAX+1),o,j,p,y=new z,x=Array(this.BMAX);n=Array(this.N_MAX);var E,s=Array(this.BMAX+1),B,A,u;u=this.root=null;for(f=0;ff&&(m=f);for(B=1<(B-=h[k])){this.status=2;this.m=m;return}if(0>(B-=h[f]))this.status=2,this.m=m;else{h[f]+=B;s[1]=k=0;o=h;j=1;for(p=2;0<--f;)s[p++]=k+=o[j++];o=a;f=j=0;do if(0!=(k=o[j++]))n[s[k]++]=f;while(++fE+q[1+n];){E+=q[1+n];n++;A=(A=t-E)>m?m:A;if((r=1<<(k=g-E))>a+1){r-=a+1;for(p=g;++ki&&E>E-q[n],x[n-1][k].e=y.e,x[n-1][k].b=y.b,x[n-1][k].n=y.n,x[n-1][k].t=y.t)}y.b=g-E;j>=b?y.e=99:o[j]o[j]?16:15,y.n=o[j++]): +(y.e=e[o[j]-c],y.n=d[o[j++]-c]);r=1<>E;k>=1)f^=k;for(f^=k;(f&(1<>=a;b-=a},y=function(a,b,c){var f,k,g;if(0==c)return 0;for(g=0;;){m(o);k=h.list[t(o)];for(f=k.e;16e;e++)p[E[e]]= +0;o=7;e=new F(p,19,19,null,null,o);if(0!=e.status)return-1;h=e.root;o=e.m;i=g+j;for(d=f=0;de)p[d++]=f=e;else if(16==e){m(2);e=3+t(2);r(2);if(d+e>i)return-1;for(;0i)return-1;for(;0D;D++)H[D]=8;for(;256>D;D++)H[D]=9;for(;280>D;D++)H[D]=7;for(;288>D;D++)H[D]=8;a=7;D=new F(H,288,257,B,A,a);if(0!=D.status){alert("HufBuild error: "+D.status);G=-1;break b}f=D.root;a=D.m;for(D=0;30>D;D++)H[D]=5;L=5;D=new F(H,30,0,q,x,L);if(1e&&k.setStart(i,k.startOffset-1);k.endContainer===a?k.setEnd(i,e):k.endContainer===i&&k.endOffset>e&&k.setEnd(i,k.endOffset-1)}if(d){for(c=0;c1/f?"-0":""+f)+"."):j(c+" should be "+a+" (of type "+typeof a+"). Was "+f+" (of type "+typeof f+").")}var g=0;this.shouldBeNull=function(a,c){f(a,c,"null")};this.shouldBeNonNull=function(a,c){var b,d;try{d=eval(c)}catch(f){b=f}b?j(c+" should be non-null. Threw exception "+b):null!==d?runtime.log("pass",c+" is non-null."):j(c+" should be non-null. Was "+ +d)};this.shouldBe=f;this.countFailedTests=function(){return g}}; +core.UnitTester=function(){var j=0,l={};this.runTests=function(f,g){function a(b){if(0===b.length)l[c]=e,j+=d.countFailedTests(),g();else{h=b[0];var f=Runtime.getFunctionName(h);runtime.log("Running "+f);o=d.countFailedTests();k.setUp();h(function(){k.tearDown();e[f]=o===d.countFailedTests();a(b.slice(1))})}}var c=Runtime.getFunctionName(f),b,d=new core.UnitTestRunner,k=new f(d),e={},i,h,n,o;if(c.hasOwnProperty(l))runtime.log("Test "+c+" has already run.");else{runtime.log("Running "+c+": "+k.description()); +n=k.tests();for(i=0;i>>8^f;return c^-1}function g(a){return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&15,a>>5&63,(a&31)<<1)}function a(a){var b=a.getFullYear();return 1980>b?0:b-1980<< +25|a.getMonth()+1<<21|a.getDate()<<16|a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1}function c(a,b){var c,e,d,f,h,i,m,n=this;this.load=function(b){if(void 0!==n.data)b(null,n.data);else{var d=h+34+c+e+256;d+m>o&&(d=o-m);runtime.read(a,m,d,function(c,e){if(c)b(c,e);else a:{var d=e,m=new core.ByteArray(d),k=m.readUInt32LE(),g;if(67324752!==k)b("File entry signature is wrong."+k.toString()+" "+d.length.toString(),null);else{m.pos+=22;k=m.readUInt16LE();g=m.readUInt16LE();m.pos+=k+g;if(f){d=d.slice(m.pos, +m.pos+h);if(h!==d.length){b("The amount of compressed bytes read was "+d.length.toString()+" instead of "+h.toString()+" for "+n.filename+" in "+a+".",null);break a}d=s(d,i)}else d=d.slice(m.pos,m.pos+i);i!==d.length?b("The amount of bytes read was "+d.length.toString()+" instead of "+i.toString()+" for "+n.filename+" in "+a+".",null):(n.data=d,b(null,d))}}})}};this.set=function(a,b,c,e){n.filename=a;n.data=b;n.compressed=c;n.date=e};this.error=null;b&&(33639248!==b.readUInt32LE()?this.error="Central directory entry has wrong signature at position "+ +(b.pos-4).toString()+' for file "'+a+'": '+b.data.length.toString():(b.pos+=6,f=b.readUInt16LE(),this.date=g(b.readUInt32LE()),b.readUInt32LE(),h=b.readUInt32LE(),i=b.readUInt32LE(),c=b.readUInt16LE(),e=b.readUInt16LE(),d=b.readUInt16LE(),b.pos+=8,m=b.readUInt32LE(),this.filename=runtime.byteArrayToString(b.data.slice(b.pos,b.pos+c),"utf8"),b.pos+=c+e+d))}function b(a,b){if(22!==a.length)b("Central directory length should be 22.",p);else{var e=new core.ByteArray(a),d;d=e.readUInt32LE();101010256!== +d?b("Central directory signature is wrong: "+d.toString(),p):0!==e.readUInt16LE()?b("Zip files with non-zero disk numbers are not supported.",p):0!==e.readUInt16LE()?b("Zip files with non-zero disk numbers are not supported.",p):(d=e.readUInt16LE(),u=e.readUInt16LE(),d!==u?b("Number of entries is inconsistent.",p):(d=e.readUInt32LE(),e=e.readUInt16LE(),e=o-22-d,runtime.read(j,e,o-e,function(a,e){a:{var d=new core.ByteArray(e),f,m;n=[];for(f=0;fo?l("File '"+ +j+"' cannot be read.",p):runtime.read(j,o-22,22,function(a,c){a||null===l?l(a,p):b(c,l)})})}; +// Input 12 +xmldom.LSSerializerFilter=function(){}; +// Input 13 +"function"!==typeof Object.create&&(Object.create=function(j){var l=function(){};l.prototype=j;return new l}); +xmldom.LSSerializer=function(){function j(f,g){var a="",c=Object.create(f),b=l.filter?l.filter.acceptNode(g):1,d;if(1===b){d="";var k=g.attributes,e,i,h,n="",o;if(k){c[g.namespaceURI]!==g.prefix&&(c[g.namespaceURI]=g.prefix);d+="<"+g.nodeName;e=k.length;for(i=0;i"}a+=d}if(1===b||3===b){for(d=g.firstChild;d;)a+=j(c,d),d=d.nextSibling;g.nodeValue&&(a+=g.nodeValue)}1===b&&(c="",1===g.nodeType&&(c+=""),a+=c);return a}var l=this;this.filter=null;this.writeToString=function(f,g){if(!f)return"";var a;if(g){a=g;var c={},b;for(b in a)a.hasOwnProperty(b)&&(c[a[b]]=b);a=c}else a={};return j(a, +f)}}; +// Input 14 +xmldom.RelaxNGParser=function(){function j(a,b){this.message=function(){b&&(a+=1===b.nodeType?" Element ":" Node ",a+=b.nodeName,b.nodeValue&&(a+=" with value '"+b.nodeValue+"'"),a+=".");return a}}function l(a){if(2>=a.e.length)return a;var b={name:a.name,e:a.e.slice(0,2)};return l({name:a.name,e:[b].concat(a.e.slice(2))})}function f(a){var a=a.split(":",2),b="",c;1===a.length?a=["",a[0]]:b=a[0];for(c in d)d[c]===b&&(a[0]=c);return a}function g(a,b){for(var c=0,d,k,j=a.name;a.e&&c=c.length)return b;0===f&&(f=0);for(var h=c.item(f);h.namespaceURI===e;){f+=1;if(f>=c.length)return b;h=c.item(f)}return h=d(a,b.attDeriv(a,c.item(f)),c,f+1)}function k(a,b,c){c.e[0].a?(a.push(c.e[0].text),b.push(c.e[0].a.ns)):k(a,b,c.e[0]);c.e[1].a?(a.push(c.e[1].text),b.push(c.e[1].a.ns)): +k(a,b,c.e[1])}var e="http://www.w3.org/2000/xmlns/",i,h,n,o,u,s,p,w,B,A,q={type:"notAllowed",nullable:!1,hash:"notAllowed",textDeriv:function(){return q},startTagOpenDeriv:function(){return q},attDeriv:function(){return q},startTagCloseDeriv:function(){return q},endTagDeriv:function(){return q}},x={type:"empty",nullable:!0,hash:"empty",textDeriv:function(){return q},startTagOpenDeriv:function(){return q},attDeriv:function(){return q},startTagCloseDeriv:function(){return x},endTagDeriv:function(){return q}}, +E={type:"text",nullable:!0,hash:"text",textDeriv:function(){return E},startTagOpenDeriv:function(){return q},attDeriv:function(){return q},startTagCloseDeriv:function(){return E},endTagDeriv:function(){return q}},C,z,F;i=g("choice",function(a,b){if(a===q)return b;if(b===q||a===b)return a},function(b,c){var d={},e;a(d,{p1:b,p2:c});c=b=void 0;for(e in d)d.hasOwnProperty(e)&&(void 0===b?b=d[e]:c=void 0===c?d[e]:i(c,d[e]));return function(a,b){return{type:"choice",p1:a,p2:b,nullable:a.nullable||b.nullable, +textDeriv:function(c,d){return i(a.textDeriv(c,d),b.textDeriv(c,d))},startTagOpenDeriv:f(function(c){return i(a.startTagOpenDeriv(c),b.startTagOpenDeriv(c))}),attDeriv:function(c,d){return i(a.attDeriv(c,d),b.attDeriv(c,d))},startTagCloseDeriv:j(function(){return i(a.startTagCloseDeriv(),b.startTagCloseDeriv())}),endTagDeriv:j(function(){return i(a.endTagDeriv(),b.endTagDeriv())})}}(b,c)});h=function(a,b,c){return function(){var d={},e=0;return function(f,h){var i=b&&b(f,h),k,g;if(void 0!==i)return i; +i=f.hash||f.toString();k=h.hash||h.toString();i=f&&b.push(l(a.substring(c,d)))):"["===a[d]&&(0>=f&&(c=d+1),f+=1),d+=1;return d};f.prototype.next=function(){};f.prototype.reset=function(){};i=function(b,e,f){var g,h,i,j;for(g= +0;g text|list-item > text|list",c-=1;try{a.insertRule(b+ +" > list-item:before{"+d+"}",a.cssRules.length)}catch(e){throw e;}}function e(a,f,g,j){if("list"===f)for(var l=j.firstChild,m,t;l;){if(l.namespaceURI===n)if(m=l,"list-level-style-number"===l.localName){t=m;var r=t.getAttributeNS(h,"num-format"),o=t.getAttributeNS(h,"num-suffix"),s="",s={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"},u="",u=t.getAttributeNS(h,"num-prefix")||"",u=s.hasOwnProperty(r)?u+(" counter(list, "+s[r]+")"):r?u+("'"+r+"';"):u+" ''";o&&(u+=" '"+o+ +"'");t=s="content: "+u+";";k(a,g,m,t)}else"list-level-style-image"===l.localName?(t="content: none;",k(a,g,m,t)):"list-level-style-bullet"===l.localName&&(t="content: '"+m.getAttributeNS(n,"bullet-char")+"';",k(a,g,m,t));l=l.nextSibling}else{g=c(f,g,j).join(",");l="";if(m=b(j,h,"text-properties")){t=""+d(m,p);r=m.getAttributeNS(h,"text-underline-style");"solid"===r&&(t+="text-decoration: underline;");if(r=m.getAttributeNS(h,"font-name"))(r='"'+r+'"')&&(t+="font-family: "+r+";");l+=t}if(m=b(j,h,"paragraph-properties")){t= +m;m=""+d(t,B);t=t.getElementsByTagNameNS(h,"background-image");if(0c)break;e=e.nextSibling}a.insertBefore(b,e)}}}function a(a){this.OdfContainer=a}function c(a,b,c){var d=this;this.size=0;this.type=null;this.name=a;this.container=b;this.onchange=this.onreadystatechange=this.document=this.mimetype=this.url=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.load=function(){var b=u[a];this.mimetype=b;c.loadAsDataURL(a,b,function(a,b){d.url=b;if(d.onchange)d.onchange(d);if(d.onstatereadychange)d.onstatereadychange(d)})}; +this.abort=function(){}}function b(){this.length=0;this.item=function(){}}var d=new odf.StyleInfo,k=new odf.Style2CSS,e="urn:oasis:names:tc:opendocument:xmlns:office:1.0",i="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0",h="meta,settings,scripts,font-face-decls,styles,automatic-styles,master-styles,body".split(","),n=new core.Base64,o=new odf.FontLoader,u={};a.prototype=new function(){};a.prototype.constructor=a;a.namespaceURI=e;a.localName="document";c.prototype.load=function(){};c.prototype.getUrl= +function(){return this.data?"data:;base64,"+n.toBase64(this.data):null};odf.OdfContainer=function p(d,h){function l(a){for(var b=a.firstChild,c;b;)c=b.nextSibling,1===b.nodeType?l(b):7===b.nodeType&&a.removeChild(b),b=c}function n(a){var b=v.rootElement.ownerDocument,c;if(a){l(a.documentElement);try{c=b.importNode(a.documentElement,!0)}catch(d){}}return c}function x(a){v.state=a;if(v.onchange)v.onchange(v);if(v.onstatereadychange)v.onstatereadychange(v)}function E(a){var a=n(a),b=v.rootElement;!a|| +"document-styles"!==a.localName||a.namespaceURI!==e?x(p.INVALID):(b.fontFaceDecls=j(a,e,"font-face-decls"),g(b,b.fontFaceDecls),b.styles=j(a,e,"styles"),g(b,b.styles),b.automaticStyles=j(a,e,"automatic-styles"),g(b,b.automaticStyles),b.masterStyles=j(a,e,"master-styles"),g(b,b.masterStyles),o.loadFonts(b.fontFaceDecls,J,null))}function C(a){var a=n(a),b,c,d;if(!a||"document-content"!==a.localName||a.namespaceURI!==e)x(p.INVALID);else{b=v.rootElement;c=j(a,e,"font-face-decls");if(b.fontFaceDecls&& +c)for(d=c.firstChild;d;)b.fontFaceDecls.appendChild(d),d=c.firstChild;else c&&(b.fontFaceDecls=c,g(b,c));c=j(a,e,"automatic-styles");if(b.automaticStyles&&c)for(d=c.firstChild;d;)b.automaticStyles.appendChild(d),d=c.firstChild;else c&&(b.automaticStyles=c,g(b,c));b.body=j(a,e,"body");g(b,b.body)}}function z(a){var a=n(a),b;if(a&&!("document-meta"!==a.localName||a.namespaceURI!==e))b=v.rootElement,b.meta=j(a,e,"meta"),g(b,b.meta)}function F(a){var a=n(a),b;if(a&&!("document-settings"!==a.localName|| +a.namespaceURI!==e))b=v.rootElement,b.settings=j(a,e,"settings"),g(b,b.settings)}function m(a,b){J.loadAsDOM(a,b)}function t(){m("styles.xml",function(a,b){E(b);v.state!==p.INVALID&&m("content.xml",function(a,b){C(b);v.state!==p.INVALID&&m("meta.xml",function(a,b){z(b);v.state!==p.INVALID&&m("settings.xml",function(a,b){b&&F(b);m("META-INF/manifest.xml",function(a,b){if(b){var c=n(b),d;if(c&&!("manifest"!==c.localName||c.namespaceURI!==i)){d=v.rootElement;d.manifest=c;for(c=d.manifest.firstChild;c;)1=== +c.nodeType&&"file-entry"===c.localName&&c.namespaceURI===i&&(u[c.getAttributeNS(i,"full-path")]=c.getAttributeNS(i,"media-type")),c=c.nextSibling}}v.state!==p.INVALID&&x(p.DONE)})})})})})}function r(a,b){var c="",d;for(d in b)b.hasOwnProperty(d)&&(c+=" xmlns:"+d+'="'+b[d]+'"');return''}function y(){var a=k.namespaces,b=new xmldom.LSSerializer,c=r("document-meta",a);b.filter=new f(v.rootElement);c+=b.writeToString(v.rootElement.meta, +a);return c+""}function L(){var a=k.namespaces,b=new xmldom.LSSerializer,c=r("document-settings",a);b.filter=new f(v.rootElement);c+=b.writeToString(v.rootElement.settings,a);return c+""}function T(){var a=k.namespaces,b=new xmldom.LSSerializer,c=r("document-styles",a);b.filter=new f(v.rootElement,v.rootElement.masterStyles);c+=b.writeToString(v.rootElement.fontFaceDecls,a);c+=b.writeToString(v.rootElement.styles,a);c+=b.writeToString(v.rootElement.automaticStyles, +a);c+=b.writeToString(v.rootElement.masterStyles,a);return c+""}function O(){var a=k.namespaces,b=new xmldom.LSSerializer,c=r("document-content",a);b.filter=new f(v.rootElement,v.rootElement.body);c+=b.writeToString(v.rootElement.automaticStyles,a);c+=b.writeToString(v.rootElement.body,a);return c+""}function N(a,b){runtime.loadXML(a,function(a,c){if(a)b(a);else{var d=n(c);!d||"document"!==d.localName||d.namespaceURI!==e?x(p.INVALID):(v.rootElement= +d,d.fontFaceDecls=j(d,e,"font-face-decls"),d.styles=j(d,e,"styles"),d.automaticStyles=j(d,e,"automatic-styles"),d.masterStyles=j(d,e,"master-styles"),d.body=j(d,e,"body"),d.meta=j(d,e,"meta"),x(p.DONE))}})}var v=this,J=null;this.onstatereadychange=h;this.parts=this.rootElement=this.state=this.onchange=null;this.getPart=function(a){return new c(a,v,J)};this.save=function(a){var b;b=runtime.byteArrayFromString(L(),"utf8");J.save("settings.xml",b,!0,new Date);b=runtime.byteArrayFromString(y(),"utf8"); +J.save("meta.xml",b,!0,new Date);b=runtime.byteArrayFromString(T(),"utf8");J.save("styles.xml",b,!0,new Date);b=runtime.byteArrayFromString(O(),"utf8");J.save("content.xml",b,!0,new Date);J.write(function(b){a(b)})};this.state=p.LOADING;this.rootElement=function(a){var b=document.createElementNS(a.namespaceURI,a.localName),c,a=new a;for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}(a);this.parts=new b(this);J=new core.Zip(d,function(a,b){J=b;a?N(d,function(b){a&&(J.error=a+"\n"+b,x(p.INVALID))}): +t()})};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getContainer=function(a){return new odf.OdfContainer(a,null)};return odf.OdfContainer}(); +// Input 24 +odf.Formatting=function(){function j(f){function g(a,b){for(var d=a&&a.firstChild;d&&b;)d=d.nextSibling,b-=1;return d}var a=g(f.startContainer,f.startOffset);g(f.endContainer,f.endOffset);this.next=function(){return null===a?a:null}}var l=new odf.StyleInfo;this.setOdfContainer=function(){};this.isCompletelyBold=function(){return!1};this.getAlignment=function(f){this.getParagraphStyles(f)};this.getParagraphStyles=function(f){var g,a,c,b=[];for(g=0;ga?-1:a-1})};a.slideChange=function(c){var b=a.getPages(a.odf_canvas.odfContainer().rootElement),d=-1,f=0;b.forEach(function(a){a=a[1];a.hasAttribute("slide_current")&&(d=f,a.removeAttribute("slide_current"));f+=1});c=c(d,b.length);-1===c&&(c=d); +b[c][1].setAttribute("slide_current","1");document.getElementById("pagelist").selectedIndex=c;"cont"===a.slide_mode&&window.scrollBy(0,b[c][1].getBoundingClientRect().top-30)};a.selectSlide=function(c){a.slideChange(function(a,d){return c>=d||0>c?-1:c})};a.scrollIntoContView=function(c){var b=a.getPages(a.odf_canvas.odfContainer().rootElement);0!==b.length&&window.scrollBy(0,b[c][1].getBoundingClientRect().top-30)};a.getPages=function(a){var a=a.getElementsByTagNameNS(f("draw"),"page"),b=[],d;for(d= +0;dd}}var a=l.node().ownerDocument,c=new core.Cursor(j,a);this.movePointForward=function(a){f(a,l.stepForward)};this.movePointBackward=function(a){f(a,l.stepBackward)};this.moveLineForward=function(a){j.modify?j.modify(a?"extend":"move","forward", +"line"):f(a,g)};this.moveLineBackward=function(a){j.modify?j.modify(a?"extend":"move","backward","line"):f(a,function(){})};return this}; +// Input 29 +runtime.loadClass("core.PointWalker");runtime.loadClass("core.Cursor"); +gui.XMLEdit=function(j,l){function f(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent?a.attachEvent("on"+b,c):a["on"+b]=c}function g(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function a(){var a=j.ownerDocument.defaultView.getSelection();a&&!(0>=a.rangeCount)&&s&&(a=a.getRangeAt(0),s.setPoint(a.startContainer,a.startOffset))}function c(){var a=j.ownerDocument.defaultView.getSelection(),b,c;a.removeAllRanges();s&&s.node()&&(b=s.node(),c=b.ownerDocument.createRange(), +c.setStart(b,s.position()),c.collapse(!0),a.addRange(c))}function b(b){var d=b.charCode||b.keyCode;if(s=null,s&&37===d)a(),s.stepBackward(),c();else if(16<=d&&20>=d||33<=d&&40>=d)return;g(b)}function d(){}function k(a){j.ownerDocument.defaultView.getSelection().getRangeAt(0);g(a)}function e(a){for(var b=a.firstChild;b&&b!==a;)1===b.nodeType&&e(b),b=b.nextSibling||b.parentNode;var c,d,f,b=a.attributes;c="";for(f=b.length-1;0<=f;f-=1)d=b.item(f),c=c+" "+d.nodeName+'="'+d.nodeValue+'"';a.setAttribute("customns_name", +a.nodeName);a.setAttribute("customns_atts",c);b=a.firstChild;for(d=/^\s*$/;b&&b!==a;)c=b,b=b.nextSibling||b.parentNode,3===c.nodeType&&d.test(c.nodeValue)&&c.parentNode.removeChild(c)}function i(a,b){for(var c=a.firstChild,d,e,f;c&&c!==a;){if(1===c.nodeType){i(c,b);d=c.attributes;for(f=d.length-1;0<=f;f-=1)e=d.item(f),"http://www.w3.org/2000/xmlns/"===e.namespaceURI&&!b[e.nodeValue]&&(b[e.nodeValue]=e.localName)}c=c.nextSibling||c.parentNode}}function h(){var a=j.ownerDocument.createElement("style"), +b;b={};i(j,b);var c={},d,e,f=0;for(d in b)if(b.hasOwnProperty(d)&&d){e=b[d];if(!e||c.hasOwnProperty(e)||"xmlns"===e){do e="ns"+f,f+=1;while(c.hasOwnProperty(e));b[d]=e}c[e]=!0}a.type="text/css";b="@namespace customns url(customns);\n"+n;a.appendChild(j.ownerDocument.createTextNode(b));l=l.parentNode.replaceChild(a,l)}var n,o,u,s=null;j.id||(j.id="xml"+(""+Math.random()).substring(2));o="#"+j.id+" ";n=o+"*,"+o+":visited, "+o+":link {display:block; margin: 0px; margin-left: 10px; font-size: medium; color: black; background: white; font-variant: normal; font-weight: normal; font-style: normal; font-family: sans-serif; text-decoration: none; white-space: pre-wrap; height: auto; width: auto}\n"+ +o+":before {color: blue; content: '<' attr(customns_name) attr(customns_atts) '>';}\n"+o+":after {color: blue; content: '';}\n"+o+"{overflow: auto;}\n";(function(a){f(a,"click",k);f(a,"keydown",b);f(a,"keypress",d);f(a,"drop",g);f(a,"dragend",g);f(a,"beforepaste",g);f(a,"paste",g)})(j);this.updateCSS=h;this.setXML=function(a){a=a.documentElement||a;u=a=j.ownerDocument.importNode(a,true);for(e(a);j.lastChild;)j.removeChild(j.lastChild);j.appendChild(a);h();s=new core.PointWalker(a)}; +this.getXML=function(){return u}}; +// Input 30 +(function(){return"core/Async.js,core/Base64.js,core/ByteArray.js,core/ByteArrayWriter.js,core/Cursor.js,core/JSLint.js,core/PointWalker.js,core/RawDeflate.js,core/RawInflate.js,core/UnitTester.js,core/Zip.js,gui/Caret.js,gui/SelectionMover.js,gui/XMLEdit.js,gui/PresenterUI.js,odf/FontLoader.js,odf/Formatting.js,odf/OdfCanvas.js,odf/OdfContainer.js,odf/Style2CSS.js,odf/StyleInfo.js,xmldom/LSSerializer.js,xmldom/LSSerializerFilter.js,xmldom/OperationalTransformDOM.js,xmldom/OperationalTransformInterface.js,xmldom/RelaxNG.js,xmldom/RelaxNG2.js,xmldom/RelaxNGParser.js,xmldom/XPath.js".split(",")})(); diff --git a/apps/files_odfviewer/src/.gitignore b/apps/files_odfviewer/src/.gitignore new file mode 100644 index 0000000000..378eac25d3 --- /dev/null +++ b/apps/files_odfviewer/src/.gitignore @@ -0,0 +1 @@ +build diff --git a/apps/files_odfviewer/src/update.sh b/apps/files_odfviewer/src/update.sh new file mode 100755 index 0000000000..dad9bf35fb --- /dev/null +++ b/apps/files_odfviewer/src/update.sh @@ -0,0 +1,9 @@ +cd webodf +git pull +cd .. +rm -Rf build +mkdir build +cd build +cmake ../webodf +make webodf.js webodf-debug.js +cp webodf/webodf*.js ../../js/ diff --git a/apps/files_odfviewer/src/webodf/.gitignore b/apps/files_odfviewer/src/webodf/.gitignore new file mode 100644 index 0000000000..5f9afa1071 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/.gitignore @@ -0,0 +1,17 @@ +#android/bin +#android/gen +nativeQtClient/nativeQtClient.pro.user +programs/firefoxextension/content/webodf.js +programs/firefoxextension/content/webodf.css +programs/firefoxextension/install.rdf +programs/ios/WebODF.xcodeproj/project.xcworkspace +programs/ios/WebODF.xcodeproj/xcuserdata +programs/ios/www/ZoomIn.png +programs/ios/www/ZoomOut.png +programs/ios/www/app/ +programs/ios/www/sencha-touch.css +programs/ios/www/sencha-touch.js +programs/ios/www/webodf.css +programs/ios/www/webodf.js +.DS_Store +programs/ios/build/ diff --git a/apps/files_odfviewer/src/webodf/.gitmodules b/apps/files_odfviewer/src/webodf/.gitmodules new file mode 100644 index 0000000000..0d440b2a36 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/.gitmodules @@ -0,0 +1,9 @@ +[submodule "webodf/extjs"] + path = webodf/extjs + url = git://github.com/probonogeek/extjs.git +[submodule "simplerevisionserver/pywebdav"] + path = simplerevisionserver/pywebdav + url = ssh://vandenoever@heap.kogmbh.net/srv/git/pywebdav +[submodule "extjs"] + path = extjs + url = git://github.com/probonogeek/extjs.git diff --git a/apps/files_odfviewer/src/webodf/CMakeLists.txt b/apps/files_odfviewer/src/webodf/CMakeLists.txt new file mode 100644 index 0000000000..dfac345df1 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/CMakeLists.txt @@ -0,0 +1,160 @@ +# WebODF is mostly a JavaScript project. CMake needs to know about the C++ parts +project (WebODF C CXX) +# version 2.8.2 is needed to have support for zip files in external projects +cmake_minimum_required(VERSION 2.8.2) + +# At this point, the version number that is used throughout is defined +set(WEBODF_VERSION 0.3.0) + +# This makefile 'compiles' WebODF using various tools, instruments the code and +# builds and packages programs that use WebODF. + +# Find installed dependencies +find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtWebKit) +if (NOT QT4_FOUND) + message(WARNING "Qt4 with modules QtCore QtGui QtXml QtNetwork QtWebKit was not found. qtjsruntime will no be built.") +endif (NOT QT4_FOUND) + +# java runtime is needed for Closure Compiler +find_package(Java COMPONENTS Runtime) + +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "Compiling in the source directortory is not supported. Use for example 'mkdir build; cd build; cmake ..'.") +endif (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + +# Tools must be obtained to work with: +include (ExternalProject) + +if(Java_JAVA_EXECUTABLE) + # Closure Compiler + ExternalProject_Add( + ClosureCompiler + URL "http://closure-compiler.googlecode.com/files/compiler-20120305.tar.gz" + URL_MD5 513344df6f18bfa00b17f034cabf897d + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + set(CLOSURE_JAR ${CMAKE_BINARY_DIR}/ClosureCompiler-prefix/src/ClosureCompiler/compiler.jar) +endif(Java_JAVA_EXECUTABLE) + +# Rhino +if(Java_JAVA_EXECUTABLE) + ExternalProject_Add( + Rhino + URL "http://ftp.mozilla.org/pub/js/rhino1_7R3.zip" + URL_MD5 99d94103662a8d0b571e247a77432ac5 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + set(RHINO ${CMAKE_BINARY_DIR}/Rhino-prefix/src/Rhino/js.jar) +endif(Java_JAVA_EXECUTABLE) + +# JSDoc +ExternalProject_Add( + JsDoc + URL "http://jsdoc-toolkit.googlecode.com/files/jsdoc_toolkit-2.4.0.zip" + URL_MD5 a8f78f5ecd24b54501147b2af341a231 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" +) +set(JSDOCDIR ${CMAKE_BINARY_DIR}/JsDoc-prefix/src/JsDoc/jsdoc-toolkit) + +# Node.JS +ExternalProject_Add( + NodeJS + URL "http://nodejs.org/dist/v0.6.15/node-v0.6.15.tar.gz" + URL_MD5 852cfb1ed8125a4cdba456446d869d19 + CONFIGURE_COMMAND "./configure" + BUILD_IN_SOURCE 1 + INSTALL_COMMAND "" +) +set(NODE ${CMAKE_BINARY_DIR}/NodeJS-prefix/src/NodeJS/out/Release/node) + +# JSCoverage +ExternalProject_Add( + JSCoverage + URL "http://siliconforks.com/jscoverage/download/jscoverage-0.5.1.tar.bz2" + URL_MD5 a70d79a6759367fbcc0bcc18d6866ff3 + PATCH_COMMAND patch -p0 < ${CMAKE_CURRENT_SOURCE_DIR}/JSCoverage.patch + CONFIGURE_COMMAND "./configure" + BUILD_IN_SOURCE 1 + INSTALL_COMMAND "" +) +set(JSCOVERAGE ${CMAKE_BINARY_DIR}/JSCoverage-prefix/src/JSCoverage/jscoverage) + +# Android +if (NOT ANDROID_SDK_DIR) + find_path(ANDROID_SDK_DIR platform-tools/aapt) +endif(NOT ANDROID_SDK_DIR) +if (NOT ANT) + find_file(ANT NAMES ant ant.exe /usr/bin /usr/local/bin) +endif(NOT ANT) + + + +set(LIBJSFILES lib/packages.js lib/runtime.js lib/core/Base64.js + lib/core/RawDeflate.js lib/core/ByteArray.js + lib/core/ByteArrayWriter.js lib/core/RawInflate.js + lib/core/Cursor.js lib/core/UnitTester.js + lib/core/PointWalker.js lib/core/Async.js + lib/core/Zip.js + + lib/xmldom/LSSerializerFilter.js lib/xmldom/LSSerializer.js + lib/xmldom/RelaxNGParser.js lib/xmldom/RelaxNG.js + lib/xmldom/RelaxNG2.js lib/xmldom/OperationalTransformInterface.js + lib/xmldom/OperationalTransformDOM.js + lib/xmldom/XPath.js + + lib/odf/StyleInfo.js lib/odf/Style2CSS.js + lib/odf/FontLoader.js lib/odf/OdfContainer.js + lib/odf/Formatting.js lib/odf/OdfCanvas.js + + lib/gui/PresenterUI.js lib/gui/Caret.js + lib/gui/SelectionMover.js lib/gui/XMLEdit.js + + lib/manifest.js +) + +set(HTML5UIFILES + app/app.js app/controller/Files.js app/model/FileSystem.js + app/views/FileDetail.js app/views/FilesList.js app/views/OdfView.js + app/views/Viewport.js sencha-touch.css sencha-touch.js + app/store/FileStore.js + ZoomOut.png ZoomIn.png go-previous.png go-next.png + zoom-fit-width.png zoom-fit-best.png zoom-fit-height.png +) + +add_subdirectory(webodf) +add_subdirectory(programs) + +# package webodf +set(WEBODFZIP webodf-${WEBODF_VERSION}.zip) +set(WEBODFZIP_FILES + ${CMAKE_BINARY_DIR}/webodf/webodf-debug.js + ${CMAKE_BINARY_DIR}/webodf/webodf.js + ${CMAKE_SOURCE_DIR}/webodf/webodf.css +) +add_custom_command( + OUTPUT ${WEBODFZIP} + # zip using javascript code running in node.js + COMMAND ${NODE} ARGS webodf/lib/runtime.js packwebodf.js + ${CMAKE_BINARY_DIR}/${WEBODFZIP} +#input files + ${WEBODFZIP_FILES} +#output files + webodf-debug.js + webodf.js + webodf.css + DEPENDS NodeJS + packwebodf.js + ${WEBODFZIP_FILES} + webodf-debug.js + webodf.js + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +) +add_custom_target(zip ALL DEPENDS ${WEBODFZIP}) + +# vim:expandtab diff --git a/apps/files_odfviewer/src/webodf/JSCoverage.patch b/apps/files_odfviewer/src/webodf/JSCoverage.patch new file mode 100644 index 0000000000..b769f40b9d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/JSCoverage.patch @@ -0,0 +1,13 @@ +--- ./util.c_ 2011-04-20 11:22:46.558521731 +0200 ++++ ./util.c 2011-04-20 11:23:23.999880771 +0200 +@@ -478,6 +478,10 @@ + p->next = head; + head = p; + } ++ else if (S_ISDIR(buf.st_mode)) { ++ head = recursive_dir_list(root, entry_wrt_root, head); ++ free(entry_wrt_root); ++ } + else { + fatal("refusing to follow symbolic link: %s", entry); + } diff --git a/apps/files_odfviewer/src/webodf/packwebodf.js b/apps/files_odfviewer/src/webodf/packwebodf.js new file mode 100644 index 0000000000..3a0d76c692 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/packwebodf.js @@ -0,0 +1,93 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true*/ +runtime.loadClass("core.Zip"); +runtime.loadClass("core.Base64"); + +function addFiles(zip, pos, inputfiles, zipfiles, callback) { + "use strict"; + if (inputfiles.length !== zipfiles.length) { + return callback( + "Arrays inputfiles and zipfiles should have the same length."); + } + if (pos >= inputfiles.length) { + zip.write(function (err) { + return callback(err); + }); + return; + } + var inputfile = inputfiles[pos], + zipmemberpath = zipfiles[pos]; + runtime.readFile(inputfile, "binary", function (err, data) { + var base64; + if (err) { + return callback(err); + } + zip.save(zipmemberpath, data, false, new Date()); + addFiles(zip, pos + 1, inputfiles, zipfiles, callback); + }); +} + +function usage() { + "use strict"; + runtime.log("Usage:"); +} + +/** + * This script takes 1+2n arguments + * First argument is the name of the target zip file. + * The next n arguments are the input files. The last n arguments are the + * names of the files in the zip file. + */ +if (arguments.length % 2 !== 0) { + runtime.log("Wrong number of arguments."); + usage(); + runtime.exit(1); +} +var args = arguments, + n = (args.length - 2) / 2, + zipfilename = args[1], + inputmembers = [], + zipmembers = [], + i, + zip = new core.Zip(zipfilename, null); +for (i = 0; i < n; i += 1) { + inputmembers[i] = args[2 + i]; + zipmembers[i] = args[2 + n + i]; +} +addFiles(zip, 0, inputmembers, zipmembers, function (err) { + "use strict"; + if (err) { + runtime.log(err); + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/CMakeLists.txt new file mode 100644 index 0000000000..4621a25d67 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/CMakeLists.txt @@ -0,0 +1,30 @@ +macro(COPY_FILES _varname _srcdir _tgtdir) + foreach(_file ${ARGN}) + GET_FILENAME_COMPONENT(_subdir ${_file} PATH) + FILE(MAKE_DIRECTORY ${_tgtdir}/${_subdir}) + add_custom_command( + OUTPUT ${_tgtdir}/${_file} + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different + ${_srcdir}/${_file} + ${_tgtdir}/${_file} + DEPENDS + ${_srcdir}/${_file} + ) + set(${_varname} ${${_varname}} ${_tgtdir}/${_file}) + endforeach(_file) +endmacro(COPY_FILES _directory _files) + +if(QT4_FOUND) + add_subdirectory(qtjsruntime) + add_subdirectory(nativeQtClient) + add_subdirectory(docnosis) +endif(QT4_FOUND) + +if(ANDROID_SDK_DIR AND ANT) + add_subdirectory(android) +endif(ANDROID_SDK_DIR AND ANT) + +add_subdirectory(firefoxextension) + +add_subdirectory(touchui) +add_subdirectory(playbook) diff --git a/apps/files_odfviewer/src/webodf/programs/android/AndroidManifest.xml b/apps/files_odfviewer/src/webodf/programs/android/AndroidManifest.xml new file mode 100644 index 0000000000..491bbb80a2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/android/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/android/CMakeLists.txt new file mode 100644 index 0000000000..b16c5a2f69 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/CMakeLists.txt @@ -0,0 +1,41 @@ +set(ANDROID_JAR ${ANDROID_SDK_DIR}/platforms/android-8/android.jar) + +COPY_FILES(APKDEPS ${CMAKE_SOURCE_DIR}/programs/touchui + ${CMAKE_CURRENT_BINARY_DIR}/assets/www ${HTML5UIFILES}) +COPY_FILES(APKDEPS ${CMAKE_CURRENT_SOURCE_DIR}/assets/www + ${CMAKE_CURRENT_BINARY_DIR}/assets/www + index.html icon.png phonegap-1.4.1.js) +COPY_FILES(APKDEPS ${CMAKE_CURRENT_SOURCE_DIR}/res + ${CMAKE_CURRENT_BINARY_DIR}/res + drawable-hdpi/ic_launcher.png drawable-ldpi/ic_launcher.png + drawable/icon.png drawable-mdpi/ic_launcher.png values/strings.xml + xml/phonegap.xml xml/plugins.xml layout/selector.xml + layout/main.xml layout/listitem.xml) +COPY_FILES(APKDEPS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + src/org/webodf/WebODFActivity.java libs/phonegap-1.4.1.jar + AndroidManifest.xml) +COPY_FILES(APKDEPS ${CMAKE_SOURCE_DIR}/webodf + ${CMAKE_CURRENT_BINARY_DIR}/assets/www webodf.css) +COPY_FILES(APKDEPS ${CMAKE_BINARY_DIR}/webodf + ${CMAKE_CURRENT_BINARY_DIR}/assets/www webodf.js) + +set(WEBODFAPK ${CMAKE_CURRENT_BINARY_DIR}/bin/WebODF-debug.apk) +add_custom_command( + OUTPUT ${WEBODFAPK} + COMMAND ${ANDROID_SDK_DIR}/tools/android + ARGS update project --path . --target android-7 --name WebODF + COMMAND ${ANT} + ARGS -lib ${CMAKE_CURRENT_SOURCE_DIR}/libs/phonegap-1.4.1.jar debug + DEPENDS ${APKDEPS} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +add_custom_target(apk ALL DEPENDS ${WEBODFAPK}) +set(WEBODFRELEASEAPK ${CMAKE_CURRENT_BINARY_DIR}/bin/WebODF-release.apk) +add_custom_command( + OUTPUT ${WEBODFRELEASEAPK} + COMMAND ${ANT} + ARGS -lib ${CMAKE_CURRENT_SOURCE_DIR}/libs/phonegap-1.4.1.jar release + DEPENDS ${WEBODFAPK} webodf.js + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +add_custom_target(releaseapk ALL DEPENDS ${WEBODFRELEASEAPK}) diff --git a/apps/files_odfviewer/src/webodf/programs/android/assets/www/config.xml b/apps/files_odfviewer/src/webodf/programs/android/assets/www/config.xml new file mode 100644 index 0000000000..21b5ca9ecc --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/assets/www/config.xml @@ -0,0 +1,25 @@ + + + + WebODF: online/offline office + + A viewer for ODF files. + + + Jos van den Oever + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/android/assets/www/icon.png b/apps/files_odfviewer/src/webodf/programs/android/assets/www/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2993aa9f146d3aa5775b1d80bae7109f8cc93fb6 GIT binary patch literal 3793 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 Hu0mjf{LD+l literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/android/assets/www/index.html b/apps/files_odfviewer/src/webodf/programs/android/assets/www/index.html new file mode 100644 index 0000000000..d9a299d24d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/assets/www/index.html @@ -0,0 +1,46 @@ + + + + WebODF + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/android/assets/www/phonegap-1.4.1.js b/apps/files_odfviewer/src/webodf/programs/android/assets/www/phonegap-1.4.1.js new file mode 100644 index 0000000000..908b8a8a21 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/assets/www/phonegap-1.4.1.js @@ -0,0 +1,4586 @@ +/* + * 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. + */ + +// Version 1.2.0 + +if (typeof PhoneGap === "undefined") { + +/** + * The order of events during page load and PhoneGap startup is as follows: + * + * onDOMContentLoaded Internal event that is received when the web page is loaded and parsed. + * window.onload Body onload event. + * onNativeReady Internal event that indicates the PhoneGap native side is ready. + * onPhoneGapInit Internal event that kicks off creation of all PhoneGap JavaScript objects (runs constructors). + * onPhoneGapReady Internal event fired when all PhoneGap JavaScript objects have been created + * onPhoneGapInfoReady Internal event fired when device properties are available + * onDeviceReady User event fired to indicate that PhoneGap is ready + * onResume User event fired to indicate a start/resume lifecycle event + * onPause User event fired to indicate a pause lifecycle event + * onDestroy Internal event fired when app is being destroyed (User should use window.onunload event, not this one). + * + * The only PhoneGap events that user code should register for are: + * deviceready PhoneGap native code is initialized and PhoneGap APIs can be called from JavaScript + * pause App has moved to background + * resume App has returned to foreground + * + * Listeners can be registered as: + * document.addEventListener("deviceready", myDeviceReadyListener, false); + * document.addEventListener("resume", myResumeListener, false); + * document.addEventListener("pause", myPauseListener, false); + * + * The DOM lifecycle events should be used for saving and restoring state + * window.onload + * window.onunload + */ + +/** + * This represents the PhoneGap API itself, and provides a global namespace for accessing + * information about the state of PhoneGap. + * @class + */ +var PhoneGap = { + documentEventHandler: {}, // Collection of custom document event handlers + windowEventHandler: {} // Collection of custom window event handlers +}; + +/** + * List of resource files loaded by PhoneGap. + * This is used to ensure JS and other files are loaded only once. + */ +PhoneGap.resources = {base: true}; + +/** + * Determine if resource has been loaded by PhoneGap + * + * @param name + * @return + */ +PhoneGap.hasResource = function(name) { + return PhoneGap.resources[name]; +}; + +/** + * Add a resource to list of loaded resources by PhoneGap + * + * @param name + */ +PhoneGap.addResource = function(name) { + PhoneGap.resources[name] = true; +}; + +/** + * Custom pub-sub channel that can have functions subscribed to it + * @constructor + */ +PhoneGap.Channel = function (type) +{ + this.type = type; + this.handlers = {}; + this.guid = 0; + this.fired = false; + this.enabled = true; +}; + +/** + * Subscribes the given function to the channel. Any time that + * Channel.fire is called so too will the function. + * Optionally specify an execution context for the function + * and a guid that can be used to stop subscribing to the channel. + * Returns the guid. + */ +PhoneGap.Channel.prototype.subscribe = function(f, c, g) { + // need a function to call + if (f === null) { return; } + + var func = f; + if (typeof c === "object" && typeof f === "function") { func = PhoneGap.close(c, f); } + + g = g || func.observer_guid || f.observer_guid || this.guid++; + func.observer_guid = g; + f.observer_guid = g; + this.handlers[g] = func; + return g; +}; + +/** + * Like subscribe but the function is only called once and then it + * auto-unsubscribes itself. + */ +PhoneGap.Channel.prototype.subscribeOnce = function(f, c) { + var g = null; + var _this = this; + var m = function() { + f.apply(c || null, arguments); + _this.unsubscribe(g); + }; + if (this.fired) { + if (typeof c === "object" && typeof f === "function") { f = PhoneGap.close(c, f); } + f.apply(this, this.fireArgs); + } else { + g = this.subscribe(m); + } + return g; +}; + +/** + * Unsubscribes the function with the given guid from the channel. + */ +PhoneGap.Channel.prototype.unsubscribe = function(g) { + if (typeof g === "function") { g = g.observer_guid; } + this.handlers[g] = null; + delete this.handlers[g]; +}; + +/** + * Calls all functions subscribed to this channel. + */ +PhoneGap.Channel.prototype.fire = function(e) { + if (this.enabled) { + var fail = false; + var item, handler, rv; + for (item in this.handlers) { + if (this.handlers.hasOwnProperty(item)) { + handler = this.handlers[item]; + if (typeof handler === "function") { + rv = (handler.apply(this, arguments) === false); + fail = fail || rv; + } + } + } + this.fired = true; + this.fireArgs = arguments; + return !fail; + } + return true; +}; + +/** + * Calls the provided function only after all of the channels specified + * have been fired. + */ +PhoneGap.Channel.join = function(h, c) { + var i = c.length; + var f = function() { + if (!(--i)) { + h(); + } + }; + var len = i; + var j; + for (j=0; j + * + * @param name The plugin name + * @param obj The plugin object + */ +PhoneGap.addPlugin = function(name, obj) { + if (!window.plugins[name]) { + window.plugins[name] = obj; + } + else { + console.log("Error: Plugin "+name+" already exists."); + } +}; + +/** + * onDOMContentLoaded channel is fired when the DOM content + * of the page has been parsed. + */ +PhoneGap.onDOMContentLoaded = new PhoneGap.Channel('onDOMContentLoaded'); + +/** + * onNativeReady channel is fired when the PhoneGap native code + * has been initialized. + */ +PhoneGap.onNativeReady = new PhoneGap.Channel('onNativeReady'); + +/** + * onPhoneGapInit channel is fired when the web page is fully loaded and + * PhoneGap native code has been initialized. + */ +PhoneGap.onPhoneGapInit = new PhoneGap.Channel('onPhoneGapInit'); + +/** + * onPhoneGapReady channel is fired when the JS PhoneGap objects have been created. + */ +PhoneGap.onPhoneGapReady = new PhoneGap.Channel('onPhoneGapReady'); + +/** + * onPhoneGapInfoReady channel is fired when the PhoneGap device properties + * has been set. + */ +PhoneGap.onPhoneGapInfoReady = new PhoneGap.Channel('onPhoneGapInfoReady'); + +/** + * onPhoneGapConnectionReady channel is fired when the PhoneGap connection properties + * has been set. + */ +PhoneGap.onPhoneGapConnectionReady = new PhoneGap.Channel('onPhoneGapConnectionReady'); + +/** + * onDestroy channel is fired when the PhoneGap native code + * is destroyed. It is used internally. + * Window.onunload should be used by the user. + */ +PhoneGap.onDestroy = new PhoneGap.Channel('onDestroy'); +PhoneGap.onDestroy.subscribeOnce(function() { + PhoneGap.shuttingDown = true; +}); +PhoneGap.shuttingDown = false; + +// _nativeReady is global variable that the native side can set +// to signify that the native code is ready. It is a global since +// it may be called before any PhoneGap JS is ready. +if (typeof _nativeReady !== 'undefined') { PhoneGap.onNativeReady.fire(); } + +/** + * onDeviceReady is fired only after all PhoneGap objects are created and + * the device properties are set. + */ +PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady'); + + +// Array of channels that must fire before "deviceready" is fired +PhoneGap.deviceReadyChannelsArray = [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady, PhoneGap.onPhoneGapConnectionReady]; + +// Hashtable of user defined channels that must also fire before "deviceready" is fired +PhoneGap.deviceReadyChannelsMap = {}; + +/** + * Indicate that a feature needs to be initialized before it is ready to be used. + * This holds up PhoneGap's "deviceready" event until the feature has been initialized + * and PhoneGap.initComplete(feature) is called. + * + * @param feature {String} The unique feature name + */ +PhoneGap.waitForInitialization = function(feature) { + if (feature) { + var channel = new PhoneGap.Channel(feature); + PhoneGap.deviceReadyChannelsMap[feature] = channel; + PhoneGap.deviceReadyChannelsArray.push(channel); + } +}; + +/** + * Indicate that initialization code has completed and the feature is ready to be used. + * + * @param feature {String} The unique feature name + */ +PhoneGap.initializationComplete = function(feature) { + var channel = PhoneGap.deviceReadyChannelsMap[feature]; + if (channel) { + channel.fire(); + } +}; + +/** + * Create all PhoneGap objects once page has fully loaded and native side is ready. + */ +PhoneGap.Channel.join(function() { + + // Start listening for XHR callbacks + setTimeout(function() { + if (PhoneGap.UsePolling) { + PhoneGap.JSCallbackPolling(); + } + else { + var polling = prompt("usePolling", "gap_callbackServer:"); + PhoneGap.UsePolling = polling; + if (polling == "true") { + PhoneGap.UsePolling = true; + PhoneGap.JSCallbackPolling(); + } + else { + PhoneGap.UsePolling = false; + PhoneGap.JSCallback(); + } + } + }, 1); + + // Run PhoneGap constructors + PhoneGap.onPhoneGapInit.fire(); + + // Fire event to notify that all objects are created + PhoneGap.onPhoneGapReady.fire(); + + // Fire onDeviceReady event once all constructors have run and PhoneGap info has been + // received from native side, and any user defined initialization channels. + PhoneGap.Channel.join(function() { + // Let native code know we are inited on JS side + prompt("", "gap_init:"); + + PhoneGap.onDeviceReady.fire(); + }, PhoneGap.deviceReadyChannelsArray); + +}, [ PhoneGap.onDOMContentLoaded, PhoneGap.onNativeReady ]); + +// Listen for DOMContentLoaded and notify our channel subscribers +document.addEventListener('DOMContentLoaded', function() { + PhoneGap.onDOMContentLoaded.fire(); +}, false); + +// Intercept calls to document.addEventListener and watch for deviceready +PhoneGap.m_document_addEventListener = document.addEventListener; + +// Intercept calls to window.addEventListener +PhoneGap.m_window_addEventListener = window.addEventListener; + +/** + * Add a custom window event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addWindowEventHandler = function(event, callback) { + PhoneGap.windowEventHandler[event] = callback; +}; + +/** + * Add a custom document event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addDocumentEventHandler = function(event, callback) { + PhoneGap.documentEventHandler[event] = callback; +}; + +/** + * Intercept adding document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + if (e === 'deviceready') { + PhoneGap.onDeviceReady.subscribeOnce(handler); + } + else { + // If subscribing to Android backbutton + if (e === 'backbutton') { + PhoneGap.exec(null, null, "App", "overrideBackbutton", [true]); + } + + // If subscribing to an event that is handled by a plugin + else if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_addEventListener.call(document, evt, handler, capture); + } +}; + +/** + * Intercept adding window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_addEventListener.call(window, evt, handler, capture); +}; + +// Intercept calls to document.removeEventListener and watch for events that +// are generated by PhoneGap native code +PhoneGap.m_document_removeEventListener = document.removeEventListener; + +// Intercept calls to window.removeEventListener +PhoneGap.m_window_removeEventListener = window.removeEventListener; + +/** + * Intercept removing document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubscribing to Android backbutton + if (e === 'backbutton') { + PhoneGap.exec(null, null, "App", "overrideBackbutton", [false]); + } + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_removeEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept removing window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_removeEventListener.call(window, evt, handler, capture); +}; + +/** + * Method to fire document event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireDocumentEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + document.dispatchEvent(e); +}; + +/** + * Method to fire window event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireWindowEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + window.dispatchEvent(e); +}; + +/** + * Does a deep clone of the object. + * + * @param obj + * @return {Object} + */ +PhoneGap.clone = function(obj) { + var i, retVal; + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + retVal = []; + for(i = 0; i < obj.length; ++i){ + retVal.push(PhoneGap.clone(obj[i])); + } + return retVal; + } + + if (typeof obj === "function") { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + if (obj instanceof Date) { + return obj; + } + + retVal = {}; + for(i in obj){ + if(!(i in retVal) || retVal[i] !== obj[i]) { + retVal[i] = PhoneGap.clone(obj[i]); + } + } + return retVal; +}; + +PhoneGap.callbackId = 0; +PhoneGap.callbacks = {}; +PhoneGap.callbackStatus = { + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 + }; + + +/** + * Execute a PhoneGap command. It is up to the native side whether this action is synch or async. + * The native side can return: + * Synchronous: PluginResult object as a JSON string + * Asynchrounous: Empty string "" + * If async, the native side will PhoneGap.callbackSuccess or PhoneGap.callbackError, + * depending upon the result of the action. + * + * @param {Function} success The success callback + * @param {Function} fail The fail callback + * @param {String} service The name of the service to use + * @param {String} action Action to be run in PhoneGap + * @param {Array.} [args] Zero or more arguments to pass to the method + */ +PhoneGap.exec = function(success, fail, service, action, args) { + try { + var callbackId = service + PhoneGap.callbackId++; + if (success || fail) { + PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; + } + + var r = prompt(JSON.stringify(args), "gap:"+JSON.stringify([service, action, callbackId, true])); + + // If a result was returned + if (r.length > 0) { + eval("var v="+r+";"); + + // If status is OK, then return value back to caller + if (v.status === PhoneGap.callbackStatus.OK) { + + // If there is a success callback, then call it now with + // returned value + if (success) { + try { + success(v.message); + } catch (e) { + console.log("Error in success callback: " + callbackId + " = " + e); + } + + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } + return v.message; + } + + // If no result + else if (v.status === PhoneGap.callbackStatus.NO_RESULT) { + + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } + + // If error, then display error + else { + console.log("Error: Status="+v.status+" Message="+v.message); + + // If there is a fail callback, then call it now with returned value + if (fail) { + try { + fail(v.message); + } + catch (e1) { + console.log("Error in error callback: "+callbackId+" = "+e1); + } + + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } + return null; + } + } + } catch (e2) { + console.log("Error: "+e2); + } +}; + +/** + * Called by native code when returning successful result from an action. + * + * @param callbackId + * @param args + */ +PhoneGap.callbackSuccess = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + + // If result is to be sent to callback + if (args.status === PhoneGap.callbackStatus.OK) { + try { + if (PhoneGap.callbacks[callbackId].success) { + PhoneGap.callbacks[callbackId].success(args.message); + } + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + +/** + * Called by native code when returning error result from an action. + * + * @param callbackId + * @param args + */ +PhoneGap.callbackError = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + try { + if (PhoneGap.callbacks[callbackId].fail) { + PhoneGap.callbacks[callbackId].fail(args.message); + } + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + +PhoneGap.JSCallbackPort = null; +PhoneGap.JSCallbackToken = null; + +/** + * This is only for Android. + * + * Internal function that uses XHR to call into PhoneGap Java code and retrieve + * any JavaScript code that needs to be run. This is used for callbacks from + * Java to JavaScript. + */ +PhoneGap.JSCallback = function() { + + // Exit if shutting down app + if (PhoneGap.shuttingDown) { + return; + } + + // If polling flag was changed, start using polling from now on + if (PhoneGap.UsePolling) { + PhoneGap.JSCallbackPolling(); + return; + } + + var xmlhttp = new XMLHttpRequest(); + + // Callback function when XMLHttpRequest is ready + xmlhttp.onreadystatechange=function(){ + if(xmlhttp.readyState === 4){ + + // Exit if shutting down app + if (PhoneGap.shuttingDown) { + return; + } + + // If callback has JavaScript statement to execute + if (xmlhttp.status === 200) { + + // Need to url decode the response + var msg = decodeURIComponent(xmlhttp.responseText); + setTimeout(function() { + try { + var t = eval(msg); + } + catch (e) { + // If we're getting an error here, seeing the message will help in debugging + console.log("JSCallback: Message from Server: " + msg); + console.log("JSCallback Error: "+e); + } + }, 1); + setTimeout(PhoneGap.JSCallback, 1); + } + + // If callback ping (used to keep XHR request from timing out) + else if (xmlhttp.status === 404) { + setTimeout(PhoneGap.JSCallback, 10); + } + + // If security error + else if (xmlhttp.status === 403) { + console.log("JSCallback Error: Invalid token. Stopping callbacks."); + } + + // If server is stopping + else if (xmlhttp.status === 503) { + console.log("JSCallback Server Closed: Stopping callbacks."); + } + + // If request wasn't GET + else if (xmlhttp.status === 400) { + console.log("JSCallback Error: Bad request. Stopping callbacks."); + } + + // If error, revert to polling + else { + console.log("JSCallback Error: Request failed."); + PhoneGap.UsePolling = true; + PhoneGap.JSCallbackPolling(); + } + } + }; + + if (PhoneGap.JSCallbackPort === null) { + PhoneGap.JSCallbackPort = prompt("getPort", "gap_callbackServer:"); + } + if (PhoneGap.JSCallbackToken === null) { + PhoneGap.JSCallbackToken = prompt("getToken", "gap_callbackServer:"); + } + xmlhttp.open("GET", "http://127.0.0.1:"+PhoneGap.JSCallbackPort+"/"+PhoneGap.JSCallbackToken , true); + xmlhttp.send(); +}; + +/** + * The polling period to use with JSCallbackPolling. + * This can be changed by the application. The default is 50ms. + */ +PhoneGap.JSCallbackPollingPeriod = 50; + +/** + * Flag that can be set by the user to force polling to be used or force XHR to be used. + */ +PhoneGap.UsePolling = false; // T=use polling, F=use XHR + +/** + * This is only for Android. + * + * Internal function that uses polling to call into PhoneGap Java code and retrieve + * any JavaScript code that needs to be run. This is used for callbacks from + * Java to JavaScript. + */ +PhoneGap.JSCallbackPolling = function() { + + // Exit if shutting down app + if (PhoneGap.shuttingDown) { + return; + } + + // If polling flag was changed, stop using polling from now on + if (!PhoneGap.UsePolling) { + PhoneGap.JSCallback(); + return; + } + + var msg = prompt("", "gap_poll:"); + if (msg) { + setTimeout(function() { + try { + var t = eval(""+msg); + } + catch (e) { + console.log("JSCallbackPolling: Message from Server: " + msg); + console.log("JSCallbackPolling Error: "+e); + } + }, 1); + setTimeout(PhoneGap.JSCallbackPolling, 1); + } + else { + setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod); + } +}; + +/** + * Create a UUID + * + * @return {String} + */ +PhoneGap.createUUID = function() { + return PhoneGap.UUIDcreatePart(4) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(6); +}; + +PhoneGap.UUIDcreatePart = function(length) { + var uuidpart = ""; + var i, uuidchar; + for (i=0; i frequency + 10 sec + PhoneGap.exec( + function(timeout) { + if (timeout < (frequency + 10000)) { + PhoneGap.exec(null, null, "Accelerometer", "setTimeout", [frequency + 10000]); + } + }, + function(e) { }, "Accelerometer", "getTimeout", []); + + // Start watch timer + var id = PhoneGap.createUUID(); + navigator.accelerometer.timers[id] = setInterval(function() { + PhoneGap.exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []); + }, (frequency ? frequency : 1)); + + return id; +}; + +/** + * Clears the specified accelerometer watch. + * + * @param {String} id The id of the watch returned from #watchAcceleration. + */ +Accelerometer.prototype.clearWatch = function(id) { + + // Stop javascript timer & remove from timer list + if (id && navigator.accelerometer.timers[id] !== undefined) { + clearInterval(navigator.accelerometer.timers[id]); + delete navigator.accelerometer.timers[id]; + } +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.accelerometer === "undefined") { + navigator.accelerometer = new Accelerometer(); + } +}); +} +/* + * 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. + */ + +if (!PhoneGap.hasResource("app")) { +PhoneGap.addResource("app"); +(function() { + +/** + * Constructor + * @constructor + */ +var App = function() {}; + +/** + * Clear the resource cache. + */ +App.prototype.clearCache = function() { + PhoneGap.exec(null, null, "App", "clearCache", []); +}; + +/** + * Load the url into the webview or into new browser instance. + * + * @param url The URL to load + * @param props Properties that can be passed in to the activity: + * wait: int => wait msec before loading URL + * loadingDialog: "Title,Message" => display a native loading dialog + * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error + * clearHistory: boolean => clear webview history (default=false) + * openExternal: boolean => open in a new browser (default=false) + * + * Example: + * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000}); + */ +App.prototype.loadUrl = function(url, props) { + PhoneGap.exec(null, null, "App", "loadUrl", [url, props]); +}; + +/** + * Cancel loadUrl that is waiting to be loaded. + */ +App.prototype.cancelLoadUrl = function() { + PhoneGap.exec(null, null, "App", "cancelLoadUrl", []); +}; + +/** + * Clear web history in this web view. + * Instead of BACK button loading the previous web page, it will exit the app. + */ +App.prototype.clearHistory = function() { + PhoneGap.exec(null, null, "App", "clearHistory", []); +}; + +/** + * Go to previous page displayed. + * This is the same as pressing the backbutton on Android device. + */ +App.prototype.backHistory = function() { + PhoneGap.exec(null, null, "App", "backHistory", []); +}; + +/** + * Exit and terminate the application. + */ +App.prototype.exitApp = function() { + return PhoneGap.exec(null, null, "App", "exitApp", []); +}; + +PhoneGap.addConstructor(function() { + navigator.app = new App(); +}); +}()); +} +/* + * 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. + */ + +if (!PhoneGap.hasResource("battery")) { +PhoneGap.addResource("battery"); + +/** + * This class contains information about the current battery status. + * @constructor + */ +var Battery = function() { + this._level = null; + this._isPlugged = null; + this._batteryListener = []; + this._lowListener = []; + this._criticalListener = []; +}; + +/** + * Registers as an event producer for battery events. + * + * @param {Object} eventType + * @param {Object} handler + * @param {Object} add + */ +Battery.prototype.eventHandler = function(eventType, handler, add) { + var me = navigator.battery; + if (add) { + // If there are no current registered event listeners start the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + PhoneGap.exec(me._status, me._error, "Battery", "start", []); + } + + // Register the event listener in the proper array + if (eventType === "batterystatus") { + if (me._batteryListener.indexOf(handler) === -1) { + me._batteryListener.push(handler); + } + } else if (eventType === "batterylow") { + if (me._lowListener.indexOf(handler) === -1) { + me._lowListener.push(handler); + } + } else if (eventType === "batterycritical") { + if (me._criticalListener.indexOf(handler) === -1) { + me._criticalListener.push(handler); + } + } + } else { + var pos = -1; + // Remove the event listener from the proper array + if (eventType === "batterystatus") { + pos = me._batteryListener.indexOf(handler); + if (pos > -1) { + me._batteryListener.splice(pos, 1); + } + } else if (eventType === "batterylow") { + pos = me._lowListener.indexOf(handler); + if (pos > -1) { + me._lowListener.splice(pos, 1); + } + } else if (eventType === "batterycritical") { + pos = me._criticalListener.indexOf(handler); + if (pos > -1) { + me._criticalListener.splice(pos, 1); + } + } + + // If there are no more registered event listeners stop the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + PhoneGap.exec(null, null, "Battery", "stop", []); + } + } +}; + +/** + * Callback for battery status + * + * @param {Object} info keys: level, isPlugged + */ +Battery.prototype._status = function(info) { + if (info) { + var me = this; + var level = info.level; + if (me._level !== level || me._isPlugged !== info.isPlugged) { + // Fire batterystatus event + PhoneGap.fireWindowEvent("batterystatus", info); + + // Fire low battery event + if (level === 20 || level === 5) { + if (level === 20) { + PhoneGap.fireWindowEvent("batterylow", info); + } + else { + PhoneGap.fireWindowEvent("batterycritical", info); + } + } + } + me._level = level; + me._isPlugged = info.isPlugged; + } +}; + +/** + * Error callback for battery start + */ +Battery.prototype._error = function(e) { + console.log("Error initializing Battery: " + e); +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.battery === "undefined") { + navigator.battery = new Battery(); + PhoneGap.addWindowEventHandler("batterystatus", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterylow", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterycritical", navigator.battery.eventHandler); + } +}); +} +/* + * 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. + */ + +if (!PhoneGap.hasResource("camera")) { +PhoneGap.addResource("camera"); + +/** + * This class provides access to the device camera. + * + * @constructor + */ +var Camera = function() { + this.successCallback = null; + this.errorCallback = null; + this.options = null; +}; + +/** + * Format of image that returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.DestinationType = { + DATA_URL: 0, // Return base64 encoded string + FILE_URI: 1 // Return file uri (content://media/external/images/media/2 for Android) +}; +Camera.prototype.DestinationType = Camera.DestinationType; + +/** + * Encoding of image returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.CAMERA, + * encodingType: Camera.EncodingType.PNG}) +*/ +Camera.EncodingType = { + JPEG: 0, // Return JPEG encoded image + PNG: 1 // Return PNG encoded image +}; +Camera.prototype.EncodingType = Camera.EncodingType; + +/** + * Type of pictures to select from. Only applicable when + * PictureSourceType is PHOTOLIBRARY or SAVEDPHOTOALBUM + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY, + * mediaType: Camera.MediaType.PICTURE}) + */ +Camera.MediaType = { + PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType + VIDEO: 1, // allow selection of video only, ONLY RETURNS URL + ALLMEDIA : 2 // allow selection from all media types +}; +Camera.prototype.MediaType = Camera.MediaType; + + +/** + * Source to getPicture from. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.PictureSourceType = { + PHOTOLIBRARY : 0, // Choose image from picture library (same as SAVEDPHOTOALBUM for Android) + CAMERA : 1, // Take picture from camera + SAVEDPHOTOALBUM : 2 // Choose image from picture library (same as PHOTOLIBRARY for Android) +}; +Camera.prototype.PictureSourceType = Camera.PictureSourceType; + +/** + * Gets a picture from source defined by "options.sourceType", and returns the + * image as defined by the "options.destinationType" option. + + * The defaults are sourceType=CAMERA and destinationType=DATA_URL. + * + * @param {Function} successCallback + * @param {Function} errorCallback + * @param {Object} options + */ +Camera.prototype.getPicture = function(successCallback, errorCallback, options) { + + // successCallback required + if (typeof successCallback !== "function") { + console.log("Camera Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback !== "function")) { + console.log("Camera Error: errorCallback is not a function"); + return; + } + + if (options === null || typeof options === "undefined") { + options = {}; + } + if (options.quality === null || typeof options.quality === "undefined") { + options.quality = 80; + } + if (options.maxResolution === null || typeof options.maxResolution === "undefined") { + options.maxResolution = 0; + } + if (options.destinationType === null || typeof options.destinationType === "undefined") { + options.destinationType = Camera.DestinationType.FILE_URI; + } + if (options.sourceType === null || typeof options.sourceType === "undefined") { + options.sourceType = Camera.PictureSourceType.CAMERA; + } + if (options.encodingType === null || typeof options.encodingType === "undefined") { + options.encodingType = Camera.EncodingType.JPEG; + } + if (options.mediaType === null || typeof options.mediaType === "undefined") { + options.mediaType = Camera.MediaType.PICTURE; + } + if (options.targetWidth === null || typeof options.targetWidth === "undefined") { + options.targetWidth = -1; + } + else if (typeof options.targetWidth === "string") { + var width = new Number(options.targetWidth); + if (isNaN(width) === false) { + options.targetWidth = width.valueOf(); + } + } + if (options.targetHeight === null || typeof options.targetHeight === "undefined") { + options.targetHeight = -1; + } + else if (typeof options.targetHeight === "string") { + var height = new Number(options.targetHeight); + if (isNaN(height) === false) { + options.targetHeight = height.valueOf(); + } + } + + PhoneGap.exec(successCallback, errorCallback, "Camera", "takePicture", [options]); +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.camera === "undefined") { + navigator.camera = new Camera(); + } +}); +} +/* + * 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. + */ + +if (!PhoneGap.hasResource("capture")) { +PhoneGap.addResource("capture"); + +/** + * Represents a single file. + * + * name {DOMString} name of the file, without path information + * fullPath {DOMString} the full path of the file, including the name + * type {DOMString} mime type + * lastModifiedDate {Date} last modified date + * size {Number} size of the file in bytes + */ +var MediaFile = function(name, fullPath, type, lastModifiedDate, size){ + this.name = name || null; + this.fullPath = fullPath || null; + this.type = type || null; + this.lastModifiedDate = lastModifiedDate || null; + this.size = size || 0; +}; + +/** + * Launch device camera application for recording video(s). + * + * @param {Function} successCB + * @param {Function} errorCB + */ +MediaFile.prototype.getFormatData = function(successCallback, errorCallback){ + PhoneGap.exec(successCallback, errorCallback, "Capture", "getFormatData", [this.fullPath, this.type]); +}; + +/** + * MediaFileData encapsulates format information of a media file. + * + * @param {DOMString} codecs + * @param {long} bitrate + * @param {long} height + * @param {long} width + * @param {float} duration + */ +var MediaFileData = function(codecs, bitrate, height, width, duration){ + this.codecs = codecs || null; + this.bitrate = bitrate || 0; + this.height = height || 0; + this.width = width || 0; + this.duration = duration || 0; +}; + +/** + * The CaptureError interface encapsulates all errors in the Capture API. + */ +var CaptureError = function(){ + this.code = null; +}; + +// Capture error codes +CaptureError.CAPTURE_INTERNAL_ERR = 0; +CaptureError.CAPTURE_APPLICATION_BUSY = 1; +CaptureError.CAPTURE_INVALID_ARGUMENT = 2; +CaptureError.CAPTURE_NO_MEDIA_FILES = 3; +CaptureError.CAPTURE_NOT_SUPPORTED = 20; + +/** + * The Capture interface exposes an interface to the camera and microphone of the hosting device. + */ +var Capture = function(){ + this.supportedAudioModes = []; + this.supportedImageModes = []; + this.supportedVideoModes = []; +}; + +/** + * Launch audio recorder application for recording audio clip(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureAudioOptions} options + */ +Capture.prototype.captureAudio = function(successCallback, errorCallback, options){ + PhoneGap.exec(successCallback, errorCallback, "Capture", "captureAudio", [options]); +}; + +/** + * Launch camera application for taking image(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureImageOptions} options + */ +Capture.prototype.captureImage = function(successCallback, errorCallback, options){ + PhoneGap.exec(successCallback, errorCallback, "Capture", "captureImage", [options]); +}; + +/** + * Launch camera application for taking image(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureImageOptions} options + */ +Capture.prototype._castMediaFile = function(pluginResult){ + var mediaFiles = []; + var i; + for (i = 0; i < pluginResult.message.length; i++) { + var mediaFile = new MediaFile(); + mediaFile.name = pluginResult.message[i].name; + mediaFile.fullPath = pluginResult.message[i].fullPath; + mediaFile.type = pluginResult.message[i].type; + mediaFile.lastModifiedDate = pluginResult.message[i].lastModifiedDate; + mediaFile.size = pluginResult.message[i].size; + mediaFiles.push(mediaFile); + } + pluginResult.message = mediaFiles; + return pluginResult; +}; + +/** + * Launch device camera application for recording video(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureVideoOptions} options + */ +Capture.prototype.captureVideo = function(successCallback, errorCallback, options){ + PhoneGap.exec(successCallback, errorCallback, "Capture", "captureVideo", [options]); +}; + +/** + * Encapsulates a set of parameters that the capture device supports. + */ +var ConfigurationData = function(){ + // The ASCII-encoded string in lower case representing the media type. + this.type = null; + // The height attribute represents height of the image or video in pixels. + // In the case of a sound clip this attribute has value 0. + this.height = 0; + // The width attribute represents width of the image or video in pixels. + // In the case of a sound clip this attribute has value 0 + this.width = 0; +}; + +/** + * Encapsulates all image capture operation configuration options. + */ +var CaptureImageOptions = function(){ + // Upper limit of images user can take. Value must be equal or greater than 1. + this.limit = 1; + // The selected image mode. Must match with one of the elements in supportedImageModes array. + this.mode = null; +}; + +/** + * Encapsulates all video capture operation configuration options. + */ +var CaptureVideoOptions = function(){ + // Upper limit of videos user can record. Value must be equal or greater than 1. + this.limit = 1; + // Maximum duration of a single video clip in seconds. + this.duration = 0; + // The selected video mode. Must match with one of the elements in supportedVideoModes array. + this.mode = null; +}; + +/** + * Encapsulates all audio capture operation configuration options. + */ +var CaptureAudioOptions = function(){ + // Upper limit of sound clips user can record. Value must be equal or greater than 1. + this.limit = 1; + // Maximum duration of a single sound clip in seconds. + this.duration = 0; + // The selected audio mode. Must match with one of the elements in supportedAudioModes array. + this.mode = null; +}; + +PhoneGap.addConstructor(function(){ + if (typeof navigator.device.capture === "undefined") { + navigator.device.capture = window.device.capture = new Capture(); + } +}); +} +/* + * 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. + */ + +if (!PhoneGap.hasResource("compass")) { +PhoneGap.addResource("compass"); + +var CompassError = function(){ + this.code = null; +}; + +// Capture error codes +CompassError.COMPASS_INTERNAL_ERR = 0; +CompassError.COMPASS_NOT_SUPPORTED = 20; + +var CompassHeading = function() { + this.magneticHeading = null; + this.trueHeading = null; + this.headingAccuracy = null; + this.timestamp = null; +}; + +/** + * This class provides access to device Compass data. + * @constructor + */ +var Compass = function() { + /** + * The last known Compass position. + */ + this.lastHeading = null; + + /** + * List of compass watch timers + */ + this.timers = {}; +}; + +Compass.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"]; + +/** + * Asynchronously aquires the current heading. + * + * @param {Function} successCallback The function to call when the heading data is available + * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) + * @param {PositionOptions} options The options for getting the heading data such as timeout. (OPTIONAL) + */ +Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, options) { + + // successCallback required + if (typeof successCallback !== "function") { + console.log("Compass Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback !== "function")) { + console.log("Compass Error: errorCallback is not a function"); + return; + } + + // Get heading + PhoneGap.exec(successCallback, errorCallback, "Compass", "getHeading", []); +}; + +/** + * Asynchronously aquires the heading repeatedly at a given interval. + * + * @param {Function} successCallback The function to call each time the heading data is available + * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) + * @param {HeadingOptions} options The options for getting the heading data such as timeout and the frequency of the watch. (OPTIONAL) + * @return String The watch id that must be passed to #clearWatch to stop watching. + */ +Compass.prototype.watchHeading= function(successCallback, errorCallback, options) { + + // Default interval (100 msec) + var frequency = (options !== undefined) ? options.frequency : 100; + + // successCallback required + if (typeof successCallback !== "function") { + console.log("Compass Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback !== "function")) { + console.log("Compass Error: errorCallback is not a function"); + return; + } + + // Make sure compass timeout > frequency + 10 sec + PhoneGap.exec( + function(timeout) { + if (timeout < (frequency + 10000)) { + PhoneGap.exec(null, null, "Compass", "setTimeout", [frequency + 10000]); + } + }, + function(e) { }, "Compass", "getTimeout", []); + + // Start watch timer to get headings + var id = PhoneGap.createUUID(); + navigator.compass.timers[id] = setInterval( + function() { + PhoneGap.exec(successCallback, errorCallback, "Compass", "getHeading", []); + }, (frequency ? frequency : 1)); + + return id; +}; + + +/** + * Clears the specified heading watch. + * + * @param {String} id The ID of the watch returned from #watchHeading. + */ +Compass.prototype.clearWatch = function(id) { + + // Stop javascript timer & remove from timer list + if (id && navigator.compass.timers[id]) { + clearInterval(navigator.compass.timers[id]); + delete navigator.compass.timers[id]; + } +}; + +Compass.prototype._castDate = function(pluginResult) { + if (pluginResult.message.timestamp) { + var timestamp = new Date(pluginResult.message.timestamp); + pluginResult.message.timestamp = timestamp; + } + return pluginResult; +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.compass === "undefined") { + navigator.compass = new Compass(); + } +}); +} +/* + * 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. + */ + +if (!PhoneGap.hasResource("contact")) { +PhoneGap.addResource("contact"); + +/** +* Contains information about a single contact. +* @constructor +* @param {DOMString} id unique identifier +* @param {DOMString} displayName +* @param {ContactName} name +* @param {DOMString} nickname +* @param {Array.} phoneNumbers array of phone numbers +* @param {Array.} emails array of email addresses +* @param {Array.} addresses array of addresses +* @param {Array.} ims instant messaging user ids +* @param {Array.} organizations +* @param {DOMString} birthday contact's birthday +* @param {DOMString} note user notes about contact +* @param {Array.} photos +* @param {Array.} categories +* @param {Array.} urls contact's web sites +*/ +var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, birthday, note, photos, categories, urls) { + this.id = id || null; + this.rawId = null; + this.displayName = displayName || null; + this.name = name || null; // ContactName + this.nickname = nickname || null; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.birthday = birthday || null; + this.note = note || null; + this.photos = photos || null; // ContactField[] + this.categories = categories || null; // ContactField[] + this.urls = urls || null; // ContactField[] +}; + +/** + * ContactError. + * An error code assigned by an implementation when an error has occurreds + * @constructor + */ +var ContactError = function() { + this.code=null; +}; + +/** + * Error codes + */ +ContactError.UNKNOWN_ERROR = 0; +ContactError.INVALID_ARGUMENT_ERROR = 1; +ContactError.TIMEOUT_ERROR = 2; +ContactError.PENDING_OPERATION_ERROR = 3; +ContactError.IO_ERROR = 4; +ContactError.NOT_SUPPORTED_ERROR = 5; +ContactError.PERMISSION_DENIED_ERROR = 20; + +/** +* Removes contact from device storage. +* @param successCB success callback +* @param errorCB error callback +*/ +Contact.prototype.remove = function(successCB, errorCB) { + if (this.id === null) { + var errorObj = new ContactError(); + errorObj.code = ContactError.UNKNOWN_ERROR; + errorCB(errorObj); + } + else { + PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]); + } +}; + +/** +* Creates a deep copy of this Contact. +* With the contact ID set to null. +* @return copy of this Contact +*/ +Contact.prototype.clone = function() { + var clonedContact = PhoneGap.clone(this); + var i; + clonedContact.id = null; + clonedContact.rawId = null; + // Loop through and clear out any id's in phones, emails, etc. + if (clonedContact.phoneNumbers) { + for (i = 0; i < clonedContact.phoneNumbers.length; i++) { + clonedContact.phoneNumbers[i].id = null; + } + } + if (clonedContact.emails) { + for (i = 0; i < clonedContact.emails.length; i++) { + clonedContact.emails[i].id = null; + } + } + if (clonedContact.addresses) { + for (i = 0; i < clonedContact.addresses.length; i++) { + clonedContact.addresses[i].id = null; + } + } + if (clonedContact.ims) { + for (i = 0; i < clonedContact.ims.length; i++) { + clonedContact.ims[i].id = null; + } + } + if (clonedContact.organizations) { + for (i = 0; i < clonedContact.organizations.length; i++) { + clonedContact.organizations[i].id = null; + } + } + if (clonedContact.tags) { + for (i = 0; i < clonedContact.tags.length; i++) { + clonedContact.tags[i].id = null; + } + } + if (clonedContact.photos) { + for (i = 0; i < clonedContact.photos.length; i++) { + clonedContact.photos[i].id = null; + } + } + if (clonedContact.urls) { + for (i = 0; i < clonedContact.urls.length; i++) { + clonedContact.urls[i].id = null; + } + } + return clonedContact; +}; + +/** +* Persists contact to device storage. +* @param successCB success callback +* @param errorCB error callback +*/ +Contact.prototype.save = function(successCB, errorCB) { + PhoneGap.exec(successCB, errorCB, "Contacts", "save", [this]); +}; + +/** +* Contact name. +* @constructor +* @param formatted +* @param familyName +* @param givenName +* @param middle +* @param prefix +* @param suffix +*/ +var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { + this.formatted = formatted || null; + this.familyName = familyName || null; + this.givenName = givenName || null; + this.middleName = middle || null; + this.honorificPrefix = prefix || null; + this.honorificSuffix = suffix || null; +}; + +/** +* Generic contact field. +* @constructor +* @param {DOMString} id unique identifier, should only be set by native code +* @param type +* @param value +* @param pref +*/ +var ContactField = function(type, value, pref) { + this.id = null; + this.type = type || null; + this.value = value || null; + this.pref = pref || null; +}; + +/** +* Contact address. +* @constructor +* @param {DOMString} id unique identifier, should only be set by native code +* @param formatted +* @param streetAddress +* @param locality +* @param region +* @param postalCode +* @param country +*/ +var ContactAddress = function(pref, type, formatted, streetAddress, locality, region, postalCode, country) { + this.id = null; + this.pref = pref || null; + this.type = type || null; + this.formatted = formatted || null; + this.streetAddress = streetAddress || null; + this.locality = locality || null; + this.region = region || null; + this.postalCode = postalCode || null; + this.country = country || null; +}; + +/** +* Contact organization. +* @constructor +* @param {DOMString} id unique identifier, should only be set by native code +* @param name +* @param dept +* @param title +* @param startDate +* @param endDate +* @param location +* @param desc +*/ +var ContactOrganization = function(pref, type, name, dept, title) { + this.id = null; + this.pref = pref || null; + this.type = type || null; + this.name = name || null; + this.department = dept || null; + this.title = title || null; +}; + +/** +* Represents a group of Contacts. +* @constructor +*/ +var Contacts = function() { + this.inProgress = false; + this.records = []; +}; +/** +* Returns an array of Contacts matching the search criteria. +* @param fields that should be searched +* @param successCB success callback +* @param errorCB error callback +* @param {ContactFindOptions} options that can be applied to contact searching +* @return array of Contacts matching search criteria +*/ +Contacts.prototype.find = function(fields, successCB, errorCB, options) { + if (successCB === null) { + throw new TypeError("You must specify a success callback for the find command."); + } + if (fields === null || fields === "undefined" || fields.length === "undefined" || fields.length <= 0) { + if (typeof errorCB === "function") { + errorCB({"code": ContactError.INVALID_ARGUMENT_ERROR}); + } + } else { + PhoneGap.exec(successCB, errorCB, "Contacts", "search", [fields, options]); + } +}; + +/** +* This function creates a new contact, but it does not persist the contact +* to device storage. To persist the contact to device storage, invoke +* contact.save(). +* @param properties an object who's properties will be examined to create a new Contact +* @returns new Contact object +*/ +Contacts.prototype.create = function(properties) { + var i; + var contact = new Contact(); + for (i in properties) { + if (contact[i] !== 'undefined') { + contact[i] = properties[i]; + } + } + return contact; +}; + +/** +* This function returns and array of contacts. It is required as we need to convert raw +* JSON objects into concrete Contact objects. Currently this method is called after +* navigator.contacts.find but before the find methods success call back. +* +* @param jsonArray an array of JSON Objects that need to be converted to Contact objects. +* @returns an array of Contact objects +*/ +Contacts.prototype.cast = function(pluginResult) { + var contacts = []; + var i; + for (i=0; i][;base64], + * + * @param file {File} File object containing file properties + */ +FileReader.prototype.readAsDataURL = function(file) { + this.fileName = ""; + if (typeof file.fullPath === "undefined") { + this.fileName = file; + } else { + this.fileName = file.fullPath; + } + + // LOADING state + this.readyState = FileReader.LOADING; + + // If loadstart callback + if (typeof this.onloadstart === "function") { + this.onloadstart({"type":"loadstart", "target":this}); + } + + var me = this; + + // Read file + PhoneGap.exec( + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save result + me.result = r; + + // If onload callback + if (typeof me.onload === "function") { + me.onload({"type":"load", "target":me}); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + me.onloadend({"type":"loadend", "target":me}); + } + }, + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + me.onerror({"type":"error", "target":me}); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + me.onloadend({"type":"loadend", "target":me}); + } + }, "File", "readAsDataURL", [this.fileName]); +}; + +/** + * Read file and return data as a binary data. + * + * @param file {File} File object containing file properties + */ +FileReader.prototype.readAsBinaryString = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +/** + * Read file and return data as a binary data. + * + * @param file {File} File object containing file properties + */ +FileReader.prototype.readAsArrayBuffer = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +//----------------------------------------------------------------------------- +// File Writer +//----------------------------------------------------------------------------- + +/** + * This class writes to the mobile device file system. + * + * For Android: + * The root directory is the root of the file system. + * To write to the SD card, the file name is "sdcard/my_file.txt" + * + * @constructor + * @param file {File} File object containing file properties + * @param append if true write to the end of the file, otherwise overwrite the file + */ +var FileWriter = function(file) { + this.fileName = ""; + this.length = 0; + if (file) { + this.fileName = file.fullPath || file; + this.length = file.size || 0; + } + // default is to write at the beginning of the file + this.position = 0; + + this.readyState = 0; // EMPTY + + this.result = null; + + // Error + this.error = null; + + // Event handlers + this.onwritestart = null; // When writing starts + this.onprogress = null; // While writing the file, and reporting partial file data + this.onwrite = null; // When the write has successfully completed. + this.onwriteend = null; // When the request has completed (either in success or failure). + this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method. + this.onerror = null; // When the write has failed (see errors). +}; + +// States +FileWriter.INIT = 0; +FileWriter.WRITING = 1; +FileWriter.DONE = 2; + +/** + * Abort writing file. + */ +FileWriter.prototype.abort = function() { + // check for invalid state + if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) { + throw FileError.INVALID_STATE_ERR; + } + + // set error + var error = new FileError(), evt; + error.code = error.ABORT_ERR; + this.error = error; + + // If error callback + if (typeof this.onerror === "function") { + this.onerror({"type":"error", "target":this}); + } + // If abort callback + if (typeof this.onabort === "function") { + this.onabort({"type":"abort", "target":this}); + } + + this.readyState = FileWriter.DONE; + + // If write end callback + if (typeof this.onwriteend === "function") { + this.onwriteend({"type":"writeend", "target":this}); + } +}; + +/** + * Writes data to the file + * + * @param text to be written + */ +FileWriter.prototype.write = function(text) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + me.onwritestart({"type":"writestart", "target":me}); + } + + // Write file + PhoneGap.exec( + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // position always increases by bytes written because file would be extended + me.position += r; + // The length of the file is now where we are done writing. + me.length = me.position; + + // If onwrite callback + if (typeof me.onwrite === "function") { + me.onwrite({"type":"write", "target":me}); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + me.onwriteend({"type":"writeend", "target":me}); + } + }, + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + me.onerror({"type":"error", "target":me}); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + me.onwriteend({"type":"writeend", "target":me}); + } + }, "File", "write", [this.fileName, text, this.position]); +}; + +/** + * Moves the file pointer to the location specified. + * + * If the offset is a negative number the position of the file + * pointer is rewound. If the offset is greater than the file + * size the position is set to the end of the file. + * + * @param offset is the location to move the file pointer to. + */ +FileWriter.prototype.seek = function(offset) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (!offset) { + return; + } + + // See back from end of file. + if (offset < 0) { + this.position = Math.max(offset + this.length, 0); + } + // Offset is bigger then file size so set position + // to the end of the file. + else if (offset > this.length) { + this.position = this.length; + } + // Offset is between 0 and file size so set the position + // to start writing. + else { + this.position = offset; + } +}; + +/** + * Truncates the file to the size specified. + * + * @param size to chop the file at. + */ +FileWriter.prototype.truncate = function(size) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + me.onwritestart({"type":"writestart", "target":this}); + } + + // Write file + PhoneGap.exec( + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Update the length of the file + me.length = r; + me.position = Math.min(me.position, r); + + // If onwrite callback + if (typeof me.onwrite === "function") { + me.onwrite({"type":"write", "target":me}); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + me.onwriteend({"type":"writeend", "target":me}); + } + }, + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + me.onerror({"type":"error", "target":me}); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + me.onwriteend({"type":"writeend", "target":me}); + } + }, "File", "truncate", [this.fileName, size]); +}; + +/** + * Information about the state of the file or directory + * + * @constructor + * {Date} modificationTime (readonly) + */ +var Metadata = function() { + this.modificationTime=null; +}; + +/** + * Supplies arguments to methods that lookup or create files and directories + * + * @constructor + * @param {boolean} create file or directory if it doesn't exist + * @param {boolean} exclusive if true the command will fail if the file or directory exists + */ +var Flags = function(create, exclusive) { + this.create = create || false; + this.exclusive = exclusive || false; +}; + +/** + * An interface representing a file system + * + * @constructor + * {DOMString} name the unique name of the file system (readonly) + * {DirectoryEntry} root directory of the file system (readonly) + */ +var FileSystem = function() { + this.name = null; + this.root = null; +}; + +/** + * An interface that lists the files and directories in a directory. + * @constructor + */ +var DirectoryReader = function(fullPath){ + this.fullPath = fullPath || null; +}; + +/** + * Returns a list of entries from a directory. + * + * @param {Function} successCallback is called with a list of entries + * @param {Function} errorCallback is called with a FileError + */ +DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "readEntries", [this.fullPath]); +}; + +/** + * An interface representing a directory on the file system. + * + * @constructor + * {boolean} isFile always false (readonly) + * {boolean} isDirectory always true (readonly) + * {DOMString} name of the directory, excluding the path leading to it (readonly) + * {DOMString} fullPath the absolute full path to the directory (readonly) + * {FileSystem} filesystem on which the directory resides (readonly) + */ +var DirectoryEntry = function() { + this.isFile = false; + this.isDirectory = true; + this.name = null; + this.fullPath = null; + this.filesystem = null; +}; + +/** + * Copies a directory to a new location + * + * @param {DirectoryEntry} parent the directory to which to copy the entry + * @param {DOMString} newName the new name of the entry, defaults to the current name + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "copyTo", [this.fullPath, parent, newName]); +}; + +/** + * Looks up the metadata of the entry + * + * @param {Function} successCallback is called with a Metadata object + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.getMetadata = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getMetadata", [this.fullPath]); +}; + +/** + * Gets the parent of the entry + * + * @param {Function} successCallback is called with a parent entry + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.getParent = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getParent", [this.fullPath]); +}; + +/** + * Moves a directory to a new location + * + * @param {DirectoryEntry} parent the directory to which to move the entry + * @param {DOMString} newName the new name of the entry, defaults to the current name + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "moveTo", [this.fullPath, parent, newName]); +}; + +/** + * Removes the entry + * + * @param {Function} successCallback is called with no parameters + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.remove = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "remove", [this.fullPath]); +}; + +/** + * Returns a URI that can be used to identify this entry. + * + * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI. + * @return uri + */ +DirectoryEntry.prototype.toURI = function(mimeType) { + return "file://" + this.fullPath; +}; + +/** + * Creates a new DirectoryReader to read entries from this directory + */ +DirectoryEntry.prototype.createReader = function(successCallback, errorCallback) { + return new DirectoryReader(this.fullPath); +}; + +/** + * Creates or looks up a directory + * + * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory + * @param {Flags} options to create or excluively create the directory + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getDirectory", [this.fullPath, path, options]); +}; + +/** + * Creates or looks up a file + * + * @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file + * @param {Flags} options to create or excluively create the file + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getFile", [this.fullPath, path, options]); +}; + +/** + * Deletes a directory and all of it's contents + * + * @param {Function} successCallback is called with no parameters + * @param {Function} errorCallback is called with a FileError + */ +DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "removeRecursively", [this.fullPath]); +}; + +/** + * An interface representing a directory on the file system. + * + * @constructor + * {boolean} isFile always true (readonly) + * {boolean} isDirectory always false (readonly) + * {DOMString} name of the file, excluding the path leading to it (readonly) + * {DOMString} fullPath the absolute full path to the file (readonly) + * {FileSystem} filesystem on which the directory resides (readonly) + */ +var FileEntry = function() { + this.isFile = true; + this.isDirectory = false; + this.name = null; + this.fullPath = null; + this.filesystem = null; +}; + +/** + * Copies a file to a new location + * + * @param {DirectoryEntry} parent the directory to which to copy the entry + * @param {DOMString} newName the new name of the entry, defaults to the current name + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "copyTo", [this.fullPath, parent, newName]); +}; + +/** + * Looks up the metadata of the entry + * + * @param {Function} successCallback is called with a Metadata object + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.getMetadata = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getMetadata", [this.fullPath]); +}; + +/** + * Gets the parent of the entry + * + * @param {Function} successCallback is called with a parent entry + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.getParent = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getParent", [this.fullPath]); +}; + +/** + * Moves a directory to a new location + * + * @param {DirectoryEntry} parent the directory to which to move the entry + * @param {DOMString} newName the new name of the entry, defaults to the current name + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "moveTo", [this.fullPath, parent, newName]); +}; + +/** + * Removes the entry + * + * @param {Function} successCallback is called with no parameters + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.remove = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "remove", [this.fullPath]); +}; + +/** + * Returns a URI that can be used to identify this entry. + * + * @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI. + * @return uri + */ +FileEntry.prototype.toURI = function(mimeType) { + return "file://" + this.fullPath; +}; + +/** + * Creates a new FileWriter associated with the file that this FileEntry represents. + * + * @param {Function} successCallback is called with the new FileWriter + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.createWriter = function(successCallback, errorCallback) { + this.file(function(filePointer) { + var writer = new FileWriter(filePointer); + + if (writer.fileName === null || writer.fileName === "") { + if (typeof errorCallback === "function") { + errorCallback({ + "code": FileError.INVALID_STATE_ERR + }); + } + } + + if (typeof successCallback === "function") { + successCallback(writer); + } + }, errorCallback); +}; + +/** + * Returns a File that represents the current state of the file that this FileEntry represents. + * + * @param {Function} successCallback is called with the new File object + * @param {Function} errorCallback is called with a FileError + */ +FileEntry.prototype.file = function(successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "getFileMetadata", [this.fullPath]); +}; + +/** @constructor */ +var LocalFileSystem = function() { +}; + +// File error codes +LocalFileSystem.TEMPORARY = 0; +LocalFileSystem.PERSISTENT = 1; +LocalFileSystem.RESOURCE = 2; +LocalFileSystem.APPLICATION = 3; + +/** + * Requests a filesystem in which to store application data. + * + * @param {int} type of file system being requested + * @param {Function} successCallback is called with the new FileSystem + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) { + if (type < 0 || type > 3) { + if (typeof errorCallback === "function") { + errorCallback({ + "code": FileError.SYNTAX_ERR + }); + } + } + else { + PhoneGap.exec(successCallback, errorCallback, "File", "requestFileSystem", [type, size]); + } +}; + +/** + * + * @param {DOMString} uri referring to a local file in a filesystem + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "File", "resolveLocalFileSystemURI", [uri]); +}; + +/** +* This function returns and array of contacts. It is required as we need to convert raw +* JSON objects into concrete Contact objects. Currently this method is called after +* navigator.service.contacts.find but before the find methods success call back. +* +* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects. +* @returns an entry +*/ +LocalFileSystem.prototype._castFS = function(pluginResult) { + var entry = null; + entry = new DirectoryEntry(); + entry.isDirectory = pluginResult.message.root.isDirectory; + entry.isFile = pluginResult.message.root.isFile; + entry.name = pluginResult.message.root.name; + entry.fullPath = pluginResult.message.root.fullPath; + pluginResult.message.root = entry; + return pluginResult; +}; + +LocalFileSystem.prototype._castEntry = function(pluginResult) { + var entry = null; + if (pluginResult.message.isDirectory) { + entry = new DirectoryEntry(); + } + else if (pluginResult.message.isFile) { + entry = new FileEntry(); + } + entry.isDirectory = pluginResult.message.isDirectory; + entry.isFile = pluginResult.message.isFile; + entry.name = pluginResult.message.name; + entry.fullPath = pluginResult.message.fullPath; + pluginResult.message = entry; + return pluginResult; +}; + +LocalFileSystem.prototype._castEntries = function(pluginResult) { + var entries = pluginResult.message; + var retVal = []; + for (var i=0; i 0) + { + var constructor = PhoneGap._constructors.shift(); + try + { + constructor(); + } + catch(e) + { + if (typeof(console['log']) == 'function') + { + console.log("Failed to run constructor: " + console.processMessage(e)); + } + else + { + alert("Failed to run constructor: " + e.message); + } + } + } + // all constructors run, now fire the deviceready event + var e = document.createEvent('Events'); + e.initEvent('deviceready'); + document.dispatchEvent(e); + } + }, 1); +})(); + +// session id for calls +PhoneGap.sessionKey = 0; + +// centralized callbacks +PhoneGap.callbackId = 0; +PhoneGap.callbacks = {}; +PhoneGap.callbackStatus = { + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 + }; + +/** + * Creates a gap bridge iframe used to notify the native code about queued + * commands. + * + * @private + */ +PhoneGap.createGapBridge = function() { + gapBridge = document.createElement("iframe"); + gapBridge.setAttribute("style", "display:none;"); + gapBridge.setAttribute("height","0px"); + gapBridge.setAttribute("width","0px"); + gapBridge.setAttribute("frameborder","0"); + document.documentElement.appendChild(gapBridge); + return gapBridge; +} + +/** + * Execute a PhoneGap command by queuing it and letting the native side know + * there are queued commands. The native side will then request all of the + * queued commands and execute them. + * + * Arguments may be in one of two formats: + * + * FORMAT ONE (preferable) + * The native side will call PhoneGap.callbackSuccess or + * PhoneGap.callbackError, depending upon the result of the action. + * + * @param {Function} success The success callback + * @param {Function} fail The fail callback + * @param {String} service The name of the service to use + * @param {String} action The name of the action to use + * @param {String[]} [args] Zero or more arguments to pass to the method + * + * FORMAT TWO + * @param {String} command Command to be run in PhoneGap, e.g. + * "ClassName.method" + * @param {String[]} [args] Zero or more arguments to pass to the method + * object parameters are passed as an array object + * [object1, object2] each object will be passed as + * JSON strings + */ +PhoneGap.exec = function() { + if (!PhoneGap.available) { + alert("ERROR: Attempting to call PhoneGap.exec()" + +" before 'deviceready'. Ignoring."); + return; + } + + var successCallback, failCallback, service, action, actionArgs; + var callbackId = null; + if (typeof arguments[0] !== "string") { + // FORMAT ONE + successCallback = arguments[0]; + failCallback = arguments[1]; + service = arguments[2]; + action = arguments[3]; + actionArgs = arguments[4]; + + // Since we need to maintain backwards compatibility, we have to pass + // an invalid callbackId even if no callback was provided since plugins + // will be expecting it. The PhoneGap.exec() implementation allocates + // an invalid callbackId and passes it even if no callbacks were given. + callbackId = 'INVALID'; + } else { + // FORMAT TWO + splitCommand = arguments[0].split("."); + action = splitCommand.pop(); + service = splitCommand.join("."); + actionArgs = Array.prototype.splice.call(arguments, 1); + } + + // Start building the command object. + var command = { + className: service, + methodName: action, + arguments: [] + }; + + // Register the callbacks and add the callbackId to the positional + // arguments if given. + if (successCallback || failCallback) { + callbackId = service + PhoneGap.callbackId++; + PhoneGap.callbacks[callbackId] = + {success:successCallback, fail:failCallback}; + } + if (callbackId != null) { + command.arguments.push(callbackId); + } + + for (var i = 0; i < actionArgs.length; ++i) { + var arg = actionArgs[i]; + if (arg == undefined || arg == null) { + continue; + } else if (typeof(arg) == 'object') { + command.options = arg; + } else { + command.arguments.push(arg); + } + } + + // Stringify and queue the command. We stringify to command now to + // effectively clone the command arguments in case they are mutated before + // the command is executed. + PhoneGap.commandQueue.push(JSON.stringify(command)); + + // If the queue length is 1, then that means it was empty before we queued + // the given command, so let the native side know that we have some + // commands to execute, unless the queue is currently being flushed, in + // which case the command will be picked up without notification. + if (PhoneGap.commandQueue.length == 1 && !PhoneGap.commandQueueFlushing) { + if (!PhoneGap.gapBridge) { + PhoneGap.gapBridge = PhoneGap.createGapBridge(); + } + + PhoneGap.gapBridge.src = "gap://ready"; + } +} + +/** + * Called by native code to retrieve all queued commands and clear the queue. + */ +PhoneGap.getAndClearQueuedCommands = function() { + json = JSON.stringify(PhoneGap.commandQueue); + PhoneGap.commandQueue = []; + return json; +} + +/** + * Called by native code when returning successful result from an action. + * + * @param callbackId + * @param args + * args.status - PhoneGap.callbackStatus + * args.message - return value + * args.keepCallback - 0 to remove callback, 1 to keep callback in PhoneGap.callbacks[] + */ +PhoneGap.callbackSuccess = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + + // If result is to be sent to callback + if (args.status == PhoneGap.callbackStatus.OK) { + try { + if (PhoneGap.callbacks[callbackId].success) { + PhoneGap.callbacks[callbackId].success(args.message); + } + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + +/** + * Called by native code when returning error result from an action. + * + * @param callbackId + * @param args + */ +PhoneGap.callbackError = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + try { + if (PhoneGap.callbacks[callbackId].fail) { + PhoneGap.callbacks[callbackId].fail(args.message); + } + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + + +/** + * Does a deep clone of the object. + * + * @param obj + * @return + */ +PhoneGap.clone = function(obj) { + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + var retVal = new Array(); + for(var i = 0; i < obj.length; ++i){ + retVal.push(PhoneGap.clone(obj[i])); + } + return retVal; + } + + if (obj instanceof Function) { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + if (obj instanceof Date) { + return obj; + } + + retVal = new Object(); + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = PhoneGap.clone(obj[i]); + } + } + return retVal; +}; + +// Intercept calls to document.addEventListener +PhoneGap.m_document_addEventListener = document.addEventListener; + +// Intercept calls to window.addEventListener +PhoneGap.m_window_addEventListener = window.addEventListener; + +/** + * Add a custom window event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addWindowEventHandler = function(event, callback) { + PhoneGap.windowEventHandler[event] = callback; +} + +/** + * Add a custom document event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addDocumentEventHandler = function(event, callback) { + PhoneGap.documentEventHandler[event] = callback; +} + +/** + * Intercept adding document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_addEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept adding window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_addEventListener.call(window, evt, handler, capture); +}; + +// Intercept calls to document.removeEventListener and watch for events that +// are generated by PhoneGap native code +PhoneGap.m_document_removeEventListener = document.removeEventListener; + +// Intercept calls to window.removeEventListener +PhoneGap.m_window_removeEventListener = window.removeEventListener; + +/** + * Intercept removing document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_removeEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept removing window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_removeEventListener.call(window, evt, handler, capture); +}; + +/** + * Method to fire document event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireDocumentEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + document.dispatchEvent(e); +}; + +/** + * Method to fire window event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireWindowEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + window.dispatchEvent(e); +}; + +/** + * Method to fire event from native code + * Leaving this generic version to handle problems with iOS 3.x. Is currently used by orientation and battery events + * Remove when iOS 3.x no longer supported and call fireWindowEvent or fireDocumentEvent directly + */ +PhoneGap.fireEvent = function(type, target, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + target = target || document; + if (target.dispatchEvent === undefined) { // ie window.dispatchEvent is undefined in iOS 3.x + target = document; + } + + target.dispatchEvent(e); +}; +/** + * Create a UUID + * + * @return + */ +PhoneGap.createUUID = function() { + return PhoneGap.UUIDcreatePart(4) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(6); +}; + +PhoneGap.UUIDcreatePart = function(length) { + var uuidpart = ""; + for (var i=0; i -1) { + me._batteryListener.splice(pos, 1); + } + } else if (eventType === "batterylow") { + var pos = me._lowListener.indexOf(handler); + if (pos > -1) { + me._lowListener.splice(pos, 1); + } + } else if (eventType === "batterycritical") { + var pos = me._criticalListener.indexOf(handler); + if (pos > -1) { + me._criticalListener.splice(pos, 1); + } + } + + // If there are no more registered event listeners stop the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + PhoneGap.exec(null, null, "com.phonegap.battery", "stop", []); + } + } +}; + +/** + * Callback for battery status + * + * @param {Object} info keys: level, isPlugged + */ +Battery.prototype._status = function(info) { + if (info) { + var me = this; + if (me._level != info.level || me._isPlugged != info.isPlugged) { + // Fire batterystatus event + //PhoneGap.fireWindowEvent("batterystatus", info); + // use this workaround since iOS 3.x does have window.dispatchEvent + PhoneGap.fireEvent("batterystatus", window, info); + + // Fire low battery event + if (info.level == 20 || info.level == 5) { + if (info.level == 20) { + //PhoneGap.fireWindowEvent("batterylow", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + PhoneGap.fireEvent("batterylow", window, info); + } + else { + //PhoneGap.fireWindowEvent("batterycritical", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + PhoneGap.fireEvent("batterycritical", window, info); + } + } + } + me._level = info.level; + me._isPlugged = info.isPlugged; + } +}; + +/** + * Error callback for battery start + */ +Battery.prototype._error = function(e) { + console.log("Error initializing Battery: " + e); +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.battery === "undefined") { + navigator.battery = new Battery(); + PhoneGap.addWindowEventHandler("batterystatus", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterylow", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterycritical", navigator.battery.eventHandler); + } +}); +}if (!PhoneGap.hasResource("camera")) { + PhoneGap.addResource("camera"); + + +/** + * This class provides access to the device camera. + * @constructor + */ +Camera = function() { + +} +/** + * Available Camera Options + * {boolean} allowEdit - true to allow editing image, default = false + * {number} quality 0-100 (low to high) default = 100 + * {Camera.DestinationType} destinationType default = DATA_URL + * {Camera.PictureSourceType} sourceType default = CAMERA + * {number} targetWidth - width in pixels to scale image default = 0 (no scaling) + * {number} targetHeight - height in pixels to scale image default = 0 (no scaling) + * {Camera.EncodingType} - encodingType default = JPEG + * {boolean} correctOrientation - Rotate the image to correct for the orientation of the device during capture (iOS only) + * {boolean} saveToPhotoAlbum - Save the image to the photo album on the device after capture (iOS only) + */ +/** + * Format of image that is returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.DestinationType = { + DATA_URL: 0, // Return base64 encoded string + FILE_URI: 1 // Return file uri +}; +Camera.prototype.DestinationType = Camera.DestinationType; + +/** + * Source to getPicture from. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.PictureSourceType = { + PHOTOLIBRARY : 0, // Choose image from picture library + CAMERA : 1, // Take picture from camera + SAVEDPHOTOALBUM : 2 // Choose image from picture library +}; +Camera.prototype.PictureSourceType = Camera.PictureSourceType; + +/** + * Encoding of image returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.CAMERA, + * encodingType: Camera.EncodingType.PNG}) + */ +Camera.EncodingType = { + JPEG: 0, // Return JPEG encoded image + PNG: 1 // Return PNG encoded image +}; +Camera.prototype.EncodingType = Camera.EncodingType; + +/** + * Type of pictures to select from. Only applicable when + * PictureSourceType is PHOTOLIBRARY or SAVEDPHOTOALBUM + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY, + * mediaType: Camera.MediaType.PICTURE}) + */ +Camera.MediaType = { + PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType + VIDEO: 1, // allow selection of video only, ONLY RETURNS URL + ALLMEDIA : 2 // allow selection from all media types +}; +Camera.prototype.MediaType = Camera.MediaType; + +/** + * Gets a picture from source defined by "options.sourceType", and returns the + * image as defined by the "options.destinationType" option. + + * The defaults are sourceType=CAMERA and destinationType=DATA_URL. + * + * @param {Function} successCallback + * @param {Function} errorCallback + * @param {Object} options + */ +Camera.prototype.getPicture = function(successCallback, errorCallback, options) { + // successCallback required + if (typeof successCallback != "function") { + console.log("Camera Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback != "function")) { + console.log("Camera Error: errorCallback is not a function"); + return; + } + + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.camera","getPicture",[options]); +}; + + + +PhoneGap.addConstructor(function() { + if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); +}); +}; + +if (!PhoneGap.hasResource("device")) { + PhoneGap.addResource("device"); + +/** + * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the + * phone, etc. + * @constructor + */ +Device = function() +{ + this.platform = null; + this.version = null; + this.name = null; + this.phonegap = null; + this.uuid = null; + try + { + this.platform = DeviceInfo.platform; + this.version = DeviceInfo.version; + this.name = DeviceInfo.name; + this.phonegap = DeviceInfo.gap; + this.uuid = DeviceInfo.uuid; + + } + catch(e) + { + // TODO: + } + this.available = PhoneGap.available = this.uuid != null; +} + +PhoneGap.addConstructor(function() { + if (typeof navigator.device === "undefined") { + navigator.device = window.device = new Device(); + } +}); +}; +if (!PhoneGap.hasResource("capture")) { + PhoneGap.addResource("capture"); +/** + * The CaptureError interface encapsulates all errors in the Capture API. + */ +function CaptureError() { + this.code = null; +}; + +// Capture error codes +CaptureError.CAPTURE_INTERNAL_ERR = 0; +CaptureError.CAPTURE_APPLICATION_BUSY = 1; +CaptureError.CAPTURE_INVALID_ARGUMENT = 2; +CaptureError.CAPTURE_NO_MEDIA_FILES = 3; +CaptureError.CAPTURE_NOT_SUPPORTED = 20; + +/** + * The Capture interface exposes an interface to the camera and microphone of the hosting device. + */ +function Capture() { + this.supportedAudioModes = []; + this.supportedImageModes = []; + this.supportedVideoModes = []; +}; + +/** + * Launch audio recorder application for recording audio clip(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureAudioOptions} options + * + * No audio recorder to launch for iOS - return CAPTURE_NOT_SUPPORTED + */ +Capture.prototype.captureAudio = function(successCallback, errorCallback, options) { + /*if (errorCallback && typeof errorCallback === "function") { + errorCallback({ + "code": CaptureError.CAPTURE_NOT_SUPPORTED + }); + }*/ + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.mediacapture", "captureAudio", [options]); +}; + +/** + * Launch camera application for taking image(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureImageOptions} options + */ +Capture.prototype.captureImage = function(successCallback, errorCallback, options) { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.mediacapture", "captureImage", [options]); +}; + +/** + * Casts a PluginResult message property (array of objects) to an array of MediaFile objects + * (used in Objective-C) + * + * @param {PluginResult} pluginResult + */ +Capture.prototype._castMediaFile = function(pluginResult) { + var mediaFiles = []; + var i; + for (i=0; i} categories +* @param {ContactField[]} urls contact's web sites +*/ +var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, birthday, note, photos, categories, urls) { + this.id = id || null; + this.displayName = displayName || null; + this.name = name || null; // ContactName + this.nickname = nickname || null; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.birthday = birthday || null; // JS Date + this.note = note || null; + this.photos = photos || null; // ContactField[] + this.categories = categories || null; + this.urls = urls || null; // ContactField[] +}; + +/** +* Converts Dates to milliseconds before sending to iOS +*/ +Contact.prototype.convertDatesOut = function() +{ + var dates = new Array("birthday"); + for (var i=0; i][;base64], + * + * @param file {File} File object containing file properties + */ +FileReader.prototype.readAsDataURL = function(file) { + this.fileName = ""; + + if (typeof file.fullPath === "undefined") { + this.fileName = file; + } else { + this.fileName = file.fullPath; + } + + // LOADING state + this.readyState = FileReader.LOADING; + + // If loadstart callback + if (typeof this.onloadstart === "function") { + var evt = File._createEvent("loadstart", this); + this.onloadstart(evt); + } + + var me = this; + + // Read file + navigator.fileMgr.readAsDataURL(this.fileName, + + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save result + me.result = r; + + // If onload callback + if (typeof me.onload === "function") { + evt = File._createEvent("load", me); + me.onload(evt); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + evt = File._createEvent("loadend", me); + me.onloadend(evt); + } + }, + + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + evt = File._createEvent("loadend", me); + me.onloadend(evt); + } + } + ); +}; + +/** + * Read file and return data as a binary data. + * + * @param file The name of the file + */ +FileReader.prototype.readAsBinaryString = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +/** + * Read file and return data as a binary data. + * + * @param file The name of the file + */ +FileReader.prototype.readAsArrayBuffer = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +//----------------------------------------------------------------------------- +// File Writer +//----------------------------------------------------------------------------- + +/** + * This class writes to the mobile device file system. + * + @param file {File} a File object representing a file on the file system +*/ +FileWriter = function(file) { + this.fileName = ""; + this.length = 0; + if (file) { + this.fileName = file.fullPath || file; + this.length = file.size || 0; + } + + // default is to write at the beginning of the file + this.position = 0; + + this.readyState = 0; // EMPTY + + this.result = null; + + // Error + this.error = null; + + // Event handlers + this.onwritestart = null; // When writing starts + this.onprogress = null; // While writing the file, and reporting partial file data + this.onwrite = null; // When the write has successfully completed. + this.onwriteend = null; // When the request has completed (either in success or failure). + this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method. + this.onerror = null; // When the write has failed (see errors). +} + +// States +FileWriter.INIT = 0; +FileWriter.WRITING = 1; +FileWriter.DONE = 2; + +/** + * Abort writing file. + */ +FileWriter.prototype.abort = function() { + // check for invalid state + if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) { + throw FileError.INVALID_STATE_ERR; + } + + // set error + var error = new FileError(), evt; + error.code = error.ABORT_ERR; + this.error = error; + + // If error callback + if (typeof this.onerror === "function") { + evt = File._createEvent("error", this); + this.onerror(evt); + } + // If abort callback + if (typeof this.onabort === "function") { + evt = File._createEvent("abort", this); + this.onabort(evt); + } + + this.readyState = FileWriter.DONE; + + // If write end callback + if (typeof this.onwriteend == "function") { + evt = File._createEvent("writeend", this); + this.onwriteend(evt); + } +}; + +/** + * @Deprecated: use write instead + * + * @param file to write the data to + * @param text to be written + * @param bAppend if true write to end of file, otherwise overwrite the file + */ +FileWriter.prototype.writeAsText = function(file, text, bAppend) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (bAppend !== true) { + bAppend = false; // for null values + } + + this.fileName = file; + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + + // Write file + navigator.fileMgr.writeAsText(file, text, bAppend, + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save result + me.result = r; + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); +}; + +/** + * Writes data to the file + * + * @param text to be written + */ +FileWriter.prototype.write = function(text) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + // Write file + navigator.fileMgr.write(this.fileName, text, this.position, + + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + + // position always increases by bytes written because file would be extended + me.position += r; + // The length of the file is now where we are done writing. + me.length = me.position; + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); + +}; + +/** + * Moves the file pointer to the location specified. + * + * If the offset is a negative number the position of the file + * pointer is rewound. If the offset is greater than the file + * size the position is set to the end of the file. + * + * @param offset is the location to move the file pointer to. + */ +FileWriter.prototype.seek = function(offset) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (!offset) { + return; + } + + // See back from end of file. + if (offset < 0) { + this.position = Math.max(offset + this.length, 0); + } + // Offset is bigger then file size so set position + // to the end of the file. + else if (offset > this.length) { + this.position = this.length; + } + // Offset is between 0 and file size so set the position + // to start writing. + else { + this.position = offset; + } +}; + +/** + * Truncates the file to the size specified. + * + * @param size to chop the file at. + */ +FileWriter.prototype.truncate = function(size) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + // what if no size specified? + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + // Write file + navigator.fileMgr.truncate(this.fileName, size, + + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Update the length of the file + me.length = r; + me.position = Math.min(me.position, r); + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); +}; + +LocalFileSystem = function() { +}; + +// File error codes +LocalFileSystem.TEMPORARY = 0; +LocalFileSystem.PERSISTENT = 1; +LocalFileSystem.RESOURCE = 2; +LocalFileSystem.APPLICATION = 3; + +/** + * Requests a filesystem in which to store application data. + * + * @param {int} type of file system being requested + * @param {Function} successCallback is called with the new FileSystem + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) { + if (type < 0 || type > 3) { + if (typeof errorCallback == "function") { + errorCallback({ + "code": FileError.SYNTAX_ERR + }); + } + } + else { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.file", "requestFileSystem", [type, size]); + } +}; + +/** + * + * @param {DOMString} uri referring to a local file in a filesystem + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.file", "resolveLocalFileSystemURI", [uri]); +}; + +/** +* This function is required as we need to convert raw +* JSON objects into concrete File and Directory objects. +* +* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects. +* @returns an entry +*/ +LocalFileSystem.prototype._castFS = function(pluginResult) { + var entry = null; + entry = new DirectoryEntry(); + entry.isDirectory = pluginResult.message.root.isDirectory; + entry.isFile = pluginResult.message.root.isFile; + entry.name = pluginResult.message.root.name; + entry.fullPath = pluginResult.message.root.fullPath; + pluginResult.message.root = entry; + return pluginResult; +} + +LocalFileSystem.prototype._castEntry = function(pluginResult) { + var entry = null; + if (pluginResult.message.isDirectory) { + entry = new DirectoryEntry(); + } + else if (pluginResult.message.isFile) { + entry = new FileEntry(); + } + entry.isDirectory = pluginResult.message.isDirectory; + entry.isFile = pluginResult.message.isFile; + entry.name = pluginResult.message.name; + entry.fullPath = pluginResult.message.fullPath; + pluginResult.message = entry; + return pluginResult; +} + +LocalFileSystem.prototype._castEntries = function(pluginResult) { + var entries = pluginResult.message; + var retVal = []; + for (i=0; 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/drawable-hdpi/ic_launcher.png b/apps/files_odfviewer/src/webodf/programs/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8074c4c571b8cd19e27f4ee5545df367420686d7 GIT binary patch literal 4147 zcmV-35X|q1P)OwvMs$Q8_8nISM!^>PxsujeDCl4&hPxrxkp%Qc^^|l zp6LqAcf3zf1H4aA1Gv-O6ha)ktct9Y+VA@N^9i;p0H%6v>ZJZYQ`zEa396z-gi{r_ zDz)D=vgRv62GCVeRjK{15j7V@v6|2nafFX6W7z2j1_T0a zLyT3pGTubf1lB5)32>bl0*BflrA!$|_(WD2)iJIfV}37=ZKAC zSe3boYtQ=;o0i>)RtBvsI#iT{0!oF1VFeW`jDjF2Q4aE?{pGCAd>o8Kg#neIh*AMY zLl{;F!vLiem7s*x0<9FKAd6LoPz3~G32P+F+cuGOJ5gcC@pU_?C2fmix7g2)SUaQO$NS07~H)#fn!Q<}KQWtX}wW`g2>cMld+`7Rxgq zChaey66SG560JhO66zA!;sK1cWa2AG$9k~VQY??6bOmJsw9@3uL*z;WWa7(Nm{^TA zilc?y#N9O3LcTo2c)6d}SQl-v-pE4^#wb=s(RxaE28f3FQW(yp$ulG9{KcQ7r>7mQ zE!HYxUYex~*7IinL+l*>HR*UaD;HkQhkL(5I@UwN%Wz504M^d!ylo>ANvKPF_TvA< zkugG5;F6x}$s~J8cnev->_(Ic7%lGQgUi3n#XVo36lUpcS9s z)ympRr7}@|6WF)Ae;D{owN1;aZSR50al9h~?-WhbtKK%bDd zhML131oi1Bu1&Qb$Cp199LJ#;j5d|FhW8_i4KO1OI>}J^p2DfreMSVGY9aFlr&90t zyI2FvxQiKMFviSQeP$Ixh#70qj5O%I+O_I2t2XHWqmh2!1~tHpN3kA4n=1iHj?`@c<~3q^X6_Q$AqTDjBU`|!y<&lkqL|m5tG(b z8a!z&j^m(|;?SW(l*?tZ*{m2H9d&3jqBtXh>O-5e4Qp-W*a5=2NL&Oi62BUM)>zE3 zbSHb>aU3d@3cGggA`C-PsT9^)oy}%dHCaO~nwOrm5E54=aDg(&HR4S23Oa#-a^=}w%g?ZP-1iq8PSjE8jYaGZu z$I)?YN8he?F9>)2d$G6a*zm0XB*Rf&gZAjq(8l@CUDSY1tB#!i> zW$VfG%#SYSiZ};)>pHA`qlfDTEYQEwN6>NNEp+uxuqx({Fgr zjI@!4xRc?vk^9+~eU|mzH__dCDI=xb{Cd}4bELS9xRaS!*FXMwtMR-RR%SLMh0Cjl zencr8#Su<4(%}$yGVBU-HX{18v=yPH*+%^Vtknc>2A;%-~DrYFx^3XfuVgvZ{#1tA== zm3>IzAM2{3Iv_d1XG{P6^tN3|PkJMnjs&CWN7%7_CmjoVakUhsa&dMv==2~^ri?&x zVdv*rnfVyM+I1^Kg*S=23mR@+0T9BWFZUu~@toA8d)fw6be=`Yb6DSX6D?jB%2YT~ z*aHjtIOozfMhA!Jd*?u5_n!SnX>vX`=Ti-1HA4RiE>eI3vTn zz+>Ccf0HX6Ans-ebOB>RJST-Cyr#4XAk+mAlJgdQnoE{^iIN)OcYFSpgJUmXtl@tT z-^ZuUeSj5hSFrQwqX>~EtZ*{>Gi8Bu9_|o06oNtaXP?E936!a@DsvS*tsB@fa6kEA z5GkjwmH?EgpiG&itsB_Tb1NxtFnvxh_s@9KYX1Sttf?AlI~)z zT=6Y7ulx=}<8Scr_UqU-_z)5gPo%050PsbM*ZLno;_-ow&k?FZJtYmb2hPA$LkP)8 z=^d0Q6PImh6Y|QT?{grxj)S=uBKvY2EQUbm@ns9^yKiP~$DcD)c$5Em`zDSScH%iH zVov&m=cMo`1tYwA=!a}vb_ef_{)Q2?FUqn>BR$6phXQRv^1%=YfyE-F$AR4Q?9D!f zCzB^^#td~4u&l~l#rp2QLfe3+_ub9@+|x+m;=2(sQ`s%gO|j$XBb>A7Q(UydipiMw%igcweV#Cr~SP);q>w`bxts_4} znKHg?X==JDkQl3Y>Ckt%`s{n?Nq-1Fw5~%Mq$CAsi-`yu_bKm zxs#QdE7&vgJD%M84f4SNzSDv)S|V?|$!d5a#lhT5>>YWE4NGqa9-fbmV$=)@k&32kdEYetna>=j@0>V8+wRsL;po!3ivVwh<9tn z2S<1u9DAAQ>x1Sn=fk`)At|quvleV($B|#Kap_lB-F^*yV=wZ{9baUu(uXfokr95^ zA*!*W=5a>$2Ps`-F^+qRQT^{*cN>vipT*4!r#p%{(#I7s z0NN94*q?ib$KJjfDI_sjHNdmEVp5wB&j54O#VoFqBwy)gfA$%)4d_X4q${L9Xom2R3xy&ZBSNgt4a1d7K^CDWa9r zVb-_52m}Vp)`9;ZSKd#|U4ZYj5}Gp49{4utST|=c`~(#>KHF6}CCov1iHYw zt{bWo)A@yF2$~c(nR$rSAaFQ$(Wh{vkG1AlutDMw=mM`C`T=X&|Ad9fb5Od}ROt1z zOpczHqrb4Jo^rSCiW#&o(m7jFamnrsTpQb;*h4o8r#$aZ}2RaT-x2u^^ z%u@YyIv$U^u~@9(XGbSwU@fk6SikH>j+D1jQrYTKGJpW%vUT{!d}7THI5&Sa?~MKy zS0-mvMl+BOcroEJ@hN!2H_?coTEJ5Q<;Nd?yx;eIj4{$$E2?YUO|NtNPJ-PdDf;s} zab;}Mz0kbOI}5*w@3gROcnl#5)wQnEhDBfn!Xhy`u>C}*E~vWpO^HS)FC>8^umI=+ z&H;LW6w#;EF`}vQd_9Muru`KnQVPI9U?(sD)&Dg-0j3#(!fNKVZ_GoYH{la~d*1Yh$TI-TL>mI4vpNb@sU2=IZ8vL%AXUx0 zz{K0|nK(yizLHaeW#ZhRfQXoK^}1$=$#1{Yn002ovPDHLkV1n#w+^+xt literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/drawable-ldpi/ic_launcher.png b/apps/files_odfviewer/src/webodf/programs/android/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..1095584ec21f71cd0afc9e0993aa2209671b590c GIT binary patch literal 1723 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 JPDHLkV1lAbd;S0b literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/layout/listitem.xml b/apps/files_odfviewer/src/webodf/programs/android/res/layout/listitem.xml new file mode 100644 index 0000000000..f0958d609d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/res/layout/listitem.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/layout/main.xml b/apps/files_odfviewer/src/webodf/programs/android/res/layout/main.xml new file mode 100644 index 0000000000..bc12cd8231 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/layout/selector.xml b/apps/files_odfviewer/src/webodf/programs/android/res/layout/selector.xml new file mode 100644 index 0000000000..4af1380e95 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/res/layout/selector.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/values/strings.xml b/apps/files_odfviewer/src/webodf/programs/android/res/values/strings.xml new file mode 100644 index 0000000000..44673ed78b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Hello World, WebODFActivity! + WebODF + + \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/xml/phonegap.xml b/apps/files_odfviewer/src/webodf/programs/android/res/xml/phonegap.xml new file mode 100755 index 0000000000..97f31ea110 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/res/xml/phonegap.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/android/res/xml/plugins.xml b/apps/files_odfviewer/src/webodf/programs/android/res/xml/plugins.xml new file mode 100644 index 0000000000..3d8d48d838 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/res/xml/plugins.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/android/src/org/webodf/WebODFActivity.java b/apps/files_odfviewer/src/webodf/programs/android/src/org/webodf/WebODFActivity.java new file mode 100644 index 0000000000..9c826c9210 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/src/org/webodf/WebODFActivity.java @@ -0,0 +1,33 @@ +package org.webodf; + +import android.os.Bundle; + +import com.phonegap.DroidGap; + +public class WebODFActivity extends DroidGap { + + private String path; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + path = null; + if (getIntent() != null && getIntent().getData() != null) { + path = getIntent().getData().getPath(); + } + setContentView(R.layout.main); + super.loadUrl("file:///android_asset/www/index.html"); + } + + @Override + protected void onResume() { + super.onResume(); + if (path == null) { + return; + } + String escapedPath = "file://" + path.replace("'", "\\'"); + sendJavascript("invokeString = '" + escapedPath + "';"); + } + +} \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/android/updateWebODF.sh b/apps/files_odfviewer/src/webodf/programs/android/updateWebODF.sh new file mode 100755 index 0000000000..b51e94290b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/android/updateWebODF.sh @@ -0,0 +1,3 @@ +# /bin/bash +cd assets +for f in `find . -type f`; do cp ../../webodf/$f $f; done diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/docnosis/CMakeLists.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.0-os.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.0-os.rng new file mode 100644 index 0000000000..97fe580eab --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.0-os.rng @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.1.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.1.rng new file mode 100644 index 0000000000..4082d4ba95 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-manifest-schema-v1.1.rng @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.0-os.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.0-os.rng new file mode 100644 index 0000000000..cf4ee51741 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.0-os.rng @@ -0,0 +1,17666 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + boolean + short + int + long + double + string + datetime + base64Binary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + simple + + + + + replace + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + float + + + + + + date + + + + + + time + + + + + + boolean + + + + + + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + none + + + + + condition + + + + + + + + + + + + + + + + + + + + + simple + + + + + embed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + footnote + endnote + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous + current + next + + + + + + + + + + + + + + previous + next + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + number + number-and-name + plain-number-and-name + plain-number + + + + + + + + + + + + + + + + + + + full + path + name + name-and-extension + + + + + + + + + + + + + + + + + + full + path + name + name-and-extension + area + title + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:page-count + text:paragraph-count + text:word-count + text:character-count + text:table-count + text:image-count + text:object-count + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + command + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + table + text-box + image + object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:reference-ref + text:bookmark-ref + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page + chapter + direction + text + + + + + + + + + page + chapter + direction + text + category-and-value + caption + value + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value + unit + gap + + + + + + + + + + + + + + + + + + + + + + + + + float + + + + + + + + percentage + + + + + + + + currency + + + + + + + + + + + + + date + + + + + + + + time + + + + + + + + boolean + + + + + + + + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value + none + + + + + + + + + value + formula + none + + + + + + + + + value + formula + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:identifier + text:address + text:annote + text:author + text:booktitle + text:chapter + text:edition + text:editor + text:howpublished + text:institution + text:journal + text:month + text:note + text:number + text:organizations + text:pages + text:publisher + text:school + text:series + text:title + text:report-type + text:volume + text:year + text:url + text:custom1 + text:custom2 + text:custom3 + text:custom4 + text:custom5 + text:isbn + text:issn + + + + + + + + + + article + book + booklet + conference + custom1 + custom2 + custom3 + custom4 + custom5 + email + inbook + incollection + inproceedings + journal + manual + mastersthesis + misc + phdthesis + proceedings + techreport + unpublished + www + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + category-and-value + caption + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 3 + separator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + number + number-and-name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + address + annote + author + bibliography-type + booktitle + chapter + custom1 + custom2 + custom3 + custom4 + custom5 + edition + editor + howpublished + identifier + institution + isbn + issn + journal + month + note + number + organizations + pages + publisher + report-type + school + series + title + url + volume + year + + + + + + + + + + + + + + + + + + + + + + + + right + + + + left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + collapse + filter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ($?([^\. ']+|'[^']+'))?\.$?[A-Z]+$?[0-9]+ + + + + + ($?([^\. ']+|'[^']+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. ']+|'[^']+'))?\.$?[A-Z]+$?[0-9]+)? + + + + + + + + + + + + + + + + + + + copy-all + copy-results-only + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + trace-dependents + remove-dependents + trace-precedents + remove-precedents + trace-errors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + from-another-table + to-another-table + from-same-table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enable + disable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + unsorted + sort-ascending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + stop + warning + information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + column + row + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + print-range + filter + repeat-row + repeat-column + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + column + row + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + automatic + + + + + + + + + + ascending + descending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + automatic + + + + + + + + + + ascending + descending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + self + cell-range + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + data + hidden + + + + + page + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + from-top + from-bottom + + + + + + + + + + + + + + data + + + + + + + + none + manual + name + + + + + + + + ascending + descending + + + + + + + + + + + + + tabular-layout + outline-subtotals-top + outline-subtotals-bottom + + + + + + + + + + + + + + + + + + + + + + + named + + + + + + + + previous + next + + + + + + + + none + member-difference + member-percentage + member-percentage-difference + running-total + row-percentage + column-percentage + total-percentage + index + + + + + + + + + + + + + + + + + + + + + + auto + + + + + + auto + + + + + + + + + + auto + + + + + + auto + + + + + + + + + + + + + seconds + minutes + hours + days + months + quarters + years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + accepted + rejected + pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always + screen + printer + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + full + section + cut + arc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + standard + lines + line + curve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page + frame + paragraph + char + as-char + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top-left + top + top-right + left + center + right + bottom-left + bottom-right + + + + + + + auto + left + right + up + down + horizontal + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + scale + scale-min + + + + + + + + scale + scale-min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + onRequest + + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + nohref + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + parallel + perspective + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + phong + gouraud + draft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + non-primitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + phong + gouraud + draft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + parallel + perspective + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + segments + rectangle + + + + + + + + + + + + + + + + + + + + + normal + path + shape + + + + + + + + + path + shape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + title + outline + subtitle + text + graphic + object + chart + table + orgchart + page + notes + handout + header + footer + date-time + page-number + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + fade + move + stripes + open + close + dissolve + wavyline + random + lines + laser + appear + hide + move-short + checkerboard + rotate + stretch + + + + + + + + + + + + none + from-left + from-top + from-right + from-bottom + from-center + from-upper-left + from-upper-right + from-lower-left + from-lower-right + to-left + to-top + to-right + to-bottom + to-upper-left + to-upper-right + to-lower-right + to-lower-left + path + spiral-inward-left + spiral-inward-right + spiral-outward-left + spiral-outward-right + vertical + horizontal + to-center + clockwise + counter-clockwise + + + + + + + + + + + + slow + medium + fast + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + on-click + with-previous + after-previous + timing-root + main-sequence + interactive-sequence + + + + + + + + + + + + + + + + + + + + + + + custom + entrance + exit + emphasis + motion-path + ole-action + media-call + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + previous-page + next-page + first-page + last-page + hide + stop + execute + show + verb + fade-out + sound + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + current-date + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enabled + disabled + + + + + + + + + enabled + disabled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + end + top + bottom + + + + + + start + center + end + + + + + + + top-start + bottom-start + top-end + bottom-end + + + + + + + + + + + + + wide + high + balanced + + + + + custom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x + y + z + + + + + + + + + + + + + + + + + + + + + + + + + + + major + minor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + get + post + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + command + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + current + parent + + + + + + + + + + + + + + + + + + + records + current + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + unchecked + checked + unknown + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + submit + reset + push + url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + 3d + + + + + + + + + center + + + + + + start + end + top + bottom + + + + + + start + center + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + sql + sql-pass-through + value-list + table-fields + + + + + + + + + + + + + + + + + + + + + + + + + + + void + + + + + + + + + + + + + + float + + + + + + + + + + + + percentage + + + + + + + + + + + + currency + + + + + + + + + + + + + + + + + date + + + + + + + + + + + + time + + + + + + + + + + + + boolean + + + + + + + + + + + + string + + + + + + + + + + + void + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + i + I + + + + + + + + a + A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + into-default-style-data-style + into-english-number + keep-text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + discrete + linear + paced + spline + + + + + + + + + + + + + + + + + + + + + rgb + hsl + + + + + + + + + clockwise + counter-clockwise + + + + + + + + + + + + + + + + + + translate + scale + rotate + skewX + skewY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + forward + reverse + + + + + + + + + forward + reverse + + + + + + + + + in + out + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + discrete + linear + paced + spline + + + + + + + + + + + + + + + + + + + + + + + none + sum + + + + + + + + + replace + sum + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + first + last + all + media + + + + + + + + + + + + + + + + + + + remove + freeze + hold + auto + default + transition + + + + + + + + + remove + freeze + hold + transition + auto + inherit + + + + + + + + + never + always + whenNotActive + default + + + + + + + + + never + always + whenNotActive + inherit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + left + right + mirrored + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + ultra-condensed + extra-condensed + condensed + semi-condensed + semi-expanded + expanded + extra-expanded + ultra-expanded + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + language + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + medium + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gregorian + gengou + ROC + hanja_yoil + hanja + hijri + jewish + buddhist + + + + + + + + + text + + + + + + + + + + paragraph + + + + + + + + + + + + + section + + + + + + + + + + ruby + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + rigth + inner + outer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + page + + + + + + + + + text + page + section + document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + address + annote + author + bibliography-type + booktitle + chapter + custom1 + custom2 + custom3 + custom4 + custom5 + edition + editor + howpublished + identifier + institution + isbn + issn + journal + month + note + number + organizations + pages + publisher + report-type + school + series + title + url + volume + year + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + + + + + + + + + + table-column + + + + + + + + + + table-row + + + + + + + + + + table-cell + + + + + + + + + + + + + + + + + graphic + presentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + drawing-page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + linear + axial + radial + ellipsoid + square + rectangular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + objectBoundingBox + + + + + + + + + + + pad + reflect + repeat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + single + double + triple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rect + round + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + chart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + + + + + + + + + + portrait + landscape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + headers + grid + annotations + objects + charts + drawings + formulas + zero-values + + + + + + + + + + + ttb + ltr + + + + + + + + + + continue + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + both + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + + + + + + + + + + + + + + + none + line + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + small-caps + + + + + + + none + lowercase + uppercase + capitalize + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + super + sub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + roman + swiss + modern + decorative + script + system + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + variable + + + + + + + + + + + + + [A-Za-z][A-Za-z0-9._\-]* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + latin + asian + complex + ignore + + + + + + + + + + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + italic + oblique + + + + + + + none + embossed + engraved + + + + + + + + + + + + + + + none + + + + + + + + + + + + + + + none + single + double + + + + + + + + + + + + + none + solid + dotted + dash + long-dash + dot-dash + dot-dot-dash + wave + + + + + + + + + + + + + auto + normal + bold + thin + dash + medium + thick + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + normal + bold + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 + + + + + + + + + + + + + continuous + skip-white-space + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + letters + lines + + + + + + + + + + + + + + + + + + + + + none + + + none + accent + dot + circle + disc + + + above + below + + + + + + + + + + + + + + + + + + + + + + + + + fixed + line-height + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + none + + + + condition + + + none + + + + + + + + + + + + + + + + + + + + + + + + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + end + left + right + center + justify + + + + + + + + + start + center + justify + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + + char + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + page + + + + + + + + + no-limit + + + + + + + + + + + + + + + + + + + + + + word + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + column + page + + + + + + + auto + column + page + + + + + + + + + + + + + transparent + + + + + + + + + + + + + + + + + + + + + + + + + + no-repeat + repeat + stretch + + + + + + + + + left + center + right + top + bottom + + + + + + + + + + + + + + + + left + center + right + + + + + top + center + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + none + ideograph-alpha + + + + + + + + + simple + hanging + + + + + + + + + normal + strict + + + + + + + + + top + middle + bottom + auto + + + + + + + + + + + + + lr-tb + rl-tb + tb-rl + tb-lr + lr + rl + tb + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + above + below + + + + + + + + + left + center + right + distribute-letter + distribute-space + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + solid + dotted + dashed + dot-dashed + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + margins + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + collapsing + separating + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + automatic + + + + + + + + + fix + value-type + + + + + + + + + + + + + ltr + ttb + + + + + + + + + auto + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-wrap + wrap + + + + + + + + + + + + + + + + + + + + none + bottom + top + center + + + + + + + + + none + hidden-and-protected + + + + protected + formula-hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + dash + solid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + miter + round + bevel + middle + none + inherit + + + + + + + + + none + solid + bitmap + gradient + hatch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-repeat + repeat + stretch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top-left + top + top-right + left + center + right + bottom-left + bottom + bottom-right + + + + + + + + + + + + + + + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + + + none + scroll + alternate + slide + + + + + + + + + left + right + up + down + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + justify + + + + + + + + + left + center + right + justify + + + + + + + + + no-wrap + wrap + + + + + + + + + + + + + + greyscale + mono + watermark + standard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + below + above + + + + + + + + + + + + + + + + automatic + left-outside + inside + right-outside + + + + + + + automatic + above + below + center + + + + + + + + + automatic + mm + cm + m + km + pt + pc + inch + ft + mi + + + + + + + + + + + + + + + + + + + + + + + straight-line + angled-line + angled-connector-line + + + + + + + + + fixed + free + + + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + auto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + correct + attractive + + + + + + + + + + + + + + + + + + + + + + + enabled + disabled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + standard + double-sided + + + + + + + + + object + flat + sphere + + + + + + + + + normal + inverse + + + + + + + + + object + parallel + sphere + + + + + + + object + parallel + sphere + + + + + + + + + luminance + intesity + color + + + + + + + + + enabled + disabled + + + + + + + + + replace + modulate + blend + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + content + position + size + + + + + + + + + + + + left + center + right + from-left + inside + outside + from-inside + + + + + + + + + + + + + + page + page-content + page-start-margin + page-end-margin + frame + frame-content + frame-start-margin + frame-end-margin + paragraph + paragraph-content + paragraph-start-margin + paragraph-end-margin + char + + + + + + + + + + + + + top + middle + bottom + from-top + below + + + + + + + + + + + + + + + + + + page + page-content + frame + frame-content + paragraph + paragraph-content + char + line + baseline + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + left + right + parallel + dynamic + run-through + biggest + + + + + + + + + + + + + + + + no-limit + + + + + + + + + + + + + + + + + full + outside + + + + + + + + + foreground + background + + + + + + + + + + + + + + + + clip + auto-create-new-frame + + + + + + + + + none + vertical + + + vertical + + + + + vertical + + + + + + + + + horizontal + horizontal-on-odd + horizontal-on-even + + + + + + + + + + + + + + + iterative + once-concurrent + once-successive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)(px) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + automatic + + + + named-symbol + + + + square + diamond + arrow-down + arrow-up + arrow-right + arrow-left + bow-tie + hourglass + circle + star + x + plus + asterisk + horizontal-bar + vertical-bar + + + + + + image + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + cubic-spline + b-spline + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cuboid + cylinder + cone + pyramid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + side-by-side + stagger-even + stagger-odd + + + + + + + + + + + + + + + none + value + percentage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + variance + standard-deviation + percentage + error-margin + constant + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + columns + rows + + + + + + + + + none + linear + logarithmic + exponential + power + + + + + + + + + manual + automatic + semi-automatic + + + + + + + + + none + fade-from-left + fade-from-top + fade-from-right + fade-from-bottom + fade-from-upperleft + fade-from-upperright + fade-from-lowerleft + fade-from-lowerright + move-from-left + move-from-top + move-from-right + move-from-bottom + move-from-upperleft + move-from-upperright + move-from-lowerleft + move-from-lowerright + uncover-to-left + uncover-to-top + uncover-to-right + uncover-to-bottom + uncover-to-upperleft + uncover-to-upperright + uncover-to-lowerleft + uncover-to-lowerright + fade-to-center + fade-from-center + vertical-stripes + horizontal-stripes + clockwise + counterclockwise + open-vertical + open-horizontal + close-vertical + close-horizontal + wavyline-from-left + wavyline-from-top + wavyline-from-right + wavyline-from-bottom + spiralin-left + spiralin-right + spiralout-left + spiralout-right + roll-from-top + roll-from-left + roll-from-right + roll-from-bottom + stretch-from-left + stretch-from-top + stretch-from-right + stretch-from-bottom + + vertical-lines + horizontal-lines + dissolve + random + vertical-checkerboard + horizontal-checkerboard + interlocking-horizontal-left + interlocking-horizontal-right + interlocking-vertical-top + interlocking-vertical-bottom + fly-away + open + close + melt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + forward + reverse + + + + + + + + + forward + reverse + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + full + border + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + + + + + + + + + + + + + + + + + [A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})* + + + + + [A-Za-z0-9]{1,8} + + + + + [A-Za-z]{1,8} + + + + + 1 + + + + + -?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + + -?([0-9]+(\.[0-9]*)?|\.[0-9]+)% + + + + + [0-9]+\* + + + + + + + + + + + #[0-9a-fA-F]{6} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _self + _blank + _parent + _top + + + + + + + float + time + date + percentage + currency + boolean + string + + + + + + -?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)* + + + + + + + + + \([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\) + + + + + + + [0-9a-zA-Z_]+:[0-9a-zA-Z._\-]+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.1.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.1.rng new file mode 100644 index 0000000000..3ba6a687c4 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-schema-v1.1.rng @@ -0,0 +1,17891 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + boolean + short + int + long + double + string + datetime + base64Binary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + simple + + + + + replace + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + float + + + + + + date + + + + + + time + + + + + + boolean + + + + + + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + none + + + + + condition + + + + + + + + + + + + + + + + + + + + + simple + + + + + embed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + footnote + endnote + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous + current + next + + + + + + + + + + + + + + previous + next + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + number + number-and-name + plain-number-and-name + plain-number + + + + + + + + + + + + + + + + + + + full + path + name + name-and-extension + + + + + + + + + + + + + + + + + + full + path + name + name-and-extension + area + title + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:page-count + text:paragraph-count + text:word-count + text:character-count + text:table-count + text:image-count + text:object-count + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + command + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + table + text-box + image + object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:reference-ref + text:bookmark-ref + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page + chapter + direction + text + + + + + + + + + page + chapter + direction + text + category-and-value + caption + value + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value + unit + gap + + + + + + + + + + + + + + + + + + + + + + + + + float + + + + + + + + percentage + + + + + + + + currency + + + + + + + + + + + + + date + + + + + + + + time + + + + + + + + boolean + + + + + + + + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value + none + + + + + + + + + value + formula + none + + + + + + + + + value + formula + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:identifier + text:address + text:annote + text:author + text:booktitle + text:chapter + text:edition + text:editor + text:howpublished + text:institution + text:journal + text:month + text:note + text:number + text:organizations + text:pages + text:publisher + text:school + text:series + text:title + text:report-type + text:volume + text:year + text:url + text:custom1 + text:custom2 + text:custom3 + text:custom4 + text:custom5 + text:isbn + text:issn + + + + + + + + + + article + book + booklet + conference + custom1 + custom2 + custom3 + custom4 + custom5 + email + inbook + incollection + inproceedings + journal + manual + mastersthesis + misc + phdthesis + proceedings + techreport + unpublished + www + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + category-and-value + caption + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 3 + separator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + number + number-and-name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + address + annote + author + bibliography-type + booktitle + chapter + custom1 + custom2 + custom3 + custom4 + custom5 + edition + editor + howpublished + identifier + institution + isbn + issn + journal + month + note + number + organizations + pages + publisher + report-type + school + series + title + url + volume + year + + + + + + + + + + + + + + + + + + + + + + + + right + + + + left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + collapse + filter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+ + + + + + + ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)? + + + + + + + + + + + + + + + + + + + copy-all + copy-results-only + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + trace-dependents + remove-dependents + trace-precedents + remove-precedents + trace-errors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + from-another-table + to-another-table + from-same-table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enable + disable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + unsorted + sort-ascending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + stop + warning + information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + column + row + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + print-range + filter + repeat-row + repeat-column + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + column + row + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + automatic + + + + + + + + + + ascending + descending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + automatic + + + + + + + + + + ascending + descending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + self + cell-range + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + data + hidden + + + + + page + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + from-top + from-bottom + + + + + + + + + + + + + + data + + + + + + + + none + manual + name + + + + + + + + ascending + descending + + + + + + + + + + + + + tabular-layout + outline-subtotals-top + outline-subtotals-bottom + + + + + + + + + + + + + + + + + + + + + + + named + + + + + + + + previous + next + + + + + + + + none + member-difference + member-percentage + member-percentage-difference + running-total + row-percentage + column-percentage + total-percentage + index + + + + + + + + + + + + + + + + + + + + + + auto + + + + + + auto + + + + + + + + + + auto + + + + + + auto + + + + + + + + + + + + + seconds + minutes + hours + days + months + quarters + years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + accepted + rejected + pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always + screen + printer + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + full + section + cut + arc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + standard + lines + line + curve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page + frame + paragraph + char + as-char + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top-left + top + top-right + left + center + right + bottom-left + bottom-right + + + + + + + + auto + left + right + up + down + horizontal + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + scale + scale-min + + + + + + + + scale + scale-min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + onRequest + + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + nohref + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + parallel + perspective + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + phong + gouraud + draft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + non-primitive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + phong + gouraud + draft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + parallel + perspective + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + segments + rectangle + + + + + + + + + + + + + + + + + + + + + normal + path + shape + + + + + + + + + path + shape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + title + outline + subtitle + text + graphic + object + chart + table + orgchart + page + notes + handout + header + footer + date-time + page-number + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + fade + move + stripes + open + close + dissolve + wavyline + random + lines + laser + appear + hide + move-short + checkerboard + rotate + stretch + + + + + + + + + + + + none + from-left + from-top + from-right + from-bottom + from-center + from-upper-left + from-upper-right + from-lower-left + from-lower-right + to-left + to-top + to-right + to-bottom + to-upper-left + to-upper-right + to-lower-right + to-lower-left + path + spiral-inward-left + spiral-inward-right + spiral-outward-left + spiral-outward-right + vertical + horizontal + to-center + clockwise + counter-clockwise + + + + + + + + + + + + slow + medium + fast + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + on-click + with-previous + after-previous + timing-root + main-sequence + interactive-sequence + + + + + + + + + + + + + + + + + + + + + + + custom + entrance + exit + emphasis + motion-path + ole-action + media-call + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + previous-page + next-page + first-page + last-page + hide + stop + execute + show + verb + fade-out + sound + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + current-date + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enabled + disabled + + + + + + + + + enabled + disabled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + end + top + bottom + + + + + + start + center + end + + + + + + + top-start + bottom-start + top-end + bottom-end + + + + + + + + + + + + + wide + high + balanced + + + + + custom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x + y + z + + + + + + + + + + + + + + + + + + + + + + + + + + + major + minor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + get + post + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + command + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + current + parent + + + + + + + + + + + + + + + + + + + records + current + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + unchecked + checked + unknown + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + submit + reset + push + url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + 3d + + + + + + + + + center + + + + + + start + end + top + bottom + + + + + + start + center + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + sql + sql-pass-through + value-list + table-fields + + + + + + + + + + + + + + + + + + + + + + + + + + + void + + + + + + + + + + + + + + float + + + + + + + + + + + + percentage + + + + + + + + + + + + currency + + + + + + + + + + + + + + + + + date + + + + + + + + + + + + time + + + + + + + + + + + + boolean + + + + + + + + + + + + string + + + + + + + + + + + void + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + i + I + + + + + + + + a + A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + into-default-style-data-style + into-english-number + keep-text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + discrete + linear + paced + spline + + + + + + + + + + + + + + + + + + + + + rgb + hsl + + + + + + + + + clockwise + counter-clockwise + + + + + + + + + + + + + + + + + + translate + scale + rotate + skewX + skewY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + forward + reverse + + + + + + + + + forward + reverse + + + + + + + + + in + out + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + discrete + linear + paced + spline + + + + + + + + + + + + + + + + + + + + + + + none + sum + + + + + + + + + replace + sum + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + first + last + all + media + + + + + + + + + + + + + + + indefinite + + + + + + + + + remove + freeze + hold + auto + default + transition + + + + + + + + + remove + freeze + hold + transition + auto + inherit + + + + + + + + + never + always + whenNotActive + default + + + + + + + + + never + always + whenNotActive + inherit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + left + right + mirrored + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + ultra-condensed + extra-condensed + condensed + semi-condensed + semi-expanded + expanded + extra-expanded + ultra-expanded + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + language + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + medium + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gregorian + gengou + ROC + hanja_yoil + hanja + hijri + jewish + buddhist + + + + + + + + + text + + + + + + + + + + paragraph + + + + + + + + + + + + + section + + + + + + + + + + ruby + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + right + inner + outer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + page + + + + + + + + + text + page + section + document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + address + annote + author + bibliography-type + booktitle + chapter + custom1 + custom2 + custom3 + custom4 + custom5 + edition + editor + howpublished + identifier + institution + isbn + issn + journal + month + note + number + organizations + pages + publisher + report-type + school + series + title + url + volume + year + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + + + + + + + + + + table-column + + + + + + + + + + table-row + + + + + + + + + + table-cell + + + + + + + + + + + + + + + + + graphic + presentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + drawing-page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + linear + axial + radial + ellipsoid + square + rectangular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + objectBoundingBox + + + + + + + + + + + pad + reflect + repeat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + single + double + triple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rect + round + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + chart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + + + + + + + + + + portrait + landscape + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + headers + grid + annotations + objects + charts + drawings + formulas + zero-values + + + + + + + + + + + ttb + ltr + + + + + + + + + + continue + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + both + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + + + + + + + + + + + + + + + none + line + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + small-caps + + + + + + + none + lowercase + uppercase + capitalize + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + super + sub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + roman + swiss + modern + decorative + script + system + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + variable + + + + + + + + + + + + + + + + + + + + + + + [A-Za-z][A-Za-z0-9._\-]* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + latin + asian + complex + ignore + + + + + + + + + + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + italic + oblique + + + + + + + none + embossed + engraved + + + + + + + + + + + + + + + none + + + + + + + + + + + + + + + none + single + double + + + + + + + + + + + + + none + solid + dotted + dash + long-dash + dot-dash + dot-dot-dash + wave + + + + + + + + + + + + + auto + normal + bold + thin + dash + medium + thick + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + normal + bold + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 + + + + + + + + + + + + + continuous + skip-white-space + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + letters + lines + + + + + + + + + + + + + + + + + + + + + none + + + none + accent + dot + circle + disc + + + above + below + + + + + + + + + + + + + + + + + + + + + + + + + fixed + line-height + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + none + + + + condition + + + none + + + + + + + + + + + + + + + + + + + + + + + + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + end + left + right + center + justify + + + + + + + + + start + center + justify + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + + char + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + page + + + + + + + + + no-limit + + + + + + + + + + + + + + + + + + + + + + word + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + column + page + + + + + + + auto + column + page + + + + + + + + + + + + + transparent + + + + + + + + + + + + + + + + + + + + + + + + + + no-repeat + repeat + stretch + + + + + + + + + left + center + right + top + bottom + + + + + + + + + + + + + + + + left + center + right + + + + + top + center + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + none + ideograph-alpha + + + + + + + + + simple + hanging + + + + + + + + + normal + strict + + + + + + + + + top + middle + bottom + auto + baseline + + + + + + + + + + + + + lr-tb + rl-tb + tb-rl + tb-lr + lr + rl + tb + page + + + + + + + + + + + + + + + + + + + + + + + + + + auto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + above + below + + + + + + + + + left + center + right + distribute-letter + distribute-space + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + solid + dotted + dashed + dot-dashed + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + margins + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + collapsing + separating + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + automatic + + + + + + + + + fix + value-type + + + + + + + + + + + + + ltr + ttb + + + + + + + + + auto + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-wrap + wrap + + + + + + + + + + + + + + + + + + + + none + bottom + top + center + + + + + + + + + none + hidden-and-protected + + + + protected + formula-hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + dash + solid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + miter + round + bevel + middle + none + inherit + + + + + + + + + none + solid + bitmap + gradient + hatch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-repeat + repeat + stretch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top-left + top + top-right + left + center + right + bottom-left + bottom + bottom-right + + + + + + + + + + + + + + + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + + + none + scroll + alternate + slide + + + + + + + + + left + right + up + down + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + justify + + + + + + + + + left + center + right + justify + + + + + + + + + no-wrap + wrap + + + + + + + + + + + + + + greyscale + mono + watermark + standard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + below + above + + + + + + + + + + + + + + + + automatic + left-outside + inside + right-outside + + + + + + + automatic + above + below + center + + + + + + + + + automatic + mm + cm + m + km + pt + pc + inch + ft + mi + + + + + + + + + + + + + + + + + + + + + + + straight-line + angled-line + angled-connector-line + + + + + + + + + fixed + free + + + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + auto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + correct + attractive + + + + + + + + + + + + + + + + + + + + + + + enabled + disabled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + standard + double-sided + + + + + + + + + object + flat + sphere + + + + + + + + + normal + inverse + + + + + + + + + object + parallel + sphere + + + + + + + object + parallel + sphere + + + + + + + + + luminance + intensity + color + + + + + + + + + enabled + disabled + + + + + + + + + replace + modulate + blend + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + content + position + size + + + + + + + + + + + + left + center + right + from-left + inside + outside + from-inside + + + + + + + + + + + + + + page + page-content + page-start-margin + page-end-margin + frame + frame-content + frame-start-margin + frame-end-margin + paragraph + paragraph-content + paragraph-start-margin + paragraph-end-margin + char + + + + + + + + + + + + + top + middle + bottom + from-top + below + + + + + + + + + + + + + + + + + + page + page-content + frame + frame-content + paragraph + paragraph-content + char + line + baseline + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + left + right + parallel + dynamic + run-through + biggest + + + + + + + + + + + + + + + + no-limit + + + + + + + + + + + + + + + + + full + outside + + + + + + + + + foreground + background + + + + + + + + + + + + + + + + clip + auto-create-new-frame + + + + + + + + + none + vertical + + + vertical + + + + + vertical + + + + + + + + + horizontal + horizontal-on-odd + horizontal-on-even + + + + + + + + + + + + + + + iterative + once-concurrent + once-successive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)(px) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + automatic + + + + named-symbol + + + + square + diamond + arrow-down + arrow-up + arrow-right + arrow-left + bow-tie + hourglass + circle + star + x + plus + asterisk + horizontal-bar + vertical-bar + + + + + + image + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + cubic-spline + b-spline + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cuboid + cylinder + cone + pyramid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + side-by-side + stagger-even + stagger-odd + + + + + + + + + + + + + + + none + value + percentage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + variance + standard-deviation + percentage + error-margin + constant + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + columns + rows + + + + + + + + + none + linear + logarithmic + exponential + power + + + + + + + + + manual + automatic + semi-automatic + + + + + + + + + none + fade-from-left + fade-from-top + fade-from-right + fade-from-bottom + fade-from-upperleft + fade-from-upperright + fade-from-lowerleft + fade-from-lowerright + move-from-left + move-from-top + move-from-right + move-from-bottom + move-from-upperleft + move-from-upperright + move-from-lowerleft + move-from-lowerright + uncover-to-left + uncover-to-top + uncover-to-right + uncover-to-bottom + uncover-to-upperleft + uncover-to-upperright + uncover-to-lowerleft + uncover-to-lowerright + fade-to-center + fade-from-center + vertical-stripes + horizontal-stripes + clockwise + counterclockwise + open-vertical + open-horizontal + close-vertical + close-horizontal + wavyline-from-left + wavyline-from-top + wavyline-from-right + wavyline-from-bottom + spiralin-left + spiralin-right + spiralout-left + spiralout-right + roll-from-top + roll-from-left + roll-from-right + roll-from-bottom + stretch-from-left + stretch-from-top + stretch-from-right + stretch-from-bottom + + vertical-lines + horizontal-lines + dissolve + random + vertical-checkerboard + horizontal-checkerboard + interlocking-horizontal-left + interlocking-horizontal-right + interlocking-vertical-top + interlocking-vertical-bottom + fly-away + open + close + melt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + forward + reverse + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + full + border + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + + + + + + + + + + + + + + + + + + + + [A-Za-z0-9]{1,8} + + + + + [A-Za-z]{1,8} + + + + + 1 + + + + + -?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + + ([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + + -?([0-9]+(\.[0-9]*)?|\.[0-9]+)% + + + + + [0-9]+\* + + + + + + + + + + + #[0-9a-fA-F]{6} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _self + _blank + _parent + _top + + + + + + + float + time + date + percentage + currency + boolean + string + + + + + + -?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)* + + + + + + + + + \([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\) + + + + + + + [0-9a-zA-Z_]+:[0-9a-zA-Z._\-]+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.0-os.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.0-os.rng new file mode 100644 index 0000000000..aa761dc880 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.0-os.rng @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.1.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.1.rng new file mode 100644 index 0000000000..e77fe4ba6e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-strict-schema-v1.1.rng @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-dsig-schema.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-dsig-schema.rng new file mode 100644 index 0000000000..bb2e591d86 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-dsig-schema.rng @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-manifest-schema.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-manifest-schema.rng new file mode 100644 index 0000000000..8902970eec --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-manifest-schema.rng @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + edit + presentation-slide-show + read-only + + + + + + + + + + + + + + + + + + + + + + + + + + + SHA1/1K + + + + + + + + + + + + + + + + + + + Blowfish CFB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PBKDF2 + + + + + + + + + + + + + + + + + + + + + + + + + + + SHA1 + + + + + + + + + + + + + + + + [^:]+:[^:]+ + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-schema.rng b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-schema.rng new file mode 100644 index 0000000000..bd57af13f7 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/OpenDocument-v1.2-cos01-schema.rng @@ -0,0 +1,18127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + boolean + short + int + long + double + string + datetime + base64Binary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + + + + + + + simple + + + + + + + replace + + + + + onLoad + + + + + + + + + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + float + + + + + + date + + + + + + time + + + + + + boolean + + + + + + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + none + + + + + condition + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:page-count + text:paragraph-count + text:word-count + text:character-count + text:table-count + text:image-count + text:object-count + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:reference-ref + text:bookmark-ref + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value + unit + gap + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:identifier + text:address + text:annote + text:author + text:booktitle + text:chapter + text:edition + text:editor + text:howpublished + text:institution + text:journal + text:month + text:note + text:number + text:organizations + text:pages + text:publisher + text:school + text:series + text:title + text:report-type + text:volume + text:year + text:url + text:custom1 + text:custom2 + text:custom3 + text:custom4 + text:custom5 + text:isbn + text:issn + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + footnote + endnote + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous + current + next + + + + + + + + + + previous + next + + + + + + + + + + + + + + name + number + number-and-name + plain-number-and-name + plain-number + + + + + + + + + + + + + full + path + name + name-and-extension + + + + + + + + + + + full + path + name + name-and-extension + area + title + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + command + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + table + text-box + image + object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + number-no-superior + number-all-superior + number + + + + + + + + + + + + + + + + + + + + + + category-and-value + caption + value + + + + + + + page + chapter + direction + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + float + + + + + + + + percentage + + + + + + + + currency + + + + + + + + + + + + + date + + + + + + + + time + + + + + + + + boolean + + + + + + + + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + value + none + + + + + + + + + value + formula + none + + + + + + + + + value + formula + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + article + book + booklet + conference + custom1 + custom2 + custom3 + custom4 + custom5 + email + inbook + incollection + inproceedings + journal + manual + mastersthesis + misc + phdthesis + proceedings + techreport + unpublished + www + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + category-and-value + caption + + + + + + + + + + document + chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 3 + separator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + number + number-and-name + plain-number + plain-number-and-name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + address + annote + author + bibliography-type + booktitle + chapter + custom1 + custom2 + custom3 + custom4 + custom5 + edition + editor + howpublished + identifier + institution + isbn + issn + journal + month + note + number + organizations + pages + publisher + report-type + school + series + title + url + volume + year + + + + + + + + + + + + + + + + + + + + + + + + right + + + + left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + collapse + filter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+ + + + + + + ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)? + + + ($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+ + + + ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+ + + + + + + Value is a space separated list of "cellRangeAddress" patterns + + + + + + + + + + + + + + copy-all + copy-results-only + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + trace-dependents + remove-dependents + trace-precedents + remove-precedents + trace-errors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + from-another-table + to-another-table + from-same-table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + date + + + + + + + + + + + + + + + + enable + disable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + unsorted + sort-ascending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + stop + warning + information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + column + row + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + print-range + filter + repeat-row + repeat-column + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + column + row + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + alpha-numeric + integer + double + + + + + + + + + + + + + + + + + + + + text + number + automatic + + + + + + + + ascending + descending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + automatic + + + + + + + + ascending + descending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + self + cell-range + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + number + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + data + hidden + + + + + page + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + from-top + from-bottom + + + + + + + + + + + + + + + + data + + + + + + + + none + manual + name + + + + + + ascending + descending + + + + + + + + + + + + + + + tabular-layout + outline-subtotals-top + outline-subtotals-bottom + + + + + + + + + + + + + + + + + + + + + named + + + + + + + + previous + next + + + + + + none + member-difference + member-percentage + member-percentage-difference + running-total + row-percentage + column-percentage + total-percentage + index + + + + + + + + + + + + + + + + + + + + + + auto + + + + + + auto + + + + + + + + auto + + + + + + auto + + + + + + + + + seconds + minutes + hours + days + months + quarters + years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + average + count + countnums + max + min + product + stdev + stdevp + sum + var + varp + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + accepted + rejected + pending + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always + screen + printer + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + full + section + cut + arc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + standard + lines + line + curve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page + frame + paragraph + char + as-char + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top-left + top + top-right + left + center + right + bottom-left + bottom-right + + + + + + auto + left + right + up + down + horizontal + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + scale + scale-min + + + + + + + + scale + scale-min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + new + replace + + + + + + + + + + + + nohref + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + parallel + perspective + + + + + + + + + + + + + + + + + + + + + + flat + phong + gouraud + draft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + phong + gouraud + draft + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + parallel + perspective + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + segments + rectangle + + + + + + + + + + + + + + + + + normal + path + shape + + + + + + + path + shape + + + + + + + + + + + + + + + + + + non-primitive + + + + + + \([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\) + + + + + -0.5 + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + title + outline + subtitle + text + graphic + object + chart + table + orgchart + page + notes + handout + header + footer + date-time + page-number + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + new + replace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + fade + move + stripes + open + close + dissolve + wavyline + random + lines + laser + appear + hide + move-short + checkerboard + rotate + stretch + + + + + none + from-left + from-top + from-right + from-bottom + from-center + from-upper-left + from-upper-right + from-lower-left + from-lower-right + to-left + to-top + to-right + to-bottom + to-upper-left + to-upper-right + to-lower-right + to-lower-left + path + spiral-inward-left + spiral-inward-right + spiral-outward-left + spiral-outward-right + vertical + horizontal + to-center + clockwise + counter-clockwise + + + + + slow + medium + fast + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + on-click + with-previous + after-previous + timing-root + main-sequence + interactive-sequence + + + + + + + + + + + + + + + + + custom + entrance + exit + emphasis + motion-path + ole-action + media-call + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + previous-page + next-page + first-page + last-page + hide + stop + execute + show + verb + fade-out + sound + last-visited-page + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fixed + current-date + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enabled + disabled + + + + + + + enabled + disabled + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + start + end + top + bottom + + + + + + start + center + end + + + + + + + top-start + bottom-start + top-end + bottom-end + + + + + + + + + wide + high + balanced + + + + + custom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + row + column + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x + y + z + + + + + + + + + + + + + + + + + + + + + + major + minor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + none + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + equal-integer + is-boolean + equal-boolean + equal-use-only-zero + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + boolean + short + int + long + double + string + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + none + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-nulls + nullable + + + + + + + + + + + + + + + + + + + + bit + boolean + tinyint + smallint + integer + bigint + float + real + double + numeric + decimal + char + varchar + longvarchar + date + time + timestmp + binary + varbinary + longvarbinary + sqlnull + other + object + distinct + struct + array + blob + clob + ref + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + primary + unique + foreign + + + + + + + + + + + + + cascade + restrict + set-null + no-action + set-default + + + + + + + + cascade + restrict + set-null + no-action + set-default + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + + get + post + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + command + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + current + parent + + + + + records + current + page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + selection + selection-indices + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + unchecked + checked + unknown + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + horizontal + vertical + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + submit + reset + push + url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + flat + 3d + + + + + + + + + center + + + + + + start + end + top + bottom + + + + + + start + center + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + table + query + sql + sql-pass-through + value-list + table-fields + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void + + + + + + + + float + + + + + + + + + + + + percentage + + + + + + + + + + + + currency + + + + + + + + + + + + + + + + + date + + + + + + + + + + + + time + + + + + + + + + + + + boolean + + + + + + + + + + + + string + + + + + + + + + + + void + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + i + I + + + + + + + + a + A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + + + To avoid inclusion of the complete MathML schema, anything is allowed within a math:math top-level element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + into-default-style-data-style + into-english-number + keep-text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + discrete + linear + paced + spline + + + + + + + + + + + rgb + hsl + + + + + + + clockwise + counter-clockwise + + + + + + + + + translate + scale + rotate + skewX + skewY + + + + + + + + + + + + + + + + + forward + reverse + + + + + + + + + + + + in + out + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + discrete + linear + paced + spline + + + + + + + + + + + + + + + + + + + + + + + + none + sum + + + + + + + replace + sum + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + first + last + all + media + + + + + + + + + + + + + + + + indefinite + + + + + + + 0.0 + + + + + + + remove + freeze + hold + auto + default + transition + + + + + + + + + remove + freeze + hold + transition + auto + inherit + + + + + + + + + never + always + whenNotActive + default + + + + + + + + + never + always + whenNotActive + inherit + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + left + right + mirrored + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + row + column + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + normal + ultra-condensed + extra-condensed + condensed + semi-condensed + semi-expanded + expanded + extra-expanded + ultra-expanded + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + onRequest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + short + long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + short + medium + long + + + + + + + + + + + + + + + + + fixed + language + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gregorian + gengou + ROC + hanja_yoil + hanja + hijri + jewish + buddhist + + + + + + + + + + text + + + + + + + + paragraph + + + + + + + + + + + section + + + + + + + + ruby + + + + + + + + table + + + + + + + + table-column + + + + + + + + table-row + + + + + + + + table-cell + + + + + + + + + + + + + + + graphic + presentation + + + + + + + + + + + + + + + drawing-page + + + + + + + + chart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + right + inner + outer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document + chapter + page + + + + + + + text + page + section + document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + address + annote + author + bibliography-type + booktitle + chapter + custom1 + custom2 + custom3 + custom4 + custom5 + edition + editor + howpublished + identifier + institution + isbn + issn + journal + month + note + number + organizations + pages + publisher + report-type + school + series + title + url + volume + year + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + linear + axial + radial + ellipsoid + square + rectangular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + objectBoundingBox + + + + + + + + + + + pad + reflect + repeat + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + single + double + triple + + + + + + + + + + + + + + + + + + + + + + + + simple + + + + + + + embed + + + + + onLoad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rect + round + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + + + + + + + + portrait + landscape + + + + + + + + + + + + + + + + + + + + + + headers + grid + annotations + objects + charts + drawings + formulas + zero-values + + + + + + + + + ttb + ltr + + + + + + + + continue + + + + + + + + + + + + + + + + + horizontal + vertical + both + none + + + + + + + + + + + + + none + line + both + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + lowercase + uppercase + capitalize + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + super + sub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + latin + asian + complex + ignore + + + + + + + + normal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + embossed + engraved + + + + + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + letters + lines + + + + + + + + + + + + + + + + + none + + + none + accent + dot + circle + disc + + + above + below + + + + + + + + + + + + + + + + + + + fixed + line-height + + + + + + + + + + + + + + + + + + + + + true + + + none + + + + condition + + + none + + + + + + + + + normal + small-caps + + + + + roman + swiss + modern + decorative + script + system + + + + + fixed + variable + + + + + [A-Za-z][A-Za-z0-9._\-]* + + + + + normal + italic + oblique + + + + + none + + + + + + none + single + double + + + + + none + solid + dotted + dash + long-dash + dot-dash + dot-dot-dash + wave + + + + + auto + normal + bold + thin + medium + thick + + + + + + + + normal + bold + 100 + 200 + 300 + 400 + 500 + 600 + 700 + 800 + 900 + + + + + continuous + skip-white-space + + + + + + + + + + + + + + + + + normal + + + + + + + + + + + + + + + + + + + + + + + + + start + center + justify + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + auto + page + + + + + + + no-limit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + ideograph-alpha + + + + + + + simple + hanging + + + + + + + normal + strict + + + + + + + top + middle + bottom + auto + baseline + + + + + + + + + + + + + + + + + + + + + + + start + end + left + right + center + justify + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + + char + + + + + + + + + + + + + + + + + + + + + + + font-color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + word + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + column + page + + + + + + + auto + column + page + + + + + + + + + transparent + + + + + + + + + + + + + + + + + + + + + + + no-repeat + repeat + stretch + + + + + + + left + center + right + top + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + + + + + top + center + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + always + + + + + + + + + lr-tb + rl-tb + tb-rl + tb-lr + lr + rl + tb + page + + + + + + + + + + auto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + above + below + + + + + + + left + center + right + distribute-letter + distribute-space + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + solid + dotted + dashed + dot-dashed + + + + + + + + + + + + + + + top + middle + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + center + right + margins + + + + + + + + + + + + + + + + + + + + collapsing + separating + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + always + + + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + automatic + + + + + + + fix + value-type + + + + + + + + auto + 0 + 0deg + 0rad + 0grad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-wrap + wrap + + + + + + + + none + bottom + top + center + + + + + + + none + hidden-and-protected + + + + protected + formula-hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ltr + ttb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + label-width-and-position + label-alignment + + + + + + + + + + + + + + + + + + + + + listtab + space + nothing + + + + + + + + + + + + + + + + + + + + + + + + + none + dash + solid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + miter + round + bevel + middle + none + + + + + + + butt + square + round + + + + + + + + + + + + none + scroll + alternate + slide + + + + + + + left + right + up + down + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top + middle + bottom + justify + + + + + + + left + center + right + justify + + + + + + + no-wrap + wrap + + + + + + + + + + + + greyscale + mono + watermark + standard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + below + above + + + + + + + + + + + + automatic + left-outside + inside + right-outside + + + + + + + automatic + above + below + center + + + + + + + automatic + mm + cm + m + km + pt + pc + inch + ft + mi + + + + + + + + + + + + + + + + + straight-line + angled-line + angled-connector-line + + + + + + + fixed + free + + + + + + + + + + + + + + + + + horizontal + vertical + auto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + correct + attractive + + + + + + + + + + + + + + + + + enabled + disabled + + + + + + + + + + + + + + + + + + + + + + standard + double-sided + + + + + + + object + flat + sphere + + + + + + + normal + inverse + + + + + + + object + parallel + sphere + + + + + + + object + parallel + sphere + + + + + + + luminance + intensity + color + + + + + + + enabled + disabled + + + + + + + replace + modulate + blend + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + + content + position + size + + + + + + + + + + left + center + right + from-left + inside + outside + from-inside + + + + + + + + + + + + page + page-content + page-start-margin + page-end-margin + frame + frame-content + frame-start-margin + frame-end-margin + paragraph + paragraph-content + paragraph-start-margin + paragraph-end-margin + char + + + + + + + + + + + + + + + + + none + left + right + parallel + dynamic + run-through + biggest + + + + + + + + + + + + no-limit + + + + + + + + + + + + + full + outside + + + + + + + foreground + background + + + + + + + + + + + + clip + auto-create-new-frame + + + + + + + none + vertical + + + vertical + + + + + vertical + + + + + + + + auto + + + + + + + + iterative + once-concurrent + once-successive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + content + thumbnail + icon + print-view + + + + + + + + + + + + + + + + none + solid + bitmap + gradient + hatch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + no-repeat + repeat + stretch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top-left + top + top-right + left + center + right + bottom-left + bottom + bottom-right + + + + + + + + + horizontal + vertical + + + + + + + + + + + + + + + + + + nonzero + evenodd + + + + + + + + + + + + + + + + + + + top + middle + bottom + from-top + below + + + + + + + + + + + + + + page + page-content + frame + frame-content + paragraph + paragraph-content + char + line + baseline + text + + + + + + + + + + + + + + horizontal + horizontal-on-odd + horizontal-on-even + + + + + rect\([ ]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ ]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\) + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)(px) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + + + automatic + + + + named-symbol + + + + square + diamond + arrow-down + arrow-up + arrow-right + arrow-left + bow-tie + hourglass + circle + star + x + plus + asterisk + horizontal-bar + vertical-bar + + + + + + image + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + cubic-spline + b-spline + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cuboid + cylinder + cone + pyramid + + + + + + + + + + + + + + + + + use-zero + leave-gap + ignore + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + side-by-side + stagger-even + stagger-odd + + + + + + + + + none + value + percentage + value-and-percentage + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + variance + standard-deviation + percentage + error-margin + constant + standard-error + cell-range + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + columns + rows + + + + + + + none + linear + logarithmic + exponential + power + + + + + + + start + end + + + + + + + + near-axis + near-axis-other-side + outside-start + outside-end + + + + + + + at-labels + at-axis + at-labels-and-axis + + + + + + + + + + + + + avoid-overlap + center + top + top-right + right + bottom-right + bottom + bottom-left + left + top-left + inside + outside + near-origin + + + + + + + + manual + automatic + semi-automatic + + + + + + + none + fade-from-left + fade-from-top + fade-from-right + fade-from-bottom + fade-from-upperleft + fade-from-upperright + fade-from-lowerleft + fade-from-lowerright + move-from-left + move-from-top + move-from-right + move-from-bottom + move-from-upperleft + move-from-upperright + move-from-lowerleft + move-from-lowerright + uncover-to-left + uncover-to-top + uncover-to-right + uncover-to-bottom + uncover-to-upperleft + uncover-to-upperright + uncover-to-lowerleft + uncover-to-lowerright + fade-to-center + fade-from-center + vertical-stripes + horizontal-stripes + clockwise + counterclockwise + open-vertical + open-horizontal + close-vertical + close-horizontal + wavyline-from-left + wavyline-from-top + wavyline-from-right + wavyline-from-bottom + spiralin-left + spiralin-right + spiralout-left + spiralout-right + roll-from-top + roll-from-left + roll-from-right + roll-from-bottom + stretch-from-left + stretch-from-top + stretch-from-right + stretch-from-bottom + vertical-lines + horizontal-lines + dissolve + random + vertical-checkerboard + horizontal-checkerboard + interlocking-horizontal-left + interlocking-horizontal-right + interlocking-vertical-top + interlocking-vertical-bottom + fly-away + open + close + melt + + + + + + + + + + + + + + + + + + + + + + forward + reverse + + + + + + + + + + + + + + + + + visible + hidden + + + + + + + full + border + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + false + + + + + + + + + + + + + + + + + + + + [A-Za-z0-9]{1,8} + + + + + [A-Za-z]{1,8} + + + + + [A-Za-z0-9]{1,8} + + + + + 1 + + + + + -?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + ([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + ([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)) + + + + + -?([0-9]+(\.[0-9]*)?|\.[0-9]+)% + + + + + ([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)% + + + + + -?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)% + + + + + [0-9]+\* + + + + + + + + + + + #[0-9a-fA-F]{6} + + + + + + + + (([\i-[:]][\c-[:]]*)?:)?.+ + 1 + + + + + + + + + + + + \[(([\i-[:]][\c-[:]]*)?:)?.+\] + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _self + _blank + _parent + _top + + + + + + float + time + date + percentage + currency + boolean + string + + + + + -?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)* + + + + + + + + \([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\) + + + + + [^:]+:[^:]+ + + + + + An IRI-reference as defined in [RFC3987]. See ODF 1.2 Part 1 section 18.3. + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/application-vnd.oasis.opendocument.presentation.png b/apps/files_odfviewer/src/webodf/programs/docnosis/application-vnd.oasis.opendocument.presentation.png new file mode 100644 index 0000000000000000000000000000000000000000..1d0fdc08af2f32c16e879686b7da19353b0bca24 GIT binary patch literal 6617 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 Z{{bYFzUPlgdp!UE002ovPDHLkV1g%jzAFF# literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/docnosis.js b/apps/files_odfviewer/src/webodf/programs/docnosis/docnosis.js new file mode 100644 index 0000000000..4bddc12cc2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/docnosis.js @@ -0,0 +1,779 @@ +/*global runtime, Node, window, DOMParser, core, xmldom, NodeFilter, alert, + FileReader*/ +runtime.loadClass("core.Zip"); +runtime.loadClass("core.Base64"); +runtime.loadClass("xmldom.RelaxNG"); + +/** This code runs a number of tests on an ODF document. + * Ideally, it would use ODFContainer, but for now, it uses a custome container + * for loaded odf files. + */ + +function conformsToPattern(object, pattern, name) { + "use strict"; + var i; + if (object === undefined || object === null) { + return pattern === null || (typeof pattern) !== "object"; + } + for (i in pattern) { + if (pattern.hasOwnProperty(i)) { + if (!(object.hasOwnProperty(i) || + (i === "length" && object.length)) || + !conformsToPattern(object[i], pattern[i], i)) { + return false; + } + } + } + return true; +} + +function getConformingObjects(object, pattern, name) { + "use strict"; + var c = [], i, j; + name = name || "??"; + // we do not look inside long arrays and strings atm, + // detection of these types could be better + function accept(object) { + return object !== null && object !== undefined && + (typeof object) === "object" && + (object.length === undefined || object.length < 1000) && + !(object instanceof Node) && + !(object.constructor && object.constructor === window.Uint8Array); + } + for (i in object) { + if (object.hasOwnProperty(i) && accept(object[i])) { + c = c.concat(getConformingObjects(object[i], pattern, i)); + } + } + if (conformsToPattern(object, pattern, "?")) { + c.push(object); + } + return c; +} +function parseXml(data, errorlog, name) { + "use strict"; + function getText(e) { + var str = "", c = e.firstChild; + while (c) { + if (c.nodeType === 3) { + str += c.nodeValue; + } else { + str += getText(c); + } + c = c.nextSibling; + } + return str; + } + var str, parser, errorelements; + try { + str = runtime.byteArrayToString(data, "utf8"); + parser = new DOMParser(); + str = parser.parseFromString(str, "text/xml"); + if (str.documentElement.localName === "parsererror" + || str.documentElement.localName === "html") { + errorelements = str.getElementsByTagName("parsererror"); + if (errorelements.length > 0) { + errorlog.push("invalid XML in " + name + ": " + + getText(errorelements[0])); + str = null; + } + } + } catch (err) { + errorlog.push(err); + } + return str; +} + +/*** the jobs / tests ***/ + +function ParseXMLJob() { + "use strict"; + this.inputpattern = { file: { entries: [] } }; + this.outputpattern = { + file: { entries: [] }, + errors: { parseXmlErrors: [] }, + content_xml: null, + manifest_xml: null, + settings_xml: null, + meta_xml: null, + styles_xml: null + }; + function parseXmlFiles(input, position, callback) { + var e = input.file.entries, + filename, + ext, + dom; + if (position >= e.length) { + return callback(); + } + filename = e[position].filename; + ext = filename.substring(filename.length - 4); + if (ext === ".xml" || ext === ".rdf") { + dom = parseXml(e[position].data, input.errors.parseXmlErrors, + filename); + if (filename === "content.xml") { + input.content_xml = dom; + } else if (filename === "META-INF/manifest.xml") { + input.manifest_xml = dom; + } else if (filename === "styles.xml") { + input.styles_xml = dom; + } else if (filename === "meta.xml") { + input.meta_xml = dom; + } else if (filename === "settings.xml") { + input.settings_xml = dom; + } + e[position].dom = dom; + } + window.setTimeout(function () { + parseXmlFiles(input, position + 1, callback); + }, 0); + } + this.run = function (input, callback) { + input.errors = input.errors || {}; + input.errors.parseXmlErrors = []; + input.content_xml = null; + input.manifest_xml = null; + input.styles_xml = null; + input.meta_xml = null; + input.settings_xml = null; + parseXmlFiles(input, 0, callback); + }; +} +function UnpackJob() { + "use strict"; + this.inputpattern = { file: { path: "", data: { length: 0 } } }; + this.outputpattern = { + file: { entries: [], dom: null }, errors: { unpackErrors: [] } + }; + function getText(e) { + var str = "", c = e.firstChild; + while (c) { + if (c.nodeType === 3) { + str += c.nodeValue; + } else { + str += getText(c); + } + c = c.nextSibling; + } + return str; + } + function loadZipEntries(input, position, callback) { + if (position >= input.file.entries.length) { + return callback(); + } + var e = input.file.entries[position]; + e.load(function (err, data) { + if (err) { + input.errors.unpackErrors.push(err); + } + e.error = err; + e.data = data; + window.setTimeout(function () { + loadZipEntries(input, position + 1, callback); + }, 0); + }); + } + function loadZip(input, callback) { + var zip = new core.Zip(input.file.path, function (err, zip) { + var i; + if (err) { + input.errors.unpackErrors.push(err); + callback(); + } else { + input.file.entries = zip.getEntries(); + loadZipEntries(input, 0, callback); + } + }); + } + function loadXml(input, callback) { + input.file.dom = parseXml(input.file.data, input.errors.unpackErrors, + input.file.name); + callback(); + } + this.run = function (input, callback) { + input.errors = input.errors || {}; + input.errors.unpackErrors = []; + input.file.dom = null; + input.file.entries = []; + + if (input.file.data.length < 1) { + input.errors.unpackErrors.push("Input data is empty."); + return; + } + if (input.file.data[0] === 80) { // a ZIP file starts with 'P' + loadZip(input, callback); + } else { + loadXml(input, callback); + } + }; +} +function MimetypeTestJob(odffile) { + "use strict"; + this.inputpattern = { + file: { entries: [], dom: null }, + manifest_xml: null + }; + this.outputpattern = { mimetype: "", errors: { mimetypeErrors: [] } }; + var manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"; + function getManifestMimetype(manifest) { + if (!manifest) { + return null; + } + var path, mimetype, node; + node = manifest.documentElement.firstChild; + while (node) { + if (node.nodeType === 1 && node.localName === "file-entry" && + node.namespaceURI === manifestns) { + path = node.getAttributeNS(manifestns, "full-path"); + if (path === "/") { + mimetype = node.getAttributeNS(manifestns, "media-type"); + break; + } + } + node = node.nextSibling; + } + return mimetype; + } + this.run = function (input, callback) { + input.mimetype = null; + input.errors.mimetypeErrors = []; + var mime = null, + altmime, + e = input.file.entries, + i; + if (input.file.dom) { + mime = input.file.dom.documentElement.getAttributeNS( + "urn:oasis:names:tc:opendocument:xmlns:office:1.0", "mimetype"); + } else { + if (e.length < 1 || e[0].filename !== "mimetype") { + input.errors.mimetypeErrors.push( + "First file in zip is not 'mimetype'"); + } + for (i = 0; i < e.length; i += 1) { + if (e[i].filename === "mimetype") { + mime = runtime.byteArrayToString(e[i].data, "binary"); + break; + } + } + if (mime) { + altmime = input.file.data.slice(38, 38 + mime.length); + altmime = runtime.byteArrayToString(altmime, "binary"); + if (mime !== altmime) { + input.errors.mimetypeErrors.push( + "mimetype should start at byte 38 in the zip file."); + } + } + // compare with mimetype from manifest_xml + altmime = getManifestMimetype(input.manifest_xml); + if (altmime !== mime) { + input.errors.mimetypeErrors.push( + "manifest.xml has a different mimetype."); + } + } + if (!mime) { + input.errors.mimetypeErrors.push("No mimetype was found."); + } + input.mimetype = mime; + callback(); + }; +} +function VersionTestJob() { + "use strict"; + this.inputpattern = { + file: { dom: null }, + content_xml: null, + styles_xml: null, + meta_xml: null, + settings_xml: null, + manifest_xml: null + }; + this.outputpattern = { version: "", errors: { versionErrors: [] } }; + var officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; + function getVersion(dom, filename, log, vinfo, filerequired) { + var v, ns = officens; + if (!dom) { + if (filerequired) { + log.push(filename + " is missing, so version cannot be found."); + } + return; + } + if (filename === "META-INF/manifest.xml") { + ns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"; + } + if (!dom.documentElement.hasAttributeNS(ns, "version")) { + if (vinfo.versionrequired) { + log.push(filename + " has no version number."); + } + return; + } + v = dom.documentElement.getAttributeNS(ns, "version"); + if (vinfo.version === undefined) { + vinfo.version = v; + // version number is required since ODF 1.2 + vinfo.needversion = vinfo.version === "1.2"; + vinfo.versionSource = filename; + } else if (v !== vinfo.version) { + log.push(vinfo.versionSource + " and " + filename + " " + + " have different version number."); + } + } + this.run = function (input, callback) { + input.errors.versionErrors = []; + var v, + e = input.file.entries, + log = input.errors.versionErrors, + vinfo = { + version: undefined, + needversion: null, + versionSource: null + }, + contentxmlhasnoversionnumber; + if (input.file.dom) { + getVersion(input.file.dom, input.file.name, log, vinfo, true); + } else { + // until we know the version number, we cannot claim that + // content.xml needs a version number + getVersion(input.content_xml, "content.xml", log, vinfo, true); + contentxmlhasnoversionnumber = vinfo.version === undefined; + getVersion(input.manifest_xml, "META-INF/manifest.xml", log, + vinfo, true); + getVersion(input.styles_xml, "styles.xml", log, vinfo); + getVersion(input.meta_xml, "meta.xml", log, vinfo); + getVersion(input.settings_xml, "settings.xml", log, vinfo); + if (vinfo.needversion && contentxmlhasnoversionnumber) { + log.push("content.xml has no version number."); + } + } + input.version = vinfo.version; + callback(); + }; +} +function GetThumbnailJob() { + "use strict"; + var base64 = new core.Base64(); + this.inputpattern = { file: { entries: [] }, errors: {}, mimetype: "" }; + this.outputpattern = { thumbnail: "", errors: { thumbnailErrors: [] } }; + this.run = function (input, callback) { + input.thumbnail = null; + input.errors.thumbnailErrors = []; + var i, e = input.file.entries, mime = input.mimetype, thumb = null; + if (mime === "application/vnd.oasis.opendocument.text") { + thumb = "application-vnd.oasis.opendocument.text.png"; + } else if (mime === "application/vnd.oasis.opendocument.spreadsheet") { + thumb = "application-vnd.oasis.opendocument.spreadsheet.png"; + } else if (mime === "application/vnd.oasis.opendocument.presentation") { + thumb = "application-vnd.oasis.opendocument.presentation.png"; + } + for (i = 0; i < e.length; i += 1) { + if (e[i].filename === "Thumbnails/thumbnail.png") { + thumb = "data:image/png;base64," + + base64.convertUTF8ArrayToBase64(e[i].data); + break; + } + } + input.thumbnail = thumb; + callback(); + }; +} +function RelaxNGJob() { + "use strict"; + var parser = new xmldom.RelaxNGParser(), + validators = {}; + this.inputpattern = { file: {dom: null}, version: null }; + this.outputpattern = { errors: { relaxngErrors: [] } }; + function loadValidator(ns, version, callback) { + var rng; + if (ns === "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0") { + if (version === "1.2") { + rng = "OpenDocument-v1.2-cos01-manifest-schema.rng"; + } else if (version === "1.1") { + rng = "OpenDocument-manifest-schema-v1.1.rng"; + } else if (version === "1.0") { + rng = "OpenDocument-manifest-schema-v1.0-os.rng"; + } + } else if (ns === "urn:oasis:names:tc:opendocument:xmlns:office:1.0") { + if (version === "1.2") { + rng = "OpenDocument-v1.2-cos01-schema.rng"; + } else if (version === "1.1") { + rng = "OpenDocument-schema-v1.1.rng"; + } else if (version === "1.0") { + rng = "OpenDocument-schema-v1.0-os.rng"; + } + } + if (rng) { + runtime.loadXML(rng, function (err, dom) { + var relaxng; + if (err) { + runtime.log(err); + } else { + relaxng = new xmldom.RelaxNG(); + err = parser.parseRelaxNGDOM(dom, relaxng.makePattern); + if (err) { + runtime.log(err); + } else { + relaxng.init(parser.rootPattern); + } + } + validators[ns] = validators[ns] || {}; + validators[ns][version] = relaxng; + callback(relaxng); + }); + } else { + callback(null); + } + } + function getValidator(ns, version, callback) { + if (ns === "urn:oasis:names:tc:opendocument:xmlns:office:1.0" || + ns === "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0") { + if (!version) { + version = "1.1"; + } + } + if (validators[ns] && validators[ns][version]) { + return callback(validators[ns][version]); + } + loadValidator(ns, version, callback); + } + function validate(log, dom, filename, version, callback) { + var ns = dom.documentElement.namespaceURI; + getValidator(ns, version, function (relaxng) { + if (!relaxng) { + return callback(); + } + var walker = dom.createTreeWalker(dom.firstChild, 0xFFFFFFFF, + { acceptNode: function(node) { + return NodeFilter.FILTER_ACCEPT; } + }, false), + err; +runtime.log("START VALIDATING"); + err = relaxng.validate(walker, function (err) { +runtime.log("FINISHED VALIDATING"); + var i; + if (err) { + for (i = 0; i < err.length; i += 1) { + log.push(filename + ": " + err[i]); + } + } + callback(); + }); + }); + } + function validateEntries(log, entries, position, version, callback) { + if (position >= entries.length) { + return callback(); + } + var e = entries[position]; + if (e.dom) { + validate(log, e.dom, e.filename, version, function () { + window.setTimeout(function () { + validateEntries(log, entries, position + 1, version, + callback); + }, 0); + }); + } else { + validateEntries(log, entries, position + 1, version, callback); + } + } + this.run = function (input, callback) { + input.errors = input.errors || {}; + input.errors.relaxngErrors = []; + runtime.log(input.version); + if (input.file.dom) { + validate(input.errors.relaxngErrors, input.file.dom, + input.file.path, input.version, callback); + return; + } + var i, e = input.file.entries; + validateEntries(input.errors.relaxngErrors, input.file.entries, 0, + input.version, callback); + }; +} + +function DataRenderer(parentelement) { + "use strict"; + var doc = parentelement.ownerDocument, + element = doc.createElement("div"), + lastrendertime, + delayedRenderComing, + renderinterval = 300; // minimal milliseconds between renders + function clear(element) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + } + function addParagraph(div, text) { + var p = doc.createElement("p"); + p.appendChild(doc.createTextNode(text)); + div.appendChild(p); + } + function addSpan(parent, nodename, text) { + var e = doc.createElement(nodename); + e.appendChild(doc.createTextNode(text)); + parent.appendChild(e); + } + function addErrors(div, e, active) { + var i, o; + for (i in e) { + if (e.hasOwnProperty(i)) { + o = e[i]; + if (active && ((typeof o) === "string" + || o instanceof String)) { + addParagraph(div, o); + } else if (o && (typeof o) === "object" && + !(o instanceof Node) && + !(o.constructor && + o.constructor === window.Uint8Array)) { + addErrors(div, o, active || i === "errors"); + } + } + } + } + function renderFile(data) { + var div = doc.createElement("div"), + h1 = doc.createElement("h1"), + icon = doc.createElement("img"); + div.style.clear = "both"; + div.appendChild(h1); + div.appendChild(icon); + h1.appendChild(doc.createTextNode(data.file.path)); + element.appendChild(div); + if (data.thumbnail) { + icon.src = data.thumbnail; + } + icon.style.width = "128px"; + icon.style.float = "left"; + icon.style.mozBoxShadow = icon.style.webkitBoxShadow = + icon.style.boxShadow = "3px 3px 4px #000"; + icon.style.marginRight = icon.style.marginBottom = "10px"; + addParagraph(div, "mimetype: " + data.mimetype); + addParagraph(div, "version: " + data.version); + addParagraph(div, "document representation: " + + ((data.file.dom) ? "single XML document" :"package")); + addErrors(div, data, false); + } + function dorender(data) { + clear(element); + var i; + for (i = 0; i < data.length; i += 1) { + renderFile(data[i]); + } + } + this.render = function render(data) { + var now = Date.now(); + if (!lastrendertime || now - lastrendertime > renderinterval) { + lastrendertime = now; + dorender(data); + } else if (!delayedRenderComing) { + delayedRenderComing = true; + window.setTimeout(function () { + delayedRenderComing = false; + lastrendertime = now + renderinterval; + dorender(data); + }, renderinterval); + } + }; + parentelement.appendChild(element); +} + +function JobRunner(datarenderer) { + "use strict"; + var jobrunner = this, + jobtypes = [], + data, + busy = false, + todo = []; + + jobtypes.push(new UnpackJob()); + jobtypes.push(new MimetypeTestJob()); + jobtypes.push(new GetThumbnailJob()); + jobtypes.push(new VersionTestJob()); + jobtypes.push(new ParseXMLJob()); + jobtypes.push(new RelaxNGJob()); + + function run() { + if (busy) { + return; + } + var job = todo.shift(); + if (job) { + busy = true; + job.job.run(job.object, function () { + busy = false; + if (!conformsToPattern(job.object, job.job.outputpattern)) { + throw "Job does not give correct output."; + } + datarenderer.render(data); + window.setTimeout(run, 0); + }); + } + } + + function update(ignore, callback) { + var i, jobtype, j, inobjects, outobjects; + todo = []; + for (i = 0; i < jobtypes.length; i += 1) { + jobtype = jobtypes[i]; + inobjects = getConformingObjects(data, jobtype.inputpattern); + outobjects = getConformingObjects(data, jobtype.outputpattern); + for (j = 0; j < inobjects.length; j += 1) { + if (outobjects.indexOf(inobjects[j]) === -1) { + todo.push({job: jobtype, object: inobjects[j]}); + } + } + } + if (todo.length > 0) { + // run update again after all todos are done + todo.push({job: jobrunner, object: null}); + } + if (callback) { + callback(); + } else { + run(); + } + } + + this.run = update; + + this.setData = function setData(newdata) { + data = newdata; + if (busy) { + todo = []; + todo.push({job: jobrunner, object: null}); + } else { + update(); + } + }; +} +function LoadingFile(file) { + "use strict"; + var data, + error, + readRequests = []; + function load(callback) { + var reader = new FileReader(); + reader.onloadend = function(evt) { + data = runtime.byteArrayFromString(evt.target.result, "binary"); + error = evt.target.error && String(evt.target.error); + var i = 0; + for (i = 0; i < readRequests.length; i += 1) { + readRequests[i](); + } + readRequests = undefined; + reader = undefined; + callback(error, data); + }; + reader.readAsBinaryString(file); + } + this.file = file; + this.read = function (offset, length, callback) { + function read() { + if (error) { + return callback(error); + } + if (data) { + return callback(error, data.slice(offset, offset + length)); + } + readRequests.push(read); + } + read(); + }; + this.load = load; +} +function Docnosis(element) { + "use strict"; + var doc = element.ownerDocument, + form, + diagnoses = doc.createElement("div"), + openedFiles = {}, + datarenderer = new DataRenderer(diagnoses), + jobrunner = new JobRunner(datarenderer), + jobrunnerdata = []; + + function dragHandler(evt) { + var over = evt.type === "dragover" && evt.target.nodeName !== "INPUT"; + if (over || evt.type === "drop") { + evt.stopPropagation(); + evt.preventDefault(); + } + if (evt.target.style) { + evt.target.style.background = (over ? "#CCCCCC" : "inherit"); + } + } + + function fileSelectHandler(evt) { + // cancel event and hover styling + dragHandler(evt); + + function diagnoseFile(file) { + var loadingfile, path; + path = file.name; + loadingfile = new LoadingFile(file); + openedFiles[path] = loadingfile; + loadingfile.load(function (error, data) { + jobrunnerdata.push({file:{ + path: path, + data: data + }}); + jobrunner.setData(jobrunnerdata); + }); + } + // process all File objects + var i, files, div; + files = (evt.target && evt.target.files) || + (evt.dataTransfer && evt.dataTransfer.files); + if (files) { + for (i = 0; files && i < files.length; i += 1) { + div = doc.createElement("div"); + diagnoses.appendChild(div); + diagnoseFile(files[i]); + } + } else { + alert("File(s) could not be opened in this browser."); + } + } + + function createForm() { + var form = doc.createElement("form"), + fieldset = doc.createElement("fieldset"), + legend = doc.createElement("legend"), + input = doc.createElement("input"); + form = doc.createElement("form"); + form.appendChild(fieldset); + fieldset.appendChild(legend); + input.setAttribute("type", "file"); + input.setAttribute("name", "fileselect[]"); + input.setAttribute("multiple", "multiple"); + input.addEventListener("change", fileSelectHandler, false); + fieldset.appendChild(input); + fieldset.appendChild(doc.createTextNode("or drop files here")); + legend.appendChild(doc.createTextNode("docnosis")); + form.addEventListener("dragover", dragHandler, false); + form.addEventListener("dragleave", dragHandler, false); + form.addEventListener("drop", fileSelectHandler, false); + return form; + } + + function enhanceRuntime() { + var read = runtime.read, + getFileSize = runtime.getFileSize; + runtime.read = function (path, offset, length, callback) { + if (openedFiles.hasOwnProperty(path)) { + return openedFiles[path].read(offset, length, callback); + } else { + return read(path, offset, length, callback); + } + }; + runtime.getFileSize = function (path, callback) { + if (openedFiles.hasOwnProperty(path)) { + return callback(openedFiles[path].file.size); + } else { + return getFileSize(path, callback); + } + }; + } + + form = createForm(); + element.appendChild(form); + element.appendChild(diagnoses); + enhanceRuntime(); +} diff --git a/apps/files_odfviewer/src/webodf/programs/docnosis/index.html b/apps/files_odfviewer/src/webodf/programs/docnosis/index.html new file mode 100644 index 0000000000..cd56d4f746 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/docnosis/index.html @@ -0,0 +1,27 @@ + + + + + docnosis + + + + + + + +
+ + diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/firefoxextension/CMakeLists.txt new file mode 100644 index 0000000000..92d1e19f7c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/CMakeLists.txt @@ -0,0 +1,35 @@ +# the files that go into the extension +set(FIREFOXEXTENSIONFILES + bootstrap.js + chrome.manifest + skin/default/icon.png + content/odf.html + components/odfContentHandler.js +) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/install.rdf.in + ${CMAKE_CURRENT_SOURCE_DIR}/install.rdf) +set(WEBODFXPI ${CMAKE_CURRENT_BINARY_DIR}/webodf-${WEBODF_VERSION}.xpi) +add_custom_command( + OUTPUT ${WEBODFXPI} + # copy the common webodf.css and webodf.js + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different + ${CMAKE_SOURCE_DIR}/webodf/webodf.css + ${CMAKE_CURRENT_SOURCE_DIR}/content/webodf.css + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different + ${CMAKE_BINARY_DIR}/webodf/webodf.js + ${CMAKE_CURRENT_SOURCE_DIR}/content/webodf.js + # zip using javascript code running in node.js + COMMAND ${NODE} ARGS ../../webodf/lib/runtime.js packextension.js + ${WEBODFXPI} + ${FIREFOXEXTENSIONFILES} + content/webodf.js + content/webodf.css + install.rdf + DEPENDS NodeJS + packextension.js ${FIREFOXEXTENSIONFILES} + install.rdf.in + ${CMAKE_SOURCE_DIR}/webodf/webodf.css + ${CMAKE_BINARY_DIR}/webodf/webodf.js + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) +add_custom_target(firefoxextension ALL DEPENDS ${WEBODFXPI}) diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/bootstrap.js b/apps/files_odfviewer/src/webodf/programs/firefoxextension/bootstrap.js new file mode 100644 index 0000000000..c95dbd4a90 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/bootstrap.js @@ -0,0 +1,36 @@ +/*global Components: true, dump: true, Services: true*/ + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cm = Components.manager; +var Cu = Components.utils; + +Cu["import"]('resource://gre/modules/Services.jsm'); + +function log(str) { + "use strict"; + dump(str + '\n'); +} + +function startup(aData, aReason) { + "use strict"; + var manifestPath = 'chrome.manifest', + file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile); + try { + file.initWithPath(aData.installPath.path); + file.append(manifestPath); + Cm.QueryInterface(Ci.nsIComponentRegistrar).autoRegister(file); + } catch (e) { + log(e); + } +} + +function shutdown(aData, aReason) { + "use strict"; +} + +function install(aData, aReason) { + "use strict"; + var url = 'chrome://webodf.js/content/odf.html?file=%s'; + Services.prefs.setCharPref('extensions.webodf.js.url', url); +} diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/chrome.manifest b/apps/files_odfviewer/src/webodf/programs/firefoxextension/chrome.manifest new file mode 100644 index 0000000000..b6f6e75cfb --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/chrome.manifest @@ -0,0 +1,13 @@ +content webodf.js content/ +skin webodf.js default skin/default/ + +component {afe5fa21-709d-4916-b51c-56f60d574a0a} components/odfContentHandler.js +contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oasis.opendocument.text {afe5fa21-709d-4916-b51c-56f60d574a0a} +contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oasis.opendocument.spreadsheet {afe5fa21-709d-4916-b51c-56f60d574a0a} +contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oasis.opendocument.presentation {afe5fa21-709d-4916-b51c-56f60d574a0a} +category ext-to-type-mapping odt application/vnd.oasis.opendocument.text +category ext-to-type-mapping fodt application/vnd.oasis.opendocument.text +category ext-to-type-mapping ods application/vnd.oasis.opendocument.spreadsheet +category ext-to-type-mapping fods application/vnd.oasis.opendocument.spreadsheet +category ext-to-type-mapping odp application/vnd.oasis.opendocument.presentation +category ext-to-type-mapping fodp application/vnd.oasis.opendocument.presentation diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/components/odfContentHandler.js b/apps/files_odfviewer/src/webodf/programs/firefoxextension/components/odfContentHandler.js new file mode 100644 index 0000000000..47a3d349ac --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/components/odfContentHandler.js @@ -0,0 +1,196 @@ +/*jslint bitwise: true*/ +/*global Components: true, dump: true, Uint8Array: true, Services: true, + XPCOMUtils: true*/ +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cr = Components.results; +var Cu = Components.utils; + +var ODF_CONTENT_TYPE_PREFIX = 'application/vnd.oasis.opendocument.'; +var NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001; + +Cu["import"]('resource://gre/modules/XPCOMUtils.jsm'); +Cu["import"]('resource://gre/modules/Services.jsm'); + +function log(aMsg) { + "use strict"; + var msg = 'odfContentHandler.js: ' + (aMsg.join ? aMsg.join('') : aMsg); + Cc['@mozilla.org/consoleservice;1'].getService(Ci.nsIConsoleService) + .logStringMessage(msg); + dump(msg + '\n'); +} + +function fireEventTo(aName, aData, aWindow) { + "use strict"; + var mywindow = aWindow.wrappedJSObject, + evt = mywindow.document.createEvent('CustomEvent'); + evt.initCustomEvent('odf' + aName, false, false, aData); + mywindow.document.dispatchEvent(evt); +} + +function loadDocument(aWindow, aDocumentUrl) { + "use strict"; + var xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'] + .createInstance(Ci.nsIXMLHttpRequest); + xhr.onprogress = function updateProgress(evt) { + if (evt.lengthComputable) { + fireEventTo(evt.type, evt.loaded / evt.total, aWindow); + } + }; + + xhr.onerror = function error(evt) { + fireEventTo(evt.type, false, aWindow); + }; + + xhr.onload = function load(evt) { + var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || + xhr.responseArrayBuffer || xhr.response), + view, + mywindow, + arrayBuffer, + view2, + array, + i; + try { + view = new Uint8Array(data); + mywindow = aWindow.wrappedJSObject; + arrayBuffer = new mywindow.ArrayBuffer(data.byteLength); + view2 = new mywindow.Uint8Array(arrayBuffer); + view2.set(view); + array = []; + array.length = view2.byteLength; + for (i = 0; i < view2.byteLength; i += 1) { + array[i] = view2[i]; + } + fireEventTo(evt.type, array, aWindow); + } catch (e) { + log('Error - ' + e); + } + }; + + xhr.open('GET', aDocumentUrl); + xhr.responseType = 'arraybuffer'; + xhr.send(null); +} + +var WebProgressListener = { + init: function WebProgressListenerInit(aWindow, aUrl) { + "use strict"; + this.locationHasChanged = false; + this.documentUrl = aUrl; + + var flags = Ci.nsIWebProgress.NOTIFY_LOCATION | + Ci.nsIWebProgress.NOTIFY_STATE_NETWORK | + Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT, + docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell), + webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebProgress); + try { + webProgress.removeProgressListener(this); + } catch (e) { + } + webProgress.addProgressListener(this, flags); + }, + + onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, + aStatus) { + "use strict"; + var complete = Ci.nsIWebProgressListener.STATE_IS_WINDOW + + Ci.nsIWebProgressListener.STATE_STOP; + if ((aStateFlags & complete) === complete && this.locationHasChanged) { + aWebProgress.removeProgressListener(this); + loadDocument(aWebProgress.DOMWindow, this.documentUrl); + } + }, + + onProgressChange: function onProgressChange(aWebProgress, aRequest, + aCurSelf, aMaxSelf, aCurTotal, + aMaxTotal) { + "use strict"; + }, + + onLocationChange: function onLocationChange(aWebProgress, aRequest, + aLocationURI) { + "use strict"; + this.locationHasChanged = true; + }, + + onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, + aMessage) { + "use strict"; + }, + + onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) { + "use strict"; + }, + + QueryInterface: function QueryInterface(aIID) { + "use strict"; + if (aIID.equals(Ci.nsIWebProgressListener) || + aIID.equals(Ci.nsISupportsWeakReference) || + aIID.equals(Ci.nsISupports)) { + return this; + } + throw Components.results.NS_ERROR_NO_INTERFACE; + } +}; + +function odfContentHandler() { + "use strict"; +} + +odfContentHandler.prototype = { + handleContent: function handleContent(aMimetype, aContext, aRequest) { + "use strict"; + + if (!(aMimetype.indexOf(ODF_CONTENT_TYPE_PREFIX) === 0 || + aMimetype === "application/octet-stream")) { + throw NS_ERROR_WONT_HANDLE_CONTENT; + } + + if (!(aRequest instanceof Ci.nsIChannel)) { + throw NS_ERROR_WONT_HANDLE_CONTENT; + } + + var mywindow = null, + callbacks, + uri = aRequest.URI, + targetUrl = uri.spec, + tail = targetUrl.substring(targetUrl.length-9), + url; + + // if the url ends with a download parameter, then do not handle it + if (tail === "#download") { + throw NS_ERROR_WONT_HANDLE_CONTENT; + } + + callbacks = aRequest.notificationCallbacks || + aRequest.loadGroup.notificationCallbacks; + if (!callbacks) { + return; + } + + mywindow = callbacks.getInterface(Ci.nsIDOMWindow); + + WebProgressListener.init(mywindow, uri.spec); + + try { + url = Services.prefs.getCharPref('extensions.webodf.js.url'); + //url = url.replace('%s', encodeURIComponent(targetUrl)); + url = url.replace('%s', targetUrl); + } catch (e) { + log('Error retrieving the webodf base url - ' + e); + throw NS_ERROR_WONT_HANDLE_CONTENT; + } + + aRequest.cancel(Cr.NS_BINDING_ABORTED); + mywindow.location = url; + }, + + classID: Components.ID('{afe5fa21-709d-4916-b51c-56f60d574a0a}'), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler]) +}; + +var NSGetFactory = XPCOMUtils.generateNSGetFactory([odfContentHandler]); diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/content/odf.html b/apps/files_odfviewer/src/webodf/programs/firefoxextension/content/odf.html new file mode 100644 index 0000000000..0dc023aed8 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/content/odf.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + +
+
+
+ + diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/install.rdf.in b/apps/files_odfviewer/src/webodf/programs/firefoxextension/install.rdf.in new file mode 100644 index 0000000000..caf59198a2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/install.rdf.in @@ -0,0 +1,34 @@ + + + + + + uriloader@webodf.js + WebODF + 2 + @WEBODF_VERSION@ + chrome://webodf.js/skin/icon.png + + + + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + 3.6 + 9.* + + + + + + {a23983c0-fd0e-11dc-95ff-0800200c9a66} + 4.0 + 9.* + + + true + true + Jos van den Oever + OpenDocument Viewer + http://webodf.org/ + + diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/packextension.js b/apps/files_odfviewer/src/webodf/programs/firefoxextension/packextension.js new file mode 100644 index 0000000000..ce606817ea --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/firefoxextension/packextension.js @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true*/ +runtime.loadClass("core.Zip"); +runtime.loadClass("core.Base64"); + +function addFiles(zip, pos, files, callback) { + "use strict"; + if (pos >= files.length) { + zip.write(function (err) { + return callback(err); + }); + return; + } + var path = files[pos]; + runtime.readFile(path, "binary", function (err, data) { + var base64; + if (err) { + return callback(err); + } + if (path === "content/webodf.js") { + // replace eval() with evil(), since Firefox does not approve of it + base64 = new core.Base64(); + data = base64.convertUTF8ArrayToUTF16String(data); + data = data.replace(new RegExp('eval\\(', 'g'), 'evil('); + data = runtime.byteArrayFromString(data); + } + zip.save(path, data, false, new Date()); + addFiles(zip, pos + 1, files, callback); + }); +} + +var args = arguments, + filename = args[1], + zipmembers = [], + i, + zip = new core.Zip(filename, null); +for (i = 2; i < arguments.length; i += 1) { + zipmembers.push(arguments[i]); +} + +addFiles(zip, 0, zipmembers, function (err) { + "use strict"; + if (err) { + runtime.log(err); + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/firefoxextension/skin/default/icon.png b/apps/files_odfviewer/src/webodf/programs/firefoxextension/skin/default/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..94d7d8da5defc1d587cbbd4e8ef7cdc1901ca6d9 GIT binary patch literal 44606 zcmdR#Q+p*{*M)a%c5K^zVs@PDI32rV+cr8KCmq|~v2EM7?Jw`o_ztSpI;w-JS!2!X z9%DuT6(o`1@!$af0FtznxbpXU`M(Pm`ui?;$w&6RfH^5kiUO)82~Gfj%4cbD5mooq z^A3+hlO+%0$F~g)Z4EUIH?^xb=c)U11b;ASfCvMm1{$QaEJdNQQUTe3G6A0wI^R%) z(=Gwu%*f41L;?+nk`gU{IKo7QURp_~pAdiz8`J{`S}86reyVJ3d%Wm)JBWMJTPQz0 zO(Qi8OjISFF19S&^m<5sYukE!>qKxaASXPLlH{F@kNy9#-QP;6aYE?y^LP__H@YRi z;^%+y(r;hy%A|b&mx>^PlY$SV@W&AM1fw8@1w%&-kRWk?HK4P1&s%y8s@{UXe{zP} z^mSEbsy0DD9RVK}`I9etd3`U;gad53|LN*>@;Eth7R9$j((L&bCm4Ui9}w&8zxFfh zE4vdH(*QhB8lZxjh6u^CK#WNAd^oT`3y-dtooQm{mg;x=a25>k2SP$ZqCRy-HdjAP z8UBhyMUq7D-MyjRT&3;Z*lHrq!Ei7!1B8X`K4W)1=q_5~8G(L5*kk^&Le&Y`UTgZ= zPr&{xTVE@s{&EAy2`~_E5C<2*OiLq-fMmezba0{MpCv|8oJ7{N%6Msqts`NZ{!5vL z8UHVQzw>6zZ|xHBWS8T;t?x|_=%Mk4^H1=X6J~)LrhrlrMHCJqfeirfChyyLU!)%! z$FM|&?E{M<_WOeK{b0VdxAnj_^U7@|;WB_U6f6l!p}+)_v?9P&G;-$eImje40AATB zz@lEjZ?C8rH`_DDRQnxaHINgzZx}DebwCaukvtRl+iiZ1Pc8Y*Ke@k;_~AnCi-Z$+ z9@avz$6sDM^O#JuJ2*UaUkqfj0F(+~#p!{ARLZx{I?9RIm~azyc+}lDl5MeB0N-F7+W^n7^(k3?PmR2-XWk$Mcy9B$k_?2!#az2}*~7&qyQVLp=!pU({3!?- zQ7dmA*~yPDBMfZGB^PgOT>05IgQk3qW3PN~S!UOu+V4l(y_P}S4-KwA{h3Agwv;MW|Gtiq6FY^;C(P!kD|+-L$nuj^Ax_*Ae0MZ>9RYR!Ry z?>j1<W((o|;E=iak3=LQ@g1gZ_-Q{{@M_ho@$QeV%4Eov=w0w4?}O55!KsTGXc z({DgfjQl`~(|`)EjZta1#G%&(iqMwDr7%KkKRWrfp1RgMFh>6bp=W;gND25F$ej9o zFBjsNds@*KvZeiu-WzUfTpZe{M|F@#N#zDdtHn4dbyB&#&sVwqt=~m@vhg>ot)70D z=eDXCdDOA0A_z=2^ryQ;ZmUsXNLR*WYd?i(iHu4RSw-kyuYxyn@lQfY3wQb|ZQ1 z>bPss*L-_=K&0AwIa3TD_ERW((t@AX5+}GprAIpF3c>~lBMtj5@Yv$w2ZbuCUGtHo zGPbVtgGV8W7o>`qG)65zm}n&| zV=&gx3OZx8in}yKir)ME6tkQEo7f-Yuj6uxdy0TPG9Hm(X*4-tzvt(AYHLGsqm(8Y z5RxI128;n!1`;0J#gnekv9PSQBUyzavAKvvy4PC&$yEA!Tr-flt7U`_AF5TW8MEEr z9K8T*djw_>7g_6hbnH&B-W|nVH^vHFag_$$vyWhcqyj?MJN>>}6a9!NwI6|b%Fso? zODJ8#`D1HX8m89>b=O;9E@T2Q>qWI{j z>2vAjr858eL|J(}69ef2ue_=p2vg<-zx&d5n4B?{?cuCE3MT8yMtOmUE1J&;MaG*I zF8yWDq+n-8(WEk)16JS#i6m@Q+1N~CQ|W*{6@?|qCu(UqgJ&N)sLb1zxpbgB zaB^{`2ORY@EaQI8)PGw*Isa@1UwT!_?iTtSKTv(>SImB;{yNVVa60z!J2G~{56KQX ztfx>2ARwQH3Wq9WfM-C(%4GmnJY@dmb*q_LrBP>q$1v}f!5jD~EFz+2txbq`p%$eL zRoKXt!?`u%|L5l#-HxhVV)f=KmGBQWXmc*N{BaU#pm(+vBTcd;znf8T%F*nm?{z2j z#(#fF40}h-bkdDe?M~M?6iW-*ieD}!F8JGw4YPRI#s`uRtw3U2nO4R^S3E!RrT=-E z!_S!iInvkVX=?!SCA55|3AJP&IX%B@!4DJ*U6-FY@8}Z=@Ux-DLe_SuuoQJfw6}js>J) zX=1#NxGW|Fv|u${CfqS!02^ zE}i|)MydVYda3Uu-j1%UlZgJ~UUM^V14>U+9zl>W3Nrw}U>W`<&*U_icUzz}h>Ji4 zt1I%C$f$kSWqJ)PD-~Ew~RlK zBPcOvUJ_>`fOdT{*}gU5U8M|s9CL=*}Z zryLXnS-xq(uH`O$I@~^T6nR7M0_-I_o88?))5K9uRQ?UGeKEeaC84|9jjSofj|65S zujAqEqh$4ZV&6+bnE(Docjpe6Hz1riPsUVbqzx$-L^MWxMb9kfd9Ved46!FjTYLFC z+dw@*i%88|B1eY6E0@{^w~5kVjM~CRqs{>n>mM>mzKfR~y&i^4h5B zTI9g88iBNG6gjYK@Q7Kw{MX$v85vXJZ&`%l#aT=e30KRsm)?7l$T|=C?>7)5RpduU z^`iy%1|lWFH99I90l>r3R3T$%6}WzXWtEPWzbZj9HI85-~K8^-ZQ*`mNT`mk{TTbXS!7DHQ&%(z!Q* zjFYFY#jOmYaKGw`g8(-HCsgdK^KHJR#sAigNjC`(PuNvLa z=P)S`$)S5i5|SJZiahsh*z2|T9~EL}33uAE{#!2;CkoU2Dh2;)>k<39|LD4=_v3%& zR^IbH=bn7>z8jnj1Jp`s#Sxr0f$lJ^Y#EIiV&P>t~*l9g-3kA147?mQ+O=EeO~ z59negu)F2`g3%fIS#UI>GCYj&GDOs1m|(H!xQbu%+B=fBjET5G`F{RfX(b1d6Yd=$7@y_&Di%twQ!J=@TJEqFZ5T)1<2LJW$3W z6H`VdDVeamJgh99BOHk>{D=#Sw6InXbe4Wy8#Yv1qb3{`fpl{yz;!4%6X;zPT;-0_ z(cwUgNk6U7mr@)744C&<-ej=#RU%0r9aC=^Y$RF76k$RA<6UI}3gF{_RIZ!{GVrqT z$M+utk2>tf`3XFF=NBxSN(HUNfV;*p zjJgodgf;&vwy7fj@z*8_Kge7jlv?8cFv=Sz_fShs6uLF_5b9_=rG8htLV0gdR20!y zJfO*-@v^JGe)ufKOw7kO@YJ~n8w%5UbD?3o*LHN311!66cwIgZ6m;8uQOvaV;P}GZ zo(kwjsAjskmU8>xg%mE*6rsT~GUSF?TlC)Up@jrbPGg!l;jG!^hM3-;YWsnOiwLF3 z{V<_hx&`Nu9d%QPe?RlxykJFP#>PI>meY%4*UwjlRC2-&E!0FdB$6>s=luxw^=haNBs)Dzc4OSbxqv|?)Oe$))Yvo#mRpz%Jj)bhDZQfq8b zV(X#3;iv+x8_c?P_I8Q~e-hXdYOAUF)UYCBQb#L7$O8R~7@)KuW1d*M=wA7~!?X37B_hUA|Dhjc{(Hp$DSbcO%nb5ao*WUD6jidO2d}Gs>7S=wbf33)?#G8ZA;U^+GuN*F18=x`wvSOK99w9 zd~pkX9y@jY_p*f54EY;UHK*M4cj`Rb;j_=3+B>MAzKeMn#9u<q@OkCXViyLv@ye2$$b=7Vow+0K>Y>+$0`CX;guG2mO?F&Ed{Q`!RXPxkY3ezb&GyQfFe z4`Vp^U?9sItq*KBHL=&{lF-fbUDtniOQS;q4_jTrk=_Ktng+l8HRC2JDxGsJH#Ud0 z@frYHyD#M~NT)wDFd1Q!z!`ICgmEVjHHU`U7R;*hqIcHzkLoO~IQdrl1}4CFYKxB# ze{b|~#7EvN;GZ0V?ZZ?P=S`$HAUmVw=+rt~_QNu5DP+K$^))&Ata~zq+6WJJw8Z3o z+VVR)VxSNaOVsN0m8T>-yd3h@wZMbeC7g%IQ!_7zdS_z|^%@|D9&gfMyyCohz_+_@ z{jOlDZLHR{mJgnV5$E#ZFh;qoVnb~Zme?g2Dt^10n*pZ&W#sW7CoejBU1DjELv?-B zB+wci3KKhqXbJp)%uYBzh(7a$?ihn8Q^QYEmVXUHClf7AEEg5-*L-}y-~kKYBhp5j z7Un_!$wTz_+?8mQviuKx!B})r8f!2{xG>)zZ%`l^$(84Aj`yB+({*>L(yuiJVG>a# z)NmT%oV1#f*st@cj}9>ufydh3C%yNMi>}*lLhm8w*!a^9jOHE+ts^sKbzY4|TN^Bl zVB1j`tR(D`K&V_(VFu{_U~C^yJITDgT?*YYXCahKyLY7(7N1smKo*m_C2|yITRi+N zRK#ChQXT!#+7Wvj>3JLtomKPM(1_IUcFCD;Kv>wY!?rcOI%!0S3$Vcib`rbdUubV% zhY}~m5^yqtq0a62d>H~Y&U}%hYEfmYy)|rTNfz>Hf-z==dv476+ynPS#J@5=K&nN8 znEH>NS%0f{CPJ@&mlR{vRbZzT6mKjK#ln)feX=4*v1iCoWk%ciUm%hcm%QAIC=$v) zg5E>hU++tsIZ4y|p{Lv%`&Yv3d%U2Z-y&g20w$5CQ`VaCc8GklYbdksjcOE;YCa@V zs0t+!ofncqmzOPix@apxFchk?pgf%jkq-xqvObgn)<6c+fbrv{{!ym;Z)RXEL(=!w z_-lp%eM&V}=zZqCQr7QQV@|c`Z_w^*mEP(Q(ns^El1_I^`aF_c8bjMmO;wg91_F)o zocG=>bQ}_;j+0y>GlR4+YbHJW0$~xy5#{=?jX$vOpB4Ijt&2@>b_=Ihmoto8K2A`- z|3GRn#-f1b%kFExdN%@_<5rtl|_IUU=;;fvspT{+-wjau^8qdudV%3 z=VDcFAd+|hhPC_iFVw?5%CV(R5Ydy@qWoz~W1#1&d6(9hS|Z=fk~Ef<7$MH7>x5}n zwQOK-&m~JWvuTF#*df0ux!Ec~#jSAw;19hj>nib(FkK{H`O52zDmmf&{*~*H7!UtS zSeRnWPLFY4$s)nOuJ%9#yD9@dZOi2_uQW9mg9U4tG;27NOgu@?;_y6L?`4R)w$uab z2+^xXIsik}!Jo)bo>bWUzvYe4q37AFO z{bl=amcCk7=VvW2K1c;($GVdrGZH$k06KeteC}#Zuj51FL!)2yGb9dOiY^je2@7s- z@6gK9mffx-rYgdE+@S9t+X-nQ-nNT0UZ~Q+OW(ZKyisdG7VmnsdYx%gPB);|lJB(J zfV-*AbdkW2T;6bS*q&^>d{EVPwm{w_r-S8ZhCvc*8arkCM}PxU)sZH{S`kKs-Ua^j z9AQs9gpd3EJPr{*7dV}ftpm)KhYcJz_UtfrnN7DR_cmIH5hnQd{){0*rJ2E6tBW>> zHBCFujB)GDtjJvB4=BI3RjvD78M<5>YQ437ETmAE-_skXMHDx{9#x=2>GB+-_Ae6v zEJ{(3|66t_%m%$`TH_@v7gHlfG4ZL9QHzYrDe#rb$_xly0;#8no zCBv5VM;Itwsu^Fz5-j~F=M}#ElJ~!&HyU(Pr+q~r5pu<63vlH`#j+9a;5aJ5k@kb9d>Ua1o=1oypQ`)4_?NINj7P5W9^TSHTaEh%gK1P{g9UixZgGE~Iv`v_7^8_A8gVx4St2n_AM87c)ziX=8~ zYn5aRRy<^Tn|k5y-IOk8xQ=*|A*wg2u{`X9z_TX>2W;|plhKaNjRm?n5$XyQ^0}d6+FBK_o$a?JyZY;8lS0;-F=EY! zx7B73vq#>Mil-QO5!+Th5-kua(LfKora|uH#5pFZ5cj;Y1_=LN4SWS)hQO{E3UU*B zmo@c&pzSR>LSMPR`)7!{O$c#K_&(6iROa0(R!(;g$K$gWz@hd;{h9$0R#l&~U?A7o z)eNzhO(z|TGO0KZCEXTnnCYb{)rSu6r1DxrO@%_sZA5_;`@aV%b_GUs(nt<^<}i2` z=1`?jm=pm+NbSK2m6P0TZP{>9L}}UZqJ$$3L&oR>o;siUamV04#pxc1C4JjDs(MM8 ztLY3nAg3_u@kK+MBOFWF|1Fms2b2fsk`MX-h79)ps+@+vMy7nLJm6(;WY1dfWHN1n3x6}!%8VhN>kH9X zYsvn|v60L#rmhQH;p9pbUT}>jzA|UnlqSbOHZW;eT5c?wjkII>{Tz>ywVjU=JzIHa z9^=`xe12coE(q_aQqUfs;?{GujLfa>iUSWlEwmoxPA1CJt6X*X%m0C<4p@S}&)K?; z;`t*4jx!#s$GIwaMeO5#0{@-+>#&W7XLc;UR!}8`&bk1DP^>u7e+Is~6EvQyni#7h z)=V!>j}y$3-lB{dX7=WZ8ZNZ5@gW-HHYL~StsperAR8~L#8Ji0on zF~4pmjkb$UcY2ch6JzDU7{7-`rS|%wEAvkT z13UiV4I?CQM-r_4ha{bHlx0Z#sD9x(1j)e!elHVL#Z273(x4AmC2jWsHIl9Xx^oCf>zX%Z|A z*BzeL3EwBKG?Zw{Kjl2WUBoYSF=27YyN8*C>F*8Kqm>+4JOaIPwa}7)p&14YIvgB1 z5>(*##ve6yQOZ@){$!OGegF?y@u{VUcF{v+_rMxouPTGgrM?%O`&1jn#6y7l)Q^m8 zzzFJhEQ)bOH9n071yLQ#EU^R~ZqkL^uNP%6_ut?qULkRsHbb=Tz98Qw|INBjEUx)^WgH~`2a@`md=TBzt7FMEoroOSgYmh^F2Q*vX+2egP79UIk)J;baY)mexh-Cu?V|m1~Ms`cSd*a})Cu+bSKIXly~W{}tFF^SzbL^)oUv;IOmWeh`{gm}rmrXBP?2&0xcZz#yQ2>TvyRSg z65pEU3ImBoMfxWKHZiFV2J?Yj-fnf|7UZDgU14K@o~YPYZ-0X-Gx zf_KduOB%H#`tX`Uf`tK}XhwH!DaD}%+rwF>H+u~ARIIUa@%b!9fMwz6=O-jdXg>cu z_Q0eW*wPVVDGfUCSbk8)NRm9Sf*-n08ajjIZ(Q^aovfJ8bx56e1-`wT0bx5;=rmAp zhL(H91P^MXy^*#{uY%Id{dcY)pnIA9b9^LGU1pU!1FKzN&xGa*8ZEYFM6leQ?8(y-825rd36p$D9=xg*~%;J3|9BO^kBa zEd~DjH%zLG_@7f`6b^B-2qh~24z(vMHcYyXjFRmCF-mY!c?w|>&!i4!FgxE$n)G&~O=39_hc#|RF z?%jU9?_nRFE`6;gxx7rj#pa^@qU!h*B75+gc2^O-h>~eN5WkGa5I=csgawS%m5`CH z7Q(lA8BfO=xbaOX*A8OqcS4}a!sE)RrciOBq%+)|tC-g38^_T;@8hz_X-*Be>=Rv8-|Bi_+^N(_BJCrlw9$7uRI z+=!pR()rX)#=RZ(e11P)R-+JOl?6+W*l{S!MspnD8^)z(;`af+>wB3Z@95w{ow7VO zDCoufIq4)O)rEDl5e%Z#`?y;i)uM8VK5s11nSN5;i!+C~6`Evj4$9fQ(@XfeF23B$y#Mt&NkX%vN6soowhhqPR+>F`Sm8ep4q*Q4s_n6gYSUaF zC(Wd-*93i#d&g-kRm|c#6PU>}%AeO8JJx*lsqQ`*?M}DWKtFR;2h#TP zHP?polpEK?^B$?qVEx15kn*VUglP;&x2B_|jz)Q$YEZbbTu&1)MTl@>_a=Lp^!U4i zjq5)&b*B12oLdjW6uw_~8bBts3}4SjVfeL{$f$+ZyDM%5ybf~RAB~1sb5B}!4q&ha zb|j>HE0O;MQxjA4vxd5*&{r3gE7dlL67{&28Va{2l3BZI=$j5f4rhy@=8}8orD)&$ z#r+fzyC=m#l)PyUYlRP`1a_dl2f-;RTd9>GH`8Nvgk7jv8956`GWEP|Jz+qKIVgZEtl+;J;BL_2^A(cnS*s(w#D*#q3*Q|M9%&X4^Bf zx|ZxBQ}vwKdF8Fnb@zOqtqTR<|B4OLDR+zFvI7?>S2zg8(#c%wP14qWXej4KlY5f5 zhRN=V77LTKf0>ZLa6CA43R~J7x^k>L2$=7)-aWF5YJ7 z?vT8Gsb23Mo(F)%Y-Ij@Lp_~}ec0rQ^w(_fs0pfcj+p9rf}QMYQIO;iA1*u~K$)Vr z@t4r^HinX+wFDmpD;vOz>S6PQX=`cB%FQPPh|0!mA>?o{BAr`fA1B)MI^^_{hLVx0 z%9sxR&^?X}QDu$8jUP6xbi%s`{1lS&a3IaMwLA2Cdj{GuXt;u_F{&>(fP>`A%LwUL zFcDR4Y%t4WO=;7GqDI+PaHBZ1)U3o>QPI?##8+ZVA}>n3SIj!C%dKlibw<=%lw(?y z)edC2oDS%mC^NL$Dy7%epk7=1-k;}SUaYcx5SSxYFYmrSE33 zu4fHK+fKm1!-E;T?^p7lS6@6BDi82BWS=bR>AcpOE#S`9_raL^?}uL&r;M_W2G3+b)^p1j5^yek)@peUSZN;%^J$g*ySxm)>p>w{+G?vg4sIpm?MiTg-2InDIGz1A zeikeC20nW5B6qm-pk3zR_qC98 zY%G9&IdOdZ0gaqClJ%BWiv$ztj17dj=3x)K=u7@Lf&LXuk}e~)RSBvnuCUG8B|rq0 zRpNnF*O`XmI~1*(VLmgGMHQ#jXxkYif`v7Ie9M?M$q>}0a0&0#YAq-Gmq#oj9{%XU zMjf$o(8Btr(Asmy@)XSGmFA(-(2V;-3?;vVEp$ePM}>{q+VfmReSCq#dFx(VP4dvL zXO%Bmn55VBO0|xiP3`faA+5lMAqG8HQE2OpWOf%KYHC+UfI;_eys>ff`ye>9ijopo zIV-itYTUz0v7vtss|Ocbm|j!MPlAHt>I_tt1lsu|)yBi^gE4vn!pp;cDR4V4b42}* zRW&AtbN5E70%Oe-vWLC2O%2fYoS%IFvHKURwaKW?udyEhtYmgXC`Rw+zGBVMZ~u^4 zmvtg3c=-G<{#>@EjXKtd%MQ5`+<&=9N5bE+cJyHaJZ}fJTr0nvKG3LkybJ;nk-E7h zIb(V9o!QCGL)GJ1x9i$|Veu%L-PFZ|#jJy)$*S@qabBhvj~Ksmc)o_qgBRRW^J|DpdO25>S$GDFC0Z98LXvZQ7ONxLtiK{HkKRe2B*MDxy_{#4Wm6N4`#N7k_gZl}mYRY+!~^P>fAEA=YHkHYx*4 z4$Ob_ZP>4SkRtX>4Cww)NBx2{rXWz}aVg1;8pHkmXHTiy+Y%(}s`354jwbW=d75jR z*LHK<%S$*1(ofqBW%`;->xmg^H8nj|HtJg9(TY!>eb7irRz&61LAT43YWwFw36AbX zD18vDE1FZX6AtO`X50hT%A$CV2dl}>ZczL8H-^$jbkng|YYr@e%Zz@n1N3<|NHpoL zA$bK_Wzzh(A^C(3qgo7O6DkqtqJ0h|Z7c9Z|M8K^Mzx_w{4`jy{y(32gx%-JXFZXhk?dRHjOu3sU_b|x6%jZ1P5=!iG&eTvfkMpf-yVS>PY9}w z0gD}U;q6my?3DME#yEthJ-4fuL^T_YHN@TTj#wx}r$Z4Z7@x;u+^0gy+#5bedNeD| z&OUSgi*5{P2Gp5iNLaBG_lC9}ODb8rU0j|PcG*t5T%j2AXTEqXYr-rf5Pi}k1$WAH zs;9EquP#B~%NtQ@0d5oCKAkZC;mzgN?_X8dcvcD5c{wrb-j`l^0$W!;SRls=f zPC6Mdd~K)}2cI9*$PZ)t=FDcu6bDHu*pvk7!-sT5W+E!V7?gOehf?iL+UHuByQw@N zbFd`zfS)7;iIy!?Vjrv~QJ8R{5cYIxN+Kau;hbI0M`IROn_VtFw6`@HXRYz&4td2< z8kz-OSLSu%RQ(mCdLKo<EK3%+~HP)g_SipCabye_Gr7+k zo6VY7CmO*5%rZ4db`|Fu5P%m*e>e+^v}Vmno!tay)%MhuBS=RDtEG;;i(6(_N;nn^{J1JS_z2?_M(Z*3`AQHU8Jy!>hDt zn_QgMM9;2ca#&GJk=>LA93q10TxAMWJd<97CVSg`$Vi*l z*gazu4yV=U%3&Fsb7-z=6BEf;GEbmt4fEoNq;UwcKbn=8l;G7Cd&h8*x!JGs4Alv&BUhwOnyxG$f zf*R$1r$1K^dVMf1?SjB&O~f(>CK(0qUWvGH!bV-N(}GJy)U!C4&7YlmC_1i6p4qxG z)0cJSgz~@5Ajh@kU~u?cgKhwC2`aoM ztR_5Il%Q}MyS7ymHK;4`-W99~d)9rszj^K2Mu_N6!27B#^|U!^=wtfE(0l)5h*fYU zYN@Ki(7Xg&cV>En3J&z93${FmZ_JO?GdO5#RRo*nUD!Ey>xq^9vWw|`K)=NLAI@Ho zZ5J?-YumIglkQ7FgkbE>vN?^$sLRF$g8!4=7azbgDZrs5nKqO?uSMRL z@tcR>Ck0k1JuOsjm4#+4bcd|~t3!_>z{k7ozc9g( zo$bQ!`XZow6r5$n&7+6LR6fS==jb=(5-Hu?zV*f{HiM~o-S~$+!S$fLE99ZSQ^_Hd zo+v@1M5RUQZ*DVgW5Xc*1I$etq}R|czyI>OPWAeil|YC;dTC3?!fAIl6lu}Aj2o7E z7X5Tkk1M6kh7N7;Se%(@bF-=#Bua`vPA*^2vP?Wp#+G-0LIAHh~V~HdcyBXVR28$#iLc&$9@+Ueakc6#_-s2BdUXNQcE6(I^GOR##y^-{1AgA4+T zj-{+^PYuO_nSK~)IQiYtwvrHCTim3*s4-WPY$ZPxBJ9*Hm;P7A#U_(p^*U1nON11H z6d_;bV|itmWCpW)Crwb?_}f$zVW>X3S#F_S-pcA*)#}{*m`X{93?4r!M=}<}Eu+ZE z`QHJDXeKLlKTy-riD0v8Htj$F$%wE}#$`ihEw5>LCaJP0NkG-XsdMV!f>p-V)&_oj z0T0|>;PrB+*2EVkN1Pq8K;AvOld3CiYl%GND9drntmoXbHI8|a;{ zy98hNV;VPae(%t3+z2JA)}Oc3#1bWAx5TsUGR8VG9mScJjzl|v5FI#RuREEg5%y^2 zKa3NeSXK-M1p7a}V`Hy^&!q@H@Xx8Kkt8Zv)OiMrFv<~3vY7N*goG#RC*EokHdu-7 z4^1(rL<2<+{--gsCkv-s9}61WPFAk8Hm&>I*OX-ch)#bN9@_gf1yh+jZ5_+<8QfF} z5`83nn$rQ7N0RI>`)Sm<5NMLEZ19Sj-XyqUpzH?B>%kkIR^O=w7pwD_7T>E<^*GH!HhyQP zChOGFg&0-(>Zs5m*Or4|p-MlAXb)xbbnkw%XQrHSH|^tZbuz|YxF^YoR;ScASC1aZ zFJiNDaDcUrF^B+)snBJeBldWvIT_Wv(IqHhe!rU7{aSP;wJrr@t;3|p{p6{@auKB($!T-)M{S)AAI4Y&`G?IE4ss;TM zDO9#8O6HbxfrZ?tWw8QnvLCg(dSrgBFn1u$?Tv)u-9aU=eX~{>HN*=f4Icqtg5SZYd2_y~tr(&7 z)3&1WJWrMB!l$9L+te=)K_!UQ`=YQ#0IToO7Ov~&t35jVV;CZ9q2>sD*2>KA^>b#Q zNb(HE?7dBu0YnlOr|bf%dYDY1FjFXh=g3s z{B=b@&ncg_gAb8oMYVJ`Va{`GsYt|WZ|1sBdk4<(H&TEIP4g@E9RW>ow?f*>e1SFd zBBPd2e1tU~0lsG+C8Db$m#d_u2gljfl%lc~Jnlm-B?dJIgF0f+7`##>tQJ-;SUIv; ze!To=n&45aQ0k&hMvIp2+Q6+0GPdpI?#*7`@kvac9Z5jrf{hAR$*KUe)9}fRZK9K@ z_hXdC$4XeMIUtJu*XNzzL*?U>bec$eXI+pzPq4VY+s9F2!z1Ud)wySv>(&t!&jPY@ zp*0$vuvQOAU^3L$!YAmu@_)p39txp58jjk^kC=9<&1Avhc~luX5}C@A-1^t?NXDiX zIk`=GV=i2c8zp*!QaY!kv4F~;xL@=e*clVd_GgRYrfI`vCh2B#V?=EL&tD?k-M1Z< zE33avxC?I+^;HoU;oC7|5Rvli+8xwzZ+v_^FE^Gms2%*ZX-p4K9u~|74 zrTGahs3C`%7En-@3F3}s!AGT?)qj87Br{)-hQJ)t$O7X@NSM^re{muVw?E)%7zR$G zeVzX9{HbTFvrG|q*d#k&<6*?H>F=VV4|0XJtq*D=?hAWsRJVC?cPRHC!4h)QuYCJR zm9}||cO7`FTI^_PP+4kihw(aj+hu9Gsl9Tv`OB&tn81sJ4Yi;ug61N=YXt7(+qV4rULCA=bj+q;!RFzf;L|1ubDbk=P_6_|+yNWe% zAdS&cLq*br4XbFQMM6UoZv(GGJ}A7WuCm7tJ^s07)`XC_)^OFO3BKGZ}CCn<#S~ znB$AGd;K=P=km9<3$cI);={NMz3h$=zz#BtDMwC)Uxk?q{$M_5NVHpkn0O4aWD4ylgz_;!RO z)tcblxEYbc#30O;A2@ck-FEK+62Ggfqn~~0TTlj+fk_DrCk!lfkbj*oM>iD98KY^% z**?{d9z-*)D*_+ox)ip%Pr3h*;?rI+5kdb>4^D>s1Slzgo&Dbv{<_V3r{jVMuLi5u zlP%V3hl<#iUvsT#w_a;wM8pnc>t3#xmDc7)(}BR`k)B1hXl~@1+boZ-368q(g-|%; z^rbRIEO{t~GP^}_dZoO+8EOCkX^I!;{$*hOM+G6lY0r7Bl6CQ2vx6}b$i_VSth|jT z*=89JIb-L7+(X&WMSY=apNN*i;*#k@$;wW^<$Ib&FVUpCGmSTG@Z=O!MtoqXlFMxjAJ#T8tNoY2`dIrkp#B^J?6= z3t35r0a&{s#g_#(Sn2>|3Nk72pytM`KEd}=AH?-HDWn#6mhuNqjg>~Cc1u1fN;0W_ zGR>9oj{{|~X30O6)ex;ik>5VfcaS;?NaKHz*_(BT8ppU-_x-{0pEhNMJj7AOlGw|Y z(syAGUPFRSX$ew^y1RkkZnk!#gO){wb$X=P^x?t1j*rKH%L+3eE7+He!L)2*DG5^- z0qUf(xp_O>P!;+HIciZx492{9%mlnxA(2JJF@k|b*bN!+cb;NiS6iRYVE;Kes)i2zaJ(4}g$x9v-5*`s zdYRL2y-l{#Aw}_wTi7>nF=qT_0SAg~L$AVTOj8)JHzA45H4oQs>kOhVhuWu8$RO3s zu3g3VEZb;K7KoC1bt`>qd72Iva{p7dK(j0q=<^)`3)+*0WOxWF4!xw7a;a`eiSi#? zT4dqO5*;sJZ#mlcKTO8R6WG!$1N~e8DV3+u(ewg%R@Oq;i;MppN9+zZa-LseDE+2e z{BVxfS{Uqor`nBR3Kk3axQYX>8n@f4t>1g&R|Fw_wtG5Y$|CSBFEemZv2n$fBUCf* ze9yhY>$SAUR(IHsacFmzOK<)(rTZ>0>}uV$etZq?acn&QpqREHAHQ%jw$h9VqZ`KK zd02HcQ6l2#y=7s7`VWWBTAgm}YU_H<1@~8b=ASBt?O&=}KH#QbJwD7%X#lJ_sCyU5 zX-xP{Mlbs>5xQ%=>lN&6t2LfE%lob`f?f0**v)+pF zI1w0s#UDz>@=_~_^XY9aqY6QX{Y@3%jr8t}&d^BNSq25`sH~z2s;ad22L3{Ev!}4| zHicSYFLNOWwH$f4cNBc^l|XM-Z^`T}ENNW6=CG|n2}6{2KI^G&P`93{$ui{-N8De;|vWa5(^^{yWPkutrC z20X}UMoC7(AVPpqBmn|L4tlz$_pQ3SmaMAWGxj~Me|k9Q+$EOGtm+mY4K+m&<#$`(rc*BV1iCF7~dM^0OCt#EX?w z0Pyj>Q@n6v?Moo3F7k{QAPQ%EpMHLfN~wUY&E-WrA?KkH!F+O%01Aa1UVh~Y)>g~- z@WV&=^wR?j$7<6|fh~r}=K^Lkf^1+QMzFM$#jpLsSMZl_>=7i^)|cZYt+VHt&6;%R zGS}0lrz6a4(Bc{;!F^W}3Y;D_SSXiJEER~$SX;FJkm;*p(`WAEA3r^h>n0W?R|YX( z?s@mDkE2dszOq$7cQnRFhaL3Cljxo|`V+i&*p^RDyZC$0*XB6Fi-@9m^z#CC`M8Vg z>*XI0T%Nxw7Q*Gv9yCx|%3*W0^aV*OxiDOpx!yKiATb_?xc&JNo_}r=L14HTkW11w z=cHon?>jp+eD!PBF&s|t&bxbP)Vm0koTwwVMiY!Dc5qK%1esjGSHH4>U;TyW`NL0+ zAp#s7Hc+Y*P_e=Y#s+Aj6&{#i_VSygW1bJ0)fu>1WHtr}$03@hE!5VkaaeOMlbn99 zl*7#!Lc{(WfAP=Sf9Hn#TYvPUb-+~p6^dq?LM2h8o-Dl+0O(CZJZueQ5QbB@C3(s! z_v?Lp>&EgqjzlhWfak@6d#62IT`OJQ#mWUKmoEU9C#v}TK^-qVvxdtf44J=2T%@Fu z%N0mGI%r}r7~|$M>*sBhoPSsB|1U2W@wKmA$JMK={QT|_Z-27SFbwHei?0{9okEnO zafoU;hhP8ux3IQR!bf}csPl)0%G2YP6-M~nu3&mTjIGBp!i%jT`5fa{D9^K+Zl{l7 ze}vWT+O#st8h)_Y^v2`Zaf(sZHI18Thmaz-%-l9Z0MHsv zuv*G4_NucC&?ODUet&S%#a69|T*h1mF5_IU^CiILPwt=L+SW3P`OLiDsgD7d&y_}U zAxSmo-$%C(admeEHb zeCsE!^6fikcy!w1Bvhy>jo9?ks6XPcH^$aZ4aOwy0*x#2TW~riD&w;sR}%$BGjQ4o zmj(FBvl|XJyXPy}IBg+g46C&Ypu)@A%Yz4XtgL#N9YDu=^i&KNz%A!lWlq{eF8kJt zmYk9KWW(j--SeMx))`_r39(fxUI3TDFLAqD2$!3kAr8;Fc>en8MOyg{9mag4@ovOMf2W+wVTY^Ve38%?1EMgkkvf3^(C{ zn7gF^MszPe*`H?w#S*^;KI9 z_V{r50&?n7aCyeKKfim5LNSZ&t*SR@PT2ziU~_XB-+b)`*4Hce@Kp_6b}LHvSy6lEzT&Ftc$;jKT?y4jQahODva)^i?*=_AxFcX_2_h z8gcZHx=ge%Q5R!Lsamzj`}=MDmv{H^E5G1a-$&}E; zy%ttimk@>sMR@XeZn(ew$8QB9xH-oj6N1Nc_IQa~SXiVp`;=!_m+K{W_kzxq(NI8hrDudpJAmB28AADdVw?%76NsSD@Jddq*8V2WINz zl9Q51rE)S+^!g*59=B23sK5kZU<@;vfX0A90K%A=m8XVG-44$f>!Y zhD|Wt6>5R{-d@U#5xlrr#?93weE6t~;)ieE#luH+ z-@9)1*b;pK0E)Q`wzrmXSns9Yo0?QdB`!>C%~S$sXKhTzAu83fokj>-FPzH;$hkJQ zfiX@uHT{`5%YwUqFMMSa3!S8%y z^Ac?4lgGIS^&XZBIh69*i_=1vKJ1fgmm$EX56-Y&TSBc;xad9jV}i?buCL&ePmi#( zRb{ohgc~>3_>(_z6S-V~H{ZUGPwyOYJPs42ATo&cDxI z-*J4<;8MAOOfHLXLiEQWmWnxKY_mM(vS20?*v@5cW`Qs@5jCl@q%nf8zPOFg_8OS( zgdQq!-0bn{PBk*t*j_1K^l~mNx<4ltl_zlD z!%>L4`z?Is#_D-#EndtnUwlmxaQVV(IUG&UZ1wStuU*5|#xg$mXdmyq_mJK0aP}G@ z?xM43^LyjH1HN#rmR#nG;$b%tOqlwd0*odTG|t*w+gK(^etN&jZ@#?6@i?Taz?cBp zj3Ad0WCJ@)QT!P7g!lKc?yvm(ExdF4m@#i=(<5q~KJOp2@X9M&-rEoW+RZK}6GgeU zY+G9gGA~a~z@U)Nb1)cUGP#(T`muZ5$2q)A?M2V67crUufBr!|YB34`-@UbplkS9% z8iNJiK<3A8W>JTQ#Zl^c1l5<47Q*ADg#h4_d#8A2x8@4HALl)$xcx7P0tABMQkGwN zZWBNIQ#QsMjwZObcZ$=qPI`L$ViXVy{w4n2>5uX7Q4<@rLee;s8#QGPoTV4VrI-Uv$V^GLtQ7C0OoP<%lt<$+) z0EI%1B56T$>!gLHasl~5-fgJ%Ybt&8W-~ajV_5aQd_jms2?IM7k%Pa?a z7S9N?fk7@KDCGj&S})KSc;osyj1kUH8i46jT>Lp-e|MkT)g>nSJ2S;Mq#8QT5I(f6+{x3UHp`VI z7D_q3bNht9{ByT#e|RN^uG3|xiXbD*=Ca6S0|Y@p;&F)02eJr8p~( zaQN}vGyLQ?uQ2)ecoMSL8en;23D-_%rwkME!2m75#* z=@CvJF0k68bTXAPo~c1TY$o(WtkvzP^ly zy)&G&2YCLO72N*(3>0z_(oSL>h6n;85YXfT1R=0g%<&h$_ZZm%s9z7f>kX`1;#>D3>z)t>5@6bTXka0UkAm_~Cm8=r+5D zPsMNtp}G0zw;R!rE75p_X==nB;yE^cT;kY#%Xcw1z z^+COdLM}k9ltZICIv+#Mj+LBm5L5C;KEYYs+i&5u7q+pxUdE&2PTJ8X-fMQO(F`+q z-n&x(6be~f-(A6#ohpXI3GP2Q!=r;HLf745Iwbk*^JBj9@(%V7TAWP6#4zgA2ExQp zkTkoT`23-gfAQCM@ZIlR$J?Kt&g5~Yhg~yjXzm)1(|*EMqlZ$tfZAG__Ya%=$*=A3 z_MNjB65Bb*40S?rn^Z2J;jjP73;4l1k6?_D>N~x=@hJ&Un>+~=`PNc+cM+dz95 z;;22s8xPx$b?jGm%D8>ffk0SY3glN`UBiB3gdgp-I4hrgQX@{U@Zm&p)*fMdWofSA zPAwd{jA@9ZoXV^Rzr^;UN_@6g$5(EwIm2D>is=I^nr}3F4Y*oc!ZTM_u)bEt=~)-= zeDH`Te#Q^|qK${2dD&pI-ABFA!!tM5@abnqk+Jc>{Z@!luLtW|UPo!@+gfS}tS@y$<;KqX7dMUp~<(bv|`wIzcf6@L|S z@h|V~ckuCXm!T+r^J|;VAH1@TUwU~BKYg<{FY@D)88mRv=wW98v-~9lv=`@d z7o=uB-8;kfdKu+nZb56)3*+1wQG*EtS9fdp?oZytx4(W3!%2w0`P)1A;oEySIqS@e zdpYkN@7z7*_I4G;LUuZIkJ;pTy#ajZiu5+jzxmNaJb$H{oY}&}mcuEnbb|1b=vbq{ zn5|}y8=K2KZT7gmQD(X}moBHPxUyZrI8^or6FVA&V2}}JvH>y~- z_{MvO_~E+;{NU3QxX~r(b^1gG$d?Pz>+;1s`rQ!$9KQMI{{#QdJ?=06%XinGujQBX z89~MfGJ!p-?l8n(ecmQObcZ4T-w)65>}mn)Q;o-o1<82;uk2Q^S06y8JX?1-!3T$J zzu^i5cxkgd?NJuTvhnjcFM;Hl*=B*nmcQO@Dz%_2VVEU&KlAmgc=wY-n=<1$XnE@K)!GtvH!IlLs34OKaCF?pyC3iK;HYhlH8wSJ zhJklolajN7r>8>C{ zBnB8Vk@bx>hIqJ_gWfznYI195l^G}@fJv4a7~$4h5#7Pq=7v>iKLDr`<&Z>>Ap={H zL@LOMK-DIRj2Mz?k*4w2&=63lTX@6a2)SVvrAiSYh+!|vbss(z!@b`e+>GuV<2l_K z5e_Fagj3W!%g$5tE6#8l+GYYlHY?{ayGSMK>%B3a-z?$wVRtcRbRIUro6h%`0vt8_ zFd|s5+d~o{^2PYj&CYqpQQw;oNKM#`|(r6rF@8KDrdv*hFyt9{RY~zh8GETao zzX^}YlmQdM{$NZUrwa{)pb;>1{<@`0j{Aezbt1kuTU>$R(V?@m2V zTiF=dlgS)U00n6R0}(+k6L746PSlNW_P5j6!Nel2#E%dqm4a@w&+7UzpkucCV?d~& z96c4o74q4u)go(48BW3wf&dU=zcs;UXT!%np6?U*&1)5WdfZDrJ~fiWHQ=)*aL^gz zg{_p~#{2l?o&|8q2XE{#e$_`abvB_lauzG z%_J80PlYy&cUbj0alZb}KED3dZGQf+H3uexDbz$i;?kyj2sa!_giFSvzUoQ|&3e}s zh#SLvU>IZrXRLN?rrQe$wW=ynGKAQL0VM*1Ohyaq+U_cf=_+#0?1-5vqnz z4GDFBCr;n|v;ThlcW$`9{l{+wAg@1a^|4y6;op7Oup1e@8qI!abxEP~cJAcTeQB%2 zl~RT${b6!Pp64MWCx3mVh}ZA7&a;oljztfg5aXSDv#-4X^fKX5WopjMT(3AMp5=KP z#hr%@eD&5A)@n;QwW55iuPou()-rZCmyydD?4NY-?k7jwKWYi7C+?s3nJxkd zu?JT2&fOE-d}bY|ryVls5ocZ_oHAs(kjSyPf}?tm1!Eurh8C&&wyEBsGpaCx+Wc$^ z>KG78QRVSrog14qwps&HZJO~XU%SFj?$_fq5#d^`x;cl@@vP@00VpT|5P-~N48{O8 zbUmc41v}#uKny{kxLk1RE5m#-i$P~}@VGYjWqI5y0J5P1pB=aHYhS6cHv#|4-4@0= ziPSAj)HRB0EuxJ2)ka>{FPiP;9I{66>UIS}JI8f2AqL|KyJMB^DCB4yso%I;E68zc zglu5&v$t08*PqsrSST_lmw28KBYJ$l-p5beT>GNeh>7ZZxrE2R3?#>RqPV-?z^k`5 z(C&_KWz)mp4&MFb5c|h1jK|8PgS$i?dzvjK=Z70sbk11G#H1oifurLVuk6;ayHmx( zM~x{DX+7Z_RN-B`g|jBsE8pL5ak-R7qcgBDS)FEC7m`yhCKghZtIGwP)%&QQby2OB zxV}~4@xwY{$l7ud_l~=X7}?sos4xneT}ZE%L*|4EQ7|+>poVrjL%?uMh9F!Qcz3FT zY*tt-=Fw{ONhnI?B@TK|&v2i0>x-RH$PbTN5Ha}aXG-|X&)S^o%(-Zd%*fXMV z`!}+IARic(az-lo3@U{TR?5~38xh<+>T&OEfbYGqivDIk9&K^5XmtTaMGJ#-ixroix5;j+suv#r5V+4W@-udJZkB(Zlk5SrM z=XrRhqwHD6c|Js*^YP7;&?0fjJ9m%y;tM-GJZ#az^VFV{j(cZ6M>5^Tw?8_<@BH!$ zY;*^Vx>h8nzDF#ze@w+8W$OZ8y0Oat#Z{PtI9h#942QTWcj? z?=l7&dEa@4#?#I~LRD;43wU_i`(mk|Cm@uAz+j_Vz?L)AwQ3O{aNOwO=(LLuK0C%Y zU)sUmVGH*jHRJ2J2#N!X{?3^#=A8IC8Qvtq)2W;)(P;M3=?t*DyMp_Br&0QcOce_x z;#=Q+BGN}Cl~(-xZk^XRE7&`1M|oOXrz0+ROVXw{QsCyrXIA)^-@j{xw*&`+5u1%J zH+NRhtGCb{PpoH-z@a4Iwo_t>KOCBscJcNnhd62UEedldd2hdo8{1WUc0Uy!Tn>uQH{^6}Y6R8Eq){fWY62b2 z5=VFU&iLv}yL_}?=VYv&WSrw|oxzAJ)b{Tk6{V2xe0+rGhbw&L`E|Z`=PZKMmVlb> z$8KTr)>@G#M;$yk>?G1g!jq#0Z{FJB*T3@&-~ar?hHC~?wMr;a7u!a@#k1Bz4K0j^ z*pLsf!H?OKdlK&`D?&`$CR&eDEZz=L;L|Z~yUIMTl(Jyluqd z!7;KdW)1oyn=`ZV5E)Kch70rgt!ric`A5f0=Mc$6a-E56AybrcOitjqJ;Iy!nvyla zyu9jViVQd%6Yn?r^J;S+(|Bdhx(4#u47OH^*j_DR+d<#SL~(f5#e<_Ze)!P=PU<~d z8p`={m3#Y5y!zY*mkL?*2IEVMFBXL<3-%T(RERQo3C20;F=yCepwk|p-5y|fX9f4~ zpU%rPJ5TH(X(AWv+Jcht%$?i!>YR*2+`PHQJNqq8k!cntM=>Vp}YX={Jw@n}D+G7Owo%TY(;LN6$~>mR=AJ&KS(lNZi>z>0b_xatIx8$)EQ&XQV69`r-1+0|wSgRJWy|RRrN&&-h zh=a2(?i{r6{r4Z?v@vkiRPoh1?_Z}k;%Tdo>pN9^bm!y}o>mrzCKs^%^9d4p;b;nqDG ztHO5wJLwGZof~ET;9eUU2>+*Fyw0(b|KdMCU~gmzgIvaNJesf{5?3pE-fs*ODynFQ zOvX9l_ufTtc}|?1Ovo@^iy{jc=9EG1*Lzqgs3dua!yx zYZW^QP!(u)hd6EZ@yUY*_D?%FZT1s%OyY1Cq27d4@cw=i&+gXd87|LBjU{Cu7a8%w zoUIo`q)9GG%_MAfoY&o5!TtLu3B{6Qg?;)bEnoBmT9VC({`Tj8eTVy?_zk2gsm)ddhg;>LV^~Eh-zft24-+P4htr|P+K1aie zC8In6MfG(@^m$oz@vneTKcNo-5eu4a46DrMvnVYuv3b_UcsyYspfLe*ASWhc8F)L_c-y@(dcz5}Yen8Y>`0OptuE!TR>@R28aIfCydxvd)=UN$oF&vCT4o1q`Cj*{#M*PvkHhBJDlL8HNa_WfOqbk^0e8` z;OMM_8@pA!dwalhjys(qnpRHDrez|MXrU2L8EvZOHZs0udx&;tfZd%H-rqZAELC(W znq(^*Pxu(i{)kw8u>YI7nDeOK^T*)S=1x-i@n>iJ<)6LDet*nDA4hr(&mW!eq&MPGXTp>21d(8TQJfnugp|M#bDFzOIh?r!RW4(sQplp54^S#( zSSe(sl+UnS$VjP>K`C#)vY7xNG0`Q|N`0KP`uuROE+?%aPFj8RhLc(1C>@wSDFc0} z@<3; zu9Pw8j$F&w82Vc6F{x@SKO-bU+lN^r=G_``sj|d;HsHxo3sB2#Ic!2@2q8Gm1cy(> za7+2zH8A9>TQ%;rM|}N35B1^1BL=HAzEa^0E0scqr9wusfq|0j z4MXYl$5D63c7M!+dSBZ8F*?IBy8Q{C-7L$iH&*bk{_3+xWZ;Eu=Npy8s<1D$r_HPp zK0IvUn=kEPt-6HMMsGUG$Hn4`8RBU^q>c<+X1iF-A*PaPpH_RoPG`W~ofY1{e;UQd zKDU_`QAh$J$4%ul>7C)Lf0S-!4?WZtg3Zo=#Y~2yiMn1?7W#$`R>!M}Y_@t_T3%wQ zQb4EOvoP76vr_2i2?-2ArHas~i=D+#K<08;E-e?(I%$)WFpkmH!*5&S#|aOfisAmF zuWnwyxmH9rlVPa#VhuIqa7<(ZurnO-v*RB7lL;p(ytY!n^;&^O3?DVeYz`;<-LDln zR^@6bi|02=%)TlN444fJvc@nl!mJSnfiM&OY?uv1G9nC&NG320jQB}_)}j;`g^IQ_ z#8!WT_Fyb0ogwa?blL8Yr869(-J7s8nuywX%UM{|{nw|H1q5;#!|%PiEn+0%D-!Yi zV@&A%(hWB{;Ao=QKknfAZq*wu=TK8T2Rd^O={8Mp&3NLdB**KkC6%9zyEwu#%niQ$ z(l#IM*Et?5#YhtF`p^hW=Z&M1KBlw)P7Fb@F>)mGcamBG$CHqZJhSCdh3-8C$?by8 zdWXv^OYC(AP+QtZg;;@+@0gK<$q=uMW~PwA@@k3Q){vwA2-cXDWB`$nApv7QVB^g{ z{e!_%G2H*_z0+%V>LX?YB5Mq?2K>s}60g)Uyi@NZoG1ektd;`aSgCM0Ccl5b!z>N6 z888Th*+5v#Wtk0xrCh*L)^MbX!ARK-$4)J!7^`ADA;w|I@q`>t)Xq>1$#JMM3GE1q zi4v2E$|O|RtWJ}uq&Uv?Tf0?X(YUq-HWRH;4k8JyPul}zM7UPT%So$``Q*-zv6%jn zF#7&}6W@Gk7jJ!dz*#gf6Mih}+|LWVGH1N3k7?zcx;po--RZH@8E|K(#=ZMz>0`N? zYtbaqiVZlDASxn;*ynx4kx6idL~pA_5_(5aIq8x$#eIxZnKWeiVFg z*xOM9%GmB~D}^jFqWu2nbywU>KDSolVUzsR4<0}WhD^X9*CI#&{*QnE8Gdxw!C$<0 zLWNR&4$T>up}&by0dMqk)C_@9Uj+N2B;rm>;C-6TSAi$uWTg>X(&3k~qpqo>GIX^o#QTy^@`Xoublm2*Uj??-N;o*_ob%e05no`m^J7pEFG@^# zOQgJQil~ZHM0@wo@X|{=+<(-V&FlL6ZQ#^U_6|rAGE2;Zxc;F;TvF%AE4$u$gAv8p z-_;czcn@!j6x?dFPM*zrkJXhjd(8nt`h2cBwX&5wYT#h9DuZl>we@9;dn2|QeLqK* z5Kuxx8W%0unp}$E;TKs1Puz1#7267AgrtV{qLp$1d*cvJRl!%bm+`^TfIoQ9BAwC3 zX#+x2RUqzWx!oyEjCgi}o?%WjzxIEy-__kJGFG^H9Rn5iu0?+rs?(CIx-VOW#87Qp zl8M@%CrX4$9=8TqtK_5AYz%0O&D*BFL|{ZHMrg$LDYDZp>@5{}>;d+?gwfj5RN}#5 z3)gq5u_u)U^{c5|X+#PpV%bP149*fqK2yaxlE(|bn%yBg-66NPYl-_!S3{SGi^UlL z;~r8-WE#Y8-V{H$nj$7aS_$txYIA3O$u0*Ecbx|mW4(BC9rn6Isw&INMGD9u^30Kv zD~gXzAY5CoG8~WDXtwQUrXfLNbKRFV&xL*}yqU*4$T z#f@eD=Q}O#w}wn43X=V1btjb_T2ef!kC2WQyXuF?c1Wr#q! zGlon4xyPAMTseJNycTS#$VnajTDyPH;%2pIVYN4ID%FZUNJfH6n}`*%dDdaMwnSr$ zom?QXFhu>&fv~n--7y?Rm|}9|K|_tPX#I?#8szsNtFcs zhff<6V{FH)M2i~V^G8FvSiydm=%OWKnmBjpl+Q#Y>|kOijs!oPk}1p%x{#UdB{*B; zdY*cU0OX`Oz^m74Oh|;H51rbA02rSENHqQCRHj6XeLP5-g90jm=xkbxycA^S(OD0Z zP_esN!QOuJqTKC5m`oM6{0f%nvhz0f%qdZt|s*zV$N@zG3jyN7oSYBRY ztKN3&)XN^hATV5AT_!=Coi^QCjY+gL^X_qPHF!>94TnMg6R0vOkR%tC_sG&D5 zrwbJuA6UyW&Pa{h8J$No9@VP-yToJzW{UQ_l0{OxFQTI9^A~k`agi5_3KBmbHwRc= z$|0W(yzO%#WOZS-{i1gTX;`l5FEaqisrkeEF3-cV+9zkK+p&fT4wBa)_&6^!%1$?g`25Sd7N4X8M8 z8}+iXaqV|ryTXs|HR8|VUSs0?Fg;5w9u8C3I_t7rDN-^9P@x1uq0j^wtZb}M37#Ie zsA`x(fHd?CBLuYT-Rd$Z!h@$`xUc=MZx#Wp`QYCwLi{i!7svWo)h4O!ycSRAi$?lm z@iR&pcPjA4>B$2+*hEQ5?(J)I9(0S?s%faa7$(j)-Wfx#cSoFr%Jt;}W)(wRq*6+4 z7AYx_57ymRWX!ZNwu9mH<1V~G2h#>^jT*)qvw-*ao7`S6y8&UBI_Joci3LVG?-&ji zQY4)MN*DzIit&=h1gwSd^t3}`glns%#CtJynY>4h?y(4?#uSVVR3J3T^bnb-7Fks7jh_z>V!?G92^tq(u!$g+kOpWFZk) z5=vcNuv*a(Lz@tOI))2kS7-|&BBK?h&_re^jPOd35%pedN5i~jj^ao>H+pb3J??vaA)P9Lf87=1;eoCGy3GbRR+7#SH+)LS= z>i&L%J3F;>zSnsxn1rF*xK}0ONW^u1f{QDe=-F&Hi9*hh#^OWu)qajWw(gK_GjWWs z|Ic~dX1&W|Imb*UU@jkUV{3)u@r0+xZP!29dwxqsiJJKO`DqL8_!1ZeaP(9RSIAv8 zeuwi$W2iov?F)-(A+(Yt9aMApO`I`lKL3$?<%gH64 z8++%3XQq-2RdM%W1FN+q7V=p;l-YY_2eB>F9T_s>jg`}LTsbGr{Vc*M_L4KI z9?t4z6AorEImNi~cG7^4TLT~C^4v7kIs?{QLtNQhhFXuzP#H-H z#iylW^2_F*#kgi@sq2>7psb)Fx<{Pd^kk0Frtf3akpkfUeuJyE5_9=X>K^;!(vs~F zT=qt)){|;Pnt1~iag}slG3D2wi)TS<;JRc)s9ECf7tW|F)g@L}%N$Q8L|~0uZM`m` z&f7YetZKcjc!cShZSg4~9zGSr{l>reQB8nCl#_C>#WQ~@>NON}YNN=55{7O9l6nf? zrFzuEW_vh9aZBV?6GrV?y~Y~{=dr|`ilt`Z+3bR!HDb=dN8q^CM?Py3x`Q1!;91;AMFmRWc@;^7bM`UE&`_fW zcB(#)ZUS<3tIG0nfu{#eo}IM0R4Cd8a5O}~Xd}=>6Lf$6URUc`Wk=vX9m55~9mFhh z6m$4p$H%ok4sijx^Ozdb`-CN$1?qy?1T2yiuLqCRxUUW{}J7}U>F0fL{PZ4dAAwy}6H;R+h zk}B4a!N9<$p%_45BqgAkIbTVVhB8Y^Nji2`|M>oXgPR)_2ALohWY`h5F$|7EDp8F* zw$D;PDWWP-TO=FXIyfs4yr!#0^BaIfo>)N!nGCnDtk8(?@L_|)@tEV`n8V?S<#N$; zT1mW^|HzQHDR z*_Y~bvCv34cQcUbIDM|Xu{Rj=q|u$u=`LWitw&bpg(6j$+o+9KfEiVzgcGExH;f@^$Fr!@?ww6>Gm)4jw=_vU+Nt8 z_M5zBwae!TPNoDHbephGJw+bb_a3%h*qBJdDOT^L$xYYCo{TdJn)n==$`%Ot=%CK6 z?PXW>BmO?SP1%qTwH_`KWvC}LB{e`y6ohIRs`a{Y)sPqqH0(4Ho5X<#tE(lhuP?K4 z)@Jjx8y(YS(m5WEIT5Hv=U%0IC=l z7Z~Gq6ZMf!+}w@s10#~5sb7@hR52D#yXKaDSM<7A@m^Qb1XEI*s-iQ=`sD6DojXh| zYEAwP3rLu`!i^2AxTjiW?2cJ`ho>_H0CmfTiYuvl?y!Dud~w{TH~|g zNEHXYm0-Kwag|&b1LK-_xHgrv8c)CL39Q!?zdKSr zRCKvByBk{%tDcOK*h|_SSX~_t-28}Xh($^4)-n|jCz!|?XeQI$0y&3~zR(jNw+37- z=NTB!lXF`Bm?}S$`3mDj?|13g*6VF$zW5~ieKZPjc-mnCF3(d$#X^cjd2+uAfehgk zaVkFjq;BxE^T1$WjEj+lBBGI&*OECJ6)(_xVf&o@!!zC5s-`xTIMz*yF%kvy6w542 z;Gi|B;)o-+T9G7FU0hmTE^zz$DnpX{59=HbCpP|7I1MwS_Y)NkyF&^?mMR77Z5`5t zTJqIyYN1OHIoPZ+5#iZWFY2v`M6+oGCU*UWA`W267~&i&!IPGqkiJ^U zGaXm@IW^NI4VNo*yU5#0!myIV(wOwVoP#g~d~n#}?q)UZji-=|BnqRjC>BL5Eu`;# z=-_jbMs`z#_8W}CA5Ov2-kzF;1udaxo zwK@-+=riPnlM+EI#`@=3W>^JNi;s+ApJbvxO;9b4X?=<#sq~6P_QLUmY;;DPl0MEH z%d5deV(Y>JQS*6FS<(Xiq^yYxh^iTHesI!3F(0s6E-oU6<~41b_PFYsu=)B_CItOa zE`($lrJj_k*0jA5XIzP+i4|Pdqqw@ zs=o35A#Yt@alKA#0(hxh6K zno8o_Dd*;(T`Rew15!fBE?o(KP;I49L53*Cg3({p;M@2NTv7Bfe1|? z>KJMjF}6U!ZN`U3Ev~IqGzg4Wb48oDUmqIZOHH=0Ny;I|lTgFaM1|16KsUE)y0ul) zcD<`dkIr;52~`kSk)jc+gLbmTm=T6g={TZ_>~;DqmkU?Fcn4Xm;^0eSE>lgKD%>8ch@`t4k$mvWUPPPF>#C z$I7z>*gg#g9wY#X*Mp>_E2`OER@)}XUtkYqCFvzJu^Xq9 zSIPJn^9#NcBTkTt*`sD;31g2ICduPwkDJxPWzsuH$Iq8c2}OMe&n3%}xm!-L%`;H@ z;H1N~T9MgE;IPRC{eB9>d zMm36qov_EIcWh=rA(DuJ#pQb4;{c20JX@21UwdVTt$LS_9@aS-O{fko!s(~HAVU~3 z^199t-Ix)LQk*oLOvr9;!18jzl2{OmQwK)XK=!Ng#-IHD@TnNCGTabJlg&^;p}HMC%H_t!D=||UA%JNE zP72tK{~H%T#o4a>$E^X&g)H(}bG~7vjB&~v@4|Yc-gj0{>|!%-&GlBFqjAWs z_0oKgJ7008^D2K5JA~Q|7n&sS(nc$qc)bs47!C6w)u)zpqRue{Y&5%CEM~d9T%_>= z9XMi&acwTCinxr90%10r;k6qZ`rLE7T5t6A?5N4cS=W{K#oZuN>~q4~sv5c~TNTFX zrYMIjWUn=3b}7#w6R1E{>5bKjGhC_Q0lwsamydCc+3*WQUA2$UP>gL{;gnLUG`=mI zdZC6>4XL|%7Lh2_c0L#HfnEB@G0W-)7g__=L~*sx*3}wkwK)P-BE!J2k%a$`zK%Io`Q@$ouz>I2nZsV{^G;EWbh*dXaR5^~TV=~AU=y{#{Na9&r`P(+TNn&FCK%@R_is4WUmX8`m@3(GW%PrQRl zHFlIrB*aL@$F|QRgfxu2sU^3>r+{LT%Rw!TezuY;^|@lV5Hzu95{qt1#9@3q%QQsf zl$ys*JDuxsN%FKc;CiKyexE2V_U%!y2!3J?9L0qM(LCY)RQ}a_v8n2sD9+tlFVB%Y zO3dJMTHzF>Z8WKbLUPJL!b1yTGY&~l&KU06Fp2R-YQqoz8g;&qA*csOP1dR<51%O+ zXkY>w<5D~V^{tLpR+jkUD_3=6tEPvCP5t=8N9?o)1jtOr#OWXk8ERC=E56S%O;kwl zyFscV>b7B3QqDW8C8`GP0hg9?iPkiU{IC5w{<01CQqAJN{=d9Yfig#-+6I`0QNwE2 zhr7fyZoorzKL1nu1AYT$=TD^0PB?^W}ZD&TPR*eofx?@ zzjNc%@M)em9y47=G}|Lt;)mm5&OAKsAops(mE|Jp&0eDVi7{g>sl078qm~Jes~%4! z(sf=_92u?8w@wjMRtJ#u;?~uP*y$V)FKSix`eSW(2V7k%>)}DuR_*|5#4^bQSS;ps z_v(r+E#=v4_4x4i35Ub6YeA?gV&mpWNa4OKgbbZAsz&GKyI)v^mF=BupHCXK$Fu0! zu-_lBB4rjzIriH_3#_BsBOSc{C%@l(Duye{H8HM?gh~0L&B2QprPBCG3_==#AsH$l zBK8+2K}Wm|w zjN2BR!&*F&GcsUT5DHR`TLawOuFQ@ci$*-zF*BGyrz9S4n6}Aj@y4R53G;rRZDKy9 zjv9p_&YFF0ua|k&>_H?+ph>zslF2?^am7uHUJ|20TycS>SmksT5aakcBDJhjv&t$* zemRap)pvb7I&A8dE2}&>XeyK%x=xL`ywR&y*0i=-Vz)EoXP+Htr!i3aIYLfd<@zVv z{(Uqm0hFrhLopFA&$X}fd01OSqY5L+kPb;0=Z}r$XAIeI4_I0%a?lyNT(Xl}3chrh zd}*jG!nL@Ml&D6kRa;=7j!llVnlKs_7kl}lgRwr&RUhw)Po9f9A8t$dq8lCcuvT%q zuqK+z`I0{Zaf05#WI=+sA`~VTWF%mqCYk2Qqj+|jNirqf;|(ILcZOUk=QRPtXJW(j zsL+|O_;a{2$8_tL8Q82d?Du^2mo6mM2t9IeS>hrLjTz-Mk>}dZL~OA@5}h46UA+~j z>XIavB#A*LjMkRs+08p?wDx_}LTaryx-`aUrBZMODx%xlRlfA{Rpv{1e*W2!e)91n z_Pax7jL-LvHIsank8n9)v((d zFq_LT$Y!V_Y86*df%&l*?&bO_6KmF$dRm;SgmL|oEqwM68OAtHM8!9cu!BvF_(tcR z+_F2YlQ+XPlovPJ+Ya&*H|H?wW*as4bG`Q&H9zzM4?pF~rr#YlvNM}JWTtCsnrx*U zbw(COvzo=vow7|`EJ_giKPp)745eJiAe%85kHh)M7fBWH+{yyZsm-}~t}SMgO*7tB z5(N*MnA7s;xXqWJ+eAK_;cz%fkH$>(_ksghY46IEMA9*|GNVRQQJ->2v&nXI_9+zi zxJ0UNXS5NdCY5@8(&E-uRWl~gYgboEP#-)v)sy44E3#J&Mby9&R0wTgM~GhCUe-?! zTGqpgM59RP+Bk?IH8d2X?sv7Wgd_~2zp3}i?z>kFiB32gjae=iw0_#Ln}b~^$4|v@ zU;D$?jVh}mM#XiPaYn3S`|tT0NzI*uLmlqdz_+aBTP@qha?7^w&9>bQ-`28iFWYX} z#?o!+re(X{e*eY${09%tc@94395XNW^Z!gr&E}VA)RS!+ai(+iqkwtJ`CPhXjjDFL z|4KY17di(436mrS7AHz!E(|DMDK_>syzU50%3s5%h44x=hg_WLc0`R_eXGFN(pE^= zA7qk{?G1MCx6oef=JmWELk*uEOatJEWH7VIR8e>OCIS?(HHKj4>@rV3KM!zxTONmi z7t>i)MJt#SZ5}4Wv*nZ3bVI!zxgp+w*)qR4 zxFw{R3UN8HeDry{QsKpv6l@9ux@7=hY2l+(2*Bf=XM@8L8k_FQGdN87#caYc=N|BZ z*cQxV^fY^xg(o0JS7*8^F#}AaM5{d3sYH2b69{68tbSQ2hj@o-TRSo*(T;8Ln*rXukTR7<6sZ}Bmvuo<9^L2k0s`N^qMgW_#Ab=(p@|bls$NeW6ShS>$9zDd47fG zzMcMld>#96WqI@gboqD!X2l#X&lnZ+D+_h(D?|~W*adjRsS`zhFxE5&d3!5Xu;Uuh z(W9t}CqUEP`{NMqj|T@ma_ij+NZPCx2`ebXvo0H{lOuF3YvB+aHs`JX3#t9mP<@WQ zr3KmXO!%}{#bsWdoi_UNwYk*QTQDR(gL$dD7j%%-?2A#hAoBHyJBd2#J|TVjU|!sz z>+Y(iQ!ARVqPWY+R6dAo*+eoM#9NLmJ-*Ai@yx{dTTu&^W{}HJ`lzyJkYHnt-pvXu z_57hMy`6`pyDL9(X^_?G%eTJ~PlhTjYT5Mp(c~>8^~I8-c~8SiJ%RUwsQ|*tMK=~l zW~{xep>}0Fk#~8u3X4#KU49wk2qJeGUe|@TBY%`TU;or`_&Yt=$g2^UBsPmS7!91= zipLlg`t=nxRgg%$w8Oiu-rVQ#+b(CrWfc>4Qzo&pikhT&0vC9gvreL0rGD(e zf?yyv)47m5E$p6_ zjCFb#^|m{l(;g%}B|DEG^Zw-q`WI?UI-LWLJM|(LO%CtvK5s&6R`=o3*c44zm#9|Q zkQODRsl_ytA?47^8!v*HZ=Ze*a;zfF9`%#(1L7*?^uKL=Xd~WljP}{LH@hmNHnoBc z2rT`+MU~67wKm1-=9N5)>5}dv*u1fSrjCI%P#$j9O%-X64l!~xp4tB@aOow~2+NeW zB&EWWRdxhQMmETnyqKF8_LhnRq8paK)@!nIq|LbU5q}pRfCpat0JRi^f)cPQVf&;V z1TiBCL!`xV)Q*Skl^RZq7$|p$jv}%|cLzu|X=hxpvD%^8?Z18~(lXCXed1DMJ~6Jp z9W9Jy;<|z2l4yFi>t|4znKsc$K4ND5@T7S{pO$MB-l^WOaFKcrAXE^-ON)S;Yx+FV zg``>f9q9m}NB;qgg55d&<;-@WHEW0u%?EVu0xpVPkoKwoBbb$&n z&GD8BK0Bs%@SdsBqXYAG)yZ%d>~)-Q!b#18X-yz-se(CpyMP-x7p~+9E%#k5V#98j z&8WcT(bOWMVnWJM)C?;s_^`6vxe4+<5<0KLWN++r<20FNX|a*&iz|bXzJO#mO{QJqvz z+T!lcI)!SP;n8fFgj*WI`g#WQIj0r~tI?!FwinX}BjcEwYANRR;i_5=doxEs1t^KB+Ysv}or!Hx1*9EF9$a^x(Mcxz$V zgBm1RRk2mB73^A8^nWl0S~IUWs&UM8tE~345;M^=zWp67i(%2lq^6yf$%Pb$>@;aG zkGjeW%Jxrm^zGn%)#H&f&z{p;UWZLZ`8s9^6FY*F@N0}_f31@%=|*uH>JFd1+(w(~ zEIHT29~Ua%&HGzeUdTCT2<=Q^Jo)r z72{84yvFQo&lH6BK=3A^*)cGu_0Q8C#K~&-z?5jy+>8h(2wSSa76d}lLM|-+Pl6Jg znq5i0F!`)_@cTbk<8L9g%qn32Mlqnig7 z<@vjLHNJSDjy}e>)KNKgYHnkgu(s{QiE*;jY>+G1O|Bx;c*I;GUUGpCYoEiW=})l0 zld~M(AM#8I??AS0M`-Bg8L@2G2*HaRnw2QWhNyBN-+9i|uy+8z|FtFJOjwPdXJ7^`z7AATxNFH6Qjya@5K z^FlAVES6d({w?})~!8;a82`b%w60Z`Q!=;$L(pj zK_Exhmvn3{{toyi(kIE%Q*X*7Aaf*X6lAk#X~JY+qM)EZH8nHajEjRqYw>_Qy0M8_ zOcKk>In3axYky~*x&D&wD>=;C7Yr^ASX-1*SVERQy0JGG)^Bksm@g)>0HQB(p?Y-K zZM836fg+W*!aTg-sAlaFsrEe1E3^S5DwaoSeS_`46~)FTteDFh-EA@C_%USCO~jAY z834VvKTD}vv#bgU3wi%8gHi_1eKxBsTC?ILal11j2nD!hWVK0r5m>>0!~LZm&EJ}z z(puZS2KU;>SPLeI95uxLeS=tt{CY?17`mj&AGuD4`hJsS0E#n5$v}p&W=BU!X zJ!xv>8fNaTt>q?H;+ScU=r7o1Fc;?FnHAc2Kb;88R@|VOPB{tijQ*%-&`SxnAlAEw$ad1`6e|AcG)n7~^^fD@Shk?GD`Du7vfGnQT z(4xA$y+MyNOeF&W2wSbqH*OLhZ%6dpwi`?H?PFMgiMZ#0I^%RsZr|M*xk_K3DZc$B z4c}LZbOWXaWXk_yx5#JKJ{7>L8D2Y7-F+i7o}RcP#owIce0+q(*O!&HrKCW>@jbG8 z{7cuUqf+(557Q!N{%eBGwip3ITds|PYx(7;Sye>y`p73^j)qFlCgX&7;W9zDJkF^4 z{>T^-XIe*_ww@>dZ8)q6&=x`VP`7mRNAb)|?`Ubsm3apZ%z&N)Zgw)69>;?0b%WTLh62RX+t<)nr+-H)Z=o#*iJzoG(OR}w_hl$sqbrO;6&mURN zQN()l(#VD*o-SXDgyme|*3}iWmuH-JfJc^*Ka}$MRU-Asv?U}0{U>nepjdkZD>xwp zc?vt&b#kq_of!=IW-TWccpfez1DkD_F%l9bh)cH$1EcRXMX9s=j6{Jk^|Pl~QB+7) z^mjp}^SxT=bS?NZJ7Q@#%-Cjse%&%vOsa!tdYY=C^Tg8_JZl#GXPdQ80TY$s2iH)& zYupU#Lif9vp#G8ix#!`vQQ-pWr)?zBcZMN}Wn2q^Y_Nu1``Kfj+N6BD8_I4Q+FUoi z+wjzWlHsK-X5lUu%{|nORF`yOu#S;;&?jALTNhIS4M(cwF4o=ASKL>4VVfS@;N?V6 zHV&v=s5DG~j_%?dp0PYkzfZ=%buJE{jq*D+3xrJ!GsNQxI6VSd4W?F)knb=MIg+n> zJZ<~EZ!@F}!Hz*prTcBoZoO7)rx$%;Gj8w31On(&h~*=!O4b~BGk6swF2ap)f>8%< zW6b&afaNIhba~McW9&lc@EWVO^2~Mrzf{EPb5|c*6YR=Oh?wy?>Gqq!~5=~KW7vzAVghDlSa340Y%}v`dwau<1%>DEG>FYPnX&yLi&81Ou zbBSw`HnoXv73_+V#H;C4+aAvt?DkV1Ikl*Kyvqh%9*Z&k1fPaU5m%fs-Yac?X!Zzh<^&WqqbN^6WD>U)erzV8A^Gnt ziOc7R2%l3(Hz@vI?K3R%TNgre0^HC~Di{IV{E|ZkWDfQDX(Pz}LU7Vp+m{3G5HjyN z8GCaR1{$?(Bhi3b^GFGEYIB+TXQiSZV9mt_ zB3XX`>+>vE0loB)a8#q-nP^mF>OHQEn|E}?Sx#GNjKZ6oUeyJttXuWKuo#f39`iSg zm#MWgJ-2m+5j_4hrMMAo$zPeW3MEPfQTH4}2Rnj=F7~Cy&i@MD*xTJpgk4!)h(DdOC0MN4KA{tCn)nMBA81FwR zhhBQ!?9Id&YNA7$>TSW1?aLvdPs4eIq@;ZSrZYPAhoH4_h#P{E!@iWB5ZHk9e2jXr z?EtuFa}m^nv`BMbe{{Vo!=d%3WjSS9U{rELQC-2S{6rVR9v1p<|1E);O>uu`$w>?_ zoT^8FvL@}5eL8yicGti)m!?vmY&OL@qTM_0qNOURzn78W1hZbMhHJy&u22tVJf@yhJA3tG`9-{1?vAszy}4V(e!OCUT8!2qCkSwidRW z3Cb7N0`V7dTV(K>NV~VD-Gy}0IQ~XWAas-`gch)`^{F;d= z^<}dg{Oj0j4z*^&P@`Cx&a{b;ItqU4B1qcVtgYL*tn!q~RJCZ{L2q&EZ)}E7Ig2a=7~e#0G70>8nP9Q`l@Vf{=6jSa}#iT zubvWxJ@twp6ILslF~a5RniRrCXa?0PUwtoNH(Opp2`cN$?KYJ36EQpD^Y(7BxHTtW zV$F9UJB3qBVn!H##toaxR>*bz&*n8jC8D-x5_$t=%#_+C5*$b-Fd5h zMeUS!jt5D8;#for}#)TVa$0M;HYYp;vcG`aHh=c*A2TWz35l1AmkJV_S=X0NI|p3!$WwexTbVtRnm*yIGE|(ungVyG5=UM8hOe} zJMBD>72{8hVQ$WR`bfzrE#rj3f>5UromFk-c813F{7v+Sq1DjQGx8C3h`+7&FVW=7 zo9yPgZf69nLjGM>6az(WCw+kodkbu=)K+KeD}=L+fcz0tIG~C8AWDz?7|8H93|XFF zY*J^iDJ=kdj%|R%HTx-?uM+v8kku9DTkF%uEkrddtk>Mwa3={Hn>e$6vO!U@u2p<` zU=7vz>m^vp+cp|mM$nKzyhin>Mp;H=IQ}GLtVQR43Qm!b`a0Mvlaf91Rip#0C&Ys4PEJJ(FpraP5!3NW|-}fowO6AS~Q3p zxJQjaWJ9yRm+Hs-hJX;Y-n}O{zegeSO*FHP1x=z8t&Dx;M=H-+591VET8N0qMGK=M z6E6ZRc~}qYG?+U8V0_!D?;m2zI1*Bd`3)O6nGUq~p*Q1I^f8r0;D(Ntky?=+Ry#d^ zO0|yrfDLVi`!bMc^XflKhoTuhC(xLB7hf^n!bltD95#1DetuQ&1chtL^j9shHv;QF z|H+doTEOr^h;ckQ|Z}R)TfWiTIgp9iF*USAec*g-CfU`cRc(g-& zUbg6SJ}pPO7~ogzC*9ovI*@*@b4vn4kmR|=&<;2{1ih)Q6e7<2IFqz@U(6Tp-D@Rt zT`yeY`8L5lnLXvC)0P8fhaDtH4)KoCf(dH$gjxamKgv6B5^CX?n+DE%(fXZBN)308fns!Ll z(do?0#sbeOmCh&N8MBFgr2FmeI}S>I-RDt}@kLxQyUX}dSO(iLrI5SbA^mxIDHxkS zqFOB~%+6tlQ#a{;yi4pStU=^)ZBe4kqe-enJVBy3ib@1oU%!kUPnT)AA^H)qb)ukvhCGAFcSj7ThL)s$;L{GXp&-8*`TknDU1}yEHrLSjsX?xg0>0O-4X`5S*hesWAl(-HIqsc<2y}N z%u2^vSifS*Pj16pZJtGWJ)f>_{?$~S-&nXEs7gneWwd=6H@gz4Q;4uMsYY5CL|ZHG z*RxwXflp>}5D;Q!OH=uvXDIE*58TNtNCc$_f!~_`^Wni|11hEi;ZBs@F5yuHgR9ye zerijXWl#+H$;~Y*@~8V7C&%>-?S2vz3{%yZo>odGsnz>Szob5vs_X?9js)_Z-S128 zTqE$0J=yuJOSjwav2S^KA!}@F*v9$T(7R-5D!mXc@flpAd1IaVpCk$LDnY_Z85TDO zuNN6slj+J4QvpGs>xFR=#B_A7 zY0F@88oC>l$Kr6R!olrU=KC!+O-!MjMdB5!;-NMcTfhZL$o((qavY;mzifTRIdEIp z`1{L_l&8t~Nu?<@KE(W8?BKxQu1aFU0zE-M|9ehg&7p2FrS}5Tl?>jf-3>FTIf`1tEQv{zkl)p0M3<8#GHB)@d?`_bBE_;?F$X@v8aLD1H7JW) zX+2ysBR?{2f=WPd{Bi7y7Pje>1bqGxj>H*Qs^92NMsA4c8}|a1so;K2VUp|Krd>aen2i&z6+bsUUMaNhZL_ygtU+C z|9e~=)5Ei*b{9|`qrn4NHyxdaA@_rp5a)~ zzq`qU{54qZFj}GN$f8qk$Cc%kgXr3CPO(ub;qGbu~% zUU~9VwTM!RLX-w%O<>$AG4f6m^K;fwlm%xs3%`V!jY4sWwIoO{Q@K5RSpb_i&(s;- z5=7FQx=lSKvkKmJu5%Y@Kx%Dy(oN5zRWf0`A&IvNFw?`1Q;HT8JD!f|Gl_|)N8plI zGEtNrJz)%)FGFsUZdGP>e%~W<%rRUiG<`KT`g5ODa~j*$7&sagJXjRq`X?DFiA)!Z z%NF}Qu-F2NDY0YPaFQV(hWy-dz+qa_U)3f+RV7A3?X3K;CHw>vQsS%-q9?xLdy!`J z{No10=oKT-i=Hy;Qb7_*f%O<2J_`PRL*xH6zun&bwzc0~qalPr@)MKQB=X^V( zX|gUVC0><({ue$&LoKwY>@2G8yZp-LM^}_u=BcAUcWQA^I0j+BQP8}`?oaWw5PhtF z;&#j9(?9t&NTLYo?KPVDYzO^OpfUP(>eE-xz%PVXwm&-rv?VV%`Sg0QSN`%FI~Dfb zmY4<~L)WYM?%fvxp!VkN1PWjM>3jHv~VQw;vyVL}K#% zcU=7a9IRX|EHhi#rY|S^aq&uNZy_(#G9l5-e8e%(L)lyU7(Uq_!O8A?vIOE#=TE}o z{m$u7V>qS%h|%+5MMGf^w`DmL2Xe%A_SsFq+`VTMZG!TUfDsG>fAY<}hb6C`L`qkR zfY#)VVnauBo z#U)sgPB)uUI%$y|rPq#lmGaRAasN=t8G4_$%ec2e09kn4`(5i@CdBnXhE}c$>6THe zM${r?u~G}_Tab%9pM)W1dJy?5+1c>oB-4}zdewb#BMG&$(#WWF#OyAE+FQ>ljC`R$ zlOaaKwzQ;c=UNLZIW!#dszuv`nhqOAzwwY_iuhrFNm1`Cvba+TO|*s4fKO6;?7wR@ z3wq8#)G5U#3ZlL<9~=x7w)rI2z%EGRmK39Wi%n;fovp3NO)JcC$`hKwkTNFST#tOC zXwjjTldZ~K^2{Z?o_nn1s5EuFFRAiv^RmJY@k;n-?du4yW8~_JgR?PM;KuC<><7$181bUPa`Q>aDNxy3+i*-?bs`aZ&}2Y#gdj5P?x)<4itQu1~mok>eN;qE!eLs0&COj}+? z?~8@^JH&Ph_oceRgyC9hS-bg*8`8&z4Nx3dmgFd)mGZS{oG8zRPAPrUn6b^9EJPW2 zS7xiKhmqI3eiNXXFI%U>YYYBaj;w~h>u9agYjX17D;~SkWjXrvNe&!p$%}l)-q0QP zHni!d27h$DZM5M-Bn9PS3p}U$E_0DncqL$!WINWf_YKBd%EqWFt797+O*ZCPLht)K z{LM@4ai@sPkLY)nQ5Id`eGN6GQJhg;$I(YO?wyNpS8PQm1fTd+0a^Z$va zPytrK1x6!R_JKpSFLPgrS0z;lgQL;rbqCBbxnvV_xe?==FzPp?>)wlve0l7`1MD7p z0$(E1Q1^uM_0RQRiPQNH)Y%SbkGn0X9|`^8cYW+MQamvD`i7LI-D--FRUCrt@9=jyk;b}_#7_I! zojzVpj%ZJqdrNE`Q<3O?^Zx9&P(tr(kkMNbt&2M>xFmkqR}sYqouVlC@8}bz;KLQ$ ztMiw|-!O)6*Ll{Oj~e3sNv-uRLq*n}6lQ55&Jg0F@CydYK?sggwa;xgX@WVXH_JqwE5 zI)!ua)GHBBaGe#$RoMtUSNZNkS$vg05`nBtYRt{2SuX(~_J72;lYaHwVfuY{pA_!* z5S#Zrh$VT(-GcYcamUtV|6e__C!?uRdPJF@l;l~!4ey!X)zC$z@NIdZJ2@pr_$VxI z*V`*sg>P1TYp{1jk~`<#+!(&9v3Lq?=<6F+tw1YWb7&^Sh_R{31qAh;{nv`yq~ zPAis(1-+B&`UaBt7c%1T{l4=%LvPj^nJB->zF79F!wz;C5;ntc*wGQPw_ZKN8;nIF z!}qtZL4O$sC$zjli}J`DTtk~aw=rFH9KBboG=^PuK^v#AseMUM!xk!XdW#3|*;N0g z9|S(Lgt%kl+V~YyR^J29JEeJ?jo{i|t-hB~UZMU9$QwDlyu=Y4L1<^Bd_PLS=(@dp z8aIeNHoEU=EPQgMam2D%u!g07{C6IRj5ot_`7$J2RpS_@qWK^t)qZlEqx>JtqI3|& zaPT+ZEyvlXdasS=m+teY9XY>E?Z6v0A<}@&EV+NR$QBy75hVc}2I2v<0q3FpGa3&w zcC#Y9xo?v*hJH`?o7cZ3_jt9kzH2Y>glu7m+<#F<<@n7mh}Yy(?FO7xFNkS*fil5W z$0D*U*14%~dQG*_0Xg3%M+~WcbPhLGLrotsq`dFV$l7pjQ=Wb^7aQHbas8Ncm{8#2 z?K+(%t9!phj5GG;Hf`m;3$&t5MWjKp7Qk!56N_?A85cW_%$ND?d~T4YyaPU2BD)?F z0|d%0@ghO(k##U2Dk68sUT>{WD6hY_iSm4AXt3IUF25W+XANe3JUgdN0Z1Mp21ppM z2}KDHvU{1Y)W*EfL9E)Y$8{FjnOO*E1^Jt?&}*J@onvU($VxRO#uv-E6?K z%gpabwU?u?%{Mru?<}@~%5p@Be#N_-BE43iJ{3pY;?ia&1eTZ%aN?#0ONt6X+{-dA z+21!VvS-`bTM>{^!a4EV$$(R7xDXTNOwT_OGU4hvy=dLk$$0tE!UqER6us+_V7!X5 zpl4IWzD@i&I?~76)s5xwb>H)$bYmKpj?8P^@~R zSE5nisS6XMBvi}k{UV$8ul-_5!VhT)buY!cdC;Lwk^Er&9yU&CYgg3owZj>_k-Y+s^fJ z%!4j#EsFsFGigER-FCYj$1@__^4|Ymb}NH}H((Euo^Mmi%O2k00#BzgjxgSWJJXJt h)c*gi%hTR>gto-)VAhPo^iLm4PD)v_M%?(v{{hXjYZd?i literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/ios/Default-Landscape~ipad.png b/apps/files_odfviewer/src/webodf/programs/ios/Default-Landscape~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..06bb96b394f8360815781aada7d1c3704263726b GIT binary patch literal 52135 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/ios/Default-Portrait~ipad.png b/apps/files_odfviewer/src/webodf/programs/ios/Default-Portrait~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..dbfed967af6dbda81c510e41d83cc9abf4ae9626 GIT binary patch literal 51794 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

Cn*^&C zJ(~MDe`9t6pK=oY&@Ww6NjGiVs|v2q&oI^8dxWN+Duc&33Emq6WBaTKJ|!hp1b_La zJ(*`F&-bGn?QvUc)s;sgfp4xbjE>Wnlv=XHTA=Di#Ol>ZZM&hFsjDPe$vpB|PY!WV zFH`Cgs@XdC-Ih^a=Jc$BP$i=W%}Nk0I}&3bq0|uGUu|cdk0Fw z^_Bv_wHeZt`b*4Kv*coQDuO}JNaQm>a35nTSwUJ*t>tc_S`VylT3@^s9b!>+6wpER zlwmSSlPpN{!jjGT4ZTF*S)ZkvZW>Ppkwgq1O!<33n#r%uLIe2z@+?0to0gnf{q(tL zNS?{ED|=QIQmE^hGADCM=jtz+(;4I_yOQhm4wn#IZPA(vx%aBTR^pE~s))LNgZ=9c z`D+v0Tp3{;wky%FG6ufV&n#Z+(gp)13XRh-YsuX^R^PA8I9|7^a+(v9)vY?|GD$~& z8y>s$>U!1aq;_pba6Pt*UmaCHfmv#|fhqK_j4bBu{x8*CNeaq_qbD5cMEc_`;10yQU7o%{YKMGAgQ^s?2mg;2qp68((jO78JO+#%Etny zS4FLLIT(qJ@5F`ny)Rd3n7^C+VuVoGcD`~?-=)SoN+Aa(a|vr}1K;`9;EUbdY9^Kh zz$6LJy813;j{_Z79MR8cm8;c{5XyMfzELs;+IH?$vMuwu&^-A1gMi#N*_x`$n#kS zSg2?%4SB4iK4QWgfC!?~^l$ELDK*T$3G)-KJVB}dy3jJ@Ok|8Ocy3fY&-Q=`S-e?< zo}L*b0Y2CKNUx=es*Xx3R~Z%20 zHUT_J>y8E4*c?-4&O5K}E6q~F-MKm9z*y%Gpqra!a$-_c3xg}e1LuINERf-A>{k@> z38An(h)=^TdyA+?NZx4w`Z|7@ESpz_*&*VU-X|3iC;{oO!z1&ywl9{n^B2R$37@(m zFm`9C0C=J=u@H#p@(B^xQEc?bE(P8Ci`)?0>}T)+*2|!mXK>tNOV?Zy38Oxc{njsJP?m?QXb;c3F&h$-3w@cR`6~6 zt$Cw#Rm?Asa~@k9ugd*Oqm@cY?^|Sa>GbkVa6)S-Ub>TASR5AQ4@%LU2wkfca(6DQ zOpy+x{cga2`b8$mb%vVr#TOFJ+1skW9)Uau$o(I)tq0CMJK%^O*m@{ga6o?nYFZXH z$R^OLzLK*f5;%>hJ$(6fenxmpV>qK(c-u)1Vb{1aJaa*w4?Z1tVtAc<+rP$~UnuDr zCxh^48eb+|6fd#gOlI~U9wlBk75|f?-H{YA1MWPaIQEHrk4aQuYwJ|iD_uUq=+@-6rm!*Z zlUP!YB>o~HEZvF!IquEn3~l~>-ay3ROeVh8`0;5!0#Vjls>nj6!DO7_Sjo4i%4!Oz zbSA@J{w=#!9&Bhq{%x%fe8RoLt1igsrk*C5^e7`ET$Qt4JSEDJjA!hYYZ?b#Q&KUU zNj9AuOP2#%C&ZS2RNuhfa1nejFa!}FPqvZQE}7L?9$lbc3$zARi4`jo$uSf(%tveb zP!w>8j%VFAovY6qHmI!=*Na0K!(qg$!LJ_`?J+t`;W5vEb9d)FvTl2oXeqankVo^#(M^U?nUHeT>Ol7}&BW_;Q2z%AYy;@=SnEFhSe&(m}AoA1x< zQyDD7I#gz2arKzP0iX=*UWu9rIQpGmic2g^1DCf%{68~j_?x7NsW&fk6+9=InYyuUOo5=SQ(%$M6cBDJXeEm@7p2D} zH+#!=W=^XD;w@H7c;NZai1+pnTOYW?I37`q4PxNZ7kLX^{v{^v($<;15D0C}nR_L| zU;)BdL8zZniqIEVTS=7#S&N^Cf(XaqQSJt~b=xE{ z8cQMKui*=8zCCs+zVieq(JiHaVwasOzDG}>B9zJ%=9_LwmM<#%5d6mv?=wlv{i@P_ z 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 + +#ifdef PHONEGAP_FRAMEWORK + #import +#else + #import "PGViewController.h" +#endif + + +@interface AppDelegate : NSObject < UIApplicationDelegate, UIWebViewDelegate, PGCommandDelegate > { + + NSString* invokeString; +} + +// invoke string is passed to your app on launch, this is only valid if you +// edit FooBar.plist to add a protocol +// a simple tutorial can be found here : +// http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html + +@property (nonatomic, copy) NSString* invokeString; +@property (nonatomic, retain) IBOutlet UIWindow* window; +@property (nonatomic, retain) IBOutlet PGViewController* viewController; + +@end + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/AppDelegate.m b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/AppDelegate.m new file mode 100644 index 0000000000..6845e95349 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/AppDelegate.m @@ -0,0 +1,202 @@ +/* + 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. + */ + +// +// AppDelegate.m +// WebODF +// +// Created by KO GmbH on 2/2/12. +// Copyright __MyCompanyName__ 2012. All rights reserved. +// + +#import "AppDelegate.h" +#import "MainViewController.h" + +#ifdef PHONEGAP_FRAMEWORK + #import + #import +#else + #import "PGPlugin.h" + #import "PGURLProtocol.h" +#endif +#import "WebViewCache.h" + + +@implementation AppDelegate + +@synthesize invokeString, window, viewController; + +- (id) init +{ + /** If you need to do any extra app-specific initialization, you can do it here + * -jm + **/ + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; + + [PGURLProtocol registerPGHttpURLProtocol]; + + return [super init]; +} + +#pragma UIApplicationDelegate implementation + +/** + * This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up) + */ +- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions +{ + NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey]; + if (url && [url isKindOfClass:[NSURL class]]) { + self.invokeString = [url absoluteString]; + NSLog(@"WebODF launchOptions = %@", url); + } + + CGRect screenBounds = [[UIScreen mainScreen] bounds]; + self.window = [[UIWindow alloc] initWithFrame:screenBounds]; + self.window.autoresizesSubviews = YES; + + CGRect viewBounds = [[UIScreen mainScreen] applicationFrame]; + + self.viewController = [[MainViewController alloc] init]; + self.viewController.useSplashScreen = YES; + self.viewController.wwwFolderName = @"www"; + self.viewController.startPage = @"index.html"; + self.viewController.view.frame = viewBounds; + + // over-ride delegates + self.viewController.webView.delegate = self; + self.viewController.commandDelegate = self; + + // check whether the current orientation is supported: if it is, keep it, rather than forcing a rotation + BOOL forceStartupRotation = YES; + UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation]; + + if (UIDeviceOrientationUnknown == curDevOrientation) { + // UIDevice isn't firing orientation notifications yet… go look at the status bar + curDevOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation]; + } + + if (UIDeviceOrientationIsValidInterfaceOrientation(curDevOrientation)) { + for (NSNumber *orient in self.viewController.supportedOrientations) { + if ([orient intValue] == curDevOrientation) { + forceStartupRotation = NO; + break; + } + } + } + + if (forceStartupRotation) { + NSLog(@"supportedOrientations: %@", self.viewController.supportedOrientations); + // The first item in the supportedOrientations array is the start orientation (guaranteed to be at least Portrait) + UIInterfaceOrientation newOrient = [[self.viewController.supportedOrientations objectAtIndex:0] intValue]; + NSLog(@"AppDelegate forcing status bar to: %d from: %d", newOrient, curDevOrientation); + [[UIApplication sharedApplication] setStatusBarOrientation:newOrient]; + } + + [self.window addSubview:self.viewController.view]; + [self.window makeKeyAndVisible]; + + + NSString *path = @"./cache"; + NSUInteger discCapacity = 1*1024*1024; + NSUInteger memoryCapacity = 0*1024*1024; + + WebViewCache *cache = + [[WebViewCache alloc] initWithMemoryCapacity: memoryCapacity + diskCapacity: discCapacity diskPath:path]; + [NSURLCache setSharedURLCache:cache]; + + + return YES; +} + +// this happens while we are running ( in the background, or from within our own app ) +// only valid if FooBar.plist specifies a protocol to handle +- (BOOL) application:(UIApplication*)application handleOpenURL:(NSURL*)url +{ + if (!url) { + return NO; + } + + // calls into javascript global function 'handleOpenURL' + NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", url]; + [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString]; + + // all plugins will get the notification, and their handlers will be called + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:PGPluginHandleOpenURLNotification object:url]]; + + return YES; +} + +#pragma PGCommandDelegate implementation + +- (id) getCommandInstance:(NSString*)className +{ + return [self.viewController getCommandInstance:className]; +} + +- (BOOL) execute:(InvokedUrlCommand*)command +{ + return [self.viewController execute:command]; +} + +- (NSString*) pathForResource:(NSString*)resourcepath; +{ + return [self.viewController pathForResource:resourcepath]; +} + +#pragma UIWebDelegate implementation + +- (void) webViewDidFinishLoad:(UIWebView*) theWebView +{ + // only valid if FooBar.plist specifies a protocol to handle + if (self.invokeString) + { + // this is passed before the deviceready event is fired, so you can access it in js when you receive deviceready + NSString* jsString = [NSString stringWithFormat:@"var invokeString = \"%@\";", self.invokeString]; + [theWebView stringByEvaluatingJavaScriptFromString:jsString]; + } + + // Black base color for background matches the native apps + theWebView.backgroundColor = [UIColor blackColor]; + + return [self.viewController webViewDidFinishLoad:theWebView]; +} + +- (void) webViewDidStartLoad:(UIWebView*)theWebView +{ + return [self.viewController webViewDidStartLoad:theWebView]; +} + +- (void) webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error +{ + return [self.viewController webView:theWebView didFailLoadWithError:error]; +} + +- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType +{ + return [self.viewController webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType]; +} + +- (void) dealloc +{ +} + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.h new file mode 100644 index 0000000000..33ddbc2103 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.h @@ -0,0 +1,17 @@ +// +// MainViewController.h +// FooBar +// +// Created by Shazron Abdullah on 12-01-26. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#ifdef PHONEGAP_FRAMEWORK + #import +#else + #import "PGViewController.h" +#endif + +@interface MainViewController : PGViewController + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.m b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.m new file mode 100644 index 0000000000..550e4b25c2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.m @@ -0,0 +1,47 @@ +// +// MainViewController.m +// WebODF +// +#import "MainViewController.h" + +@implementation MainViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view from its nib. +} + +- (void)viewDidUnload +{ + [super viewDidUnload]; + // Release any retained subviews of the main view. + // e.g. self.myOutlet = nil; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + // Return YES for supported orientations + return (interfaceOrientation == UIInterfaceOrientationPortrait); +} + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.xib b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.xib new file mode 100644 index 0000000000..9837f578ca --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/MainViewController.xib @@ -0,0 +1,118 @@ + + + + 1280 + 11C25 + 1919 + 1138.11 + 566.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 916 + + + IBProxyObject + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + {{0, 20}, {320, 460}} + + + + 3 + MQA + + 2 + + + + IBCocoaTouchFramework + + + + + + + view + + + + 3 + + + + + + 0 + + + + + + 1 + + + + + -1 + + + File's Owner + + + -2 + + + + + + + MainViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 3 + + + + + MainViewController + UIViewController + + IBProjectSource + ./Classes/MainViewController.h + + + + + 0 + IBCocoaTouchFramework + YES + 3 + 916 + + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.h new file mode 100644 index 0000000000..eb1ff485a7 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.h @@ -0,0 +1,33 @@ +// +// NSData+Base64.h +// base64 +// +// Created by Matt Gallagher on 2009/06/03. +// Copyright 2009 Matt Gallagher. All rights reserved. +// +// Permission is given to use this source code file, free of charge, in any +// project, commercial or otherwise, entirely at your risk, with the condition +// that any redistribution (in part or whole) of source code must retain +// this copyright and permission notice. Attribution in compiled projects is +// appreciated but not required. +// + +#import + +void *NewBase64Decode( + const char *inputBuffer, + size_t length, + size_t *outputLength); + +char *NewBase64Encode( + const void *inputBuffer, + size_t length, + bool separateLines, + size_t *outputLength); + +@interface NSData (Base64) + ++ (NSData *)dataFromBase64String:(NSString *)aString; +- (NSString *)base64EncodedString; + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.m b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.m new file mode 100644 index 0000000000..13f828d09c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NSData+Base64.m @@ -0,0 +1,299 @@ +// +// NSData+Base64.m +// base64 +// +// Created by Matt Gallagher on 2009/06/03. +// Copyright 2009 Matt Gallagher. All rights reserved. +// +// Permission is given to use this source code file, free of charge, in any +// project, commercial or otherwise, entirely at your risk, with the condition +// that any redistribution (in part or whole) of source code must retain +// this copyright and permission notice. Attribution in compiled projects is +// appreciated but not required. +// + +#import "NSData+Base64.h" + +// +// Mapping from 6 bit pattern to ASCII character. +// +static unsigned char base64EncodeLookup[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +// +// Definition for "masked-out" areas of the base64DecodeLookup mapping +// +#define xx 65 + +// +// Mapping from ASCII character to 6 bit pattern. +// +static unsigned char base64DecodeLookup[256] = +{ + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, + xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, + xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, +}; + +// +// Fundamental sizes of the binary and base64 encode/decode units in bytes +// +#define BINARY_UNIT_SIZE 3 +#define BASE64_UNIT_SIZE 4 + +// +// NewBase64Decode +// +// Decodes the base64 ASCII string in the inputBuffer to a newly malloced +// output buffer. +// +// inputBuffer - the source ASCII string for the decode +// length - the length of the string or -1 (to specify strlen should be used) +// outputLength - if not-NULL, on output will contain the decoded length +// +// returns the decoded buffer. Must be free'd by caller. Length is given by +// outputLength. +// +void *NewBase64Decode( + const char *inputBuffer, + size_t length, + size_t *outputLength) +{ + if (length == -1) + { + length = strlen(inputBuffer); + } + + size_t outputBufferSize = (length / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE; + unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize); + + size_t i = 0; + size_t j = 0; + while (i < length) + { + // + // Accumulate 4 valid characters (ignore everything else) + // + unsigned char accumulated[BASE64_UNIT_SIZE]; + bzero(accumulated, sizeof(unsigned char) * BASE64_UNIT_SIZE); + size_t accumulateIndex = 0; + while (i < length) + { + unsigned char decode = base64DecodeLookup[inputBuffer[i++]]; + if (decode != xx) + { + accumulated[accumulateIndex] = decode; + accumulateIndex++; + + if (accumulateIndex == BASE64_UNIT_SIZE) + { + break; + } + } + } + + // + // Store the 6 bits from each of the 4 characters as 3 bytes + // + outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4); + outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2); + outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3]; + j += accumulateIndex - 1; + } + + if (outputLength) + { + *outputLength = j; + } + return outputBuffer; +} + +// +// NewBase64Decode +// +// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced +// output buffer. +// +// inputBuffer - the source data for the encode +// length - the length of the input in bytes +// separateLines - if zero, no CR/LF characters will be added. Otherwise +// a CR/LF pair will be added every 64 encoded chars. +// outputLength - if not-NULL, on output will contain the encoded length +// (not including terminating 0 char) +// +// returns the encoded buffer. Must be free'd by caller. Length is given by +// outputLength. +// +char *NewBase64Encode( + const void *buffer, + size_t length, + bool separateLines, + size_t *outputLength) +{ + const unsigned char *inputBuffer = (const unsigned char *)buffer; + + #define MAX_NUM_PADDING_CHARS 2 + #define OUTPUT_LINE_LENGTH 64 + #define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE) + #define CR_LF_SIZE 0 + + // + // Byte accurate calculation of final buffer size + // + size_t outputBufferSize = + ((length / BINARY_UNIT_SIZE) + + ((length % BINARY_UNIT_SIZE) ? 1 : 0)) + * BASE64_UNIT_SIZE; + if (separateLines) + { + outputBufferSize += + (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE; + } + + // + // Include space for a terminating zero + // + outputBufferSize += 1; + + // + // Allocate the output buffer + // + char *outputBuffer = (char *)malloc(outputBufferSize); + if (!outputBuffer) + { + return NULL; + } + + size_t i = 0; + size_t j = 0; + const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length; + size_t lineEnd = lineLength; + + while (true) + { + if (lineEnd > length) + { + lineEnd = length; + } + + for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE) + { + // + // Inner loop: turn 48 bytes into 64 base64 characters + // + outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; + outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) + | ((inputBuffer[i + 1] & 0xF0) >> 4)]; + outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) + | ((inputBuffer[i + 2] & 0xC0) >> 6)]; + outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F]; + } + + if (lineEnd == length) + { + break; + } + + // + // Add the newline + // + //outputBuffer[j++] = '\r'; + //outputBuffer[j++] = '\n'; + lineEnd += lineLength; + } + + if (i + 1 < length) + { + // + // Handle the single '=' case + // + outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; + outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) + | ((inputBuffer[i + 1] & 0xF0) >> 4)]; + outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]; + outputBuffer[j++] = '='; + } + else if (i < length) + { + // + // Handle the double '=' case + // + outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; + outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]; + outputBuffer[j++] = '='; + outputBuffer[j++] = '='; + } + outputBuffer[j] = 0; + + // + // Set the output length and return the buffer + // + if (outputLength) + { + *outputLength = j; + } + return outputBuffer; +} + +@implementation NSData (Base64) + +// +// dataFromBase64String: +// +// Creates an NSData object containing the base64 decoded representation of +// the base64 string 'aString' +// +// Parameters: +// aString - the base64 string to decode +// +// returns the autoreleased NSData representation of the base64 string +// ++ (NSData *)dataFromBase64String:(NSString *)aString +{ + NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding]; + size_t outputLength; + void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength); + NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength]; + free(outputBuffer); + return result; +} + +// +// base64EncodedString +// +// Creates an NSString object that contains the base 64 encoding of the +// receiver's data. Lines are broken at 64 characters long. +// +// returns an autoreleased NSString being the base 64 representation of the +// receiver. +// +- (NSString *)base64EncodedString +{ + size_t outputLength; + char *outputBuffer = + NewBase64Encode([self bytes], [self length], true, &outputLength); + + NSString *result = + [[[NSString alloc] + initWithBytes:outputBuffer + length:outputLength + encoding:NSASCIIStringEncoding] + autorelease]; + free(outputBuffer); + return result; +} + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.h new file mode 100644 index 0000000000..44e296b8cf --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.h @@ -0,0 +1,13 @@ +#import + +@interface NativeZip : PGPlugin { + NSString* callbackID; +} + +@property (nonatomic, copy) NSString* callbackID; + +- (void) load:(BOOL)base64 arguments:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options; +- (void) loadAsString:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options; +- (void) loadAsDataURL:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options; + +@end \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.m b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.m new file mode 100644 index 0000000000..d8c241cf0b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/NativeZip.m @@ -0,0 +1,79 @@ +#import "NativeZip.h" +#import "minizip/unzip.h" +#import "NSData+Base64.h" + +@implementation NativeZip +@synthesize callbackID; + +-(void) load:(BOOL)base64 arguments:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options +{ + self.callbackID = [arguments objectAtIndex:0]; + NSString *zipPath = [arguments objectAtIndex:1]; + NSString *entryPath = [arguments objectAtIndex:2]; + NSString *mimetype = nil; + if (base64 == TRUE) { + mimetype = [arguments objectAtIndex:3]; + } + + const char* path = [ zipPath cStringUsingEncoding:NSUTF8StringEncoding ]; + unzFile unzipFile = unzOpen(path); + NSString* jsString = nil; + BOOL error = TRUE; + if (!unzipFile) { + jsString = [[NSString alloc] initWithString: @"cannot open file"]; + } else { + path = [ entryPath cStringUsingEncoding:NSUTF8StringEncoding ]; + int r = unzLocateFile(unzipFile, path, 2); + if (r != UNZ_OK) { + jsString = [[NSString alloc] initWithString: @"cannot find entry"]; + } else { + unz_file_info info; + r = unzGetCurrentFileInfo(unzipFile, &info, 0, 0, 0, 0, 0, 0); + if (r != UNZ_OK) { + jsString = [[NSString alloc] initWithString: @"cannot determine size"]; + } else { + r = unzOpenCurrentFile(unzipFile); + if (r != UNZ_OK) { + jsString = [[NSString alloc] initWithString: @"cannot open entry"]; + } else { + char* contents = malloc(info.uncompressed_size); + r = unzReadCurrentFile(unzipFile, contents, info.uncompressed_size); + if (r != info.uncompressed_size) { + jsString = [[NSString alloc] initWithString: @"cannot uncompress file"]; + } else { + if (base64) { + NSData* readData = [NSData dataWithBytes:(const void *)contents length:sizeof(unsigned char)*info.uncompressed_size]; + jsString = [NSString stringWithFormat:@"data:%@;base64,%@", mimetype, [readData base64EncodedString]]; + } else { + jsString = [[NSString alloc] initWithUTF8String: contents]; + } + } + unzCloseCurrentFile(unzipFile); + free(contents); + error = FALSE; + } + } + } + unzClose(unzipFile); + } + PluginResult* pluginResult = [PluginResult + resultWithStatus:PGCommandStatus_OK + messageAsString: jsString + ]; + if (!error) { + [self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]]; + } else { + [self writeJavascript: [pluginResult toErrorCallbackString:self.callbackID]]; + } +} + +-(void)loadAsString:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options +{ + [self load:FALSE arguments:arguments withDict:options]; +} +-(void)loadAsDataURL:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options +{ + [self load:TRUE arguments:arguments withDict:options]; +} + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.h new file mode 100644 index 0000000000..216a0bf2bb --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.h @@ -0,0 +1,15 @@ +// +// WebCache.h +// KO Viewer +// +// Created by Tobias Hintze on 3/5/12. +// Copyright (c) 2012 KO GmbH. All rights reserved. +// + +#import + +@interface WebViewCache : NSURLCache + +- (NSData*)getSomeData:(NSString*)zip entry:(NSString*)entry; + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.m b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.m new file mode 100644 index 0000000000..4de0bb3a0c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/WebViewCache.m @@ -0,0 +1,72 @@ +// +// WebCache.m +// KO Viewer +// +// Created by Tobias Hintze on 3/5/12. +// Copyright (c) 2012 KO GmbH. All rights reserved. +// + +#import "WebViewCache.h" +#import "minizip/unzip.h" + +@implementation WebViewCache + +- (NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request +{ + [super removeAllCachedResponses]; + NSURL *url = [request URL]; + if ([url query]) { + NSData *somedata = [self getSomeData:[url path] entry:[url query]]; + NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url + MIMEType:@"text/xml" + expectedContentLength:[somedata length] + textEncodingName:nil]; + NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] + initWithResponse:response data:somedata]; + return cachedResponse; + } + return [super cachedResponseForRequest:request]; +} + +- (NSData*)getSomeData:(NSString*)zip entry:(NSString*)entry +{ + NSLog(@"get some data: %@ %@", zip, entry); + const char* path = [ zip cStringUsingEncoding:NSUTF8StringEncoding ]; + unzFile unzipFile = unzOpen(path); + NSData *data = nil; + if (!unzipFile) { + NSLog(@"cannot open file %@", zip); + } else { + path = [ entry cStringUsingEncoding:NSUTF8StringEncoding ]; + int r = unzLocateFile(unzipFile, path, 2); + if (r != UNZ_OK) { + NSLog(@"cannot find entry %@", entry); + } else { + unz_file_info info; + r = unzGetCurrentFileInfo(unzipFile, &info, 0, 0, 0, 0, 0, 0); + if (r != UNZ_OK) { + NSLog(@"cannot determine size of %@", entry); + } else { + r = unzOpenCurrentFile(unzipFile); + if (r != UNZ_OK) { + NSLog(@"cannot open entry %@", entry); + } else { + char* contents = malloc(info.uncompressed_size); + r = unzReadCurrentFile(unzipFile, contents, info.uncompressed_size); + if (r != info.uncompressed_size) { + NSLog(@"cannot uncompress file %@", entry); + } else { + data = [NSData dataWithBytes:(const void *)contents length:sizeof(unsigned char)*info.uncompressed_size]; + NSLog(@"read file entry %li %@", info.uncompressed_size, entry); + } + unzCloseCurrentFile(unzipFile); + free(contents); + } + } + } + unzClose(unzipFile); + } + return data; +} + +@end diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/crypt.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/crypt.h new file mode 100644 index 0000000000..622f4bc2ec --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/crypt.h @@ -0,0 +1,132 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.c b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.c new file mode 100644 index 0000000000..7f20c182f9 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.c @@ -0,0 +1,177 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +#include "zlib.h" +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_file_func OF(( + voidpf opaque, + voidpf stream)); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.h new file mode 100644 index 0000000000..e73a3b2bd8 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.c b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.c new file mode 100644 index 0000000000..74e6c75778 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.c @@ -0,0 +1,28 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.h new file mode 100644 index 0000000000..82d1597ad7 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/mztools.h @@ -0,0 +1,31 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.c b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.c new file mode 100644 index 0000000000..81aee6a149 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.c @@ -0,0 +1,1597 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.h new file mode 100644 index 0000000000..c3206a0589 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/minizip/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/zip.h b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/zip.h new file mode 100644 index 0000000000..a4f0716054 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Classes/zip.h @@ -0,0 +1,15 @@ +// +// Header.h +// WebODF +// +// Created by KO GmbH on 3/1/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#ifndef WebODF_Header_h +#define WebODF_Header_h + +void readZipEntry(const char* zippath, const char* entrypath) {} + + +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/PhoneGap.plist b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/PhoneGap.plist new file mode 100644 index 0000000000..29011e6d11 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/PhoneGap.plist @@ -0,0 +1,57 @@ + + + + + TopActivityIndicator + gray + EnableLocation + + EnableViewportScale + + AutoHideSplashScreen + + ShowSplashScreenSpinner + + MediaPlaybackRequiresUserAction + + AllowInlineMediaPlayback + + OpenAllWhitelistURLsInWebView + + ExternalHosts + + zipserver + + Plugins + + ZipClass + NativeZip + com.phonegap.accelerometer + PGAccelerometer + com.phonegap.camera + PGCamera + com.phonegap.connection + PGConnection + com.phonegap.contacts + PGContacts + com.phonegap.debugconsole + PGDebugConsole + com.phonegap.file + PGFile + com.phonegap.filetransfer + PGFileTransfer + com.phonegap.geolocation + PGLocation + com.phonegap.notification + PGNotification + com.phonegap.media + PGSound + com.phonegap.mediacapture + PGCapture + com.phonegap.splashscreen + PGSplashScreen + com.phonegap.battery + PGBattery + + + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/en.lproj/Localizable.strings b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/en.lproj/Localizable.strings new file mode 100644 index 0000000000..8972684435 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/en.lproj/Localizable.strings @@ -0,0 +1,25 @@ +/* + 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. + */ + +// accessibility label for recording button +"toggle audio recording" = "toggle audio recording"; +// notification spoken by VoiceOver when timed recording finishes +"timed recording complete" = "timed recording complete"; +// accessibility hint for display of recorded elapsed time +"recorded time in minutes and seconds" = "recorded time in minutes and seconds"; \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon-72.png b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon-72.png new file mode 100644 index 0000000000000000000000000000000000000000..1aebf5d34b638026e1c7caa63e5821e372a00c45 GIT binary patch literal 8844 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon@2x.png b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/icons/icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b7ccb848e3949b55361f2fb30dfe3a39756aa387 GIT binary patch literal 19269 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default-Landscape~ipad.png b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default-Landscape~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..06bb96b394f8360815781aada7d1c3704263726b GIT binary patch literal 52135 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default-Portrait~ipad.png b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/Resources/splash/Default-Portrait~ipad.png new file mode 100644 index 0000000000000000000000000000000000000000..dbfed967af6dbda81c510e41d83cc9abf4ae9626 GIT binary patch literal 51794 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",'
{message}
'].join(""),loadMoreCmp:{xtype:"component",baseCls:Ext.baseCSSPrefix+"list-paging"},loadMoreCmpAdded:false,loadingCls:Ext.baseCSSPrefix+"loading",list:null,scroller:null,loading:false},init:function(c){var a=c.getScrollable().getScroller(),b=c.getStore();this.setList(c);this.setScroller(a);this.bindStore(c.getStore());if(b){this.disableDataViewMask(b)}c.updateStore=Ext.Function.createInterceptor(c.updateStore,this.bindStore,this);if(this.getAutoPaging()){a.on({scrollend:this.onScrollEnd,scope:this})}},bindStore:function(a,b){if(b){b.un({load:this.onStoreLoad,beforeload:this.onStoreBeforeLoad,scope:this})}if(a){a.on({load:this.onStoreLoad,beforeload:this.onStoreBeforeLoad,scope:this})}},disableDataViewMask:function(a){var b=this.getList();if(a.isAutoLoading()){b.setLoadingText(null)}else{a.on({load:{single:true,fn:function(){b.setLoadingText(null)}}})}},applyLoadTpl:function(a){return(Ext.isObject(a)&&a.isTemplate)?a:new Ext.XTemplate(a)},applyLoadMoreCmp:function(a){a=Ext.merge(a,{html:this.getLoadTpl().apply({cssPrefix:Ext.baseCSSPrefix,message:this.getLoadMoreText()}),listeners:{tap:{fn:this.loadNextPage,scope:this,element:"element"}}});return Ext.factory(a,Ext.Component,this.getLoadMoreCmp())},onScrollEnd:function(b,a,c){if(!this.getLoading()&&c>=b.maxPosition.y){if(!this.storeFullyLoaded()){this.loadNextPage()}}},updateLoading:function(a){var b=this.getLoadMoreCmp(),c=this.getLoadingCls();if(a){b.addCls(c)}else{b.removeCls(c)}},onStoreBeforeLoad:function(a){if(a.getCount()===0){this.getLoadMoreCmp().hide()}},onStoreLoad:function(a){var d=this.addLoadMoreCmp(),b=this.getLoadTpl(),c=this.storeFullyLoaded()?this.getNoMoreRecordsText():this.getLoadMoreText();this.getLoadMoreCmp().show();this.setLoading(false);if(this.scrollY){this.getScroller().scrollTo(null,this.scrollY);delete this.scrollY}d.setHtml(b.apply({cssPrefix:Ext.baseCSSPrefix,message:c}))},addLoadMoreCmp:function(){var b=this.getList(),a=this.getLoadMoreCmp();if(!this.getLoadMoreCmpAdded()){b.add(a);this.setLoadMoreCmpAdded(true)}return a},storeFullyLoaded:function(){var a=this.getList().getStore(),b=a.getTotalCount();return b!==null?a.getTotalCount()<=(a.currentPage*a.getPageSize()):false},loadNextPage:function(){var a=this.getList().getStore();this.setLoading(true);this.scrollY=this.getScroller().position.y;a.nextPage({addRecords:true})}});Ext.define("Ext.plugin.PullRefresh",{extend:"Ext.Component",alias:"plugin.pullrefresh",requires:["Ext.DateExtras"],config:{list:null,pullRefreshText:"Pull down to refresh...",releaseRefreshText:"Release to refresh...",loadingText:"Loading...",snappingAnimationDuration:150,refreshFn:null,pullTpl:['
','
','
','','','','',"
",'
','

{message}

','
Last Updated: {lastUpdated:date("m/d/Y h:iA")}
',"
","
"].join("")},isRefreshing:false,currentViewState:"",initialize:function(){this.callParent();this.on({painted:"onPainted",scope:this})},init:function(f){var d=this,b=f.getStore(),e=d.getPullTpl(),c=d.element,a=f.getScrollable().getScroller();d.setList(f);d.lastUpdated=new Date();f.insert(0,d);if(b){if(b.isAutoLoading()){f.setLoadingText(null)}else{b.on({load:{single:true,fn:function(){f.setLoadingText(null)}}})}}e.overwrite(c,{message:d.getPullRefreshText(),lastUpdated:d.lastUpdated},true);d.loadingElement=c.getFirstChild();d.messageEl=c.down(".x-list-pullrefresh-message");d.updatedEl=c.down(".x-list-pullrefresh-updated > span");d.maxScroller=a.getMaxPosition();a.on({maxpositionchange:d.setMaxScroller,scroll:d.onScrollChange,scope:d})},fetchLatest:function(){var b=this.getList().getStore(),c=b.getProxy(),a;a=Ext.create("Ext.data.Operation",{page:1,start:0,model:b.getModel(),limit:b.getPageSize(),action:"read",filters:b.getRemoteFilter()?b.getFilters():[]});c.read(a,this.onLatestFetched,this)},onLatestFetched:function(d){var j=this.getList().getStore(),b=j.getData(),c=d.getRecords(),a=c.length,g=[],h,f,e;for(e=0;ethis.maxScroller.y){this.onBounceBottom(c)}},applyPullTpl:function(a){return(Ext.isObject(a)&&a.isTemplate)?a:new Ext.XTemplate(a)},onBounceTop:function(d){var b=this,c=b.getList(),a=c.getScrollable().getScroller();if(!b.isReleased){if(!b.isRefreshing&&-d>=b.pullHeight+10){b.isRefreshing=true;b.setViewState("release");a.getContainer().onBefore({dragend:"onScrollerDragEnd",single:true,scope:b})}else{if(b.isRefreshing&&-d=1){a=Math.round((f-1)*b);e=this.applyLength(d-a);a=d-e;this.updateLength(e);g=c+a}else{g=c*f}}this.setOffset(g)},setOffset:function(c){var a=this.getAxis(),b=this.element.dom.style;c=Math.round(c);if(a==="x"){b.webkitTransform="translate3d("+c+"px, 0, 0)"}else{b.webkitTransform="translate3d(0, "+c+"px, 0)"}}});Ext.define("Ext.scroll.indicator.Default",{extend:"Ext.scroll.indicator.Abstract",config:{cls:"default"},setOffset:function(c){var b=this.getAxis(),a=this.element.dom.style;if(b==="x"){a.webkitTransform="translate3d("+c+"px, 0, 0)"}else{a.webkitTransform="translate3d(0, "+c+"px, 0)"}},applyLength:function(a){return Math.round(Math.max(0,a))},updateValue:function(f){var b=this.barLength,c=this.gapLength,d=this.getLength(),e,g,a;if(f<=0){g=0;this.updateLength(this.applyLength(d+f*b))}else{if(f>=1){a=Math.round((f-1)*b);e=this.applyLength(d-a);a=d-e;this.updateLength(e);g=c+a}else{g=c*f}}this.setOffset(g)}});Ext.define("Ext.scroll.indicator.ScrollPosition",{extend:"Ext.scroll.indicator.Abstract",config:{cls:"scrollposition"},getElementConfig:function(){var a=this.callParent(arguments);a.children.unshift({className:"x-scroll-bar-stretcher"});return a},updateValue:function(a){if(this.gapLength===0){if(a>1){a=a-1}this.setOffset(this.barLength*a)}else{this.setOffset(this.gapLength*a)}},setLength:function(e){var c=this.getAxis(),a=this.barLength,d=this.barElement.dom,b=this.element;this.callParent(arguments);if(c==="x"){d.scrollLeft=a;b.setLeft(a)}else{d.scrollTop=a;b.setTop(a)}},setOffset:function(d){var b=this.getAxis(),a=this.barLength,c=this.barElement.dom;d=a-d;if(b==="x"){c.scrollLeft=d}else{c.scrollTop=d}}});Ext.define("Ext.scroll.Indicator",{requires:["Ext.scroll.indicator.Default","Ext.scroll.indicator.ScrollPosition","Ext.scroll.indicator.CssTransform"],alternateClassName:"Ext.util.Indicator",constructor:function(a){if(Ext.os.is.Android2||Ext.browser.is.ChromeMobile){return new Ext.scroll.indicator.ScrollPosition(a)}else{if(Ext.os.is.iOS){return new Ext.scroll.indicator.CssTransform(a)}else{return new Ext.scroll.indicator.Default(a)}}}});Ext.define("Ext.scroll.View",{extend:"Ext.Evented",alternateClassName:"Ext.util.ScrollView",requires:["Ext.scroll.Scroller","Ext.scroll.Indicator"],config:{indicatorsUi:"dark",element:null,scroller:{},indicators:{x:{axis:"x"},y:{axis:"y"}},indicatorsHidingDelay:100,cls:Ext.baseCSSPrefix+"scroll-view"},processConfig:function(c){if(!c){return null}if(typeof c=="string"){c={direction:c}}c=Ext.merge({},c);var a=c.scroller,b;if(!a){c.scroller=a={}}for(b in c){if(c.hasOwnProperty(b)){if(!this.hasConfig(b)){a[b]=c[b];delete c[b]}}}return c},constructor:function(a){a=this.processConfig(a);this.useIndicators={x:true,y:true};this.doHideIndicators=Ext.Function.bind(this.doHideIndicators,this);this.initConfig(a)},setConfig:function(a){return this.callParent([this.processConfig(a)])},updateIndicatorsUi:function(a){var b=this.getIndicators();b.x.setUi(a);b.y.setUi(a)},applyScroller:function(a,b){return Ext.factory(a,Ext.scroll.Scroller,b)},applyIndicators:function(b,d){var a=Ext.scroll.Indicator,c=this.useIndicators;if(!b){b={}}if(!b.x){c.x=false;b.x={}}if(!b.y){c.y=false;b.y={}}return{x:Ext.factory(b.x,a,d&&d.x),y:Ext.factory(b.y,a,d&&d.y)}},updateIndicators:function(a){this.indicatorsGrid=Ext.Element.create({className:"x-scroll-bar-grid-wrapper",children:[{className:"x-scroll-bar-grid",children:[{children:[{},{children:[a.y.barElement]}]},{children:[{children:[a.x.barElement]},{}]}]}]})},updateScroller:function(a){a.on({scope:this,scrollstart:"onScrollStart",scroll:"onScroll",scrollend:"onScrollEnd",refresh:"refreshIndicators"})},isAxisEnabled:function(a){return this.getScroller().isAxisEnabled(a)&&this.useIndicators[a]},applyElement:function(a){if(a){return Ext.get(a)}},updateElement:function(c){var b=c.getFirstChild().getFirstChild(),a=this.getScroller();c.addCls(this.getCls());c.insertFirst(this.indicatorsGrid);a.setElement(b);this.refreshIndicators();return this},showIndicators:function(){var a=this.getIndicators();if(this.hasOwnProperty("indicatorsHidingTimer")){clearTimeout(this.indicatorsHidingTimer);delete this.indicatorsHidingTimer}if(this.isAxisEnabled("x")){a.x.show()}if(this.isAxisEnabled("y")){a.y.show()}},hideIndicators:function(){var a=this.getIndicatorsHidingDelay();if(a>0){this.indicatorsHidingTimer=setTimeout(this.doHideIndicators,a)}else{this.doHideIndicators()}},doHideIndicators:function(){var a=this.getIndicators();if(this.isAxisEnabled("x")){a.x.hide()}if(this.isAxisEnabled("y")){a.y.hide()}},onScrollStart:function(){this.onScroll.apply(this,arguments);this.showIndicators()},onScrollEnd:function(){this.hideIndicators()},onScroll:function(b,a,c){this.setIndicatorValue("x",a);this.setIndicatorValue("y",c)},setIndicatorValue:function(b,f){if(!this.isAxisEnabled(b)){return this}var a=this.getScroller(),c=a.getMaxPosition()[b],e=a.getContainerSize()[b],d;if(c===0){d=f/e;if(f>=0){d+=1}}else{if(f>c){d=1+((f-c)/e)}else{if(f<0){d=f/e}else{d=f/c}}}this.getIndicators()[b].setValue(d)},refreshIndicator:function(d){if(!this.isAxisEnabled(d)){return this}var a=this.getScroller(),b=this.getIndicators()[d],e=a.getContainerSize()[d],f=a.getSize()[d],c=e/f;b.setRatio(c);b.refresh()},refresh:function(){return this.getScroller().refresh()},refreshIndicators:function(){var a=this.getIndicators();a.x.setActive(this.isAxisEnabled("x"));a.y.setActive(this.isAxisEnabled("y"));this.refreshIndicator("x");this.refreshIndicator("y")},destroy:function(){var a=this.getElement(),b=this.getIndicators();if(a&&!a.isDestroyed){a.removeCls(this.getCls())}b.x.destroy();b.y.destroy();Ext.destroy(this.getScroller(),this.indicatorsGrid);delete this.indicatorsGrid;this.callParent(arguments)}});Ext.define("Ext.behavior.Scrollable",{extend:"Ext.behavior.Behavior",requires:["Ext.scroll.View"],constructor:function(){this.listeners={painted:"onComponentPainted",scope:this};this.callParent(arguments)},onComponentPainted:function(){this.scrollView.refresh()},setConfig:function(d){var b=this.scrollView,c=this.component,f,e,a;if(d){if(!b){this.scrollView=b=new Ext.scroll.View(d);b.on("destroy","onScrollViewDestroy",this);c.setUseBodyElement(true);this.scrollerElement=a=c.innerElement;this.scrollContainer=e=a.wrap();this.scrollViewElement=f=c.bodyElement;b.setElement(f);if(c.isPainted()){this.onComponentPainted(c)}c.on(this.listeners)}else{if(Ext.isObject(d)){b.setConfig(d)}}}else{if(b){b.destroy()}}return this},getScrollView:function(){return this.scrollView},onScrollViewDestroy:function(){var b=this.component,a=this.scrollerElement;if(!a.isDestroyed){this.scrollerElement.unwrap()}this.scrollContainer.destroy();b.un(this.listeners);delete this.scrollerElement;delete this.scrollView;delete this.scrollContainer},onComponentDestroy:function(){var a=this.scrollView;if(a){a.destroy()}}});Ext.define("Ext.Container",{extend:"Ext.Component",alternateClassName:"Ext.lib.Container",requires:["Ext.layout.Layout","Ext.ItemCollection","Ext.behavior.Scrollable","Ext.Mask"],xtype:"container",eventedConfig:{activeItem:0},config:{layout:null,control:{},defaults:null,items:null,autoDestroy:true,defaultType:null,scrollable:null,useBodyElement:null,masked:null,modal:null,hideOnMaskTap:null},isContainer:true,delegateListeners:{delegate:"> component",centeredchange:"onItemCenteredChange",dockedchange:"onItemDockedChange",floatingchange:"onItemFloatingChange"},constructor:function(a){var b=this;b._items=b.items=new Ext.ItemCollection();b.innerItems=[];b.onItemAdd=b.onFirstItemAdd;b.callParent(arguments)},getElementConfig:function(){return{reference:"element",className:"x-container",children:[{reference:"innerElement",className:"x-inner"}]}},applyMasked:function(a,b){b=Ext.factory(a,Ext.Mask,b);if(b){this.add(b)}return b},mask:function(a){this.setMasked(a||true)},unmask:function(){this.setMasked(false)},applyModal:function(a,b){if(!a&&!b){return}return Ext.factory(a,Ext.Mask,b)},updateModal:function(c,a){var b={painted:"refreshModalMask",erased:"destroyModalMask"};if(c){this.on(b);c.on("destroy","onModalDestroy",this);if(this.getTop()===null&&this.getBottom()===null&&this.getRight()===null&&this.getLeft()===null&&!this.getCentered()){this.setTop(0);this.setLeft(0)}if(this.isPainted()){this.refreshModalMask()}}else{if(a){a.un("destroy","onModalDestroy",this);this.un(b)}}},onModalDestroy:function(){this.setModal(null)},refreshModalMask:function(){var b=this.getModal(),a=this.getParent();if(!this.painted){this.painted=true;if(b){a.insertBefore(b,this);b.setZIndex(this.getZIndex()-1)}}},destroyModalMask:function(){var b=this.getModal(),a=this.getParent();if(this.painted){this.painted=false;if(b){a.remove(b,false)}}},updateZIndex:function(b){var a=this.getModal();this.callParent(arguments);if(a){a.setZIndex(b-1)}},updateHideOnMaskTap:function(b){var a=this.getModal();if(a){a[b?"on":"un"].call(a,"tap","hide",this)}},updateBaseCls:function(a,b){var c=this,d=c.getUi();if(a){this.element.addCls(a);this.innerElement.addCls(a,null,"inner");if(d){this.element.addCls(a,null,d)}}if(b){this.element.removeCls(b);this.innerElement.removeCls(a,null,"inner");if(d){this.element.removeCls(b,null,d)}}},updateUseBodyElement:function(a){if(a){this.bodyElement=this.innerElement.wrap({cls:"x-body"});this.referenceList.push("bodyElement")}},applyItems:function(a,b){if(a){this.getDefaultType();this.getDefaults();if(this.initialized&&b.length>0){this.removeAll()}this.add(a)}},applyControl:function(c){var a,b,e,d;for(a in c){d=c[a];for(b in d){e=d[b];if(Ext.isObject(e)){e.delegate=a}}d.delegate=a;this.addListener(d)}return c},onFirstItemAdd:function(){delete this.onItemAdd;this.setLayout(new Ext.layout.Layout(this,this.getLayout()||"default"));if(this.innerHtmlElement&&!this.getHtml()){this.innerHtmlElement.destroy();delete this.innerHtmlElement}this.on(this.delegateListeners);return this.onItemAdd.apply(this,arguments)},updateDefaultType:function(a){this.defaultItemClass=Ext.ClassManager.getByAlias("widget."+a)},applyDefaults:function(a){if(a){this.factoryItem=this.factoryItemWithDefaults;return a}},factoryItem:function(a){return Ext.factory(a,this.defaultItemClass)},factoryItemWithDefaults:function(c){var b=this,d=b.getDefaults(),a;if(!d){return Ext.factory(c,b.defaultItemClass)}if(c.isComponent){a=c;if(d&&c.isInnerItem()&&!b.has(a)){a.setConfig(d,true)}}else{if(d&&!c.ignoreDefaults){if(!(c.hasOwnProperty("left")&&c.hasOwnProperty("right")&&c.hasOwnProperty("top")&&c.hasOwnProperty("bottom")&&c.hasOwnProperty("docked")&&c.hasOwnProperty("centered"))){c=Ext.mergeIf({},c,d)}}a=Ext.factory(c,b.defaultItemClass)}return a},add:function(a){var e=this,b,d,c,f;a=Ext.Array.from(a);d=a.length;for(b=0;b0&&c.isInnerItem()){f=c}}if(f){this.setActiveItem(f)}return c},doAdd:function(d){var c=this,a=c.getItems(),b;if(!a.has(d)){b=a.length;a.add(d);if(d.isInnerItem()){c.insertInner(d)}d.setParent(c);c.onItemAdd(d,b)}},remove:function(d,b){var c=this,a=c.indexOf(d),e=this.getInnerItems(),f;if(b===undefined){b=c.getAutoDestroy()}if(a!==-1){if(!this.removingAll&&e.length>1&&d===this.getActiveItem()){this.on({activeitemchange:"doRemove",scope:this,single:true,order:"after",args:[d,a,b]});f=e.indexOf(d);if(f===0){this.setActiveItem(1)}else{this.setActiveItem(0)}}else{this.doRemove(d,a,b)}}return c},doRemove:function(d,a,b){var c=this;c.items.remove(d);if(d.isInnerItem()){c.removeInner(d)}c.onItemRemove(d,a,b);d.setParent(null);if(b){d.destroy()}},removeAll:function(c,f){var a=this.items,e=a.length,b=0,d;if(c===undefined){c=this.getAutoDestroy()}f=Boolean(f);this.removingAll=true;for(;b=0;b--){c.insert(a,d[b])}return c}d=this.factoryItem(d);this.doInsert(a,d);return d},doInsert:function(d,f){var e=this,b=e.items,c=b.length,a,g;g=f.isInnerItem();if(d>c){d=c}if(b[d-1]===f){return e}a=e.indexOf(f);if(a!==-1){if(a "+a)[0]||null},down:function(a){return this.query(a)[0]||null},destroy:function(){var a=this.getModal();if(a){a.destroy()}this.removeAll(true,true);Ext.destroy(this.getScrollable(),this.bodyElement);this.callParent()}},function(){this.addMember("defaultItemClass",this)});Ext.define("Ext.Panel",{extend:"Ext.Container",requires:["Ext.util.LineSegment"],alternateClassName:"Ext.lib.Panel",xtype:"panel",isPanel:true,config:{baseCls:Ext.baseCSSPrefix+"panel",bodyPadding:null,bodyMargin:null,bodyBorder:null},getElementConfig:function(){var a=this.callParent();a.children.push({reference:"tipElement",className:"x-anchor",hidden:true});return a},applyBodyPadding:function(a){if(a===true){a=5}a=Ext.dom.Element.unitizeBox(a);return a},updateBodyPadding:function(a){this.element.setStyle("padding",a)},applyBodyMargin:function(a){if(a===true){a=5}a=Ext.dom.Element.unitizeBox(a);return a},updateBodyMargin:function(a){this.element.setStyle("margin",a)},applyBodyBorder:function(a){if(a===true){a=1}a=Ext.dom.Element.unitizeBox(a);return a},updateBodyBorder:function(a){this.element.setStyle("border-width",a)},alignTo:function(m){var w=this.tipElement;w.hide();if(this.currentTipPosition){w.removeCls("x-anchor-"+this.currentTipPosition)}this.callParent(arguments);var f=Ext.util.LineSegment,d=m.isComponent?m.renderElement:m,a=this.renderElement,n=d.getPageBox(),k=a.getPageBox(),b=k.left,t=k.top,C=k.right,h=k.bottom,j=b+(k.width/2),i=t+(k.height/2),o={x:b,y:t},l={x:C,y:t},B={x:b,y:h},D={x:C,y:h},y={x:j,y:i},s=n.left+(n.width/2),q=n.top+(n.height/2),v={x:s,y:q},c=new f(y,v),g=0,A=0,e,z,r,p,x,u;w.setVisibility(false);w.show();e=w.getSize();z=e.width;r=e.height;if(c.intersects(new f(o,l))){x=Math.min(Math.max(s,b),C-(z/2));u=t;A=r+10;p="top"}else{if(c.intersects(new f(o,B))){x=b;u=Math.min(Math.max(q+(z/2),t),h);g=r+10;p="left"}else{if(c.intersects(new f(B,D))){x=Math.min(Math.max(s,b),C-(z/2));u=h;A=-r-10;p="bottom"}else{if(c.intersects(new f(l,D))){x=C;u=Math.min(Math.max(q-(z/2),t),h);g=-r-10;p="right"}}}}if(x||u){this.currentTipPosition=p;w.addCls("x-anchor-"+p);w.setLeft(x-b);w.setTop(u-t);w.setVisibility(true);this.setLeft(this.getLeft()+g);this.setTop(this.getTop()+A)}}});Ext.define("Ext.SegmentedButton",{extend:"Ext.Container",xtype:"segmentedbutton",requires:["Ext.Button"],config:{baseCls:Ext.baseCSSPrefix+"segmentedbutton",pressedCls:Ext.baseCSSPrefix+"button-pressed",allowMultiple:false,allowDepress:null,pressedButtons:null,layout:{type:"hbox",align:"stretch"},defaultType:"button"},initialize:function(){var a=this;a.callParent();a.on({delegate:"> button",scope:a,tap:"onButtonRelease"});a.onAfter({delegate:"> button",scope:a,hiddenchange:"onButtonHiddenChange"})},updateAllowMultiple:function(){if(!this.initialized&&!this.getInitialConfig().hasOwnProperty("allowDepress")){this.setAllowDepress(true)}},applyItems:function(){var e=this,f=[],d,b,c,a;e.callParent(arguments);a=this.getItems();d=a.length;for(b=0;b=0;b--){c=a.items[b];if(!c.isHidden()){c.addCls(e+"last");break}}},applyPressedButtons:function(a){var e=this,f=[],c,d,b;if(Ext.isArray(a)){d=a.length;for(b=0;bm){c.renderElement.setWidth(m)}}var j=this.spacer.renderElement.getPageBox(),k=f.getPageBox(),g=k.width-j.width,d=k.left,i=k.right,b,l,e;if(g>0){f.setWidth(j.width);b=g/2;d+=b;i-=b}l=j.left-d;e=i-j.right;if(l>0){f.setLeft(l)}else{if(e>0){f.setLeft(-e)}}f.repaint()},updateTitle:function(a){this.titleComponent.setTitle(a);this.titleBox=null;if(this.painted){this.refreshTitlePosition()}},destroy:function(){this.callParent();var a=this.sizeMonitors;a.leftBox.destroy();a.spacer.destroy();a.rightBox.destroy()}});Ext.define("Ext.Toolbar",{extend:"Ext.Container",xtype:"toolbar",requires:["Ext.Button","Ext.Title","Ext.Spacer"],isToolbar:true,config:{baseCls:Ext.baseCSSPrefix+"toolbar",ui:"dark",title:null,defaultType:"button",layout:{type:"hbox",align:"center"}},constructor:function(a){a=a||{};if(a.docked=="left"||a.docked=="right"){a.layout={type:"vbox",align:"stretch"}}this.callParent([a])},applyTitle:function(a){if(typeof a=="string"){a={title:a,centered:true}}return Ext.factory(a,Ext.Title,this.getTitle())},updateTitle:function(b,a){if(b){this.add(b);this.getLayout().setItemFlex(b,1)}if(a){a.destroy()}},showTitle:function(){var a=this.getTitle();if(a){a.show()}},hideTitle:function(){var a=this.getTitle();if(a){a.hide()}}},function(){});Ext.define("Ext.MessageBox",{extend:"Ext.Sheet",requires:["Ext.Toolbar","Ext.field.Text","Ext.field.TextArea"],config:{ui:"dark",baseCls:Ext.baseCSSPrefix+"msgbox",iconCls:null,showAnimation:{type:"popIn",duration:250,easing:"ease-out"},hideAnimation:{type:"popOut",duration:250,easing:"ease-out"},zIndex:10,defaultTextHeight:75,title:null,buttons:null,message:null,prompt:null,layout:{type:"vbox",pack:"center"}},statics:{OK:{text:"OK",itemId:"ok",ui:"action"},YES:{text:"Yes",itemId:"yes",ui:"action"},NO:{text:"No",itemId:"no"},CANCEL:{text:"Cancel",itemId:"cancel"},INFO:Ext.baseCSSPrefix+"msgbox-info",WARNING:Ext.baseCSSPrefix+"msgbox-warning",QUESTION:Ext.baseCSSPrefix+"msgbox-question",ERROR:Ext.baseCSSPrefix+"msgbox-error",OKCANCEL:[{text:"Cancel",itemId:"cancel"},{text:"OK",itemId:"ok",ui:"action"}],YESNOCANCEL:[{text:"Cancel",itemId:"cancel"},{text:"No",itemId:"no"},{text:"Yes",itemId:"yes",ui:"action"}],YESNO:[{text:"No",itemId:"no"},{text:"Yes",itemId:"yes",ui:"action"}]},constructor:function(a){a=a||{};if(a.hasOwnProperty("promptConfig")){Ext.applyIf(a,{prompt:a.promptConfig});delete a.promptConfig}if(a.hasOwnProperty("multiline")||a.hasOwnProperty("multiLine")){a.prompt=a.prompt||{};Ext.applyIf(a.prompt,{multiLine:a.multiline||a.multiLine});delete a.multiline;delete a.multiLine}this.callParent([a])},applyTitle:function(a){if(typeof a=="string"){a={title:a}}Ext.applyIf(a,{docked:"top",cls:this.getBaseCls()+"-title"});return Ext.factory(a,Ext.Toolbar,this.getTitle())},updateTitle:function(a){if(a){this.add(a)}},updateButtons:function(a){var b=this;if(a){if(b.buttonsToolbar){b.buttonsToolbar.removeAll();b.buttonsToolbar.setItems(a)}else{b.buttonsToolbar=Ext.create("Ext.Toolbar",{docked:"bottom",defaultType:"button",layout:{type:"hbox",pack:"center"},ui:b.getUi(),cls:b.getBaseCls()+"-buttons",items:a});b.add(b.buttonsToolbar)}}},applyMessage:function(a){a={html:a,cls:this.getBaseCls()+"-text"};return Ext.factory(a,Ext.Component,this._message)},updateMessage:function(a){if(a){this.add(a)}},getMessage:function(){if(this._message){return this._message.getHtml()}return null},applyIconCls:function(a){a={xtype:"component",docked:"left",width:40,height:40,baseCls:Ext.baseCSSPrefix+"icon",hidden:(a)?false:true,cls:a};return Ext.factory(a,Ext.Component,this._iconCls)},updateIconCls:function(a,b){var c=this;this.getTitle();this.getButtons();if(a&&!b){this.add(a)}else{this.remove(b)}},getIconCls:function(){var b=this._iconCls,a;if(b){a=b.getCls();return(a)?a[0]:null}return null},applyPrompt:function(a){if(a){var b={label:false};if(Ext.isObject(a)){Ext.apply(b,a)}if(b.multiLine){b.height=Ext.isNumber(b.multiLine)?parseFloat(b.multiLine):this.getDefaultTextHeight();return Ext.factory(b,Ext.field.TextArea,this.getPrompt())}else{return Ext.factory(b,Ext.field.Text,this.getPrompt())}}return a},updatePrompt:function(a,b){if(a){this.add(a)}if(b){this.remove(b)}},onClick:function(c){if(c){var b=c.config.userConfig||{},d=c.getInitialConfig(),a=this.getPrompt();if(typeof b.fn=="function"){this.on({hiddenchange:function(){b.fn.call(b.scope||null,d.itemId||d.text,a?a.getValue():null,b)},single:true,scope:this})}if(b.cls){this.el.removeCls(b.cls)}if(b.input){b.input.dom.blur()}}this.hide()},show:function(f){if(!this.getParent()&&Ext.Viewport){Ext.Viewport.add(this)}if(!f){return this.callParent()}var b=Ext.Object.merge({},{value:""},f);var e=f.buttons||Ext.MessageBox.OK||[],d=[],c=f;Ext.each(e,function(g){if(!g){return}d.push(Ext.apply({userConfig:c,scope:this,handler:"onClick"},g))},this);b.buttons=d;if(b.promptConfig){}b.prompt=(b.promptConfig||b.prompt)||null;if(b.multiLine){b.prompt=b.prompt||{};b.prompt.multiLine=b.multiLine;delete b.multiLine}this.setConfig(b);var a=this.getPrompt();if(a){a.setValue(f.value||"")}this.callParent();return this},alert:function(d,c,b,a){return this.show({title:d,message:c,buttons:Ext.MessageBox.OK,promptConfig:false,fn:function(e){if(b){b.call(a,e)}},scope:a})},confirm:function(d,c,b,a){return this.show({title:d,message:c,buttons:Ext.MessageBox.YESNO,promptConfig:false,scope:a,fn:function(e){if(b){b.call(a,e)}}})},prompt:function(g,d,c,b,f,e,a){return this.show({title:g,message:d,buttons:Ext.MessageBox.OKCANCEL,scope:b,prompt:a||true,multiLine:f,value:e,fn:function(i,h){if(c){c.call(b,i,h)}}})}},function(a){Ext.onSetup(function(){Ext.Msg=new a})});Ext.define("Ext.carousel.Carousel",{extend:"Ext.Container",alternateClassName:"Ext.Carousel",xtype:"carousel",requires:["Ext.fx.easing.EaseOut","Ext.carousel.Item","Ext.carousel.Indicator"],config:{baseCls:"x-carousel",direction:"horizontal",directionLock:false,animation:{duration:250,easing:{type:"ease-out"}},indicator:true,ui:"dark",itemConfig:{},bufferSize:1,itemLength:null},itemLength:0,offset:0,flickStartOffset:0,flickStartTime:0,dragDirection:0,count:0,painted:false,activeIndex:-1,beforeInitialize:function(){this.animationListeners={animationframe:"onActiveItemAnimationFrame",animationend:"onActiveItemAnimationEnd",scope:this};this.element.on({dragstart:"onDragStart",drag:"onDrag",dragend:"onDragEnd",scope:this});this.on({painted:"onPainted",erased:"onErased",resize:"onSizeChange"});this.carouselItems=[];this.orderedCarouselItems=[];this.inactiveCarouselItems=[];this.hiddenTranslation=0},updateBufferSize:function(n){var l=Ext.carousel.Item,h=n*2+1,m=this.isRendered(),c=this.innerElement,g=this.carouselItems,f=g.length,e=this.getItemConfig(),d=this.getItemLength(),j=this.getDirection(),b=j==="horizontal"?"setWidth":"setHeight",a,k;for(a=f;a=a-c&&b<=a+c)},onDragStart:function(f){var d=this.getDirection(),b=f.absDeltaX,a=f.absDeltaY,c=this.getDirectionLock();this.isDragging=true;if(c){if((d==="horizontal"&&b>a)||(d==="vertical"&&a>b)){f.stopPropagation()}else{this.isDragging=false;return}}if(this.isAnimating){this.getActiveCarouselItem().getTranslatable().stopAnimation()}this.dragStartOffset=this.offset;this.dragDirection=0},onDrag:function(j){if(!this.isDragging){return}var k=this.dragStartOffset,l=this.getDirection(),m=l==="horizontal"?j.deltaX:j.deltaY,a=this.offset,i=this.flickStartTime,c=this.dragDirection,b=Ext.Date.now(),h=this.getActiveIndex(),f=this.getMaxItemIndex(),d=c,g;if((h===0&&m>0)||(h===f&&m<0)){m*=0.5}g=k+m;if(g>a){c=1}else{if(g300){this.flickStartOffset=a;this.flickStartTime=b}this.dragDirection=c;this.setOffset(g)},onDragEnd:function(j){if(!this.isDragging){return}this.onDrag(j);this.isDragging=false;var a=Ext.Date.now(),i=this.itemLength,g=i/2,f=this.offset,m=this.getActiveIndex(),c=this.getMaxItemIndex(),h=0,l=f-this.flickStartOffset,b=a-this.flickStartTime,k=this.getIndicator(),d;if(b>0&&Math.abs(l)>=10){d=l/b;if(Math.abs(d)>=1){if(d<0&&m0&&m>0){h=1}}}}if(h===0){if(m0&&f>g){h=1}}}if(k){k.setActiveIndex(m-h)}this.animationDirection=h;this.setOffsetAnimated(h*i)},applyAnimation:function(a){a.easing=Ext.factory(a.easing,Ext.fx.easing.EaseOut);return a},updateDirection:function(b){var a=this.getIndicator();this.currentAxis=(b==="horizontal")?"x":"y";if(a){a.setDirection(b)}},setOffset:function(e){var k=this.orderedCarouselItems,c=this.getBufferSize(),g=k[c],j=this.itemLength,d=this.currentAxis,a,h,b,f;this.offset=e;e+=this.itemOffset;if(g){g.translateAxis(d,e);for(f=1,b=0;f<=c;f++){h=k[c-f];if(h){b+=j;h.translateAxis(d,e-b)}}for(f=1,b=0;f<=c;f++){a=k[c+f];if(a){b+=j;a.translateAxis(d,e+b)}}}return this},setOffsetAnimated:function(c){var b=this.orderedCarouselItems[this.getBufferSize()],a=this.getIndicator();if(a){a.setActiveIndex(this.getActiveIndex()-this.animationDirection)}this.offset=c;c+=this.itemOffset;if(b){this.isAnimating=true;b.getTranslatable().on(this.animationListeners);b.translateAxis(this.currentAxis,c,this.getAnimation())}return this},onActiveItemAnimationFrame:function(k){var j=this.orderedCarouselItems,c=this.getBufferSize(),h=this.itemLength,d=this.currentAxis,e=k[d],g,a,f,b;for(f=1,b=0;f<=c;f++){g=j[c-f];if(g){b+=h;g.translateAxis(d,e-b)}}for(f=1,b=0;f<=c;f++){a=j[c+f];if(a){b+=h;a.translateAxis(d,e+b)}}},onActiveItemAnimationEnd:function(b){var c=this.getActiveIndex(),a=this.animationDirection,e=this.currentAxis,f=b[e],d=this.itemLength,g;this.isAnimating=false;b.un(this.animationListeners);if(a===-1){g=d+f}else{if(a===1){g=f-d}else{g=f}}g-=this.itemOffset;this.offset=g;this.setActiveItem(c-a)},refresh:function(){this.refreshSizing();this.refreshActiveItem()},refreshSizing:function(){var a=this.element,b=this.getItemLength(),c,d;if(this.getDirection()==="horizontal"){d=a.getWidth()}else{d=a.getHeight()}this.hiddenTranslation=-d;if(b===null){b=d;c=0}else{c=(d-b)/2}this.itemLength=b;this.itemOffset=c},refreshOffset:function(){this.setOffset(this.offset)},refreshActiveItem:function(){this.doSetActiveItem(this.getActiveItem())},getActiveIndex:function(){return this.activeIndex},refreshActiveIndex:function(){this.activeIndex=this.getInnerItemIndex(this.getActiveItem())},refreshCarouselItems:function(){var a=this.carouselItems,b,d,c;for(b=0,d=a.length;b0){for(f=1;f<=c;f++){h=q-f;if(h>=0){a=this.getInnerItemAt(h);b=a.getId();o[b]=a;p[b]=c-f}else{break}}}if(qb){this.setActiveItem(b)}else{this.rebuildInnerIndexes(a);this.refreshActiveItem()}}},rebuildInnerIndexes:function(n){var c=this.innerIndexToItem,g=this.innerIdToIndex,j=this.innerItems.slice(),h=j.length,b=this.getBufferSize(),d=this.getMaxItemIndex(),l=[],e,k,f,a,m;if(n===undefined){this.innerIndexToItem=c={};this.innerIdToIndex=g={};for(e=0;e=0&&e<=d){if(c.hasOwnProperty(e)){Ext.Array.remove(j,c[e]);continue}l.push(e)}}for(e=0,h=l.length;e ."+Ext.baseCSSPrefix+"data-item",scope:this})},initialize:function(){this.callParent();this.doInitialize()},onItemTouchStart:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);a.on({touchmove:"onItemTouchMove",scope:b,single:true});b.fireEvent("itemtouchstart",b,a,b.indexOf(a),d)},onItemTouchMove:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);b.fireEvent("itemtouchmove",b,a,b.indexOf(a),d)},onItemTouchEnd:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);a.un({touchmove:"onItemTouchMove",scope:b});b.fireEvent("itemtouchend",b,a,b.indexOf(a),d)},onItemTap:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);b.fireEvent("itemtap",b,a,b.indexOf(a),d)},onItemTapHold:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);b.fireEvent("itemtaphold",b,a,b.indexOf(a),d)},onItemDoubleTap:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);b.fireEvent("itemdoubletap",b,a,b.indexOf(a),d)},onItemSwipe:function(d){var b=this,c=d.getTarget(),a=Ext.getCmp(c.id);b.fireEvent("itemswipe",b,a,b.indexOf(a),d)},moveItemsToCache:function(j,k){var h=this,c=h.dataview,a=c.getMaxItemCache(),g=h.getViewItems(),f=h.itemCache,e=f.length,l=c.getPressedCls(),d=c.getSelectedCls(),b=k-j,m;for(;b>=0;b--){m=g[j+b];if(e!==a){h.remove(m,false);m.removeCls([l,d]);f.push(m);e++}else{m.destroy()}}if(h.getViewItems().length==0){this.dataview.showEmptyText()}},moveItemsFromCache:function(b){var l=this,e=l.dataview,m=e.getStore(),k=b.length,a=e.getDefaultType(),h=e.getItemConfig(),g=l.itemCache,f=g.length,j=[],c,n,d;if(k){e.hideEmptyText()}for(c=0;ci._tmpIndex?1:-1});for(c=0;c{text}",pressedCls:"x-item-pressed",itemCls:null,selectedCls:"x-item-selected",triggerEvent:"itemtap",triggerCtEvent:"tap",deselectOnContainerClick:true,scrollable:true,inline:null,pressedDelay:100,loadingText:"Loading...",useComponents:null,itemConfig:{},maxItemCache:20,defaultType:"dataitem",scrollToTopOnRefresh:true},constructor:function(a){var b=this;b.hasLoadedStore=false;b.mixins.selectable.constructor.apply(b,arguments);b.callParent(arguments)},updateItemCls:function(c,b){var a=this.container;if(a){if(b){a.doRemoveItemCls(b)}if(c){a.doAddItemCls(c)}}},storeEventHooks:{beforeload:"onBeforeLoad",load:"onLoad",refresh:"refresh",addrecords:"onStoreAdd",removerecords:"onStoreRemove",updaterecord:"onStoreUpdate"},initialize:function(){this.callParent();var b=this,a;b.on(b.getTriggerCtEvent(),b.onContainerTrigger,b);a=b.container=this.add(new Ext.dataview[b.getUseComponents()?"component":"element"].Container({baseCls:this.getBaseCls()}));a.dataview=b;b.on(b.getTriggerEvent(),b.onItemTrigger,b);a.on({itemtouchstart:"onItemTouchStart",itemtouchend:"onItemTouchEnd",itemtap:"onItemTap",itemtaphold:"onItemTapHold",itemtouchmove:"onItemTouchMove",itemdoubletap:"onItemDoubleTap",itemswipe:"onItemSwipe",scope:b});if(this.getStore()){this.refresh()}},applyInline:function(a){if(Ext.isObject(a)){a=Ext.apply({},a)}return a},updateInline:function(c,b){var a=this.getBaseCls();if(b){this.removeCls([a+"-inlineblock",a+"-nowrap"])}if(c){this.addCls(a+"-inlineblock");if(Ext.isObject(c)&&c.wrap===false){this.addCls(a+"-nowrap")}else{this.removeCls(a+"-nowrap")}}},prepareData:function(c,b,a){return c},onContainerTrigger:function(b){var a=this;if(b.target!=a.element.dom){return}if(a.getDeselectOnContainerClick()&&a.getStore()){a.deselectAll()}},onItemTrigger:function(b,a){this.selectWithEvent(this.getStore().getAt(a))},doAddPressedCls:function(a){var c=this,b=c.container.getViewItems()[c.getStore().indexOf(a)];if(Ext.isElement(b)){b=Ext.get(b)}if(b){b.addCls(c.getPressedCls())}},onItemTouchStart:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);f.fireAction("itemtouchstart",[f,d,h,a,g],"doItemTouchStart")},doItemTouchStart:function(c,b,e,a){var d=c.getPressedDelay();if(a){if(d>0){c.pressedTimeout=Ext.defer(c.doAddPressedCls,d,c,[a])}else{c.doAddPressedCls(a)}}},onItemTouchEnd:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);if(this.hasOwnProperty("pressedTimeout")){clearTimeout(this.pressedTimeout);delete this.pressedTimeout}if(a&&h){h.removeCls(f.getPressedCls())}f.fireEvent("itemtouchend",f,d,h,a,g)},onItemTouchMove:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);if(f.hasOwnProperty("pressedTimeout")){clearTimeout(f.pressedTimeout);delete f.pressedTimeout}if(a&&h){h.removeCls(f.getPressedCls())}f.fireEvent("itemtouchmove",f,d,h,a,g)},onItemTap:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);f.fireEvent("itemtap",f,d,h,a,g)},onItemTapHold:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);f.fireEvent("itemtaphold",f,d,h,a,g)},onItemDoubleTap:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);f.fireEvent("itemdoubletap",f,d,h,a,g)},onItemSwipe:function(b,h,d,g){var f=this,c=f.getStore(),a=c&&c.getAt(d);f.fireEvent("itemswipe",f,d,h,a,g)},onItemSelect:function(a,b){var c=this;if(b){c.doItemSelect(c,a)}else{c.fireAction("select",[c,a],"doItemSelect")}},doItemSelect:function(c,a){if(c.container){var b=c.container.getViewItems()[c.getStore().indexOf(a)];if(Ext.isElement(b)){b=Ext.get(b)}if(b){b.removeCls(c.getPressedCls());b.addCls(c.getSelectedCls())}}},onItemDeselect:function(a,b){var c=this;if(c.container){if(b){c.doItemDeselect(c,a)}else{c.fireAction("deselect",[c,a,b],"doItemDeselect")}}},doItemDeselect:function(c,a){var b=c.container.getViewItems()[c.getStore().indexOf(a)];if(Ext.isElement(b)){b=Ext.get(b)}if(b){b.removeCls([c.getPressedCls(),c.getSelectedCls()])}},updateData:function(b){var a=this.getStore();if(!a){this.setStore(Ext.create("Ext.data.Store",{data:b}))}else{a.add(b)}},applyStore:function(b){var d=this,e=Ext.apply({},d.storeEventHooks,{scope:d}),c,a;if(b){b=Ext.data.StoreManager.lookup(b);if(b&&Ext.isObject(b)&&b.isStore){b.on(e);c=b.getProxy();if(c){a=c.getReader();if(a){a.on("exception","handleException",this)}}}}return b},handleException:function(){this.setMasked(false)},updateStore:function(b,e){var d=this,f=Ext.apply({},d.storeEventHooks,{scope:d}),c,a;if(e&&Ext.isObject(e)&&e.isStore){if(e.autoDestroy){e.destroy()}else{e.un(f);c=e.getProxy();if(c){a=c.getReader();if(a){a.un("exception","handleException",this)}}}}if(b){if(b.isLoaded()){this.hasLoadedStore=true}if(b.isLoading()){d.onBeforeLoad()}if(d.container){d.refresh()}}},onBeforeLoad:function(){var b=this.getScrollable();if(b){b.getScroller().stopAnimation()}var a=this.getLoadingText();if(a){this.setMasked({xtype:"loadmask",message:a});if(b){b.getScroller().setDisabled(true)}}this.hideEmptyText()},updateEmptyText:function(b){var a=this;if(b){a.emptyTextCmp=a.add({xtype:"component",cls:a.getBaseCls()+"-emptytext",html:b,hidden:true})}else{if(a.emptyTextCmp){a.remove(a.emptyTextCmp,true);delete a.emptyTextCmp}}},onLoad:function(a){var b=this.getScrollable();this.hasLoadedStore=true;this.setMasked(false);if(b){b.getScroller().setDisabled(false)}if(!a.getCount()){this.showEmptyText()}},refresh:function(){var b=this,a=b.container;if(!b.getStore()){if(!b.hasLoadedStore&&!b.getDeferEmptyText()){b.showEmptyText()}return}if(a){b.fireAction("refresh",[b],"doRefresh")}},applyItemTpl:function(a){return(Ext.isObject(a)&&a.isTemplate)?a:new Ext.XTemplate(a)},onAfterRender:function(){var a=this;a.callParent(arguments);a.updateStore(a.getStore())},getViewItems:function(){return this.container.getViewItems()},doRefresh:function(f){var a=f.container,j=f.getStore(),b=j.getRange(),e=a.getViewItems(),h=b.length,l=e.length,c=h-l,g=f.getScrollable(),d,k;if(this.getScrollToTopOnRefresh()&&g){g.getScroller().scrollToTop()}if(h<1){f.onStoreClear();return}if(c<0){a.moveItemsToCache(l+c,l-1);e=a.getViewItems();l=e.length}else{if(c>0){a.moveItemsFromCache(j.getRange(l))}}for(d=0;dh.y){c=g;break}f=g}return{current:f,next:c}},doRefreshHeaders:function(){if(!this.getGrouped()||!this.container){return false}var l=this.findGroupHeaderIndices(),f=l.length,g=this.container.getViewItems(),j=this.pinHeaderInfo={offsets:[]},a=j.offsets,h=this.getScrollable(),e,k,b,d,c;if(f){for(b=0;bd.offset)||(f&&h0&&d.offset-h<=c){var k=c-(d.offset-h);this.translateHeader(k)}else{this.translateHeader(null)}},translateHeaderTransform:function(a){this.header.renderElement.dom.style.webkitTransform=(a===null)?null:"translate3d(0px, -"+a+"px, 0px)"},translateHeaderCssPosition:function(a){this.header.renderElement.dom.style.top=(a===null)?null:"-"+Math.round(a)+"px"},setActiveGroup:function(b){var a=this,c=a.header;if(c){if(b){if(!a.activeGroup||a.activeGroup.header!=b.header){c.show();if(c.element){c.setHtml(b.header.innerHTML)}}}else{if(c&&c.dom){c.hide()}}}this.activeGroup=b},onIndex:function(o,c){var r=this,s=c.toLowerCase(),b=r.getStore(),q=b.getGroups(),f=q.length,h=r.getScrollable(),n,e,m,g,k,p;if(h){n=r.getScrollable().getScroller()}else{return}for(m=0;ms){g=e;break}else{g=e}}if(h&&g){p=r.container.getViewItems()[b.indexOf(g.children[0])];n.stopAnimation();var l=n.getContainerSize().y,j=n.getSize().y,d=j-l,a=(p.offsetTop>d)?d:p.offsetTop;n.scrollTo(0,a)}},applyOnItemDisclosure:function(a){if(Ext.isFunction(a)){return{scope:this,handler:a}}return a},handleItemDisclosure:function(f){var d=this,c=f.getTarget().parentNode,b=d.container.getViewItems().indexOf(c),a=d.getStore().getAt(b);d.fireAction("disclose",[d,a,c,b,f],"doDisclose")},doDisclose:function(f,a,d,c,g){var b=f.getOnItemDisclosure();if(b&&b.handler){b.handler.call(f,a,d,c,g)}},findGroupHeaderIndices:function(){if(!this.getGrouped()){return[]}var h=this,k=h.getStore();if(!k){return[]}var b=h.container,d=k.getGroups(),m=d.length,g=b.getViewItems(),c=[],l=b.footerClsShortCache,e,a,f,n,j;b.doRemoveHeaders();b.doRemoveFooterCls();if(g.length){for(e=0;e class="x-list-item-leaf">'+a.getItemTextTpl(b)+""},this.getListConfig())}},function(){});Ext.define("Ext.form.FieldSet",{extend:"Ext.Container",alias:"widget.fieldset",requires:["Ext.Title"],config:{baseCls:Ext.baseCSSPrefix+"form-fieldset",title:null,instructions:null},applyTitle:function(a){if(typeof a=="string"){a={title:a}}Ext.applyIf(a,{docked:"top",baseCls:this.getBaseCls()+"-title"});return Ext.factory(a,Ext.Title,this.getTitle())},updateTitle:function(b,a){if(b){this.add(b)}if(a){this.remove(a)}},applyInstructions:function(a){if(typeof a=="string"){a={title:a}}Ext.applyIf(a,{docked:"bottom",baseCls:this.getBaseCls()+"-instructions"});return Ext.factory(a,Ext.Title,this.getInstructions())},updateInstructions:function(b,a){if(b){this.add(b)}if(a){this.remove(a)}}});Ext.define("Ext.form.Panel",{alternateClassName:"Ext.form.FormPanel",extend:"Ext.Panel",xtype:"formpanel",requires:["Ext.XTemplate","Ext.field.Checkbox","Ext.Ajax"],config:{baseCls:Ext.baseCSSPrefix+"form",standardSubmit:false,url:null,baseParams:null,submitOnAction:true,record:null,method:"post",scrollable:{translationMethod:"scrollposition"}},getElementConfig:function(){var a=this.callParent();a.tag="form";return a},initialize:function(){var a=this;a.callParent();a.on({action:"onFieldAction",scope:a});a.element.on({submit:"onSubmit",scope:a})},updateRecord:function(c){var a,b,d;if(c&&(a=c.fields)){b=this.getValues();for(d in b){if(b.hasOwnProperty(d)&&a.containsKey(d)){c.set(d,b[d])}}}return this},setRecord:function(a){var b=this;if(a&&a.data){b.setValues(a.data)}b._record=a;return this},onSubmit:function(b){var a=this;if(b&&!a.getStandardSubmit()){b.stopEvent()}a.fireAction("submit",[a,a.getValues(true),b],"doSubmit")},doSubmit:function(b,a,c){if(c){c.stopEvent()}},onFieldAction:function(a){if(this.getSubmitOnAction()){a.blur();this.submit()}},submit:function(a){var c=this,b=c.element.dom||{},d;a=Ext.apply({url:c.getUrl()||b.action,submit:false,method:c.getMethod()||b.method||"post",autoAbort:false,params:null,waitMsg:null,headers:null,success:null,failure:null},a||{});d=c.getValues(c.getStandardSubmit()||!a.submitDisabled);return c.fireAction("beforesubmit",[c,d,a],"doBeforeSubmit")},doBeforeSubmit:function(c,d,a){var b=c.element.dom||{};if(c.getStandardSubmit()){if(a.url&&Ext.isEmpty(b.action)){b.action=a.url}b.method=(a.method||b.method).toLowerCase();b.submit()}else{if(a.waitMsg){c.setMasked(a.waitMsg)}return Ext.Ajax.request({url:a.url,method:a.method,rawData:Ext.urlEncode(Ext.apply(Ext.apply({},c.getBaseParams()||{}),a.params||{},d)),autoAbort:a.autoAbort,headers:Ext.apply({"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},a.headers||{}),scope:c,callback:function(e,j,f){var h=this,i=f.responseText,g;h.setMasked(false);g=function(){if(Ext.isFunction(a.failure)){a.failure.call(a.scope||h,h,f,i)}h.fireEvent("exception",h,f)};if(j){f=Ext.decode(i);j=!!f.success;if(j){if(Ext.isFunction(a.success)){a.success.call(a.scope||h,h,f,i)}h.fireEvent("submit",h,f)}else{g()}}else{g()}}})}},setValues:function(b){var a=this.getFields(),c,e,d;b=b||{};for(c in b){if(b.hasOwnProperty(c)){e=a[c];d=b[c];if(e){if(Ext.isArray(e)){e.forEach(function(g){if(g.isRadio){g.setGroupValue(d)}else{if(Ext.isArray(b[c])){g.setChecked((d.indexOf(g.getValue())!=-1))}else{g.setChecked((d==g.getValue()))}}})}else{if(e.setChecked){e.setChecked(d)}else{e.setValue(d)}}}}}return this},getValues:function(d){var a=this.getFields(),b={},g,c,f,e;for(c in a){if(a.hasOwnProperty(c)){if(Ext.isArray(a[c])){b[c]=[];f=a[c].length;for(e=0;e1){this.pushBackButtonAnimated(this.getBackButtonText())}this.pushTitleAnimated(this.getTitleText())}else{if(this.backButtonStack.length>1){this.pushBackButton(this.getBackButtonText())}this.pushTitle(this.getTitleText())}},onViewRemove:function(a,c,b){var d=a.getLayout().getAnimation();this.endAnimation();this.backButtonStack.pop();this.refreshNavigationBarProxy();if(d&&d.isAnimation&&a.isPainted()){this.popBackButtonAnimated(this.getBackButtonText());this.popTitleAnimated(this.getTitleText())}else{this.popBackButton(this.getBackButtonText());this.popTitle(this.getTitleText())}},endAnimation:function(){var c=this.lastAnimationProperties,d,b,a;if(c){for(d in c){b=Ext.get(d);for(a in c[d].to){b.setStyle(a,c[d][a])}if(c[d].onEnd){c[d].onEnd.call(this)}}}},applyBackButton:function(a){return Ext.factory(a,Ext.Button,this.getBackButton())},updateBackButton:function(a,b){if(b){this.remove(b)}if(a){this.add(a);a.on({scope:this,tap:this.onBackButtonTap})}},onBackButtonTap:function(){this.fireEvent("back",this)},updateUseTitleForBackButtonText:function(a){var b=this.getBackButton();if(b){b.setText(this.getBackButtonText())}this.onSizeMonitorChange()},onPainted:function(){this.painted=true;this.sizeMonitor.refresh();this.onSizeMonitorChange()},onErased:function(){this.painted=false},applyItems:function(c){var e=this;if(!e.initialized){var f=e.getDefaults()||{},a,b,d;e.leftBox=a=e.add({xtype:"container",style:"position: relative",layout:{type:"hbox",align:"center"}});e.spacer=d=e.add({xtype:"component",style:"position: relative",flex:1});e.rightBox=b=e.add({xtype:"container",style:"position: relative",layout:{type:"hbox",align:"center"}});e.titleComponent=e.add({xtype:"title",hidden:f.hidden,centered:true});e.sizeMonitor=new Ext.util.SizeMonitor({element:e.element,callback:e.onSizeMonitorChange,scope:e});e.doAdd=e.doBoxAdd;e.doInsert=e.doBoxInsert}e.callParent(arguments)},doBoxAdd:function(a){if(a.config.align=="right"){this.rightBox.add(a)}else{this.leftBox.add(a)}},doBoxInsert:function(a,b){if(b.config.align=="right"){this.rightBox.add(b)}else{this.leftBox.add(b)}},onSizeMonitorChange:function(){if(!this.rendered){return}var c=this.getBackButton(),a=this.titleComponent;if(c&&c.rendered){c.setWidth(null)}this.refreshNavigationBarProxy();var b=this.getNavigationBarProxyProperties();if(c&&c.rendered){c.setWidth(b.backButton.width)}a.setStyle("-webkit-transform",null);a.setWidth(b.title.width);a.element.setLeft(b.title.left)},getBackButtonAnimationProperties:function(){var c=this,b=c.element,h=c.getBackButton().element,e=c.titleComponent.element,g=Math.min(b.getWidth()/3,200),a=this.getNavigationBarProxyProperties(),d,f;d=e.getX()-b.getX();f=b.getX()-h.getX()-h.getWidth();d=Math.min(d,g);return{element:{from:{left:d,width:a.backButton.width,opacity:0},to:{left:0,width:a.backButton.width,opacity:1}},ghost:{from:null,to:{left:f,opacity:0}}}},getBackButtonAnimationReverseProperties:function(){var d=this,c=d.element,h=d.getBackButton().element,f=d.titleComponent.element,b=Math.min(c.getWidth()/3,200),a=this.getNavigationBarProxyProperties(),e,g;e=c.getX()-h.getX()-h.getWidth();g=f.getX()-h.getWidth();g=Math.min(g,b);return{element:{from:{left:e,width:a.backButton.width,opacity:0},to:{left:0,width:a.backButton.width,opacity:1}},ghost:{from:null,to:{left:g,opacity:0}}}},getTitleAnimationProperties:function(){var c=this,b=c.element,e=c.titleComponent.element,a=this.getNavigationBarProxyProperties(),d,f;d=b.getWidth()-e.getX();f=b.getX()-e.getX()+a.backButton.width;if((a.backButton.left+e.getWidth())>e.getX()){f=b.getX()-e.getX()-e.getWidth()}return{element:{from:{left:d,width:a.title.width,opacity:0},to:{left:a.title.left,width:a.title.width,opacity:1}},ghost:{from:e.getLeft(),to:{left:f,opacity:0}}}},getTitleAnimationReverseProperties:function(){var d=this,c=d.element,f=d.titleComponent.element,a=this.getNavigationBarProxyProperties(),b=0,e,g;b=f.getLeft();f.setLeft(0);e=c.getX()-f.getX()+a.backButton.width;g=c.getX()+c.getWidth();if((a.backButton.left+f.getWidth())>f.getX()){e=c.getX()-f.getX()-f.getWidth()}return{element:{from:{left:e,width:a.title.width,opacity:0},to:{left:a.title.left,width:a.title.width,opacity:1}},ghost:{from:b,to:{left:g,opacity:0}}}},animate:function(c,d,h,g,b){var e=this,a={element:d,easing:"ease-in-out",duration:this.getAnimation().duration,replacePrevious:true,preserveEndState:true},f;this.lastAnimationProperties[d.id]={to:g,onEnd:b};d.setLeft(0);if(Ext.os.is.Android){if(h){a.from={left:h.left,opacity:h.opacity};if(h.width){a.from.width=h.width}}if(g){a.to={left:g.left,opacity:g.opacity};if(g.width){a.to.width=g.width}}}else{if(h){a.from={transform:{translateX:h.left},opacity:h.opacity};if(h.width){a.from.width=h.width}}if(g){a.to={transform:{translateX:g.left},opacity:g.opacity};if(g.width){a.to.width=g.width}}}fn=function(){if(b){b.call(e)}if(c&&Ext.isNumber(g.width)){c.setWidth(g.width)}e.lastAnimationProperties={}};f=new Ext.fx.Animation(a);f.on("animationend",fn,this);Ext.Animator.run(f)},getBackButtonText:function(){var b=this.backButtonStack[this.backButtonStack.length-2],a=this.getUseTitleForBackButtonText();if(!a){if(b){b=this.getDefaultBackButtonText()}}return b},getTitleText:function(){return this.backButtonStack[this.backButtonStack.length-1]},pushBackButton:function(c){var b=this.getBackButton();b.setText(c);b.show();var a=this.getBackButtonAnimationProperties(),d=a.element.to;if(d.left){b.setLeft(d.left)}if(d.width){b.setWidth(d.width)}},pushBackButtonAnimated:function(f){var e=this;var d=e.getBackButton(),b=d.getText(),g=d.element,c=e.getBackButtonAnimationProperties(),a;if(b){a=e.createProxy(d)}d.setText(this.getBackButtonText());d.show();e.animate(d,g,c.element.from,c.element.to,function(){e.animating=false});if(a){e.animate(null,a,c.ghost.from,c.ghost.to,function(){a.destroy()})}},popBackButton:function(c){var b=this.getBackButton();b.setText(null);if(c){b.setText(this.getBackButtonText())}else{b.hide()}var a=this.getBackButtonAnimationReverseProperties(),d=a.element.to;if(d.left){b.setLeft(d.left)}if(d.width){b.setWidth(d.width)}},popBackButtonAnimated:function(f){var e=this;var d=e.getBackButton(),b=d.getText(),g=d.element,c=e.getBackButtonAnimationReverseProperties(),a;if(b){a=e.createProxy(d)}if(f&&e.backButtonStack.length){d.setText(this.getBackButtonText());d.show();e.animate(d,g,c.element.from,c.element.to)}else{d.hide()}if(a){e.animate(null,a,c.ghost.from,c.ghost.to,function(){a.destroy();if(!f){d.setText(null)}})}},pushTitle:function(e){var c=this.titleComponent,b=c.element,a=this.getTitleAnimationProperties(),d=a.element.to;c.setTitle(e);if(d.left){b.setLeft(d.left)}if(d.width){c.setWidth(d.width)}},pushTitleAnimated:function(h){var e=this;var d=e.getBackButton(),b=(d)?d.getText():null,g=e.titleComponent,f=g.element,c,a;if(b){a=e.createProxy(g,true)}g.setTitle(h);c=e.getTitleAnimationProperties();e.animate(g,f,c.element.from,c.element.to);if(a){e.animate(null,a,c.ghost.from,c.ghost.to,function(){a.destroy()})}},popTitle:function(e){var c=this.titleComponent,b=c.element,a=this.getTitleAnimationReverseProperties(),d=a.element.to;c.setTitle(e);if(d.left){b.setLeft(d.left)}if(d.width){c.setWidth(d.width)}},popTitleAnimated:function(h){var e=this;var d=e.getBackButton(),b=e.titleComponent.getTitle(),g=e.titleComponent,f=g.element,c=e.getTitleAnimationReverseProperties(),a;if(b){a=e.createProxy(g,true)}g.setTitle(h||"");e.animate(g,f,c.element.from,c.element.to,function(){e.animating=false});if(a){e.animate(null,a,c.ghost.from,c.ghost.to,function(){a.destroy()})}},createNavigationBarProxy:function(){var a=this.proxy;if(a){return}this.proxy=a=Ext.create("Ext.TitleBar",{items:[{xtype:"button",ui:"back",text:""}],title:this.backButtonStack[0]});a.backButton=a.down("button[ui=back]");Ext.getBody().appendChild(a.element);a.element.setStyle("position","absolute");a.element.setStyle("visibility","hidden");a.element.setX(0);a.element.setY(-1000)},getNavigationBarProxyProperties:function(){return{title:{left:this.proxy.titleComponent.element.getLeft(),width:this.proxy.titleComponent.element.getWidth()},backButton:{left:this.proxy.backButton.element.getLeft(),width:this.proxy.backButton.element.getWidth()}}},refreshNavigationBarProxy:function(){var c=this.proxy,b=this.element,a=this.backButtonStack,e=a[a.length-1],d=this.getBackButtonText();if(!c){this.createNavigationBarProxy();c=this.proxy}c.element.setWidth(b.getWidth());c.element.setHeight(b.getHeight());c.setTitle(e);if(d){c.backButton.setText(d);c.backButton.show()}else{c.backButton.hide()}c.refreshTitlePosition()},onBeforePop:function(b){b--;for(var a=0;a1&&d===this.getActiveItem()){this.on({activeitemchange:"doRemove",scope:this,single:true,order:"after",args:[d,a,b]});g=f.indexOf(d);if(g>0){if(e&&e.isAnimation){e.setReverse(true)}this.setActiveItem(g-1);this.getNavigationBar().onViewRemove(this,f[g],g)}}else{this.doRemove(d,a,b)}}return c},doRemove:function(){var a=this.getLayout().getAnimation();if(a&&a.isAnimation){a.setReverse(false)}this.callParent(arguments)},onItemAdd:function(b,a){this.doItemLayoutAdd(b,a);if(!this.isItemsInitializing&&b.isInnerItem()){this.setActiveItem(b);this.getNavigationBar().onViewAdd(this,b,a)}if(this.initialized){this.fireEvent("add",this,b,a)}},reset:function(){this.pop(this.getInnerItems().length)}});Ext.define("Ext.picker.Slot",{extend:"Ext.DataView",xtype:"pickerslot",alternateClassName:"Ext.Picker.Slot",requires:["Ext.XTemplate","Ext.data.Store","Ext.Component","Ext.data.StoreManager"],isSlot:true,config:{title:null,showTitle:true,cls:Ext.baseCSSPrefix+"picker-slot",name:null,value:null,flex:1,align:"left",displayField:"text",valueField:"value",scrollable:{direction:"vertical",indicators:false,momentumEasing:{minVelocity:2},slotSnapEasing:{duration:100}}},constructor:function(){this.selectedIndex=0;this.callParent(arguments)},applyTitle:function(a){if(a){a=Ext.create("Ext.Component",{cls:Ext.baseCSSPrefix+"picker-slot-title",docked:"top",html:a})}return a},updateTitle:function(b,a){if(b){this.add(b);this.setupBar()}if(a){this.remove(a)}},updateShowTitle:function(a){var b=this.getTitle();if(b){b[a?"show":"hide"]();this.setupBar()}},updateDisplayField:function(a){this.setItemTpl('
'+Ext.baseCSSPrefix+'picker-invalid">{'+a+"}
")},updateAlign:function(a,c){var b=this.element;b.addCls(Ext.baseCSSPrefix+"picker-"+a);b.removeCls(Ext.baseCSSPrefix+"picker-"+c)},applyData:function(d){var f=[],c=d&&d.length,a,b,e;if(d&&Ext.isArray(d)&&c){for(a=0;a{'+this.getDisplayField()+"}",listeners:{select:this.onListSelect,itemtap:this.onListTap,scope:this}}},a))}return this.listPanel},onMaskTap:function(){if(this.getDisabled()){return false}this.showPicker();return false},showPicker:function(){if(this.getStore().getCount()===0){return}if(this.getReadOnly()){return}this.isFocused=true;if(this.getUsePicker()){var e=this.getPhonePicker(),d=this.getName(),h={};h[d]=this.record.get(this.getValueField());e.setValue(h);if(!e.getParent()){Ext.Viewport.add(e)}e.show()}else{var f=this.getTabletPicker(),g=f.down("list"),b=g.getStore(),c=b.find(this.getValueField(),this.getValue(),null,null,null,true),a=b.getAt((c==-1)?0:c);if(!f.getParent()){Ext.Viewport.add(f)}f.showBy(this.getComponent());g.select(a,null,true)}},onListSelect:function(c,a){var b=this;if(a){b.setValue(a)}},onListTap:function(){this.listPanel.hide({type:"fade",out:true,scope:this})},onPickerChange:function(d,f){var e=this,g=f[e.getName()],b=e.getStore(),c=b.find(e.getValueField(),g,null,null,null,true),a=b.getAt(c);e.setValue(a)},updateOptions:function(b){var a=this.getStore();if(!b){a.clearData()}else{a.setData(b);this.onStoreDataChanged(a)}},applyStore:function(a){if(a===true){a=Ext.create("Ext.data.Store",{fields:[this.getValueField(),this.getDisplayField()]})}if(a){a=Ext.data.StoreManager.lookup(a);a.on({scope:this,addrecords:this.onStoreDataChanged,removerecords:this.onStoreDataChanged,updaterecord:this.onStoreDataChanged,refresh:this.onStoreDataChanged})}return a},updateStore:function(a){if(a){this.onStoreDataChanged(a)}},onStoreDataChanged:function(a){var c=this.getInitialConfig(),b=this.getValue();if(Ext.isDefined(b)){this.updateValue(this.applyValue(b))}if(this.getValue()===null){if(c.hasOwnProperty("value")){this.setValue(c.value)}if(this.getValue()===null){if(a.getCount()>0){this.setValue(a.getAt(0))}}}},doSetDisabled:function(a){Ext.Component.prototype.doSetDisabled.apply(this,arguments)},setDisabled:function(){Ext.Component.prototype.setDisabled.apply(this,arguments)},reset:function(){var b=this.getStore(),a=(this.originalValue)?this.originalValue:b.getAt(0);if(b&&a){this.setValue(a)}return this},onFocus:function(a){this.fireEvent("focus",this,a);this.isFocused=true;this.showPicker()},destroy:function(){this.callParent(arguments);Ext.destroy(this.listPanel,this.picker,this.hiddenField)}});Ext.define("Ext.picker.Date",{extend:"Ext.picker.Picker",xtype:"datepicker",alternateClassName:"Ext.DatePicker",requires:["Ext.DateExtras"],config:{yearFrom:1980,yearTo:new Date().getFullYear(),monthText:"Month",dayText:"Day",yearText:"Year",slotOrder:["month","day","year"]},initialize:function(){this.callParent();this.on({scope:this,delegate:"> slot",slotpick:this.onSlotPick})},setValue:function(b,a){if(Ext.isDate(b)){b={day:b.getDate(),month:b.getMonth()+1,year:b.getFullYear()}}this.callParent([b,a])},getValue:function(){var h={},a,g,c,f,e=this.getItems().items,d=e.length,j,b;for(b=0;bf){e=m;m=f;f=e}for(d=m;d<=f;d++){g.push({text:d,value:d})}a=this.getDaysInMonth(1,new Date().getFullYear());for(d=0;d thumb",dragstart:"onThumbDragStart",drag:"onThumbDrag",dragend:"onThumbDragEnd"});this.on({painted:"refresh",resize:"refresh"})},factoryThumb:function(){return Ext.factory(this.getThumbConfig(),Ext.slider.Thumb)},getThumbs:function(){return this.innerItems},getThumb:function(a){if(typeof a!="number"){a=0}return this.innerItems[a]},refreshOffsetValueRatio:function(){var b=this.getMaxValue()-this.getMinValue(),a=this.elementWidth-this.thumbWidth;this.offsetValueRatio=a/b},refreshElementWidth:function(){this.elementWidth=this.element.dom.offsetWidth;this.thumbWidth=this.getThumb(0).getElementWidth()},refresh:function(){this.refreshElementWidth();this.refreshValue()},setActiveThumb:function(b){var a=this.activeThumb;if(a&&a!==b){a.setZIndex(null)}this.activeThumb=b;b.setZIndex(2);return this},onThumbDragStart:function(a,b){if(b.absDeltaX<=b.absDeltaY){return false}else{b.stopPropagation()}if(this.getAllowThumbsOverlapping()){this.setActiveThumb(a)}this.dragStartValue=this.getValue()[this.getThumbIndex(a)];this.fireEvent("dragstart",this,a,this.dragStartValue,b)},onThumbDrag:function(c,g,a){var d=this.getThumbIndex(c),f=this.offsetValueRatio,b=this.constrainValue(a/f);g.stopPropagation();this.setIndexValue(d,b);this.fireEvent("drag",this,c,this.getValue(),g);return false},setIndexValue:function(d,g,f){var c=this.getThumb(d),b=this.getValue(),e=this.offsetValueRatio,a=c.getDraggable();a.setOffset(g*e,null,f);b[d]=this.constrainValue(a.getOffset().x/e)},onThumbDragEnd:function(a,f){this.refreshThumbConstraints(a);var c=this.getThumbIndex(a),d=this.getValue()[c],b=this.dragStartValue;this.fireEvent("dragend",this,a,this.getValue(),f);if(b!==d){this.fireEvent("change",this,a,d,b)}},getThumbIndex:function(a){return this.getThumbs().indexOf(a)},refreshThumbConstraints:function(d){var b=this.getAllowThumbsOverlapping(),a=d.getDraggable().getOffset().x,c=this.getThumbs(),e=this.getThumbIndex(d),g=c[e-1],h=c[e+1],f=this.thumbWidth;if(g){g.getDraggable().addExtraConstraint({max:{x:a-((b)?0:f)}})}if(h){h.getDraggable().addExtraConstraint({min:{x:a+((b)?0:f)}})}},onTap:function(j){if(this.isDisabled()){return}var k=Ext.get(j.target);if(!k||k.hasCls("x-thumb")){return}var n=j.touch.point.x,h=this.element,c=h.getX(),d=n-c-(this.thumbWidth/2),o=this.constrainValue(d/this.offsetValueRatio),r=this.getValue(),q=Infinity,m=r.length,g,f,l,p,b,a;if(m===1){p=0}else{for(g=0;g=(a/2)){e+=(c>0)?a:-a}e=Math.max(d,e);e=Math.min(f,e);return e},setThumbsCount:function(e){var a=this.getThumbs(),f=a.length,c,d,b;if(f>e){for(c=0,d=f-e;c0,b=d.getMaxValueCls(),e=d.getMinValueCls();this.element.addCls(g?b:e);this.element.removeCls(g?e:b)}});Ext.define("Ext.field.Toggle",{extend:"Ext.field.Slider",xtype:"togglefield",alternateClassName:"Ext.form.Toggle",requires:["Ext.slider.Toggle"],config:{cls:"x-toggle-field"},proxyConfig:{minValueCls:"x-toggle-off",maxValueCls:"x-toggle-on"},applyComponent:function(a){return Ext.factory(a,Ext.slider.Toggle)},setValue:function(a){if(a===true){a=1}this.getComponent().setValue(a);return this},toggle:function(){var a=this.getValue();this.setValue((a==1)?0:1);return this}});Ext.define("Ext.tab.Tab",{extend:"Ext.Button",xtype:"tab",alternateClassName:"Ext.Tab",isTab:true,config:{baseCls:Ext.baseCSSPrefix+"tab",pressedCls:Ext.baseCSSPrefix+"tab-pressed",activeCls:Ext.baseCSSPrefix+"tab-active",active:false,title:" "},template:[{tag:"span",reference:"badgeElement",hidden:true},{tag:"span",className:Ext.baseCSSPrefix+"button-icon",reference:"iconElement",style:"visibility: hidden !important"},{tag:"span",reference:"textElement",hidden:true}],updateTitle:function(a){this.setText(a)},hideIconElement:function(){this.iconElement.dom.style.setProperty("visibility","hidden","!important")},showIconElement:function(){this.iconElement.dom.style.setProperty("visibility","visible","!important")},updateActive:function(c,b){var a=this.getActiveCls();if(c&&!b){this.element.addCls(a);this.fireEvent("activate",this)}else{if(b){this.element.removeCls(a);this.fireEvent("deactivate",this)}}}},function(){this.override({activate:function(){this.setActive(true)},deactivate:function(){this.setActive(false)}})});Ext.define("Ext.tab.Bar",{extend:"Ext.Toolbar",alternateClassName:"Ext.TabBar",xtype:"tabbar",requires:["Ext.tab.Tab"],config:{baseCls:Ext.baseCSSPrefix+"tabbar",defaultType:"tab",layout:{type:"hbox",align:"middle"}},eventedConfig:{activeTab:null},initialize:function(){var a=this;a.callParent();a.on({tap:"onTabTap",delegate:"> tab",scope:a})},onTabTap:function(a){this.setActiveTab(a)},applyActiveTab:function(a,c){if(!a&&a!==0){return}var b=this.parseActiveTab(a);if(!b){return}return b},doSetDocked:function(a){var c=this.getLayout(),b=a=="bottom"?"center":"left";if(c.isLayout){c.setPack(b)}else{c.pack=(c&&c.pack)?c.pack:b}},doSetActiveTab:function(b,a){if(b){b.setActive(true)}if(a){a.setActive(false)}},parseActiveTab:function(a){if(typeof a=="number"){return this.getInnerItems()[a]}else{if(typeof a=="string"){a=Ext.getCmp(a)}}return a}});Ext.define("Ext.tab.Panel",{extend:"Ext.Container",xtype:"tabpanel",alternateClassName:"Ext.TabPanel",requires:["Ext.tab.Bar"],config:{ui:"dark",tabBar:true,tabBarPosition:"top",layout:{type:"card",animation:{type:"slide",direction:"left"}},cls:Ext.baseCSSPrefix+"tabpanel"},delegateListeners:{delegate:"> component",centeredchange:"onItemCenteredChange",dockedchange:"onItemDockedChange",floatingchange:"onItemFloatingChange",disabledchange:"onItemDisabledChange"},initialize:function(){this.callParent();this.on({order:"before",activetabchange:"doTabChange",delegate:"> tabbar",scope:this})},applyScrollable:function(){return false},updateUi:function(a,b){this.callParent(arguments);if(this.initialized){this.getTabBar().setUi(a)}},doSetActiveItem:function(d,j){if(d){var f=this.getInnerItems(),g=f.indexOf(j),i=f.indexOf(d),e=g>i,c=this.getLayout().getAnimation(),b=this.getTabBar(),h=b.parseActiveTab(g),a=b.parseActiveTab(i);if(c&&c.setReverse){c.setReverse(e)}this.callParent(arguments);if(i!=-1){this.getTabBar().setActiveTab(i);if(h){h.setActive(false)}if(a){a.setActive(true)}}}},doTabChange:function(a,b){this.setActiveItem(a.indexOf(b))},applyTabBar:function(a){if(a===true){a={}}if(a){Ext.applyIf(a,{ui:this.getUi(),docked:this.getTabBarPosition()})}return Ext.factory(a,Ext.tab.Bar,this.getTabBar())},updateTabBar:function(a){if(a){this.add(a);this.setTabBarPosition(a.getDocked())}},updateTabBarPosition:function(b){var a=this.getTabBar();if(a){a.setDocked(b)}},onItemAdd:function(e){var k=this;if(!e.isInnerItem()){return k.callParent(arguments)}var c=k.getTabBar(),o=e.getInitialConfig(),d=o.tab||{},g=o.title,i=o.iconCls,j=o.hidden,n=o.disabled,p=o.badgeText,b=k.getInnerItems(),h=b.indexOf(e),l=c.getItems(),a=k.getInnerItems(),m=(l.length>=a.length)&&l.getAt(h),f;if(g&&!d.title){d.title=g}if(i&&!d.iconCls){d.iconCls=i}if(j&&!d.hidden){d.hidden=j}if(n&&!d.disabled){d.disabled=n}if(p&&!d.badgeText){d.badgeText=p}f=Ext.factory(d,Ext.tab.Tab,m);if(!m){c.insert(h,f)}e.tab=f;k.callParent(arguments)},onItemDisabledChange:function(a,b){if(a&&a.tab){a.tab.setDisabled(b)}},onItemRemove:function(b,a){this.getTabBar().remove(b.tab,this.getAutoDestroy());this.callParent(arguments)}},function(){});Ext.define("Ext.table.Cell",{extend:"Ext.Container",xtype:"tablecell",config:{baseCls:"x-table-cell"},getElementConfig:function(){var a=this.callParent();a.children.length=0;return a}});Ext.define("Ext.table.Row",{extend:"Ext.table.Cell",xtype:"tablerow",config:{baseCls:"x-table-row",defaultType:"tablecell"}});Ext.define("Ext.table.Table",{extend:"Ext.Container",requires:["Ext.table.Row"],xtype:"table",config:{baseCls:"x-table",defaultType:"tablerow"},cachedConfig:{fixedLayout:false},fixedLayoutCls:"x-table-fixed",updateFixedLayout:function(a){this.innerElement[a?"addCls":"removeCls"](this.fixedLayoutCls)}});Ext.define("Ext.viewport.Default",{extend:"Ext.Container",xtype:"viewport",PORTRAIT:"portrait",LANDSCAPE:"landscape",requires:["Ext.LoadMask"],config:{autoMaximize:false,autoBlurInput:true,preventPanning:true,preventZooming:true,autoRender:true,layout:"card",width:"100%",height:"100%"},isReady:false,isViewport:true,isMaximizing:false,id:"ext-viewport",isInputRegex:/^(input|textarea|select|a)$/i,focusedElement:null,fullscreenItemCls:Ext.baseCSSPrefix+"fullscreen",constructor:function(a){var b=Ext.Function.bind;this.doPreventPanning=b(this.doPreventPanning,this);this.doPreventZooming=b(this.doPreventZooming,this);this.doBlurInput=b(this.doBlurInput,this);this.maximizeOnEvents=["ready","orientationchange"];this.orientation=this.determineOrientation();this.windowWidth=this.getWindowWidth();this.windowHeight=this.getWindowHeight();this.windowOuterHeight=this.getWindowOuterHeight();if(!this.stretchHeights){this.stretchHeights={}}this.callParent([a]);if(this.supportsOrientation()){this.addWindowListener("orientationchange",b(this.onOrientationChange,this))}else{this.addWindowListener("resize",b(this.onResize,this))}document.addEventListener("focus",b(this.onElementFocus,this),true);document.addEventListener("blur",b(this.onElementBlur,this),true);Ext.onDocumentReady(this.onDomReady,this);this.on("ready",this.onReady,this,{single:true});this.getEventDispatcher().addListener("component","*","fullscreen","onItemFullscreenChange",this);return this},onDomReady:function(){this.isReady=true;this.updateSize();this.fireEvent("ready",this)},onReady:function(){if(this.getAutoRender()){this.render()}},onElementFocus:function(a){this.focusedElement=a.target},onElementBlur:function(){this.focusedElement=null},render:function(){if(!this.rendered){var a=Ext.getBody(),b=Ext.baseCSSPrefix,h=[],d=Ext.os,g=d.name.toLowerCase(),f=Ext.browser.name.toLowerCase(),e=d.version.getMajor(),c=this.getOrientation();this.renderTo(a);h.push(b+d.deviceType.toLowerCase());if(d.is.iPad){h.push(b+"ipad")}h.push(b+g);h.push(b+f);if(e){h.push(b+g+"-"+e)}if(d.is.BlackBerry){h.push(b+"bb")}if(Ext.browser.is.Standalone){h.push(b+"standalone")}h.push(b+c);a.addCls(h)}},applyAutoBlurInput:function(a){var b=(Ext.feature.has.Touch)?"touchstart":"mousedown";if(a){this.addWindowListener(b,this.doBlurInput,false)}else{this.removeWindowListener(b,this.doBlurInput,false)}return a},applyAutoMaximize:function(a){if(a){this.on("ready","doAutoMaximizeOnReady",this,{single:true});this.on("orientationchange","doAutoMaximizeOnOrientationChange",this)}else{this.un("ready","doAutoMaximizeOnReady",this);this.un("orientationchange","doAutoMaximizeOnOrientationChange",this)}return a},applyPreventPanning:function(a){if(a){this.addWindowListener("touchmove",this.doPreventPanning,false)}else{this.removeWindowListener("touchmove",this.doPreventPanning,false)}return a},applyPreventZooming:function(a){var b=(Ext.feature.has.Touch)?"touchstart":"mousedown";if(a){this.addWindowListener(b,this.doPreventZooming,false)}else{this.removeWindowListener(b,this.doPreventZooming,false)}return a},doAutoMaximizeOnReady:function(){var a=arguments[arguments.length-1];a.pause();this.isMaximizing=true;this.on("maximize",function(){this.isMaximizing=false;this.updateSize();a.resume();this.fireEvent("ready",this)},this,{single:true});this.maximize()},doAutoMaximizeOnOrientationChange:function(){var a=arguments[arguments.length-1],b=a.firingArguments;a.pause();this.isMaximizing=true;this.on("maximize",function(){this.isMaximizing=false;this.updateSize();b[1]=this.windowWidth;b[2]=this.windowHeight;a.resume()},this,{single:true});this.maximize()},doBlurInput:function(b){var a=b.target,c=this.focusedElement;if(c&&!this.isInputRegex.test(a.tagName)){delete this.focusedElement;c.blur()}},doPreventPanning:function(a){a.preventDefault()},doPreventZooming:function(b){if("button" in b&&b.button!==0){return}var a=b.target;if(a&&a.nodeType===1&&!this.isInputRegex.test(a.tagName)){b.preventDefault()}},addWindowListener:function(b,c,a){window.addEventListener(b,c,Boolean(a))},removeWindowListener:function(b,c,a){window.removeEventListener(b,c,Boolean(a))},doAddListener:function(a,d,c,b){if(a==="ready"&&this.isReady&&!this.isMaximizing){d.call(c);return this}this.mixins.observable.doAddListener.apply(this,arguments)},supportsOrientation:function(){return Ext.feature.has.Orientation},onResize:function(){var c=this.windowWidth,f=this.windowHeight,e=this.getWindowWidth(),a=this.getWindowHeight(),d=this.getOrientation(),b=this.determineOrientation();if((c!==e||f!==a)&&d!==b){this.fireOrientationChangeEvent(b,d)}},onOrientationChange:function(){var b=this.getOrientation(),a=this.determineOrientation();if(a!==b){this.fireOrientationChangeEvent(a,b)}},fireOrientationChangeEvent:function(b,c){var a=Ext.baseCSSPrefix;Ext.getBody().replaceCls(a+c,a+b);this.orientation=b;this.updateSize();this.fireEvent("orientationchange",this,b,this.windowWidth,this.windowHeight)},updateSize:function(b,a){this.windowWidth=b!==undefined?b:this.getWindowWidth();this.windowHeight=a!==undefined?a:this.getWindowHeight();return this},waitUntil:function(h,e,g,a,f){if(!a){a=50}if(!f){f=2000}var c=this,b=0;setTimeout(function d(){b+=a;if(h.call(c)===true){if(e){e.call(c)}}else{if(b>=f){if(g){g.call(c)}}else{setTimeout(d,a)}}},a)},maximize:function(){this.fireMaximizeEvent()},fireMaximizeEvent:function(){this.updateSize();this.fireEvent("maximize",this)},doSetHeight:function(a){Ext.getBody().setHeight(a);this.callParent(arguments)},doSetWidth:function(a){Ext.getBody().setWidth(a);this.callParent(arguments)},scrollToTop:function(){window.scrollTo(0,-1)},getWindowWidth:function(){return window.innerWidth},getWindowHeight:function(){return window.innerHeight},getWindowOuterHeight:function(){return window.outerHeight},getWindowOrientation:function(){return window.orientation},getOrientation:function(){return this.orientation},getSize:function(){return{width:this.windowWidth,height:this.windowHeight}},determineOrientation:function(){var b=this.PORTRAIT,a=this.LANDSCAPE;if(this.supportsOrientation()){if(this.getWindowOrientation()%180===0){return b}return a}else{if(this.getWindowHeight()>=this.getWindowWidth()){return b}return a}},onItemFullscreenChange:function(a){a.addCls(this.fullscreenItemCls);this.add(a)}});Ext.define("Ext.viewport.Android",{extend:"Ext.viewport.Default",constructor:function(){this.on("orientationchange","doFireOrientationChangeEvent",this,{prepend:true});this.on("orientationchange","hideKeyboardIfNeeded",this,{prepend:true});return this.callParent(arguments)},getDummyInput:function(){var a=this.dummyInput,c=this.focusedElement,b=Ext.fly(c).getPageBox();if(!a){this.dummyInput=a=document.createElement("input");a.style.position="absolute";a.style.opacity="0";document.body.appendChild(a)}a.style.left=b.left+"px";a.style.top=b.top+"px";a.style.display="";return a},doBlurInput:function(c){var b=c.target,d=this.focusedElement,a;if(d&&!this.isInputRegex.test(b.tagName)){a=this.getDummyInput();delete this.focusedElement;a.focus();setTimeout(function(){a.style.display="none"},100)}},hideKeyboardIfNeeded:function(){var a=arguments[arguments.length-1],b=this.focusedElement;if(b){delete this.focusedElement;a.pause();if(Ext.os.version.lt("4")){b.style.display="none"}else{b.blur()}setTimeout(function(){b.style.display="";a.resume()},1000)}},doFireOrientationChangeEvent:function(){var a=arguments[arguments.length-1];this.orientationChanging=true;a.pause();this.waitUntil(function(){return this.getWindowOuterHeight()!==this.windowOuterHeight},function(){this.windowOuterHeight=this.getWindowOuterHeight();this.updateSize();a.firingArguments[1]=this.windowWidth;a.firingArguments[2]=this.windowHeight;a.resume();this.orientationChanging=false},function(){});return this},applyAutoMaximize:function(a){this.callParent(arguments);this.on("add","fixSize",this,{single:true});if(!a){this.on("ready","fixSize",this,{single:true});this.onAfter("orientationchange","doFixSize",this)}else{this.un("ready","fixSize",this);this.unAfter("orientationchange","doFixSize",this)}},fixSize:function(){this.doFixSize()},doFixSize:function(){this.setHeight(this.getWindowHeight())},getActualWindowOuterHeight:function(){return Math.round(this.getWindowOuterHeight()/window.devicePixelRatio)},maximize:function(){var c=this.stretchHeights,b=this.orientation,a;a=c[b];if(!a){c[b]=a=this.getActualWindowOuterHeight()}if(!this.addressBarHeight){this.addressBarHeight=a-this.getWindowHeight()}this.setHeight(a);var d=Ext.Function.bind(this.isHeightMaximized,this,[a]);this.scrollToTop();this.waitUntil(d,this.fireMaximizeEvent,this.fireMaximizeEvent)},isHeightMaximized:function(a){this.scrollToTop();return this.getWindowHeight()===a}},function(){if(!Ext.os.is.Android){return}var a=Ext.os.version,b=Ext.browser.userAgent,c=/(htc|desire|incredible|ADR6300)/i.test(b)&&a.lt("2.3");if(c){this.override({constructor:function(d){if(!d){d={}}d.autoMaximize=false;this.watchDogTick=Ext.Function.bind(this.watchDogTick,this);setInterval(this.watchDogTick,1000);return this.callParent([d])},watchDogTick:function(){this.watchDogLastTick=Ext.Date.now()},doPreventPanning:function(){var e=Ext.Date.now(),f=this.watchDogLastTick,d=e-f;if(d>=2000){return}return this.callParent(arguments)},doPreventZooming:function(){var e=Ext.Date.now(),f=this.watchDogLastTick,d=e-f;if(d>=2000){return}return this.callParent(arguments)}})}if(a.match("2")){this.override({onReady:function(){this.addWindowListener("resize",Ext.Function.bind(this.onWindowResize,this));this.callParent(arguments)},scrollToTop:function(){document.body.scrollTop=100},onWindowResize:function(){var e=this.windowWidth,g=this.windowHeight,f=this.getWindowWidth(),d=this.getWindowHeight();if(this.getAutoMaximize()&&!this.isMaximizing&&!this.orientationChanging&&window.scrollY===0&&e===f&&d=g-this.addressBarHeight)||!this.focusedElement)){this.scrollToTop()}},fixSize:function(){var d=this.getOrientation(),f=window.outerHeight,g=window.outerWidth,e;if(d==="landscape"&&(f=g)){e=this.getActualWindowOuterHeight()}else{e=this.getWindowHeight()}this.waitUntil(function(){return e>this.getWindowHeight()},this.doFixSize,this.doFixSize,50,1000)}})}else{if(a.gtEq("3.1")){this.override({isHeightMaximized:function(d){this.scrollToTop();return this.getWindowHeight()===d-1}})}else{if(a.match("3")){this.override({isHeightMaximized:function(){this.scrollToTop();return true}})}}}if(a.gtEq("4")){this.override({doBlurInput:Ext.emptyFn})}});Ext.define("Ext.viewport.Ios",{extend:"Ext.viewport.Default",isFullscreen:function(){return this.isHomeScreen()},isHomeScreen:function(){return window.navigator.standalone===true},constructor:function(){this.callParent(arguments);if(this.getAutoMaximize()&&!this.isFullscreen()){this.addWindowListener("touchstart",Ext.Function.bind(this.onTouchStart,this))}},maximize:function(){if(this.isFullscreen()){return this.callParent()}var c=this.stretchHeights,b=this.orientation,d=this.getWindowHeight(),a=c[b];if(window.scrollY>0){this.scrollToTop();if(!a){c[b]=a=this.getWindowHeight()}this.setHeight(a);this.fireMaximizeEvent()}else{if(!a){a=this.getScreenHeight()}this.setHeight(a);this.waitUntil(function(){this.scrollToTop();return d!==this.getWindowHeight()},function(){if(!c[b]){a=c[b]=this.getWindowHeight();this.setHeight(a)}this.fireMaximizeEvent()},function(){a=c[b]=this.getWindowHeight();this.setHeight(a);this.fireMaximizeEvent()},50,1000)}},getScreenHeight:function(){return window.screen[this.orientation===this.PORTRAIT?"height":"width"]},onElementFocus:function(){if(this.getAutoMaximize()&&!this.isFullscreen()){clearTimeout(this.scrollToTopTimer)}this.callParent(arguments)},onElementBlur:function(){if(this.getAutoMaximize()&&!this.isFullscreen()){this.scrollToTopTimer=setTimeout(this.scrollToTop,500)}this.callParent(arguments)},onTouchStart:function(){if(this.focusedElement===null){this.scrollToTop()}},scrollToTop:function(){window.scrollTo(0,0)}},function(){if(!Ext.os.is.iOS){return}if(Ext.os.version.lt("3.2")){this.override({constructor:function(){var a=this.stretchHeights={};a[this.PORTRAIT]=416;a[this.LANDSCAPE]=268;return this.callOverridden(arguments)}})}if(Ext.os.version.lt("5")){this.override({fieldMaskClsTest:"-field-mask",doPreventZooming:function(b){var a=b.target;if(a&&a.nodeType===1&&!this.isInputRegex.test(a.tagName)&&a.className.indexOf(this.fieldMaskClsTest)==-1){b.preventDefault()}}})}if(Ext.os.is.iPad){this.override({isFullscreen:function(){return true}})}});Ext.define("Ext.viewport.Viewport",{requires:["Ext.viewport.Ios","Ext.viewport.Android"],constructor:function(b){var c=Ext.os.name,d,a;switch(c){case"Android":d="Android";break;case"iOS":d="Ios";break;default:d="Default"}a=Ext.create("Ext.viewport."+d,b);return a}});Ext.define("Ext.event.recognizer.Swipe",{extend:"Ext.event.recognizer.SingleTouch",handledEvents:["swipe"],inheritableStatics:{MAX_OFFSET_EXCEEDED:16,MAX_DURATION_EXCEEDED:17,DISTANCE_NOT_ENOUGH:18},config:{minDistance:80,maxOffset:35,maxDuration:1000},onTouchStart:function(a){if(this.callParent(arguments)===false){return false}var b=a.changedTouches[0];this.startTime=a.time;this.isHorizontal=true;this.isVertical=true;this.startX=b.pageX;this.startY=b.pageY},onTouchMove:function(f){var h=f.changedTouches[0],b=h.pageX,g=h.pageY,c=Math.abs(b-this.startX),a=Math.abs(g-this.startY),d=f.time;if(d-this.startTime>this.getMaxDuration()){return this.fail(this.self.MAX_DURATION_EXCEEDED)}if(this.isVertical&&c>this.getMaxOffset()){this.isVertical=false}if(this.isHorizontal&&a>this.getMaxOffset()){this.isHorizontal=false}if(!this.isHorizontal&&!this.isVertical){return this.fail(this.self.MAX_OFFSET_EXCEEDED)}},onTouchEnd:function(i){if(this.onTouchMove(i)===false){return false}var h=i.changedTouches[0],l=h.pageX,j=h.pageY,g=l-this.startX,f=j-this.startY,c=Math.abs(g),b=Math.abs(f),m=this.getMinDistance(),d=i.time-this.startTime,k,a;if(this.isVertical&&bc){return this.fail(this.self.MAX_DURATION_EXCEEDED)}if(a>b){return this.fail(this.self.MAX_OFFSET_EXCEEDED)}},onTouchEnd:function(f){if(this.onTouchMove(f)!==false){var i=f.changedTouches[0],a=i.pageX,b=a-this.startX,h=Math.abs(b),d=f.time-this.startTime,g=this.getMinDistance(),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π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 VP7)gCNetuhr~j#5=kRIo{{a)gMvwpi literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-best.png b/apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-best.png new file mode 100644 index 0000000000000000000000000000000000000000..623885a022926da4d55e2a8672462d89e5b19d99 GIT binary patch literal 932 zcmV;V16%xwP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2iOG+ z3JN#>O3Zlx00SgRL_t(|+SQiNOB7)o#-DebRnwq4q?ZVymQMWzU1|+NJL`WCT}s1) z6-!^4{zlHb3no;ZaUAEhW!V7pBxFpcj!8C66A9BC2?_wq zwoxjTzzjxAk3sUzGMt>XiuKty00RU(o6X`!u?XNd5I8z8fK)1_gdq6`A=Pc5uN#mh zvfu#ngNA^Qj*Y=E46(Mnv=q68N|WRAa|c(?8#sH?fKYeh0j%iAHb>U`owfWngl-g=;C3 z8emb5fMI~nJd;kN)a=6HUI&ANgD_~_g)#3egY3>n`Z$)a^gz*G1EhwA#PiLU0~k5o z6tf2^3^j}rLI6#X8*st?4X99Isdx?Ok|5Oe z0Ks5=E#4)>ZUYE{`vr-A1nSq!ZNTt>#|jdD2h>Z*0e|?u-T`?D^(yzR0rd}xdI^Kz zfAJ2eM<5yqhwCrroC~W84WJ)Gy#-x5Tmg4F9XO67OtV-Mo9Z&7H2{bPG?*W}TrQ(n zED)4K{LmBbzha35wktbT0M+0Co_gyR#~vhhS|}8dOeVFXXti3%<#P7J*_jytD}a;{ zR&To#R=up9{73jkexoxtKldP$dAR_f77#!JYBsP{;vk7<&EiVkUQoN;7H95-=Qs0w zaq-#X`MLQg5*`r1Mf7(A*OzR3uW(Gfu+ZPb0_!IjxvjuAH}lA3(hIZq?$2s)J%Fz9 zp#-cpFma(9iuC#gkQz{Sp3bD7-n?;ZO2Wf6Y}+<(G#b3wZ1Ugp%&RJ=7Yb9&!UW<3 z6{cBymM$P)S@|U9^{?yBox9VIKt)0-UI6l*1FWvD^0l=!YkXpS8bBXnXqa9oVG`&< zH9O>nW%J_C5`XvpLv?g)bTSH@LDea867jV|{zz`%f6*_Jdo;uJuyNzYy;r~QyY}PMjn}7dy*+d0?74I2&!4|=>C&YuSFT*UcI`S4 z+_-+@#too*ZruW+TX*l?xeo*{e>`~g^Wn2MPhP%%_U!rd7cXACeEH(#D-d}7`t_SP zuit%m0|am1zI_J<@87@s^y57cd;o)wA3uEg^$`d@fx%}m_yPuBzkd1l{VNcBgMjbf zzC*x|?>~Ng|M}|&5c~v#UtsVX4E{jCUl8~Q0{{R2mk};$2Zp{_NswPK11A@^jEa@D zjjd-sRHYdAWDL@3gyW8df=G@ot9|?C zf!eAtkyG3^J}sH^#zFBzrJMJT-GaLgAon{&{! zkae%af}~HaQyGM|T3wmL>b4-qCE3G;CFU!KOkN%PLxDRs=ca8*e{i9oKic_JY}lQW zKA!Df)=F>Ni*k2{?>W%2S?Zq=bCA{}t1YclZ|l5@cxO=Q$oKSBiKWZyWeY4$oIP6< zo8r07@&i-bmA0#YGFN%8Rg#?Nf6BN@TJ7!#+DLctaa(QRopUT4lre4dJ{;IEK_BSt$TVF7(6O@ZQUHx3v IIVCg!0H;O`R{#J2 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-width.png b/apps/files_odfviewer/src/webodf/programs/touchui/zoom-fit-width.png new file mode 100644 index 0000000000000000000000000000000000000000..5bd06de6979a73e181830b111c019f62371d1dbe GIT binary patch literal 934 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|I14-?i-C%- zgD|6$#_S59AbW|YuPgfvRvs=+p46POc|bkQ0X`wFKq>qnG%PeEBsecWFDEyrwyvh5 zv;Ew~ONURKx_R^F?K`*c+`S{5_gvQMMpFe-$(xppRu3Wix?b>x9xN-f) zjT=D6+`0usx9&WCedpPiyLa#0d;0c15WM*I=-HcR&z?Vf_2K!87cXAEeDU(t%U7>n zzWwwH2wuN_{pQW*AK!oc`2O?P4+vRx(bt)hFmF2_|VbE-@aQV~0Jv{sOlDP!7$*4!>d)`)38Je(((G;BPif61r8 z@ucSswlskQlYWlUc&SNXx`9k%BXM-!u0 z)btg{nl4=EuA_?d}_ms4{P?n_P*DDDbwP58`IfOljN5_ z-XrF7_1#4eTYFFUdEEO$Q5TIRE#bLjII&mDG~IPwPB7+TDZ0FN;K_ q)T(e58%t(?`K;zSXTfBrfA;hLXB0=6^= 0 + Code = Code + CodeIncrement + if BitLength(i) <> LastBitLength then + LastBitLength=BitLength(i) + CodeIncrement = 1 shifted left (16 - LastBitLength) + ShannonCode(i) = Code + i <- i - 1 + end loop + +3) Reverse the order of all the bits in the above ShannonCode() + vector, so that the most significant bit becomes the least + significant bit. For example, the value 0x1234 (hex) would + become 0x2C48 (hex). + +4) Restore the order of Shannon-Fano codes as originally stored + within the file. + +Example: + + This example will show the encoding of a Shannon-Fano tree + of size 8. Notice that the actual Shannon-Fano trees used + for Imploding are either 64 or 256 entries in size. + +Example: 0x02, 0x42, 0x01, 0x13 + + The first byte indicates 3 values in this table. Decoding the + bytes: + 0x42 = 5 codes of 3 bits long + 0x01 = 1 code of 2 bits long + 0x13 = 2 codes of 4 bits long + + This would generate the original bit length array of: + (3, 3, 3, 3, 3, 2, 4, 4) + + There are 8 codes in this table for the values 0 thru 7. Using + the algorithm to obtain the Shannon-Fano codes produces: + + Reversed Order Original +Val Sorted Constructed Code Value Restored Length +--- ------ ----------------- -------- -------- ------ +0: 2 1100000000000000 11 101 3 +1: 3 1010000000000000 101 001 3 +2: 3 1000000000000000 001 110 3 +3: 3 0110000000000000 110 010 3 +4: 3 0100000000000000 010 100 3 +5: 3 0010000000000000 100 11 2 +6: 4 0001000000000000 1000 1000 4 +7: 4 0000000000000000 0000 0000 4 + +The values in the Val, Order Restored and Original Length columns +now represent the Shannon-Fano encoding tree that can be used for +decoding the Shannon-Fano encoded data. How to parse the +variable length Shannon-Fano values from the data stream is beyond +the scope of this document. (See the references listed at the end of +this document for more information.) However, traditional decoding +schemes used for Huffman variable length decoding, such as the +Greenlaw algorithm, can be successfully applied. + +The compressed data stream begins immediately after the +compressed Shannon-Fano data. The compressed data stream can be +interpreted as follows: + +loop until done + read 1 bit from input stream. + + if this bit is non-zero then (encoded data is literal data) + if Literal Shannon-Fano tree is present + read and decode character using Literal Shannon-Fano tree. + otherwise + read 8 bits from input stream. + copy character to the output stream. + otherwise (encoded data is sliding dictionary match) + if 8K dictionary size + read 7 bits for offset Distance (lower 7 bits of offset). + otherwise + read 6 bits for offset Distance (lower 6 bits of offset). + + using the Distance Shannon-Fano tree, read and decode the + upper 6 bits of the Distance value. + + using the Length Shannon-Fano tree, read and decode + the Length value. + + Length <- Length + Minimum Match Length + + if Length = 63 + Minimum Match Length + read 8 bits from the input stream, + add this value to Length. + + move backwards Distance+1 bytes in the output stream, and + copy Length characters from this position to the output + stream. (if this position is before the start of the output + stream, then assume that all the data before the start of + the output stream is filled with zeros). +end loop + +Tokenizing - Method 7 +--------------------- + +This method is not used by PKZIP. + +Deflating - Method 8 +-------------------- + +The Deflate algorithm is similar to the Implode algorithm using +a sliding dictionary of up to 32K with secondary compression +from Huffman/Shannon-Fano codes. + +The compressed data is stored in blocks with a header describing +the block and the Huffman codes used in the data block. The header +format is as follows: + + Bit 0: Last Block bit This bit is set to 1 if this is the last + compressed block in the data. + Bits 1-2: Block type + 00 (0) - Block is stored - All stored data is byte aligned. + Skip bits until next byte, then next word = block + length, followed by the ones compliment of the block + length word. Remaining data in block is the stored + data. + + 01 (1) - Use fixed Huffman codes for literal and distance codes. + Lit Code Bits Dist Code Bits + --------- ---- --------- ---- + 0 - 143 8 0 - 31 5 + 144 - 255 9 + 256 - 279 7 + 280 - 287 8 + + Literal codes 286-287 and distance codes 30-31 are + never used but participate in the huffman construction. + + 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes) + + 11 (3) - Reserved - Flag a "Error in compressed data" if seen. + +Expanding Huffman Codes +----------------------- +If the data block is stored with dynamic Huffman codes, the Huffman +codes are sent in the following compressed format: + + 5 Bits: # of Literal codes sent - 256 (256 - 286) + All other codes are never sent. + 5 Bits: # of Dist codes - 1 (1 - 32) + 4 Bits: # of Bit Length codes - 3 (3 - 19) + +The Huffman codes are sent as bit lengths and the codes are built as +described in the implode algorithm. The bit lengths themselves are +compressed with Huffman codes. There are 19 bit length codes: + + 0 - 15: Represent bit lengths of 0 - 15 + 16: Copy the previous bit length 3 - 6 times. + The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6) + Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will + expand to 12 bit lengths of 8 (1 + 6 + 5) + 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length) + 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length) + +The lengths of the bit length codes are sent packed 3 bits per value +(0 - 7) in the following order: + + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + +The Huffman codes should be built as described in the Implode algorithm +except codes are assigned starting at the shortest bit length, i.e. the +shortest code should be all 0's rather than all 1's. Also, codes with +a bit length of zero do not participate in the tree construction. The +codes are then used to decode the bit lengths for the literal and +distance tables. + +The bit lengths for the literal tables are sent first with the number +of entries sent described by the 5 bits sent earlier. There are up +to 286 literal characters; the first 256 represent the respective 8 +bit character, code 256 represents the End-Of-Block code, the remaining +29 codes represent copy lengths of 3 thru 258. There are up to 30 +distance codes representing distances from 1 thru 32k as described +below. + + Length Codes + ------------ + Extra Extra Extra Extra + Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- --------- + 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162 + 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194 + 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226 + 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257 + 261 0 7 269 2 19-22 277 4 67-82 285 0 258 + 262 0 8 270 2 23-26 278 4 83-98 + 263 0 9 271 2 27-30 279 4 99-114 + 264 0 10 272 2 31-34 280 4 115-130 + + Distance Codes + -------------- + Extra Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- -------- + 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144 + 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192 + 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288 + 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384 + 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576 + 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768 + 6 2 9-12 14 6 129-192 22 10 2049-3072 + 7 2 13-16 15 6 193-256 23 10 3073-4096 + +The compressed data stream begins immediately after the +compressed header data. The compressed data stream can be +interpreted as follows: + +do + read header from input stream. + + if stored block + skip bits until byte aligned + read count and 1's compliment of count + copy count bytes data block + otherwise + loop until end of block code sent + decode literal character from input stream + if literal < 256 + copy character to the output stream + otherwise + if literal = end of block + break from loop + otherwise + decode distance from input stream + + move backwards distance bytes in the output stream, and + copy length characters from this position to the output + stream. + end loop +while not last block + +if data descriptor exists + skip bits until byte aligned + read crc and sizes +endif + +Enhanced Deflating - Method 9 +----------------------------- + +The Enhanced Deflating algorithm is similar to Deflate but +uses a sliding dictionary of up to 64K. Deflate64(tm) is supported +by the Deflate extractor. + +BZIP2 - Method 12 +----------------- + +BZIP2 is an open-source data compression algorithm developed by +Julian Seward. Information and source code for this algorithm +can be found on the internet. + +LZMA - Method 14 (EFS) +---------------------- + +LZMA is a block-oriented, general purpose data compression algorithm +developed and maintained by Igor Pavlov. It is a derivative of LZ77 +that utilizes Markov chains and a range coder. Information and +source code for this algorithm can be found on the internet. Consult +with the author of this algorithm for information on terms or +restrictions on use. + +Support for LZMA within the ZIP format is defined as follows: + +The Compression method field within the ZIP Local and Central +Header records will be set to the value 14 to indicate data was +compressed using LZMA. + +The Version needed to extract field within the ZIP Local and +Central Header records will be set to 6.3 to indicate the +minimum ZIP format version supporting this feature. + +File data compressed using the LZMA algorithm must be placed +immediately following the Local Header for the file. If a +standard ZIP encryption header is required, it will follow +the Local Header and will precede the LZMA compressed file +data segment. The location of LZMA compressed data segment +within the ZIP format will be as shown: + + [local header file 1] + [encryption header file 1] + [LZMA compressed data segment for file 1] + [data descriptor 1] + [local header file 2] + +The encryption header and data descriptor records may +be conditionally present. The LZMA Compressed Data Segment +will consist of an LZMA Properties Header followed by the +LZMA Compressed Data as shown: + + [LZMA properties header for file 1] + [LZMA compressed data for file 1] + +The LZMA Compressed Data will be stored as provided by the +LZMA compression library. Compressed size, uncompressed +size and other file characteristics about the file being +compressed must be stored in standard ZIP storage format. + +The LZMA Properties Header will store specific data required to +decompress the LZMA compressed Data. This data is set by the +LZMA compression engine using the function WriteCoderProperties() +as documented within the LZMA SDK. + +Storage fields for the property information within the LZMA +Properties Header are as follows: + + LZMA Version Information 2 bytes + LZMA Properties Size 2 bytes + LZMA Properties Data variable, defined by "LZMA Properties Size" + +LZMA Version Information - this field identifies which version of + the LZMA SDK was used to compress a file. The first byte will + store the major version number of the LZMA SDK and the second + byte will store the minor number. + +LZMA Properties Size - this field defines the size of the remaining + property data. Typically this size should be determined by the + version of the SDK. This size field is included as a convenience + and to help avoid any ambiguity should it arise in the future due + to changes in this compression algorithm. + +LZMA Property Data - this variable sized field records the required + values for the decompressor as defined by the LZMA SDK. The + data stored in this field should be obtained using the + WriteCoderProperties() in the version of the SDK defined by + the "LZMA Version Information" field. + +The layout of the "LZMA Properties Data" field is a function of the +LZMA compression algorithm. It is possible that this layout may be +changed by the author over time. The data layout in version 4.32 +of the LZMA SDK defines a 5 byte array that uses 4 bytes to store +the dictionary size in little-endian order. This is preceded by a +single packed byte as the first element of the array that contains +the following fields: + + PosStateBits + LiteralPosStateBits + LiteralContextBits + +Refer to the LZMA documentation for a more detailed explanation of +these fields. + +Data compressed with method 14, LZMA, may include an end-of-stream +(EOS) marker ending the compressed data stream. This marker is not +required, but its use is highly recommended to facilitate processing +and implementers should include the EOS marker whenever possible. +When the EOS marker is used, general purpose bit 1 must be set. If +general purpose bit 1 is not set, the EOS marker is not present. + +WavPack - Method 97 +------------------- + +Information describing the use of compression method 97 is +provided by WinZIP International, LLC. This method relies on the +open source WavPack audio compression utility developed by David Bryant. +Information on WavPack is available at www.wavpack.com. Please consult +with the author of this algorithm for information on terms and +restrictions on use. + +WavPack data for a file begins immediately after the end of the +local header data. This data is the output from WavPack compression +routines. Within the ZIP file, the use of WavPack compression is +indicated by setting the compression method field to a value of 97 +in both the local header and the central directory header. The Version +needed to extract and version made by fields use the same values as are +used for data compressed using the Deflate algorithm. + +An implementation note for storing digital sample data when using +WavPack compression within ZIP files is that all of the bytes of +the sample data should be compressed. This includes any unused +bits up to the byte boundary. An example is a 2 byte sample that +uses only 12 bits for the sample data with 4 unused bits. If only +12 bits are passed as the sample size to the WavPack routines, the 4 +unused bits will be set to 0 on extraction regardless of their original +state. To avoid this, the full 16 bits of the sample data size +should be provided. + +PPMd - Method 98 +---------------- + +PPMd is a data compression algorithm developed by Dmitry Shkarin +which includes a carryless rangecoder developed by Dmitry Subbotin. +This algorithm is based on predictive phrase matching on multiple +order contexts. Information and source code for this algorithm +can be found on the internet. Consult with the author of this +algorithm for information on terms or restrictions on use. + +Support for PPMd within the ZIP format currently is provided only +for version I, revision 1 of the algorithm. Storage requirements +for using this algorithm are as follows: + +Parameters needed to control the algorithm are stored in the two +bytes immediately preceding the compressed data. These bytes are +used to store the following fields: + +Model order - sets the maximum model order, default is 8, possible + values are from 2 to 16 inclusive + +Sub-allocator size - sets the size of sub-allocator in MB, default is 50, + possible values are from 1MB to 256MB inclusive + +Model restoration method - sets the method used to restart context + model at memory insufficiency, values are: + + 0 - restarts model from scratch - default + 1 - cut off model - decreases performance by as much as 2x + 2 - freeze context tree - not recommended + +An example for packing these fields into the 2 byte storage field is +illustrated below. These values are stored in Intel low-byte/high-byte +order. + +wPPMd = (Model order - 1) + + ((Sub-allocator size - 1) << 4) + + (Model restoration method << 12) + + +VII. Traditional PKWARE Encryption +---------------------------------- + +The following information discusses the decryption steps +required to support traditional PKWARE encryption. This +form of encryption is considered weak by today's standards +and its use is recommended only for situations with +low security needs or for compatibility with older .ZIP +applications. + +Decryption +---------- + +PKWARE is grateful to Mr. Roger Schlafly for his expert contribution +towards the development of PKWARE's traditional encryption. + +PKZIP encrypts the compressed data stream. Encrypted files must +be decrypted before they can be extracted. + +Each encrypted file has an extra 12 bytes stored at the start of +the data area defining the encryption header for that file. The +encryption header is originally set to random values, and then +itself encrypted, using three, 32-bit keys. The key values are +initialized using the supplied encryption password. After each byte +is encrypted, the keys are then updated using pseudo-random number +generation techniques in combination with the same CRC-32 algorithm +used in PKZIP and described elsewhere in this document. + +The following is the basic steps required to decrypt a file: + +1) Initialize the three 32-bit keys with the password. +2) Read and decrypt the 12-byte encryption header, further + initializing the encryption keys. +3) Read and decrypt the compressed data stream using the + encryption keys. + +Step 1 - Initializing the encryption keys +----------------------------------------- + +Key(0) <- 305419896 +Key(1) <- 591751049 +Key(2) <- 878082192 + +loop for i <- 0 to length(password)-1 + update_keys(password(i)) +end loop + +Where update_keys() is defined as: + +update_keys(char): + Key(0) <- crc32(key(0),char) + Key(1) <- Key(1) + (Key(0) & 000000ffH) + Key(1) <- Key(1) * 134775813 + 1 + Key(2) <- crc32(key(2),key(1) >> 24) +end update_keys + +Where crc32(old_crc,char) is a routine that given a CRC value and a +character, returns an updated CRC value after applying the CRC-32 +algorithm described elsewhere in this document. + +Step 2 - Decrypting the encryption header +----------------------------------------- + +The purpose of this step is to further initialize the encryption +keys, based on random data, to render a plaintext attack on the +data ineffective. + +Read the 12-byte encryption header into Buffer, in locations +Buffer(0) thru Buffer(11). + +loop for i <- 0 to 11 + C <- buffer(i) ^ decrypt_byte() + update_keys(C) + buffer(i) <- C +end loop + +Where decrypt_byte() is defined as: + +unsigned char decrypt_byte() + local unsigned short temp + temp <- Key(2) | 2 + decrypt_byte <- (temp * (temp ^ 1)) >> 8 +end decrypt_byte + +After the header is decrypted, the last 1 or 2 bytes in Buffer +should be the high-order word/byte of the CRC for the file being +decrypted, stored in Intel low-byte/high-byte order. Versions of +PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is +used on versions after 2.0. This can be used to test if the password +supplied is correct or not. + +Step 3 - Decrypting the compressed data stream +---------------------------------------------- + +The compressed data stream can be decrypted as follows: + +loop until done + read a character into C + Temp <- C ^ decrypt_byte() + update_keys(temp) + output Temp +end loop + + +VIII. Strong Encryption Specification +------------------------------------- + +The Strong Encryption technology defined in this specification is +covered under a pending patent application. The use or implementation +in a product of certain technological aspects set forth in the current +APPNOTE, including those with regard to strong encryption, patching, +or extended tape operations requires a license from PKWARE. Portions +of this Strong Encryption technology are available for use at no charge. +Contact PKWARE for licensing terms and conditions. Refer to section II +of this APPNOTE (Contacting PKWARE) for information on how to +contact PKWARE. + +Version 5.x of this specification introduced support for strong +encryption algorithms. These algorithms can be used with either +a password or an X.509v3 digital certificate to encrypt each file. +This format specification supports either password or certificate +based encryption to meet the security needs of today, to enable +interoperability between users within both PKI and non-PKI +environments, and to ensure interoperability between different +computing platforms that are running a ZIP program. + +Password based encryption is the most common form of encryption +people are familiar with. However, inherent weaknesses with +passwords (e.g. susceptibility to dictionary/brute force attack) +as well as password management and support issues make certificate +based encryption a more secure and scalable option. Industry +efforts and support are defining and moving towards more advanced +security solutions built around X.509v3 digital certificates and +Public Key Infrastructures(PKI) because of the greater scalability, +administrative options, and more robust security over traditional +password based encryption. + +Most standard encryption algorithms are supported with this +specification. Reference implementations for many of these +algorithms are available from either commercial or open source +distributors. Readily available cryptographic toolkits make +implementation of the encryption features straight-forward. +This document is not intended to provide a treatise on data +encryption principles or theory. Its purpose is to document the +data structures required for implementing interoperable data +encryption within the .ZIP format. It is strongly recommended that +you have a good understanding of data encryption before reading +further. + +The algorithms introduced in Version 5.0 of this specification +include: + + RC2 40 bit, 64 bit, and 128 bit + RC4 40 bit, 64 bit, and 128 bit + DES + 3DES 112 bit and 168 bit + +Version 5.1 adds support for the following: + + AES 128 bit, 192 bit, and 256 bit + + +Version 6.1 introduces encryption data changes to support +interoperability with Smartcard and USB Token certificate storage +methods which do not support the OAEP strengthening standard. + +Version 6.2 introduces support for encrypting metadata by compressing +and encrypting the central directory data structure to reduce information +leakage. Information leakage can occur in legacy ZIP applications +through exposure of information about a file even though that file is +stored encrypted. The information exposed consists of file +characteristics stored within the records and fields defined by this +specification. This includes data such as a files name, its original +size, timestamp and CRC32 value. + +Version 6.3 introduces support for encrypting data using the Blowfish +and Twofish algorithms. These are symmetric block ciphers developed +by Bruce Schneier. Blowfish supports using a variable length key from +32 to 448 bits. Block size is 64 bits. Implementations should use 16 +rounds and the only mode supported within ZIP files is CBC. Twofish +supports key sizes 128, 192 and 256 bits. Block size is 128 bits. +Implementations should use 16 rounds and the only mode supported within +ZIP files is CBC. Information and source code for both Blowfish and +Twofish algorithms can be found on the internet. Consult with the author +of these algorithms for information on terms or restrictions on use. + +Central Directory Encryption provides greater protection against +information leakage by encrypting the Central Directory structure and +by masking key values that are replicated in the unencrypted Local +Header. ZIP compatible programs that cannot interpret an encrypted +Central Directory structure cannot rely on the data in the corresponding +Local Header for decompression information. + +Extra Field records that may contain information about a file that should +not be exposed should not be stored in the Local Header and should only +be written to the Central Directory where they can be encrypted. This +design currently does not support streaming. Information in the End of +Central Directory record, the Zip64 End of Central Directory Locator, +and the Zip64 End of Central Directory records are not encrypted. Access +to view data on files within a ZIP file with an encrypted Central Directory +requires the appropriate password or private key for decryption prior to +viewing any files, or any information about the files, in the archive. + +Older ZIP compatible programs not familiar with the Central Directory +Encryption feature will no longer be able to recognize the Central +Directory and may assume the ZIP file is corrupt. Programs that +attempt streaming access using Local Headers will see invalid +information for each file. Central Directory Encryption need not be +used for every ZIP file. Its use is recommended for greater security. +ZIP files not using Central Directory Encryption should operate as +in the past. + +This strong encryption feature specification is intended to provide for +scalable, cross-platform encryption needs ranging from simple password +encryption to authenticated public/private key encryption. + +Encryption provides data confidentiality and privacy. It is +recommended that you combine X.509 digital signing with encryption +to add authentication and non-repudiation. + + +Single Password Symmetric Encryption Method: +------------------------------------------- + +The Single Password Symmetric Encryption Method using strong +encryption algorithms operates similarly to the traditional +PKWARE encryption defined in this format. Additional data +structures are added to support the processing needs of the +strong algorithms. + +The Strong Encryption data structures are: + +1. General Purpose Bits - Bits 0 and 6 of the General Purpose bit +flag in both local and central header records. Both bits set +indicates strong encryption. Bit 13, when set indicates the Central +Directory is encrypted and that selected fields in the Local Header +are masked to hide their actual value. + + +2. Extra Field 0x0017 in central header only. + + Fields to consider in this record are: + + Format - the data format identifier for this record. The only + value allowed at this time is the integer value 2. + + AlgId - integer identifier of the encryption algorithm from the + following range + + 0x6601 - DES + 0x6602 - RC2 (version needed to extract < 5.2) + 0x6603 - 3DES 168 + 0x6609 - 3DES 112 + 0x660E - AES 128 + 0x660F - AES 192 + 0x6610 - AES 256 + 0x6702 - RC2 (version needed to extract >= 5.2) + 0x6720 - Blowfish + 0x6721 - Twofish + 0x6801 - RC4 + 0xFFFF - Unknown algorithm + + Bitlen - Explicit bit length of key + + 32 - 448 bits + + Flags - Processing flags needed for decryption + + 0x0001 - Password is required to decrypt + 0x0002 - Certificates only + 0x0003 - Password or certificate required to decrypt + + Values > 0x0003 reserved for certificate processing + + +3. Decryption header record preceding compressed file data. + + -Decryption Header: + + Value Size Description + ----- ---- ----------- + IVSize 2 bytes Size of initialization vector (IV) + IVData IVSize Initialization vector for this file + Size 4 bytes Size of remaining decryption header data + Format 2 bytes Format definition for this record + AlgID 2 bytes Encryption algorithm identifier + Bitlen 2 bytes Bit length of encryption key + Flags 2 bytes Processing flags + ErdSize 2 bytes Size of Encrypted Random Data + ErdData ErdSize Encrypted Random Data + Reserved1 4 bytes Reserved certificate processing data + Reserved2 (var) Reserved for certificate processing data + VSize 2 bytes Size of password validation data + VData VSize-4 Password validation data + VCRC32 4 bytes Standard ZIP CRC32 of password validation data + + IVData - The size of the IV should match the algorithm block size. + The IVData can be completely random data. If the size of + the randomly generated data does not match the block size + it should be complemented with zero's or truncated as + necessary. If IVSize is 0,then IV = CRC32 + Uncompressed + File Size (as a 64 bit little-endian, unsigned integer value). + + Format - the data format identifier for this record. The only + value allowed at this time is the integer value 3. + + AlgId - integer identifier of the encryption algorithm from the + following range + + 0x6601 - DES + 0x6602 - RC2 (version needed to extract < 5.2) + 0x6603 - 3DES 168 + 0x6609 - 3DES 112 + 0x660E - AES 128 + 0x660F - AES 192 + 0x6610 - AES 256 + 0x6702 - RC2 (version needed to extract >= 5.2) + 0x6720 - Blowfish + 0x6721 - Twofish + 0x6801 - RC4 + 0xFFFF - Unknown algorithm + + Bitlen - Explicit bit length of key + + 32 - 448 bits + + Flags - Processing flags needed for decryption + + 0x0001 - Password is required to decrypt + 0x0002 - Certificates only + 0x0003 - Password or certificate required to decrypt + + Values > 0x0003 reserved for certificate processing + + ErdData - Encrypted random data is used to store random data that + is used to generate a file session key for encrypting + each file. SHA1 is used to calculate hash data used to + derive keys. File session keys are derived from a master + session key generated from the user-supplied password. + If the Flags field in the decryption header contains + the value 0x4000, then the ErdData field must be + decrypted using 3DES. If the value 0x4000 is not set, + then the ErdData field must be decrypted using AlgId. + + + Reserved1 - Reserved for certificate processing, if value is + zero, then Reserved2 data is absent. See the explanation + under the Certificate Processing Method for details on + this data structure. + + Reserved2 - If present, the size of the Reserved2 data structure + is located by skipping the first 4 bytes of this field + and using the next 2 bytes as the remaining size. See + the explanation under the Certificate Processing Method + for details on this data structure. + + VSize - This size value will always include the 4 bytes of the + VCRC32 data and will be greater than 4 bytes. + + VData - Random data for password validation. This data is VSize + in length and VSize must be a multiple of the encryption + block size. VCRC32 is a checksum value of VData. + VData and VCRC32 are stored encrypted and start the + stream of encrypted data for a file. + + +4. Useful Tips + +Strong Encryption is always applied to a file after compression. The +block oriented algorithms all operate in Cypher Block Chaining (CBC) +mode. The block size used for AES encryption is 16. All other block +algorithms use a block size of 8. Two ID's are defined for RC2 to +account for a discrepancy found in the implementation of the RC2 +algorithm in the cryptographic library on Windows XP SP1 and all +earlier versions of Windows. It is recommended that zero length files +not be encrypted, however programs should be prepared to extract them +if they are found within a ZIP file. + +A pseudo-code representation of the encryption process is as follows: + +Password = GetUserPassword() +MasterSessionKey = DeriveKey(SHA1(Password)) +RD = CryptographicStrengthRandomData() +For Each File + IV = CryptographicStrengthRandomData() + VData = CryptographicStrengthRandomData() + VCRC32 = CRC32(VData) + FileSessionKey = DeriveKey(SHA1(IV + RD) + ErdData = Encrypt(RD,MasterSessionKey,IV) + Encrypt(VData + VCRC32 + FileData, FileSessionKey,IV) +Done + +The function names and parameter requirements will depend on +the choice of the cryptographic toolkit selected. Almost any +toolkit supporting the reference implementations for each +algorithm can be used. The RSA BSAFE(r), OpenSSL, and Microsoft +CryptoAPI libraries are all known to work well. + + +Single Password - Central Directory Encryption: +----------------------------------------------- + +Central Directory Encryption is achieved within the .ZIP format by +encrypting the Central Directory structure. This encapsulates the metadata +most often used for processing .ZIP files. Additional metadata is stored for +redundancy in the Local Header for each file. The process of concealing +metadata by encrypting the Central Directory does not protect the data within +the Local Header. To avoid information leakage from the exposed metadata +in the Local Header, the fields containing information about a file are masked. + +Local Header: + +Masking replaces the true content of the fields for a file in the Local +Header with false information. When masked, the Local Header is not +suitable for streaming access and the options for data recovery of damaged +archives is reduced. Extra Data fields that may contain confidential +data should not be stored within the Local Header. The value set into +the Version needed to extract field should be the correct value needed to +extract the file without regard to Central Directory Encryption. The fields +within the Local Header targeted for masking when the Central Directory is +encrypted are: + + Field Name Mask Value + ------------------ --------------------------- + compression method 0 + last mod file time 0 + last mod file date 0 + crc-32 0 + compressed size 0 + uncompressed size 0 + file name (variable size) Base 16 value from the + range 1 - 0xFFFFFFFFFFFFFFFF + represented as a string whose + size will be set into the + file name length field + +The Base 16 value assigned as a masked file name is simply a sequentially +incremented value for each file starting with 1 for the first file. +Modifications to a ZIP file may cause different values to be stored for +each file. For compatibility, the file name field in the Local Header +should never be left blank. As of Version 6.2 of this specification, +the Compression Method and Compressed Size fields are not yet masked. +Fields having a value of 0xFFFF or 0xFFFFFFFF for the ZIP64 format +should not be masked. + +Encrypting the Central Directory: + +Encryption of the Central Directory does not include encryption of the +Central Directory Signature data, the Zip64 End of Central Directory +record, the Zip64 End of Central Directory Locator, or the End +of Central Directory record. The ZIP file comment data is never +encrypted. + +Before encrypting the Central Directory, it may optionally be compressed. +Compression is not required, but for storage efficiency it is assumed +this structure will be compressed before encrypting. Similarly, this +specification supports compressing the Central Directory without +requiring that it also be encrypted. Early implementations of this +feature will assume the encryption method applied to files matches the +encryption applied to the Central Directory. + +Encryption of the Central Directory is done in a manner similar to +that of file encryption. The encrypted data is preceded by a +decryption header. The decryption header is known as the Archive +Decryption Header. The fields of this record are identical to +the decryption header preceding each encrypted file. The location +of the Archive Decryption Header is determined by the value in the +Start of the Central Directory field in the Zip64 End of Central +Directory record. When the Central Directory is encrypted, the +Zip64 End of Central Directory record will always be present. + +The layout of the Zip64 End of Central Directory record for all +versions starting with 6.2 of this specification will follow the +Version 2 format. The Version 2 format is as follows: + +The leading fixed size fields within the Version 1 format for this +record remain unchanged. The record signature for both Version 1 +and Version 2 will be 0x06064b50. Immediately following the last +byte of the field known as the Offset of Start of Central +Directory With Respect to the Starting Disk Number will begin the +new fields defining Version 2 of this record. + +New fields for Version 2: + +Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + Compression Method 2 bytes Method used to compress the + Central Directory + Compressed Size 8 bytes Size of the compressed data + Original Size 8 bytes Original uncompressed size + AlgId 2 bytes Encryption algorithm ID + BitLen 2 bytes Encryption key length + Flags 2 bytes Encryption flags + HashID 2 bytes Hash algorithm identifier + Hash Length 2 bytes Length of hash data + Hash Data (variable) Hash data + +The Compression Method accepts the same range of values as the +corresponding field in the Central Header. + +The Compressed Size and Original Size values will not include the +data of the Central Directory Signature which is compressed or +encrypted. + +The AlgId, BitLen, and Flags fields accept the same range of values +the corresponding fields within the 0x0017 record. + +Hash ID identifies the algorithm used to hash the Central Directory +data. This data does not have to be hashed, in which case the +values for both the HashID and Hash Length will be 0. Possible +values for HashID are: + + Value Algorithm + ------ --------- + 0x0000 none + 0x0001 CRC32 + 0x8003 MD5 + 0x8004 SHA1 + 0x8007 RIPEMD160 + 0x800C SHA256 + 0x800D SHA384 + 0x800E SHA512 + +When the Central Directory data is signed, the same hash algorithm +used to hash the Central Directory for signing should be used. +This is recommended for processing efficiency, however, it is +permissible for any of the above algorithms to be used independent +of the signing process. + +The Hash Data will contain the hash data for the Central Directory. +The length of this data will vary depending on the algorithm used. + +The Version Needed to Extract should be set to 62. + +The value for the Total Number of Entries on the Current Disk will +be 0. These records will no longer support random access when +encrypting the Central Directory. + +When the Central Directory is compressed and/or encrypted, the +End of Central Directory record will store the value 0xFFFFFFFF +as the value for the Total Number of Entries in the Central +Directory. The value stored in the Total Number of Entries in +the Central Directory on this Disk field will be 0. The actual +values will be stored in the equivalent fields of the Zip64 +End of Central Directory record. + +Decrypting and decompressing the Central Directory is accomplished +in the same manner as decrypting and decompressing a file. + +Certificate Processing Method: +----------------------------- + +The Certificate Processing Method of for ZIP file encryption +defines the following additional data fields: + +1. Certificate Flag Values + +Additional processing flags that can be present in the Flags field of both +the 0x0017 field of the central directory Extra Field and the Decryption +header record preceding compressed file data are: + + 0x0007 - reserved for future use + 0x000F - reserved for future use + 0x0100 - Indicates non-OAEP key wrapping was used. If this + this field is set, the version needed to extract must + be at least 61. This means OAEP key wrapping is not + used when generating a Master Session Key using + ErdData. + 0x4000 - ErdData must be decrypted using 3DES-168, otherwise use the + same algorithm used for encrypting the file contents. + 0x8000 - reserved for future use + + +2. CertData - Extra Field 0x0017 record certificate data structure + +The data structure used to store certificate data within the section +of the Extra Field defined by the CertData field of the 0x0017 +record are as shown: + + Value Size Description + ----- ---- ----------- + RCount 4 bytes Number of recipients. + HashAlg 2 bytes Hash algorithm identifier + HSize 2 bytes Hash size + SRList (var) Simple list of recipients hashed public keys + + + RCount This defines the number intended recipients whose + public keys were used for encryption. This identifies + the number of elements in the SRList. + + HashAlg This defines the hash algorithm used to calculate + the public key hash of each public key used + for encryption. This field currently supports + only the following value for SHA-1 + + 0x8004 - SHA1 + + HSize This defines the size of a hashed public key. + + SRList This is a variable length list of the hashed + public keys for each intended recipient. Each + element in this list is HSize. The total size of + SRList is determined using RCount * HSize. + + +3. Reserved1 - Certificate Decryption Header Reserved1 Data: + + Value Size Description + ----- ---- ----------- + RCount 4 bytes Number of recipients. + + RCount This defines the number intended recipients whose + public keys were used for encryption. This defines + the number of elements in the REList field defined below. + + +4. Reserved2 - Certificate Decryption Header Reserved2 Data Structures: + + + Value Size Description + ----- ---- ----------- + HashAlg 2 bytes Hash algorithm identifier + HSize 2 bytes Hash size + REList (var) List of recipient data elements + + + HashAlg This defines the hash algorithm used to calculate + the public key hash of each public key used + for encryption. This field currently supports + only the following value for SHA-1 + + 0x8004 - SHA1 + + HSize This defines the size of a hashed public key + defined in REHData. + + REList This is a variable length of list of recipient data. + Each element in this list consists of a Recipient + Element data structure as follows: + + + Recipient Element (REList) Data Structure: + + Value Size Description + ----- ---- ----------- + RESize 2 bytes Size of REHData + REKData + REHData HSize Hash of recipients public key + REKData (var) Simple key blob + + + RESize This defines the size of an individual REList + element. This value is the combined size of the + REHData field + REKData field. REHData is defined by + HSize. REKData is variable and can be calculated + for each REList element using RESize and HSize. + + REHData Hashed public key for this recipient. + + REKData Simple Key Blob. The format of this data structure + is identical to that defined in the Microsoft + CryptoAPI and generated using the CryptExportKey() + function. The version of the Simple Key Blob + supported at this time is 0x02 as defined by + Microsoft. + +Certificate Processing - Central Directory Encryption: +------------------------------------------------------ + +Central Directory Encryption using Digital Certificates will +operate in a manner similar to that of Single Password Central +Directory Encryption. This record will only be present when there +is data to place into it. Currently, data is placed into this +record when digital certificates are used for either encrypting +or signing the files within a ZIP file. When only password +encryption is used with no certificate encryption or digital +signing, this record is not currently needed. When present, this +record will appear before the start of the actual Central Directory +data structure and will be located immediately after the Archive +Decryption Header if the Central Directory is encrypted. + +The Archive Extra Data record will be used to store the following +information. Additional data may be added in future versions. + +Extra Data Fields: + +0x0014 - PKCS#7 Store for X.509 Certificates +0x0016 - X.509 Certificate ID and Signature for central directory +0x0019 - PKCS#7 Encryption Recipient Certificate List + +The 0x0014 and 0x0016 Extra Data records that otherwise would be +located in the first record of the Central Directory for digital +certificate processing. When encrypting or compressing the Central +Directory, the 0x0014 and 0x0016 records must be located in the +Archive Extra Data record and they should not remain in the first +Central Directory record. The Archive Extra Data record will also +be used to store the 0x0019 data. + +When present, the size of the Archive Extra Data record will be +included in the size of the Central Directory. The data of the +Archive Extra Data record will also be compressed and encrypted +along with the Central Directory data structure. + +Certificate Processing Differences: + +The Certificate Processing Method of encryption differs from the +Single Password Symmetric Encryption Method as follows. Instead +of using a user-defined password to generate a master session key, +cryptographically random data is used. The key material is then +wrapped using standard key-wrapping techniques. This key material +is wrapped using the public key of each recipient that will need +to decrypt the file using their corresponding private key. + +This specification currently assumes digital certificates will follow +the X.509 V3 format for 1024 bit and higher RSA format digital +certificates. Implementation of this Certificate Processing Method +requires supporting logic for key access and management. This logic +is outside the scope of this specification. + +OAEP Processing with Certificate-based Encryption: + +OAEP stands for Optimal Asymmetric Encryption Padding. It is a +strengthening technique used for small encoded items such as decryption +keys. This is commonly applied in cryptographic key-wrapping techniques +and is supported by PKCS #1. Versions 5.0 and 6.0 of this specification +were designed to support OAEP key-wrapping for certificate-based +decryption keys for additional security. + +Support for private keys stored on Smartcards or Tokens introduced +a conflict with this OAEP logic. Most card and token products do +not support the additional strengthening applied to OAEP key-wrapped +data. In order to resolve this conflict, versions 6.1 and above of this +specification will no longer support OAEP when encrypting using +digital certificates. + +Versions of PKZIP available during initial development of the +certificate processing method set a value of 61 into the +version needed to extract field for a file. This indicates that +non-OAEP key wrapping is used. This affects certificate encryption +only, and password encryption functions should not be affected by +this value. This means values of 61 may be found on files encrypted +with certificates only, or on files encrypted with both password +encryption and certificate encryption. Files encrypted with both +methods can safely be decrypted using the password methods documented. + +IX. Change Process +------------------ + +In order for the .ZIP file format to remain a viable definition, this +specification should be considered as open for periodic review and +revision. Although this format was originally designed with a +certain level of extensibility, not all changes in technology +(present or future) were or will be necessarily considered in its +design. If your application requires new definitions to the +extensible sections in this format, or if you would like to +submit new data structures, please forward your request to +zipformat@pkware.com. All submissions will be reviewed by the +ZIP File Specification Committee for possible inclusion into +future versions of this specification. Periodic revisions +to this specification will be published to ensure interoperability. +We encourage comments and feedback that may help improve clarity +or content. + +X. Incorporating PKWARE Proprietary Technology into Your Product +---------------------------------------------------------------- + +PKWARE is committed to the interoperability and advancement of the +.ZIP format. PKWARE offers a free license for certain technological +aspects described above under certain restrictions and conditions. +However, the use or implementation in a product of certain technological +aspects set forth in the current APPNOTE, including those with regard to +strong encryption, patching, or extended tape operations requires a +license from PKWARE. Please contact PKWARE with regard to acquiring +a license. + +XI. Acknowledgements +--------------------- + +In addition to the above mentioned contributors to PKZIP and PKUNZIP, +I would like to extend special thanks to Robert Mahoney for suggesting +the extension .ZIP for this software. + +XII. References +--------------- + + Fiala, Edward R., and Greene, Daniel H., "Data compression with + finite windows", Communications of the ACM, Volume 32, Number 4, + April 1989, pages 490-505. + + Held, Gilbert, "Data Compression, Techniques and Applications, + Hardware and Software Considerations", John Wiley & Sons, 1987. + + Huffman, D.A., "A method for the construction of minimum-redundancy + codes", Proceedings of the IRE, Volume 40, Number 9, September 1952, + pages 1098-1101. + + Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14, + Number 10, October 1989, pages 29-37. + + Nelson, Mark, "The Data Compression Book", M&T Books, 1991. + + Storer, James A., "Data Compression, Methods and Theory", + Computer Science Press, 1988 + + Welch, Terry, "A Technique for High-Performance Data Compression", + IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19. + + Ziv, J. and Lempel, A., "A universal algorithm for sequential data + compression", Communications of the ACM, Volume 30, Number 6, + June 1987, pages 520-540. + + Ziv, J. and Lempel, A., "Compression of individual sequences via + variable-rate coding", IEEE Transactions on Information Theory, + Volume 24, Number 5, September 1978, pages 530-536. + + +APPENDIX A - AS/400 Extra Field (0x0065) Attribute Definitions +-------------------------------------------------------------- + +Field Definition Structure: + + a. field length including length 2 bytes + b. field code 2 bytes + c. data x bytes + +Field Code Description + 4001 Source type i.e. CLP etc + 4002 The text description of the library + 4003 The text description of the file + 4004 The text description of the member + 4005 x'F0' or 0 is PF-DTA, x'F1' or 1 is PF_SRC + 4007 Database Type Code 1 byte + 4008 Database file and fields definition + 4009 GZIP file type 2 bytes + 400B IFS code page 2 bytes + 400C IFS Creation Time 4 bytes + 400D IFS Access Time 4 bytes + 400E IFS Modification time 4 bytes + 005C Length of the records in the file 2 bytes + 0068 GZIP two words 8 bytes + +APPENDIX B - z/OS Extra Field (0x0065) Attribute Definitions +------------------------------------------------------------ + +Field Definition Structure: + + a. field length including length 2 bytes + b. field code 2 bytes + c. data x bytes + +Field Code Description + 0001 File Type 2 bytes + 0002 NonVSAM Record Format 1 byte + 0003 Reserved + 0004 NonVSAM Block Size 2 bytes Big Endian + 0005 Primary Space Allocation 3 bytes Big Endian + 0006 Secondary Space Allocation 3 bytes Big Endian + 0007 Space Allocation Type1 byte flag + 0008 Modification Date Retired with PKZIP 5.0 + + 0009 Expiration Date Retired with PKZIP 5.0 + + 000A PDS Directory Block Allocation 3 bytes Big Endian binary value + 000B NonVSAM Volume List variable + 000C UNIT Reference Retired with PKZIP 5.0 + + 000D DF/SMS Management Class 8 bytes EBCDIC Text Value + 000E DF/SMS Storage Class 8 bytes EBCDIC Text Value + 000F DF/SMS Data Class 8 bytes EBCDIC Text Value + 0010 PDS/PDSE Member Info. 30 bytes + 0011 VSAM sub-filetype 2 bytes + 0012 VSAM LRECL 13 bytes EBCDIC "(num_avg num_max)" + 0013 VSAM Cluster Name Retired with PKZIP 5.0 + + 0014 VSAM KSDS Key Information 13 bytes EBCDIC "(num_length num_position)" + 0015 VSAM Average LRECL 5 bytes EBCDIC num_value padded with blanks + 0016 VSAM Maximum LRECL 5 bytes EBCDIC num_value padded with blanks + 0017 VSAM KSDS Key Length 5 bytes EBCDIC num_value padded with blanks + 0018 VSAM KSDS Key Position 5 bytes EBCDIC num_value padded with blanks + 0019 VSAM Data Name 1-44 bytes EBCDIC text string + 001A VSAM KSDS Index Name 1-44 bytes EBCDIC text string + 001B VSAM Catalog Name 1-44 bytes EBCDIC text string + 001C VSAM Data Space Type 9 bytes EBCDIC text string + 001D VSAM Data Space Primary 9 bytes EBCDIC num_value left-justified + 001E VSAM Data Space Secondary 9 bytes EBCDIC num_value left-justified + 001F VSAM Data Volume List variable EBCDIC text list of 6-character Volume IDs + 0020 VSAM Data Buffer Space 8 bytes EBCDIC num_value left-justified + 0021 VSAM Data CISIZE 5 bytes EBCDIC num_value left-justified + 0022 VSAM Erase Flag 1 byte flag + 0023 VSAM Free CI % 3 bytes EBCDIC num_value left-justified + 0024 VSAM Free CA % 3 bytes EBCDIC num_value left-justified + 0025 VSAM Index Volume List variable EBCDIC text list of 6-character Volume IDs + 0026 VSAM Ordered Flag 1 byte flag + 0027 VSAM REUSE Flag 1 byte flag + 0028 VSAM SPANNED Flag 1 byte flag + 0029 VSAM Recovery Flag 1 byte flag + 002A VSAM WRITECHK Flag 1 byte flag + 002B VSAM Cluster/Data SHROPTS 3 bytes EBCDIC "n,y" + 002C VSAM Index SHROPTS 3 bytes EBCDIC "n,y" + 002D VSAM Index Space Type 9 bytes EBCDIC text string + 002E VSAM Index Space Primary 9 bytes EBCDIC num_value left-justified + 002F VSAM Index Space Secondary 9 bytes EBCDIC num_value left-justified + 0030 VSAM Index CISIZE 5 bytes EBCDIC num_value left-justified + 0031 VSAM Index IMBED 1 byte flag + 0032 VSAM Index Ordered Flag 1 byte flag + 0033 VSAM REPLICATE Flag 1 byte flag + 0034 VSAM Index REUSE Flag 1 byte flag + 0035 VSAM Index WRITECHK Flag 1 byte flag Retired with PKZIP 5.0 + + 0036 VSAM Owner 8 bytes EBCDIC text string + 0037 VSAM Index Owner 8 bytes EBCDIC text string + 0038 Reserved + 0039 Reserved + 003A Reserved + 003B Reserved + 003C Reserved + 003D Reserved + 003E Reserved + 003F Reserved + 0040 Reserved + 0041 Reserved + 0042 Reserved + 0043 Reserved + 0044 Reserved + 0045 Reserved + 0046 Reserved + 0047 Reserved + 0048 Reserved + 0049 Reserved + 004A Reserved + 004B Reserved + 004C Reserved + 004D Reserved + 004E Reserved + 004F Reserved + 0050 Reserved + 0051 Reserved + 0052 Reserved + 0053 Reserved + 0054 Reserved + 0055 Reserved + 0056 Reserved + 0057 Reserved + 0058 PDS/PDSE Member TTR Info. 6 bytes Big Endian + 0059 PDS 1st LMOD Text TTR 3 bytes Big Endian + 005A PDS LMOD EP Rec # 4 bytes Big Endian + 005B Reserved + 005C Max Length of records 2 bytes Big Endian + 005D PDSE Flag 1 byte flag + 005E Reserved + 005F Reserved + 0060 Reserved + 0061 Reserved + 0062 Reserved + 0063 Reserved + 0064 Reserved + 0065 Last Date Referenced 4 bytes Packed Hex "yyyymmdd" + 0066 Date Created 4 bytes Packed Hex "yyyymmdd" + 0068 GZIP two words 8 bytes + 0071 Extended NOTE Location 12 bytes Big Endian + 0072 Archive device UNIT 6 bytes EBCDIC + 0073 Archive 1st Volume 6 bytes EBCDIC + 0074 Archive 1st VOL File Seq# 2 bytes Binary + +APPENDIX C - Zip64 Extensible Data Sector Mappings (EFS) +-------------------------------------------------------- + + -Z390 Extra Field: + + The following is the general layout of the attributes for the + ZIP 64 "extra" block for extended tape operations. Portions of + this extended tape processing technology is covered under a + pending patent application. The use or implementation in a + product of certain technological aspects set forth in the + current APPNOTE, including those with regard to strong encryption, + patching or extended tape operations, requires a license from + PKWARE. Please contact PKWARE with regard to acquiring a license. + + + Note: some fields stored in Big Endian format. All text is + in EBCDIC format unless otherwise specified. + + Value Size Description + ----- ---- ----------- + (Z390) 0x0065 2 bytes Tag for this "extra" block type + Size 4 bytes Size for the following data block + Tag 4 bytes EBCDIC "Z390" + Length71 2 bytes Big Endian + Subcode71 2 bytes Enote type code + FMEPos 1 byte + Length72 2 bytes Big Endian + Subcode72 2 bytes Unit type code + Unit 1 byte Unit + Length73 2 bytes Big Endian + Subcode73 2 bytes Volume1 type code + FirstVol 1 byte Volume + Length74 2 bytes Big Endian + Subcode74 2 bytes FirstVol file sequence + FileSeq 2 bytes Sequence + +APPENDIX D - Language Encoding (EFS) +------------------------------------ + +The ZIP format has historically supported only the original IBM PC character +encoding set, commonly referred to as IBM Code Page 437. This limits storing +file name characters to only those within the original MS-DOS range of values +and does not properly support file names in other character encodings, or +languages. To address this limitation, this specification will support the +following change. + +If general purpose bit 11 is unset, the file name and comment should conform +to the original ZIP character encoding. If general purpose bit 11 is set, the +filename and comment must support The Unicode Standard, Version 4.1.0 or +greater using the character encoding form defined by the UTF-8 storage +specification. The Unicode Standard is published by the The Unicode +Consortium (www.unicode.org). UTF-8 encoded data stored within ZIP files +is expected to not include a byte order mark (BOM). + +Applications may choose to supplement this file name storage through the use +of the 0x0008 Extra Field. Storage for this optional field is currently +undefined, however it will be used to allow storing extended information +on source or target encoding that may further assist applications with file +name, or file content encoding tasks. Please contact PKWARE with any +requirements on how this field should be used. + +The 0x0008 Extra Field storage may be used with either setting for general +purpose bit 11. Examples of the intended usage for this field is to store +whether "modified-UTF-8" (JAVA) is used, or UTF-8-MAC. Similarly, other +commonly used character encoding (code page) designations can be indicated +through this field. Formalized values for use of the 0x0008 record remain +undefined at this time. The definition for the layout of the 0x0008 field +will be published when available. Use of the 0x0008 Extra Field provides +for storing data within a ZIP file in an encoding other than IBM Code +Page 437 or UTF-8. + +General purpose bit 11 will not imply any encoding of file content or +password. Values defining character encoding for file content or +password must be stored within the 0x0008 Extended Language Encoding +Extra Field. + +Ed Gordon of the Info-ZIP group has defined a pair of "extra field" records +that can be used to store UTF-8 file name and file comment fields. These +records can be used for cases when the general purpose bit 11 method +for storing UTF-8 data in the standard file name and comment fields is +not desirable. A common case for this alternate method is if backward +compatibility with older programs is required. + +Definitions for the record structure of these fields are included above +in the section on 3rd party mappings for "extra field" records. These +records are identified by Header ID's 0x6375 (Info-ZIP Unicode Comment +Extra Field) and 0x7075 (Info-ZIP Unicode Path Extra Field). + +The choice of which storage method to use when writing a ZIP file is left +to the implementation. Developers should expect that a ZIP file may +contain either method and should provide support for reading data in +either format. Use of general purpose bit 11 reduces storage requirements +for file name data by not requiring additional "extra field" data for +each file, but can result in older ZIP programs not being able to extract +files. Use of the 0x6375 and 0x7075 records will result in a ZIP file +that should always be readable by older ZIP programs, but requires more +storage per file to write file name and/or file comment fields. + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/CMakeLists.txt b/apps/files_odfviewer/src/webodf/webodf/CMakeLists.txt new file mode 100644 index 0000000000..247ff5c625 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/CMakeLists.txt @@ -0,0 +1,201 @@ +string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" + WRONGCMAKEDIR) +if(WRONGCMAKEDIR) + message(FATAL_ERROR "You should point CMake to the parent directory.") +endif(WRONGCMAKEDIR) + +set(TESTJSFILES tests/core/ZipTests.js + tests/core/Base64Tests.js + tests/core/CursorTests.js + tests/core/PointWalkerTests.js + tests/core/RuntimeTests.js + tests/gui/CaretTests.js + tests/gui/SelectionMoverTests.js + tests/gui/XMLEditTests.js + tests/xmldom/OperationalTransformDOMTests.js + tests/xmldom/XPathTests.js + tests/tests.js +) + +add_custom_target(jslintcheck ALL + COMMAND ${NODE} lib/runtime.js tools/runjslint.js + ${LIBJSFILES} ${TESTJSFILES} + DEPENDS NodeJS + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + SOURCES ${LIBJSFILES} ${TESTJSFILES} +) + +if (Java_JAVA_EXECUTABLE) + # nonStandardJsDocs is not used because we use @licstart @licend and @source + set(SHARED_CLOSURE_ARGS --warning_level VERBOSE --jscomp_error accessControls --jscomp_error ambiguousFunctionDecl --jscomp_error checkRegExp --jscomp_error checkTypes --jscomp_error checkVars --jscomp_error constantProperty --jscomp_error deprecated --jscomp_error externsValidation --jscomp_error fileoverviewTags --jscomp_error globalThis --jscomp_error invalidCasts --jscomp_error missingProperties --jscomp_error strictModuleDepCheck --jscomp_error typeInvalidation --jscomp_error undefinedVars --jscomp_error unknownDefines --jscomp_error uselessCode --jscomp_error visibility --jscomp_off nonStandardJsDocs --summary_detail_level 3) + + foreach(JSFILE ${LIBJSFILES}) + set(LIB_CLOSURE_ARGS ${LIB_CLOSURE_ARGS} + --js ${CMAKE_CURRENT_SOURCE_DIR}/${JSFILE}) + endforeach(JSFILE ${LIBJSFILES}) + + foreach(JSFILE ${TESTJSFILES}) + set(TEST_CLOSURE_ARGS ${TEST_CLOSURE_ARGS} + --js ${CMAKE_CURRENT_SOURCE_DIR}/${JSFILE}) + endforeach(JSFILE ${TESTJSFILES}) + + add_custom_command( + OUTPUT simplecompiled.js + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${CLOSURE_JAR} + ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} ${TEST_CLOSURE_ARGS} + --compilation_level WHITESPACE_ONLY + --formatting PRETTY_PRINT + --js_output_file simplecompiled.js + DEPENDS ClosureCompiler ${LIBJSFILES} ${TESTJSFILES} + ) + + add_custom_command( + OUTPUT compiled.js + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${CLOSURE_JAR} + --define IS_COMPILED_CODE=true + ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} ${TEST_CLOSURE_ARGS} + --compilation_level ADVANCED_OPTIMIZATIONS + --formatting PRETTY_PRINT + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/externs.js + --js_output_file compiled.js + DEPENDS ClosureCompiler ${LIBJSFILES} ${TESTJSFILES} tools/externs.js + ) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/webodf.js + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${CLOSURE_JAR} + --define IS_COMPILED_CODE=true + ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} + --compilation_level SIMPLE_OPTIMIZATIONS + --formatting PRINT_INPUT_DELIMITER + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/externs.js + --js_output_file ${CMAKE_CURRENT_BINARY_DIR}/webodf.js + DEPENDS ClosureCompiler ${LIBJSFILES} tools/externs.js + ) + add_custom_target(webodf.js + SOURCES ${CMAKE_CURRENT_BINARY_DIR}/webodf.js + ) + + # too hardcore for now... + # add_custom_command( + # OUTPUT webodf-experimental.js + # COMMAND ${Java_JAVA_EXECUTABLE} + # ARGS -jar ${CLOSURE_JAR} + # --define IS_COMPILED_CODE=true + # ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} + # --js ${CMAKE_CURRENT_SOURCE_DIR}/lib/export.js + # --compilation_level ADVANCED_OPTIMIZATIONS + # --formatting PRINT_INPUT_DELIMITER + # --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/externs.js + # --js_output_file webodf-experimental.js + # DEPENDS ClosureCompiler ${LIBJSFILES} lib/export.js tools/externs.js + # ) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/webodf-debug.js + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${CLOSURE_JAR} + --define IS_COMPILED_CODE=true + ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} + --compilation_level WHITESPACE_ONLY + --formatting PRETTY_PRINT + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/externs.js + --js_output_file ${CMAKE_CURRENT_BINARY_DIR}/webodf-debug.js + DEPENDS ClosureCompiler ${LIBJSFILES} tools/externs.js + ) + add_custom_target(webodf-debug.js + SOURCES ${CMAKE_CURRENT_BINARY_DIR}/webodf-debug.js + ) + + add_custom_command( + OUTPUT odfedit.js + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${CLOSURE_JAR} + --define IS_COMPILED_CODE=true + ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} + --js ${CMAKE_CURRENT_SOURCE_DIR}/odfedit.js + --compilation_level ADVANCED_OPTIMIZATIONS + --formatting PRETTY_PRINT + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/externs.js + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/extjsexterns.js + --js_output_file odfedit.js + DEPENDS ClosureCompiler ${LIBJSFILES} ${APPJSFILES} tools/externs.js tools/extjsexterns.js odfedit.js + ) + + add_custom_command( + OUTPUT gui.js + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${CLOSURE_JAR} + --define IS_COMPILED_CODE=true + ${SHARED_CLOSURE_ARGS} ${LIB_CLOSURE_ARGS} + --js ${CMAKE_CURRENT_SOURCE_DIR}/filelister.js + --js ${CMAKE_CURRENT_SOURCE_DIR}/gui.js + --compilation_level ADVANCED_OPTIMIZATIONS + --formatting PRETTY_PRINT + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/externs.js + --externs ${CMAKE_CURRENT_SOURCE_DIR}/tools/extjsexterns.js + --js_output_file gui.js + DEPENDS ClosureCompiler ${LIBJSFILES} ${APPJSFILES} tools/externs.js tools/extjsexterns.js filelister.js gui.js + ) + + add_custom_target(syntaxcheck ALL + DEPENDS simplecompiled.js webodf.js webodf-debug.js compiled.js + ) + + add_custom_target(rhinotest + COMMAND ${Java_JAVA_EXECUTABLE} -jar ${RHINO} + -debug lib/runtime.js tests/tests.js + DEPENDS Rhino + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + SOURCES ${LIBJSFILES} + ) + add_custom_target(simplerhinotest + COMMAND ${Java_JAVA_EXECUTABLE} -jar ${RHINO} + ${CMAKE_CURRENT_BINARY_DIR}/simplecompiled.js + DEPENDS Rhino simplecompiled.js + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests + ) + add_custom_command( + OUTPUT docs/index.html + COMMAND ${Java_JAVA_EXECUTABLE} + ARGS -jar ${JSDOCDIR}/jsrun.jar + ${JSDOCDIR}/app/run.js -d=${CMAKE_CURRENT_BINARY_DIR}/docs + -t=${JSDOCDIR}/templates/jsdoc ${LIBJSFILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${LIBJSFILES} JsDoc + ) + add_custom_target(doc DEPENDS docs/index.html) + add_custom_target(simplenodetest ALL + COMMAND ${NODE} ${CMAKE_CURRENT_BINARY_DIR}/simplecompiled.js + DEPENDS NodeJS simplecompiled.js + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests + ) + +endif (Java_JAVA_EXECUTABLE) + +add_custom_target(nodetest ALL + COMMAND ${NODE} lib/runtime.js tests/tests.js + DEPENDS NodeJS + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + SOURCES ${LIBJSFILES} +) +if (QT4_FOUND) + add_custom_target(qtjsruntimetest ALL + COMMAND ${CMAKE_BINARY_DIR}/programs/qtjsruntime/qtjsruntime ../lib/runtime.js tests.js + DEPENDS qtjsruntime jslintcheck + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests + SOURCES ${LIBJSFILES} + ) +endif (QT4_FOUND) +add_custom_command( + OUTPUT instrumented/index.html + COMMAND ${JSCOVERAGE} + ARGS --exclude=extjs --exclude=extjs/.git ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/instrumented + DEPENDS ${LIBJSFILES} jslintcheck JSCoverage +) +add_custom_target(instrumented ALL DEPENDS instrumented/index.html) +# vim:expandtab diff --git a/apps/files_odfviewer/src/webodf/webodf/README b/apps/files_odfviewer/src/webodf/webodf/README new file mode 100644 index 0000000000..a4dde2fee7 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/README @@ -0,0 +1,43 @@ +This directory contains the javacript code to WebODF as well as applications that use it. The applications are browser applications, commandline applications and unit tests. + +lib/ +lib/core/ Parts of WebODF that also work on JavaScript runtimes without a + document window. +lib/gui/ Parts of WebODF that require a domtree + +The library should be able to run in a number of different runtimes. Currently these are: + - a webbrowser + - node.js + - rhino +A common API is implemented for these three environments in the files lib/browser.js, lib/node.js and lib/rhino.js respectively. + + + +Requirements on the code + +There are several requirements that need to met before code can be considered for inclusion in WebODF. Most requirements can be checked automatically, a few have to be checked by hand. A contribution must: + - be contributed under the appropriate license + - be javascript + - not give any warnings in a JSLint check + - be unchanged when passed through jsbeautifier + - compile with the closure compiler + - must pass all the unit tests that were passed before + - as separate js files in the currenlty used Node.JS implementation + - as a single compiled file in the currenlty used Node.JS implementation + - as separate js files in the currenlty used Rhino implementation + - as a single compiled file Rhino implementation + - must have equal or greater code coverage for the each of the test runs + +The automatic checks can be performed by running a dedicated command that reports in an xml file. This report is compared to the previous report. + +runtests.js is the command that creates a report. + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/compare.html b/apps/files_odfviewer/src/webodf/webodf/compare.html new file mode 100644 index 0000000000..0cf1cc80af --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/compare.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + +
+ + diff --git a/apps/files_odfviewer/src/webodf/webodf/compare.js b/apps/files_odfviewer/src/webodf/webodf/compare.js new file mode 100644 index 0000000000..16bf5e333f --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/compare.js @@ -0,0 +1,45 @@ +/*global runtime: true, odf: true*/ +/*jslint white: false*/ +function getURIParameters(window) { + "use strict"; + var params = {}, + query = window.location.search.substring(1), + parms = query.split('&'), + i, + pos, + key, + val; + for (i = 0; i < parms.length; i += 1) { + pos = parms[i].indexOf('='); + if (pos > 0) { + key = parms[i].substring(0, pos); + val = parms[i].substring(pos + 1); + params[key] = val; + } + } + return params; +} +function init(window, document) { + "use strict"; + runtime.loadClass("odf.OdfCanvas"); + var params = getURIParameters(window), + odfelement = document.getElementById("odf"), + odfcanvas = new odf.OdfCanvas(odfelement); + if (!params.odf) { + return; + } + odfcanvas.addListener("statereadychange", function () { + var s = odfelement.style, + bgzoom = "100% auto", + pos; + s.backgroundImage = "url(" + params.bg + ")"; + s.backgroundRepeat = "no-repeat"; + if (params.bgzoom) { + bgzoom = params.bgzoom + "% auto"; + } + s.backgroundSize = bgzoom; + pos = (params.x || "0") + "px " + (params.y || "0") + "px"; + s.backgroundPosition = pos; + }); + odfcanvas.load(params.odf); +} diff --git a/apps/files_odfviewer/src/webodf/webodf/deflateinmozilla.txt b/apps/files_odfviewer/src/webodf/webodf/deflateinmozilla.txt new file mode 100644 index 0000000000..866b29de77 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/deflateinmozilla.txt @@ -0,0 +1,69 @@ +Found this in a mozilla forum. +http://forums.mozillazine.org/viewtopic.php?f=27&t=313496&start=0# + +Another implementation under MIT license can be found here: +http://www.codeproject.com/KB/scripting/Javascript_binaryenc.aspx + + //listener for the converted data + var listener = + { + onDataAvailable : function(request, context, inputStream, offset, count) + { + //write the data + var output = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); + + //outputFile is a file which will contain the gunzipped data + if(!outputFile.exists()) + output.init(outputFile, 0x02 | 0x08, 0644, 0); + + else + output.init(outputFile, 0x02 | 0x10, 0644, 0); + + var scriptable = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); + scriptable.init(inputStream); + + var data = scriptable.read(inputStream.available()); + output.write(data, data.length); + + output.close(); + }, + + onStartRequest : function(request, context) + { + }, + + onStopRequest : function(request, context) + { + } + }; + + //fake uri needed to create a channel + var uri = Components.classes["@mozilla.org/network/simple-uri;1"].createInstance(Components.interfaces.nsIURI); + uri.scheme = "http://gunzip"; + + //fake channel needed to create a request + var chan = Components.classes["@mozilla.org/network/input-stream-channel;1"].createInstance(Components.interfaces.nsIInputStreamChannel); + chan.setURI(uri); + chan.contentLength = decrypted.length; + chan.contentType = "gzip"; + chan.contentStream = null; + + var request = chan.QueryInterface(Components.interfaces.nsIRequest); + + // Attempt to gunzip + var conv = Components.classes["@mozilla.org/streamconv;1?from=gzip&to=uncompressed"].createInstance(Components.interfaces.nsIStreamConverter); + + conv.asyncConvertData("gzip", "uncompressed", listener, null); + + conv.onStartRequest(request, null); + + //input is an inputstream which contains the gzipped data + var avail = input.available(); + + //really do the conversion + conv.onDataAvailable(request, null, input, 0, avail); + + var status = {}; + conv.onStopRequest(request, null, status); + + input.close(); diff --git a/apps/files_odfviewer/src/webodf/webodf/embedodf.html b/apps/files_odfviewer/src/webodf/webodf/embedodf.html new file mode 100644 index 0000000000..96bb25cc2b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/embedodf.html @@ -0,0 +1,2 @@ + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/filelister.js b/apps/files_odfviewer/src/webodf/webodf/filelister.js new file mode 100644 index 0000000000..08f6cd3cb0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/filelister.js @@ -0,0 +1,200 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global XMLHttpRequest*/ +/*jslint regexp: true*/ +/** asynchroneous function that lists all files **/ +function listFiles(startdir, filepattern, fileCallback, doneCallback) { + "use strict"; + + var todoList = [], + doneList = [], + dirpattern = /\/$/, + hasWEBDAV = false; + + function getHref(responseElement) { + var n = responseElement.firstChild; + while (n && !(n.namespaceURI === 'DAV:' && n.localName === 'href')) { + n = n.nextSibling; + } + return n && n.firstChild && n.firstChild.nodeValue; + } + + function isDirectory(responseElement) { + var n = responseElement.firstChild; + while (n && + !(n.namespaceURI === 'DAV:' && n.localName === 'propstat')) { + n = n.nextSibling; + } + n = n && n.firstChild; + while (n && + !(n.namespaceURI === 'DAV:' && n.localName === 'prop')) { + n = n.nextSibling; + } + n = n && n.firstChild; + while (n && !(n.namespaceURI === 'DAV:' && + n.localName === 'resourcetype')) { + n = n.nextSibling; + } + n = n && n.firstChild; + while (n && + !(n.namespaceURI === 'DAV:' && n.localName === 'collection')) { + n = n.nextSibling; + } + return n; + } + + function processWebDavResponse(xml) { + if (!xml) { + throw new Error('No proper XML response.'); + } + + var refs = xml.getElementsByTagNameNS('DAV:', 'response'), + directories = [], + files = [], + i, + d, + href; + if (refs.length === 0) { + throw new Error('No proper XML response.'); + } + for (i = 0; i < refs.length; i += 1) { + href = getHref(refs[i]); + if (isDirectory(refs[i])) { + directories.push(href); + } else if (filepattern.test(href)) { + files.push(href); + } + } + for (i = 0; i < directories.length; i += 1) { + d = directories[i]; + if (doneList.indexOf(d) === -1 && todoList.indexOf(d) === -1) { + todoList.push(d); + } + } + fileCallback(directories, files); + } + + function processIndexHtmlResponse(base, text) { + // use regex because index.html is usually not valid xml + var re = /href="([^\/\?"][^"]*)"/ig, + matches, + files = [], + directories = [], + name, + d, + i; + while ((matches = re.exec(text)) !== null) { + name = matches[1]; + if (dirpattern.test(name)) { + directories.push(base + name); + } else if (filepattern.test(name)) { + files.push(base + name); + } + } + for (i = 0; i < directories.length; i += 1) { + d = directories[i]; + if (doneList.indexOf(d) === -1 && todoList.indexOf(d) === -1) { + todoList.push(d); + } + } + fileCallback(directories, files); + } + + function getNextFileListWithIndexHtml() { + var url = todoList.shift(), + req; + while (url && typeof url !== 'string') { + url = todoList.shift(); + } + if (!url) { + if (doneCallback) { + doneCallback(); + } + return; + } + req = new XMLHttpRequest(); + req.open('GET', url, true); + req.onreadystatechange = function (evt) { + if (req.readyState !== 4) { + return; + } + if (req.status >= 200 && req.status < 300) { + processIndexHtmlResponse(url, req.responseText); + } + getNextFileListWithIndexHtml(); + }; + req.send(null); + + doneList.push(url); + } + + function getNextFileListWithWebDav() { + var url = todoList.shift(), + req; + if (!url) { + if (doneCallback) { + doneCallback(); + } + return; + } + + req = new XMLHttpRequest(); + req.open('PROPFIND', url, true); + req.onreadystatechange = function (evt) { + if (req.readyState !== 4) { + return; + } + if (req.status >= 200 && req.status < 300) { + try { + processWebDavResponse(req.responseXML); + hasWEBDAV = true; + } catch (e) { + } + } + if (hasWEBDAV) { + getNextFileListWithWebDav(); + } else { + todoList.push(url); + doneList = []; + getNextFileListWithIndexHtml(); + } + }; + req.setRequestHeader('Depth', '1'); + req.send(null); + + doneList.push(url); + } + + todoList.push(startdir); + getNextFileListWithWebDav(); +} diff --git a/apps/files_odfviewer/src/webodf/webodf/flashput/Makefile b/apps/files_odfviewer/src/webodf/webodf/flashput/Makefile new file mode 100644 index 0000000000..291eef04b6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/flashput/Makefile @@ -0,0 +1,2 @@ +all: + /tmp/flex/bin/mxmlc PUT.as diff --git a/apps/files_odfviewer/src/webodf/webodf/flashput/PUT.as b/apps/files_odfviewer/src/webodf/webodf/flashput/PUT.as new file mode 100644 index 0000000000..451d8a0fd0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/flashput/PUT.as @@ -0,0 +1,18 @@ +package { + import flash.display.Sprite; + import flash.display.LoaderInfo; + import flash.external.ExternalInterface; + public class PUT extends Sprite { + public function PUT() { + ExternalInterface.addCallback("put", this.put); + var callback:String = LoaderInfo(root.loaderInfo).parameters["readyCallback"]; + ExternalInterface.call(callback); + } + public function put(host:String, port:uint, path:String, + data:String, callbackFunctionName:String, + callbackId:String):void { + new Request(host, port, path, data, + callbackFunctionName, callbackId); + } + } +} diff --git a/apps/files_odfviewer/src/webodf/webodf/flashput/PUT.swf b/apps/files_odfviewer/src/webodf/webodf/flashput/PUT.swf new file mode 100644 index 0000000000000000000000000000000000000000..466d0a1316e109f0617b7f723b0929cbd03439ce GIT binary patch literal 18031 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⁢XH@G-fEC^Hqg}a-MvHTX4Cm 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 + + hi + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/gui.js b/apps/files_odfviewer/src/webodf/webodf/gui.js new file mode 100644 index 0000000000..5fce22f51e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/gui.js @@ -0,0 +1,263 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global Ext:true, runtime:true, core:true, listFiles:true*/ +runtime.loadClass("core.Zip"); +runtime.loadClass("core.Base64"); + +/** + * @param {Ext.data.Model} node + * @return {undefined} + */ +function addThumbnail(node) { + "use strict"; + var url = node.get('id'), zip; +/* + zip = new core.Zip(url, function (err, zipobject) { + zip = zipobject; + if (err) { + return; + } + zip.load('Thumbnails/thumbnail.png', function (err, data) { + if (data === null) { + return; + } + var url = 'data:;base64,' + + (new core.Base64()).convertUTF8ArrayToBase64(data), + el, spans, i, s; + el = node.getUI().getEl(); + if (el) { + spans = el.getElementsByTagName('span'); + for (i = 0; i < spans.length; i += 1) { + s = spans.item(i); + if (s.getAttribute('qtip')) { + s.setAttribute('qtip', node.attributes.qtip); + } + } + } else { + node.attributes.qtip += '
'; + } + }); + }); +*/ +} + +/** + * @param {!string} url + * @param {!Ext.tab.Panel} panel + * @param {!string} title + * @return {undefined} + */ +function loadODF(url, panel, title) { + "use strict"; + var tab = panel.items.findBy(function (item) { + return item.url === url; + }), + newTab; + if (tab) { + panel.setActiveTab(tab); + return; + } + newTab = Ext.create('Ext.container.Container', { + title: title, + tabTip: url, + url: url, + closable: true, + autoEl: { + tag: 'iframe', + name: url, + src: 'odf.html#' + url, + frameBorder: 0, + style: { + border: '0 none' + } + }, + region: 'center' + }); + panel.add(newTab); + panel.setActiveTab(newTab); +} + +Ext.onReady(function () { + "use strict"; + var editButton, tabpanel, slider, tree, viewport; + + Ext.QuickTips.init(); + + /** + * @param {!Ext.Button} button + * @param {!boolean} pressed + * @return {undefined} + */ + function editToggle(button, pressed) { + var tab = tabpanel.getActiveTab(), o, odfcanvas = "odfcanvas"; + if (!tab) { + return; + } + tab.el.dom.contentDocument[odfcanvas].setEditable(pressed); + } + + /** + * @param {!Object} slider + * @param {!number} zoomlevel + * @param {!Object} thumb + * @return {undefined} + */ + function setZoom(slider, zoomlevel, thumb) { + var tab = tabpanel.getActiveTab(), + body; + if (!tab) { + return; + } + body = tab.el.dom.contentDocument.body; + zoomlevel = Math.pow(10, zoomlevel / 10.0); + body.style.zoom = zoomlevel; + body.style.MozTransform = 'scale(' + zoomlevel + ')'; + } + + /** + * @param {!Ext.data.NodeInterface} root + * @param {!string} uri + * @return {!Ext.data.NodeInterface} + */ + function getParentNode(root, uri) { + var parts = uri.split('/'), + node = root, + id = parts[0], + i, + n; + for (i = 1; i < parts.length - 1; i += 1) { + n = node.findChild('text', parts[i], false); + id += '/' + parts[i]; + if (!n) { + n = { + id: id, + text: parts[i], + qtip: uri, + cls: 'folder' + }; + n = node.appendChild(n); + } + node = n; + } + return node; + } + + /** + * @param {!Array.} directories + * @param {!Array.} files + * @return {undefined} + */ + function listFilesCallback(directories, files) { + var root = tree.getRootNode(), + i, + f, + parentNode, + qtip, + node; + for (i = 0; i < files.length; i += 1) { + f = files[i]; + parentNode = getParentNode(root, f); + qtip = f; + node = parentNode.appendChild({ + id: f, + qtip: qtip, + text: f.substr(f.lastIndexOf('/') + 1), + cls: 'file', + leaf: true, + editable: false + }); + f = /**@type{!Ext.data.Model}*/(node); + addThumbnail(f); + } + } + + /** + * @return {undefined} + */ + function listFilesDoneCallback() { + } + + editButton = new Ext.Button({ + enableToggle: true, + text: 'Editable', + listeners: { toggle: { fn: editToggle } } + }); + + slider = new Ext.Slider({ + width: 300, + minValue: -5, + maxValue: 5, + values: [0], + listeners: { changecomplete: { fn: setZoom } } + }); + + tabpanel = Ext.create('Ext.tab.Panel', { + tbar: [ 'Zoom: ', slider, editButton ], + region: 'center' + }); + + tree = Ext.create('Ext.tree.Panel', { + title: 'Documents', + region: 'west', + width: 200, + split: true, + autoScroll: true, + collapsible: true, + rootVisible: false, + enableTabScroll: true, + defaults: {autoScroll: true}, + listeners: { + itemclick: function (view, rec) { + if (rec.get('cls') === 'file') { + loadODF(rec.get('id'), tabpanel, rec.get('text')); + } else if (rec.get('cls') === 'folder') { + if (rec.isExpanded()) { + rec.collapse(); + } else { + rec.expand(); + } + } + } + }, + root: { nodeType: 'node' } + }); + + viewport = new Ext.Viewport({ + layout: 'border', + items: [ tabpanel, tree ] + }); + + // put data in the tree + listFiles('./demodocs/', /\.od[tps]$/i, listFilesCallback, + listFilesDoneCallback); +}); diff --git a/apps/files_odfviewer/src/webodf/webodf/httpserver.js b/apps/files_odfviewer/src/webodf/webodf/httpserver.js new file mode 100644 index 0000000000..245ce9f3f7 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/httpserver.js @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global require: true, console: true, process: true, Buffer: true, + unescape: true */ +/* A Node.JS http server*/ +var http = require("http"), + url = require("url"), + path = require("path"), + fs = require("fs"), + lookForIndexHtml = true, + ipaddress = "127.0.0.1", + //ipaddress = "192.168.1.105", + port = 8124; + +function statFile(dir, filelist, position, callback) { + "use strict"; + if (position >= filelist.length) { + return callback(null, filelist); + } + fs.stat(dir + "/" + filelist[position], function (err, stats) { + if (stats && stats.isDirectory()) { + filelist[position] = filelist[position] + "/"; + } + statFile(dir, filelist, position + 1, callback); + }); +} + +function listFiles(dir, callback) { + "use strict"; + fs.readdir(dir, function (err, files) { + if (err) { + return callback(err); + } + statFile(dir, files, 0, callback); + }); +} + +http.createServer(function (request, response) { + "use strict"; + var uri = unescape(url.parse(request.url).pathname), + filename = path.join(process.cwd(), uri); + if (uri !== '/favicon.ico') { + console.log(request.method + " " + uri); + } + function put() { + var contentlength = parseInt(request.headers["content-length"], 10), + alldata = new Buffer(contentlength), + sum = 0; + request.on("data", function (data) { + data.copy(alldata, sum, 0); + sum += data.length; + }); + request.on("end", function () { + fs.writeFile(filename, alldata, "binary", function (err) { + if (err) { + response.writeHead(500); + response.write(err); + } else { + response.writeHead(200); + } + response.end(); + }); + }); + } + if (request.method === "PUT") { + put(request, response); + return; + } + if (request.method === "DELETE") { + fs.unlink(filename, function (err) { + if (err) { + response.writeHead(500); + } else { + response.writeHead(200); + } + response.end(); + }); + return; + } + function handleStat(err, stats, lookForIndexHtml) { + if (!err && stats.isFile()) { + fs.readFile(filename, "binary", function (err, file) { + if (err) { + response.writeHead(500, {"Content-Type": "text/plain"}); + if (request.method !== "HEAD") { + response.write(err + "\n"); + } + response.end(); + return; + } + var head = {"Content-Length": stats.size}; + if (filename.substr(-3) === ".js") { + head["Content-Type"] = "text/javascript"; + } else if (filename.substr(-4) === ".css") { + head["Content-Type"] = "text/css"; + } else if (filename.substr(-4) === ".odt" || + filename.substr(-5) === ".fodt") { + head["Content-Type"] = "application/vnd.oasis.opendocument.text"; + } else if (filename.substr(-4) === ".ods" || + filename.substr(-5) === ".fods") { + head["Content-Type"] = "application/vnd.oasis.opendocument.presentation"; + } else if (filename.substr(-4) === ".odp" || + filename.substr(-5) === ".fodp") { + head["Content-Type"] = "application/vnd.oasis.opendocument.spreadsheet"; + } + response.writeHead(200, head); + if (request.method !== "HEAD") { + response.write(file, "binary"); + } + response.end(); + }); + } else if (!err && stats.isDirectory()) { + if (lookForIndexHtml) { + fs.stat(filename + "/index.html", function (err, stats) { + if (err) { + fs.stat(filename, handleStat); + } else { + filename = filename + "/index.html"; + handleStat(err, stats); + } + }); + return; + } + if (uri.length === 0 || uri[uri.length - 1] !== "/") { + response.writeHead(301, {"Content-Type": "text/plain", + "Location": uri + "/"}); + if (request.method !== "HEAD") { + response.write("Moved permanently\n"); + } + response.end(); + return; + } + listFiles(filename, function (err, files) { + if (err) { + response.writeHead(500, {"Content-Type": "text/plain"}); + if (request.method !== "HEAD") { + response.write(err + "\n"); + } + response.end(); + return; + } + response.writeHead(200); + if (request.method !== "HEAD") { + files.sort(); + response.write(""); + response.write(""); + var i, l = files.length, file; + for (i = 0; i < l; i += 1) { + file = files[i]; + if (file.length > 0 && file[file.length - 1] === '/') { + file = encodeURIComponent(file.slice(0, file.length - 1)) + "/"; + } else { + file = encodeURIComponent(file); + } + response.write("\n"); + } + response.write("
"); + file = files[i].replace("&", "&") + .replace("<", ">"); + response.write(file.replace("\"", "\\\"")); + response.write("
\n"); + } + response.end(); + }); + } else { + if (uri !== '/favicon.ico') { + console.log("Not found: " + uri); + } + response.writeHead(404, {"Content-Type": "text/plain"}); + if (request.method !== "HEAD") { + response.write("404 Not Found\n"); + } + response.end(); + } + } + fs.stat(filename, function (err, stats) { + handleStat(err, stats, lookForIndexHtml); + }); +}).listen(port, ipaddress); + +console.log('Server running at ' + ipaddress + ':' + port + '/'); diff --git a/apps/files_odfviewer/src/webodf/webodf/index.html b/apps/files_odfviewer/src/webodf/webodf/index.html new file mode 100644 index 0000000000..027a8a9b23 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + WebODF + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/Async.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/Async.js new file mode 100644 index 0000000000..358a8feee0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/Async.js @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core*/ + +/** + * @constructor + */ +core.Async = function Async() { + "use strict"; + /** + * @param {!Array.<*>} items + * @param {function(*, !function(!string):undefined):undefined} f + * @param {function(?string)} callback + * @return {undefined} + */ + this.forEach = function (items, f, callback) { + var i, l = items.length, itemsDone = 0; + function end(err) { + if (itemsDone !== l) { + if (err) { + itemsDone = l; + callback(err); + } else { + itemsDone += 1; + if (itemsDone === l) { + callback(null); + } + } + } + } + for (i = 0; i < l; i += 1) { + f(items[i], end); + } + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/Base64.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/Base64.js new file mode 100644 index 0000000000..736f5bb531 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/Base64.js @@ -0,0 +1,362 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*jslint bitwise: true, regexp: true*/ +/*global core: true, runtime: true*/ +/* + * $Id: base64.js,v 0.9 2009/03/01 20:51:18 dankogai Exp dankogai $ + */ +/** + * @namespace + */ +core.Base64 = (function () { + "use strict"; + var b64chars + = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', + + b64charcodes = (function () { + var a = [], i, + codeA = 'A'.charCodeAt(0), + codea = 'a'.charCodeAt(0), + code0 = '0'.charCodeAt(0); + for (i = 0; i < 26; i += 1) { + a.push(codeA + i); + } + for (i = 0; i < 26; i += 1) { + a.push(codea + i); + } + for (i = 0; i < 10; i += 1) { + a.push(code0 + i); + } + a.push('+'.charCodeAt(0)); + a.push('/'.charCodeAt(0)); + return a; + }()), + + b64tab = (function (bin) { + var t = {}, i, l; + for (i = 0, l = bin.length; i < l; i += 1) { + t[bin.charAt(i)] = i; + } + return t; + }(b64chars)), + convertUTF16StringToBase64, + convertBase64ToUTF16String, + btoa, atob; + + /** + * @param {!string} s + * @return {!Array} + */ + function stringToArray(s) { + var a = [], i, l = s.length; + for (i = 0; i < l; i += 1) { + a[i] = s.charCodeAt(i) & 0xff; + } + return a; + } + + function convertUTF8ArrayToBase64(bin) { + var n, + b64 = "", + i, + l = bin.length - 2; + for (i = 0; i < l; i += 3) { + n = (bin[i] << 16) | (bin[i + 1] << 8) | bin[i + 2]; + b64 += b64chars[n >>> 18]; + b64 += b64chars[(n >>> 12) & 63]; + b64 += b64chars[(n >>> 6) & 63]; + b64 += b64chars[n & 63]; + } + if (i === l + 1) { // 1 byte left + n = bin[i] << 4; + b64 += b64chars[n >>> 6]; + b64 += b64chars[n & 63]; + b64 += "=="; + } else if (i === l) { // 2 bytes left + n = (bin[i] << 10) | (bin[i + 1] << 2); + b64 += b64chars[n >>> 12]; + b64 += b64chars[(n >>> 6) & 63]; + b64 += b64chars[n & 63]; + b64 += "="; + } + return b64; + } + + function convertBase64ToUTF8Array(b64) { + b64 = b64.replace(/[^A-Za-z0-9+\/]+/g, ''); + var bin = [], + padlen = b64.length % 4, + i, + l = b64.length, + n; + for (i = 0; i < l; i += 4) { + n = ((b64tab[b64.charAt(i)] || 0) << 18) | + ((b64tab[b64.charAt(i + 1)] || 0) << 12) | + ((b64tab[b64.charAt(i + 2)] || 0) << 6) | + ((b64tab[b64.charAt(i + 3)] || 0)); + bin.push( + (n >> 16), + ((n >> 8) & 0xff), + (n & 0xff) + ); + } + bin.length -= [0, 0, 2, 1][padlen]; + return bin; + } + + function convertUTF16ArrayToUTF8Array(uni) { + var bin = [], i, l = uni.length, n; + for (i = 0; i < l; i += 1) { + n = uni[i]; + if (n < 0x80) { + bin.push(n); + } else if (n < 0x800) { + bin.push( + 0xc0 | (n >>> 6), + 0x80 | (n & 0x3f) + ); + } else { + bin.push( + 0xe0 | ((n >>> 12) & 0x0f), + 0x80 | ((n >>> 6) & 0x3f), + 0x80 | (n & 0x3f) + ); + } + } + return bin; + } + + function convertUTF8ArrayToUTF16Array(bin) { + var uni = [], i, l = bin.length, + c0, c1, c2; + for (i = 0; i < l; i += 1) { + c0 = bin[i]; + if (c0 < 0x80) { + uni.push(c0); + } else { + i += 1; + c1 = bin[i]; + if (c0 < 0xe0) { + uni.push(((c0 & 0x1f) << 6) | (c1 & 0x3f)); + } else { + i += 1; + c2 = bin[i]; + uni.push(((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | + (c2 & 0x3f) + ); + } + } + } + return uni; + } + + function convertUTF8StringToBase64(bin) { + return convertUTF8ArrayToBase64(stringToArray(bin)); + } + + function convertBase64ToUTF8String(b64) { + return String.fromCharCode.apply(String, convertBase64ToUTF8Array(b64)); + } + + function convertUTF8StringToUTF16Array(bin) { + return convertUTF8ArrayToUTF16Array(stringToArray(bin)); + } + + function convertUTF8ArrayToUTF16String(bin) { + // this conversion is done in chunks to avoid a stack overflow in + // apply() + var b = convertUTF8ArrayToUTF16Array(bin), + r = "", + i = 0, + chunksize = 45000; + while (i < b.length) { + r += String.fromCharCode.apply(String, b.slice(i, i + chunksize)); + i += chunksize; + } + return r; + } + /** + * @param {!Array.|!string} bin + * @param {!number} i + * @param {!number} end + * @return {!string} + */ + function convertUTF8StringToUTF16String_internal(bin, i, end) { + var str = "", c0, c1, c2, j; + for (j = i; j < end; j += 1) { + c0 = bin.charCodeAt(j) & 0xff; + if (c0 < 0x80) { + str += String.fromCharCode(c0); + } else { + j += 1; + c1 = bin.charCodeAt(j) & 0xff; + if (c0 < 0xe0) { + str += String.fromCharCode(((c0 & 0x1f) << 6) | + (c1 & 0x3f)); + } else { + j += 1; + c2 = bin.charCodeAt(j) & 0xff; + str += String.fromCharCode(((c0 & 0x0f) << 12) | + ((c1 & 0x3f) << 6) | (c2 & 0x3f)); + } + } + } + return str; + } + + /** + * Convert a utf-8 array into a utf-16 string. + * The input array is treated as a list of values between 0 and 255. + * This function works with a callback and splits the work up in parts + * between which it yields to the main thread. + * After each part the progress is reported with the callback function that + * also passes a booleant that indicates if the job has finished. + * If the conversion should stop, the callback should return false. + * + * @param {!Array.|!string} bin + * @param {!function(!string, boolean):boolean} callback + * @return {undefined} + */ + function convertUTF8StringToUTF16String(bin, callback) { + var partsize = 100000, + numparts = bin.length / partsize, + str = "", + pos = 0; + if (bin.length < partsize) { + callback(convertUTF8StringToUTF16String_internal(bin, 0, + bin.length), true); + return; + } + // make a local copy if the input is a string, to avoid modification + if (typeof bin !== "string") { + bin = bin.slice(); + } + function f() { + var end = pos + partsize; + if (end > bin.length) { + end = bin.length; + } + str += convertUTF8StringToUTF16String_internal(bin, pos, end); + pos = end; + end = pos === bin.length; + if (callback(str, end) && !end) { + runtime.setTimeout(f, 0); + } + } + f(); + } + + function convertUTF16StringToUTF8Array(uni) { + return convertUTF16ArrayToUTF8Array(stringToArray(uni)); + } + + function convertUTF16ArrayToUTF8String(uni) { + return String.fromCharCode.apply(String, + convertUTF16ArrayToUTF8Array(uni)); + } + + function convertUTF16StringToUTF8String(uni) { + return String.fromCharCode.apply(String, + convertUTF16ArrayToUTF8Array(stringToArray(uni))); + } + + btoa = runtime.getWindow() && runtime.getWindow().btoa; + if (btoa) { + convertUTF16StringToBase64 = function (uni) { + return btoa(convertUTF16StringToUTF8String(uni)); + }; + } else { + btoa = convertUTF8StringToBase64; + convertUTF16StringToBase64 = function (uni) { + return convertUTF8ArrayToBase64(convertUTF16StringToUTF8Array(uni)); + }; + } + atob = runtime.getWindow() && runtime.getWindow().atob; + if (atob) { + convertBase64ToUTF16String = function (b64) { + var b = atob(b64); + return convertUTF8StringToUTF16String_internal(b, 0, b.length); + }; + } else { + atob = convertBase64ToUTF8String; + convertBase64ToUTF16String = function (b64) { + return convertUTF8ArrayToUTF16String(convertBase64ToUTF8Array(b64)); + }; + } + + /** + * @constructor + */ + function Base64() { + this.convertUTF8ArrayToBase64 = convertUTF8ArrayToBase64; + this.convertByteArrayToBase64 = convertUTF8ArrayToBase64; + this.convertBase64ToUTF8Array = convertBase64ToUTF8Array; + this.convertBase64ToByteArray = convertBase64ToUTF8Array; + this.convertUTF16ArrayToUTF8Array = convertUTF16ArrayToUTF8Array; + this.convertUTF16ArrayToByteArray = convertUTF16ArrayToUTF8Array; + this.convertUTF8ArrayToUTF16Array = convertUTF8ArrayToUTF16Array; + this.convertByteArrayToUTF16Array = convertUTF8ArrayToUTF16Array; + this.convertUTF8StringToBase64 = convertUTF8StringToBase64; + this.convertBase64ToUTF8String = convertBase64ToUTF8String; + this.convertUTF8StringToUTF16Array = convertUTF8StringToUTF16Array; + this.convertUTF8ArrayToUTF16String = convertUTF8ArrayToUTF16String; + this.convertByteArrayToUTF16String = convertUTF8ArrayToUTF16String; + this.convertUTF8StringToUTF16String = convertUTF8StringToUTF16String; + this.convertUTF16StringToUTF8Array = convertUTF16StringToUTF8Array; + this.convertUTF16StringToByteArray = convertUTF16StringToUTF8Array; + this.convertUTF16ArrayToUTF8String = convertUTF16ArrayToUTF8String; + this.convertUTF16StringToUTF8String = convertUTF16StringToUTF8String; + this.convertUTF16StringToBase64 = convertUTF16StringToBase64; + this.convertBase64ToUTF16String = convertBase64ToUTF16String; + this.fromBase64 = convertBase64ToUTF8String; + this.toBase64 = convertUTF8StringToBase64; + this.atob = atob; + this.btoa = btoa; + this.utob = convertUTF16StringToUTF8String; + this.btou = convertUTF8StringToUTF16String; + this.encode = convertUTF16StringToBase64; + this.encodeURI = function (u) { + return convertUTF16StringToBase64(u).replace(/[+\/]/g, + function (m0) { + return m0 === '+' ? '-' : '_'; + }).replace(/\\=+$/, ''); + }; + this.decode = function (a) { + return convertBase64ToUTF16String(a.replace(/[\-_]/g, + function (m0) { + return m0 === '-' ? '+' : '/'; + })); + }; + } + return Base64; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArray.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArray.js new file mode 100644 index 0000000000..d8a9ddd73d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArray.js @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core*/ +/*jslint plusplus: true, bitwise: true */ +/** + * @constructor + * @param {!Runtime.ByteArray} data + */ +core.ByteArray = function ByteArray(data) { + "use strict"; + /** + * @type {!number} + */ + this.pos = 0; + /** + * @type {!Runtime.ByteArray} + */ + this.data = data; + /** + * @return {number} + */ + this.readUInt32LE = function () { + var data = this.data, + pos = (this.pos += 4); + return (data[--pos] << 24) | + (data[--pos] << 16) | + (data[--pos] << 8) | + data[--pos]; + }; + /** + * @return {number} + */ + this.readUInt16LE = function () { + var data = this.data, + pos = (this.pos += 2); + return (data[--pos] << 8) | data[--pos]; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArrayWriter.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArrayWriter.js new file mode 100644 index 0000000000..a7838be3dc --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/ByteArrayWriter.js @@ -0,0 +1,101 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true*/ +/*jslint bitwise: true */ +/** + * @constructor + * @param {!string} encoding + */ +core.ByteArrayWriter = function ByteArrayWriter(encoding) { + "use strict"; + var self = this, + data = new runtime.ByteArray(0); + + /** + * @param {!core.ByteArrayWriter} writer + * @return {undefined} + */ + this.appendByteArrayWriter = function (writer) { + data = runtime.concatByteArrays(data, writer.getByteArray()); + }; + /** + * @param {!Runtime.ByteArray} array + * @return {undefined} + */ + this.appendByteArray = function (array) { + data = runtime.concatByteArrays(data, array); + }; + /** + * @param {!Array.} array + * @return {undefined} + */ + this.appendArray = function (array) { + data = runtime.concatByteArrays(data, + runtime.byteArrayFromArray(array)); + }; + /** + * @param {!number} value + * @return {undefined} + */ + this.appendUInt16LE = function (value) { + self.appendArray([value & 0xff, (value >> 8) & 0xff]); + }; + /** + * @param {!number} value + * @return {undefined} + */ + this.appendUInt32LE = function (value) { + self.appendArray([value & 0xff, (value >> 8) & 0xff, + (value >> 16) & 0xff, (value >> 24) & 0xff]); + }; + /** + * @param {!string} string + * @return {undefined} + */ + this.appendString = function (string) { + data = runtime.concatByteArrays(data, + runtime.byteArrayFromString(string, encoding)); + }; + /** + * @return {!number} + */ + this.getLength = function () { + return data.length; + }; + /** + * @return {!Runtime.ByteArray} + */ + this.getByteArray = function () { + return data; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/Cursor.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/Cursor.js new file mode 100644 index 0000000000..d8f7965388 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/Cursor.js @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, Node: true*/ +/** + * @class + * A cursor is a dom node that visually represents a cursor in a DOM tree. + * It should stay synchronized with the selection in the document. When + * there is only one collapsed selection range, a cursor should be shown at + * that point. + * + * Putting the cursor in the DOM tree modifies the DOM, so care should be taken + * to keep the selection consistent. If e.g. a selection is drawn over the + * cursor, and the cursor is updated to the selection, the cursor is removed + * from the DOM because the selection is not collapsed. This means that the + * offsets of the selection may have to be changed. + * + * When the selection is collapsed, the cursor is placed after the point of the + * selection and the selection will stay valid. However, if the cursor was + * placed in the DOM tree and was counted in the offset, the offset in the + * selection should be decreased by one. + * + * Even when the selection allows for a cursor, it might be desireable to hide + * the cursor by not letting it be part of the DOM. + * + * @constructor + * @param {Selection} selection The selection to which the cursor corresponds + * @param {Document} document The document in which the cursor is placed + */ +core.Cursor = function Cursor(selection, document) { + "use strict"; + var cursorns, + cursorNode; + cursorns = 'urn:webodf:names:cursor'; + cursorNode = document.createElementNS(cursorns, 'cursor'); + + function putCursorIntoTextNode(container, offset) { + var len, ref, textnode, parent; + parent = container.parentNode; + if (offset === 0) { + parent.insertBefore(cursorNode, container); + } else if (offset === container.length) { + parent.appendChild(cursorNode); + } else { + len = container.length; + ref = container.nextSibling; + textnode = document.createTextNode( + container.substringData(offset, len) + ); + container.deleteData(offset, len); + if (ref) { + parent.insertBefore(textnode, ref); + } else { + parent.appendChild(textnode); + } + parent.insertBefore(cursorNode, textnode); + } + } + function putCursorIntoContainer(container, offset) { + var node; + node = container.firstChild; + while (node && offset) { + node = node.nextSibling; + offset -= 1; + } + container.insertBefore(cursorNode, node); + } + function getPotentialParentOrNode(parent, node) { + var n = node; + while (n && n !== parent) { + n = n.parentNode; + } + return n || node; + } + function removeCursorFromSelectionRange(range, cursorpos) { + var cursorParent, start, end; + cursorParent = cursorNode.parentNode; + start = getPotentialParentOrNode(cursorNode, range.startContainer); + end = getPotentialParentOrNode(cursorNode, range.endContainer); + if (start === cursorNode) { + range.setStart(cursorParent, cursorpos); + } else if (start === cursorParent && + range.startOffset > cursorpos) { + range.setStart(cursorParent, range.startOffset - 1); + } + if (range.endContainer === cursorNode) { + range.setEnd(cursorParent, cursorpos); + } else if (range.endContainer === cursorParent && + range.endOffset > cursorpos) { + range.setEnd(cursorParent, range.endOffset - 1); + } + } + function adaptRangeToMergedText(range, prev, textnodetomerge, cursorpos) { + var diff = prev.length - textnodetomerge.length; + if (range.startContainer === textnodetomerge) { + range.setStart(prev, diff + range.startOffset); + } else if (range.startContainer === prev.parentNode && + range.startOffset === cursorpos) { + range.setStart(prev, diff); + } + if (range.endContainer === textnodetomerge) { + range.setEnd(prev, diff + range.endOffset); + } else if (range.endContainer === prev.parentNode && + range.endOffset === cursorpos) { + range.setEnd(prev, diff); + } + } + function removeCursor() { + // if the cursor is part of a selection, the selection must be adapted + var i, cursorpos, node, textnodetoremove, range; + // if the cursor has no parent, it is already not part of the document + // tree + if (!cursorNode.parentNode) { + return; + } + // find the position of the cursor in its parent + cursorpos = 0; + node = cursorNode.parentNode.firstChild; + while (node && node !== cursorNode) { + cursorpos += 1; + node = node.nextSibling; + } + // Check if removing the node will result in a merge of texts. + // This will happen if the cursor is between two text nodes. + // The text of the text node after the cursor is put in the text node + // before the cursor. The latter node is removed after the selection + // has been adapted. + if (cursorNode.previousSibling && + cursorNode.previousSibling.nodeType === 3 && // TEXT_NODE + cursorNode.nextSibling && + cursorNode.nextSibling.nodeType === 3) { // TEXT_NODE + textnodetoremove = cursorNode.nextSibling; + cursorNode.previousSibling.appendData(textnodetoremove.nodeValue); + } + // remove the node from the selections + for (i = 0; i < selection.rangeCount; i += 1) { + removeCursorFromSelectionRange(selection.getRangeAt(i), cursorpos); + } + // merge the texts that surround the cursor + if (textnodetoremove) { + for (i = 0; i < selection.rangeCount; i += 1) { + adaptRangeToMergedText(selection.getRangeAt(i), + cursorNode.previousSibling, textnodetoremove, cursorpos); + } + textnodetoremove.parentNode.removeChild(textnodetoremove); + } + cursorNode.parentNode.removeChild(cursorNode); + } + // put the cursor at a particular position + function putCursor(container, offset) { + if (container.nodeType === 3) { // TEXT_NODE + putCursorIntoTextNode(container, offset); + } else if (container.nodeType !== 9) { // DOCUMENT_NODE + putCursorIntoContainer(container, offset); + } + } + /** + * Obtain the node representing the cursor. + * @return {Element} + */ + this.getNode = function () { + return cursorNode; + }; + /** + * Synchronize the cursor with the current selection. + * If there is a single collapsed selection range, the cursor will be placed + * there. If not, the cursor will be removed from the document tree. + * @return {undefined} + */ + this.updateToSelection = function () { + var range; + removeCursor(); + if (selection.focusNode) { + putCursor(selection.focusNode, selection.focusOffset); + } + }; + /** + * Remove the cursor from the document tree. + * @return {undefined} + */ + this.remove = function () { + removeCursor(); + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/JSLint.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/JSLint.js new file mode 100644 index 0000000000..b3e422ef59 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/JSLint.js @@ -0,0 +1,6403 @@ +// jslint.js +// 2012-04-15 + +// Copyright (c) 2002 Douglas Crockford (www.JSLint.com) + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// The Software shall be used for Good, not Evil. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// WARNING: JSLint will hurt your feelings. + +// JSLINT is a global function. It takes two parameters. + +// var myResult = JSLINT(source, option); + +// The first parameter is either a string or an array of strings. If it is a +// string, it will be split on '\n' or '\r'. If it is an array of strings, it +// is assumed that each string represents one line. The source can be a +// JavaScript text, or HTML text, or a JSON text, or a CSS text. + +// The second parameter is an optional object of options that control the +// operation of JSLINT. Most of the options are booleans: They are all +// optional and have a default value of false. One of the options, predef, +// can be an array of names, which will be used to declare global variables, +// or an object whose keys are used as global names, with a boolean value +// that determines if they are assignable. + +// If it checks out, JSLINT returns true. Otherwise, it returns false. + +// If false, you can inspect JSLINT.errors to find out the problems. +// JSLINT.errors is an array of objects containing these properties: + +// { +// line : The line (relative to 0) at which the lint was found +// character : The character (relative to 0) at which the lint was found +// reason : The problem +// evidence : The text line in which the problem occurred +// raw : The raw message before the details were inserted +// a : The first detail +// b : The second detail +// c : The third detail +// d : The fourth detail +// } + +// If a stopping error was found, a null will be the last element of the +// JSLINT.errors array. A stopping error means that JSLint was not confident +// enough to continue. It does not necessarily mean that the error was +// especially heinous. + +// You can request a Function Report, which shows all of the functions +// and the parameters and vars that they use. This can be used to find +// implied global variables and other problems. The report is in HTML and +// can be inserted in an HTML . + +// var myReport = JSLINT.report(errors_only); + +// If errors_only is true, then the report will be limited to only errors. + +// You can request a data structure that contains JSLint's results. + +// var myData = JSLINT.data(); + +// It returns a structure with this form: + +// { +// errors: [ +// { +// line: NUMBER, +// character: NUMBER, +// reason: STRING, +// evidence: STRING +// } +// ], +// functions: [ +// { +// name: STRING, +// line: NUMBER, +// last: NUMBER, +// params: [ +// { +// string: STRING +// } +// ], +// closure: [ +// STRING +// ], +// var: [ +// STRING +// ], +// exception: [ +// STRING +// ], +// outer: [ +// STRING +// ], +// unused: [ +// STRING +// ], +// undef: [ +// STRING +// ], +// global: [ +// STRING +// ], +// label: [ +// STRING +// ] +// } +// ], +// globals: [ +// STRING +// ], +// member: { +// STRING: NUMBER +// }, +// urls: [ +// STRING +// ], +// json: BOOLEAN +// } + +// Empty arrays will not be included. + +// You can obtain the parse tree that JSLint constructed while parsing. The +// latest tree is kept in JSLINT.tree. A nice stringication can be produced +// with + +// JSON.stringify(JSLINT.tree, [ +// 'string', 'arity', 'name', 'first', +// 'second', 'third', 'block', 'else' +// ], 4)); + +// JSLint provides three directives. They look like slashstar comments, and +// allow for setting options, declaring global variables, and establishing a +// set of allowed property names. + +// These directives respect function scope. + +// The jslint directive is a special comment that can set one or more options. +// The current option set is + +// anon true, if the space may be omitted in anonymous function declarations +// bitwise true, if bitwise operators should be allowed +// browser true, if the standard browser globals should be predefined +// cap true, if upper case HTML should be allowed +// 'continue' true, if the continuation statement should be tolerated +// css true, if CSS workarounds should be tolerated +// debug true, if debugger statements should be allowed +// devel true, if logging should be allowed (console, alert, etc.) +// eqeq true, if == should be allowed +// es5 true, if ES5 syntax should be allowed +// evil true, if eval should be allowed +// forin true, if for in statements need not filter +// fragment true, if HTML fragments should be allowed +// indent the indentation factor +// maxerr the maximum number of errors to allow +// maxlen the maximum length of a source line +// newcap true, if constructor names capitalization is ignored +// node true, if Node.js globals should be predefined +// nomen true, if names may have dangling _ +// on true, if HTML event handlers should be allowed +// passfail true, if the scan should stop on first error +// plusplus true, if increment/decrement should be allowed +// properties true, if all property names must be declared with /*properties*/ +// regexp true, if the . should be allowed in regexp literals +// rhino true, if the Rhino environment globals should be predefined +// undef true, if variables can be declared out of order +// unparam true, if unused parameters should be tolerated +// sloppy true, if the 'use strict'; pragma is optional +// stupid true, if really stupid practices are tolerated +// sub true, if all forms of subscript notation are tolerated +// vars true, if multiple var statements per function should be allowed +// white true, if sloppy whitespace is tolerated +// widget true if the Yahoo Widgets globals should be predefined +// windows true, if MS Windows-specific globals should be predefined + +// For example: + +/*jslint + evil: true, nomen: true, regexp: true +*/ + +// The properties directive declares an exclusive list of property names. +// Any properties named in the program that are not in the list will +// produce a warning. + +// For example: + +/*properties + '\b', '\t', '\n', '\f', '\r', '!', '!=', '!==', '"', '%', '\'', + '(arguments)', '(begin)', '(breakage)', '(context)', '(error)', + '(identifier)', '(line)', '(loopage)', '(name)', '(params)', '(scope)', + '(token)', '(vars)', '(verb)', '*', '+', '-', '/', '<', '<=', '==', + '===', '>', '>=', ADSAFE, Array, Date, Function, Object, '\\', a, + a_label, a_not_allowed, a_not_defined, a_scope, abbr, acronym, address, + adsafe, adsafe_a, adsafe_autocomplete, adsafe_bad_id, adsafe_div, + adsafe_fragment, adsafe_go, adsafe_html, adsafe_id, adsafe_id_go, adsafe_lib, + adsafe_lib_second, adsafe_missing_id, adsafe_name_a, adsafe_placement, + adsafe_prefix_a, adsafe_script, adsafe_source, adsafe_subscript_a, + adsafe_tag, all, already_defined, and, anon, applet, apply, approved, area, + arity, article, aside, assign, assign_exception, + assignment_function_expression, at, attribute_case_a, audio, autocomplete, + avoid_a, b, background, 'background-attachment', 'background-color', + 'background-image', 'background-position', 'background-repeat', + bad_assignment, bad_color_a, bad_constructor, bad_entity, bad_html, bad_id_a, + bad_in_a, bad_invocation, bad_name_a, bad_new, bad_number, bad_operand, + bad_style, bad_type, bad_url_a, bad_wrap, base, bdo, big, bitwise, block, + blockquote, body, border, 'border-bottom', 'border-bottom-color', + 'border-bottom-left-radius', 'border-bottom-right-radius', + 'border-bottom-style', 'border-bottom-width', 'border-collapse', + 'border-color', 'border-left', 'border-left-color', 'border-left-style', + 'border-left-width', 'border-radius', 'border-right', 'border-right-color', + 'border-right-style', 'border-right-width', 'border-spacing', 'border-style', + 'border-top', 'border-top-color', 'border-top-left-radius', + 'border-top-right-radius', 'border-top-style', 'border-top-width', + 'border-width', bottom, br, braille, browser, button, c, call, canvas, cap, + caption, 'caption-side', center, charAt, charCodeAt, character, cite, clear, + clip, closure, cm, code, col, colgroup, color, combine_var, command, + conditional_assignment, confusing_a, confusing_regexp, constructor_name_a, + content, continue, control_a, 'counter-increment', 'counter-reset', create, + css, cursor, d, dangerous_comment, dangling_a, data, datalist, dd, debug, + del, deleted, details, devel, dfn, dialog, dir, direction, display, disrupt, + div, dl, dt, duplicate_a, edge, edition, else, em, embed, embossed, empty, + 'empty-cells', empty_block, empty_case, empty_class, entityify, eqeq, errors, + es5, eval, evidence, evil, ex, exception, exec, expected_a, + expected_a_at_b_c, expected_a_b, expected_a_b_from_c_d, expected_at_a, + expected_attribute_a, expected_attribute_value_a, expected_class_a, + expected_fraction_a, expected_id_a, expected_identifier_a, + expected_identifier_a_reserved, expected_lang_a, expected_linear_a, + expected_media_a, expected_name_a, expected_nonstandard_style_attribute, + expected_number_a, expected_operator_a, expected_percent_a, + expected_positive_a, expected_pseudo_a, expected_selector_a, + expected_small_a, expected_space_a_b, expected_string_a, + expected_style_attribute, expected_style_pattern, expected_tagname_a, + expected_type_a, f, fieldset, figure, filter, first, flag, float, floor, + font, 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', + 'font-style', 'font-variant', 'font-weight', footer, forEach, for_if, forin, + form, fragment, frame, frameset, from, fromCharCode, fud, funct, function, + function_block, function_eval, function_loop, function_statement, + function_strict, functions, global, globals, h1, h2, h3, h4, h5, h6, + handheld, hasOwnProperty, head, header, height, hgroup, hr, + 'hta:application', html, html_confusion_a, html_handlers, i, id, identifier, + identifier_function, iframe, img, immed, implied_evil, in, indent, indexOf, + infix_in, init, input, ins, insecure_a, isAlpha, isArray, isDigit, isNaN, + join, jslint, json, kbd, keygen, keys, label, labeled, lang, lbp, + leading_decimal_a, led, left, legend, length, 'letter-spacing', li, lib, + line, 'line-height', link, 'list-style', 'list-style-image', + 'list-style-position', 'list-style-type', map, margin, 'margin-bottom', + 'margin-left', 'margin-right', 'margin-top', mark, 'marker-offset', match, + 'max-height', 'max-width', maxerr, maxlen, member, menu, message, meta, + meter, 'min-height', 'min-width', missing_a, missing_a_after_b, + missing_option, missing_property, missing_space_a_b, missing_url, + missing_use_strict, mixed, mm, mode, move_invocation, move_var, n, name, + name_function, nav, nested_comment, newcap, node, noframes, nomen, noscript, + not, not_a_constructor, not_a_defined, not_a_function, not_a_label, + not_a_scope, not_greater, nud, number, object, octal_a, ol, on, opacity, + open, optgroup, option, outer, outline, 'outline-color', 'outline-style', + 'outline-width', output, overflow, 'overflow-x', 'overflow-y', p, padding, + 'padding-bottom', 'padding-left', 'padding-right', 'padding-top', + 'page-break-after', 'page-break-before', param, parameter_a_get_b, + parameter_arguments_a, parameter_set_a, params, paren, parent, passfail, pc, + plusplus, pop, position, postscript, pre, predef, print, progress, + projection, properties, prototype, pt, push, px, q, quote, quotes, r, radix, + range, raw, read_only, reason, redefinition_a, regexp, replace, report, + reserved, reserved_a, rhino, right, rp, rt, ruby, safe, samp, scanned_a_b, + screen, script, search, second, section, select, shift, slash_equal, slice, + sloppy, small, sort, source, span, speech, split, src, statement_block, + stopping, strange_loop, strict, string, strong, stupid, style, styleproperty, + sub, subscript, substr, sup, supplant, sync_a, t, table, 'table-layout', + tag_a_in_b, tbody, td, test, 'text-align', 'text-decoration', 'text-indent', + 'text-shadow', 'text-transform', textarea, tfoot, th, thead, third, thru, + time, title, toLowerCase, toString, toUpperCase, token, too_long, too_many, + top, tr, trailing_decimal_a, tree, tt, tty, tv, type, u, ul, unclosed, + unclosed_comment, unclosed_regexp, undef, undefined, unescaped_a, + unexpected_a, unexpected_char_a_b, unexpected_comment, unexpected_else, + unexpected_label_a, unexpected_property_a, unexpected_space_a_b, + 'unicode-bidi', unnecessary_initialize, unnecessary_use, unparam, + unreachable_a_b, unrecognized_style_attribute_a, unrecognized_tag_a, unsafe, + unused, url, urls, use_array, use_braces, use_charAt, use_object, use_or, + use_param, used_before_a, var, var_a_not, vars, 'vertical-align', video, + visibility, was, weird_assignment, weird_condition, weird_new, weird_program, + weird_relation, weird_ternary, white, 'white-space', widget, width, windows, + 'word-spacing', 'word-wrap', wrap, wrap_immediate, wrap_regexp, + write_is_wrong, writeable, 'z-index' +*/ + +// The global directive is used to declare global variables that can +// be accessed by the program. If a declaration is true, then the variable +// is writeable. Otherwise, it is read-only. + +// We build the application inside a function so that we produce only a single +// global variable. That function will be invoked immediately, and its return +// value is the JSLINT function itself. That function is also an object that +// can contain data and other functions. + +var JSLINT = (function () { + 'use strict'; + + function array_to_object(array, value) { + +// Make an object from an array of keys and a common value. + + var i, length = array.length, object = {}; + for (i = 0; i < length; i += 1) { + object[array[i]] = value; + } + return object; + } + + + var adsafe_id, // The widget's ADsafe id. + adsafe_may, // The widget may load approved scripts. + adsafe_top, // At the top of the widget script. + adsafe_went, // ADSAFE.go has been called. + allowed_option = { + anon : true, + bitwise : true, + browser : true, + cap : true, + 'continue': true, + css : true, + debug : true, + devel : true, + eqeq : true, + es5 : true, + evil : true, + forin : true, + fragment : true, + indent : 10, + maxerr : 1000, + maxlen : 256, + newcap : true, + node : true, + nomen : true, + on : true, + passfail : true, + plusplus : true, + properties: true, + regexp : true, + rhino : true, + undef : true, + unparam : true, + sloppy : true, + stupid : true, + sub : true, + vars : true, + white : true, + widget : true, + windows : true + }, + anonname, // The guessed name for anonymous functions. + approved, // ADsafe approved urls. + +// These are operators that should not be used with the ! operator. + + bang = { + '<' : true, + '<=' : true, + '==' : true, + '===': true, + '!==': true, + '!=' : true, + '>' : true, + '>=' : true, + '+' : true, + '-' : true, + '*' : true, + '/' : true, + '%' : true + }, + +// These are property names that should not be permitted in the safe subset. + + banned = array_to_object([ + 'arguments', 'callee', 'caller', 'constructor', 'eval', 'prototype', + 'stack', 'unwatch', 'valueOf', 'watch' + ], true), + begin, // The root token + +// browser contains a set of global names that are commonly provided by a +// web browser environment. + + browser = array_to_object([ + 'clearInterval', 'clearTimeout', 'document', 'event', 'FormData', + 'frames', 'history', 'Image', 'localStorage', 'location', 'name', + 'navigator', 'Option', 'parent', 'screen', 'sessionStorage', + 'setInterval', 'setTimeout', 'Storage', 'window', 'XMLHttpRequest' + ], false), + +// bundle contains the text messages. + + bundle = { + a_label: "'{a}' is a statement label.", + a_not_allowed: "'{a}' is not allowed.", + a_not_defined: "'{a}' is not defined.", + a_scope: "'{a}' used out of scope.", + adsafe_a: "ADsafe violation: '{a}'.", + adsafe_autocomplete: "ADsafe autocomplete violation.", + adsafe_bad_id: "ADSAFE violation: bad id.", + adsafe_div: "ADsafe violation: Wrap the widget in a div.", + adsafe_fragment: "ADSAFE: Use the fragment option.", + adsafe_go: "ADsafe violation: Misformed ADSAFE.go.", + adsafe_html: "Currently, ADsafe does not operate on whole HTML " + + "documents. It operates on
fragments and .js files.", + adsafe_id: "ADsafe violation: id does not match.", + adsafe_id_go: "ADsafe violation: Missing ADSAFE.id or ADSAFE.go.", + adsafe_lib: "ADsafe lib violation.", + adsafe_lib_second: "ADsafe: The second argument to lib must be a function.", + adsafe_missing_id: "ADSAFE violation: missing ID_.", + adsafe_name_a: "ADsafe name violation: '{a}'.", + adsafe_placement: "ADsafe script placement violation.", + adsafe_prefix_a: "ADsafe violation: An id must have a '{a}' prefix", + adsafe_script: "ADsafe script violation.", + adsafe_source: "ADsafe unapproved script source.", + adsafe_subscript_a: "ADsafe subscript '{a}'.", + adsafe_tag: "ADsafe violation: Disallowed tag '{a}'.", + already_defined: "'{a}' is already defined.", + and: "The '&&' subexpression should be wrapped in parens.", + assign_exception: "Do not assign to the exception parameter.", + assignment_function_expression: "Expected an assignment or " + + "function call and instead saw an expression.", + attribute_case_a: "Attribute '{a}' not all lower case.", + avoid_a: "Avoid '{a}'.", + bad_assignment: "Bad assignment.", + bad_color_a: "Bad hex color '{a}'.", + bad_constructor: "Bad constructor.", + bad_entity: "Bad entity.", + bad_html: "Bad HTML string", + bad_id_a: "Bad id: '{a}'.", + bad_in_a: "Bad for in variable '{a}'.", + bad_invocation: "Bad invocation.", + bad_name_a: "Bad name: '{a}'.", + bad_new: "Do not use 'new' for side effects.", + bad_number: "Bad number '{a}'.", + bad_operand: "Bad operand.", + bad_style: "Bad style.", + bad_type: "Bad type.", + bad_url_a: "Bad url '{a}'.", + bad_wrap: "Do not wrap function literals in parens unless they " + + "are to be immediately invoked.", + combine_var: "Combine this with the previous 'var' statement.", + conditional_assignment: "Expected a conditional expression and " + + "instead saw an assignment.", + confusing_a: "Confusing use of '{a}'.", + confusing_regexp: "Confusing regular expression.", + constructor_name_a: "A constructor name '{a}' should start with " + + "an uppercase letter.", + control_a: "Unexpected control character '{a}'.", + css: "A css file should begin with @charset 'UTF-8';", + dangling_a: "Unexpected dangling '_' in '{a}'.", + dangerous_comment: "Dangerous comment.", + deleted: "Only properties should be deleted.", + duplicate_a: "Duplicate '{a}'.", + empty_block: "Empty block.", + empty_case: "Empty case.", + empty_class: "Empty class.", + es5: "This is an ES5 feature.", + evil: "eval is evil.", + expected_a: "Expected '{a}'.", + expected_a_b: "Expected '{a}' and instead saw '{b}'.", + expected_a_b_from_c_d: "Expected '{a}' to match '{b}' from line " + + "{c} and instead saw '{d}'.", + expected_at_a: "Expected an at-rule, and instead saw @{a}.", + expected_a_at_b_c: "Expected '{a}' at column {b}, not column {c}.", + expected_attribute_a: "Expected an attribute, and instead saw [{a}].", + expected_attribute_value_a: "Expected an attribute value and " + + "instead saw '{a}'.", + expected_class_a: "Expected a class, and instead saw .{a}.", + expected_fraction_a: "Expected a number between 0 and 1 and " + + "instead saw '{a}'", + expected_id_a: "Expected an id, and instead saw #{a}.", + expected_identifier_a: "Expected an identifier and instead saw '{a}'.", + expected_identifier_a_reserved: "Expected an identifier and " + + "instead saw '{a}' (a reserved word).", + expected_linear_a: "Expected a linear unit and instead saw '{a}'.", + expected_lang_a: "Expected a lang code, and instead saw :{a}.", + expected_media_a: "Expected a CSS media type, and instead saw '{a}'.", + expected_name_a: "Expected a name and instead saw '{a}'.", + expected_nonstandard_style_attribute: "Expected a non-standard " + + "style attribute and instead saw '{a}'.", + expected_number_a: "Expected a number and instead saw '{a}'.", + expected_operator_a: "Expected an operator and instead saw '{a}'.", + expected_percent_a: "Expected a percentage and instead saw '{a}'", + expected_positive_a: "Expected a positive number and instead saw '{a}'", + expected_pseudo_a: "Expected a pseudo, and instead saw :{a}.", + expected_selector_a: "Expected a CSS selector, and instead saw {a}.", + expected_small_a: "Expected a small positive integer and instead saw '{a}'", + expected_space_a_b: "Expected exactly one space between '{a}' and '{b}'.", + expected_string_a: "Expected a string and instead saw {a}.", + expected_style_attribute: "Excepted a style attribute, and instead saw '{a}'.", + expected_style_pattern: "Expected a style pattern, and instead saw '{a}'.", + expected_tagname_a: "Expected a tagName, and instead saw {a}.", + expected_type_a: "Expected a type, and instead saw {a}.", + for_if: "The body of a for in should be wrapped in an if " + + "statement to filter unwanted properties from the prototype.", + function_block: "Function statements should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", + function_eval: "The Function constructor is eval.", + function_loop: "Don't make functions within a loop.", + function_statement: "Function statements are not invocable. " + + "Wrap the whole function invocation in parens.", + function_strict: "Use the function form of 'use strict'.", + html_confusion_a: "HTML confusion in regular expression '<{a}'.", + html_handlers: "Avoid HTML event handlers.", + identifier_function: "Expected an identifier in an assignment " + + "and instead saw a function invocation.", + implied_evil: "Implied eval is evil. Pass a function instead of a string.", + infix_in: "Unexpected 'in'. Compare with undefined, or use the " + + "hasOwnProperty method instead.", + insecure_a: "Insecure '{a}'.", + isNaN: "Use the isNaN function to compare with NaN.", + lang: "lang is deprecated.", + leading_decimal_a: "A leading decimal point can be confused with a dot: '.{a}'.", + missing_a: "Missing '{a}'.", + missing_a_after_b: "Missing '{a}' after '{b}'.", + missing_option: "Missing option value.", + missing_property: "Missing property name.", + missing_space_a_b: "Missing space between '{a}' and '{b}'.", + missing_url: "Missing url.", + missing_use_strict: "Missing 'use strict' statement.", + mixed: "Mixed spaces and tabs.", + move_invocation: "Move the invocation into the parens that " + + "contain the function.", + move_var: "Move 'var' declarations to the top of the function.", + name_function: "Missing name in function statement.", + nested_comment: "Nested comment.", + not: "Nested not.", + not_a_constructor: "Do not use {a} as a constructor.", + not_a_defined: "'{a}' has not been fully defined yet.", + not_a_function: "'{a}' is not a function.", + not_a_label: "'{a}' is not a label.", + not_a_scope: "'{a}' is out of scope.", + not_greater: "'{a}' should not be greater than '{b}'.", + octal_a: "Don't use octal: '{a}'. Use '\\u....' instead.", + parameter_arguments_a: "Do not mutate parameter '{a}' when using 'arguments'.", + parameter_a_get_b: "Unexpected parameter '{a}' in get {b} function.", + parameter_set_a: "Expected parameter (value) in set {a} function.", + radix: "Missing radix parameter.", + read_only: "Read only.", + redefinition_a: "Redefinition of '{a}'.", + reserved_a: "Reserved name '{a}'.", + scanned_a_b: "{a} ({b}% scanned).", + slash_equal: "A regular expression literal can be confused with '/='.", + statement_block: "Expected to see a statement and instead saw a block.", + stopping: "Stopping. ", + strange_loop: "Strange loop.", + strict: "Strict violation.", + subscript: "['{a}'] is better written in dot notation.", + sync_a: "Unexpected sync method: '{a}'.", + tag_a_in_b: "A '<{a}>' must be within '<{b}>'.", + too_long: "Line too long.", + too_many: "Too many errors.", + trailing_decimal_a: "A trailing decimal point can be confused " + + "with a dot: '.{a}'.", + type: "type is unnecessary.", + unclosed: "Unclosed string.", + unclosed_comment: "Unclosed comment.", + unclosed_regexp: "Unclosed regular expression.", + unescaped_a: "Unescaped '{a}'.", + unexpected_a: "Unexpected '{a}'.", + unexpected_char_a_b: "Unexpected character '{a}' in {b}.", + unexpected_comment: "Unexpected comment.", + unexpected_else: "Unexpected 'else' after 'return'.", + unexpected_label_a: "Unexpected label '{a}'.", + unexpected_property_a: "Unexpected /*property*/ '{a}'.", + unexpected_space_a_b: "Unexpected space between '{a}' and '{b}'.", + unnecessary_initialize: "It is not necessary to initialize '{a}' " + + "to 'undefined'.", + unnecessary_use: "Unnecessary 'use strict'.", + unreachable_a_b: "Unreachable '{a}' after '{b}'.", + unrecognized_style_attribute_a: "Unrecognized style attribute '{a}'.", + unrecognized_tag_a: "Unrecognized tag '<{a}>'.", + unsafe: "Unsafe character.", + url: "JavaScript URL.", + use_array: "Use the array literal notation [].", + use_braces: "Spaces are hard to count. Use {{a}}.", + use_charAt: "Use the charAt method.", + use_object: "Use the object literal notation {}.", + use_or: "Use the || operator.", + use_param: "Use a named parameter.", + used_before_a: "'{a}' was used before it was defined.", + var_a_not: "Variable {a} was not declared correctly.", + weird_assignment: "Weird assignment.", + weird_condition: "Weird condition.", + weird_new: "Weird construction. Delete 'new'.", + weird_program: "Weird program.", + weird_relation: "Weird relation.", + weird_ternary: "Weird ternary.", + wrap_immediate: "Wrap an immediate function invocation in parentheses " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself.", + wrap_regexp: "Wrap the /regexp/ literal in parens to " + + "disambiguate the slash operator.", + write_is_wrong: "document.write can be a form of eval." + }, + comments_off, + css_attribute_data, + css_any, + + css_colorData = array_to_object([ + "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", + "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", + "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", + "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", + "darkcyan", "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", + "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", + "darkred", "darksalmon", "darkseagreen", "darkslateblue", + "darkslategray", "darkturquoise", "darkviolet", "deeppink", + "deepskyblue", "dimgray", "dodgerblue", "firebrick", "floralwhite", + "forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", + "goldenrod", "gray", "green", "greenyellow", "honeydew", "hotpink", + "indianred", "indigo", "ivory", "khaki", "lavender", + "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", + "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgreen", + "lightpink", "lightsalmon", "lightseagreen", "lightskyblue", + "lightslategray", "lightsteelblue", "lightyellow", "lime", + "limegreen", "linen", "magenta", "maroon", "mediumaquamarine", + "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", + "mediumslateblue", "mediumspringgreen", "mediumturquoise", + "mediumvioletred", "midnightblue", "mintcream", "mistyrose", + "moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab", + "orange", "orangered", "orchid", "palegoldenrod", "palegreen", + "paleturquoise", "palevioletred", "papayawhip", "peachpuff", + "peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown", + "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", + "seashell", "sienna", "silver", "skyblue", "slateblue", "slategray", + "snow", "springgreen", "steelblue", "tan", "teal", "thistle", + "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", + "yellow", "yellowgreen", + + "activeborder", "activecaption", "appworkspace", "background", + "buttonface", "buttonhighlight", "buttonshadow", "buttontext", + "captiontext", "graytext", "highlight", "highlighttext", + "inactiveborder", "inactivecaption", "inactivecaptiontext", + "infobackground", "infotext", "menu", "menutext", "scrollbar", + "threeddarkshadow", "threedface", "threedhighlight", + "threedlightshadow", "threedshadow", "window", "windowframe", + "windowtext" + ], true), + + css_border_style, + css_break, + + css_lengthData = { + '%': true, + 'cm': true, + 'em': true, + 'ex': true, + 'in': true, + 'mm': true, + 'pc': true, + 'pt': true, + 'px': true + }, + + css_media, + css_overflow, + + descapes = { + 'b': '\b', + 't': '\t', + 'n': '\n', + 'f': '\f', + 'r': '\r', + '"': '"', + '/': '/', + '\\': '\\', + '!': '!' + }, + + devel = array_to_object([ + 'alert', 'confirm', 'console', 'Debug', 'opera', 'prompt', 'WSH' + ], false), + directive, + escapes = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\'': '\\\'', + '"' : '\\"', + '/' : '\\/', + '\\': '\\\\' + }, + + funct, // The current function, including the labels used in + // the function, as well as (breakage), + // (context), (loopage), (name), (params), (token), + // (vars), (verb) + + functionicity = [ + 'closure', 'exception', 'global', 'label', 'outer', 'undef', + 'unused', 'var' + ], + + functions, // All of the functions + global_funct, // The global body + global_scope, // The global scope + html_tag = { + a: {}, + abbr: {}, + acronym: {}, + address: {}, + applet: {}, + area: {empty: true, parent: ' map '}, + article: {}, + aside: {}, + audio: {}, + b: {}, + base: {empty: true, parent: ' head '}, + bdo: {}, + big: {}, + blockquote: {}, + body: {parent: ' html noframes '}, + br: {empty: true}, + button: {}, + canvas: {parent: ' body p div th td '}, + caption: {parent: ' table '}, + center: {}, + cite: {}, + code: {}, + col: {empty: true, parent: ' table colgroup '}, + colgroup: {parent: ' table '}, + command: {parent: ' menu '}, + datalist: {}, + dd: {parent: ' dl '}, + del: {}, + details: {}, + dialog: {}, + dfn: {}, + dir: {}, + div: {}, + dl: {}, + dt: {parent: ' dl '}, + em: {}, + embed: {}, + fieldset: {}, + figure: {}, + font: {}, + footer: {}, + form: {}, + frame: {empty: true, parent: ' frameset '}, + frameset: {parent: ' html frameset '}, + h1: {}, + h2: {}, + h3: {}, + h4: {}, + h5: {}, + h6: {}, + head: {parent: ' html '}, + header: {}, + hgroup: {}, + hr: {empty: true}, + 'hta:application': + {empty: true, parent: ' head '}, + html: {parent: '*'}, + i: {}, + iframe: {}, + img: {empty: true}, + input: {empty: true}, + ins: {}, + kbd: {}, + keygen: {}, + label: {}, + legend: {parent: ' details fieldset figure '}, + li: {parent: ' dir menu ol ul '}, + link: {empty: true, parent: ' head '}, + map: {}, + mark: {}, + menu: {}, + meta: {empty: true, parent: ' head noframes noscript '}, + meter: {}, + nav: {}, + noframes: {parent: ' html body '}, + noscript: {parent: ' body head noframes '}, + object: {}, + ol: {}, + optgroup: {parent: ' select '}, + option: {parent: ' optgroup select '}, + output: {}, + p: {}, + param: {empty: true, parent: ' applet object '}, + pre: {}, + progress: {}, + q: {}, + rp: {}, + rt: {}, + ruby: {}, + samp: {}, + script: {empty: true, parent: ' body div frame head iframe p pre span '}, + section: {}, + select: {}, + small: {}, + span: {}, + source: {}, + strong: {}, + style: {parent: ' head ', empty: true}, + sub: {}, + sup: {}, + table: {}, + tbody: {parent: ' table '}, + td: {parent: ' tr '}, + textarea: {}, + tfoot: {parent: ' table '}, + th: {parent: ' tr '}, + thead: {parent: ' table '}, + time: {}, + title: {parent: ' head '}, + tr: {parent: ' table tbody thead tfoot '}, + tt: {}, + u: {}, + ul: {}, + 'var': {}, + video: {} + }, + + ids, // HTML ids + in_block, + indent, + itself, // JSLint itself + json_mode, + lex, // the tokenizer + lines, + lookahead, + node = array_to_object([ + 'Buffer', 'clearInterval', 'clearTimeout', 'console', 'exports', + 'global', 'module', 'process', 'querystring', 'require', + 'setInterval', 'setTimeout', '__dirname', '__filename' + ], false), + node_js, + numbery = array_to_object(['indexOf', 'lastIndexOf', 'search'], true), + next_token, + option, + predefined, // Global variables defined by option + prereg, + prev_token, + property, + regexp_flag = array_to_object(['g', 'i', 'm'], true), + return_this = function return_this() { + return this; + }, + rhino = array_to_object([ + 'defineClass', 'deserialize', 'gc', 'help', 'load', 'loadClass', + 'print', 'quit', 'readFile', 'readUrl', 'runCommand', 'seal', + 'serialize', 'spawn', 'sync', 'toint32', 'version' + ], false), + + scope, // An object containing an object for each variable in scope + semicolon_coda = array_to_object([';', '"', '\'', ')'], true), + src, + stack, + +// standard contains the global names that are provided by the +// ECMAScript standard. + + standard = array_to_object([ + 'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent', + 'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError', + 'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number', + 'Object', 'parseInt', 'parseFloat', 'RangeError', 'ReferenceError', + 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError' + ], false), + + strict_mode, + syntax = {}, + tab, + token, + urls, + var_mode, + warnings, + +// widget contains the global names which are provided to a Yahoo +// (fna Konfabulator) widget. + + widget = array_to_object([ + 'alert', 'animator', 'appleScript', 'beep', 'bytesToUIString', + 'Canvas', 'chooseColor', 'chooseFile', 'chooseFolder', + 'closeWidget', 'COM', 'convertPathToHFS', 'convertPathToPlatform', + 'CustomAnimation', 'escape', 'FadeAnimation', 'filesystem', 'Flash', + 'focusWidget', 'form', 'FormField', 'Frame', 'HotKey', 'Image', + 'include', 'isApplicationRunning', 'iTunes', 'konfabulatorVersion', + 'log', 'md5', 'MenuItem', 'MoveAnimation', 'openURL', 'play', + 'Point', 'popupMenu', 'preferenceGroups', 'preferences', 'print', + 'prompt', 'random', 'Rectangle', 'reloadWidget', 'ResizeAnimation', + 'resolvePath', 'resumeUpdates', 'RotateAnimation', 'runCommand', + 'runCommandInBg', 'saveAs', 'savePreferences', 'screen', + 'ScrollBar', 'showWidgetPreferences', 'sleep', 'speak', 'Style', + 'suppressUpdates', 'system', 'tellWidget', 'Text', 'TextArea', + 'Timer', 'unescape', 'updateNow', 'URL', 'Web', 'widget', 'Window', + 'XMLDOM', 'XMLHttpRequest', 'yahooCheckLogin', 'yahooLogin', + 'yahooLogout' + ], true), + + windows = array_to_object([ + 'ActiveXObject', 'CScript', 'Debug', 'Enumerator', 'System', + 'VBArray', 'WScript', 'WSH' + ], false), + +// xmode is used to adapt to the exceptions in html parsing. +// It can have these states: +// '' .js script file +// 'html' +// 'outer' +// 'script' +// 'style' +// 'scriptstring' +// 'styleproperty' + + xmode, + xquote, + +// Regular expressions. Some of these are stupidly long. + +// unsafe comment or string + ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i, +// carriage return, carriage return linefeed, or linefeed + crlfx = /\r\n?|\n/, +// unsafe characters that are silently deleted by one or more browsers + cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, +// query characters for ids + dx = /[\[\]\/\\"'*<>.&:(){}+=#]/, +// html token + hx = /^\s*(['"=>\/&#]|<(?:\/|\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\-:]*|[0-9]+|--)/, +// identifier + ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/, +// javascript url + jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i, +// star slash + lx = /\*\/|\/\*/, +// characters in strings that need escapement + nx = /[\u0000-\u001f'\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, +// outer html token + ox = /[>&]|<[\/!]?|--/, +// attributes characters + qx = /[^a-zA-Z0-9+\-_\/. ]/, +// style + sx = /^\s*([{}:#%.=,>+\[\]@()"';]|[*$\^~]=|[a-zA-Z_][a-zA-Z0-9_\-]*|[0-9]+|<\/|\/\*)/, + ssx = /^\s*([@#!"'};:\-%.=,+\[\]()*_]|[a-zA-Z][a-zA-Z0-9._\-]*|\/\*?|\d+(?:\.\d+)?|<\/)/, +// token + tx = /^\s*([(){}\[\]\?.,:;'"~#@`]|={1,3}|\/(\*(jslint|properties|property|members?|globals?)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|[\^%]=?|&[&=]?|\|[|=]?|>{1,3}=?|<(?:[\/=!]|\!(\[|--)?|<=?)?|\!={0,2}|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\.[0-9]*)?(?:[eE][+\-]?[0-9]+)?)/, +// url badness + ux = /&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto|script/i, + + rx = { + outer: hx, + html: hx, + style: sx, + styleproperty: ssx + }; + + + function F() {} // Used by Object.create + +// Provide critical ES5 functions to ES3. + + if (typeof Array.prototype.filter !== 'function') { + Array.prototype.filter = function (f) { + var i, length = this.length, result = [], value; + for (i = 0; i < length; i += 1) { + try { + value = this[i]; + if (f(value)) { + result.push(value); + } + } catch (ignore) { + } + } + return result; + }; + } + + if (typeof Array.prototype.forEach !== 'function') { + Array.prototype.forEach = function (f) { + var i, length = this.length; + for (i = 0; i < length; i += 1) { + try { + f(this[i]); + } catch (ignore) { + } + } + }; + } + + if (typeof Array.isArray !== 'function') { + Array.isArray = function (o) { + return Object.prototype.toString.apply(o) === '[object Array]'; + }; + } + + if (!Object.prototype.hasOwnProperty.call(Object, 'create')) { + Object.create = function (o) { + F.prototype = o; + return new F(); + }; + } + + if (typeof Object.keys !== 'function') { + Object.keys = function (o) { + var array = [], key; + for (key in o) { + if (Object.prototype.hasOwnProperty.call(o, key)) { + array.push(key); + } + } + return array; + }; + } + + if (typeof String.prototype.entityify !== 'function') { + String.prototype.entityify = function () { + return this + .replace(/&/g, '&') + .replace(//g, '>'); + }; + } + + if (typeof String.prototype.isAlpha !== 'function') { + String.prototype.isAlpha = function () { + return (this >= 'a' && this <= 'z\uffff') || + (this >= 'A' && this <= 'Z\uffff'); + }; + } + + if (typeof String.prototype.isDigit !== 'function') { + String.prototype.isDigit = function () { + return (this >= '0' && this <= '9'); + }; + } + + if (typeof String.prototype.supplant !== 'function') { + String.prototype.supplant = function (o) { + return this.replace(/\{([^{}]*)\}/g, function (a, b) { + var replacement = o[b]; + return typeof replacement === 'string' || + typeof replacement === 'number' ? replacement : a; + }); + }; + } + + + function sanitize(a) { + +// Escapify a troublesome character. + + return escapes[a] || + '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); + } + + + function add_to_predefined(group) { + Object.keys(group).forEach(function (name) { + predefined[name] = group[name]; + }); + } + + + function assume() { + if (!option.safe) { + if (option.rhino) { + add_to_predefined(rhino); + option.rhino = false; + } + if (option.devel) { + add_to_predefined(devel); + option.devel = false; + } + if (option.browser) { + add_to_predefined(browser); + option.browser = false; + } + if (option.windows) { + add_to_predefined(windows); + option.windows = false; + } + if (option.node) { + add_to_predefined(node); + option.node = false; + node_js = true; + } + if (option.widget) { + add_to_predefined(widget); + option.widget = false; + } + } + } + + +// Produce an error warning. + + function artifact(tok) { + if (!tok) { + tok = next_token; + } + return tok.number || tok.string; + } + + function quit(message, line, character) { + throw { + name: 'JSLintError', + line: line, + character: character, + message: bundle.scanned_a_b.supplant({ + a: message, + b: Math.floor((line / lines.length) * 100) + }) + }; + } + + function warn(message, offender, a, b, c, d) { + var character, line, warning; + offender = offender || next_token; // ~~ + line = offender.line || 0; + character = offender.from || 0; + warning = { + id: '(error)', + raw: bundle[message] || message, + evidence: lines[line - 1] || '', + line: line, + character: character, + a: a || (offender.id === '(number)' + ? String(offender.number) + : offender.string), + b: b, + c: c, + d: d + }; + warning.reason = warning.raw.supplant(warning); + JSLINT.errors.push(warning); + if (option.passfail) { + quit(bundle.stopping, line, character); + } + warnings += 1; + if (warnings >= option.maxerr) { + quit(bundle.too_many, line, character); + } + return warning; + } + + function warn_at(message, line, character, a, b, c, d) { + return warn(message, { + line: line, + from: character + }, a, b, c, d); + } + + function stop(message, offender, a, b, c, d) { + var warning = warn(message, offender, a, b, c, d); + quit(bundle.stopping, warning.line, warning.character); + } + + function stop_at(message, line, character, a, b, c, d) { + return stop(message, { + line: line, + from: character + }, a, b, c, d); + } + + function expected_at(at) { + if (!option.white && next_token.from !== at) { + warn('expected_a_at_b_c', next_token, '', at, + next_token.from); + } + } + + function aint(it, name, expected) { + if (it[name] !== expected) { + warn('expected_a_b', it, expected, it[name]); + return true; + } + return false; + } + + +// lexical analysis and token construction + + lex = (function lex() { + var character, c, from, length, line, pos, source_row; + +// Private lex methods + + function next_line() { + var at; + if (line >= lines.length) { + return false; + } + character = 1; + source_row = lines[line]; + line += 1; + at = source_row.search(/ \t/); + if (at >= 0) { + warn_at('mixed', line, at + 1); + } + source_row = source_row.replace(/\t/g, tab); + at = source_row.search(cx); + if (at >= 0) { + warn_at('unsafe', line, at); + } + if (option.maxlen && option.maxlen < source_row.length) { + warn_at('too_long', line, source_row.length); + } + return true; + } + +// Produce a token object. The token inherits from a syntax symbol. + + function it(type, value) { + var id, the_token; + if (type === '(string)' || type === '(range)') { + if (jx.test(value)) { + warn_at('url', line, from); + } + } + the_token = Object.create(syntax[( + type === '(punctuator)' || (type === '(identifier)' && + Object.prototype.hasOwnProperty.call(syntax, value)) + ? value + : type + )] || syntax['(error)']); + if (type === '(identifier)') { + the_token.identifier = true; + if (value === '__iterator__' || value === '__proto__') { + stop_at('reserved_a', line, from, value); + } else if (!option.nomen && + (value.charAt(0) === '_' || + value.charAt(value.length - 1) === '_')) { + warn_at('dangling_a', line, from, value); + } + } + if (type === '(number)') { + the_token.number = +value; + } else if (value !== undefined) { + the_token.string = String(value); + } + the_token.line = line; + the_token.from = from; + the_token.thru = character; + id = the_token.id; + prereg = id && ( + ('(,=:[!&|?{};'.indexOf(id.charAt(id.length - 1)) >= 0) || + id === 'return' || id === 'case' + ); + return the_token; + } + + function match(x) { + var exec = x.exec(source_row), first; + if (exec) { + length = exec[0].length; + first = exec[1]; + c = first.charAt(0); + source_row = source_row.slice(length); + from = character + length - first.length; + character += length; + return first; + } + } + + function string(x) { + var c, pos = 0, r = '', result; + + function hex(n) { + var i = parseInt(source_row.substr(pos + 1, n), 16); + pos += n; + if (i >= 32 && i <= 126 && + i !== 34 && i !== 92 && i !== 39) { + warn_at('unexpected_a', line, character, '\\'); + } + character += n; + c = String.fromCharCode(i); + } + + if (json_mode && x !== '"') { + warn_at('expected_a', line, character, '"'); + } + + if (xquote === x || (xmode === 'scriptstring' && !xquote)) { + return it('(punctuator)', x); + } + + for (;;) { + while (pos >= source_row.length) { + pos = 0; + if (xmode !== 'html' || !next_line()) { + stop_at('unclosed', line, from); + } + } + c = source_row.charAt(pos); + if (c === x) { + character += 1; + source_row = source_row.slice(pos + 1); + result = it('(string)', r); + result.quote = x; + return result; + } + if (c < ' ') { + if (c === '\n' || c === '\r') { + break; + } + warn_at('control_a', line, character + pos, + source_row.slice(0, pos)); + } else if (c === xquote) { + warn_at('bad_html', line, character + pos); + } else if (c === '<') { + if (option.safe && xmode === 'html') { + warn_at('adsafe_a', line, character + pos, c); + } else if (source_row.charAt(pos + 1) === '/' && (xmode || option.safe)) { + warn_at('expected_a_b', line, character, + '<\\/', '= '0' && c <= '7' ? 'octal_a' : 'unexpected_a', + line, character, '\\' + c); + } else { + c = descapes[c]; + } + } + } + } + r += c; + character += 1; + pos += 1; + } + } + + function number(snippet) { + var digit; + if (xmode !== 'style' && xmode !== 'styleproperty' && + source_row.charAt(0).isAlpha()) { + warn_at('expected_space_a_b', + line, character, c, source_row.charAt(0)); + } + if (c === '0') { + digit = snippet.charAt(1); + if (digit.isDigit()) { + if (token.id !== '.' && xmode !== 'styleproperty') { + warn_at('unexpected_a', line, character, snippet); + } + } else if (json_mode && (digit === 'x' || digit === 'X')) { + warn_at('unexpected_a', line, character, '0x'); + } + } + if (snippet.slice(snippet.length - 1) === '.') { + warn_at('trailing_decimal_a', line, character, snippet); + } + if (xmode !== 'style') { + digit = +snippet; + if (!isFinite(digit)) { + warn_at('bad_number', line, character, snippet); + } + snippet = digit; + } + return it('(number)', snippet); + } + + function comment(snippet) { + if (comments_off || src || (xmode && xmode !== 'script' && + xmode !== 'style' && xmode !== 'styleproperty')) { + warn_at('unexpected_comment', line, character); + } else if (xmode === 'script' && /<\//i.test(source_row)) { + warn_at('unexpected_a', line, character, '<\/'); + } else if (option.safe && ax.test(snippet)) { + warn_at('dangerous_comment', line, character); + } + } + + function regexp() { + var b, + bit, + captures = 0, + depth = 0, + flag = '', + high, + letter, + length = 0, + low, + potential, + quote, + result; + for (;;) { + b = true; + c = source_row.charAt(length); + length += 1; + switch (c) { + case '': + stop_at('unclosed_regexp', line, from); + return; + case '/': + if (depth > 0) { + warn_at('unescaped_a', line, from + length, '/'); + } + c = source_row.slice(0, length - 1); + potential = Object.create(regexp_flag); + for (;;) { + letter = source_row.charAt(length); + if (potential[letter] !== true) { + break; + } + potential[letter] = false; + length += 1; + flag += letter; + } + if (source_row.charAt(length).isAlpha()) { + stop_at('unexpected_a', line, from, source_row.charAt(length)); + } + character += length; + source_row = source_row.slice(length); + quote = source_row.charAt(0); + if (quote === '/' || quote === '*') { + stop_at('confusing_regexp', line, from); + } + result = it('(regexp)', c); + result.flag = flag; + return result; + case '\\': + c = source_row.charAt(length); + if (c < ' ') { + warn_at('control_a', line, from + length, String(c)); + } else if (c === '<') { + warn_at(bundle.unexpected_a, line, from + length, '\\'); + } + length += 1; + break; + case '(': + depth += 1; + b = false; + if (source_row.charAt(length) === '?') { + length += 1; + switch (source_row.charAt(length)) { + case ':': + case '=': + case '!': + length += 1; + break; + default: + warn_at(bundle.expected_a_b, line, from + length, + ':', source_row.charAt(length)); + } + } else { + captures += 1; + } + break; + case '|': + b = false; + break; + case ')': + if (depth === 0) { + warn_at('unescaped_a', line, from + length, ')'); + } else { + depth -= 1; + } + break; + case ' ': + pos = 1; + while (source_row.charAt(length) === ' ') { + length += 1; + pos += 1; + } + if (pos > 1) { + warn_at('use_braces', line, from + length, pos); + } + break; + case '[': + c = source_row.charAt(length); + if (c === '^') { + length += 1; + if (!option.regexp) { + warn_at('insecure_a', line, from + length, c); + } else if (source_row.charAt(length) === ']') { + stop_at('unescaped_a', line, from + length, '^'); + } + } + bit = false; + if (c === ']') { + warn_at('empty_class', line, from + length - 1); + bit = true; + } +klass: do { + c = source_row.charAt(length); + length += 1; + switch (c) { + case '[': + case '^': + warn_at('unescaped_a', line, from + length, c); + bit = true; + break; + case '-': + if (bit) { + bit = false; + } else { + warn_at('unescaped_a', line, from + length, '-'); + bit = true; + } + break; + case ']': + if (!bit) { + warn_at('unescaped_a', line, from + length - 1, '-'); + } + break klass; + case '\\': + c = source_row.charAt(length); + if (c < ' ') { + warn_at(bundle.control_a, line, from + length, String(c)); + } else if (c === '<') { + warn_at(bundle.unexpected_a, line, from + length, '\\'); + } + length += 1; + bit = true; + break; + case '/': + warn_at('unescaped_a', line, from + length - 1, '/'); + bit = true; + break; + case '<': + if (xmode === 'script') { + c = source_row.charAt(length); + if (c === '!' || c === '/') { + warn_at(bundle.html_confusion_a, line, + from + length, c); + } + } + bit = true; + break; + default: + bit = true; + } + } while (c); + break; + case '.': + if (!option.regexp) { + warn_at('insecure_a', line, from + length, c); + } + break; + case ']': + case '?': + case '{': + case '}': + case '+': + case '*': + warn_at('unescaped_a', line, from + length, c); + break; + case '<': + if (xmode === 'script') { + c = source_row.charAt(length); + if (c === '!' || c === '/') { + warn_at(bundle.html_confusion_a, line, from + length, c); + } + } + break; + } + if (b) { + switch (source_row.charAt(length)) { + case '?': + case '+': + case '*': + length += 1; + if (source_row.charAt(length) === '?') { + length += 1; + } + break; + case '{': + length += 1; + c = source_row.charAt(length); + if (c < '0' || c > '9') { + warn_at(bundle.expected_number_a, line, + from + length, c); + } + length += 1; + low = +c; + for (;;) { + c = source_row.charAt(length); + if (c < '0' || c > '9') { + break; + } + length += 1; + low = +c + (low * 10); + } + high = low; + if (c === ',') { + length += 1; + high = Infinity; + c = source_row.charAt(length); + if (c >= '0' && c <= '9') { + length += 1; + high = +c; + for (;;) { + c = source_row.charAt(length); + if (c < '0' || c > '9') { + break; + } + length += 1; + high = +c + (high * 10); + } + } + } + if (source_row.charAt(length) !== '}') { + warn_at(bundle.expected_a_b, line, from + length, + '}', c); + } else { + length += 1; + } + if (source_row.charAt(length) === '?') { + length += 1; + } + if (low > high) { + warn_at(bundle.not_greater, line, from + length, + low, high); + } + break; + } + } + } + c = source_row.slice(0, length - 1); + character += length; + source_row = source_row.slice(length); + return it('(regexp)', c); + } + +// Public lex methods + + return { + init: function (source) { + if (typeof source === 'string') { + lines = source.split(crlfx); + } else { + lines = source; + } + line = 0; + next_line(); + from = 1; + }, + + range: function (begin, end) { + var c, value = ''; + from = character; + if (source_row.charAt(0) !== begin) { + stop_at('expected_a_b', line, character, begin, + source_row.charAt(0)); + } + for (;;) { + source_row = source_row.slice(1); + character += 1; + c = source_row.charAt(0); + switch (c) { + case '': + stop_at('missing_a', line, character, c); + break; + case end: + source_row = source_row.slice(1); + character += 1; + return it('(range)', value); + case xquote: + case '\\': + warn_at('unexpected_a', line, character, c); + break; + } + value += c; + } + }, + +// token -- this is called by advance to get the next token. + + token: function () { + var c, i, snippet; + + for (;;) { + while (!source_row) { + if (!next_line()) { + return it('(end)'); + } + } + while (xmode === 'outer') { + i = source_row.search(ox); + if (i === 0) { + break; + } else if (i > 0) { + character += 1; + source_row = source_row.slice(i); + break; + } else { + if (!next_line()) { + return it('(end)', ''); + } + } + } + snippet = match(rx[xmode] || tx); + if (!snippet) { + if (source_row) { + if (source_row.charAt(0) === ' ') { + if (!option.white) { + warn_at('unexpected_a', line, character, + '(space)'); + } + character += 1; + source_row = ''; + } else { + stop_at('unexpected_a', line, character, + source_row.charAt(0)); + } + } + } else { + +// identifier + + c = snippet.charAt(0); + if (c.isAlpha() || c === '_' || c === '$') { + return it('(identifier)', snippet); + } + +// number + + if (c.isDigit()) { + return number(snippet); + } + switch (snippet) { + +// string + + case '"': + case "'": + return string(snippet); + +// // comment + + case '//': + comment(source_row); + source_row = ''; + break; + +// /* comment + + case '/*': + for (;;) { + i = source_row.search(lx); + if (i >= 0) { + break; + } + comment(source_row); + if (!next_line()) { + stop_at('unclosed_comment', line, character); + } + } + comment(source_row.slice(0, i)); + character += i + 2; + if (source_row.charAt(i) === '/') { + stop_at('nested_comment', line, character); + } + source_row = source_row.slice(i + 2); + break; + + case '': + break; +// / + case '/': + if (token.id === '/=') { + stop_at( + bundle.slash_equal, + line, + from + ); + } + return prereg + ? regexp() + : it('(punctuator)', snippet); + +// punctuator + + case ''); + } + character += 3; + source_row = source_row.slice(i + 3); + break; + case '#': + if (xmode === 'html' || xmode === 'styleproperty') { + for (;;) { + c = source_row.charAt(0); + if ((c < '0' || c > '9') && + (c < 'a' || c > 'f') && + (c < 'A' || c > 'F')) { + break; + } + character += 1; + source_row = source_row.slice(1); + snippet += c; + } + if (snippet.length !== 4 && snippet.length !== 7) { + warn_at('bad_color_a', line, + from + length, snippet); + } + return it('(color)', snippet); + } + return it('(punctuator)', snippet); + + default: + if (xmode === 'outer' && c === '&') { + character += 1; + source_row = source_row.slice(1); + for (;;) { + c = source_row.charAt(0); + character += 1; + source_row = source_row.slice(1); + if (c === ';') { + break; + } + if (!((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + c === '#')) { + stop_at('bad_entity', line, from + length, + character); + } + } + break; + } + return it('(punctuator)', snippet); + } + } + } + } + }; + }()); + + + function add_label(token, kind, name) { + +// Define the symbol in the current function in the current scope. + + name = name || token.string; + +// Global variables cannot be created in the safe subset. If a global variable +// already exists, do nothing. If it is predefined, define it. + + if (funct === global_funct) { + if (option.safe) { + warn('adsafe_a', token, name); + } + if (typeof global_funct[name] !== 'string') { + token.writeable = typeof predefined[name] === 'boolean' + ? predefined[name] + : true; + token.funct = funct; + global_scope[name] = token; + } + if (kind === 'becoming') { + kind = 'var'; + } + +// Ordinary variables. + + } else { + +// Warn if the variable already exists. + + if (typeof funct[name] === 'string') { + if (funct[name] === 'undef') { + if (!option.undef) { + warn('used_before_a', token, name); + } + kind = 'var'; + } else { + warn('already_defined', token, name); + } + } else { + +// Add the symbol to the current function. + + token.funct = funct; + token.writeable = true; + scope[name] = token; + } + } + funct[name] = kind; + } + + + function peek(distance) { + +// Peek ahead to a future token. The distance is how far ahead to look. The +// default is the next token. + + var found, slot = 0; + + distance = distance || 0; + while (slot <= distance) { + found = lookahead[slot]; + if (!found) { + found = lookahead[slot] = lex.token(); + } + slot += 1; + } + return found; + } + + + function advance(id, match) { + +// Produce the next token, also looking for programming errors. + + if (indent) { + +// If indentation checking was requested, then inspect all of the line breakings. +// The var statement is tricky because the names might be aligned or not. We +// look at the first line break after the var to determine the programmer's +// intention. + + if (var_mode && next_token.line !== token.line) { + if ((var_mode !== indent || !next_token.edge) && + next_token.from === indent.at - + (next_token.edge ? option.indent : 0)) { + var dent = indent; + for (;;) { + dent.at -= option.indent; + if (dent === var_mode) { + break; + } + dent = dent.was; + } + dent.open = false; + } + var_mode = null; + } + if (next_token.id === '?' && indent.mode === ':' && + token.line !== next_token.line) { + indent.at -= option.indent; + } + if (indent.open) { + +// If the token is an edge. + + if (next_token.edge) { + if (next_token.edge === 'label') { + expected_at(1); + } else if (next_token.edge === 'case' || indent.mode === 'statement') { + expected_at(indent.at - option.indent); + } else if (indent.mode !== 'array' || next_token.line !== token.line) { + expected_at(indent.at); + } + +// If the token is not an edge, but is the first token on the line. + + } else if (next_token.line !== token.line) { + if (next_token.from < indent.at + (indent.mode === + 'expression' ? 0 : option.indent)) { + expected_at(indent.at + option.indent); + } + indent.wrap = true; + } + } else if (next_token.line !== token.line) { + if (next_token.edge) { + expected_at(indent.at); + } else { + indent.wrap = true; + if (indent.mode === 'statement' || indent.mode === 'var') { + expected_at(indent.at + option.indent); + } else if (next_token.from < indent.at + (indent.mode === + 'expression' ? 0 : option.indent)) { + expected_at(indent.at + option.indent); + } + } + } + } + + switch (token.id) { + case '(number)': + if (next_token.id === '.') { + warn('trailing_decimal_a'); + } + break; + case '-': + if (next_token.id === '-' || next_token.id === '--') { + warn('confusing_a'); + } + break; + case '+': + if (next_token.id === '+' || next_token.id === '++') { + warn('confusing_a'); + } + break; + } + if (token.id === '(string)' || token.identifier) { + anonname = token.string; + } + + if (id && next_token.id !== id) { + if (match) { + warn('expected_a_b_from_c_d', next_token, id, + match.id, match.line, artifact()); + } else if (!next_token.identifier || next_token.string !== id) { + warn('expected_a_b', next_token, id, artifact()); + } + } + prev_token = token; + token = next_token; + next_token = lookahead.shift() || lex.token(); + } + + + function advance_identifier(string) { + if (next_token.identifier && next_token.string === string) { + advance(); + } else { + warn('expected_a_b', next_token, string, artifact()); + } + } + + + function do_safe() { + if (option.adsafe) { + option.safe = true; + } + if (option.safe) { + option.browser = + option['continue'] = + option.css = + option.debug = + option.devel = + option.evil = + option.forin = + option.newcap = + option.nomen = + option.on = + option.rhino = + option.sloppy = + option.sub = + option.undef = + option.widget = + option.windows = false; + + + delete predefined.Array; + delete predefined.Date; + delete predefined.Function; + delete predefined.Object; + delete predefined['eval']; + + add_to_predefined({ + ADSAFE: false, + lib: false + }); + } + } + + + function do_globals() { + var name, writeable; + for (;;) { + if (next_token.id !== '(string)' && !next_token.identifier) { + return; + } + name = next_token.string; + advance(); + writeable = false; + if (next_token.id === ':') { + advance(':'); + switch (next_token.id) { + case 'true': + writeable = predefined[name] !== false; + advance('true'); + break; + case 'false': + advance('false'); + break; + default: + stop('unexpected_a'); + } + } + predefined[name] = writeable; + if (next_token.id !== ',') { + return; + } + advance(','); + } + } + + + function do_jslint() { + var name, value; + while (next_token.id === '(string)' || next_token.identifier) { + name = next_token.string; + if (!allowed_option[name]) { + stop('unexpected_a'); + } + advance(); + if (next_token.id !== ':') { + stop('expected_a_b', next_token, ':', artifact()); + } + advance(':'); + if (typeof allowed_option[name] === 'number') { + value = next_token.number; + if (value > allowed_option[name] || value <= 0 || + Math.floor(value) !== value) { + stop('expected_small_a'); + } + option[name] = value; + } else { + if (next_token.id === 'true') { + option[name] = true; + } else if (next_token.id === 'false') { + option[name] = false; + } else { + stop('unexpected_a'); + } + } + advance(); + if (next_token.id === ',') { + advance(','); + } + } + assume(); + } + + + function do_properties() { + var name; + option.properties = true; + for (;;) { + if (next_token.id !== '(string)' && !next_token.identifier) { + return; + } + name = next_token.string; + advance(); + if (next_token.id === ':') { + for (;;) { + advance(); + if (next_token.id !== '(string)' && !next_token.identifier) { + break; + } + } + } + property[name] = 0; + if (next_token.id !== ',') { + return; + } + advance(','); + } + } + + + directive = function directive() { + var command = this.id, + old_comments_off = comments_off, + old_indent = indent; + comments_off = true; + indent = null; + if (next_token.line === token.line && next_token.from === token.thru) { + warn('missing_space_a_b', next_token, artifact(token), artifact()); + } + if (lookahead.length > 0) { + warn('unexpected_a', this); + } + switch (command) { + case '/*properties': + case '/*property': + case '/*members': + case '/*member': + do_properties(); + break; + case '/*jslint': + if (option.safe) { + warn('adsafe_a', this); + } + do_jslint(); + break; + case '/*globals': + case '/*global': + if (option.safe) { + warn('adsafe_a', this); + } + do_globals(); + break; + default: + stop('unexpected_a', this); + } + comments_off = old_comments_off; + advance('*/'); + indent = old_indent; + }; + + +// Indentation intention + + function edge(mode) { + next_token.edge = indent ? indent.open && (mode || 'edge') : ''; + } + + + function step_in(mode) { + var open; + if (typeof mode === 'number') { + indent = { + at: +mode, + open: true, + was: indent + }; + } else if (!indent) { + indent = { + at: 1, + mode: 'statement', + open: true + }; + } else if (mode === 'statement') { + indent = { + at: indent.at, + open: true, + was: indent + }; + } else { + open = mode === 'var' || next_token.line !== token.line; + indent = { + at: (open || mode === 'control' + ? indent.at + option.indent + : indent.at) + (indent.wrap ? option.indent : 0), + mode: mode, + open: open, + was: indent + }; + if (mode === 'var' && open) { + var_mode = indent; + } + } + } + + function step_out(id, symbol) { + if (id) { + if (indent && indent.open) { + indent.at -= option.indent; + edge(); + } + advance(id, symbol); + } + if (indent) { + indent = indent.was; + } + } + +// Functions for conformance of whitespace. + + function one_space(left, right) { + left = left || token; + right = right || next_token; + if (right.id !== '(end)' && !option.white && + (token.line !== right.line || + token.thru + 1 !== right.from)) { + warn('expected_space_a_b', right, artifact(token), artifact(right)); + } + } + + function one_space_only(left, right) { + left = left || token; + right = right || next_token; + if (right.id !== '(end)' && (left.line !== right.line || + (!option.white && left.thru + 1 !== right.from))) { + warn('expected_space_a_b', right, artifact(left), artifact(right)); + } + } + + function no_space(left, right) { + left = left || token; + right = right || next_token; + if ((!option.white || xmode === 'styleproperty' || xmode === 'style') && + left.thru !== right.from && left.line === right.line) { + warn('unexpected_space_a_b', right, artifact(left), artifact(right)); + } + } + + function no_space_only(left, right) { + left = left || token; + right = right || next_token; + if (right.id !== '(end)' && (left.line !== right.line || + (!option.white && left.thru !== right.from))) { + warn('unexpected_space_a_b', right, artifact(left), artifact(right)); + } + } + + function spaces(left, right) { + if (!option.white) { + left = left || token; + right = right || next_token; + if (left.thru === right.from && left.line === right.line) { + warn('missing_space_a_b', right, artifact(left), artifact(right)); + } + } + } + + function comma() { + if (next_token.id !== ',') { + warn_at('expected_a_b', token.line, token.thru, ',', artifact()); + } else { + if (!option.white) { + no_space_only(); + } + advance(','); + spaces(); + } + } + + + function semicolon() { + if (next_token.id !== ';') { + warn_at('expected_a_b', token.line, token.thru, ';', artifact()); + } else { + if (!option.white) { + no_space_only(); + } + advance(';'); + if (semicolon_coda[next_token.id] !== true) { + spaces(); + } + } + } + + function use_strict() { + if (next_token.string === 'use strict') { + if (strict_mode) { + warn('unnecessary_use'); + } + edge(); + advance(); + semicolon(); + strict_mode = true; + option.undef = false; + return true; + } + return false; + } + + + function are_similar(a, b) { + if (a === b) { + return true; + } + if (Array.isArray(a)) { + if (Array.isArray(b) && a.length === b.length) { + var i; + for (i = 0; i < a.length; i += 1) { + if (!are_similar(a[i], b[i])) { + return false; + } + } + return true; + } + return false; + } + if (Array.isArray(b)) { + return false; + } + if (a.id === '(number)' && b.id === '(number)') { + return a.number === b.number; + } + if (a.arity === b.arity && a.string === b.string) { + switch (a.arity) { + case 'prefix': + case 'suffix': + case undefined: + return a.id === b.id && are_similar(a.first, b.first); + case 'infix': + return are_similar(a.first, b.first) && + are_similar(a.second, b.second); + case 'ternary': + return are_similar(a.first, b.first) && + are_similar(a.second, b.second) && + are_similar(a.third, b.third); + case 'function': + case 'regexp': + return false; + default: + return true; + } + } else { + if (a.id === '.' && b.id === '[' && b.arity === 'infix') { + return a.second.string === b.second.string && b.second.id === '(string)'; + } + if (a.id === '[' && a.arity === 'infix' && b.id === '.') { + return a.second.string === b.second.string && a.second.id === '(string)'; + } + } + return false; + } + + +// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it +// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is +// like .nud except that it is only used on the first token of a statement. +// Having .fud makes it much easier to define statement-oriented languages like +// JavaScript. I retained Pratt's nomenclature. + +// .nud Null denotation +// .fud First null denotation +// .led Left denotation +// lbp Left binding power +// rbp Right binding power + +// They are elements of the parsing method called Top Down Operator Precedence. + + function expression(rbp, initial) { + +// rbp is the right binding power. +// initial indicates that this is the first expression of a statement. + + var left; + if (next_token.id === '(end)') { + stop('unexpected_a', token, next_token.id); + } + advance(); + if (option.safe && scope[token.string] && + scope[token.string] === global_scope[token.string] && + (next_token.id !== '(' && next_token.id !== '.')) { + warn('adsafe_a', token); + } + if (initial) { + anonname = 'anonymous'; + funct['(verb)'] = token.string; + } + if (initial === true && token.fud) { + left = token.fud(); + } else { + if (token.nud) { + left = token.nud(); + } else { + if (next_token.id === '(number)' && token.id === '.') { + warn('leading_decimal_a', token, artifact()); + advance(); + return token; + } + stop('expected_identifier_a', token, token.id); + } + while (rbp < next_token.lbp) { + advance(); + if (token.led) { + left = token.led(left); + } else { + stop('expected_operator_a', token, token.id); + } + } + } + return left; + } + + +// Functional constructors for making the symbols that will be inherited by +// tokens. + + function symbol(s, p) { + var x = syntax[s]; + if (!x || typeof x !== 'object') { + syntax[s] = x = { + id: s, + lbp: p || 0, + string: s + }; + } + return x; + } + + function postscript(x) { + x.postscript = true; + return x; + } + + function ultimate(s) { + var x = symbol(s, 0); + x.from = 1; + x.thru = 1; + x.line = 0; + x.edge = 'edge'; + s.string = s; + return postscript(x); + } + + + function stmt(s, f) { + var x = symbol(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + function labeled_stmt(s, f) { + var x = stmt(s, f); + x.labeled = true; + } + + function disrupt_stmt(s, f) { + var x = stmt(s, f); + x.disrupt = true; + } + + + function reserve_name(x) { + var c = x.id.charAt(0); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + x.identifier = x.reserved = true; + } + return x; + } + + + function prefix(s, f) { + var x = symbol(s, 150); + reserve_name(x); + x.nud = typeof f === 'function' + ? f + : function () { + if (s === 'typeof') { + one_space(); + } else { + no_space_only(); + } + this.first = expression(150); + this.arity = 'prefix'; + if (this.id === '++' || this.id === '--') { + if (!option.plusplus) { + warn('unexpected_a', this); + } else if ((!this.first.identifier || this.first.reserved) && + this.first.id !== '.' && this.first.id !== '[') { + warn('bad_operand', this); + } + } + return this; + }; + return x; + } + + + function type(s, t, nud) { + var x = symbol(s); + x.arity = t; + if (nud) { + x.nud = nud; + } + return x; + } + + + function reserve(s, f) { + var x = symbol(s); + x.identifier = x.reserved = true; + if (typeof f === 'function') { + x.nud = f; + } + return x; + } + + + function constant(name) { + var x = reserve(name); + x.string = name; + x.nud = return_this; + return x; + } + + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === 'function') { + v(this); + } + return this; + }); + } + + + function infix(s, p, f, w) { + var x = symbol(s, p); + reserve_name(x); + x.led = function (left) { + this.arity = 'infix'; + if (!w) { + spaces(prev_token, token); + spaces(); + } + if (!option.bitwise && this.bitwise) { + warn('unexpected_a', this); + } + if (typeof f === 'function') { + return f(left, this); + } + this.first = left; + this.second = expression(p); + return this; + }; + return x; + } + + function expected_relation(node, message) { + if (node.assign) { + warn(message || bundle.conditional_assignment, node); + } + return node; + } + + function expected_condition(node, message) { + switch (node.id) { + case '[': + case '-': + if (node.arity !== 'infix') { + warn(message || bundle.weird_condition, node); + } + break; + case 'false': + case 'function': + case 'Infinity': + case 'NaN': + case 'null': + case 'true': + case 'undefined': + case 'void': + case '(number)': + case '(regexp)': + case '(string)': + case '{': + warn(message || bundle.weird_condition, node); + break; + case '(': + if (node.first.id === '.' && numbery[node.first.second.string] === true) { + warn(message || bundle.weird_condition, node); + } + break; + } + return node; + } + + function check_relation(node) { + switch (node.arity) { + case 'prefix': + switch (node.id) { + case '{': + case '[': + warn('unexpected_a', node); + break; + case '!': + warn('confusing_a', node); + break; + } + break; + case 'function': + case 'regexp': + warn('unexpected_a', node); + break; + default: + if (node.id === 'NaN') { + warn('isNaN', node); + } + } + return node; + } + + + function relation(s, eqeq) { + return infix(s, 100, function (left, that) { + check_relation(left); + if (eqeq && !option.eqeq) { + warn('expected_a_b', that, eqeq, that.id); + } + var right = expression(100); + if (are_similar(left, right) || + ((left.id === '(string)' || left.id === '(number)') && + (right.id === '(string)' || right.id === '(number)'))) { + warn('weird_relation', that); + } + that.first = left; + that.second = check_relation(right); + return that; + }); + } + + + function assignop(s, op) { + var x = infix(s, 20, function (left, that) { + var l; + that.first = left; + if (left.identifier) { + if (scope[left.string]) { + if (scope[left.string].writeable === false) { + warn('read_only', left); + } + } else { + stop('read_only'); + } + if (funct['(params)']) { + funct['(params)'].forEach(function (value) { + if (value.string === left.string) { + value.assign = true; + } + }); + } + } else if (option.safe) { + l = left; + do { + if (typeof predefined[l.string] === 'boolean') { + warn('adsafe_a', l); + } + l = l.first; + } while (l); + } + if (left === syntax['function']) { + warn('identifier_function', token); + } + if (left.id === '.' || left.id === '[') { + if (!left.first || left.first.string === 'arguments') { + warn('bad_assignment', that); + } + } else if (left.identifier) { + if (!left.reserved && funct[left.string] === 'exception') { + warn('assign_exception', left); + } + } else { + warn('bad_assignment', that); + } + that.second = expression(19); + if (that.id === '=' && are_similar(that.first, that.second)) { + warn('weird_assignment', that); + } + return that; + }); + x.assign = true; + if (op) { + if (syntax[op].bitwise) { + x.bitwise = true; + } + } + return x; + } + + + function bitwise(s, p) { + var x = infix(s, p, 'number'); + x.bitwise = true; + return x; + } + + + function suffix(s) { + var x = symbol(s, 150); + x.led = function (left) { + no_space_only(prev_token, token); + if (!option.plusplus) { + warn('unexpected_a', this); + } else if ((!left.identifier || left.reserved) && + left.id !== '.' && left.id !== '[') { + warn('bad_operand', this); + } + this.first = left; + this.arity = 'suffix'; + return this; + }; + return x; + } + + + function optional_identifier() { + if (next_token.identifier) { + advance(); + if (option.safe && banned[token.string]) { + warn('adsafe_a', token); + } else if (token.reserved && !option.es5) { + warn('expected_identifier_a_reserved', token); + } + return token.string; + } + } + + + function identifier() { + var i = optional_identifier(); + if (!i) { + stop(token.id === 'function' && next_token.id === '(' + ? 'name_function' + : 'expected_identifier_a'); + } + return i; + } + + + function statement() { + + var label, old_scope = scope, the_statement; + +// We don't like the empty statement. + + if (next_token.id === ';') { + warn('unexpected_a'); + semicolon(); + return; + } + +// Is this a labeled statement? + + if (next_token.identifier && !next_token.reserved && peek().id === ':') { + edge('label'); + label = next_token; + advance(); + advance(':'); + scope = Object.create(old_scope); + add_label(label, 'label'); + if (next_token.labeled !== true || funct === global_funct) { + stop('unexpected_label_a', label); + } else if (jx.test(label.string + ':')) { + warn('url', label); + } + next_token.label = label; + } + +// Parse the statement. + + if (token.id !== 'else') { + edge(); + } + step_in('statement'); + the_statement = expression(0, true); + if (the_statement) { + +// Look for the final semicolon. + + if (the_statement.arity === 'statement') { + if (the_statement.id === 'switch' || + (the_statement.block && the_statement.id !== 'do')) { + spaces(); + } else { + semicolon(); + } + } else { + +// If this is an expression statement, determine if it is acceptable. +// We do not like +// new Blah(); +// statments. If it is to be used at all, new should only be used to make +// objects, not side effects. The expression statements we do like do +// assignment or invocation or delete. + + if (the_statement.id === '(') { + if (the_statement.first.id === 'new') { + warn('bad_new'); + } + } else if (!the_statement.assign && + the_statement.id !== 'delete' && + the_statement.id !== '++' && + the_statement.id !== '--') { + warn('assignment_function_expression', token); + } + semicolon(); + } + } + step_out(); + scope = old_scope; + return the_statement; + } + + + function statements() { + var array = [], disruptor, the_statement; + +// A disrupt statement may not be followed by any other statement. +// If the last statement is disrupt, then the sequence is disrupt. + + while (next_token.postscript !== true) { + if (next_token.id === ';') { + warn('unexpected_a', next_token); + semicolon(); + } else { + if (next_token.string === 'use strict') { + if ((!node_js && xmode !== 'script') || funct !== global_funct || array.length > 0) { + warn('function_strict'); + } + use_strict(); + } + if (disruptor) { + warn('unreachable_a_b', next_token, next_token.string, + disruptor.string); + disruptor = null; + } + the_statement = statement(); + if (the_statement) { + array.push(the_statement); + if (the_statement.disrupt) { + disruptor = the_statement; + array.disrupt = true; + } + } + } + } + return array; + } + + + function block(ordinary) { + +// array block is array sequence of statements wrapped in braces. +// ordinary is false for function bodies and try blocks. +// ordinary is true for if statements, while, etc. + + var array, + curly = next_token, + old_in_block = in_block, + old_scope = scope, + old_strict_mode = strict_mode; + + in_block = ordinary; + scope = Object.create(scope); + spaces(); + if (next_token.id === '{') { + advance('{'); + step_in(); + if (!ordinary && !use_strict() && !old_strict_mode && + !option.sloppy && funct['(context)'] === global_funct) { + warn('missing_use_strict'); + } + array = statements(); + strict_mode = old_strict_mode; + step_out('}', curly); + } else if (!ordinary) { + stop('expected_a_b', next_token, '{', artifact()); + } else { + warn('expected_a_b', next_token, '{', artifact()); + array = [statement()]; + array.disrupt = array[0].disrupt; + } + funct['(verb)'] = null; + scope = old_scope; + in_block = old_in_block; + if (ordinary && array.length === 0) { + warn('empty_block'); + } + return array; + } + + + function tally_property(name) { + if (option.properties && typeof property[name] !== 'number') { + warn('unexpected_property_a', token, name); + } + if (typeof property[name] === 'number') { + property[name] += 1; + } else { + property[name] = 1; + } + } + + +// ECMAScript parser + + syntax['(identifier)'] = { + id: '(identifier)', + lbp: 0, + identifier: true, + nud: function () { + var name = this.string, + variable = scope[name], + site, + writeable; + +// If the variable is not in scope, then we may have an undeclared variable. +// Check the predefined list. If it was predefined, create the global +// variable. + + if (typeof variable !== 'object') { + writeable = predefined[name]; + if (typeof writeable === 'boolean') { + global_scope[name] = variable = { + string: name, + writeable: writeable, + funct: global_funct + }; + global_funct[name] = 'var'; + +// But if the variable is not in scope, and is not predefined, and if we are not +// in the global scope, then we have an undefined variable error. + + } else { + if (!option.undef) { + warn('used_before_a', token); + } + scope[name] = variable = { + string: name, + writeable: true, + funct: funct + }; + funct[name] = 'undef'; + } + + } + site = variable.funct; + +// The name is in scope and defined in the current function. + + if (funct === site) { + +// Change 'unused' to 'var', and reject labels. + + switch (funct[name]) { + case 'becoming': + warn('unexpected_a', token); + funct[name] = 'var'; + break; + case 'unused': + funct[name] = 'var'; + break; + case 'unparam': + funct[name] = 'parameter'; + break; + case 'unction': + funct[name] = 'function'; + break; + case 'label': + warn('a_label', token, name); + break; + } + +// If the name is already defined in the current +// function, but not as outer, then there is a scope error. + + } else { + switch (funct[name]) { + case 'closure': + case 'function': + case 'var': + case 'unused': + warn('a_scope', token, name); + break; + case 'label': + warn('a_label', token, name); + break; + case 'outer': + case 'global': + break; + default: + +// If the name is defined in an outer function, make an outer entry, and if +// it was unused, make it var. + + switch (site[name]) { + case 'becoming': + case 'closure': + case 'function': + case 'parameter': + case 'unction': + case 'unused': + case 'var': + site[name] = 'closure'; + funct[name] = site === global_funct + ? 'global' + : 'outer'; + break; + case 'unparam': + site[name] = 'parameter'; + funct[name] = 'outer'; + break; + case 'undef': + funct[name] = 'undef'; + break; + case 'label': + warn('a_label', token, name); + break; + } + } + } + return this; + }, + led: function () { + stop('expected_operator_a'); + } + }; + +// Build the syntax table by declaring the syntactic elements. + + type('(array)', 'array'); + type('(color)', 'color'); + type('(function)', 'function'); + type('(number)', 'number', return_this); + type('(object)', 'object'); + type('(string)', 'string', return_this); + type('(boolean)', 'boolean', return_this); + type('(range)', 'range'); + type('(regexp)', 'regexp', return_this); + + ultimate('(begin)'); + ultimate('(end)'); + ultimate('(error)'); + postscript(symbol(''); + postscript(symbol('}')); + symbol(')'); + symbol(']'); + postscript(symbol('"')); + postscript(symbol('\'')); + symbol(';'); + symbol(':'); + symbol(','); + symbol('#'); + symbol('@'); + symbol('*/'); + postscript(reserve('case')); + reserve('catch'); + postscript(reserve('default')); + reserve('else'); + reserve('finally'); + + reservevar('arguments', function (x) { + if (strict_mode && funct === global_funct) { + warn('strict', x); + } else if (option.safe) { + warn('adsafe_a', x); + } + funct['(arguments)'] = true; + }); + reservevar('eval', function (x) { + if (option.safe) { + warn('adsafe_a', x); + } + }); + constant('false', 'boolean'); + constant('Infinity', 'number'); + constant('NaN', 'number'); + constant('null', ''); + reservevar('this', function (x) { + if (option.safe) { + warn('adsafe_a', x); + } else if (strict_mode && funct['(token)'].arity === 'statement' && + funct['(name)'].charAt(0) > 'Z') { + warn('strict', x); + } + }); + constant('true', 'boolean'); + constant('undefined', ''); + + infix('?', 30, function (left, that) { + step_in('?'); + that.first = expected_condition(expected_relation(left)); + that.second = expression(0); + spaces(); + step_out(); + var colon = next_token; + advance(':'); + step_in(':'); + spaces(); + that.third = expression(10); + that.arity = 'ternary'; + if (are_similar(that.second, that.third)) { + warn('weird_ternary', colon); + } else if (are_similar(that.first, that.second)) { + warn('use_or', that); + } + step_out(); + return that; + }); + + infix('||', 40, function (left, that) { + function paren_check(that) { + if (that.id === '&&' && !that.paren) { + warn('and', that); + } + return that; + } + + that.first = paren_check(expected_condition(expected_relation(left))); + that.second = paren_check(expected_relation(expression(40))); + if (are_similar(that.first, that.second)) { + warn('weird_condition', that); + } + return that; + }); + + infix('&&', 50, function (left, that) { + that.first = expected_condition(expected_relation(left)); + that.second = expected_relation(expression(50)); + if (are_similar(that.first, that.second)) { + warn('weird_condition', that); + } + return that; + }); + + prefix('void', function () { + this.first = expression(0); + this.arity = 'prefix'; + if (option.es5) { + warn('expected_a_b', this, 'undefined', 'void'); + } else if (this.first.number !== 0) { + warn('expected_a_b', this.first, '0', artifact(this.first)); + } + return this; + }); + + bitwise('|', 70); + bitwise('^', 80); + bitwise('&', 90); + + relation('==', '==='); + relation('==='); + relation('!=', '!=='); + relation('!=='); + relation('<'); + relation('>'); + relation('<='); + relation('>='); + + bitwise('<<', 120); + bitwise('>>', 120); + bitwise('>>>', 120); + + infix('in', 120, function (left, that) { + warn('infix_in', that); + that.left = left; + that.right = expression(130); + return that; + }); + infix('instanceof', 120); + infix('+', 130, function (left, that) { + if (left.id === '(number)') { + if (left.number === 0) { + warn('unexpected_a', left, '0'); + } + } else if (left.id === '(string)') { + if (left.string === '') { + warn('expected_a_b', left, 'String', '\'\''); + } + } + var right = expression(130); + if (right.id === '(number)') { + if (right.number === 0) { + warn('unexpected_a', right, '0'); + } + } else if (right.id === '(string)') { + if (right.string === '') { + warn('expected_a_b', right, 'String', '\'\''); + } + } + if (left.id === right.id) { + if (left.id === '(string)' || left.id === '(number)') { + if (left.id === '(string)') { + left.string += right.string; + if (jx.test(left.string)) { + warn('url', left); + } + } else { + left.number += right.number; + } + left.thru = right.thru; + return left; + } + } + that.first = left; + that.second = right; + return that; + }); + prefix('+', 'num'); + prefix('+++', function () { + warn('confusing_a', token); + this.first = expression(150); + this.arity = 'prefix'; + return this; + }); + infix('+++', 130, function (left) { + warn('confusing_a', token); + this.first = left; + this.second = expression(130); + return this; + }); + infix('-', 130, function (left, that) { + if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') { + warn('unexpected_a', left); + } + var right = expression(130); + if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') { + warn('unexpected_a', right); + } + if (left.id === right.id && left.id === '(number)') { + left.number -= right.number; + left.thru = right.thru; + return left; + } + that.first = left; + that.second = right; + return that; + }); + prefix('-'); + prefix('---', function () { + warn('confusing_a', token); + this.first = expression(150); + this.arity = 'prefix'; + return this; + }); + infix('---', 130, function (left) { + warn('confusing_a', token); + this.first = left; + this.second = expression(130); + return this; + }); + infix('*', 140, function (left, that) { + if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') { + warn('unexpected_a', left); + } + var right = expression(140); + if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') { + warn('unexpected_a', right); + } + if (left.id === right.id && left.id === '(number)') { + left.number *= right.number; + left.thru = right.thru; + return left; + } + that.first = left; + that.second = right; + return that; + }); + infix('/', 140, function (left, that) { + if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') { + warn('unexpected_a', left); + } + var right = expression(140); + if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') { + warn('unexpected_a', right); + } + if (left.id === right.id && left.id === '(number)') { + left.number /= right.number; + left.thru = right.thru; + return left; + } + that.first = left; + that.second = right; + return that; + }); + infix('%', 140, function (left, that) { + if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') { + warn('unexpected_a', left); + } + var right = expression(140); + if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') { + warn('unexpected_a', right); + } + if (left.id === right.id && left.id === '(number)') { + left.number %= right.number; + left.thru = right.thru; + return left; + } + that.first = left; + that.second = right; + return that; + }); + + suffix('++'); + prefix('++'); + + suffix('--'); + prefix('--'); + prefix('delete', function () { + one_space(); + var p = expression(0); + if (!p || (p.id !== '.' && p.id !== '[')) { + warn('deleted'); + } + this.first = p; + return this; + }); + + + prefix('~', function () { + no_space_only(); + if (!option.bitwise) { + warn('unexpected_a', this); + } + expression(150); + return this; + }); + prefix('!', function () { + no_space_only(); + this.first = expected_condition(expression(150)); + this.arity = 'prefix'; + if (bang[this.first.id] === true || this.first.assign) { + warn('confusing_a', this); + } + return this; + }); + prefix('typeof', null); + prefix('new', function () { + one_space(); + var c = expression(160), n, p, v; + this.first = c; + if (c.id !== 'function') { + if (c.identifier) { + switch (c.string) { + case 'Object': + warn('use_object', token); + break; + case 'Array': + if (next_token.id === '(') { + p = next_token; + p.first = this; + advance('('); + if (next_token.id !== ')') { + n = expression(0); + p.second = [n]; + if (n.id !== '(number)' || next_token.id === ',') { + warn('use_array', p); + } + while (next_token.id === ',') { + advance(','); + p.second.push(expression(0)); + } + } else { + warn('use_array', token); + } + advance(')', p); + return p; + } + warn('use_array', token); + break; + case 'Number': + case 'String': + case 'Boolean': + case 'Math': + case 'JSON': + warn('not_a_constructor', c); + break; + case 'Function': + if (!option.evil) { + warn('function_eval'); + } + break; + case 'Date': + case 'RegExp': + case 'this': + break; + default: + if (c.id !== 'function') { + v = c.string.charAt(0); + if (!option.newcap && (v < 'A' || v > 'Z')) { + warn('constructor_name_a', token); + } + } + } + } else { + if (c.id !== '.' && c.id !== '[' && c.id !== '(') { + warn('bad_constructor', token); + } + } + } else { + warn('weird_new', this); + } + if (next_token.id !== '(') { + warn('missing_a', next_token, '()'); + } + return this; + }); + + infix('(', 160, function (left, that) { + var p; + if (indent && indent.mode === 'expression') { + no_space(prev_token, token); + } else { + no_space_only(prev_token, token); + } + if (!left.immed && left.id === 'function') { + warn('wrap_immediate'); + } + p = []; + if (left.identifier) { + if (left.string.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if (left.string !== 'Number' && left.string !== 'String' && + left.string !== 'Boolean' && left.string !== 'Date') { + if (left.string === 'Math' || left.string === 'JSON') { + warn('not_a_function', left); + } else if (left.string === 'Object') { + warn('use_object', token); + } else if (left.string === 'Array' || !option.newcap) { + warn('missing_a', left, 'new'); + } + } + } + } else if (left.id === '.') { + if (option.safe && left.first.string === 'Math' && + left.second === 'random') { + warn('adsafe_a', left); + } else if (left.second.string === 'split' && + left.first.id === '(string)') { + warn('use_array', left.second); + } + } + step_in(); + if (next_token.id !== ')') { + no_space(); + for (;;) { + edge(); + p.push(expression(10)); + if (next_token.id !== ',') { + break; + } + comma(); + } + } + no_space(); + step_out(')', that); + if (typeof left === 'object') { + if (left.string === 'parseInt' && p.length === 1) { + warn('radix', left); + } + if (!option.evil) { + if (left.string === 'eval' || left.string === 'Function' || + left.string === 'execScript') { + warn('evil', left); + } else if (p[0] && p[0].id === '(string)' && + (left.string === 'setTimeout' || + left.string === 'setInterval')) { + warn('implied_evil', left); + } + } + if (!left.identifier && left.id !== '.' && left.id !== '[' && + left.id !== '(' && left.id !== '&&' && left.id !== '||' && + left.id !== '?') { + warn('bad_invocation', left); + } + } + that.first = left; + that.second = p; + return that; + }, true); + + prefix('(', function () { + step_in('expression'); + no_space(); + edge(); + if (next_token.id === 'function') { + next_token.immed = true; + } + var value = expression(0); + value.paren = true; + no_space(); + step_out(')', this); + if (value.id === 'function') { + switch (next_token.id) { + case '(': + warn('move_invocation'); + break; + case '.': + case '[': + warn('unexpected_a'); + break; + default: + warn('bad_wrap', this); + } + } + return value; + }); + + infix('.', 170, function (left, that) { + no_space(prev_token, token); + no_space(); + var name = identifier(); + if (typeof name === 'string') { + tally_property(name); + } + that.first = left; + that.second = token; + if (left && left.string === 'arguments' && + (name === 'callee' || name === 'caller')) { + warn('avoid_a', left, 'arguments.' + name); + } else if (!option.evil && left && left.string === 'document' && + (name === 'write' || name === 'writeln')) { + warn('write_is_wrong', left); + } else if (!option.stupid && name.indexOf('Sync') > 0) { + warn('sync_a', token); + } else if (option.adsafe) { + if (!adsafe_top && left.string === 'ADSAFE') { + if (name === 'id' || name === 'lib') { + warn('adsafe_a', that); + } else if (name === 'go') { + if (xmode !== 'script') { + warn('adsafe_a', that); + } else if (adsafe_went || next_token.id !== '(' || + peek(0).id !== '(string)' || + peek(0).string !== adsafe_id || + peek(1).id !== ',') { + stop('adsafe_a', that, 'go'); + } + adsafe_went = true; + adsafe_may = false; + } + } + adsafe_top = false; + } + if (!option.evil && (name === 'eval' || name === 'execScript')) { + warn('evil'); + } else if (option.safe) { + for (;;) { + if (banned[name] === true) { + warn('adsafe_a', token, name); + } + if (typeof predefined[left.string] !== 'boolean' || //// check for writeable + next_token.id === '(') { + break; + } + if (next_token.id !== '.') { + warn('adsafe_a', that); + break; + } + advance('.'); + token.first = that; + token.second = name; + that = token; + name = identifier(); + if (typeof name === 'string') { + tally_property(name); + } + } + } + return that; + }, true); + + infix('[', 170, function (left, that) { + var e, s; + no_space_only(prev_token, token); + no_space(); + step_in(); + edge(); + e = expression(0); + switch (e.id) { + case '(number)': + if (e.id === '(number)' && left.id === 'arguments') { + warn('use_param', left); + } + break; + case '(string)': + if (option.safe && (banned[e.string] || + e.string.charAt(0) === '_' || e.string.slice(-1) === '_')) { + warn('adsafe_subscript_a', e); + } else if (!option.evil && + (e.string === 'eval' || e.string === 'execScript')) { + warn('evil', e); + } else if (!option.sub && ix.test(e.string)) { + s = syntax[e.string]; + if (!s || !s.reserved) { + warn('subscript', e); + } + } + tally_property(e.string); + break; + default: + if (option.safe) { + warn('adsafe_subscript_a', e); + } + } + step_out(']', that); + no_space(prev_token, token); + that.first = left; + that.second = e; + return that; + }, true); + + prefix('[', function () { + this.arity = 'prefix'; + this.first = []; + step_in('array'); + while (next_token.id !== '(end)') { + while (next_token.id === ',') { + warn('unexpected_a', next_token); + advance(','); + } + if (next_token.id === ']') { + break; + } + indent.wrap = false; + edge(); + this.first.push(expression(10)); + if (next_token.id === ',') { + comma(); + if (next_token.id === ']' && !option.es5) { + warn('unexpected_a', token); + break; + } + } else { + break; + } + } + step_out(']', this); + return this; + }, 170); + + + function property_name() { + var id = optional_identifier(true); + if (!id) { + if (next_token.id === '(string)') { + id = next_token.string; + if (option.safe) { + if (banned[id]) { + warn('adsafe_a'); + } else if (id.charAt(0) === '_' || + id.charAt(id.length - 1) === '_') { + warn('dangling_a'); + } + } + advance(); + } else if (next_token.id === '(number)') { + id = next_token.number.toString(); + advance(); + } + } + return id; + } + + + function function_params() { + var id, paren = next_token, params = []; + advance('('); + step_in(); + no_space(); + if (next_token.id === ')') { + no_space(); + step_out(')', paren); + return params; + } + for (;;) { + edge(); + id = identifier(); + params.push(token); + add_label(token, option.unparam ? 'parameter' : 'unparam'); + if (next_token.id === ',') { + comma(); + } else { + no_space(); + step_out(')', paren); + return params; + } + } + } + + + + function do_function(func, name) { + var old_funct = funct, + old_option = option, + old_scope = scope; + funct = { + '(name)' : name || '\'' + (anonname || '').replace(nx, sanitize) + '\'', + '(line)' : next_token.line, + '(context)' : old_funct, + '(breakage)' : 0, + '(loopage)' : 0, + '(scope)' : scope, + '(token)' : func + }; + option = Object.create(old_option); + scope = Object.create(old_scope); + functions.push(funct); + func.name = name; + if (name) { + add_label(func, 'function', name); + } + func.writeable = false; + func.first = funct['(params)'] = function_params(); + one_space(); + func.block = block(false); + if (funct['(arguments)']) { + func.first.forEach(function (value) { + if (value.assign) { + warn('parameter_arguments_a', value, value.string); + } + }); + } + funct = old_funct; + option = old_option; + scope = old_scope; + } + + + assignop('='); + assignop('+=', '+'); + assignop('-=', '-'); + assignop('*=', '*'); + assignop('/=', '/').nud = function () { + stop('slash_equal'); + }; + assignop('%=', '%'); + assignop('&=', '&'); + assignop('|=', '|'); + assignop('^=', '^'); + assignop('<<=', '<<'); + assignop('>>=', '>>'); + assignop('>>>=', '>>>'); + + + prefix('{', function () { + var get, i, j, name, p, set, seen = {}; + this.arity = 'prefix'; + this.first = []; + step_in(); + while (next_token.id !== '}') { + indent.wrap = false; + +// JSLint recognizes the ES5 extension for get/set in object literals, +// but requires that they be used in pairs. + + edge(); + if (next_token.string === 'get' && peek().id !== ':') { + if (!option.es5) { + warn('es5'); + } + get = next_token; + advance('get'); + one_space_only(); + name = next_token; + i = property_name(); + if (!i) { + stop('missing_property'); + } + get.string = ''; + do_function(get); + if (funct['(loopage)']) { + warn('function_loop', get); + } + p = get.first; + if (p && p.length) { + warn('parameter_a_get_b', p[0], p[0].string, i); + } + comma(); + set = next_token; + spaces(); + edge(); + advance('set'); + set.string = ''; + one_space_only(); + j = property_name(); + if (i !== j) { + stop('expected_a_b', token, i, j || next_token.string); + } + do_function(set); + if (set.block.length === 0) { + warn('missing_a', token, 'throw'); + } + p = set.first; + if (!p || p.length !== 1) { + stop('parameter_set_a', set, 'value'); + } else if (p[0].string !== 'value') { + stop('expected_a_b', p[0], 'value', p[0].string); + } + name.first = [get, set]; + } else { + name = next_token; + i = property_name(); + if (typeof i !== 'string') { + stop('missing_property'); + } + advance(':'); + spaces(); + name.first = expression(10); + } + this.first.push(name); + if (seen[i] === true) { + warn('duplicate_a', next_token, i); + } + seen[i] = true; + tally_property(i); + if (next_token.id !== ',') { + break; + } + for (;;) { + comma(); + if (next_token.id !== ',') { + break; + } + warn('unexpected_a', next_token); + } + if (next_token.id === '}' && !option.es5) { + warn('unexpected_a', token); + } + } + step_out('}', this); + return this; + }); + + stmt('{', function () { + warn('statement_block'); + this.arity = 'statement'; + this.block = statements(); + this.disrupt = this.block.disrupt; + advance('}', this); + return this; + }); + + stmt('/*global', directive); + stmt('/*globals', directive); + stmt('/*jslint', directive); + stmt('/*member', directive); + stmt('/*members', directive); + stmt('/*property', directive); + stmt('/*properties', directive); + + stmt('var', function () { + +// JavaScript does not have block scope. It only has function scope. So, +// declaring a variable in a block can have unexpected consequences. + +// var.first will contain an array, the array containing name tokens +// and assignment tokens. + + var assign, id, name; + + if (funct['(vars)'] && !option.vars) { + warn('combine_var'); + } else if (funct !== global_funct) { + funct['(vars)'] = true; + } + this.arity = 'statement'; + this.first = []; + step_in('var'); + for (;;) { + name = next_token; + id = identifier(); + add_label(name, 'becoming'); + + if (next_token.id === '=') { + assign = next_token; + assign.first = name; + spaces(); + advance('='); + spaces(); + if (next_token.id === 'undefined') { + warn('unnecessary_initialize', token, id); + } + if (peek(0).id === '=' && next_token.identifier) { + stop('var_a_not'); + } + assign.second = expression(0); + assign.arity = 'infix'; + this.first.push(assign); + } else { + this.first.push(name); + } + if (funct[id] === 'becoming') { + funct[id] = 'unused'; + } + if (next_token.id !== ',') { + break; + } + comma(); + indent.wrap = false; + if (var_mode && next_token.line === token.line && + this.first.length === 1) { + var_mode = null; + indent.open = false; + indent.at -= option.indent; + } + spaces(); + edge(); + } + var_mode = null; + step_out(); + return this; + }); + + stmt('function', function () { + one_space(); + if (in_block) { + warn('function_block', token); + } + var name = next_token, id = identifier(); + add_label(name, 'unction'); + no_space(); + this.arity = 'statement'; + do_function(this, id); + if (next_token.id === '(' && next_token.line === token.line) { + stop('function_statement'); + } + return this; + }); + + prefix('function', function () { + if (!option.anon) { + one_space(); + } + var id = optional_identifier(); + if (id) { + no_space(); + } else { + id = ''; + } + do_function(this, id); + if (funct['(loopage)']) { + warn('function_loop'); + } + switch (next_token.id) { + case ';': + case '(': + case ')': + case ',': + case ']': + case '}': + case ':': + break; + case '.': + if (peek().string !== 'bind' || peek(1).id !== '(') { + warn('unexpected_a'); + } + break; + default: + stop('unexpected_a'); + } + this.arity = 'function'; + return this; + }); + + stmt('if', function () { + var paren = next_token; + one_space(); + advance('('); + step_in('control'); + no_space(); + edge(); + this.arity = 'statement'; + this.first = expected_condition(expected_relation(expression(0))); + no_space(); + step_out(')', paren); + one_space(); + this.block = block(true); + if (next_token.id === 'else') { + one_space(); + advance('else'); + one_space(); + this['else'] = next_token.id === 'if' || next_token.id === 'switch' + ? statement(true) + : block(true); + if (this['else'].disrupt && this.block.disrupt) { + this.disrupt = true; + } + } + return this; + }); + + stmt('try', function () { + +// try.first The catch variable +// try.second The catch clause +// try.third The finally clause +// try.block The try block + + var exception_variable, old_scope, paren; + if (option.adsafe) { + warn('adsafe_a', this); + } + one_space(); + this.arity = 'statement'; + this.block = block(false); + if (next_token.id === 'catch') { + one_space(); + advance('catch'); + one_space(); + paren = next_token; + advance('('); + step_in('control'); + no_space(); + edge(); + old_scope = scope; + scope = Object.create(old_scope); + exception_variable = next_token.string; + this.first = exception_variable; + if (!next_token.identifier) { + warn('expected_identifier_a', next_token); + } else { + add_label(next_token, 'exception'); + } + advance(); + no_space(); + step_out(')', paren); + one_space(); + this.second = block(false); + scope = old_scope; + } + if (next_token.id === 'finally') { + one_space(); + advance('finally'); + one_space(); + this.third = block(false); + } else if (!this.second) { + stop('expected_a_b', next_token, 'catch', artifact()); + } + return this; + }); + + labeled_stmt('while', function () { + one_space(); + var paren = next_token; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + step_in('control'); + no_space(); + edge(); + this.arity = 'statement'; + this.first = expected_relation(expression(0)); + if (this.first.id !== 'true') { + expected_condition(this.first, bundle.unexpected_a); + } + no_space(); + step_out(')', paren); + one_space(); + this.block = block(true); + if (this.block.disrupt) { + warn('strange_loop', prev_token); + } + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }); + + reserve('with'); + + labeled_stmt('switch', function () { + +// switch.first the switch expression +// switch.second the array of cases. A case is 'case' or 'default' token: +// case.first the array of case expressions +// case.second the array of statements +// If all of the arrays of statements are disrupt, then the switch is disrupt. + + var cases = [], + old_in_block = in_block, + particular, + the_case = next_token, + unbroken = true; + + function find_duplicate_case(value) { + if (are_similar(particular, value)) { + warn('duplicate_a', value); + } + } + + funct['(breakage)'] += 1; + one_space(); + advance('('); + no_space(); + step_in(); + this.arity = 'statement'; + this.first = expected_condition(expected_relation(expression(0))); + no_space(); + step_out(')', the_case); + one_space(); + advance('{'); + step_in(); + in_block = true; + this.second = []; + while (next_token.id === 'case') { + the_case = next_token; + cases.forEach(find_duplicate_case); + the_case.first = []; + the_case.arity = 'case'; + spaces(); + edge('case'); + advance('case'); + for (;;) { + one_space(); + particular = expression(0); + cases.forEach(find_duplicate_case); + cases.push(particular); + the_case.first.push(particular); + if (particular.id === 'NaN') { + warn('unexpected_a', particular); + } + no_space_only(); + advance(':'); + if (next_token.id !== 'case') { + break; + } + spaces(); + edge('case'); + advance('case'); + } + spaces(); + the_case.second = statements(); + if (the_case.second && the_case.second.length > 0) { + particular = the_case.second[the_case.second.length - 1]; + if (particular.disrupt) { + if (particular.id === 'break') { + unbroken = false; + } + } else { + warn('missing_a_after_b', next_token, 'break', 'case'); + } + } else { + warn('empty_case'); + } + this.second.push(the_case); + } + if (this.second.length === 0) { + warn('missing_a', next_token, 'case'); + } + if (next_token.id === 'default') { + spaces(); + the_case = next_token; + the_case.arity = 'case'; + edge('case'); + advance('default'); + no_space_only(); + advance(':'); + spaces(); + the_case.second = statements(); + if (the_case.second && the_case.second.length > 0) { + particular = the_case.second[the_case.second.length - 1]; + if (unbroken && particular.disrupt && particular.id !== 'break') { + this.disrupt = true; + } + } + this.second.push(the_case); + } + funct['(breakage)'] -= 1; + spaces(); + step_out('}', this); + in_block = old_in_block; + return this; + }); + + stmt('debugger', function () { + if (!option.debug) { + warn('unexpected_a', this); + } + this.arity = 'statement'; + return this; + }); + + labeled_stmt('do', function () { + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + one_space(); + this.arity = 'statement'; + this.block = block(true); + if (this.block.disrupt) { + warn('strange_loop', prev_token); + } + one_space(); + advance('while'); + var paren = next_token; + one_space(); + advance('('); + step_in(); + no_space(); + edge(); + this.first = expected_condition(expected_relation(expression(0)), bundle.unexpected_a); + no_space(); + step_out(')', paren); + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }); + + labeled_stmt('for', function () { + + var blok, filter, ok = false, paren = next_token, value; + this.arity = 'statement'; + funct['(breakage)'] += 1; + funct['(loopage)'] += 1; + advance('('); + if (next_token.id === ';') { + no_space(); + advance(';'); + no_space(); + advance(';'); + no_space(); + advance(')'); + blok = block(true); + } else { + step_in('control'); + spaces(this, paren); + no_space(); + if (next_token.id === 'var') { + stop('move_var'); + } + edge(); + if (peek(0).id === 'in') { + this.forin = true; + value = next_token; + switch (funct[value.string]) { + case 'unused': + funct[value.string] = 'var'; + break; + case 'closure': + case 'var': + break; + default: + warn('bad_in_a', value); + } + advance(); + advance('in'); + this.first = value; + this.second = expression(20); + step_out(')', paren); + blok = block(true); + if (!option.forin) { + if (blok.length === 1 && typeof blok[0] === 'object' && + blok[0].string === 'if' && !blok[0]['else']) { + filter = blok[0].first; + while (filter.id === '&&') { + filter = filter.first; + } + switch (filter.id) { + case '===': + case '!==': + ok = filter.first.id === '[' + ? filter.first.first.string === this.second.string && + filter.first.second.string === this.first.string + : filter.first.id === 'typeof' && + filter.first.first.id === '[' && + filter.first.first.first.string === this.second.string && + filter.first.first.second.string === this.first.string; + break; + case '(': + ok = filter.first.id === '.' && (( + filter.first.first.string === this.second.string && + filter.first.second.string === 'hasOwnProperty' && + filter.second[0].string === this.first.string + ) || ( + filter.first.first.string === 'ADSAFE' && + filter.first.second.string === 'has' && + filter.second[0].string === this.second.string && + filter.second[1].string === this.first.string + ) || ( + filter.first.first.id === '.' && + filter.first.first.first.id === '.' && + filter.first.first.first.first.string === 'Object' && + filter.first.first.first.second.string === 'prototype' && + filter.first.first.second.string === 'hasOwnProperty' && + filter.first.second.string === 'call' && + filter.second[0].string === this.second.string && + filter.second[1].string === this.first.string + )); + break; + } + } + if (!ok) { + warn('for_if', this); + } + } + } else { + edge(); + this.first = []; + for (;;) { + this.first.push(expression(0, 'for')); + if (next_token.id !== ',') { + break; + } + comma(); + } + semicolon(); + edge(); + this.second = expected_relation(expression(0)); + if (this.second.id !== 'true') { + expected_condition(this.second, bundle.unexpected_a); + } + semicolon(token); + if (next_token.id === ';') { + stop('expected_a_b', next_token, ')', ';'); + } + this.third = []; + edge(); + for (;;) { + this.third.push(expression(0, 'for')); + if (next_token.id !== ',') { + break; + } + comma(); + } + no_space(); + step_out(')', paren); + one_space(); + blok = block(true); + } + } + if (blok.disrupt) { + warn('strange_loop', prev_token); + } + this.block = blok; + funct['(breakage)'] -= 1; + funct['(loopage)'] -= 1; + return this; + }); + + disrupt_stmt('break', function () { + var label = next_token.string; + this.arity = 'statement'; + if (funct['(breakage)'] === 0) { + warn('unexpected_a', this); + } + if (next_token.identifier && token.line === next_token.line) { + one_space_only(); + if (funct[label] !== 'label') { + warn('not_a_label', next_token); + } else if (scope[label].funct !== funct) { + warn('not_a_scope', next_token); + } + this.first = next_token; + advance(); + } + return this; + }); + + disrupt_stmt('continue', function () { + if (!option['continue']) { + warn('unexpected_a', this); + } + var label = next_token.string; + this.arity = 'statement'; + if (funct['(breakage)'] === 0) { + warn('unexpected_a', this); + } + if (next_token.identifier && token.line === next_token.line) { + one_space_only(); + if (funct[label] !== 'label') { + warn('not_a_label', next_token); + } else if (scope[label].funct !== funct) { + warn('not_a_scope', next_token); + } + this.first = next_token; + advance(); + } + return this; + }); + + disrupt_stmt('return', function () { + if (funct === global_funct && xmode !== 'scriptstring') { + warn('unexpected_a', this); + } + this.arity = 'statement'; + if (next_token.id !== ';' && next_token.line === token.line) { + one_space_only(); + if (next_token.id === '/' || next_token.id === '(regexp)') { + warn('wrap_regexp'); + } + this.first = expression(20); + } + if (peek(0).id === '}' && peek(1).id === 'else') { + warn('unexpected_else', this); + } + return this; + }); + + disrupt_stmt('throw', function () { + this.arity = 'statement'; + one_space_only(); + this.first = expression(20); + return this; + }); + + +// Superfluous reserved words + + reserve('class'); + reserve('const'); + reserve('enum'); + reserve('export'); + reserve('extends'); + reserve('import'); + reserve('super'); + +// Harmony reserved words + + reserve('implements'); + reserve('interface'); + reserve('let'); + reserve('package'); + reserve('private'); + reserve('protected'); + reserve('public'); + reserve('static'); + reserve('yield'); + + +// Parse JSON + + function json_value() { + + function json_object() { + var brace = next_token, object = {}; + advance('{'); + if (next_token.id !== '}') { + while (next_token.id !== '(end)') { + while (next_token.id === ',') { + warn('unexpected_a', next_token); + advance(','); + } + if (next_token.id !== '(string)') { + warn('expected_string_a'); + } + if (object[next_token.string] === true) { + warn('duplicate_a'); + } else if (next_token.string === '__proto__') { + warn('dangling_a'); + } else { + object[next_token.string] = true; + } + advance(); + advance(':'); + json_value(); + if (next_token.id !== ',') { + break; + } + advance(','); + if (next_token.id === '}') { + warn('unexpected_a', token); + break; + } + } + } + advance('}', brace); + } + + function json_array() { + var bracket = next_token; + advance('['); + if (next_token.id !== ']') { + while (next_token.id !== '(end)') { + while (next_token.id === ',') { + warn('unexpected_a', next_token); + advance(','); + } + json_value(); + if (next_token.id !== ',') { + break; + } + advance(','); + if (next_token.id === ']') { + warn('unexpected_a', token); + break; + } + } + } + advance(']', bracket); + } + + switch (next_token.id) { + case '{': + json_object(); + break; + case '[': + json_array(); + break; + case 'true': + case 'false': + case 'null': + case '(number)': + case '(string)': + advance(); + break; + case '-': + advance('-'); + no_space_only(); + advance('(number)'); + break; + default: + stop('unexpected_a'); + } + } + + +// CSS parsing. + + function css_name() { + if (next_token.identifier) { + advance(); + return true; + } + } + + + function css_number() { + if (next_token.id === '-') { + advance('-'); + no_space_only(); + } + if (next_token.id === '(number)') { + advance('(number)'); + return true; + } + } + + + function css_string() { + if (next_token.id === '(string)') { + advance(); + return true; + } + } + + function css_color() { + var i, number, paren, value; + if (next_token.identifier) { + value = next_token.string; + if (value === 'rgb' || value === 'rgba') { + advance(); + paren = next_token; + advance('('); + for (i = 0; i < 3; i += 1) { + if (i) { + comma(); + } + number = next_token.number; + if (next_token.id !== '(number)' || number < 0) { + warn('expected_positive_a', next_token); + advance(); + } else { + advance(); + if (next_token.id === '%') { + advance('%'); + if (number > 100) { + warn('expected_percent_a', token, number); + } + } else { + if (number > 255) { + warn('expected_small_a', token, number); + } + } + } + } + if (value === 'rgba') { + comma(); + number = next_token.number; + if (next_token.id !== '(number)' || number < 0 || number > 1) { + warn('expected_fraction_a', next_token); + } + advance(); + if (next_token.id === '%') { + warn('unexpected_a'); + advance('%'); + } + } + advance(')', paren); + return true; + } + if (css_colorData[next_token.string] === true) { + advance(); + return true; + } + } else if (next_token.id === '(color)') { + advance(); + return true; + } + return false; + } + + + function css_length() { + if (next_token.id === '-') { + advance('-'); + no_space_only(); + } + if (next_token.id === '(number)') { + advance(); + if (next_token.id !== '(string)' && + css_lengthData[next_token.string] === true) { + no_space_only(); + advance(); + } else if (+token.number !== 0) { + warn('expected_linear_a'); + } + return true; + } + return false; + } + + + function css_line_height() { + if (next_token.id === '-') { + advance('-'); + no_space_only(); + } + if (next_token.id === '(number)') { + advance(); + if (next_token.id !== '(string)' && + css_lengthData[next_token.string] === true) { + no_space_only(); + advance(); + } + return true; + } + return false; + } + + + function css_width() { + if (next_token.identifier) { + switch (next_token.string) { + case 'thin': + case 'medium': + case 'thick': + advance(); + return true; + } + } else { + return css_length(); + } + } + + + function css_margin() { + if (next_token.identifier) { + if (next_token.string === 'auto') { + advance(); + return true; + } + } else { + return css_length(); + } + } + + function css_attr() { + if (next_token.identifier && next_token.string === 'attr') { + advance(); + advance('('); + if (!next_token.identifier) { + warn('expected_name_a'); + } + advance(); + advance(')'); + return true; + } + return false; + } + + + function css_comma_list() { + while (next_token.id !== ';') { + if (!css_name() && !css_string()) { + warn('expected_name_a'); + } + if (next_token.id !== ',') { + return true; + } + comma(); + } + } + + + function css_counter() { + if (next_token.identifier && next_token.string === 'counter') { + advance(); + advance('('); + advance(); + if (next_token.id === ',') { + comma(); + if (next_token.id !== '(string)') { + warn('expected_string_a'); + } + advance(); + } + advance(')'); + return true; + } + if (next_token.identifier && next_token.string === 'counters') { + advance(); + advance('('); + if (!next_token.identifier) { + warn('expected_name_a'); + } + advance(); + if (next_token.id === ',') { + comma(); + if (next_token.id !== '(string)') { + warn('expected_string_a'); + } + advance(); + } + if (next_token.id === ',') { + comma(); + if (next_token.id !== '(string)') { + warn('expected_string_a'); + } + advance(); + } + advance(')'); + return true; + } + return false; + } + + + function css_radius() { + return css_length() && (next_token.id !== '(number)' || css_length()); + } + + + function css_shape() { + var i; + if (next_token.identifier && next_token.string === 'rect') { + advance(); + advance('('); + for (i = 0; i < 4; i += 1) { + if (!css_length()) { + warn('expected_number_a'); + break; + } + } + advance(')'); + return true; + } + return false; + } + + + function css_url() { + var c, url; + if (next_token.identifier && next_token.string === 'url') { + next_token = lex.range('(', ')'); + url = next_token.string; + c = url.charAt(0); + if (c === '"' || c === '\'') { + if (url.slice(-1) !== c) { + warn('bad_url_a'); + } else { + url = url.slice(1, -1); + if (url.indexOf(c) >= 0) { + warn('bad_url_a'); + } + } + } + if (!url) { + warn('missing_url'); + } + if (ux.test(url)) { + stop('bad_url_a'); + } + urls.push(url); + advance(); + return true; + } + return false; + } + + + css_any = [css_url, function () { + for (;;) { + if (next_token.identifier) { + switch (next_token.string.toLowerCase()) { + case 'url': + css_url(); + break; + case 'expression': + warn('unexpected_a'); + advance(); + break; + default: + advance(); + } + } else { + if (next_token.id === ';' || next_token.id === '!' || + next_token.id === '(end)' || next_token.id === '}') { + return true; + } + advance(); + } + } + }]; + + + function font_face() { + advance_identifier('font-family'); + advance(':'); + if (!css_name() && !css_string()) { + stop('expected_name_a'); + } + semicolon(); + advance_identifier('src'); + advance(':'); + while (true) { + if (next_token.string === 'local') { + advance_identifier('local'); + advance('('); + if (ux.test(next_token.string)) { + stop('bad_url_a'); + } + + if (!css_name() && !css_string()) { + stop('expected_name_a'); + } + advance(')'); + } else if (!css_url()) { + stop('expected_a_b', next_token, 'url', artifact()); + } + if (next_token.id !== ',') { + break; + } + comma(); + } + semicolon(); + } + + + css_border_style = [ + 'none', 'dashed', 'dotted', 'double', 'groove', + 'hidden', 'inset', 'outset', 'ridge', 'solid' + ]; + + css_break = [ + 'auto', 'always', 'avoid', 'left', 'right' + ]; + + css_media = { + 'all': true, + 'braille': true, + 'embossed': true, + 'handheld': true, + 'print': true, + 'projection': true, + 'screen': true, + 'speech': true, + 'tty': true, + 'tv': true + }; + + css_overflow = [ + 'auto', 'hidden', 'scroll', 'visible' + ]; + + css_attribute_data = { + background: [ + true, 'background-attachment', 'background-color', + 'background-image', 'background-position', 'background-repeat' + ], + 'background-attachment': ['scroll', 'fixed'], + 'background-color': ['transparent', css_color], + 'background-image': ['none', css_url], + 'background-position': [ + 2, [css_length, 'top', 'bottom', 'left', 'right', 'center'] + ], + 'background-repeat': [ + 'repeat', 'repeat-x', 'repeat-y', 'no-repeat' + ], + 'border': [true, 'border-color', 'border-style', 'border-width'], + 'border-bottom': [ + true, 'border-bottom-color', 'border-bottom-style', + 'border-bottom-width' + ], + 'border-bottom-color': css_color, + 'border-bottom-left-radius': css_radius, + 'border-bottom-right-radius': css_radius, + 'border-bottom-style': css_border_style, + 'border-bottom-width': css_width, + 'border-collapse': ['collapse', 'separate'], + 'border-color': ['transparent', 4, css_color], + 'border-left': [ + true, 'border-left-color', 'border-left-style', 'border-left-width' + ], + 'border-left-color': css_color, + 'border-left-style': css_border_style, + 'border-left-width': css_width, + 'border-radius': function () { + function count(separator) { + var n = 1; + if (separator) { + advance(separator); + } + if (!css_length()) { + return false; + } + while (next_token.id === '(number)') { + if (!css_length()) { + return false; + } + n += 1; + } + if (n > 4) { + warn('bad_style'); + } + return true; + } + + return count() && (next_token.id !== '/' || count('/')); + }, + 'border-right': [ + true, 'border-right-color', 'border-right-style', + 'border-right-width' + ], + 'border-right-color': css_color, + 'border-right-style': css_border_style, + 'border-right-width': css_width, + 'border-spacing': [2, css_length], + 'border-style': [4, css_border_style], + 'border-top': [ + true, 'border-top-color', 'border-top-style', 'border-top-width' + ], + 'border-top-color': css_color, + 'border-top-left-radius': css_radius, + 'border-top-right-radius': css_radius, + 'border-top-style': css_border_style, + 'border-top-width': css_width, + 'border-width': [4, css_width], + bottom: [css_length, 'auto'], + 'caption-side' : ['bottom', 'left', 'right', 'top'], + clear: ['both', 'left', 'none', 'right'], + clip: [css_shape, 'auto'], + color: css_color, + content: [ + 'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote', + css_string, css_url, css_counter, css_attr + ], + 'counter-increment': [ + css_name, 'none' + ], + 'counter-reset': [ + css_name, 'none' + ], + cursor: [ + css_url, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move', + 'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize', + 'se-resize', 'sw-resize', 'w-resize', 'text', 'wait' + ], + direction: ['ltr', 'rtl'], + display: [ + 'block', 'compact', 'inline', 'inline-block', 'inline-table', + 'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption', + 'table-cell', 'table-column', 'table-column-group', + 'table-footer-group', 'table-header-group', 'table-row', + 'table-row-group' + ], + 'empty-cells': ['show', 'hide'], + 'float': ['left', 'none', 'right'], + font: [ + 'caption', 'icon', 'menu', 'message-box', 'small-caption', + 'status-bar', true, 'font-size', 'font-style', 'font-weight', + 'font-family' + ], + 'font-family': css_comma_list, + 'font-size': [ + 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', + 'xx-large', 'larger', 'smaller', css_length + ], + 'font-size-adjust': ['none', css_number], + 'font-stretch': [ + 'normal', 'wider', 'narrower', 'ultra-condensed', + 'extra-condensed', 'condensed', 'semi-condensed', + 'semi-expanded', 'expanded', 'extra-expanded' + ], + 'font-style': [ + 'normal', 'italic', 'oblique' + ], + 'font-variant': [ + 'normal', 'small-caps' + ], + 'font-weight': [ + 'normal', 'bold', 'bolder', 'lighter', css_number + ], + height: [css_length, 'auto'], + left: [css_length, 'auto'], + 'letter-spacing': ['normal', css_length], + 'line-height': ['normal', css_line_height], + 'list-style': [ + true, 'list-style-image', 'list-style-position', 'list-style-type' + ], + 'list-style-image': ['none', css_url], + 'list-style-position': ['inside', 'outside'], + 'list-style-type': [ + 'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero', + 'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha', + 'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana', + 'hiragana-iroha', 'katakana-oroha', 'none' + ], + margin: [4, css_margin], + 'margin-bottom': css_margin, + 'margin-left': css_margin, + 'margin-right': css_margin, + 'margin-top': css_margin, + 'marker-offset': [css_length, 'auto'], + 'max-height': [css_length, 'none'], + 'max-width': [css_length, 'none'], + 'min-height': css_length, + 'min-width': css_length, + opacity: css_number, + outline: [true, 'outline-color', 'outline-style', 'outline-width'], + 'outline-color': ['invert', css_color], + 'outline-style': [ + 'dashed', 'dotted', 'double', 'groove', 'inset', 'none', + 'outset', 'ridge', 'solid' + ], + 'outline-width': css_width, + overflow: css_overflow, + 'overflow-x': css_overflow, + 'overflow-y': css_overflow, + padding: [4, css_length], + 'padding-bottom': css_length, + 'padding-left': css_length, + 'padding-right': css_length, + 'padding-top': css_length, + 'page-break-after': css_break, + 'page-break-before': css_break, + position: ['absolute', 'fixed', 'relative', 'static'], + quotes: [8, css_string], + right: [css_length, 'auto'], + 'table-layout': ['auto', 'fixed'], + 'text-align': ['center', 'justify', 'left', 'right'], + 'text-decoration': [ + 'none', 'underline', 'overline', 'line-through', 'blink' + ], + 'text-indent': css_length, + 'text-shadow': ['none', 4, [css_color, css_length]], + 'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'], + top: [css_length, 'auto'], + 'unicode-bidi': ['normal', 'embed', 'bidi-override'], + 'vertical-align': [ + 'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle', + 'text-bottom', css_length + ], + visibility: ['visible', 'hidden', 'collapse'], + 'white-space': [ + 'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit' + ], + width: [css_length, 'auto'], + 'word-spacing': ['normal', css_length], + 'word-wrap': ['break-word', 'normal'], + 'z-index': ['auto', css_number] + }; + + function style_attribute() { + var v; + while (next_token.id === '*' || next_token.id === '#' || + next_token.string === '_') { + if (!option.css) { + warn('unexpected_a'); + } + advance(); + } + if (next_token.id === '-') { + if (!option.css) { + warn('unexpected_a'); + } + advance('-'); + if (!next_token.identifier) { + warn('expected_nonstandard_style_attribute'); + } + advance(); + return css_any; + } + if (!next_token.identifier) { + warn('expected_style_attribute'); + } else { + if (Object.prototype.hasOwnProperty.call(css_attribute_data, + next_token.string)) { + v = css_attribute_data[next_token.string]; + } else { + v = css_any; + if (!option.css) { + warn('unrecognized_style_attribute_a'); + } + } + } + advance(); + return v; + } + + + function style_value(v) { + var i = 0, + n, + once, + match, + round, + start = 0, + vi; + switch (typeof v) { + case 'function': + return v(); + case 'string': + if (next_token.identifier && next_token.string === v) { + advance(); + return true; + } + return false; + } + for (;;) { + if (i >= v.length) { + return false; + } + vi = v[i]; + i += 1; + if (typeof vi === 'boolean') { + break; + } else if (typeof vi === 'number') { + n = vi; + vi = v[i]; + i += 1; + } else { + n = 1; + } + match = false; + while (n > 0) { + if (style_value(vi)) { + match = true; + n -= 1; + } else { + break; + } + } + if (match) { + return true; + } + } + start = i; + once = []; + for (;;) { + round = false; + for (i = start; i < v.length; i += 1) { + if (!once[i]) { + if (style_value(css_attribute_data[v[i]])) { + match = true; + round = true; + once[i] = true; + break; + } + } + } + if (!round) { + return match; + } + } + } + + function style_child() { + if (next_token.id === '(number)') { + advance(); + if (next_token.string === 'n' && next_token.identifier) { + no_space_only(); + advance(); + if (next_token.id === '+') { + no_space_only(); + advance('+'); + no_space_only(); + advance('(number)'); + } + } + return; + } + if (next_token.identifier && + (next_token.string === 'odd' || next_token.string === 'even')) { + advance(); + return; + } + warn('unexpected_a'); + } + + function substyle() { + var v; + for (;;) { + if (next_token.id === '}' || next_token.id === '(end)' || + (xquote && next_token.id === xquote)) { + return; + } + v = style_attribute(); + advance(':'); + if (next_token.identifier && next_token.string === 'inherit') { + advance(); + } else { + if (!style_value(v)) { + warn('unexpected_a'); + advance(); + } + } + if (next_token.id === '!') { + advance('!'); + no_space_only(); + if (next_token.identifier && next_token.string === 'important') { + advance(); + } else { + warn('expected_a_b', + next_token, 'important', artifact()); + } + } + if (next_token.id === '}' || next_token.id === xquote) { + warn('expected_a_b', next_token, ';', artifact()); + } else { + semicolon(); + } + } + } + + function style_selector() { + if (next_token.identifier) { + if (!Object.prototype.hasOwnProperty.call(html_tag, option.cap + ? next_token.string.toLowerCase() + : next_token.string)) { + warn('expected_tagname_a'); + } + advance(); + } else { + switch (next_token.id) { + case '>': + case '+': + advance(); + style_selector(); + break; + case ':': + advance(':'); + switch (next_token.string) { + case 'active': + case 'after': + case 'before': + case 'checked': + case 'disabled': + case 'empty': + case 'enabled': + case 'first-child': + case 'first-letter': + case 'first-line': + case 'first-of-type': + case 'focus': + case 'hover': + case 'last-child': + case 'last-of-type': + case 'link': + case 'only-of-type': + case 'root': + case 'target': + case 'visited': + advance_identifier(next_token.string); + break; + case 'lang': + advance_identifier('lang'); + advance('('); + if (!next_token.identifier) { + warn('expected_lang_a'); + } + advance(')'); + break; + case 'nth-child': + case 'nth-last-child': + case 'nth-last-of-type': + case 'nth-of-type': + advance_identifier(next_token.string); + advance('('); + style_child(); + advance(')'); + break; + case 'not': + advance_identifier('not'); + advance('('); + if (next_token.id === ':' && peek(0).string === 'not') { + warn('not'); + } + style_selector(); + advance(')'); + break; + default: + warn('expected_pseudo_a'); + } + break; + case '#': + advance('#'); + if (!next_token.identifier) { + warn('expected_id_a'); + } + advance(); + break; + case '*': + advance('*'); + break; + case '.': + advance('.'); + if (!next_token.identifier) { + warn('expected_class_a'); + } + advance(); + break; + case '[': + advance('['); + if (!next_token.identifier) { + warn('expected_attribute_a'); + } + advance(); + if (next_token.id === '=' || next_token.string === '~=' || + next_token.string === '$=' || + next_token.string === '|=' || + next_token.id === '*=' || + next_token.id === '^=') { + advance(); + if (next_token.id !== '(string)') { + warn('expected_string_a'); + } + advance(); + } + advance(']'); + break; + default: + stop('expected_selector_a'); + } + } + } + + function style_pattern() { + if (next_token.id === '{') { + warn('expected_style_pattern'); + } + for (;;) { + style_selector(); + if (next_token.id === '= 0) { + warn('unexpected_char_a_b', token, v.charAt(x), a); + } + ids[u] = true; + } else if (a === 'class' || a === 'type' || a === 'name') { + x = v.search(qx); + if (x >= 0) { + warn('unexpected_char_a_b', token, v.charAt(x), a); + } + ids[u] = true; + } else if (a === 'href' || a === 'background' || + a === 'content' || a === 'data' || + a.indexOf('src') >= 0 || a.indexOf('url') >= 0) { + if (option.safe && ux.test(v)) { + stop('bad_url_a', next_token, v); + } + urls.push(v); + } else if (a === 'for') { + if (option.adsafe) { + if (adsafe_id) { + if (v.slice(0, adsafe_id.length) !== adsafe_id) { + warn('adsafe_prefix_a', next_token, adsafe_id); + } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) { + warn('adsafe_bad_id'); + } + } else { + warn('adsafe_bad_id'); + } + } + } else if (a === 'name') { + if (option.adsafe && v.indexOf('_') >= 0) { + warn('adsafe_name_a', next_token, v); + } + } + } + + function do_tag(name, attribute) { + var i, tag = html_tag[name], script, x; + src = false; + if (!tag) { + stop( + bundle.unrecognized_tag_a, + next_token, + name === name.toLowerCase() + ? name + : name + ' (capitalization error)' + ); + } + if (stack.length > 0) { + if (name === 'html') { + stop('unexpected_a', token, name); + } + x = tag.parent; + if (x) { + if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) { + stop('tag_a_in_b', token, name, x); + } + } else if (!option.adsafe && !option.fragment) { + i = stack.length; + do { + if (i <= 0) { + stop('tag_a_in_b', token, name, 'body'); + } + i -= 1; + } while (stack[i].name !== 'body'); + } + } + switch (name) { + case 'div': + if (option.adsafe && stack.length === 1 && !adsafe_id) { + warn('adsafe_missing_id'); + } + break; + case 'script': + xmode = 'script'; + advance('>'); + if (attribute.lang) { + warn('lang', token); + } + if (option.adsafe && stack.length !== 1) { + warn('adsafe_placement', token); + } + if (attribute.src) { + if (option.adsafe && (!adsafe_may || !approved[attribute.src])) { + warn('adsafe_source', token); + } + } else { + step_in(next_token.from); + edge(); + use_strict(); + adsafe_top = true; + script = statements(); + +// JSLint is also the static analyzer for ADsafe. See www.ADsafe.org. + + if (option.adsafe) { + if (adsafe_went) { + stop('adsafe_script', token); + } + if (script.length !== 1 || + aint(script[0], 'id', '(') || + aint(script[0].first, 'id', '.') || + aint(script[0].first.first, 'string', 'ADSAFE') || + aint(script[0].second[0], 'string', adsafe_id)) { + stop('adsafe_id_go'); + } + switch (script[0].first.second.string) { + case 'id': + if (adsafe_may || adsafe_went || + script[0].second.length !== 1) { + stop('adsafe_id', next_token); + } + adsafe_may = true; + break; + case 'go': + if (adsafe_went) { + stop('adsafe_go'); + } + if (script[0].second.length !== 2 || + aint(script[0].second[1], 'id', 'function') || + !script[0].second[1].first || + aint(script[0].second[1].first[0], 'string', 'dom') || + script[0].second[1].first.length > 2 || + (script[0].second[1].first.length === 2 && + aint(script[0].second[1].first[1], 'string', 'lib'))) { + stop('adsafe_go', next_token); + } + adsafe_went = true; + break; + default: + stop('adsafe_id_go'); + } + } + indent = null; + } + xmode = 'html'; + advance(''); + styles(); + xmode = 'html'; + advance(''; + } + + function html() { + var attribute, attributes, is_empty, name, old_white = option.white, + quote, tag_name, tag, wmode; + xmode = 'html'; + xquote = ''; + stack = null; + for (;;) { + switch (next_token.string) { + case '<': + xmode = 'html'; + advance('<'); + attributes = {}; + tag_name = next_token; + name = tag_name.string; + advance_identifier(name); + if (option.cap) { + name = name.toLowerCase(); + } + tag_name.name = name; + if (!stack) { + stack = []; + do_begin(name); + } + tag = html_tag[name]; + if (typeof tag !== 'object') { + stop('unrecognized_tag_a', tag_name, name); + } + is_empty = tag.empty; + tag_name.type = name; + for (;;) { + if (next_token.id === '/') { + advance('/'); + if (next_token.id !== '>') { + warn('expected_a_b', next_token, '>', artifact()); + } + break; + } + if (next_token.id && next_token.id.charAt(0) === '>') { + break; + } + if (!next_token.identifier) { + if (next_token.id === '(end)' || next_token.id === '(error)') { + warn('expected_a_b', next_token, '>', artifact()); + } + warn('bad_name_a'); + } + option.white = false; + spaces(); + attribute = next_token.string; + option.white = old_white; + advance(); + if (!option.cap && attribute !== attribute.toLowerCase()) { + warn('attribute_case_a', token); + } + attribute = attribute.toLowerCase(); + xquote = ''; + if (Object.prototype.hasOwnProperty.call(attributes, attribute)) { + warn('duplicate_a', token, attribute); + } + if (attribute.slice(0, 2) === 'on') { + if (!option.on) { + warn('html_handlers'); + } + xmode = 'scriptstring'; + advance('='); + quote = next_token.id; + if (quote !== '"' && quote !== '\'') { + stop('expected_a_b', next_token, '"', artifact()); + } + xquote = quote; + wmode = option.white; + option.white = true; + advance(quote); + use_strict(); + statements(); + option.white = wmode; + if (next_token.id !== quote) { + stop('expected_a_b', next_token, quote, artifact()); + } + xmode = 'html'; + xquote = ''; + advance(quote); + tag = false; + } else if (attribute === 'style') { + xmode = 'scriptstring'; + advance('='); + quote = next_token.id; + if (quote !== '"' && quote !== '\'') { + stop('expected_a_b', next_token, '"', artifact()); + } + xmode = 'styleproperty'; + xquote = quote; + advance(quote); + substyle(); + xmode = 'html'; + xquote = ''; + advance(quote); + tag = false; + } else { + if (next_token.id === '=') { + advance('='); + tag = next_token.string; + if (!next_token.identifier && + next_token.id !== '"' && + next_token.id !== '\'' && + next_token.id !== '(string)' && + next_token.id !== '(string)' && + next_token.id !== '(color)') { + warn('expected_attribute_value_a', token, attribute); + } + advance(); + } else { + tag = true; + } + } + attributes[attribute] = tag; + do_attribute(attribute, tag); + } + do_tag(name, attributes); + if (!is_empty) { + stack.push(tag_name); + } + xmode = 'outer'; + advance('>'); + break; + case '') { + stop('expected_a_b', next_token, '>', artifact()); + } + xmode = 'outer'; + advance('>'); + break; + case '' || next_token.id === '(end)') { + break; + } + if (next_token.string.indexOf('--') >= 0) { + stop('unexpected_a', next_token, '--'); + } + if (next_token.string.indexOf('<') >= 0) { + stop('unexpected_a', next_token, '<'); + } + if (next_token.string.indexOf('>') >= 0) { + stop('unexpected_a', next_token, '>'); + } + } + xmode = 'outer'; + advance('>'); + break; + case '(end)': + if (stack.length !== 0) { + warn('missing_a', next_token, ''); + } + return; + default: + if (next_token.id === '(end)') { + stop('missing_a', next_token, + ''); + } else { + advance(); + } + } + if (stack && stack.length === 0 && (option.adsafe || + !option.fragment || next_token.id === '(end)')) { + break; + } + } + if (next_token.id !== '(end)') { + stop('unexpected_a'); + } + } + + +// The actual JSLINT function itself. + + itself = function JSLint(the_source, the_option) { + + var i, predef, tree; + JSLINT.errors = []; + JSLINT.tree = ''; + begin = prev_token = token = next_token = + Object.create(syntax['(begin)']); + predefined = {}; + add_to_predefined(standard); + property = {}; + if (the_option) { + option = Object.create(the_option); + predef = option.predef; + if (predef) { + if (Array.isArray(predef)) { + for (i = 0; i < predef.length; i += 1) { + predefined[predef[i]] = true; + } + } else if (typeof predef === 'object') { + add_to_predefined(predef); + } + } + do_safe(); + } else { + option = {}; + } + option.indent = +option.indent || 4; + option.maxerr = +option.maxerr || 50; + adsafe_id = ''; + adsafe_may = adsafe_top = adsafe_went = false; + approved = {}; + if (option.approved) { + for (i = 0; i < option.approved.length; i += 1) { + approved[option.approved[i]] = option.approved[i]; + } + } else { + approved.test = 'test'; + } + tab = ''; + for (i = 0; i < option.indent; i += 1) { + tab += ' '; + } + global_scope = scope = {}; + global_funct = funct = { + '(scope)': scope, + '(breakage)': 0, + '(loopage)': 0 + }; + functions = [funct]; + + comments_off = false; + ids = {}; + in_block = false; + indent = null; + json_mode = false; + lookahead = []; + node_js = false; + prereg = true; + src = false; + stack = null; + strict_mode = false; + urls = []; + var_mode = null; + warnings = 0; + xmode = ''; + lex.init(the_source); + + assume(); + + try { + advance(); + if (next_token.id === '(number)') { + stop('unexpected_a'); + } else if (next_token.string.charAt(0) === '<') { + html(); + if (option.adsafe && !adsafe_went) { + warn('adsafe_go', this); + } + } else { + switch (next_token.id) { + case '{': + case '[': + json_mode = true; + json_value(); + break; + case '@': + case '*': + case '#': + case '.': + case ':': + xmode = 'style'; + advance(); + if (token.id !== '@' || !next_token.identifier || + next_token.string !== 'charset' || token.line !== 1 || + token.from !== 1) { + stop('css'); + } + advance(); + if (next_token.id !== '(string)' && + next_token.string !== 'UTF-8') { + stop('css'); + } + advance(); + semicolon(); + styles(); + break; + + default: + if (option.adsafe && option.fragment) { + stop('expected_a_b', + next_token, '
', artifact()); + } + +// If the first token is a semicolon, ignore it. This is sometimes used when +// files are intended to be appended to files that may be sloppy. A sloppy +// file may be depending on semicolon insertion on its last line. + + step_in(1); + if (next_token.id === ';' && !node_js) { + semicolon(); + } + adsafe_top = true; + tree = statements(); + begin.first = tree; + JSLINT.tree = begin; + // infer_types(tree); + if (option.adsafe && (tree.length !== 1 || + aint(tree[0], 'id', '(') || + aint(tree[0].first, 'id', '.') || + aint(tree[0].first.first, 'string', 'ADSAFE') || + aint(tree[0].first.second, 'string', 'lib') || + tree[0].second.length !== 2 || + tree[0].second[0].id !== '(string)' || + aint(tree[0].second[1], 'id', 'function'))) { + stop('adsafe_lib'); + } + if (tree.disrupt) { + warn('weird_program', prev_token); + } + } + } + indent = null; + advance('(end)'); + } catch (e) { + if (e) { // ~~ + JSLINT.errors.push({ + reason : e.message, + line : e.line || next_token.line, + character : e.character || next_token.from + }, null); + } + } + return JSLINT.errors.length === 0; + }; + + +// Data summary. + + itself.data = function () { + var data = {functions: []}, + function_data, + globals, + i, + j, + kind, + members = [], + name, + the_function, + undef = [], + unused = []; + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (json_mode) { + data.json = true; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(global_scope).filter(function (value) { + return value.charAt(0) !== '(' && typeof standard[value] !== 'boolean'; + }); + if (globals.length > 0) { + data.globals = globals; + } + + for (i = 1; i < functions.length; i += 1) { + the_function = functions[i]; + function_data = {}; + for (j = 0; j < functionicity.length; j += 1) { + function_data[functionicity[j]] = []; + } + for (name in the_function) { + if (Object.prototype.hasOwnProperty.call(the_function, name)) { + if (name.charAt(0) !== '(') { + kind = the_function[name]; + if (kind === 'unction' || kind === 'unparam') { + kind = 'unused'; + } + if (Array.isArray(function_data[kind])) { + function_data[kind].push(name); + if (kind === 'unused') { + unused.push({ + name: name, + line: the_function['(line)'], + 'function': the_function['(name)'] + }); + } else if (kind === 'undef') { + undef.push({ + name: name, + line: the_function['(line)'], + 'function': the_function['(name)'] + }); + } + } + } + } + } + for (j = 0; j < functionicity.length; j += 1) { + if (function_data[functionicity[j]].length === 0) { + delete function_data[functionicity[j]]; + } + } + function_data.name = the_function['(name)']; + function_data.params = the_function['(params)']; + function_data.line = the_function['(line)']; + data.functions.push(function_data); + } + + if (unused.length > 0) { + data.unused = unused; + } + if (undef.length > 0) { + data['undefined'] = undef; + } + + members = []; + for (name in property) { + if (typeof property[name] === 'number') { + data.member = property; + break; + } + } + + return data; + }; + + + itself.report = function (errors_only) { + var data = itself.data(), err, evidence, i, italics, j, key, keys, + length, mem = '', name, names, not_first, output = [], snippets, + the_function, warning; + + function detail(h, value) { + var comma_needed, singularity; + if (Array.isArray(value)) { + output.push('
' + h + ' '); + value.sort().forEach(function (item) { + if (item !== singularity) { + singularity = item; + output.push((comma_needed ? ', ' : '') + singularity); + comma_needed = true; + } + }); + output.push('
'); + } else if (value) { + output.push('
' + h + ' ' + value + '
'); + } + } + + if (data.errors || data.unused || data['undefined']) { + err = true; + output.push('
Error:'); + if (data.errors) { + for (i = 0; i < data.errors.length; i += 1) { + warning = data.errors[i]; + if (warning) { + evidence = warning.evidence || ''; + output.push('

Problem' + (isFinite(warning.line) + ? ' at line ' + String(warning.line) + + ' character ' + String(warning.character) + : '') + + ': ' + warning.reason.entityify() + + '

' + + (evidence && (evidence.length > 80 + ? evidence.slice(0, 77) + '...' + : evidence).entityify()) + '

'); + } + } + } + + if (data['undefined']) { + snippets = []; + for (i = 0; i < data['undefined'].length; i += 1) { + snippets[i] = '' + data['undefined'][i].name + ' ' + + String(data['undefined'][i].line) + ' ' + + data['undefined'][i]['function'] + ''; + } + output.push('

Undefined variable: ' + snippets.join(', ') + '

'); + } + if (data.unused) { + snippets = []; + for (i = 0; i < data.unused.length; i += 1) { + snippets[i] = '' + data.unused[i].name + ' ' + + String(data.unused[i].line) + ' ' + + data.unused[i]['function'] + ''; + } + output.push('

Unused variable: ' + snippets.join(', ') + '

'); + } + if (data.json) { + output.push('

JSON: bad.

'); + } + output.push('
'); + } + + if (!errors_only) { + + output.push('
'); + + if (data.urls) { + detail("URLs
", data.urls, '
'); + } + + if (xmode === 'style') { + output.push('

CSS.

'); + } else if (data.json && !err) { + output.push('

JSON: good.

'); + } else if (data.globals) { + output.push('
Global ' + + data.globals.sort().join(', ') + '
'); + } else { + output.push('
No new global variables introduced.
'); + } + + for (i = 0; i < data.functions.length; i += 1) { + the_function = data.functions[i]; + names = []; + if (the_function.params) { + for (j = 0; j < the_function.params.length; j += 1) { + names[j] = the_function.params[j].string; + } + } + output.push('
' + + String(the_function.line) + ' ' + + the_function.name.entityify() + + '(' + names.join(', ') + ')
'); + detail('Undefined', the_function['undefined']); + detail('Unused', the_function.unused); + detail('Closure', the_function.closure); + detail('Variable', the_function['var']); + detail('Exception', the_function.exception); + detail('Outer', the_function.outer); + detail('Global', the_function.global); + detail('Label', the_function.label); + } + + if (data.member) { + keys = Object.keys(data.member); + if (keys.length) { + keys = keys.sort(); + output.push('
/*properties
'); + mem = ' '; + italics = 0; + j = 0; + not_first = false; + for (i = 0; i < keys.length; i += 1) { + key = keys[i]; + if (data.member[key] > 0) { + if (not_first) { + mem += ', '; + } + name = ix.test(key) + ? key + : '\'' + key.entityify().replace(nx, sanitize) + '\''; + length += name.length + 2; + if (data.member[key] === 1) { + name = '' + name + ''; + italics += 1; + j = 1; + } + if (mem.length + name.length - (italics * 7) > 80) { + output.push(mem + '
'); + mem = ' '; + italics = j; + } + mem += name; + j = 0; + not_first = true; + } + } + output.push(mem + '
*/
'); + } + output.push('
'); + } + } + return output.join(''); + }; + itself.jslint = itself; + + itself.edition = '2012-04-15'; + + return itself; +}()); +core.JSLint = function JSLint() { + this.JSLINT = JSLINT; +}; + diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/PointWalker.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/PointWalker.js new file mode 100644 index 0000000000..f3f0008f78 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/PointWalker.js @@ -0,0 +1,197 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, Node: true*/ +/** + * A simple walker that allows finegrained stepping through the DOM. + * It does not support node filtering. + * TODO: write a position walker that uses a treewalker + * @constructor + * @param {!Node} node + */ +core.PointWalker = function PointWalker(node) { + "use strict"; + var currentNode = node, + before = null, // node before the point + after = node && node.firstChild, // node after the point + root = node, + pos = 0; + + /** + * @param {!Node} node + * @return {!number} + */ + function getPosition(node) { + var /**@type{!number}*/ p = -1, + /**@type{Node}*/ n = node; + while (n) { + n = n.previousSibling; + p += 1; + } + return p; + } + /** + * Move the walker to the point given by @p node and @p position. + * @param {!Element} node must be the root of this walker or part of the + * tree of this walker. + * @param {!number} position must be a valid position in @node. + **/ + this.setPoint = function (node, position) { + currentNode = node; + pos = position; + if (currentNode.nodeType === 3) { // Node.TEXT_NODE + after = null; + before = null; + } else { + after = currentNode.firstChild; + while (position) { + position -= 1; + after = after.nextSibling; + } + if (after) { + before = after.previousSibling; + } else { + before = currentNode.lastChild; + } + } + }; + /** + * @return {!boolean} + */ + this.stepForward = function () { + var len; + // if this is a text node, move to the next position in the text + if (currentNode.nodeType === 3) { // TEXT_NODE + if (typeof currentNode.nodeValue.length === "number") { + len = currentNode.nodeValue.length; + } else { + len = currentNode.nodeValue.length(); + } + if (pos < len) { + pos += 1; + return true; + } + } + if (after) { + if (after.nodeType === 1) { // ELEMENT_NODE + currentNode = after; + before = null; + after = currentNode.firstChild; + pos = 0; + } else if (after.nodeType === 3) { // TEXT_NODE + currentNode = after; + before = null; + after = null; + pos = 0; + } else { + before = after; + after = after.nextSibling; + pos += 1; + } + return true; + } + if (currentNode !== root) { + before = currentNode; + after = before.nextSibling; + currentNode = currentNode.parentNode; + pos = getPosition(before) + 1; + return true; + } + return false; + }; + /** + * @return {!boolean} + */ + this.stepBackward = function () { + // if this is a text node, move to the next position in the text + if (currentNode.nodeType === 3) { // TEXT_NODE + if (pos > 0) { + pos -= 1; + return true; + } + } + if (before) { + if (before.nodeType === 1) { // ELEMENT_NODE + currentNode = before; + before = currentNode.lastChild; + after = null; + pos = getPosition(before) + 1; + } else if (before.nodeType === 3) { // TEXT_NODE + currentNode = before; + before = null; + after = null; + if (typeof currentNode.nodeValue.length === "number") { + pos = currentNode.nodeValue.length; + } else { + pos = currentNode.nodeValue.length(); + } + } else { + after = before; + before = before.previousSibling; + pos -= 1; + } + return true; + } + if (currentNode !== root) { + after = currentNode; + before = after.previousSibling; + currentNode = currentNode.parentNode; + pos = getPosition(after); + return true; + } + return false; + }; + /** + * @return {?Node} + */ + this.node = function () { + return currentNode; + }; + /** + * @return {!number} + */ + this.position = function () { + return pos; + }; + /** + * @return {?Node} + */ + this.precedingSibling = function () { + return before; + }; + /** + * @return {?Node} + */ + this.followingSibling = function () { + return after; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/RawDeflate.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/RawDeflate.js new file mode 100644 index 0000000000..5fdd2b02de --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/RawDeflate.js @@ -0,0 +1,1833 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core, runtime*/ +/*jslint bitwise: true, white: false, plusplus: true, vars: true, continue: true*/ +/* + * $Id: rawdeflate.js,v 0.3 2009/03/01 19:05:05 dankogai Exp dankogai $ + * + * Original: + * http://www.onicos.com/staff/iz/amuse/javascript/expert/deflate.txt + */ +/** + * @constructor + */ +core.RawDeflate = function () { + "use strict"; + /* Copyright (C) 1999 Masanao Izumo + * Version: 1.0.1 + * LastModified: Dec 25 1999 + */ + + /* Interface: + * data = zip_deflate(src); + */ + + /* constant parameters */ + var zip_WSIZE = 32768, // Sliding Window size + zip_STORED_BLOCK = 0, + zip_STATIC_TREES = 1, + zip_DYN_TREES = 2, + + /* for deflate */ + zip_DEFAULT_LEVEL = 6, + zip_FULL_SEARCH = true, + zip_INBUFSIZ = 32768, // Input buffer size + zip_INBUF_EXTRA = 64, // Extra buffer + zip_OUTBUFSIZ = 1024 * 8, + zip_window_size = 2 * zip_WSIZE, + zip_MIN_MATCH = 3, + zip_MAX_MATCH = 258, + zip_BITS = 16, + // for SMALL_MEM + zip_LIT_BUFSIZE = 0x2000, + zip_HASH_BITS = 13, + // for MEDIUM_MEM + // var zip_LIT_BUFSIZE = 0x4000; + // var zip_HASH_BITS = 14; + // for BIG_MEM + // var zip_LIT_BUFSIZE = 0x8000; + zip_DIST_BUFSIZE = zip_LIT_BUFSIZE, + zip_HASH_SIZE = 1 << zip_HASH_BITS, + zip_HASH_MASK = zip_HASH_SIZE - 1, + zip_WMASK = zip_WSIZE - 1, + zip_NIL = 0, // Tail of hash chains + zip_TOO_FAR = 4096, + zip_MIN_LOOKAHEAD = zip_MAX_MATCH + zip_MIN_MATCH + 1, + zip_MAX_DIST = zip_WSIZE - zip_MIN_LOOKAHEAD, + zip_SMALLEST = 1, + zip_MAX_BITS = 15, + zip_MAX_BL_BITS = 7, + zip_LENGTH_CODES = 29, + zip_LITERALS = 256, + zip_END_BLOCK = 256, + zip_L_CODES = zip_LITERALS + 1 + zip_LENGTH_CODES, + zip_D_CODES = 30, + zip_BL_CODES = 19, + zip_REP_3_6 = 16, + zip_REPZ_3_10 = 17, + zip_REPZ_11_138 = 18, + zip_HEAP_SIZE = 2 * zip_L_CODES + 1, + zip_H_SHIFT = parseInt((zip_HASH_BITS + zip_MIN_MATCH - 1) / + zip_MIN_MATCH, 10), + + /* variables */ + zip_free_queue, + zip_qhead, + zip_qtail, + zip_initflag, + zip_outbuf = null, + zip_outcnt, + zip_outoff, + zip_complete, + zip_window, + zip_d_buf, + zip_l_buf, + zip_prev, + zip_bi_buf, + zip_bi_valid, + zip_block_start, + zip_ins_h, + zip_hash_head, + zip_prev_match, + zip_match_available, + zip_match_length, + zip_prev_length, + zip_strstart, + zip_match_start, + zip_eofile, + zip_lookahead, + zip_max_chain_length, + zip_max_lazy_match, + zip_compr_level, + zip_good_match, + zip_nice_match, + zip_dyn_ltree, + zip_dyn_dtree, + zip_static_ltree, + zip_static_dtree, + zip_bl_tree, + zip_l_desc, + zip_d_desc, + zip_bl_desc, + zip_bl_count, + zip_heap, + zip_heap_len, + zip_heap_max, + zip_depth, + zip_length_code, + zip_dist_code, + zip_base_length, + zip_base_dist, + zip_flag_buf, + zip_last_lit, + zip_last_dist, + zip_last_flags, + zip_flags, + zip_flag_bit, + zip_opt_len, + zip_static_len, + zip_deflate_data, + zip_deflate_pos, + // var zip_HASH_BITS = 15; + /* constant tables */ + zip_extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0], + zip_extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13], + zip_extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7], + zip_bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], + zip_configuration_table; + if (zip_LIT_BUFSIZE > zip_INBUFSIZ) { + runtime.log("error: zip_INBUFSIZ is too small"); + } + if ((zip_WSIZE << 1) > (1 << zip_BITS)) { + runtime.log("error: zip_WSIZE is too large"); + } + if (zip_HASH_BITS > zip_BITS - 1) { + runtime.log("error: zip_HASH_BITS is too large"); + } + if (zip_HASH_BITS < 8 || zip_MAX_MATCH !== 258) { + runtime.log("error: Code too clever"); + } + + /* objects (deflate) */ + /** + * @constructor + */ + function Zip_DeflateCT() { + this.fc = 0; // frequency count or bit string + this.dl = 0; // father node in Huffman tree or length of bit string + } + /** + * @constructor + */ + function Zip_DeflateTreeDesc() { + this.dyn_tree = null; // the dynamic tree + this.static_tree = null; // corresponding static tree or NULL + this.extra_bits = null; // extra bits for each code or NULL + this.extra_base = 0; // base index for extra_bits + this.elems = 0; // max number of elements in the tree + this.max_length = 0; // max bit length for the codes + this.max_code = 0; // largest code with non zero frequency + } + + /** Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + * @constructor + */ + function Zip_DeflateConfiguration(a, b, c, d) { + this.good_length = a; // reduce lazy search above this match length + this.max_lazy = b; // do not perform lazy search above this match length + this.nice_length = c; // quit search above this match length + this.max_chain = d; + } + + /** + * @constructor + */ + function Zip_DeflateBuffer() { + this.next = null; + this.len = 0; + this.ptr = []; + this.ptr.length = zip_OUTBUFSIZ; + this.off = 0; + } + + /* constant tables */ + zip_configuration_table = [ + new Zip_DeflateConfiguration(0, 0, 0, 0), + new Zip_DeflateConfiguration(4, 4, 8, 4), + new Zip_DeflateConfiguration(4, 5, 16, 8), + new Zip_DeflateConfiguration(4, 6, 32, 32), + new Zip_DeflateConfiguration(4, 4, 16, 16), + new Zip_DeflateConfiguration(8, 16, 32, 32), + new Zip_DeflateConfiguration(8, 16, 128, 128), + new Zip_DeflateConfiguration(8, 32, 128, 256), + new Zip_DeflateConfiguration(32, 128, 258, 1024), + new Zip_DeflateConfiguration(32, 258, 258, 4096) + ]; + + + /* routines (deflate) */ + + function zip_deflate_start(level) { + var i; + + if (!level) { + level = zip_DEFAULT_LEVEL; + } else if (level < 1) { + level = 1; + } else if (level > 9) { + level = 9; + } + + zip_compr_level = level; + zip_initflag = false; + zip_eofile = false; + if (zip_outbuf !== null) { + return; + } + + zip_free_queue = zip_qhead = zip_qtail = null; + zip_outbuf = []; + zip_outbuf.length = zip_OUTBUFSIZ; + zip_window = []; + zip_window.length = zip_window_size; + zip_d_buf = []; + zip_d_buf.length = zip_DIST_BUFSIZE; + zip_l_buf = []; + zip_l_buf.length = zip_INBUFSIZ + zip_INBUF_EXTRA; + zip_prev = []; + zip_prev.length = 1 << zip_BITS; + zip_dyn_ltree = []; + zip_dyn_ltree.length = zip_HEAP_SIZE; + for (i = 0; i < zip_HEAP_SIZE; i++) { + zip_dyn_ltree[i] = new Zip_DeflateCT(); + } + zip_dyn_dtree = []; + zip_dyn_dtree.length = 2 * zip_D_CODES + 1; + for (i = 0; i < 2 * zip_D_CODES + 1; i++) { + zip_dyn_dtree[i] = new Zip_DeflateCT(); + } + zip_static_ltree = []; + zip_static_ltree.length = zip_L_CODES + 2; + for (i = 0; i < zip_L_CODES + 2; i++) { + zip_static_ltree[i] = new Zip_DeflateCT(); + } + zip_static_dtree = []; + zip_static_dtree.length = zip_D_CODES; + for (i = 0; i < zip_D_CODES; i++) { + zip_static_dtree[i] = new Zip_DeflateCT(); + } + zip_bl_tree = []; + zip_bl_tree.length = 2 * zip_BL_CODES + 1; + for (i = 0; i < 2 * zip_BL_CODES + 1; i++) { + zip_bl_tree[i] = new Zip_DeflateCT(); + } + zip_l_desc = new Zip_DeflateTreeDesc(); + zip_d_desc = new Zip_DeflateTreeDesc(); + zip_bl_desc = new Zip_DeflateTreeDesc(); + zip_bl_count = []; + zip_bl_count.length = zip_MAX_BITS + 1; + zip_heap = []; + zip_heap.length = 2 * zip_L_CODES + 1; + zip_depth = []; + zip_depth.length = 2 * zip_L_CODES + 1; + zip_length_code = []; + zip_length_code.length = zip_MAX_MATCH - zip_MIN_MATCH + 1; + zip_dist_code = []; + zip_dist_code.length = 512; + zip_base_length = []; + zip_base_length.length = zip_LENGTH_CODES; + zip_base_dist = []; + zip_base_dist.length = zip_D_CODES; + zip_flag_buf = []; + zip_flag_buf.length = parseInt(zip_LIT_BUFSIZE / 8, 10); + } + + var zip_deflate_end = function () { + zip_free_queue = zip_qhead = zip_qtail = null; + zip_outbuf = null; + zip_window = null; + zip_d_buf = null; + zip_l_buf = null; + zip_prev = null; + zip_dyn_ltree = null; + zip_dyn_dtree = null; + zip_static_ltree = null; + zip_static_dtree = null; + zip_bl_tree = null; + zip_l_desc = null; + zip_d_desc = null; + zip_bl_desc = null; + zip_bl_count = null; + zip_heap = null; + zip_depth = null; + zip_length_code = null; + zip_dist_code = null; + zip_base_length = null; + zip_base_dist = null; + zip_flag_buf = null; + }; + + var zip_reuse_queue = function (p) { + p.next = zip_free_queue; + zip_free_queue = p; + }; + + var zip_new_queue = function () { + var p; + + if (zip_free_queue !== null) { + p = zip_free_queue; + zip_free_queue = zip_free_queue.next; + } else { + p = new Zip_DeflateBuffer(); + } + p.next = null; + p.len = p.off = 0; + + return p; + }; + + var zip_head1 = function (i) { + return zip_prev[zip_WSIZE + i]; + }; + + var zip_head2 = function (i, val) { + zip_prev[zip_WSIZE + i] = val; + return val; + }; + + var zip_qoutbuf = function () { + var q, i; + if (zip_outcnt !== 0) { + q = zip_new_queue(); + if (zip_qhead === null) { + zip_qhead = zip_qtail = q; + } else { + zip_qtail = zip_qtail.next = q; + } + q.len = zip_outcnt - zip_outoff; + // System.arraycopy(zip_outbuf, zip_outoff, q.ptr, 0, q.len); + for (i = 0; i < q.len; i++) { + q.ptr[i] = zip_outbuf[zip_outoff + i]; + } + zip_outcnt = zip_outoff = 0; + } + }; + + /* put_byte is used for the compressed output, put_ubyte for the + * uncompressed output. However unlzw() uses window for its + * suffix table instead of its output buffer, so it does not use put_ubyte + * (to be cleaned up). + */ + var zip_put_byte = function (c) { + zip_outbuf[zip_outoff + zip_outcnt++] = c; + if (zip_outoff + zip_outcnt === zip_OUTBUFSIZ) { + zip_qoutbuf(); + } + }; + + /* Output a 16 bit value, lsb first */ + var zip_put_short = function (w) { + w &= 0xffff; + if (zip_outoff + zip_outcnt < zip_OUTBUFSIZ - 2) { + zip_outbuf[zip_outoff + zip_outcnt++] = (w & 0xff); + zip_outbuf[zip_outoff + zip_outcnt++] = (w >>> 8); + } else { + zip_put_byte(w & 0xff); + zip_put_byte(w >>> 8); + } + }; + + /* ========================================================================== + * Insert string s in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of s are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ + var zip_INSERT_STRING = function () { + zip_ins_h = ((zip_ins_h << zip_H_SHIFT) + ^ (zip_window[zip_strstart + zip_MIN_MATCH - 1] & 0xff)) + & zip_HASH_MASK; + zip_hash_head = zip_head1(zip_ins_h); + zip_prev[zip_strstart & zip_WMASK] = zip_hash_head; + zip_head2(zip_ins_h, zip_strstart); + }; + + /* ========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ + var zip_Buf_size = 16; // bit size of bi_buf + var zip_send_bits = function ( + value, // value to send + length + ) { // number of bits + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (zip_bi_valid > zip_Buf_size - length) { + zip_bi_buf |= (value << zip_bi_valid); + zip_put_short(zip_bi_buf); + zip_bi_buf = (value >> (zip_Buf_size - zip_bi_valid)); + zip_bi_valid += length - zip_Buf_size; + } else { + zip_bi_buf |= value << zip_bi_valid; + zip_bi_valid += length; + } + }; + + /* Send a code of the given tree. c and tree must not have side effects */ + var zip_SEND_CODE = function (c, tree) { + zip_send_bits(tree[c].fc, tree[c].dl); + }; + + /* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. dist_code[256] and dist_code[257] are never + * used. + */ + var zip_D_CODE = function (dist) { + return (dist < 256 ? zip_dist_code[dist] + : zip_dist_code[256 + (dist >> 7)]) & 0xff; + }; + + /* ========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ + var zip_SMALLER = function (tree, n, m) { + return tree[n].fc < tree[m].fc || + (tree[n].fc === tree[m].fc && zip_depth[n] <= zip_depth[m]); + }; + + /* ========================================================================== + * read string data + */ + var zip_read_buff = function (buff, offset, n) { + var i; + for (i = 0; i < n && zip_deflate_pos < zip_deflate_data.length; i++) { + buff[offset + i] = + zip_deflate_data.charCodeAt(zip_deflate_pos++) & 0xff; + } + return i; + }; + + /* ========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead, and sets eofile if end of input file. + * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 + * OUT assertions: at least one byte has been read, or eofile is set; + * file reads are performed for at least two bytes (required for the + * translate_eol option). + */ + var zip_fill_window = function () { + var n, m; + + // Amount of free space at the end of the window. + var more = zip_window_size - zip_lookahead - zip_strstart; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (more === -1) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + } else if (zip_strstart >= zip_WSIZE + zip_MAX_DIST) { + /* By the IN assertion, the window is not empty so we can't confuse + * more == 0 with more == 64K on a 16 bit machine. + */ + // Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM"); + + // System.arraycopy(window, WSIZE, window, 0, WSIZE); + for (n = 0; n < zip_WSIZE; n++) { + zip_window[n] = zip_window[n + zip_WSIZE]; + } + + zip_match_start -= zip_WSIZE; + zip_strstart -= zip_WSIZE; /* we now have strstart >= MAX_DIST: */ + zip_block_start -= zip_WSIZE; + + for (n = 0; n < zip_HASH_SIZE; n++) { + m = zip_head1(n); + zip_head2(n, m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL); + } + for (n = 0; n < zip_WSIZE; n++) { + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + m = zip_prev[n]; + zip_prev[n] = (m >= zip_WSIZE ? m - zip_WSIZE : zip_NIL); + } + more += zip_WSIZE; + } + // At this point, more >= 2 + if (!zip_eofile) { + n = zip_read_buff(zip_window, zip_strstart + zip_lookahead, more); + if (n <= 0) { + zip_eofile = true; + } else { + zip_lookahead += n; + } + } + }; + + + /* ========================================================================== + * Initialize the "longest match" routines for a new file + */ + var zip_lm_init = function () { + var j; + + /* Initialize the hash table. */ + for (j = 0; j < zip_HASH_SIZE; j++) { + // zip_head2(j, zip_NIL); + zip_prev[zip_WSIZE + j] = 0; + } + /* prev will be initialized on the fly */ + + /* Set the default configuration parameters: + */ + zip_max_lazy_match = zip_configuration_table[zip_compr_level].max_lazy; + zip_good_match = zip_configuration_table[zip_compr_level].good_length; + if (!zip_FULL_SEARCH) { + zip_nice_match = zip_configuration_table[zip_compr_level].nice_length; + } + zip_max_chain_length = zip_configuration_table[zip_compr_level].max_chain; + + zip_strstart = 0; + zip_block_start = 0; + + zip_lookahead = zip_read_buff(zip_window, 0, 2 * zip_WSIZE); + if (zip_lookahead <= 0) { + zip_eofile = true; + zip_lookahead = 0; + return; + } + zip_eofile = false; + /* Make sure that we always have enough lookahead. This is important + * if input comes from a device such as a tty. + */ + while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) { + zip_fill_window(); + } + + /* If lookahead < MIN_MATCH, ins_h is garbage, but this is + * not important since only literal bytes will be emitted. + */ + zip_ins_h = 0; + for (j = 0; j < zip_MIN_MATCH - 1; j++) { + // UPDATE_HASH(ins_h, window[j]); + zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[j] & 0xff)) & zip_HASH_MASK; + } + }; + + /* ========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + */ + var zip_longest_match = function (cur_match) { + var chain_length = zip_max_chain_length; // max hash chain length + var scanp = zip_strstart; // current string + var matchp; // matched string + var len; // length of current match + var best_len = zip_prev_length; // best match length so far + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + var limit = (zip_strstart > zip_MAX_DIST ? zip_strstart - zip_MAX_DIST : zip_NIL); + + var strendp = zip_strstart + zip_MAX_MATCH; + var scan_end1 = zip_window[scanp + best_len - 1]; + var scan_end = zip_window[scanp + best_len]; + + /* Do not waste too much time if we already have a good match: */ + if (zip_prev_length >= zip_good_match) { + chain_length >>= 2; + } + + // Assert(encoder->strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead"); + + do { + // Assert(cur_match < encoder->strstart, "no future"); + matchp = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ + if (zip_window[matchp + best_len] !== scan_end || + zip_window[matchp + best_len - 1] !== scan_end1 || + zip_window[matchp] !== zip_window[scanp] || + zip_window[++matchp] !== zip_window[scanp + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scanp += 2; + matchp++; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + ++scanp; + } while (zip_window[scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + zip_window[++scanp] === zip_window[++matchp] && + scanp < strendp); + + len = zip_MAX_MATCH - (strendp - scanp); + scanp = strendp - zip_MAX_MATCH; + + if (len > best_len) { + zip_match_start = cur_match; + best_len = len; + if (zip_FULL_SEARCH) { + if (len >= zip_MAX_MATCH) { + break; + } + } else { + if (len >= zip_nice_match) { + break; + } + } + + scan_end1 = zip_window[scanp + best_len - 1]; + scan_end = zip_window[scanp + best_len]; + } + } while ((cur_match = zip_prev[cur_match & zip_WMASK]) > limit + && --chain_length !== 0); + + return best_len; + }; + + /* ========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ + var zip_ct_tally = function ( + dist, // distance of matched string + lc + ) { // match length-MIN_MATCH or unmatched char (if dist==0) + zip_l_buf[zip_last_lit++] = lc; + if (dist === 0) { + // lc is the unmatched char + zip_dyn_ltree[lc].fc++; + } else { + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + // Assert((ush)dist < (ush)MAX_DIST && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)D_CODE(dist) < (ush)D_CODES, "ct_tally: bad match"); + + zip_dyn_ltree[zip_length_code[lc] + zip_LITERALS + 1].fc++; + zip_dyn_dtree[zip_D_CODE(dist)].fc++; + + zip_d_buf[zip_last_dist++] = dist; + zip_flags |= zip_flag_bit; + } + zip_flag_bit <<= 1; + + // Output the flags if they fill a byte + if ((zip_last_lit & 7) === 0) { + zip_flag_buf[zip_last_flags++] = zip_flags; + zip_flags = 0; + zip_flag_bit = 1; + } + // Try to guess if it is profitable to stop the current block here + if (zip_compr_level > 2 && (zip_last_lit & 0xfff) === 0) { + // Compute an upper bound for the compressed length + var out_length = zip_last_lit * 8; + var in_length = zip_strstart - zip_block_start; + var dcode; + + for (dcode = 0; dcode < zip_D_CODES; dcode++) { + out_length += zip_dyn_dtree[dcode].fc * (5 + zip_extra_dbits[dcode]); + } + out_length >>= 3; + // Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", + // encoder->last_lit, encoder->last_dist, in_length, out_length, + // 100L - out_length*100L/in_length)); + if (zip_last_dist < parseInt(zip_last_lit / 2, 10) && + out_length < parseInt(in_length / 2, 10)) { + return true; + } + } + return (zip_last_lit === zip_LIT_BUFSIZE - 1 || + zip_last_dist === zip_DIST_BUFSIZE); + /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + }; + + /* ========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ + var zip_pqdownheap = function ( + tree, // the tree to restore + k + ) { // node to move down + var v = zip_heap[k]; + var j = k << 1; // left son of k + + while (j <= zip_heap_len) { + // Set j to the smallest of the two sons: + if (j < zip_heap_len && + zip_SMALLER(tree, zip_heap[j + 1], zip_heap[j])) { + j++; + } + + // Exit if v is smaller than both sons + if (zip_SMALLER(tree, v, zip_heap[j])) { + break; + } + + // Exchange v with the smallest son + zip_heap[k] = zip_heap[j]; + k = j; + + // And continue down the tree, setting j to the left son of k + j <<= 1; + } + zip_heap[k] = v; + }; + + /* ========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ + var zip_gen_bitlen = function (desc) { // the tree descriptor + var tree = desc.dyn_tree; + var extra = desc.extra_bits; + var base = desc.extra_base; + var max_code = desc.max_code; + var max_length = desc.max_length; + var stree = desc.static_tree; + var h; // heap index + var n, m; // iterate over the tree elements + var bits; // bit length + var xbits; // extra bits + var f; // frequency + var overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= zip_MAX_BITS; bits++) { + zip_bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[zip_heap[zip_heap_max]].dl = 0; // root of the heap + + for (h = zip_heap_max + 1; h < zip_HEAP_SIZE; h++) { + n = zip_heap[h]; + bits = tree[tree[n].dl].dl + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n].dl = bits; + // We overwrite tree[n].dl which is no longer needed + + if (n > max_code) { + continue; // not a leaf node + } + + zip_bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n].fc; + zip_opt_len += f * (bits + xbits); + if (stree !== null) { + zip_static_len += f * (stree[n].dl + xbits); + } + } + if (overflow === 0) { + return; + } + + // This happens for example on obj2 and pic of the Calgary corpus + + // Find the first bit length which could increase: + do { + bits = max_length - 1; + while (zip_bl_count[bits] === 0) { + bits--; + } + zip_bl_count[bits]--; // move one leaf down the tree + zip_bl_count[bits + 1] += 2; // move one overflow item as its brother + zip_bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = zip_bl_count[bits]; + while (n !== 0) { + m = zip_heap[--h]; + if (m > max_code) { + continue; + } + if (tree[m].dl !== bits) { + zip_opt_len += (bits - tree[m].dl) * tree[m].fc; + tree[m].fc = bits; + } + n--; + } + } + }; + + /* ========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ + var zip_bi_reverse = function ( + code, // the value to invert + len + ) { // its bit length + var res = 0; + do { + res |= code & 1; + code >>= 1; + res <<= 1; + } while (--len > 0); + return res >> 1; + }; + + /* ========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ + var zip_gen_codes = function (tree, // the tree to decorate + max_code) { // largest code with non zero frequency + var next_code = []; + next_code.length = zip_MAX_BITS + 1; // next code value for each bit length + var code = 0; // running code value + var bits; // bit index + var n; // code index + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= zip_MAX_BITS; bits++) { + code = ((code + zip_bl_count[bits - 1]) << 1); + next_code[bits] = code; + } + + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + // Assert (code + encoder->bl_count[MAX_BITS]-1 == (1<> 1; n >= 1; n--) { + zip_pqdownheap(tree, n); + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + n = zip_heap[zip_SMALLEST]; + zip_heap[zip_SMALLEST] = zip_heap[zip_heap_len--]; + zip_pqdownheap(tree, zip_SMALLEST); + + m = zip_heap[zip_SMALLEST]; // m = node of next least frequency + + // keep the nodes sorted by frequency + zip_heap[--zip_heap_max] = n; + zip_heap[--zip_heap_max] = m; + + // Create a new node father of n and m + tree[node].fc = tree[n].fc + tree[m].fc; + // depth[node] = (char)(MAX(depth[n], depth[m]) + 1); + if (zip_depth[n] > zip_depth[m] + 1) { + zip_depth[node] = zip_depth[n]; + } else { + zip_depth[node] = zip_depth[m] + 1; + } + tree[n].dl = tree[m].dl = node; + + // and insert the new node in the heap + zip_heap[zip_SMALLEST] = node++; + zip_pqdownheap(tree, zip_SMALLEST); + + } while (zip_heap_len >= 2); + + zip_heap[--zip_heap_max] = zip_heap[zip_SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + zip_gen_bitlen(desc); + + // The field len is now set, we can generate the bit codes + zip_gen_codes(tree, max_code); + }; + + /* ========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. Updates opt_len to take into account the repeat + * counts. (The contribution of the bit length codes will be added later + * during the construction of bl_tree.) + */ + var zip_scan_tree = function (tree,// the tree to be scanned + max_code) { // and its largest code of non zero frequency + var n; // iterates over all tree elements + var prevlen = -1; // last emitted length + var curlen; // length of current code + var nextlen = tree[0].dl; // length of next code + var count = 0; // repeat count of the current code + var max_count = 7; // max repeat count + var min_count = 4; // min repeat count + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[max_code + 1].dl = 0xffff; // guard + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if (++count < max_count && curlen === nextlen) { + continue; + } else if (count < min_count) { + zip_bl_tree[curlen].fc += count; + } else if (curlen !== 0) { + if (curlen !== prevlen) { + zip_bl_tree[curlen].fc++; + } + zip_bl_tree[zip_REP_3_6].fc++; + } else if (count <= 10) { + zip_bl_tree[zip_REPZ_3_10].fc++; + } else { + zip_bl_tree[zip_REPZ_11_138].fc++; + } + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + }; + + + /* ========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ + var zip_build_bl_tree = function () { + var max_blindex; // index of last bit length code of non zero freq + + // Determine the bit length frequencies for literal and distance trees + zip_scan_tree(zip_dyn_ltree, zip_l_desc.max_code); + zip_scan_tree(zip_dyn_dtree, zip_d_desc.max_code); + + // Build the bit length tree: + zip_build_tree(zip_bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = zip_BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (zip_bl_tree[zip_bl_order[max_blindex]].dl !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + zip_opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + // Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + + return max_blindex; + }; + + /* ========================================================================== + * Write out any remaining bits in an incomplete byte. + */ + var zip_bi_windup = function () { + if (zip_bi_valid > 8) { + zip_put_short(zip_bi_buf); + } else if (zip_bi_valid > 0) { + zip_put_byte(zip_bi_buf); + } + zip_bi_buf = 0; + zip_bi_valid = 0; + }; + + /* ========================================================================== + * Send the block data compressed using the given Huffman trees + */ + var zip_compress_block = function ( + ltree, // literal tree + dtree + ) { // distance tree + var dist; // distance of matched string + var lc; // match length or unmatched char (if dist == 0) + var lx = 0; // running index in l_buf + var dx = 0; // running index in d_buf + var fx = 0; // running index in flag_buf + var flag = 0; // current flags + var code; // the code to send + var extra; // number of extra bits to send + + if (zip_last_lit !== 0) { + do { + if ((lx & 7) === 0) { + flag = zip_flag_buf[fx++]; + } + lc = zip_l_buf[lx++] & 0xff; + if ((flag & 1) === 0) { + zip_SEND_CODE(lc, ltree); /* send a literal byte */ + // Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + // Here, lc is the match length - MIN_MATCH + code = zip_length_code[lc]; + zip_SEND_CODE(code + zip_LITERALS + 1, ltree); // send the length code + extra = zip_extra_lbits[code]; + if (extra !== 0) { + lc -= zip_base_length[code]; + zip_send_bits(lc, extra); // send the extra length bits + } + dist = zip_d_buf[dx++]; + // Here, dist is the match distance - 1 + code = zip_D_CODE(dist); + // Assert (code < D_CODES, "bad d_code"); + + zip_SEND_CODE(code, dtree); // send the distance code + extra = zip_extra_dbits[code]; + if (extra !== 0) { + dist -= zip_base_dist[code]; + zip_send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + flag >>= 1; + } while (lx < zip_last_lit); + } + + zip_SEND_CODE(zip_END_BLOCK, ltree); + }; + + /* ========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ + var zip_send_tree = function (tree, // the tree to be scanned + max_code) { // and its largest code of non zero frequency + var n; // iterates over all tree elements + var prevlen = -1; // last emitted length + var curlen; // length of current code + var nextlen = tree[0].dl; // length of next code + var count = 0; // repeat count of the current code + var max_count = 7; // max repeat count + var min_count = 4; // min repeat count + + /* tree[max_code+1].dl = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[n + 1].dl; + if (++count < max_count && curlen === nextlen) { + continue; + } else if (count < min_count) { + do { + zip_SEND_CODE(curlen, zip_bl_tree); + } while (--count !== 0); + } else if (curlen !== 0) { + if (curlen !== prevlen) { + zip_SEND_CODE(curlen, zip_bl_tree); + count--; + } + // Assert(count >= 3 && count <= 6, " 3_6?"); + zip_SEND_CODE(zip_REP_3_6, zip_bl_tree); + zip_send_bits(count - 3, 2); + } else if (count <= 10) { + zip_SEND_CODE(zip_REPZ_3_10, zip_bl_tree); + zip_send_bits(count - 3, 3); + } else { + zip_SEND_CODE(zip_REPZ_11_138, zip_bl_tree); + zip_send_bits(count - 11, 7); + } + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + }; + + /* ========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ + var zip_send_all_trees = function (lcodes, dcodes, blcodes) { // number of codes for each tree + var rank; // index in bl_order + + // Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + // Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + // Tracev((stderr, "\nbl counts: ")); + zip_send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt + zip_send_bits(dcodes - 1, 5); + zip_send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + // Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + zip_send_bits(zip_bl_tree[zip_bl_order[rank]].dl, 3); + } + + // send the literal tree + zip_send_tree(zip_dyn_ltree, lcodes - 1); + + // send the distance tree + zip_send_tree(zip_dyn_dtree, dcodes - 1); + }; + + /* ========================================================================== + * Initialize a new block. + */ + var zip_init_block = function () { + var n; // iterates over tree elements + + // Initialize the trees. + for (n = 0; n < zip_L_CODES; n++) { + zip_dyn_ltree[n].fc = 0; + } + for (n = 0; n < zip_D_CODES; n++) { + zip_dyn_dtree[n].fc = 0; + } + for (n = 0; n < zip_BL_CODES; n++) { + zip_bl_tree[n].fc = 0; + } + + zip_dyn_ltree[zip_END_BLOCK].fc = 1; + zip_opt_len = zip_static_len = 0; + zip_last_lit = zip_last_dist = zip_last_flags = 0; + zip_flags = 0; + zip_flag_bit = 1; + }; + + /* ========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ + var zip_flush_block = function (eof) { // true if this is the last block for a file + var opt_lenb, static_lenb; // opt_len and static_len in bytes + var max_blindex; // index of last bit length code of non zero freq + var stored_len; // length of input block + + stored_len = zip_strstart - zip_block_start; + zip_flag_buf[zip_last_flags] = zip_flags; // Save the flags for the last 8 items + + // Construct the literal and distance trees + zip_build_tree(zip_l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + + zip_build_tree(zip_d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", + // encoder->opt_len, encoder->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = zip_build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb = (zip_opt_len + 3 + 7) >> 3; + static_lenb = (zip_static_len + 3 + 7) >> 3; + + // Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", + // opt_lenb, encoder->opt_len, + // static_lenb, encoder->static_len, stored_len, + // encoder->last_lit, encoder->last_dist)); + + if (static_lenb <= opt_lenb) { + opt_lenb = static_lenb; + } + if (stored_len + 4 <= opt_lenb // 4: two words for the lengths + && zip_block_start >= 0) { + var i; + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + zip_send_bits((zip_STORED_BLOCK << 1) + eof, 3); /* send block type */ + zip_bi_windup(); /* align on byte boundary */ + zip_put_short(stored_len); + zip_put_short(~stored_len); + + // copy block + /* + p = &window[block_start]; + for (i = 0; i < stored_len; i++) + put_byte(p[i]); + */ + for (i = 0; i < stored_len; i++) { + zip_put_byte(zip_window[zip_block_start + i]); + } + + } else if (static_lenb === opt_lenb) { + zip_send_bits((zip_STATIC_TREES << 1) + eof, 3); + zip_compress_block(zip_static_ltree, zip_static_dtree); + } else { + zip_send_bits((zip_DYN_TREES << 1) + eof, 3); + zip_send_all_trees(zip_l_desc.max_code + 1, + zip_d_desc.max_code + 1, + max_blindex + 1); + zip_compress_block(zip_dyn_ltree, zip_dyn_dtree); + } + + zip_init_block(); + + if (eof !== 0) { + zip_bi_windup(); + } + }; + + /* ========================================================================== + * Processes a new input file and return its compressed length. This + * function does not perform lazy evaluationof matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ + var zip_deflate_fast = function () { + while (zip_lookahead !== 0 && zip_qhead === null) { + var flush; // set if current block must be flushed + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + zip_INSERT_STRING(); + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (zip_hash_head !== zip_NIL && + zip_strstart - zip_hash_head <= zip_MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + zip_match_length = zip_longest_match(zip_hash_head); + /* longest_match() sets match_start */ + if (zip_match_length > zip_lookahead) { + zip_match_length = zip_lookahead; + } + } + if (zip_match_length >= zip_MIN_MATCH) { + // check_match(strstart, match_start, match_length); + + flush = zip_ct_tally(zip_strstart - zip_match_start, + zip_match_length - zip_MIN_MATCH); + zip_lookahead -= zip_match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (zip_match_length <= zip_max_lazy_match) { + zip_match_length--; // string at strstart already in hash table + do { + zip_strstart++; + zip_INSERT_STRING(); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since + * the next lookahead bytes will be emitted as literals. + */ + } while (--zip_match_length !== 0); + zip_strstart++; + } else { + zip_strstart += zip_match_length; + zip_match_length = 0; + zip_ins_h = zip_window[zip_strstart] & 0xff; + // UPDATE_HASH(ins_h, window[strstart + 1]); + zip_ins_h = ((zip_ins_h << zip_H_SHIFT) ^ (zip_window[zip_strstart + 1] & 0xff)) & zip_HASH_MASK; + + //#if MIN_MATCH != 3 + // Call UPDATE_HASH() MIN_MATCH-3 more times + //#endif + + } + } else { + /* No match, output a literal byte */ + flush = zip_ct_tally(0, zip_window[zip_strstart] & 0xff); + zip_lookahead--; + zip_strstart++; + } + if (flush) { + zip_flush_block(0); + zip_block_start = zip_strstart; + } + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) { + zip_fill_window(); + } + } + }; + + var zip_deflate_better = function () { + /* Process the input block. */ + while (zip_lookahead !== 0 && zip_qhead === null) { + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + zip_INSERT_STRING(); + + /* Find the longest match, discarding those <= prev_length. + */ + zip_prev_length = zip_match_length; + zip_prev_match = zip_match_start; + zip_match_length = zip_MIN_MATCH - 1; + + if (zip_hash_head !== zip_NIL && + zip_prev_length < zip_max_lazy_match && + zip_strstart - zip_hash_head <= zip_MAX_DIST) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + zip_match_length = zip_longest_match(zip_hash_head); + /* longest_match() sets match_start */ + if (zip_match_length > zip_lookahead) { + zip_match_length = zip_lookahead; + } + + /* Ignore a length 3 match if it is too distant: */ + if (zip_match_length === zip_MIN_MATCH && + zip_strstart - zip_match_start > zip_TOO_FAR) { + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + zip_match_length--; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (zip_prev_length >= zip_MIN_MATCH && + zip_match_length <= zip_prev_length) { + var flush; // set if current block must be flushed + + // check_match(strstart - 1, prev_match, prev_length); + flush = zip_ct_tally(zip_strstart - 1 - zip_prev_match, + zip_prev_length - zip_MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. + */ + zip_lookahead -= zip_prev_length - 1; + zip_prev_length -= 2; + do { + zip_strstart++; + zip_INSERT_STRING(); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since the + * next lookahead bytes will always be emitted as literals. + */ + } while (--zip_prev_length !== 0); + zip_match_available = 0; + zip_match_length = zip_MIN_MATCH - 1; + zip_strstart++; + if (flush) { + zip_flush_block(0); + zip_block_start = zip_strstart; + } + } else if (zip_match_available !== 0) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + if (zip_ct_tally(0, zip_window[zip_strstart - 1] & 0xff)) { + zip_flush_block(0); + zip_block_start = zip_strstart; + } + zip_strstart++; + zip_lookahead--; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + zip_match_available = 1; + zip_strstart++; + zip_lookahead--; + } + + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + while (zip_lookahead < zip_MIN_LOOKAHEAD && !zip_eofile) { + zip_fill_window(); + } + } + }; + + /* ========================================================================== + * Allocate the match buffer, initialize the various tables and save the + * location of the internal file attribute (ascii/binary) and method + * (DEFLATE/STORE). + */ + var zip_ct_init = function () { + var n; // iterates over tree elements + var bits; // bit counter + var length; // length value + var code; // code value + var dist; // distance index + + if (zip_static_dtree[0].dl !== 0) { + return; // ct_init already called + } + + zip_l_desc.dyn_tree = zip_dyn_ltree; + zip_l_desc.static_tree = zip_static_ltree; + zip_l_desc.extra_bits = zip_extra_lbits; + zip_l_desc.extra_base = zip_LITERALS + 1; + zip_l_desc.elems = zip_L_CODES; + zip_l_desc.max_length = zip_MAX_BITS; + zip_l_desc.max_code = 0; + + zip_d_desc.dyn_tree = zip_dyn_dtree; + zip_d_desc.static_tree = zip_static_dtree; + zip_d_desc.extra_bits = zip_extra_dbits; + zip_d_desc.extra_base = 0; + zip_d_desc.elems = zip_D_CODES; + zip_d_desc.max_length = zip_MAX_BITS; + zip_d_desc.max_code = 0; + + zip_bl_desc.dyn_tree = zip_bl_tree; + zip_bl_desc.static_tree = null; + zip_bl_desc.extra_bits = zip_extra_blbits; + zip_bl_desc.extra_base = 0; + zip_bl_desc.elems = zip_BL_CODES; + zip_bl_desc.max_length = zip_MAX_BL_BITS; + zip_bl_desc.max_code = 0; + + // Initialize the mapping length (0..255) -> length code (0..28) + length = 0; + for (code = 0; code < zip_LENGTH_CODES - 1; code++) { + zip_base_length[code] = length; + for (n = 0; n < (1 << zip_extra_lbits[code]); n++) { + zip_length_code[length++] = code; + } + } + // Assert (length == 256, "ct_init: length != 256"); + + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + zip_length_code[length - 1] = code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + zip_base_dist[code] = dist; + for (n = 0; n < (1 << zip_extra_dbits[code]); n++) { + zip_dist_code[dist++] = code; + } + } + // Assert (dist == 256, "ct_init: dist != 256"); + dist >>= 7; // from now on, all distances are divided by 128 + n = code; + for (code = n; code < zip_D_CODES; code++) { + zip_base_dist[code] = dist << 7; + for (n = 0; n < (1 << (zip_extra_dbits[code] - 7)); n++) { + zip_dist_code[256 + dist++] = code; + } + } + // Assert (dist == 256, "ct_init: 256+dist != 512"); + + // Construct the codes of the static literal tree + for (bits = 0; bits <= zip_MAX_BITS; bits++) { + zip_bl_count[bits] = 0; + } + n = 0; + while (n <= 143) { + zip_static_ltree[n++].dl = 8; + zip_bl_count[8]++; + } + while (n <= 255) { + zip_static_ltree[n++].dl = 9; + zip_bl_count[9]++; + } + while (n <= 279) { + zip_static_ltree[n++].dl = 7; + zip_bl_count[7]++; + } + while (n <= 287) { + zip_static_ltree[n++].dl = 8; + zip_bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + zip_gen_codes(zip_static_ltree, zip_L_CODES + 1); + + /* The static distance tree is trivial: */ + for (n = 0; n < zip_D_CODES; n++) { + zip_static_dtree[n].dl = 5; + zip_static_dtree[n].fc = zip_bi_reverse(n, 5); + } + + // Initialize the first block of the first file: + zip_init_block(); + }; + + + var zip_init_deflate = function () { + if (zip_eofile) { + return; + } + zip_bi_buf = 0; + zip_bi_valid = 0; + zip_ct_init(); + zip_lm_init(); + + zip_qhead = null; + zip_outcnt = 0; + zip_outoff = 0; + + if (zip_compr_level <= 3) { + zip_prev_length = zip_MIN_MATCH - 1; + zip_match_length = 0; + } else { + zip_match_length = zip_MIN_MATCH - 1; + zip_match_available = 0; + } + + zip_complete = false; + }; + + var zip_qcopy = function (buff, off, buff_size) { + var n, i, j; + + n = 0; + while (zip_qhead !== null && n < buff_size) { + i = buff_size - n; + if (i > zip_qhead.len) { + i = zip_qhead.len; + } + // System.arraycopy(qhead.ptr, qhead.off, buff, off + n, i); + for (j = 0; j < i; j++) { + buff[off + n + j] = zip_qhead.ptr[zip_qhead.off + j]; + } + + zip_qhead.off += i; + zip_qhead.len -= i; + n += i; + if (zip_qhead.len === 0) { + var p; + p = zip_qhead; + zip_qhead = zip_qhead.next; + zip_reuse_queue(p); + } + } + + if (n === buff_size) { + return n; + } + + if (zip_outoff < zip_outcnt) { + i = buff_size - n; + if (i > zip_outcnt - zip_outoff) { + i = zip_outcnt - zip_outoff; + } + // System.arraycopy(outbuf, outoff, buff, off + n, i); + for (j = 0; j < i; j++) { + buff[off + n + j] = zip_outbuf[zip_outoff + j]; + } + zip_outoff += i; + n += i; + if (zip_outcnt === zip_outoff) { + zip_outcnt = zip_outoff = 0; + } + } + return n; + }; + + /* ========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ + var zip_deflate_internal = function (buff, off, buff_size) { + var n; + + if (!zip_initflag) { + zip_init_deflate(); + zip_initflag = true; + if (zip_lookahead === 0) { // empty + zip_complete = true; + return 0; + } + } + + if ((n = zip_qcopy(buff, off, buff_size)) === buff_size) { + return buff_size; + } + + if (zip_complete) { + return n; + } + + if (zip_compr_level <= 3) { // optimized for speed + zip_deflate_fast(); + } else { + zip_deflate_better(); + } + if (zip_lookahead === 0) { + if (zip_match_available !== 0) { + zip_ct_tally(0, zip_window[zip_strstart - 1] & 0xff); + } + zip_flush_block(1); + zip_complete = true; + } + return n + zip_qcopy(buff, n + off, buff_size - n); + }; + + var zip_deflate = function (str, level) { + var i, j; + + zip_deflate_data = str; + zip_deflate_pos = 0; + if (typeof level === "undefined") { + level = zip_DEFAULT_LEVEL; + } + zip_deflate_start(level); + + var buff = new Array(1024); + var aout = []; + while ((i = zip_deflate_internal(buff, 0, buff.length)) > 0) { + var cbuf = []; + cbuf.length = i; + for (j = 0; j < i; j++) { + cbuf[j] = String.fromCharCode(buff[j]); + } + aout[aout.length] = cbuf.join(""); + } + zip_deflate_data = null; // G.C. + return aout.join(""); + }; + + this.deflate = zip_deflate; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/RawInflate.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/RawInflate.js new file mode 100644 index 0000000000..0005ea56ea --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/RawInflate.js @@ -0,0 +1,790 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core*/ +/* + * $Id: rawinflate.js,v 0.2 2009/03/01 18:32:24 dankogai Exp $ + * + * original: + * http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt + */ + +/** + * @constructor + */ +core.RawInflate = function RawInflate() { + +/* Copyright (C) 1999 Masanao Izumo + * Version: 1.0.0.1 + * LastModified: Dec 25 1999 + */ + +/* Interface: + * data = zip_inflate(src); + */ + +/* constant parameters */ +var zip_WSIZE = 32768; // Sliding Window size +var zip_STORED_BLOCK = 0; +var zip_STATIC_TREES = 1; +var zip_DYN_TREES = 2; + +/* for inflate */ +var zip_lbits = 9; // bits in base literal/length lookup table +var zip_dbits = 6; // bits in base distance lookup table +var zip_INBUFSIZ = 32768; // Input buffer size +var zip_INBUF_EXTRA = 64; // Extra buffer + +/* variables (inflate) */ +var zip_slide; +var zip_wp; // current position in slide +var zip_fixed_tl = null; // inflate static +var zip_fixed_td; // inflate static +var zip_fixed_bl, fixed_bd; // inflate static +var zip_bit_buf; // bit buffer +var zip_bit_len; // bits in bit buffer +var zip_method; +var zip_eof; +var zip_copy_leng; +var zip_copy_dist; +var zip_tl, zip_td; // literal/length and distance decoder tables +var zip_bl, zip_bd; // number of bits decoded by tl and td + +var zip_inflate_data; +var zip_inflate_pos; + + +/* constant tables (inflate) */ +var zip_MASK_BITS = new Array( + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff); +// Tables for deflate from PKZIP's appnote.txt. +var zip_cplens = new Array( // Copy lengths for literal codes 257..285 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0); +/* note: see note #13 above about the 258 in this list. */ +var zip_cplext = new Array( // Extra bits for literal codes 257..285 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99); // 99==invalid +var zip_cpdist = new Array( // Copy offsets for distance codes 0..29 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577); +var zip_cpdext = new Array( // Extra bits for distance codes + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13); +var zip_border = new Array( // Order of the bit length code lengths + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15); +/* objects (inflate) */ + +/** + * @constructor + */ +var zip_HuftList = function() { + this.next = null; + this.list = null; +} + +/** + * @constructor + */ +var zip_HuftNode = function() { + this.e = 0; // number of extra bits or operation + this.b = 0; // number of bits in this code or subcode + + // union + this.n = 0; // literal, length base, or distance base + this.t = null; // (zip_HuftNode) pointer to next level of table +} + +/** + * @constructor + */ +var zip_HuftBuild = function(b, // code lengths in bits (all assumed <= BMAX) + n, // number of codes (assumed <= N_MAX) + s, // number of simple-valued codes (0..s-1) + d, // list of base values for non-simple codes + e, // list of extra bits for non-simple codes + mm // maximum lookup bits + ) { + this.BMAX = 16; // maximum bit length of any code + this.N_MAX = 288; // maximum number of codes in any set + this.status = 0; // 0: success, 1: incomplete table, 2: bad input + this.root = null; // (zip_HuftList) starting table + this.m = 0; // maximum lookup bits, returns actual + +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. + The code with value 256 is special, and the tables are constructed + so that no bits beyond that code are fetched when that code is + decoded. */ + { + var a; // counter for codes of length k + var c = new Array(this.BMAX+1); // bit length count table + var el; // length of EOB code (value 256) + var f; // i repeats in table every f entries + var g; // maximum code length + var h; // table level + var i; // counter, current code + var j; // counter + var k; // number of bits in current code + var lx = new Array(this.BMAX+1); // stack of bits per table + var p; // pointer into c[], b[], or v[] + var pidx; // index of p + var q; // (zip_HuftNode) points to current table + var r = new zip_HuftNode(); // table entry for structure assignment + var u = new Array(this.BMAX); // zip_HuftNode[BMAX][] table stack + var v = new Array(this.N_MAX); // values in order of bit length + var w; + var x = new Array(this.BMAX+1);// bit offsets, then code stack + var xp; // pointer into x or c + var y; // number of dummy codes added + var z; // number of entries in current table + var o; + var tail; // (zip_HuftList) + + tail = this.root = null; + for(i = 0; i < c.length; i++) + c[i] = 0; + for(i = 0; i < lx.length; i++) + lx[i] = 0; + for(i = 0; i < u.length; i++) + u[i] = null; + for(i = 0; i < v.length; i++) + v[i] = 0; + for(i = 0; i < x.length; i++) + x[i] = 0; + + // Generate counts for each bit length + el = n > 256 ? b[256] : this.BMAX; // set length of EOB code, if any + p = b; pidx = 0; + i = n; + do { + c[p[pidx]]++; // assume all entries <= BMAX + pidx++; + } while(--i > 0); + if(c[0] == n) { // null input--all zero length codes + this.root = null; + this.m = 0; + this.status = 0; + return; + } + + // Find minimum and maximum length, bound *m by those + for(j = 1; j <= this.BMAX; j++) + if(c[j] != 0) + break; + k = j; // minimum code length + if(mm < j) + mm = j; + for(i = this.BMAX; i != 0; i--) + if(c[i] != 0) + break; + g = i; // maximum code length + if(mm > i) + mm = i; + + // Adjust last length count to fill out codes, if needed + for(y = 1 << j; j < i; j++, y <<= 1) + if((y -= c[j]) < 0) { + this.status = 2; // bad input: more codes than bits + this.m = mm; + return; + } + if((y -= c[i]) < 0) { + this.status = 2; + this.m = mm; + return; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = c; + pidx = 1; + xp = 2; + while(--i > 0) // note that i == g from above + x[xp++] = (j += p[pidx++]); + + // Make a table of values in order of bit lengths + p = b; pidx = 0; + i = 0; + do { + if((j = p[pidx++]) != 0) + v[x[j]++] = i; + } while(++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = v; pidx = 0; // grab values in bit order + h = -1; // no tables yet--level -1 + w = lx[0] = 0; // no bits decoded yet + q = null; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for(; k <= g; k++) { + a = c[k]; + while(a-- > 0) { + // here i is the Huffman code of length k bits for value p[pidx] + // make tables up to required level + while(k > w + lx[1 + h]) { + w += lx[1 + h]; // add bits already decoded + h++; + + // compute minimum size table less than or equal to *m bits + z = (z = g - w) > mm ? mm : z; // upper limit + if((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table + // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = k; + while(++j < z) { // try smaller tables up to z bits + if((f <<= 1) <= c[++xp]) + break; // enough codes to use up j bits + f -= c[xp]; // else deduct codes from patterns + } + } + if(w + j > el && w < el) + j = el - w; // make EOB code end at table + z = 1 << j; // table entries for j-bit table + lx[1 + h] = j; // set table size in stack + + // allocate and link in new table + q = new Array(z); + for(o = 0; o < z; o++) { + q[o] = new zip_HuftNode(); + } + + if(tail == null) + tail = this.root = new zip_HuftList(); + else + tail = tail.next = new zip_HuftList(); + tail.next = null; + tail.list = q; + u[h] = q; // table starts after link + + /* connect to last table, if there is one */ + if(h > 0) { + x[h] = i; // save pattern for backing up + r.b = lx[h]; // bits to dump before this table + r.e = 16 + j; // bits in this table + r.t = q; // pointer to this table + j = (i & ((1 << w) - 1)) >> (w - lx[h]); + u[h-1][j].e = r.e; + u[h-1][j].b = r.b; + u[h-1][j].n = r.n; + u[h-1][j].t = r.t; + } + } + + // set up table entry in r + r.b = k - w; + if(pidx >= n) + r.e = 99; // out of values--invalid code + else if(p[pidx] < s) { + r.e = (p[pidx] < 256 ? 16 : 15); // 256 is end-of-block code + r.n = p[pidx++]; // simple code is just the value + } else { + r.e = e[p[pidx] - s]; // non-simple--look up in lists + r.n = d[p[pidx++] - s]; + } + + // fill code-like entries with r // + f = 1 << (k - w); + for(j = i >> w; j < z; j += f) { + q[j].e = r.e; + q[j].b = r.b; + q[j].n = r.n; + q[j].t = r.t; + } + + // backwards increment the k-bit code i + for(j = 1 << (k - 1); (i & j) != 0; j >>= 1) + i ^= j; + i ^= j; + + // backup over finished tables + while((i & ((1 << w) - 1)) != x[h]) { + w -= lx[h]; // don't need to update q + h--; + } + } + } + + /* return actual size of base table */ + this.m = lx[1]; + + /* Return true (1) if we were given an incomplete table */ + this.status = ((y != 0 && g != 1) ? 1 : 0); + } /* end of constructor */ +} + + +/* routines (inflate) */ + +var zip_GET_BYTE = function() { + if(zip_inflate_data.length == zip_inflate_pos) + return -1; + return zip_inflate_data[zip_inflate_pos++]; +} + +var zip_NEEDBITS = function(n) { + while(zip_bit_len < n) { + zip_bit_buf |= zip_GET_BYTE() << zip_bit_len; + zip_bit_len += 8; + } +} + +var zip_GETBITS = function(n) { + return zip_bit_buf & zip_MASK_BITS[n]; +} + +var zip_DUMPBITS = function(n) { + zip_bit_buf >>= n; + zip_bit_len -= n; +} + +var zip_inflate_codes = function(buff, off, size) { + /* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ + var e; // table entry flag/number of extra bits + var t; // (zip_HuftNode) pointer to table entry + var n; + + if(size == 0) + return 0; + + // inflate the coded data + n = 0; + for(;;) { // do until end of block + zip_NEEDBITS(zip_bl); + t = zip_tl.list[zip_GETBITS(zip_bl)]; + e = t.e; + while(e > 16) { + if(e == 99) + return -1; + zip_DUMPBITS(t.b); + e -= 16; + zip_NEEDBITS(e); + t = t.t[zip_GETBITS(e)]; + e = t.e; + } + zip_DUMPBITS(t.b); + + if(e == 16) { // then it's a literal + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = t.n; + if(n == size) + return size; + continue; + } + + // exit if end of block + if(e == 15) + break; + + // it's an EOB or a length + + // get length of block to copy + zip_NEEDBITS(e); + zip_copy_leng = t.n + zip_GETBITS(e); + zip_DUMPBITS(e); + + // decode distance of block to copy + zip_NEEDBITS(zip_bd); + t = zip_td.list[zip_GETBITS(zip_bd)]; + e = t.e; + + while(e > 16) { + if(e == 99) + return -1; + zip_DUMPBITS(t.b); + e -= 16; + zip_NEEDBITS(e); + t = t.t[zip_GETBITS(e)]; + e = t.e; + } + zip_DUMPBITS(t.b); + zip_NEEDBITS(e); + zip_copy_dist = zip_wp - t.n - zip_GETBITS(e); + zip_DUMPBITS(e); + + // do the copy + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_copy_dist &= zip_WSIZE - 1; + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] + = zip_slide[zip_copy_dist++]; + } + + if(n == size) + return size; + } + + zip_method = -1; // done + return n; +} + +var zip_inflate_stored = function(buff, off, size) { + /* "decompress" an inflated type 0 (stored) block. */ + var n; + + // go to byte boundary + n = zip_bit_len & 7; + zip_DUMPBITS(n); + + // get the length and its complement + zip_NEEDBITS(16); + n = zip_GETBITS(16); + zip_DUMPBITS(16); + zip_NEEDBITS(16); + if(n != ((~zip_bit_buf) & 0xffff)) + return -1; // error in compressed data + zip_DUMPBITS(16); + + // read and output the compressed data + zip_copy_leng = n; + + n = 0; + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_wp &= zip_WSIZE - 1; + zip_NEEDBITS(8); + buff[off + n++] = zip_slide[zip_wp++] = + zip_GETBITS(8); + zip_DUMPBITS(8); + } + + if(zip_copy_leng == 0) + zip_method = -1; // done + return n; +} + +var zip_fixed_bd; +var zip_inflate_fixed = function(buff, off, size) { + /* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ + + // if first time, set up tables for fixed blocks + if(zip_fixed_tl == null) { + var i; // temporary variable + var l = new Array(288); // length list for huft_build + var h; // zip_HuftBuild + + // literal table + for(i = 0; i < 144; i++) + l[i] = 8; + for(; i < 256; i++) + l[i] = 9; + for(; i < 280; i++) + l[i] = 7; + for(; i < 288; i++) // make a complete, but wrong code set + l[i] = 8; + zip_fixed_bl = 7; + + h = new zip_HuftBuild(l, 288, 257, zip_cplens, zip_cplext, + zip_fixed_bl); + if(h.status != 0) { + alert("HufBuild error: "+h.status); + return -1; + } + zip_fixed_tl = h.root; + zip_fixed_bl = h.m; + + // distance table + for(i = 0; i < 30; i++) // make an incomplete code set + l[i] = 5; + zip_fixed_bd = 5; + + h = new zip_HuftBuild(l, 30, 0, zip_cpdist, zip_cpdext, zip_fixed_bd); + if(h.status > 1) { + zip_fixed_tl = null; + alert("HufBuild error: "+h.status); + return -1; + } + zip_fixed_td = h.root; + zip_fixed_bd = h.m; + } + + zip_tl = zip_fixed_tl; + zip_td = zip_fixed_td; + zip_bl = zip_fixed_bl; + zip_bd = zip_fixed_bd; + return zip_inflate_codes(buff, off, size); +} + +var zip_inflate_dynamic = function(buff, off, size) { + // decompress an inflated type 2 (dynamic Huffman codes) block. + var i; // temporary variables + var j; + var l; // last length + var n; // number of lengths to get + var t; // (zip_HuftNode) literal/length code table + var nb; // number of bit length codes + var nl; // number of literal/length codes + var nd; // number of distance codes + var ll = new Array(286+30); // literal/length and distance code lengths + var h; // (zip_HuftBuild) + + for(i = 0; i < ll.length; i++) + ll[i] = 0; + + // read in table lengths + zip_NEEDBITS(5); + nl = 257 + zip_GETBITS(5); // number of literal/length codes + zip_DUMPBITS(5); + zip_NEEDBITS(5); + nd = 1 + zip_GETBITS(5); // number of distance codes + zip_DUMPBITS(5); + zip_NEEDBITS(4); + nb = 4 + zip_GETBITS(4); // number of bit length codes + zip_DUMPBITS(4); + if(nl > 286 || nd > 30) + return -1; // bad lengths + + // read in bit-length-code lengths + for(j = 0; j < nb; j++) + { + zip_NEEDBITS(3); + ll[zip_border[j]] = zip_GETBITS(3); + zip_DUMPBITS(3); + } + for(; j < 19; j++) + ll[zip_border[j]] = 0; + + // build decoding table for trees--single level, 7 bit lookup + zip_bl = 7; + h = new zip_HuftBuild(ll, 19, 19, null, null, zip_bl); + if(h.status != 0) + return -1; // incomplete code set + + zip_tl = h.root; + zip_bl = h.m; + + // read in literal and distance code lengths + n = nl + nd; + i = l = 0; + while(i < n) { + zip_NEEDBITS(zip_bl); + t = zip_tl.list[zip_GETBITS(zip_bl)]; + j = t.b; + zip_DUMPBITS(j); + j = t.n; + if(j < 16) // length of code in bits (0..15) + ll[i++] = l = j; // save last length in l + else if(j == 16) { // repeat last length 3 to 6 times + zip_NEEDBITS(2); + j = 3 + zip_GETBITS(2); + zip_DUMPBITS(2); + if(i + j > n) + return -1; + while(j-- > 0) + ll[i++] = l; + } else if(j == 17) { // 3 to 10 zero length codes + zip_NEEDBITS(3); + j = 3 + zip_GETBITS(3); + zip_DUMPBITS(3); + if(i + j > n) + return -1; + while(j-- > 0) + ll[i++] = 0; + l = 0; + } else { // j == 18: 11 to 138 zero length codes + zip_NEEDBITS(7); + j = 11 + zip_GETBITS(7); + zip_DUMPBITS(7); + if(i + j > n) + return -1; + while(j-- > 0) + ll[i++] = 0; + l = 0; + } + } + + // build the decoding tables for literal/length and distance codes + zip_bl = zip_lbits; + h = new zip_HuftBuild(ll, nl, 257, zip_cplens, zip_cplext, zip_bl); + if(zip_bl == 0) // no literals or lengths + h.status = 1; + if(h.status != 0) { + //if(h.status == 1) + // ;// **incomplete literal tree** + return -1; // incomplete code set + } + zip_tl = h.root; + zip_bl = h.m; + + for(i = 0; i < nd; i++) + ll[i] = ll[i + nl]; + zip_bd = zip_dbits; + h = new zip_HuftBuild(ll, nd, 0, zip_cpdist, zip_cpdext, zip_bd); + zip_td = h.root; + zip_bd = h.m; + + if(zip_bd == 0 && nl > 257) { // lengths but no distances + // **incomplete distance tree** + return -1; + } + + //if(h.status == 1) { +// ;// **incomplete distance tree** + //} + if(h.status != 0) + return -1; + + // decompress until an end-of-block code + return zip_inflate_codes(buff, off, size); +} + +var zip_inflate_start = function() { + var i; + + if(zip_slide == null) + zip_slide = new Array(2 * zip_WSIZE); + zip_wp = 0; + zip_bit_buf = 0; + zip_bit_len = 0; + zip_method = -1; + zip_eof = false; + zip_copy_leng = zip_copy_dist = 0; + zip_tl = null; +} + +var zip_inflate_internal = function(buff, off, size) { + // decompress an inflated entry + var n, i; + + n = 0; + while(n < size) { + if(zip_eof && zip_method == -1) + return n; + + if(zip_copy_leng > 0) { + if(zip_method != zip_STORED_BLOCK) { + // STATIC_TREES or DYN_TREES + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_copy_dist &= zip_WSIZE - 1; + zip_wp &= zip_WSIZE - 1; + buff[off + n++] = zip_slide[zip_wp++] = + zip_slide[zip_copy_dist++]; + } + } else { + while(zip_copy_leng > 0 && n < size) { + zip_copy_leng--; + zip_wp &= zip_WSIZE - 1; + zip_NEEDBITS(8); + buff[off + n++] = zip_slide[zip_wp++] = zip_GETBITS(8); + zip_DUMPBITS(8); + } + if(zip_copy_leng == 0) + zip_method = -1; // done + } + if(n == size) + return n; + } + + if(zip_method == -1) { + if(zip_eof) + break; + + // read in last block bit + zip_NEEDBITS(1); + if(zip_GETBITS(1) != 0) + zip_eof = true; + zip_DUMPBITS(1); + + // read in block type + zip_NEEDBITS(2); + zip_method = zip_GETBITS(2); + zip_DUMPBITS(2); + zip_tl = null; + zip_copy_leng = 0; + } + + switch(zip_method) { + case 0: // zip_STORED_BLOCK + i = zip_inflate_stored(buff, off + n, size - n); + break; + + case 1: // zip_STATIC_TREES + if(zip_tl != null) + i = zip_inflate_codes(buff, off + n, size - n); + else + i = zip_inflate_fixed(buff, off + n, size - n); + break; + + case 2: // zip_DYN_TREES + if(zip_tl != null) + i = zip_inflate_codes(buff, off + n, size - n); + else + i = zip_inflate_dynamic(buff, off + n, size - n); + break; + + default: // error + i = -1; + break; + } + + if(i == -1) { + if(zip_eof) + return 0; + return -1; + } + n += i; + } + return n; +} + +var zip_inflate = function(data, size) { + var i, j; + + zip_inflate_start(); + zip_inflate_data = data; + zip_inflate_pos = 0; + + var buff = new runtime.ByteArray(size); + zip_inflate_internal(buff, 0, size); + zip_inflate_data = null; // G.C. + return buff; +} + +this.inflate = zip_inflate; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/UnitTester.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/UnitTester.js new file mode 100644 index 0000000000..4dbe1fa2c0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/UnitTester.js @@ -0,0 +1,255 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, Runtime: true, core: true*/ +/*jslint evil: true*/ +/** + * @interface + */ +core.UnitTest = function UnitTest() {"use strict";}; +/** + * @return {undefined} + */ +core.UnitTest.prototype.setUp = function () {"use strict";}; +/** + * @return {undefined} + */ +core.UnitTest.prototype.tearDown = function () {"use strict";}; +/** + * @return {!string} + */ +core.UnitTest.prototype.description = function () {"use strict";}; +/** + * @return {Array.} + */ +core.UnitTest.prototype.tests = function () {"use strict";}; +/** + * @return {Array.} + */ +core.UnitTest.prototype.asyncTests = function () {"use strict";}; + +/** + * @constructor + */ +core.UnitTestRunner = function UnitTestRunner() { + "use strict"; + var failedTests = 0; + function debug(msg) { + runtime.log(msg); + } + function testFailed(msg) { + failedTests += 1; + runtime.log("fail", msg); + } + function testPassed(msg) { + runtime.log("pass", msg); + } + function areArraysEqual(a, b) { + var i; + try { + if (a.length !== b.length) { + return false; + } + for (i = 0; i < a.length; i += 1) { + if (a[i] !== b[i]) { + return false; + } + } + } catch (ex) { + return false; + } + return true; + } + function isResultCorrect(actual, expected) { + if (expected === 0) { + return actual === expected && (1 / actual) === (1 / expected); + } + if (actual === expected) { + return true; + } + if (typeof expected === "number" && isNaN(expected)) { + return typeof actual === "number" && isNaN(actual); + } + if (Object.prototype.toString.call(expected) === + Object.prototype.toString.call([])) { + return areArraysEqual(actual, expected); + } + return false; + } + function stringify(v) { + if (v === 0 && 1 / v < 0) { + return "-0"; + } + return String(v); + } + /** + * @param {!Object} t + * @param {!string} a + * @param {!string} b + * @return {undefined} + */ + function shouldBe(t, a, b) { + if (typeof a !== "string" || typeof b !== "string") { + debug("WARN: shouldBe() expects string arguments"); + } + var exception, av, bv; + try { + av = eval(a); + } catch (e) { + exception = e; + } + bv = eval(b); + + if (exception) { + testFailed(a + " should be " + bv + ". Threw exception " + + exception); + } else if (isResultCorrect(av, bv)) { + testPassed(a + " is " + b); + } else if (typeof av === typeof bv) { + testFailed(a + " should be " + bv + ". Was " + stringify(av) + "."); + } else { + testFailed(a + " should be " + bv + " (of type " + typeof bv + + "). Was " + av + " (of type " + typeof av + ")."); + } + } + /** + * @param {!Object} t context in which values to be tested are placed + * @param {!string} a the value to be checked + * @return {undefined} + */ + function shouldBeNonNull(t, a) { + var exception, av; + try { + av = eval(a); + } catch (e) { + exception = e; + } + + if (exception) { + testFailed(a + " should be non-null. Threw exception " + exception); + } else if (av !== null) { + testPassed(a + " is non-null."); + } else { + testFailed(a + " should be non-null. Was " + av); + } + } + /** + * @param {!Object} t context in which values to be tested are placed + * @param {!string} a the value to be checked + * @return {undefined} + */ + function shouldBeNull(t, a) { + shouldBe(t, a, "null"); + } + this.shouldBeNull = shouldBeNull; + this.shouldBeNonNull = shouldBeNonNull; + this.shouldBe = shouldBe; + this.countFailedTests = function () { + return failedTests; + }; +}; + +/** + * @constructor + */ +core.UnitTester = function UnitTester() { + "use strict"; + var failedTests = 0, + results = {}; + /** + * @param {Function} TestClass the constructor for the test class + * @param {!function():undefined} callback + * @return {undefined} + */ + this.runTests = function (TestClass, callback) { + var testName = Runtime.getFunctionName(TestClass), + tname, + runner = new core.UnitTestRunner(), + test = new TestClass(runner), + testResults = {}, + i, + t, + tests, + lastFailCount; + + // check that this test has not been run or started yet + if (testName.hasOwnProperty(results)) { + runtime.log("Test " + testName + " has already run."); + return; + } + + runtime.log("Running " + testName + ": " + test.description()); + tests = test.tests(); + for (i = 0; i < tests.length; i += 1) { + t = tests[i]; + tname = Runtime.getFunctionName(t); + runtime.log("Running " + tname); + lastFailCount = runner.countFailedTests(); + test.setUp(); + t(); + test.tearDown(); + testResults[tname] = lastFailCount === runner.countFailedTests(); + } + function runAsyncTests(todo) { + if (todo.length === 0) { + results[testName] = testResults; + failedTests += runner.countFailedTests(); + callback(); + return; + } + t = todo[0]; + var tname = Runtime.getFunctionName(t); + runtime.log("Running " + tname); + lastFailCount = runner.countFailedTests(); + test.setUp(); + t(function () { + test.tearDown(); + testResults[tname] = lastFailCount === + runner.countFailedTests(); + runAsyncTests(todo.slice(1)); + }); + } + runAsyncTests(test.asyncTests()); + }; + /** + * @return {!number} + **/ + this.countFailedTests = function () { + return failedTests; + }; + /** + * @return {!Object} + **/ + this.results = function () { + return results; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/Zip.js b/apps/files_odfviewer/src/webodf/webodf/lib/core/Zip.js new file mode 100644 index 0000000000..66f508ee39 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/Zip.js @@ -0,0 +1,600 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime, core, DOMParser*/ +/*jslint bitwise: true*/ +/* +* @preserve +* WebODF +* Copyright (c) 2010 Jos van den Oever +* Licensed under the ... License: +* +* Project home: http://www.webodf.org/ +*/ + +runtime.loadClass("core.RawInflate"); +runtime.loadClass("core.ByteArray"); +runtime.loadClass("core.ByteArrayWriter"); +runtime.loadClass("core.Base64"); + +/** + * @constructor + * @param {!string} url path to zip file, should be readable by the runtime + * @param {?function(?string, !core.Zip):undefined} entriesReadCallback callback + * indicating the zip + * has loaded this list of entries, the arguments are a string that + * indicates error if present and the created object + */ +core.Zip = function Zip(url, entriesReadCallback) { + "use strict"; + var /**@type{Array.}*/ entries, + /**@type{number}*/ filesize, + /**@type{number}*/ nEntries, + /**@type{Function}*/ inflate = new core.RawInflate().inflate, + /**@type{!core.Zip}*/ zip = this, + base64 = new core.Base64(); + + /** + * @param {!Runtime.ByteArray} data + * @return {!number} + */ + function crc32(data) { + // Calculate the crc32 polynomial of a string + // + // version: 1009.2513 + // discuss at: http:\/\/phpjs.org\/functions\/crc32 + // + original by: Webtoolkit.info (http:\/\/www.webtoolkit.info\/) + // + improved by: T0bsn + // - depends on: utf8_encode + // * example 1: crc32('Kevin van Zonneveld'); + // * returns 1: 1249991249 + var /**@const@type{!Array.}*/table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D], + /**@type{!number}*/ crc = 0, + /**@type{!number}*/ i, + /**@const@type{!number}*/ iTop = data.length, + /**@type{!number}*/ x = 0, + /**@type{!number}*/ y = 0; + crc = crc ^ (-1); + for (i = 0; i < iTop; i += 1) { + y = (crc ^ data[i]) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + return crc ^ (-1); + } + + /** + * @param {!number} dostime + * @return {!Date} + */ + function dosTime2Date(dostime) { + var /**@const@type{!number}*/ year = ((dostime >> 25) & 0x7f) + 1980, + /**@const@type{!number}*/ month = ((dostime >> 21) & 0x0f) - 1, + /**@const@type{!number}*/ mday = (dostime >> 16) & 0x1f, + /**@const@type{!number}*/ hour = (dostime >> 11) & 0x0f, + /**@const@type{!number}*/ min = (dostime >> 5) & 0x3f, + /**@const@type{!number}*/ sec = (dostime & 0x1f) << 1, + /**@const@type{!Date}*/ d + = new Date(year, month, mday, hour, min, sec); + return d; + } + /** + * @param {!Date} date + * @return {!number} + */ + function date2DosTime(date) { + var /**@const@type{!number}*/ y = date.getFullYear(); + return y < 1980 ? 0 : + ((y - 1980) << 25) | ((date.getMonth() + 1) << 21) | + (date.getDate() << 16) | (date.getHours() << 11) | + (date.getMinutes() << 5) | (date.getSeconds() >> 1); + } + /** + * Create a new ZipEntry. + * If the stream is not provided, the object should be initialized + * with ZipEntry.set() + * @constructor + * @param {!string} url + * @param {!core.ByteArray=} stream + */ + function ZipEntry(url, stream) { + var /**@const@type{!number}*/ sig, + /**@const@type{!number}*/ namelen, + /**@const@type{!number}*/ extralen, + /**@const@type{!number}*/ commentlen, + /**@const@type{!number}*/ compressionMethod, + /**@const@type{!number}*/ compressedSize, + /**@const@type{!number}*/ uncompressedSize, + /**@const@type{!number}*/ offset, + /**@const@type{!number}*/ crc, + /**@const@type{!ZipEntry}*/ entry = this; + + /** + * @param {!Runtime.ByteArray} data + * @param {!function(?string, ?Runtime.ByteArray)} callback + * @return {undefined} + */ + function handleEntryData(data, callback) { + var /**@const@type{!core.ByteArray}*/ stream + = new core.ByteArray(data), + /**@const@type{!number}*/ sig = stream.readUInt32LE(), + /**@const@type{!number}*/ filenamelen, + /**@const@type{!number}*/ extralen; + if (sig !== 0x04034b50) { + callback('File entry signature is wrong.' + sig.toString() + + ' ' + data.length.toString(), null); + return; + } + stream.pos += 22; + filenamelen = stream.readUInt16LE(); + extralen = stream.readUInt16LE(); + stream.pos += filenamelen + extralen; + if (compressionMethod) { + data = data.slice(stream.pos, stream.pos + compressedSize); + if (compressedSize !== data.length) { + callback("The amount of compressed bytes read was " + + data.length.toString() + " instead of " + + compressedSize.toString() + " for " + entry.filename + + " in " + url + ".", null); + return; + } + data = inflate(data, uncompressedSize); + } else { + data = data.slice(stream.pos, stream.pos + uncompressedSize); + } + if (uncompressedSize !== data.length) { + callback("The amount of bytes read was " + + data.length.toString() + + " instead of " + uncompressedSize.toString() + " for " + + entry.filename + " in " + url + ".", null); + return; + } +/* + * This check is disabled for performance reasons + if (crc !== crc32(data)) { + runtime.log("Warning: CRC32 for " + entry.filename + + " is wrong."); + } +*/ + entry.data = data; + callback(null, data); + } + /** + * @param {!function(?string, ?Runtime.ByteArray)} callback + * @return {undefined} + */ + function load(callback) { + // if data has already been downloaded, use that + if (entry.data !== undefined) { + callback(null, entry.data); + return; + } + // the 256 at the end is security for when local extra field is + // larger + var /**@type{!number}*/ size + = compressedSize + 34 + namelen + extralen + 256; + if (size + offset > filesize) { + size = filesize - offset; + } + runtime.read(url, offset, size, function (err, data) { + if (err) { + callback(err, data); + } else { + handleEntryData(data, callback); + } + }); + } + this.load = load; + /** + * @param {!string} filename + * @param {!Runtime.ByteArray} data + * @param {!boolean} compressed + * @param {!Date} date + * @return {undefined} + */ + function set(filename, data, compressed, date) { + entry.filename = filename; + entry.data = data; + entry.compressed = compressed; + entry.date = date; + } + this.set = set; + /** + * @type {?string} + */ + this.error = null; + + if (!stream) { + return; + } + sig = stream.readUInt32LE(); + + if (sig !== 0x02014b50) { + this.error = + "Central directory entry has wrong signature at position " + + (stream.pos - 4).toString() + ' for file "' + url + '": ' + + stream.data.length.toString(); + return; + } + // stream should be positioned at the start of the CDS entry for the + // file + stream.pos += 6; + compressionMethod = stream.readUInt16LE(); + this.date = dosTime2Date(stream.readUInt32LE()); + crc = stream.readUInt32LE(); + compressedSize = stream.readUInt32LE(); + uncompressedSize = stream.readUInt32LE(); + namelen = stream.readUInt16LE(); + extralen = stream.readUInt16LE(); + commentlen = stream.readUInt16LE(); + stream.pos += 8; + offset = stream.readUInt32LE(); + this.filename = runtime.byteArrayToString( + stream.data.slice(stream.pos, stream.pos + namelen), "utf8"); + stream.pos += namelen + extralen + commentlen; + } + /** + * @param {!Runtime.ByteArray} data + * @param {!function(?string, !core.Zip)} callback + * @return {undefined} + */ + function handleCentralDirectory(data, callback) { + // parse the central directory + var stream = new core.ByteArray(data), i, e; + entries = []; + for (i = 0; i < nEntries; i += 1) { + e = new ZipEntry(url, stream); + if (e.error) { + callback(e.error, zip); + return; + } + entries[entries.length] = e; + } + // report that entries are listed and no error occured + callback(null, zip); + } + /** + * @param {!Runtime.ByteArray} data + * @param {!function(?string, !core.Zip)} callback + * @return {undefined} + */ + function handleCentralDirectoryEnd(data, callback) { + if (data.length !== 22) { + callback("Central directory length should be 22.", zip); + return; + } + var stream = new core.ByteArray(data), sig, disk, cddisk, diskNEntries, + cdsSize, cdsOffset; + sig = stream.readUInt32LE(); + if (sig !== 0x06054b50) { + callback('Central directory signature is wrong: ' + sig.toString(), + zip); + return; + } + disk = stream.readUInt16LE(); + if (disk !== 0) { + callback('Zip files with non-zero disk numbers are not supported.', + zip); + return; + } + cddisk = stream.readUInt16LE(); + if (cddisk !== 0) { + callback('Zip files with non-zero disk numbers are not supported.', + zip); + return; + } + diskNEntries = stream.readUInt16LE(); + nEntries = stream.readUInt16LE(); + if (diskNEntries !== nEntries) { + callback('Number of entries is inconsistent.', zip); + return; + } + cdsSize = stream.readUInt32LE(); + cdsOffset = stream.readUInt16LE(); + cdsOffset = filesize - 22 - cdsSize; + + // for some reason cdsOffset is not always equal to offset calculated + // from the central directory size. The latter is reliable. + runtime.read(url, cdsOffset, filesize - cdsOffset, + function (err, data) { + handleCentralDirectory(data, callback); + }); + } + /** + * @param {!string} filename + * @param {!function(?string, ?Runtime.ByteArray)} callback receiving err and data + * @return {undefined} + */ + function load(filename, callback) { + var entry = null, + end = filesize, + e, + i; + for (i = 0; i < entries.length; i += 1) { + e = entries[i]; + if (e.filename === filename) { + entry = e; + break; + } + } + if (entry) { + if (entry.data) { + callback(null, entry.data); + } else { + entry.load(callback); + } + } else { + callback(filename + " not found.", null); + } + } + /** + * @param {!string} filename + * @param {!function(?string, ?string)} callback receiving err and data + * @return {undefined} + */ + function loadAsString(filename, callback) { + // the javascript implementation simply reads the file and converts to + // string + load(filename, function (err, data) { + if (err) { + return callback(err, null); + } + data = runtime.byteArrayToString(data, "utf8"); + callback(null, data); + }); + } + /** + * @param {!string} filename + * @param {!Object} handler + * @return {undefined} + */ + function loadContentXmlAsFragments(filename, handler) { + // the javascript implementation simply reads the file + loadAsString(filename, function (err, data) { + if (err) { + return handler.rootElementReady(err); + } + handler.rootElementReady(null, data, true); + }); + } + function loadAsDataURL(filename, mimetype, callback) { + load(filename, function (err, data) { + if (err) { + return callback(err, null); + } + var /**@const@type{!Runtime.ByteArray}*/p = data, + chunksize = 45000, // must be multiple of 3 and less than 50000 + i = 0, + url; + if (!mimetype) { + if (p[1] === 0x50 && p[2] === 0x4E && p[3] === 0x47) { + mimetype = "image/png"; + } else if (p[0] === 0xFF && p[1] === 0xD8 && p[2] === 0xFF) { + mimetype = "image/jpeg"; + } else if (p[0] === 0x47 && p[1] === 0x49 && p[2] === 0x46) { + mimetype = "image/gif"; + } else { + mimetype = ""; + } + } + url = 'data:' + mimetype + ';base64,'; + // to avoid exceptions, base64 encoding is done in chunks + // it would make sense to move this to base64.toBase64 + while (i < data.length) { + url += base64.convertUTF8ArrayToBase64( + p.slice(i, Math.min(i + chunksize, p.length)) + ); + i += chunksize; + } + callback(null, url); + }); + } + function loadAsDOM(filename, callback) { + loadAsString(filename, function (err, xmldata) { + if (err) { + callback(err, null); + return; + } + var parser = new DOMParser(); + xmldata = parser.parseFromString(xmldata, "text/xml"); + callback(null, xmldata); + }); + } + /** + * Add or replace an entry to the zip file. + * This data is not stored to disk yet, and therefore, no callback is + * necessary. + * @param {!string} filename + * @param {!Runtime.ByteArray} data + * @param {!boolean} compressed + * @param {!Date} date + * @return {undefined} + */ + function save(filename, data, compressed, date) { + var i, + entry; + for (i = 0; i < entries.length; i += 1) { + entry = entries[i]; + if (entry.filename === filename) { + entry.set(filename, data, compressed, date); + return; + } + } + entry = new ZipEntry(url); + entry.set(filename, data, compressed, date); + entries.push(entry); + } + /** + * @param {!ZipEntry} entry + * @return {!core.ByteArrayWriter} + */ + function writeEntry(entry) { + // each entry is currently stored uncompressed + var data = new core.ByteArrayWriter("utf8"), + length = 0; + data.appendArray([0x50, 0x4B, 0x03, 0x04, 0x14, 0, 0, 0, 0, 0]); + if (entry.data) { + length = entry.data.length; + } + data.appendUInt32LE(date2DosTime(entry.date)); + data.appendUInt32LE(crc32(entry.data)); + data.appendUInt32LE(length); // compressedSize + data.appendUInt32LE(length); // uncompressedSize + data.appendUInt16LE(entry.filename.length); // namelen + data.appendUInt16LE(0); // extralen + data.appendString(entry.filename); + if (entry.data) { + data.appendByteArray(entry.data); + } + return data; + } + /** + * @param {!ZipEntry} entry + * @param {!number} offset + * @return {!core.ByteArrayWriter} + */ + function writeCODEntry(entry, offset) { + // each entry is currently stored uncompressed + var data = new core.ByteArrayWriter("utf8"), + length = 0; + data.appendArray([0x50, 0x4B, 0x01, 0x02, 0x14, 0x00, 0x14, 0x00, + 0, 0, 0, 0]); + if (entry.data) { + length = entry.data.length; + } + data.appendUInt32LE(date2DosTime(entry.date)); + data.appendUInt32LE(crc32(entry.data)); + data.appendUInt32LE(length); // compressedSize + data.appendUInt32LE(length); // uncompressedSize + data.appendUInt16LE(entry.filename.length); // namelen + // extralen, commalen, diskno, file attributes + data.appendArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + data.appendUInt32LE(offset); + data.appendString(entry.filename); + return data; + } + /** + * @param {!number} position + * @param {!function(?string):undefined} callback + * @return {undefined} + */ + function loadAllEntries(position, callback) { + if (position === entries.length) { + callback(null); + return; + } + var entry = entries[position]; + if (entry.data !== undefined) { + loadAllEntries(position + 1, callback); + return; + } + entry.load(function (err) { + if (err) { + callback(err); + return; + } + loadAllEntries(position + 1, callback); + }); + } + /** + * Write the zipfile to the given path. + * @param {!function(?string):undefined} callback receiving possible err + * @return {undefined} + */ + function write(callback) { + // make sure all data is in memory, for each entry that has data + // undefined, try to load the entry + loadAllEntries(0, function (err) { + if (err) { + callback(err); + return; + } + var data = new core.ByteArrayWriter("utf8"), + i, e, codoffset, codsize, + offsets = [0]; + // write entries + for (i = 0; i < entries.length; i += 1) { + data.appendByteArrayWriter(writeEntry(entries[i])); + offsets.push(data.getLength()); + } + // write central directory + codoffset = data.getLength(); + for (i = 0; i < entries.length; i += 1) { + e = entries[i]; + data.appendByteArrayWriter(writeCODEntry(e, offsets[i])); + } + codsize = data.getLength() - codoffset; + data.appendArray([0x50, 0x4B, 0x05, 0x06, 0, 0, 0, 0]); + data.appendUInt16LE(entries.length); + data.appendUInt16LE(entries.length); + data.appendUInt32LE(codsize); + data.appendUInt32LE(codoffset); + data.appendArray([0, 0]); + runtime.writeFile(url, data.getByteArray(), callback); + }); + } + + this.load = load; + this.save = save; + this.write = write; + // a special function that makes faster odf loading possible + this.loadContentXmlAsFragments = loadContentXmlAsFragments; + this.loadAsString = loadAsString; + this.loadAsDOM = loadAsDOM; + this.loadAsDataURL = loadAsDataURL; + this.getEntries = function () { + return entries.slice(); + }; + + // determine the file size + filesize = -1; + // if no callback is defined, this is a new file + if (entriesReadCallback === null) { + entries = []; + return; + } + runtime.getFileSize(url, function (size) { + filesize = size; + if (filesize < 0) { + entriesReadCallback("File '" + url + "' cannot be read.", zip); + } else { + runtime.read(url, filesize - 22, 22, function (err, data) { + // todo: refactor entire zip class + if (err || entriesReadCallback === null) { + entriesReadCallback(err, zip); + } else { + handleCentralDirectoryEnd(data, entriesReadCallback); + } + }); + } + }); +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/core/dummyxmlmodel.js_ b/apps/files_odfviewer/src/webodf/webodf/lib/core/dummyxmlmodel.js_ new file mode 100644 index 0000000000..c14ec84411 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/core/dummyxmlmodel.js_ @@ -0,0 +1,21 @@ +/*global exports require*/ +function createDummyXMLModel() { + var that = {}; + + function preserveWhitespace(node) { + return true; + } + + // return an array with child qnames or null for inserting text. + // the dummy implementation allows text everywhere, but no new elements + // "*" means all elements are allowed + // ["#PCDATA", "*"] means any element and text is allowed + function getAllowedChildren(node, position) { + return [null]; + } + + that.getAllowedChildren = getAllowedChildren; + that.preserveWhitespace = preserveWhitespace; + return that; +} +exports.createDummyXMLModel = createDummyXMLModel; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/export.js b/apps/files_odfviewer/src/webodf/webodf/lib/export.js new file mode 100644 index 0000000000..08982cd424 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/export.js @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global window runtime odf*/ +/*jslint sub: true*/ + +window["runtime"] = runtime; +runtime["loadClass"] = runtime.loadClass; +window["odf"] = odf; +window["odf"]["OdfCanvas"] = odf.OdfCanvas; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/gui/Caret.js b/apps/files_odfviewer/src/webodf/webodf/lib/gui/Caret.js new file mode 100644 index 0000000000..744b8b022a --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/gui/Caret.js @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global gui*/ +/** + * Class that represents a caret in a document. In text nodes, a native caret is + * used via the HTML attribute contentEditable. Outside of text nodes, an empty + * element representing the caret is used. + * @constructor + */ +gui.Caret = function Caret(selection, rootNode) { + "use strict"; + var document = rootNode.ownerDocument, + cursorns, + cursorNode; + cursorns = 'urn:webodf:names:cursor'; + cursorNode = document.createElementNS(cursorns, 'cursor'); + /** + * Synchronize the cursor with the current selection. + * If there is a single collapsed selection range, the cursor will be placed + * there. If not, the cursor will be removed from the document tree. + * @return {undefined} + */ + this.updateToSelection = function () { + var range; +// removeCursor(); + if (selection.rangeCount === 1) { + range = selection.getRangeAt(0); +/* + if (range.collapsed) { + putCursor(range.startContainer, range.startOffset); + } +*/ + } + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/gui/PresenterUI.js b/apps/files_odfviewer/src/webodf/webodf/lib/gui/PresenterUI.js new file mode 100644 index 0000000000..c6553cc3af --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/gui/PresenterUI.js @@ -0,0 +1,246 @@ +/** + * Copyright (C) 2011 KO GmbH - Tobias Hintze + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ + +/*global runtime, gui, odf, core, xmldom, document, window*/ +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.Style2CSS"); + +gui.PresenterUI = (function () { + "use strict"; + var s2css = new odf.Style2CSS(), + xpath = new xmldom.XPath(), + nsResolver = s2css.namespaceResolver; + + return function PresenterUI(odf_element) { + var self = this; + + self.setInitialSlideMode = function () { + self.startSlideMode('single'); + }; + + self.keyDownHandler = function (ev) { + if (ev.target.isContentEditable) { return; } + if (ev.target.nodeName === 'input') { return; } + switch (ev.keyCode) { + case 84: // t - hide/show toolbar + self.toggleToolbar(); + break; + case 37: // left + case 8: // left + self.prevSlide(); + break; + case 39: // right + case 32: // space + self.nextSlide(); + break; + case 36: // pos1 + self.firstSlide(); + break; + case 35: // end + self.lastSlide(); + break; + } + }; + + self.root = function () { return self.odf_canvas.odfContainer().rootElement; }; + + self.firstSlide = function () { self.slideChange(function (old, pc) { return 0; }); }; + self.lastSlide = function () { self.slideChange(function (old, pc) { return pc - 1; }); }; + + self.nextSlide = function () { + self.slideChange(function (old, pc) { return old + 1 < pc ? old + 1 : -1; }); + }; + self.prevSlide = function () { + self.slideChange(function (old, pc) { return old < 1 ? -1 : old - 1; }); + }; + // indexChanger gets (idx,pagecount) as parameter and returns the new index + self.slideChange = function (indexChanger) { + var pages = self.getPages(self.odf_canvas.odfContainer().rootElement), + last = -1, + i = 0, + newidx, + pagelist; + pages.forEach(function (tuple) { + var name = tuple[0], + node = tuple[1]; + if (node.hasAttribute('slide_current')) { + last = i; + node.removeAttribute('slide_current'); + } + i += 1; + }); + newidx = indexChanger(last, pages.length); + if (newidx === -1) { newidx = last; } + pages[newidx][1].setAttribute('slide_current', '1'); + pagelist = document.getElementById('pagelist'); + pagelist.selectedIndex = newidx; + // FIXME this needs to become a sane callback/listener mechanism + // (and the mode probably a class/instance..) + if (self.slide_mode === 'cont') { + window.scrollBy(0, pages[newidx][1].getBoundingClientRect().top - 30); + } + }; + + self.selectSlide = function (idx) { + self.slideChange(function (old, pc) { + if (idx >= pc) { return -1; } + if (idx < 0) { return -1; } + return idx; + }); + }; + + // make one specific slide visible in cont-mode + self.scrollIntoContView = function (idx) { + var pages = self.getPages(self.odf_canvas.odfContainer().rootElement); + if (pages.length === 0) { return; } + /* + if (false) { + // works in chrome + pages[idx][1].scrollIntoView(); + } else { + */ + // works in ff + window.scrollBy(0, pages[idx][1].getBoundingClientRect().top - 30); + /*}*/ + }; + + // return a list of tuples (pagename, pagenode) + self.getPages = function (root) { + var pagenodes = root.getElementsByTagNameNS(nsResolver('draw'), 'page'), + pages = [], + i; + for (i = 0; i < pagenodes.length; i += 1) { + pages.push([ + pagenodes[i].getAttribute('draw:name'), + pagenodes[i] + ]); + } + return pages; + }; + + // fill a html-select with options, one option per page in odf (odp) + self.fillPageList = function (odfdom_root, html_select) { + var pages = self.getPages(odfdom_root), + i, + html_option, + res, + page_denom; + + // empty the pagelist + while (html_select.firstChild) { + html_select.removeChild(html_select.firstChild); + } + + // populate it + for (i = 0; i < pages.length; i += 1) { + html_option = document.createElement('option'); + res = xpath.getODFElementsWithXPath(pages[i][1], + './draw:frame[@presentation:class="title"]//draw:text-box/text:p', + xmldom.XPath); + page_denom = (res.length > 0) ? res[0].textContent : pages[i][0]; + html_option.textContent = (i + 1) + ": " + page_denom; + html_select.appendChild(html_option); + } + }; + + self.startSlideMode = function (mode) { + var pagelist = document.getElementById('pagelist'), + css = self.odf_canvas.slidevisibilitycss().sheet; + self.slide_mode = mode; + while (css.cssRules.length > 0) { css.deleteRule(0); } + // start on slide 0 + self.selectSlide(0); + if (self.slide_mode === 'single') { + css.insertRule("draw|page { position:fixed; left:0px;top:30px; z-index:1; }", 0); + css.insertRule("draw|page[slide_current] { z-index:2;}", 1); + css.insertRule("draw|page { -webkit-transform: scale(1);}", 2); + self.fitToWindow(); + window.addEventListener('resize', self.fitToWindow, false); + + } else if (self.slide_mode === 'cont') { + window.removeEventListener('resize', self.fitToWindow, false); + } + + self.fillPageList(self.odf_canvas.odfContainer().rootElement, pagelist); + }; + + // toggle (show/hide) toolbar + self.toggleToolbar = function () { + var css, found, i; + css = self.odf_canvas.slidevisibilitycss().sheet; + found = -1; + for (i = 0; i < css.cssRules.length; i += 1) { + if (css.cssRules[i].cssText.substring(0, 8) === ".toolbar") { + found = i; + break; + } + } + if (found > -1) { + css.deleteRule(found); + } else { + css.insertRule(".toolbar { position:fixed; left:0px;top:-200px; z-index:0; }", 0); + } + }; + + // adapt css-transform to window-size + self.fitToWindow = function () { + function ruleByFactor(f) { + return "draw|page { \n" + + "-moz-transform: scale(" + f + "); \n" + + "-moz-transform-origin: 0% 0%; " + + "-webkit-transform-origin: 0% 0%; -webkit-transform: scale(" + f + "); " + + "-o-transform-origin: 0% 0%; -o-transform: scale(" + f + "); " + + "-ms-transform-origin: 0% 0%; -ms-transform: scale(" + f + "); " + + "}"; + } + var pages = self.getPages(self.root()), + factorVert = ((window.innerHeight - 40) / pages[0][1].clientHeight), + factorHoriz = ((window.innerWidth - 10) / pages[0][1].clientWidth), + factor = factorVert < factorHoriz ? factorVert : factorHoriz, + css = self.odf_canvas.slidevisibilitycss().sheet; + css.deleteRule(2); + css.insertRule(ruleByFactor(factor), 2); + }; + + self.load = function (url) { + self.odf_canvas.load(url); + }; + + self.odf_element = odf_element; + self.odf_canvas = new odf.OdfCanvas(self.odf_element); + self.odf_canvas.addListener("statereadychange", self.setInitialSlideMode); + self.slide_mode = 'undefined'; + document.addEventListener('keydown', self.keyDownHandler, false); + }; +}()); + diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/gui/SelectionMover.js b/apps/files_odfviewer/src/webodf/webodf/lib/gui/SelectionMover.js new file mode 100644 index 0000000000..2356c2c8c0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/gui/SelectionMover.js @@ -0,0 +1,217 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, gui: true*/ +runtime.loadClass("core.Cursor"); +/** + * This class modifies the selection in different ways. + * @constructor + * @param {Selection} selection + * @param {!core.PointWalker} pointWalker + * @return {!gui.SelectionMover} + */ +gui.SelectionMover = function SelectionMover(selection, pointWalker) { + "use strict"; + var doc = pointWalker.node().ownerDocument, + cursor = new core.Cursor(selection, doc); + /** + * Return the last range in the selection. Create one if the selection is + * empty. + */ + function getActiveRange(node) { + var range; + if (selection.rangeCount === 0) { + selection.addRange(node.ownerDocument.createRange()); + } + return selection.getRangeAt(selection.rangeCount - 1); + } + function setStart(node, offset) { + // selection interface is cumbersome and in Chrome it is buggy + // as a workaround all ranges are removed. The last one is updated and + // all ranges are placed back + var ranges = [], i, range; + for (i = 0; i < selection.rangeCount; i += 1) { + ranges[i] = selection.getRangeAt(i); + } + selection.removeAllRanges(); + if (ranges.length === 0) { + ranges[0] = node.ownerDocument.createRange(); + } + ranges[ranges.length - 1].setStart(pointWalker.node(), + pointWalker.position()); + for (i = 0; i < ranges.length; i += 1) { + selection.addRange(ranges[i]); + } + } + function doMove(extend, move) { + if (selection.rangeCount === 0) { + return; + } + var range = selection.getRangeAt(0), + /**@type{Element}*/ element; + if (!range.startContainer || range.startContainer.nodeType !== 1) { + return; + } + element = /**@type{!Element}*/(range.startContainer); + pointWalker.setPoint(element, range.startOffset); + move(); + setStart(pointWalker.node(), pointWalker.position()); + } + function doMoveForward(extend, move) { + if (selection.rangeCount === 0) { + return; + } + move(); + var range = selection.getRangeAt(0), + /**@type{Element}*/ element; + if (!range.startContainer || range.startContainer.nodeType !== 1) { + return; + } + element = /**@type{!Element}*/(range.startContainer); + pointWalker.setPoint(element, range.startOffset); + } +/* + function fallbackMoveLineUp() { + // put an element at the current position and call + // pointWalker.stepForward until the y position increases and x position + // is comparable to the previous one + cursor.updateToSelection(); + // retrieve cursor x and y position, then move selection/cursor left + // until, y offset is less and x offset about equal + var rect = cursor.getNode().getBoundingClientRect(), + x = rect.left, + y = rect.top, + arrived = false, + allowedSteps = 200; + while (!arrived && allowedSteps) { + allowedSteps -= 1; + cursor.remove(); + pointWalker.setPoint(selection.focusNode, selection.focusOffset); + pointWalker.stepForward(); + moveCursor(walker.node(), walker.position()); + moveCursorLeft(); + rect = cursor.getNode().getBoundingClientRect(); + arrived = rect.top !== y && rect.left < x; + } + } +*/ + function moveCursor(node, offset, selectMode) { + if (selectMode) { + selection.extend(node, offset); + } else { + selection.collapse(node, offset); + } + cursor.updateToSelection(); + } + function moveCursorLeft() { + var /**@type{Element}*/ element; + if (!selection.focusNode || selection.focusNode.nodeType !== 1) { + return; + } + element = /**@type{!Element}*/(selection.focusNode); + pointWalker.setPoint(element, selection.focusOffset); + pointWalker.stepBackward(); + moveCursor(pointWalker.node(), pointWalker.position(), false); + } + function moveCursorRight() { + cursor.remove(); + var /**@type{Element}*/ element; + if (!selection.focusNode || selection.focusNode.nodeType !== 1) { + return; + } + element = /**@type{!Element}*/(selection.focusNode); + pointWalker.setPoint(element, selection.focusOffset); + pointWalker.stepForward(); + moveCursor(pointWalker.node(), pointWalker.position(), false); + } + function moveCursorUp() { + // retrieve cursor x and y position, then move selection/cursor left + // until, y offset is less and x offset about equal + var rect = cursor.getNode().getBoundingClientRect(), + x = rect.left, + y = rect.top, + arrived = false, + left = 200; + while (!arrived && left) { + left -= 1; + moveCursorLeft(); + rect = cursor.getNode().getBoundingClientRect(); + arrived = rect.top !== y && rect.left < x; + } + } + function moveCursorDown() { + // retrieve cursor x and y position, then move selection/cursor right + // until, x offset is less + cursor.updateToSelection(); + var rect = cursor.getNode().getBoundingClientRect(), + x = rect.left, + y = rect.top, + arrived = false, + left = 200; + while (!arrived) { + left -= 1; + moveCursorRight(); + rect = cursor.getNode().getBoundingClientRect(); + arrived = rect.top !== y && rect.left > x; + } +//alert(left + " " + y + " " + x + " " + rect.top + " " + rect.left); + } + /** + * Move selection forward one point. + * @param {boolean} extend true if range is to be expanded from the current + * point + * @return {undefined} + **/ + this.movePointForward = function (extend) { + doMove(extend, pointWalker.stepForward); + }; + this.movePointBackward = function (extend) { + doMove(extend, pointWalker.stepBackward); + }; + this.moveLineForward = function (extend) { + if (selection.modify) { + // TODO add a way to + selection.modify(extend ? "extend" : "move", "forward", "line"); + } else { + doMove(extend, moveCursorDown); + } + }; + this.moveLineBackward = function (extend) { + if (selection.modify) { + selection.modify(extend ? "extend" : "move", "backward", "line"); + } else { + doMove(extend, function () { + }); + } + }; + return this; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/gui/XMLEdit.js b/apps/files_odfviewer/src/webodf/webodf/lib/gui/XMLEdit.js new file mode 100644 index 0000000000..aee0bd5e7d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/gui/XMLEdit.js @@ -0,0 +1,330 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, gui: true*/ +runtime.loadClass("core.PointWalker"); +runtime.loadClass("core.Cursor"); +//runtime.loadClass("gui.Caret"); +/** + * @constructor + */ +gui.XMLEdit = function XMLEdit(element, stylesheet) { + "use strict"; + var simplecss, + cssprefix, + documentElement, + customNS = "customns", + walker = null; + + if (!element.id) { + element.id = "xml" + String(Math.random()).substring(2); + } +// element.contentEditable = true; + cssprefix = "#" + element.id + " "; + + function installHandlers() { + } + + // generic css for doing xml formatting: color tags and do indentation + simplecss = cssprefix + "*," + cssprefix + ":visited, " + cssprefix + ":link {display:block; margin: 0px; margin-left: 10px; font-size: medium; color: black; background: white; font-variant: normal; font-weight: normal; font-style: normal; font-family: sans-serif; text-decoration: none; white-space: pre-wrap; height: auto; width: auto}\n" + + cssprefix + ":before {color: blue; content: '<' attr(customns_name) attr(customns_atts) '>';}\n" + + cssprefix + ":after {color: blue; content: '';}\n" + + cssprefix + "{overflow: auto;}\n"; + + function listenEvent(eventTarget, eventType, eventHandler) { + if (eventTarget.addEventListener) { + eventTarget.addEventListener(eventType, eventHandler, false); + } else if (eventTarget.attachEvent) { + eventType = "on" + eventType; + eventTarget.attachEvent(eventType, eventHandler); + } else { + eventTarget["on" + eventType] = eventHandler; + } + } + function cancelEvent(event) { + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } + } + + function isCaretMoveCommand(charCode) { + if (charCode >= 16 && charCode <= 20) { + return true; + } + if (charCode >= 33 && charCode <= 40) { //arrows,home,end,pgup,pgdown + return true; + } + return false; + } + + function syncSelectionWithWalker() { + var sel = element.ownerDocument.defaultView.getSelection(), + r; + if (!sel || sel.rangeCount <= 0 || !walker) { + return; + } + r = sel.getRangeAt(0); + walker.setPoint(r.startContainer, r.startOffset); + } + + function syncWalkerWithSelection() { + var sel = element.ownerDocument.defaultView.getSelection(), + n, r; + sel.removeAllRanges(); + if (!walker || !walker.node()) { + return; + } + n = walker.node(); + r = n.ownerDocument.createRange(); + r.setStart(n, walker.position()); + r.collapse(true); + sel.addRange(r); + } + + function handleKeyDown(event) { + var charCode = event.charCode || event.keyCode; + // cursor movement + walker = null; + if (walker && charCode === 39) { // right arrow + syncSelectionWithWalker(); + walker.stepForward(); + syncWalkerWithSelection(); + } else if (walker && charCode === 37) { //left arrow + syncSelectionWithWalker(); + walker.stepBackward(); + syncWalkerWithSelection(); + } else if (isCaretMoveCommand(charCode)) { + return; + } + cancelEvent(event); + } + + function handleKeyPress(event) { +// handleKeyDown(event); + } + + function handleClick(event) { +// alert(event.target.nodeName); + var sel = element.ownerDocument.defaultView.getSelection(), + r = sel.getRangeAt(0), + n = r.startContainer; + // if cursor is in customns node, move up to the top one + /* + if (n.parentNode.namespaceURI === customNS) { + while (n.parentNode.namespaceURI === customNS) { + n = n.parentNode; + } + r = n.ownerDocument.createRange(); + r.setStart(n.nextSibling, 0); + r.collapse(true); + sel.removeAllRanges(); + sel.addRange(r); + } +*/ +/* + r = element.ownerDocument.createRange(); + r.setStart(event.target.nodeName, 0); + r.collapse(true); + sel.removeAllRanges(); + sel.addRange(r); +*/ +//alert(sel.getRangeAt(0).startContainer.nodeName + " " + sel.getRangeAt(0).startOffset); + + cancelEvent(event); + } + + function initElement(element) { + listenEvent(element, "click", handleClick); + listenEvent(element, "keydown", handleKeyDown); + listenEvent(element, "keypress", handleKeyPress); + //listenEvent(element, "mouseup", handleMouseUp); + // ignore drop events, dragstart, drag, dragenter, dragover are ok for now + listenEvent(element, "drop", cancelEvent); + listenEvent(element, "dragend", cancelEvent); + // pasting is also disallowed for now + listenEvent(element, "beforepaste", cancelEvent); + listenEvent(element, "paste", cancelEvent); + } + + // remove all textnodes that contain only whitespace + function cleanWhitespace(node) { + var n = node.firstChild, p, + re = /^\s*$/; + while (n && n !== node) { + p = n; + n = n.nextSibling || n.parentNode; + if (p.nodeType === 3 && re.test(p.nodeValue)) { + p.parentNode.removeChild(p); + } + } + } + /** + * @param {!Node} node + * @return {undefined} + */ + function setCssHelperAttributes(node) { + var atts, attsv, a, i; + // write all attributes in a string that is shown via the css + atts = node.attributes; + attsv = ""; + for (i = atts.length - 1; i >= 0; i -= 1) { + a = atts.item(i); + attsv = attsv + " " + a.nodeName + "=\"" + a.nodeValue + "\""; + } + node.setAttribute("customns_name", node.nodeName); + node.setAttribute("customns_atts", attsv); + } + /** + * @param {!Node} node + * @return {undefined} + */ + function addExplicitAttributes(node) { + var n = node.firstChild; + // recurse over the dom + while (n && n !== node) { + if (n.nodeType === 1) { + addExplicitAttributes(n); + } + n = n.nextSibling || n.parentNode; + } + setCssHelperAttributes(node); + cleanWhitespace(node); + } + + function getNamespacePrefixes(node, prefixes) { + var n = node.firstChild, atts, att, i; + while (n && n !== node) { + if (n.nodeType === 1) { + getNamespacePrefixes(n, prefixes); + atts = n.attributes; + for (i = atts.length - 1; i >= 0; i -= 1) { + att = atts.item(i); + // record the prefix that the document uses for namespaces + if (att.namespaceURI === "http://www.w3.org/2000/xmlns/") { + if (!prefixes[att.nodeValue]) { + prefixes[att.nodeValue] = att.localName; + } + } + } + } + n = n.nextSibling || n.parentNode; + } + } + + /** + * Give each namespace a unique prefix. + * @param {Object.} prefixes Map with namespace as key and + * prefix as value + * @return {undefined} + */ + function generateUniquePrefixes(prefixes) { + var taken = {}, + ns, p, n = 0; + for (ns in prefixes) { + if (prefixes.hasOwnProperty(ns) && ns) { + p = prefixes[ns]; + if (!p || taken.hasOwnProperty(p) || p === "xmlns") { + do { + p = "ns" + n; + n += 1; + } while (taken.hasOwnProperty(p)); + prefixes[ns] = p; + } + taken[p] = true; + } + } + } + + // the CSS neededed for the XML edit view depends on the prefixes + function createCssFromXmlInstance(node) { + // collect all prefixes and elements + var prefixes = {}, // namespace prefixes as they occur in the XML + css = "@namespace customns url(customns);\n", + name, pre, ns, names, csssel; + getNamespacePrefixes(node, prefixes); + generateUniquePrefixes(prefixes); +/* + for (ns in prefixes) { + if (ns) { + css = css + "@namepace " + prefixes[ns] + " url(" + ns + ");\n"; + } + } + for (ns in prefixes) { + if (ns) { + pre = cssprefix + prefixes[ns] + "|"; + css = css + pre + ":before { content: '<" + prefixes[ns] + + ":' attr(customns_name); }\n" + + pre + ":after { content: ''; }\n"; + } + } +*/ + return css; + } + + // Adapt the CSS to the current settings. + function updateCSS() { + var css = element.ownerDocument.createElement("style"), + text = createCssFromXmlInstance(element); + css.type = "text/css"; + text = text + simplecss; + css.appendChild(element.ownerDocument.createTextNode(text)); + stylesheet = stylesheet.parentNode.replaceChild(css, stylesheet); + } + function getXML() { + return documentElement; + } + function setXML(xml) { + var node = xml.documentElement || xml; + node = element.ownerDocument.importNode(node, true); + documentElement = node; + + addExplicitAttributes(node); + + while (element.lastChild) { + element.removeChild(element.lastChild); + } + element.appendChild(node); + + updateCSS(); + + walker = new core.PointWalker(node); + } + + initElement(element); + + this.updateCSS = updateCSS; + this.setXML = setXML; + this.getXML = getXML; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/manifest.js b/apps/files_odfviewer/src/webodf/webodf/lib/manifest.js new file mode 100644 index 0000000000..1a185b85b9 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/manifest.js @@ -0,0 +1,34 @@ +(function () { + "use strict"; + return [ + "core/Async.js", + "core/Base64.js", + "core/ByteArray.js", + "core/ByteArrayWriter.js", + "core/Cursor.js", + "core/JSLint.js", + "core/PointWalker.js", + "core/RawDeflate.js", + "core/RawInflate.js", + "core/UnitTester.js", + "core/Zip.js", + "gui/Caret.js", + "gui/SelectionMover.js", + "gui/XMLEdit.js", + "gui/PresenterUI.js", + "odf/FontLoader.js", + "odf/Formatting.js", + "odf/OdfCanvas.js", + "odf/OdfContainer.js", + "odf/Style2CSS.js", + "odf/StyleInfo.js", + "xmldom/LSSerializer.js", + "xmldom/LSSerializerFilter.js", + "xmldom/OperationalTransformDOM.js", + "xmldom/OperationalTransformInterface.js", + "xmldom/RelaxNG.js", + "xmldom/RelaxNG2.js", + "xmldom/RelaxNGParser.js", + "xmldom/XPath.js" + ]; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/odf/FontLoader.js b/apps/files_odfviewer/src/webodf/webodf/lib/odf/FontLoader.js new file mode 100644 index 0000000000..f6d51f666a --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/odf/FontLoader.js @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*jslint sub: true*/ +/*global runtime, odf, core, document, xmldom*/ +runtime.loadClass("core.Base64"); +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.Style2CSS"); +/** + * This class loads embedded fonts into the CSS + * @constructor + **/ +odf.FontLoader = (function () { + "use strict"; + var style2CSS = new odf.Style2CSS(), + xpath = new xmldom.XPath(), + base64 = new core.Base64(); + /** + * @param {!Element} fontFaceDecls + * @return {!Object.} + */ + function getEmbeddedFontDeclarations(fontFaceDecls) { + var decls = {}, + fonts, + i, font, name, uris, href; + if (!fontFaceDecls) { + return decls; + } + fonts = xpath.getODFElementsWithXPath(fontFaceDecls, + "style:font-face[svg:font-face-src]", + style2CSS.namespaceResolver); + for (i = 0; i < fonts.length; i += 1) { + font = fonts[i]; + name = font.getAttributeNS(style2CSS.namespaces["style"], "name"); + uris = xpath.getODFElementsWithXPath(font, + "svg:font-face-src/svg:font-face-uri", + style2CSS.namespaceResolver); + if (uris.length > 0) { + href = uris[0].getAttributeNS(style2CSS.namespaces["xlink"], + "href"); + decls[name] = {href: href}; + } + } + return decls; + } + function addFontToCSS(name, font, fontdata, stylesheet) { + // hack: get the first stylesheet + stylesheet = document.styleSheets[0]; + var rule = "@font-face { font-family: \"" + name + "\"; src: " + + "url(data:application/x-font-ttf;charset=binary;base64," + + base64.convertUTF8ArrayToBase64(fontdata) + + ") format(\"truetype\"); }"; + try { + stylesheet.insertRule(rule, stylesheet.cssRules.length); + } catch (e) { + runtime.log("Problem inserting rule in CSS: " + rule); + } + } + function loadFontIntoCSS(embeddedFontDeclarations, zip, pos, stylesheet, + callback) { + var name, i = 0, n; + for (n in embeddedFontDeclarations) { + if (embeddedFontDeclarations.hasOwnProperty(n)) { + if (i === pos) { + name = n; + } + i += 1; + } + } + if (!name) { + return callback(); + } + zip.load(embeddedFontDeclarations[name].href, function (err, fontdata) { + if (err) { + runtime.log(err); + } else { + addFontToCSS(name, embeddedFontDeclarations[name], fontdata, + stylesheet); + } + return loadFontIntoCSS(embeddedFontDeclarations, zip, pos + 1, + stylesheet, callback); + }); + } + function loadFontsIntoCSS(embeddedFontDeclarations, zip, stylesheet) { + loadFontIntoCSS(embeddedFontDeclarations, zip, 0, stylesheet, + function () {}); + } + /** + * @constructor + */ + odf.FontLoader = function FontLoader() { + var self = this; + /** + * @param {!Element} fontFaceDecls + * @param {!core.Zip} zip + * @param {!StyleSheet} stylesheet + * @return {undefined} + */ + this.loadFonts = function (fontFaceDecls, zip, stylesheet) { + var embeddedFontDeclarations = getEmbeddedFontDeclarations( + fontFaceDecls); + loadFontsIntoCSS(embeddedFontDeclarations, zip, stylesheet); + }; + }; + return odf.FontLoader; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/odf/Formatting.js b/apps/files_odfviewer/src/webodf/webodf/lib/odf/Formatting.js new file mode 100644 index 0000000000..cf42fcc50a --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/odf/Formatting.js @@ -0,0 +1,153 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global odf: true, runtime: true*/ +/** + * @constructor + */ +odf.Formatting = function Formatting() { + "use strict"; + var /**@type{odf.OdfContainer}*/ odfContainer, + /**@type{odf.StyleInfo}*/ styleInfo = new odf.StyleInfo(); + + /** + * Class that iterates over all elements that are part of the range. + * @constructor + * @param {!Range} range + * @return {undefined} + */ + function RangeElementIterator(range) { + /** + * @param {Node} parent + * @param {!number} n + * @return {Node} + */ + function getNthChild(parent, n) { + var c = parent && parent.firstChild; + while (c && n) { + c = c.nextSibling; + n -= 1; + } + return c; + } + var start = getNthChild(range.startContainer, range.startOffset), + end = getNthChild(range.endContainer, range.endOffset), + current = start; + /** + * @return {Element|null} + */ + this.next = function () { + var c = current; + if (c === null) { + return c; + } + return null; + }; + } + + /** + * @param {!Element} element + * @return {Element} + */ + function getParentStyle(element) { + var n = element.firstChild, e; + if (n.nodeType === 1) { // Element + e = /**@type{Element}*/(n); + return e; + } + return null; + } + /** + * @param {!Range} range + * @return {!Array.} + */ + function getParagraphStyles(range) { + var iter = new RangeElementIterator(range), e, styles = []; + e = iter.next(); + while (e) { + if (styleInfo.canElementHaveStyle("paragraph", e)) { + styles.push(e); + } + } + return styles; + } + + /** + * @param {!odf.OdfContainer} odfcontainer + * @return {undefined} + */ + this.setOdfContainer = function (odfcontainer) { + odfContainer = odfcontainer; + }; + /** + * Return true if all parts of the selection are bold. + * @param {!Array.} selection + * @return {!boolean} + */ + this.isCompletelyBold = function (selection) { + return false; + }; + /** + * Get the alignment or undefined if no uniform alignment is found + * @param {!Array.} selection + * @return {!string|undefined} + */ + this.getAlignment = function (selection) { + var styles = this.getParagraphStyles(selection), i, l = styles.length; + return undefined; + }; + /** + * Get the list of paragraph styles that covered by the current selection. + * @param {!Array.} selection + * @return {!Array.} + */ + this.getParagraphStyles = function (selection) { + var i, j, s, styles = []; + for (i = 0; i < selection.length; i += 0) { + s = getParagraphStyles(selection[i]); + for (j = 0; j < s.length; j += 1) { + if (styles.indexOf(s[j]) === -1) { + styles.push(s[j]); + } + } + } + return styles; + }; + /** + * Get the list of text styles that are covered by the current selection. + * @param {!Array.} selection + * @return {!Array.} + */ + this.getTextStyles = function (selection) { + return []; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfCanvas.js b/apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfCanvas.js new file mode 100644 index 0000000000..b8077f8093 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfCanvas.js @@ -0,0 +1,912 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*jslint sub: true*/ +/*global runtime, odf, xmldom */ +runtime.loadClass("odf.OdfContainer"); +runtime.loadClass("odf.Formatting"); +runtime.loadClass("xmldom.XPath"); +/** + * This class manages a loaded ODF document that is shown in an element. + * It takes care of giving visual feedback on loading, ensures that the + * stylesheets are loaded. + * @constructor + * @param {!Element} element Put and ODF Canvas inside this element. + **/ +odf.OdfCanvas = (function () { + "use strict"; + /** + * A loading queue where various tasks related to loading can be placed + * and will be run with 10 ms between them. This gives the ui a change to + * to update. + * @constructor + */ + function LoadingQueue() { + var queue = [], + taskRunning = false; + /** + * @param {Function} task + * @return {undefined} + */ + function run(task) { + taskRunning = true; + runtime.setTimeout(function () { + try { + task(); + } catch (e) { + runtime.log(e); + } + taskRunning = false; + if (queue.length > 0) { + run(queue.pop()); + } + }, 10); + } + /** + * @return {undefined} + */ + this.clearQueue = function () { + queue.length = 0; + }; + /** + * @param {Function} loadingTask + * @return {undefined} + */ + this.addToQueue = function (loadingTask) { + if (queue.length === 0 && !taskRunning) { + return run(loadingTask); + } + queue.push(loadingTask); + }; + } + /** + * @constructor + * @param css + */ + function PageSwitcher(css) { + var sheet = css.sheet, + position = 1; + function updateCSS() { + while (sheet.cssRules.length > 0) { + sheet.deleteRule(0); + } + sheet.insertRule('office|presentation draw|page {display:none;}', 0); + sheet.insertRule("office|presentation draw|page:nth-child(" + + position + ") {display:block;}", 1); + } + /** + * @return {undefined} + */ + this.showNextPage = function () { + position += 1; + updateCSS(); + }; + /** + * @return {undefined} + */ + this.showPreviousPage = function () { + if (position > 1) { + position -= 1; + updateCSS(); + } + }; + this.css = css; + } + /** + * Register event listener on DOM element. + * @param {!Element} eventTarget + * @param {!string} eventType + * @param {!Function} eventHandler + * @return {undefined} + */ + function listenEvent(eventTarget, eventType, eventHandler) { + if (eventTarget.addEventListener) { + eventTarget.addEventListener(eventType, eventHandler, false); + } else if (eventTarget.attachEvent) { + eventType = "on" + eventType; + eventTarget.attachEvent(eventType, eventHandler); + } else { + eventTarget["on" + eventType] = eventHandler; + } + } + /** + * Class that listens to events and sends a signal if the selection changes. + * @constructor + * @param {!Element} element + */ + function SelectionWatcher(element) { + var selection = [], count = 0, listeners = []; + /** + * @param {!Element} ancestor + * @param {Node} descendant + * @return {!boolean} + */ + function isAncestorOf(ancestor, descendant) { + while (descendant) { + if (descendant === ancestor) { + return true; + } + descendant = descendant.parentNode; + } + return false; + } + /** + * @param {!Element} element + * @param {!Range} range + * @return {!boolean} + */ + function fallsWithin(element, range) { + return isAncestorOf(element, range.startContainer) && + isAncestorOf(element, range.endContainer); + } + /** + * @return {!Array.} + */ + function getCurrentSelection() { + var s = [], selection = runtime.getWindow().getSelection(), i, r; + for (i = 0; i < selection.rangeCount; i += 1) { + r = selection.getRangeAt(i); + // check if the nodes in the range fall completely within the + // element + if (r !== null && fallsWithin(element, r)) { + s.push(r); + } + } + return s; + } + /** + * @param {Range} rangeA + * @param {Range} rangeB + * @return {!boolean} + */ + function rangesNotEqual(rangeA, rangeB) { + if (rangeA === rangeB) { + return false; + } + if (rangeA === null || rangeB === null) { + return true; + } + return rangeA.startContainer !== rangeB.startContainer || + rangeA.startOffset !== rangeB.startOffset || + rangeA.endContainer !== rangeB.endContainer || + rangeA.endOffset !== rangeB.endOffset; + } + /** + * @return {undefined} + */ + function emitNewSelection() { + var i, l = listeners.length; + for (i = 0; i < l; i += 1) { + listeners[i](element, selection); + } + } + /** + * @param {!Array.} selection + * @return {!Array.} + */ + function copySelection(selection) { + var s = [selection.length], i, oldr, r, + doc = element.ownerDocument; + for (i = 0; i < selection.length; i += 1) { + oldr = selection[i]; + r = doc.createRange(); + r.setStart(oldr.startContainer, oldr.startOffset); + r.setEnd(oldr.endContainer, oldr.endOffset); + s[i] = r; + } + return s; + } + /** + * @return {undefined} + */ + function checkSelection() { + var s = getCurrentSelection(), i; + if (s.length === selection.length) { + for (i = 0; i < s.length; i += 1) { + if (rangesNotEqual(s[i], selection[i])) { + break; + } + } + if (i === s.length) { + return; // no change + } + } + selection = s; + selection = copySelection(s); + emitNewSelection(); + } + /** + * @param {!string} eventName + * @param {!function(!Element, !Array.)} handler + * @return {undefined} + */ + this.addListener = function (eventName, handler) { + var i, l = listeners.length; + for (i = 0; i < l; i += 1) { + if (listeners[i] === handler) { + return; + } + } + listeners.push(handler); + }; + listenEvent(element, "mouseup", checkSelection); + listenEvent(element, "keyup", checkSelection); + listenEvent(element, "keydown", checkSelection); + } + var style2CSS = new odf.Style2CSS(), + namespaces = style2CSS.namespaces, + drawns = namespaces.draw, + fons = namespaces.fo, + officens = namespaces.office, + svgns = namespaces.svg, + textns = namespaces.text, + xlinkns = namespaces.xlink, + window = runtime.getWindow(), + xpath = new xmldom.XPath(), + /**@const@type{!Object.>}*/ + eventHandlers = {}, + editparagraph, + loadingQueue = new LoadingQueue(); + + /** + * Register an event handler + * @param {!string} eventType + * @param {!Function} eventHandler + * @return {undefined} + */ + function addEventListener(eventType, eventHandler) { + var handlers = eventHandlers[eventType]; + if (handlers === undefined) { + handlers = eventHandlers[eventType] = []; + } + if (eventHandler && handlers.indexOf(eventHandler) === -1) { + handlers.push(eventHandler); + } + } + /** + * Fire an event + * @param {!string} eventType + * @param {Array.=} args + * @return {undefined} + */ + function fireEvent(eventType, args) { + if (!eventHandlers.hasOwnProperty(eventType)) { + return; + } + var handlers = eventHandlers[eventType], i; + for (i = 0; i < handlers.length; i += 1) { + handlers[i](args); + } + } + /** + * @param {!Element} element + * @return {undefined} + */ + function clear(element) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + } + /** + * A new styles.xml has been loaded. Update the live document with it. + * @param {!Element} odfelement + * @param {!HTMLStyleElement} stylesxmlcss + * @return {undefined} + **/ + function handleStyles(odfelement, stylesxmlcss) { + // update the css translation of the styles + var style2css = new odf.Style2CSS(); + style2css.style2css(stylesxmlcss.sheet, odfelement.styles, + odfelement.automaticStyles); + } + /** + * @param {!string} id + * @param {!Element} frame + * @param {!StyleSheet} stylesheet + * @return {undefined} + **/ + function setFramePosition(id, frame, stylesheet) { + frame.setAttribute('styleid', id); + var rule, + anchor = frame.getAttributeNS(textns, 'anchor-type'), + x = frame.getAttributeNS(svgns, 'x'), + y = frame.getAttributeNS(svgns, 'y'), + width = frame.getAttributeNS(svgns, 'width'), + height = frame.getAttributeNS(svgns, 'height'), + minheight = frame.getAttributeNS(fons, 'min-height'), + minwidth = frame.getAttributeNS(fons, 'min-width'); + if (anchor === "as-char") { + rule = 'display: inline-block;'; + } else if (anchor || x || y) { + rule = 'position: absolute;'; + } else if (width || height || minheight || minwidth) { + rule = 'display: block;'; + } + if (x) { + rule += 'left: ' + x + ';'; + } + if (y) { + rule += 'top: ' + y + ';'; + } + if (width) { + rule += 'width: ' + width + ';'; + } + if (height) { + rule += 'height: ' + height + ';'; + } + if (minheight) { + rule += 'min-height: ' + minheight + ';'; + } + if (minwidth) { + rule += 'min-width: ' + minwidth + ';'; + } + if (rule) { + rule = 'draw|' + frame.localName + '[styleid="' + id + '"] {' + + rule + '}'; + stylesheet.insertRule(rule, stylesheet.cssRules.length); + } + } + /** + * @param {!Element} image + * @return {string} + **/ + function getUrlFromBinaryDataElement(image) { + var node = image.firstChild; + while (node) { + if (node.namespaceURI === officens && + node.localName === "binary-data") { + // TODO: detect mime-type, assuming png for now + return "data:image/png;base64," + node.textContent; + } + node = node.nextSibling; + } + return ""; + } + /** + * @param {!string} id + * @param {!Object} container + * @param {!Element} image + * @param {!StyleSheet} stylesheet + * @return {undefined} + **/ + function setImage(id, container, image, stylesheet) { + image.setAttribute('styleid', id); + var url = image.getAttributeNS(xlinkns, 'href'), + part, + node; + function callback(url) { + var rule = "background-image: url(" + url + ");"; + rule = 'draw|image[styleid="' + id + '"] {' + rule + '}'; + stylesheet.insertRule(rule, stylesheet.cssRules.length); + } + // look for a office:binary-data + if (url) { + try { + if (container.getPartUrl) { + url = container.getPartUrl(url); + callback(url); + } else { + part = container.getPart(url); + part.onchange = function (part) { + callback(part.url); + }; + part.load(); + } + } catch (e) { + runtime.log('slight problem: ' + e); + } + } else { + url = getUrlFromBinaryDataElement(image); + callback(url); + } + } + function formatParagraphAnchors(odfbody) { + var runtimens = "urn:webodf", + n, + i, + nodes = xpath.getODFElementsWithXPath(odfbody, + ".//*[*[@text:anchor-type='paragraph']]", + style2CSS.namespaceResolver); + for (i = 0; i < nodes.length; i += 1) { + n = nodes[i]; + if (n.setAttributeNS) { + n.setAttributeNS(runtimens, "containsparagraphanchor", true); + } + } + } + /** + * @param {!Object} container + * @param {!Element} odfbody + * @param {!StyleSheet} stylesheet + * @return {undefined} + **/ + function modifyImages(container, odfbody, stylesheet) { + var node, + frames, + i, + images; + function namespaceResolver(prefix) { + return namespaces[prefix]; + } + // find all the frame elements + frames = []; + node = odfbody.firstChild; + while (node && node !== odfbody) { + if (node.namespaceURI === drawns) { + frames[frames.length] = node; + } + if (node.firstChild) { + node = node.firstChild; + } else { + while (node && node !== odfbody && !node.nextSibling) { + node = node.parentNode; + } + if (node && node.nextSibling) { + node = node.nextSibling; + } + } + } + // adjust all the frame positions + for (i = 0; i < frames.length; i += 1) { + node = frames[i]; + setFramePosition('frame' + String(i), node, stylesheet); + } + formatParagraphAnchors(odfbody); + } + /** + * Load all the images that are inside an odf element. + * @param {!Object} container + * @param {!Element} odffragment + * @param {!StyleSheet} stylesheet + * @return {undefined} + */ + function loadImages(container, odffragment, stylesheet) { + var i, + images, + node; + // do delayed loading for all the images + function loadImage(name, container, node, stylesheet) { + // load image with a small delay to give the html ui a chance to + // update + loadingQueue.addToQueue(function () { + setImage(name, container, node, stylesheet); + }); + } + images = odffragment.getElementsByTagNameNS(drawns, 'image'); + for (i = 0; i < images.length; i += 1) { + node = /**@type{!Element}*/(images.item(i)); + loadImage('image' + String(i), container, node, stylesheet); + } + } + /** + * @param {!string} id + * @param {!Object} container + * @param {!Element} plugin + * @param {!StyleSheet} stylesheet + * @return {undefined} + **/ + function setVideo(id, container, plugin, stylesheet) { + var video, source, url, videoType, doc = plugin.ownerDocument, part, node; + + url = plugin.getAttributeNS(xlinkns, 'href'); + + function callback(url, mimetype) { + // test for video mimetypes + if (mimetype.substr(0, 6) === 'video/') { + video = doc.createElementNS(doc.documentElement.namespaceURI, "video"); + video.setAttribute('controls', 'controls'); + + source = doc.createElement('source'); + source.setAttribute('src', url); + source.setAttribute('type', mimetype); + + video.appendChild(source); + plugin.parentNode.appendChild(video); + } else { + plugin.innerHtml = 'Unrecognised Plugin'; + } + } + // look for a office:binary-data + if (url) { + try { + if (container.getPartUrl) { + url = container.getPartUrl(url); + callback(url, 'video/mp4'); + } else { + part = container.getPart(url); + part.onchange = function (part) { + callback(part.url, part.mimetype); + }; + part.load(); + } + } catch (e) { + runtime.log('slight problem: ' + e); + } + } else { + // this will fail atm - following function assumes PNG data] + runtime.log('using MP4 data fallback'); + url = getUrlFromBinaryDataElement(plugin); + callback(url, 'video/mp4'); + } + } + /** + * Load all the video that are inside an odf element. + * @param {!Object} container + * @param {!Element} odffragment + * @param {!StyleSheet} stylesheet + * @return {undefined} + */ + function loadVideos(container, odffragment, stylesheet) { + var i, + plugins, + node; + // do delayed loading for all the videos + function loadVideo(name, container, node, stylesheet) { + // load video with a small delay to give the html ui a chance to + // update + loadingQueue.addToQueue(function () { + setVideo(name, container, node, stylesheet); + }); + } + // embedded video is stored in a draw:plugin element + plugins = odffragment.getElementsByTagNameNS(drawns, 'plugin'); + runtime.log('Loading Videos:'); + + for (i = 0; i < plugins.length; i += 1) { + runtime.log('...Found a video.'); + node = /**@type{!Element}*/(plugins.item(i)); + loadVideo('video' + String(i), container, node, stylesheet); + } + } + /** + * @param {Document} document Put and ODF Canvas inside this element. + */ + function addStyleSheet(document) { + var styles = document.getElementsByTagName("style"), + head = document.getElementsByTagName('head')[0], + text = '', + prefix, + a = "", + b; + // use cloneNode on an exisiting HTMLStyleElement, because in + // Chromium 12, document.createElement('style') does not give a + // HTMLStyleElement + if (styles && styles.length > 0) { + styles = styles[0].cloneNode(false); + } else { + styles = document.createElement('style'); + } + for (prefix in namespaces) { + if (namespaces.hasOwnProperty(prefix) && prefix) { + text += "@namespace " + prefix + " url(" + namespaces[prefix] + + ");\n"; + } + } + styles.appendChild(document.createTextNode(text)); + head.appendChild(styles); + return styles; + } + /** + * @constructor + * @param {!Element} element Put and ODF Canvas inside this element. + */ + odf.OdfCanvas = function OdfCanvas(element) { + var self = this, + document = element.ownerDocument, + /**@type{odf.OdfContainer}*/ odfcontainer, + /**@type{!odf.Formatting}*/ formatting = new odf.Formatting(), + selectionWatcher = new SelectionWatcher(element), + slidecssindex = 0, + pageSwitcher = new PageSwitcher(addStyleSheet(document)), + stylesxmlcss = addStyleSheet(document), + positioncss = addStyleSheet(document), + editable = false, + zoomLevel = 1; + + function fixContainerSize() { + var sizer = element.firstChild, + odfdoc = sizer.firstChild; + if (!odfdoc) { + return; + } + element.style.WebkitTransform = 'scale(' + zoomLevel + ')'; + element.style.WebkitTransformOrigin = 'left top'; + element.style.width = Math.round(zoomLevel * odfdoc.offsetWidth) + + "px"; + element.style.height = Math.round(zoomLevel * odfdoc.offsetHeight) + + "px"; + } + /** + * A new content.xml has been loaded. Update the live document with it. + * @param {!Object} container + * @param {!Element} odfnode + * @return {undefined} + **/ + function handleContent(container, odfnode) { + var css = positioncss.sheet, sizer; + modifyImages(container, odfnode.body, css); +/* + slidecssindex = css.insertRule( + 'office|presentation draw|page:nth-child(1n) {display:block;}', + css.cssRules.length + ); +*/ + // FIXME: this is a hack to have a defined background now + // should be removed as soon as we have sane background + // handling for pages + css.insertRule('draw|page { background-color:#fff; }', + css.cssRules.length); + + // only append the content at the end + clear(element); + sizer = document.createElement('div'); + sizer.style.display = "inline-block"; + sizer.style.background = "white"; + sizer.appendChild(odfnode); + element.appendChild(sizer); + loadImages(container, odfnode.body, css); + loadVideos(container, odfnode.body, css); + fixContainerSize(); + } + /** + * @param {!odf.OdfContainer} container + * @return {undefined} + **/ + function refreshOdf(container) { + if (odfcontainer !== container) { + return; + } + + // synchronize the object a window.odfcontainer with the view + function callback() { + clear(element); + element.style.display = "inline-block"; + var odfnode = container.rootElement; + element.ownerDocument.importNode(odfnode, true); + + formatting.setOdfContainer(container); + handleStyles(odfnode, stylesxmlcss); + // do content last, because otherwise the document is constantly + // updated whenever the css changes + handleContent(container, odfnode); + fireEvent("statereadychange"); + } + + if (odfcontainer.state === odf.OdfContainer.DONE) { + callback(); + } else { + odfcontainer.onchange = callback; + } + } + + this.odfContainer = function () { + return odfcontainer; + }; + this.slidevisibilitycss = function () { + return pageSwitcher.css; + }; + /** + * @param {!string} url + * @return {undefined} + */ + this["load"] = this.load = function (url) { + loadingQueue.clearQueue(); + element.innerHTML = 'loading ' + url; + // open the odf container + odfcontainer = new odf.OdfContainer(url, function (container) { + odfcontainer = container; + refreshOdf(container); + }); + odfcontainer.onstatereadychange = refreshOdf; + }; + + function stopEditing() { + if (!editparagraph) { + return; + } + var fragment = editparagraph.ownerDocument.createDocumentFragment(); + while (editparagraph.firstChild) { + fragment.insertBefore(editparagraph.firstChild, null); + } + editparagraph.parentNode.replaceChild(fragment, editparagraph); + } + + this.save = function (callback) { + stopEditing(); + odfcontainer.save(callback); + }; + + function cancelPropagation(event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else { + event.cancelBubble = true; + } + } + + function cancelEvent(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + } + + this.setEditable = function (iseditable) { + editable = iseditable; + if (!editable) { + stopEditing(); + } + }; + + function processClick(evt) { + evt = evt || window.event; + // go up until we find a text:p, if we find it, wrap it in

and + // make that editable + var e = evt.target, selection = window.getSelection(), + range = ((selection.rangeCount > 0) + ? selection.getRangeAt(0) : null), + startContainer = range && range.startContainer, + startOffset = range && range.startOffset, + endContainer = range && range.endContainer, + endOffset = range && range.endOffset; + + while (e && !((e.localName === "p" || e.localName === "h") && + e.namespaceURI === textns)) { + e = e.parentNode; + } + if (!editable) { + return; + } + // test code for enabling editing + if (!e || e.parentNode === editparagraph) { + return; + } + + if (!editparagraph) { + editparagraph = e.ownerDocument.createElement("p"); + if (!editparagraph.style) { + editparagraph = e.ownerDocument.createElementNS( + "http://www.w3.org/1999/xhtml", + "p" + ); + } + editparagraph.style.margin = "0px"; + editparagraph.style.padding = "0px"; + editparagraph.style.border = "0px"; + editparagraph.setAttribute("contenteditable", true); + } else if (editparagraph.parentNode) { + stopEditing(); + } + e.parentNode.replaceChild(editparagraph, e); + editparagraph.appendChild(e); + + // set the cursor or selection at the right position + editparagraph.focus(); // needed in FF to show cursor in the paragraph + if (range) { + selection.removeAllRanges(); + range = e.ownerDocument.createRange(); + range.setStart(startContainer, startOffset); + range.setEnd(endContainer, endOffset); + selection.addRange(range); + } + cancelEvent(evt); + } + + /** + * @param {!string} eventName + * @param {!function(*)} handler + * @return {undefined} + */ + this.addListener = function (eventName, handler) { + if (eventName === "selectionchange") { + selectionWatcher.addListener(eventName, handler); + } else { + addEventListener(eventName, handler); + } + }; + /** + * @return {!odf.Formatting} + */ + this.getFormatting = function () { + return formatting; + }; + /** + * @param {!number} zoom + * @return {undefined} + */ + this.setZoomLevel = function (zoom) { + zoomLevel = zoom; + fixContainerSize(); + }; + /** + * @return {!number} + */ + this.getZoomLevel = function () { + return zoomLevel; + }; + /** + * @param {!number} width + * @param {!number} height + * @return {undefined} + */ + this.fitToContainingElement = function (width, height) { + var realWidth = element.offsetWidth / zoomLevel, + realHeight = element.offsetHeight / zoomLevel; + zoomLevel = width / realWidth; + if (height / realHeight < zoomLevel) { + zoomLevel = height / realHeight; + } + fixContainerSize(); + }; + /** + * @param {!number} width + * @return {undefined} + */ + this.fitToWidth = function (width) { + var realWidth = element.offsetWidth / zoomLevel; + zoomLevel = width / realWidth; + fixContainerSize(); + }; + /** + * @param {!number} height + * @return {undefined} + */ + this.fitToHeight = function (height) { + var realHeight = element.offsetHeight / zoomLevel; + zoomLevel = height / realHeight; + fixContainerSize(); + }; + /** + * @return {undefined} + */ + this.showNextPage = function () { + pageSwitcher.showNextPage(); + }; + /** + * @return {undefined} + */ + this.showPreviousPage = function () { + pageSwitcher.showPreviousPage(); + }; + /** + * @return {undefined} + */ + this.showAllPages = function () { + }; + + listenEvent(element, "click", processClick); + }; + return odf.OdfCanvas; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfContainer.js b/apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfContainer.js new file mode 100644 index 0000000000..709addbecd --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/odf/OdfContainer.js @@ -0,0 +1,672 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, xmldom: true, odf: true, DOMParser: true, + document: true */ +runtime.loadClass("core.Base64"); +runtime.loadClass("core.Zip"); +runtime.loadClass("xmldom.LSSerializer"); +runtime.loadClass("odf.StyleInfo"); +runtime.loadClass("odf.Style2CSS"); +runtime.loadClass("odf.FontLoader"); +/** + * The OdfContainer class manages the various parts that constitues an ODF + * document. + * @constructor + * @param {!string} url + * @param {!Function|null} onstatereadychange + **/ +odf.OdfContainer = (function () { + "use strict"; + var styleInfo = new odf.StyleInfo(), + style2CSS = new odf.Style2CSS(), + namespaces = style2CSS.namespaces, + officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", + manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", + nodeorder = ['meta', 'settings', 'scripts', 'font-face-decls', 'styles', + 'automatic-styles', 'master-styles', 'body'], + base64 = new core.Base64(), + fontLoader = new odf.FontLoader(), + partMimetypes = {}; + /** + * @param {?Node} node + * @param {!string} ns + * @param {!string} name + * @return {?Node} + */ + function getDirectChild(node, ns, name) { + node = (node) ? node.firstChild : null; + while (node) { + if (node.localName === name && node.namespaceURI === ns) { + return node; + } + node = node.nextSibling; + } + return null; + } + /** + * Return the position the node should get according to the ODF flat format. + * @param {!Node} child + * @return {!number} + */ + function getNodePosition(child) { + var childpos = 0, i, l = nodeorder.length; + for (i = 0; i < l; i += 1) { + if (child.namespaceURI === officens && + child.localName === nodeorder[i]) { + return i; + } + } + return -1; + } + /** + * Class that filters runtime specific nodes from the DOM. + * @constructor + * @implements {xmldom.LSSerializerFilter} + * @param {!Element} odfroot + * @param {!Element=} usedStylesElement + */ + function OdfNodeFilter(odfroot, usedStylesElement) { + var automaticStyles = odfroot.automaticStyles, + usedKeysList; + if (usedStylesElement) { + usedKeysList = new styleInfo.UsedKeysList(usedStylesElement); + } + /** + * @param {!Node} node + * @return {!number} + */ + this.acceptNode = function (node) { + var styleName, styleFamily, result; + if (node.namespaceURI === "http://www.w3.org/1999/xhtml") { + result = 3; // FILTER_SKIP + } else if (usedKeysList && node.parentNode === automaticStyles && + node.nodeType === 1) { + if (usedKeysList.uses(node)) { + result = 1; // FILTER_ACCEPT + } else { + result = 2; // FILTER_REJECT + } + } else { + result = 1; // FILTER_ACCEPT + } + return result; + }; + } + /** + * Put the element at the right position in the parent. + * The right order is given by the value returned from getNodePosition. + * @param {!Node} node + * @param {?Node} child + * @return {undefined} + */ + function setChild(node, child) { + if (!child) { + return; + } + var childpos = getNodePosition(child), + pos, + c = node.firstChild; + if (childpos === -1) { + return; + } + while (c) { + pos = getNodePosition(c); + if (pos !== -1 && pos > childpos) { + break; + } + c = c.nextSibling; + } + node.insertBefore(child, c); + } + /** + * A DOM element that is part of and ODF part of a DOM. + * @constructor + * @extends {Element} + */ + function ODFElement() { + } + /** + * The root element of an ODF document. + * @constructor + * @extends {ODFElement} + */ + function ODFDocumentElement(odfcontainer) { + this.OdfContainer = odfcontainer; + } + ODFDocumentElement.prototype = new ODFElement(); + ODFDocumentElement.prototype.constructor = ODFDocumentElement; + ODFDocumentElement.namespaceURI = officens; + ODFDocumentElement.localName = 'document'; + // private constructor + /** + * @constructor + * @param {!string} name + * @param {!odf.OdfContainer} container + * @param {!core.Zip} zip + */ + function OdfPart(name, container, zip) { + var self = this, + privatedata; + + // declare public variables + this.size = 0; + this.type = null; + this.name = name; + this.container = container; + this.url = null; + this.mimetype = null; + this.document = null; + this.onreadystatechange = null; + this.onchange = null; + this.EMPTY = 0; + this.LOADING = 1; + this.DONE = 2; + this.state = this.EMPTY; + + // private functions + // public functions + this.load = function () { + var mimetype = partMimetypes[name]; + this.mimetype = mimetype; + zip.loadAsDataURL(name, mimetype, function (err, url) { + self.url = url; + if (self.onchange) { + self.onchange(self); + } + if (self.onstatereadychange) { + self.onstatereadychange(self); + } + }); + }; + this.abort = function () { + // TODO + }; + } + OdfPart.prototype.load = function () { + }; + OdfPart.prototype.getUrl = function () { + if (this.data) { + return 'data:;base64,' + base64.toBase64(this.data); + } + return null; + }; + /** + * @constructor + * @param {!odf.OdfContainer} odfcontainer + */ + function OdfPartList(odfcontainer) { + var self = this; + // declare public variables + this.length = 0; + this.item = function (index) { + }; + } + /** + * @constructor + * @param {!string} url + * @param {!Function|null} onstatereadychange + */ + odf.OdfContainer = function OdfContainer(url, onstatereadychange) { + var self = this, + zip = null, + contentXmlCompletelyLoaded = false; + + // NOTE each instance of OdfContainer has a copy of the private functions + // it would be better to have a class OdfContainerPrivate where the + // private functions can be defined via OdfContainerPrivate.prototype + // without exposing them + + // declare public variables + this.onstatereadychange = onstatereadychange; + this.onchange = null; + this.state = null; + this.rootElement = null; + this.parts = null; + + /** + * @param {!Element} element + * @return {undefined} + */ + function removeProcessingInstructions(element) { + var n = element.firstChild, next, e; + while (n) { + next = n.nextSibling; + if (n.nodeType === 1) { // ELEMENT + e = /**@type{!Element}*/(n); + removeProcessingInstructions(e); + } else if (n.nodeType === 7) { // PROCESSING_INSTRUCTION_NODE + element.removeChild(n); + } + n = next; + } + } + + // private functions + /** + * Import the document elementnode into the DOM of OdfContainer. + * Any processing instructions are removed, since importing them + * gives an exception. + * @param {!Document} xmldoc + * @return {!Node} + */ + function importRootNode(xmldoc) { + var doc = self.rootElement.ownerDocument, + node; + // remove all processing instructions + // TODO: replace cursor processing instruction with an element + if (xmldoc) { + removeProcessingInstructions(xmldoc.documentElement); + try { + node = doc.importNode(xmldoc.documentElement, true); + } catch (e) { + } + } + return node; + } + function setState(state) { + self.state = state; + if (self.onchange) { + self.onchange(self); + } + if (self.onstatereadychange) { + self.onstatereadychange(self); + } + } + /** + * @param {!Document} xmldoc + * @return {undefined} + */ + function handleFlatXml(xmldoc) { + var root = importRootNode(xmldoc); + if (!root || root.localName !== 'document' || + root.namespaceURI !== officens) { + setState(OdfContainer.INVALID); + return; + } + self.rootElement = root; + root.fontFaceDecls = getDirectChild(root, officens, 'font-face-decls'); + root.styles = getDirectChild(root, officens, 'styles'); + root.automaticStyles = getDirectChild(root, officens, + 'automatic-styles'); + root.masterStyles = getDirectChild(root, officens, 'master-styles'); + root.body = getDirectChild(root, officens, 'body'); + root.meta = getDirectChild(root, officens, 'meta'); + setState(OdfContainer.DONE); + } + /** + * @param {!Document} xmldoc + * @return {undefined} + */ + function handleStylesXml(xmldoc) { + var node = importRootNode(xmldoc), + root = self.rootElement; + if (!node || node.localName !== 'document-styles' || + node.namespaceURI !== officens) { + setState(OdfContainer.INVALID); + return; + } + root.fontFaceDecls = getDirectChild(node, officens, 'font-face-decls'); + setChild(root, root.fontFaceDecls); + root.styles = getDirectChild(node, officens, 'styles'); + setChild(root, root.styles); + root.automaticStyles = getDirectChild(node, officens, + 'automatic-styles'); + setChild(root, root.automaticStyles); + root.masterStyles = getDirectChild(node, officens, 'master-styles'); + setChild(root, root.masterStyles); + //removeUnusedAutomaticStyles(root.automaticStyles, + // root.masterStyles); + fontLoader.loadFonts(root.fontFaceDecls, zip, null); + } + /** + * @param {!Document} xmldoc + * @return {undefined} + */ + function handleContentXml(xmldoc) { + var node = importRootNode(xmldoc), + root, + automaticStyles, + fontFaceDecls, + c; + if (!node || node.localName !== 'document-content' || + node.namespaceURI !== officens) { + setState(OdfContainer.INVALID); + return; + } + root = self.rootElement; + fontFaceDecls = getDirectChild(node, officens, 'font-face-decls'); + if (root.fontFaceDecls && fontFaceDecls) { + c = fontFaceDecls.firstChild; + while (c) { + root.fontFaceDecls.appendChild(c); + c = fontFaceDecls.firstChild; + } + } else if (fontFaceDecls) { + root.fontFaceDecls = fontFaceDecls; + setChild(root, fontFaceDecls); + } + automaticStyles = getDirectChild(node, officens, 'automatic-styles'); + if (root.automaticStyles && automaticStyles) { + c = automaticStyles.firstChild; + while (c) { + root.automaticStyles.appendChild(c); + c = automaticStyles.firstChild; // works because node c moved + } + } else if (automaticStyles) { + root.automaticStyles = automaticStyles; + setChild(root, automaticStyles); + } + root.body = getDirectChild(node, officens, 'body'); + setChild(root, root.body); + } + /** + * @param {!Document} xmldoc + * @return {undefined} + */ + function handleMetaXml(xmldoc) { + var node = importRootNode(xmldoc), + root; + if (!node || node.localName !== 'document-meta' || + node.namespaceURI !== officens) { + return; + } + root = self.rootElement; + root.meta = getDirectChild(node, officens, 'meta'); + setChild(root, root.meta); + } + /** + * @param {!Document} xmldoc + * @return {undefined} + */ + function handleSettingsXml(xmldoc) { + var node = importRootNode(xmldoc), + root; + if (!node || node.localName !== 'document-settings' || + node.namespaceURI !== officens) { + return; + } + root = self.rootElement; + root.settings = getDirectChild(node, officens, 'settings'); + setChild(root, root.settings); + } + /** + * @param {!Document} xmldoc + * @return {undefined} + */ + function handleManifestXml(xmldoc) { + var node = importRootNode(xmldoc), + root, + n; + if (!node || node.localName !== 'manifest' || + node.namespaceURI !== manifestns) { + return; + } + root = self.rootElement; + root.manifest = node; + n = root.manifest.firstChild; + while (n) { + if (n.nodeType === 1 && n.localName === "file-entry" && + n.namespaceURI === manifestns) { + partMimetypes[n.getAttributeNS(manifestns, "full-path")] = + n.getAttributeNS(manifestns, "media-type"); + } + n = n.nextSibling; + } + } + /** + * @param {!function(?string,?Document)} callback + * @return {undefined} + */ + function getContentXmlNode(callback) { + var handler = { + rootElementReady: function (err, rootxml, done) { + contentXmlCompletelyLoaded = err || done; + if (err) { + return callback(err, null); + } + var parser = new DOMParser(); + rootxml = parser.parseFromString(rootxml, "text/xml"); + callback(null, rootxml); + }, + bodyChildElementsReady: function (err, nodes, done) { + // TODO + } + }; + zip.loadContentXmlAsFragments("content.xml", handler); + } + /** + * @param {!string} filepath + * @param {!function(?string,?Document)} callback + * @return {undefined} + */ + function getXmlNode(filepath, callback) { + zip.loadAsDOM(filepath, callback); + } + /** + * @return {undefined} + */ + function loadComponents() { + // always load content.xml, meta.xml, styles.xml and settings.xml + getXmlNode('styles.xml', function (err, xmldoc) { + handleStylesXml(xmldoc); + if (self.state === OdfContainer.INVALID) { + return; + } + getXmlNode('content.xml', function (err, xmldoc) { + handleContentXml(xmldoc); + if (self.state === OdfContainer.INVALID) { + return; + } + getXmlNode('meta.xml', function (err, xmldoc) { + handleMetaXml(xmldoc); + if (self.state === OdfContainer.INVALID) { + return; + } + getXmlNode('settings.xml', function (err, xmldoc) { + if (xmldoc) { + handleSettingsXml(xmldoc); + } + getXmlNode('META-INF/manifest.xml', function (err, + xmldoc) { + if (xmldoc) { + handleManifestXml(xmldoc); + } + if (self.state !== OdfContainer.INVALID) { + setState(OdfContainer.DONE); + } + }); + }); + }); + }); + }); + } + function documentElement(name, map) { + var s = "", i; + for (i in map) { + if (map.hasOwnProperty(i)) { + s += " xmlns:" + i + "=\"" + map[i] + "\""; + } + } + return ""; + } + /** + * @return {!string} + */ + function serializeMetaXml() { + var nsmap = style2CSS.namespaces, + serializer = new xmldom.LSSerializer(), + /**@type{!string}*/ s = documentElement("document-meta", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement); + s += serializer.writeToString(self.rootElement.meta, nsmap); + s += ""; + return s; + } + /** + * @return {!string} + */ + function serializeSettingsXml() { + var nsmap = style2CSS.namespaces, + serializer = new xmldom.LSSerializer(), + /**@type{!string}*/ s = documentElement("document-settings", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement); + s += serializer.writeToString(self.rootElement.settings, nsmap); + s += ""; + return s; + } + /** + * @return {!string} + */ + function serializeStylesXml() { + var nsmap = style2CSS.namespaces, + serializer = new xmldom.LSSerializer(), + /**@type{!string}*/ s = documentElement("document-styles", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement, + self.rootElement.masterStyles); + s += serializer.writeToString(self.rootElement.fontFaceDecls, nsmap); + s += serializer.writeToString(self.rootElement.styles, nsmap); + s += serializer.writeToString(self.rootElement.automaticStyles, nsmap); + s += serializer.writeToString(self.rootElement.masterStyles, nsmap); + s += ""; + return s; + } + /** + * @return {!string} + */ + function serializeContentXml() { + var nsmap = style2CSS.namespaces, + serializer = new xmldom.LSSerializer(), + /**@type{!string}*/ s = documentElement("document-content", nsmap); + serializer.filter = new OdfNodeFilter(self.rootElement, + self.rootElement.body); + // Until there is code to determine if a font is referenced only + // from all font declaratios will be stored in styles.xml + s += serializer.writeToString(self.rootElement.automaticStyles, nsmap); + s += serializer.writeToString(self.rootElement.body, nsmap); + s += ""; + return s; + } + function createElement(Type) { + var original = document.createElementNS( + Type.namespaceURI, + Type.localName + ), + method, + iface = new Type(); + for (method in iface) { + if (iface.hasOwnProperty(method)) { + original[method] = iface[method]; + } + } + return original; + } + function loadFromXML(url, callback) { + runtime.loadXML(url, function (err, dom) { + if (err) { + callback(err); + } else { + handleFlatXml(dom); + } + }); + } + // public functions + /** + * Open file and parse it. Return the XML Node. Return the root node of + * the file or null if this is not possible. + * For 'content.xml', 'styles.xml', 'meta.xml', and 'settings.xml', the + * elements 'document-content', 'document-styles', 'document-meta', or + * 'document-settings' will be returned respectively. + * @param {!string} partname + * @return {!OdfPart} + **/ + this.getPart = function (partname) { + return new OdfPart(partname, self, zip); + }; + /** + * @param {function(?string):undefined} callback + * @return {undefined} + */ + this.save = function (callback) { + // the assumption so far is that all ODF parts are serialized + // already, but meta, settings, styles and content should be + // refreshed + // update the zip entries with the data from the live ODF DOM + var data; + data = runtime.byteArrayFromString(serializeSettingsXml(), "utf8"); + zip.save("settings.xml", data, true, new Date()); + data = runtime.byteArrayFromString(serializeMetaXml(), "utf8"); + zip.save("meta.xml", data, true, new Date()); + data = runtime.byteArrayFromString(serializeStylesXml(), "utf8"); + zip.save("styles.xml", data, true, new Date()); + data = runtime.byteArrayFromString(serializeContentXml(), "utf8"); + zip.save("content.xml", data, true, new Date()); + zip.write(function (err) { + callback(err); + }); + }; + + // initialize public variables + this.state = OdfContainer.LOADING; + this.rootElement = createElement(ODFDocumentElement); + this.parts = new OdfPartList(this); + + // initialize private variables + zip = new core.Zip(url, function (err, zipobject) { + zip = zipobject; + if (err) { + loadFromXML(url, function (xmlerr) { + if (err) { + zip.error = err + "\n" + xmlerr; + setState(OdfContainer.INVALID); + } + }); + } else { + loadComponents(); + } + }); + }; + odf.OdfContainer.EMPTY = 0; + odf.OdfContainer.LOADING = 1; + odf.OdfContainer.DONE = 2; + odf.OdfContainer.INVALID = 3; + odf.OdfContainer.SAVING = 4; + odf.OdfContainer.MODIFIED = 5; + /** + * @param {!string} url + * @return {!odf.OdfContainer} + */ + odf.OdfContainer.getContainer = function (url) { + return new odf.OdfContainer(url, null); + }; + return odf.OdfContainer; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/odf/Style2CSS.js b/apps/files_odfviewer/src/webodf/webodf/lib/odf/Style2CSS.js new file mode 100644 index 0000000000..f33e3faef4 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/odf/Style2CSS.js @@ -0,0 +1,632 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global odf: true, runtime: true*/ +/** + * @constructor + */ +odf.Style2CSS = function Style2CSS() { + "use strict"; + // helper constants + var xlinkns = 'http://www.w3.org/1999/xlink', + drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", + fons = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", + officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", + presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", + stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0", + svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", + tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", + textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", + namespaces = { + "draw": drawns, + "fo": fons, + "office": officens, + "presentation": presentationns, + "style": stylens, + "svg": svgns, + "table": tablens, + "text": textns, + "xlink": xlinkns + }, + + familynamespaceprefixes = { + 'graphic': 'draw', + 'paragraph': 'text', + 'presentation': 'presentation', + 'ruby': 'text', + 'section': 'text', + 'table': 'table', + 'table-cell': 'table', + 'table-column': 'table', + 'table-row': 'table', + 'text': 'text', + 'list': 'text' + }, + + familytagnames = { + 'graphic': ['circle', 'connected', 'control', 'custom-shape', + 'ellipse', 'frame', 'g', 'line', 'measure', 'page', + 'page-thumbnail', 'path', 'polygon', 'polyline', 'rect', + 'regular-polygon' ], + 'paragraph': ['alphabetical-index-entry-template', 'h', + 'illustration-index-entry-template', 'index-source-style', + 'object-index-entry-template', 'p', + 'table-index-entry-template', 'table-of-content-entry-template', + 'user-index-entry-template'], + 'presentation': ['caption', 'circle', 'connector', 'control', + 'custom-shape', 'ellipse', 'frame', 'g', 'line', 'measure', + 'page-thumbnail', 'path', 'polygon', 'polyline', 'rect', + 'regular-polygon'], + 'ruby': ['ruby', 'ruby-text'], + 'section': ['alphabetical-index', 'bibliography', + 'illustration-index', 'index-title', 'object-index', 'section', + 'table-of-content', 'table-index', 'user-index'], + 'table': ['background', 'table'], + 'table-cell': ['body', 'covered-table-cell', 'even-columns', + 'even-rows', 'first-column', 'first-row', 'last-column', + 'last-row', 'odd-columns', 'odd-rows', 'table-cell'], + 'table-column': ['table-column'], + 'table-row': ['table-row'], + 'text': ['a', 'index-entry-chapter', 'index-entry-link-end', + 'index-entry-link-start', 'index-entry-page-number', + 'index-entry-span', 'index-entry-tab-stop', 'index-entry-text', + 'index-title-template', 'linenumbering-configuration', + 'list-level-style-number', 'list-level-style-bullet', + 'outline-level-style', 'span'], + 'list': ['list-item'] + }, + + textPropertySimpleMapping = [ + [ fons, 'color', 'color' ], + // this sets the element background, not just the text background + [ fons, 'background-color', 'background-color' ], + [ fons, 'font-weight', 'font-weight' ], + [ fons, 'font-style', 'font-style' ], + [ fons, 'font-size', 'font-size' ] + ], + + bgImageSimpleMapping = [ + [ stylens, 'repeat', 'background-repeat' ] + ], + + paragraphPropertySimpleMapping = [ + [ fons, 'background-color', 'background-color' ], + [ fons, 'text-align', 'text-align' ], + [ fons, 'padding-left', 'padding-left' ], + [ fons, 'padding-right', 'padding-right' ], + [ fons, 'padding-top', 'padding-top' ], + [ fons, 'padding-bottom', 'padding-bottom' ], + [ fons, 'border-left', 'border-left' ], + [ fons, 'border-right', 'border-right' ], + [ fons, 'border-top', 'border-top' ], + [ fons, 'border-bottom', 'border-bottom' ], + [ fons, 'margin-left', 'margin-left' ], + [ fons, 'margin-right', 'margin-right' ], + [ fons, 'margin-top', 'margin-top' ], + [ fons, 'margin-bottom', 'margin-bottom' ], + [ fons, 'border', 'border' ] + ], + + graphicPropertySimpleMapping = [ + [ drawns, 'fill-color', 'background-color' ], + [ drawns, 'fill', 'background' ], + [ fons, 'min-height', 'min-height' ], + [ drawns, 'stroke', 'border' ], + [ svgns, 'stroke-color', 'border-color' ] + ], + + tablecellPropertySimpleMapping = [ + [ fons, 'background-color', 'background-color' ], + [ fons, 'border-left', 'border-left' ], + [ fons, 'border-right', 'border-right' ], + [ fons, 'border-top', 'border-top' ], + [ fons, 'border-bottom', 'border-bottom' ] + ]; + + // helper functions + /** + * @param {string} prefix + * @return {string} + */ + function namespaceResolver(prefix) { + return namespaces[prefix] || null; + } + /** + * @param {!Document} doc + * @param {!Element} stylesnode + * @return {!Object} + */ + function getStyleMap(doc, stylesnode) { + // put all style elements in a hash map by family and name + var stylemap = {}, node, name, family, map; + if (!stylesnode) { + return stylemap; + } + node = stylesnode.firstChild; + while (node) { + if (node.namespaceURI === stylens && node.localName === 'style') { + family = node.getAttributeNS(stylens, 'family'); + } else if (node.namespaceURI === textns && + node.localName === 'list-style') { + family = "list"; + } + name = family && node.getAttributeNS && + node.getAttributeNS(stylens, 'name'); + if (name) { + if (!stylemap[family]) { + stylemap[family] = {}; + } + stylemap[family][name] = node; + } + node = node.nextSibling; + } + return stylemap; + } + /** + * @param {?Object} stylestree + * @param {?string} name + * @return {?string} + */ + function findStyle(stylestree, name) { + if (!name || !stylestree) { + return null; + } + if (stylestree[name]) { + return stylestree[name]; + } + var derivedStyles = stylestree.derivedStyles, + n, style; + for (n in stylestree) { + if (stylestree.hasOwnProperty(n)) { + style = findStyle(stylestree[n].derivedStyles, name); + if (style) { + return style; + } + } + } + return null; + } + /** + * @param {!string} stylename + * @param {!Object} stylesmap + * @param {!Object} stylestree + * @return {undefined} + */ + function addStyleToStyleTree(stylename, stylesmap, stylestree) { + var style = stylesmap[stylename], parentname, parentstyle; + if (!style) { + return; + } + parentname = style.getAttributeNS(stylens, 'parent-style-name'); + parentstyle = null; + if (parentname) { + parentstyle = findStyle(stylestree, parentname); + if (!parentstyle && stylesmap[parentname]) { + // parent style has not been handled yet, do that now + addStyleToStyleTree(parentname, stylesmap, stylestree); + parentstyle = stylesmap[parentname]; + stylesmap[parentname] = null; + } + } + if (parentstyle) { + if (!parentstyle.derivedStyles) { + parentstyle.derivedStyles = {}; + } + parentstyle.derivedStyles[stylename] = style; + } else { + // no parent so add the root + stylestree[stylename] = style; + } + } + /** + * @param {!Object} stylesmap + * @param {!Object} stylestree + * @return {undefined} + */ + function addStyleMapToStyleTree(stylesmap, stylestree) { + var name; + for (name in stylesmap) { + if (stylesmap.hasOwnProperty(name)) { + addStyleToStyleTree(name, stylesmap, stylestree); + stylesmap[name] = null; + } + } + } + /** + * @param {!string} family + * @param {!string} name + * @return {?string} + */ + function createSelector(family, name) { + var prefix = familynamespaceprefixes[family], + namepart, + selector = "", + first = true; + if (prefix === null) { + return null; + } + namepart = '[' + prefix + '|style-name="' + name + '"]'; + if (prefix === 'presentation') { + prefix = 'draw'; + namepart = '[presentation|style-name="' + name + '"]'; + } + return prefix + '|' + familytagnames[family].join( + namepart + ',' + prefix + '|') + namepart; + } + /** + * @param {!string} family + * @param {!string} name + * @param {!Element} node + * @return {!Array} + */ + function getSelectors(family, name, node) { + var selectors = [], n, ss, s; + selectors.push(createSelector(family, name)); + for (n in node.derivedStyles) { + if (node.derivedStyles.hasOwnProperty(n)) { + ss = getSelectors(family, n, node.derivedStyles[n]); + for (s in ss) { + if (ss.hasOwnProperty(s)) { + selectors.push(ss[s]); + } + } + } + } + return selectors; + } + /** + * @param {?Element} node + * @param {!string} ns + * @param {!string} name + * @return {?Element} + */ + function getDirectChild(node, ns, name) { + if (!node) { + return null; + } + var c = node.firstChild, e; + while (c) { + if (c.namespaceURI === ns && c.localName === name) { + e = /**@type{Element}*/(c); + return e; + } + c = c.nextSibling; + } + return null; + } + /** + * @param {!Element} props + * @param {!Object} mapping + * @return {!string} + */ + function applySimpleMapping(props, mapping) { + var rule = '', r, value; + for (r in mapping) { + if (mapping.hasOwnProperty(r)) { + r = mapping[r]; + value = props.getAttributeNS(r[0], r[1]); + if (value) { + rule += r[2] + ':' + value + ';'; + } + } + } + return rule; + } + /** + * @param {!string} name + * @return {!string} + */ + function getFontDeclaration(name) { + return '"' + name + '"'; + } + /** + * @param {!Element} props + * @return {!string} + */ + function getTextProperties(props) { + var rule = '', value; + rule += applySimpleMapping(props, textPropertySimpleMapping); + value = props.getAttributeNS(stylens, 'text-underline-style'); + if (value === 'solid') { + rule += 'text-decoration: underline;'; + } + value = props.getAttributeNS(stylens, 'font-name'); + if (value) { + value = getFontDeclaration(value); + if (value) { + rule += 'font-family: ' + value + ';'; + } + } + return rule; + } + /** + * @param {!Element} props + * @return {!string} + */ + function getParagraphProperties(props) { + var rule = '', imageProps, url, element; + rule += applySimpleMapping(props, paragraphPropertySimpleMapping); + imageProps = props.getElementsByTagNameNS(stylens, 'background-image'); + if (imageProps.length > 0) { + url = imageProps.item(0).getAttributeNS(xlinkns, 'href'); + if (url) { + rule += "background-image: url('odfkit:" + url + "');"; + //rule += "background-repeat: repeat;"; //FIXME test + element = /**@type{!Element}*/(imageProps.item(0)); + rule += applySimpleMapping(element, bgImageSimpleMapping); + } + } + return rule; + } + /** + * @param {!Element} props + * @return {!string} + */ + function getGraphicProperties(props) { + var rule = ''; + rule += applySimpleMapping(props, graphicPropertySimpleMapping); + return rule; + } + /** + * @param {!Element} props + * @return {!string} + */ + function getTableCellProperties(props) { + var rule = ''; + rule += applySimpleMapping(props, tablecellPropertySimpleMapping); + return rule; + } + /** + * @param {!StyleSheet} sheet + * @param {!string} family + * @param {!string} name + * @param {!Element} node + * @return {undefined} + */ + function addStyleRule(sheet, family, name, node) { + var selectors = getSelectors(family, name, node), + selector = selectors.join(','), + rule = '', + properties = getDirectChild(node, stylens, 'text-properties'); + if (properties) { + rule += getTextProperties(properties); + } + properties = getDirectChild(node, stylens, 'paragraph-properties'); + if (properties) { + rule += getParagraphProperties(properties); + } + properties = getDirectChild(node, stylens, 'graphic-properties'); + if (properties) { + rule += getGraphicProperties(properties); + } + properties = getDirectChild(node, stylens, 'table-cell-properties'); + if (properties) { + rule += getTableCellProperties(properties); + } + if (rule.length === 0) { + return; + } + rule = selector + '{' + rule + '}'; + try { + sheet.insertRule(rule, sheet.cssRules.length); + } catch (e) { + throw e; + } + } + /** + * @param {!Element} node + * @return {!string} + */ + function getNumberRule(node) { + var style = node.getAttributeNS(stylens, "num-format"), + suffix = node.getAttributeNS(stylens, "num-suffix"), + prefix = node.getAttributeNS(stylens, "num-prefix"), + rule = "", + stylemap = {'1': 'decimal', 'a': 'lower-latin', 'A': 'upper-latin', + 'i': 'lower-roman', 'I': 'upper-roman'}, + content = ""; + content = prefix || ""; + if (stylemap.hasOwnProperty(style)) { + content += " counter(list, " + stylemap[style] + ")"; + } else if (style) { + content += "'" + style + "';"; + } else { + content += " ''"; + } + if (suffix) { + content += " '" + suffix + "'"; + } + rule = "content: " + content + ";"; + return rule; + } + /** + * @param {!Element} node + * @return {!string} + */ + function getImageRule(node) { + var rule = "content: none;"; + return rule; + } + /** + * @param {!Element} node + * @return {!string} + */ + function getBulletRule(node) { + var rule = "", + bulletChar = node.getAttributeNS(textns, "bullet-char"); + return "content: '" + bulletChar + "';"; + } + /** + * @param {!StyleSheet} sheet + * @param {!string} name + * @param {!Element} node + * @return {undefined} + */ + function addListStyleRule(sheet, name, node, itemrule) { + var selector = 'text|list[text|style-name="' + name + + '"]', + level = node.getAttributeNS(textns, "level"), + rule = ""; + level = level && parseInt(level, 10); + while (level > 1) { + selector += " > text|list-item > text|list"; + level -= 1; + } + selector += " > list-item:before"; + rule = itemrule; + rule = selector + '{' + rule + '}'; + try { + sheet.insertRule(rule, sheet.cssRules.length); + } catch (e) { + throw e; + } + } + /** + * @param {!StyleSheet} sheet + * @param {!string} name + * @param {!Element} node + * @return {undefined} + */ + function addListStyleRules(sheet, name, node) { + var n = node.firstChild, e, itemrule; + while (n) { + if (n.namespaceURI === textns) { + e = /**@type{!Element}*/(n); + if (n.localName === "list-level-style-number") { + itemrule = getNumberRule(e); + addListStyleRule(sheet, name, e, itemrule); + } else if (n.localName === "list-level-style-image") { + itemrule = getImageRule(e); + addListStyleRule(sheet, name, e, itemrule); + } else if (n.localName === "list-level-style-bullet") { + itemrule = getBulletRule(e); + addListStyleRule(sheet, name, e, itemrule); + } + } + n = n.nextSibling; + } + } + /** + * @param {!StyleSheet} sheet + * @param {!string} family + * @param {!string} name + * @param {!Element} node + * @return {undefined} + */ + function addRule(sheet, family, name, node) { + if (family === "list") { + addListStyleRules(sheet, name, node); + } else { + addStyleRule(sheet, family, name, node); + } + } + /** + * @param {!StyleSheet} sheet + * @param {!string} family + * @param {!string} name + * @param {!Element} node + * @return {undefined} + */ + function addRules(sheet, family, name, node) { + addRule(sheet, family, name, node); + var n; + for (n in node.derivedStyles) { + if (node.derivedStyles.hasOwnProperty(n)) { + addRules(sheet, family, n, node.derivedStyles[n]); + } + } + } + + // css vs odf styles + // ODF styles occur in families. A family is a group of odf elements to + // which an element applies. ODF families can be mapped to a group of css + // elements + + this.namespaces = namespaces; + this.namespaceResolver = namespaceResolver; + this.namespaceResolver.lookupNamespaceURI = this.namespaceResolver; + + /** + * @param {!StyleSheet} stylesheet + * @param {!Element} styles + * @param {!Element} autostyles + * @return {undefined} + */ + this.style2css = function (stylesheet, styles, autostyles) { + var doc, prefix, styletree, tree, name, rule, family, + stylenodes, styleautonodes; + // make stylesheet empty + while (stylesheet.cssRules.length) { + stylesheet.deleteRule(stylesheet.cssRules.length - 1); + } + doc = null; + if (styles) { + doc = styles.ownerDocument; + } + if (autostyles) { + doc = autostyles.ownerDocument; + } + if (!doc) { + return; + } + // add @namespace rules + for (prefix in namespaces) { + if (namespaces.hasOwnProperty(prefix)) { + rule = '@namespace ' + prefix + ' url(' + namespaces[prefix] + ');'; + try { + stylesheet.insertRule(rule, stylesheet.cssRules.length); + } catch (e) { + // WebKit can throw an exception here, but it will have + // retained the namespace declarations anyway. + } + } + } + + // add the various styles + stylenodes = getStyleMap(doc, styles); + styleautonodes = getStyleMap(doc, autostyles); + styletree = {}; + for (family in familynamespaceprefixes) { + if (familynamespaceprefixes.hasOwnProperty(family)) { + tree = styletree[family] = {}; + addStyleMapToStyleTree(stylenodes[family], tree); + addStyleMapToStyleTree(styleautonodes[family], tree); + + for (name in tree) { + if (tree.hasOwnProperty(name)) { + addRules(stylesheet, family, name, tree[name]); + } + } + } + } + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/odf/StyleInfo.js b/apps/files_odfviewer/src/webodf/webodf/lib/odf/StyleInfo.js new file mode 100644 index 0000000000..9b76d13bed --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/odf/StyleInfo.js @@ -0,0 +1,424 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global odf*/ +/** + * @constructor + */ +odf.StyleInfo = function StyleInfo() { + "use strict"; + // helper constants + var chartns = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0", + dbns = "urn:oasis:names:tc:opendocument:xmlns:database:1.0", + dr3dns = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", + drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", + fons = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", + formns = "urn:oasis:names:tc:opendocument:xmlns:form:1.0", + numberns = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", + officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0", + presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", + stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0", + svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", + tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0", + textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0", + elementstyles = { + "text": [ + { ens: stylens, en: 'tab-stop', ans: stylens, a: 'leader-text-style'}, + { ens: stylens, en: 'drop-cap', ans: stylens, a: 'style-name'}, + { ens: textns, en: 'notes-configuration', ans: textns, a: 'citation-body-style-name'}, + { ens: textns, en: 'notes-configuration', ans: textns, a: 'citation-style-name'}, + { ens: textns, en: 'a', ans: textns, a: 'style-name'}, + { ens: textns, en: 'alphabetical-index', ans: textns, a: 'style-name'}, + { ens: textns, en: 'linenumbering-configuration', ans: textns, a: 'style-name'}, + { ens: textns, en: 'list-level-style-number', ans: textns, a: 'style-name'}, + { ens: textns, en: 'ruby-text', ans: textns, a: 'style-name'}, + { ens: textns, en: 'span', ans: textns, a: 'style-name'}, + { ens: textns, en: 'a', ans: textns, a: 'visited-style-name'}, + { ens: stylens, en: 'text-properties', ans: stylens, a: 'text-line-through-text-style'}, + { ens: textns, en: 'alphabetical-index-source', ans: textns, a: 'main-entry-style-name'}, + { ens: textns, en: 'index-entry-bibliography', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-chapter', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-link-end', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-link-start', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-page-number', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-span', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-tab-stop', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-entry-text', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-title-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'list-level-style-bullet', ans: textns, a: 'style-name'}, + { ens: textns, en: 'outline-level-style', ans: textns, a: 'style-name'} + ], + "paragraph": [ + { ens: drawns, en: 'caption', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'circle', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'connector', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'control', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'custom-shape', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'ellipse', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'frame', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'line', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'measure', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'path', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'polygon', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'polyline', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'rect', ans: drawns, a: 'text-style-name'}, + { ens: drawns, en: 'regular-polygon', ans: drawns, a: 'text-style-name'}, + { ens: officens, en: 'annotation', ans: drawns, a: 'text-style-name'}, + { ens: formns, en: 'column', ans: formns, a: 'text-style-name'}, + { ens: stylens, en: 'style', ans: stylens, a: 'next-style-name'}, + { ens: tablens, en: 'body', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'even-columns', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'even-rows', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'first-column', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'first-row', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'last-column', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'last-row', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'odd-columns', ans: tablens, a: 'paragraph-style-name'}, + { ens: tablens, en: 'odd-rows', ans: tablens, a: 'paragraph-style-name'}, + { ens: textns, en: 'notes-configuration', ans: textns, a: 'default-style-name'}, + { ens: textns, en: 'alphabetical-index-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'bibliography-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'h', ans: textns, a: 'style-name'}, + { ens: textns, en: 'illustration-index-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-source-style', ans: textns, a: 'style-name'}, + { ens: textns, en: 'object-index-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'p', ans: textns, a: 'style-name'}, + { ens: textns, en: 'table-index-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'table-of-content-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'table-index-entry-template', ans: textns, a: 'style-name'}, + { ens: textns, en: 'user-index-entry-template', ans: textns, a: 'style-name'}, + { ens: stylens, en: 'page-layout-properties', ans: stylens, a: 'register-truth-ref-style-name'} + ], + "chart": [ + { ens: chartns, en: 'axis', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'chart', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'data-label', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'data-point', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'equation', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'error-indicator', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'floor', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'footer', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'grid', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'legend', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'mean-value', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'plot-area', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'regression-curve', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'series', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'stock-gain-marker', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'stock-loss-marker', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'stock-range-line', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'subtitle', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'title', ans: chartns, a: 'style-name'}, + { ens: chartns, en: 'wall', ans: chartns, a: 'style-name'} + ], + "section": [ + { ens: textns, en: 'alphabetical-index', ans: textns, a: 'style-name'}, + { ens: textns, en: 'bibliography', ans: textns, a: 'style-name'}, + { ens: textns, en: 'illustration-index', ans: textns, a: 'style-name'}, + { ens: textns, en: 'index-title', ans: textns, a: 'style-name'}, + { ens: textns, en: 'object-index', ans: textns, a: 'style-name'}, + { ens: textns, en: 'section', ans: textns, a: 'style-name'}, + { ens: textns, en: 'table-of-content', ans: textns, a: 'style-name'}, + { ens: textns, en: 'table-index', ans: textns, a: 'style-name'}, + { ens: textns, en: 'user-index', ans: textns, a: 'style-name'} + ], + "ruby": [ + { ens: textns, en: 'ruby', ans: textns, a: 'style-name'} + ], + "table": [ + { ens: dbns, en: 'query', ans: dbns, a: 'style-name'}, + { ens: dbns, en: 'table-representation', ans: dbns, a: 'style-name'}, + { ens: tablens, en: 'background', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'table', ans: tablens, a: 'style-name'} + ], + "table-column": [ + { ens: dbns, en: 'column', ans: dbns, a: 'style-name'}, + { ens: tablens, en: 'table-column', ans: tablens, a: 'style-name'} + ], + "table-row": [ + { ens: dbns, en: 'query', ans: dbns, a: 'default-row-style-name'}, + { ens: dbns, en: 'table-representation', ans: dbns, a: 'default-row-style-name'}, + { ens: tablens, en: 'table-row', ans: tablens, a: 'style-name'} + ], + "table-cell": [ + { ens: dbns, en: 'column', ans: dbns, a: 'default-cell-style-name'}, + { ens: tablens, en: 'table-column', ans: tablens, a: 'default-cell-style-name'}, + { ens: tablens, en: 'table-row', ans: tablens, a: 'default-cell-style-name'}, + { ens: tablens, en: 'body', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'covered-table-cell', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'even-columns', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'covered-table-cell', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'even-columns', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'even-rows', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'first-column', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'first-row', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'last-column', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'last-row', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'odd-columns', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'odd-rows', ans: tablens, a: 'style-name'}, + { ens: tablens, en: 'table-cell', ans: tablens, a: 'style-name'} + ], + "graphic": [ + { ens: dr3dns, en: 'cube', ans: drawns, a: 'style-name'}, + { ens: dr3dns, en: 'extrude', ans: drawns, a: 'style-name'}, + { ens: dr3dns, en: 'rotate', ans: drawns, a: 'style-name'}, + { ens: dr3dns, en: 'scene', ans: drawns, a: 'style-name'}, + { ens: dr3dns, en: 'sphere', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'caption', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'circle', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'connector', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'control', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'custom-shape', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'ellipse', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'frame', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'g', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'line', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'measure', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'page-thumbnail', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'path', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'polygon', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'polyline', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'rect', ans: drawns, a: 'style-name'}, + { ens: drawns, en: 'regular-polygon', ans: drawns, a: 'style-name'}, + { ens: officens, en: 'annotation', ans: drawns, a: 'style-name'} + ], + "presentation": [ + { ens: dr3dns, en: 'cube', ans: presentationns, a: 'style-name'}, + { ens: dr3dns, en: 'extrude', ans: presentationns, a: 'style-name'}, + { ens: dr3dns, en: 'rotate', ans: presentationns, a: 'style-name'}, + { ens: dr3dns, en: 'scene', ans: presentationns, a: 'style-name'}, + { ens: dr3dns, en: 'sphere', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'caption', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'circle', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'connector', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'control', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'custom-shape', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'ellipse', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'frame', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'g', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'line', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'measure', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'page-thumbnail', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'path', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'polygon', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'polyline', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'rect', ans: presentationns, a: 'style-name'}, + { ens: drawns, en: 'regular-polygon', ans: presentationns, a: 'style-name'}, + { ens: officens, en: 'annotation', ans: presentationns, a: 'style-name'} + ], + "drawing-page": [ + { ens: drawns, en: 'page', ans: drawns, a: 'style-name'}, + { ens: presentationns, en: 'notes', ans: drawns, a: 'style-name'}, + { ens: stylens, en: 'handout-master', ans: drawns, a: 'style-name'}, + { ens: stylens, en: 'master-page', ans: drawns, a: 'style-name'} + ], + "list-style": [ + { ens: textns, en: 'list', ans: textns, a: 'style-name'}, + { ens: textns, en: 'numbered-paragraph', ans: textns, a: 'style-name'}, + { ens: textns, en: 'list-item', ans: textns, a: 'style-override'}, + { ens: stylens, en: 'style', ans: stylens, a: 'list-style-name'}, + { ens: stylens, en: 'style', ans: stylens, a: 'data-style-name'}, + { ens: stylens, en: 'style', ans: stylens, a: 'percentage-data-style-name'}, + { ens: presentationns, en: 'date-time-decl', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'creation-date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'creation-time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'database-display', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'editing-duration', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'expression', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'meta-field', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'modification-date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'modification-time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'print-date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'print-time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'table-formula', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'user-defined', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'user-field-get', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'user-field-input', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'variable-get', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'variable-input', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'variable-set', ans: stylens, a: 'data-style-name'} + ], + "data": [ + { ens: stylens, en: 'style', ans: stylens, a: 'data-style-name'}, + { ens: stylens, en: 'style', ans: stylens, a: 'percentage-data-style-name'}, + { ens: presentationns, en: 'date-time-decl', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'creation-date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'creation-time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'database-display', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'editing-duration', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'expression', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'meta-field', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'modification-date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'modification-time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'print-date', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'print-time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'table-formula', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'time', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'user-defined', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'user-field-get', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'user-field-input', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'variable-get', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'variable-input', ans: stylens, a: 'data-style-name'}, + { ens: textns, en: 'variable-set', ans: stylens, a: 'data-style-name'} + ], + "page-layout": [ + { ens: presentationns, en: 'notes', ans: stylens, a: 'page-layout-name'}, + { ens: stylens, en: 'handout-master', ans: stylens, a: 'page-layout-name'}, + { ens: stylens, en: 'master-page', ans: stylens, a: 'page-layout-name'} + ] + }, + elements; + + /** + * Return if a particular element can have a style for a particular family. + * @param {!string} family + * @param {!Element} element + * @return {!boolean} + */ + function canElementHaveStyle(family, element) { + var elname = elements[element.localName], + elns = elname && elname[element.namespaceURI], + length = elns ? elns.length : 0, + i; + return elns && elns.length > 0; + } + + /** + * @param {!string} family + * @param {!Element} element + * @return {{name:string,family:string}|null} + */ + function getStyleRef(family, element) { + var elname = elements[element.localName], + elns = elname && elname[element.namespaceURI], + length = elns ? elns.length : 0, + i, attr; + for (i = 0; i < length; i += 1) { + attr = element.getAttributeNS(elns[i].ns, elns[i].localname); +/* + if (attr) { // a style has been found! + return attr; + } +*/ + } + return null; + } + + /** + * @param {!Element} element + * @param {!Object.>} keys + * @return {undefined} + */ + function getUsedStylesForAutomatic(element, keys) { + var elname = elements[element.localName], + elns = elname && elname[element.namespaceURI], + length = elns ? elns.length : 0, + i, attr, group, map, e; + for (i = 0; i < length; i += 1) { + attr = element.getAttributeNS(elns[i].ns, elns[i].localname); + if (attr) { // a style has been found! + group = elns[i].keygroup; + map = keys[group]; + if (!map) { + map = keys[group] = {}; + } + map[attr] = 1; + } + } + i = element.firstChild; + while (i) { + if (i.nodeType === 1) { + e = /**@type{!Element}*/(i); + getUsedStylesForAutomatic(e, keys); + } + i = i.nextSibling; + } + } + + /** + * @param {!Object.>>} elementstyles + */ + function inverse(elementstyles) { + var keyname, i, list, item, l, elements = {}, map, array; + for (keyname in elementstyles) { + if (elementstyles.hasOwnProperty(keyname)) { + list = elementstyles[keyname]; + l = list.length; + for (i = 0; i < l; i += 1) { + item = list[i]; + map = elements[item.en] = elements[item.en] || {}; + array = map[item.ens] = map[item.ens] || []; + array.push( + {ns: item.ans, localname: item.a, keygroup: keyname}); + } + } + } + return elements; + } + + /** + * @constructor + * @param {!Element} element + */ + this.UsedKeysList = function (element) { + var usedKeys = {}; + + /** + * @param {!Element} element + * @return {!boolean} + */ + this.uses = function (element) { + var localName = element.localName, + name = element.getAttributeNS(drawns, "name") || + element.getAttributeNS(stylens, "name"), + keyName, map; + if (localName === "style") { + keyName = element.getAttributeNS(stylens, "family"); + } else if (element.namespaceURI === numberns) { + keyName = "data"; + } else { + keyName = localName; // list-style or page-layout + } + map = usedKeys[keyName]; + return map ? (map[name] > 0) : false; + }; + + getUsedStylesForAutomatic(element, usedKeys); + }; + + this.canElementHaveStyle = canElementHaveStyle; + + elements = inverse(elementstyles); +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/packages.js b/apps/files_odfviewer/src/webodf/webodf/lib/packages.js new file mode 100644 index 0000000000..7277a833f9 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/packages.js @@ -0,0 +1,48 @@ +/** + * @license + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/** + * @namespace The core package. + */ +var core = {}; +/** + * @namespace The gui package. + */ +var gui = {}; +/** + * @namespace The xmldom package. + */ +var xmldom = {}; +/** + * @namespace The ODF package. + */ +var odf = {}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/runtime.js b/apps/files_odfviewer/src/webodf/webodf/lib/runtime.js new file mode 100644 index 0000000000..99ded6f1d3 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/runtime.js @@ -0,0 +1,1117 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*jslint nomen: true, evil: true, bitwise: true */ +/*global window: true, XMLHttpRequest: true, require: true, console: true, + process: true, __dirname: true, setTimeout: true, Packages: true, print: true, + readFile: true, quit: true, Buffer: true, ArrayBuffer: true, Uint8Array: true, + navigator: true, VBArray: true */ +/** + * Three implementations of a runtime for browser, node.js and rhino. + */ + +/** + * Abstraction of the runtime environment. + * @class + * @interface + */ +function Runtime() {"use strict"; } +/** + * Abstraction of byte arrays. + * @constructor + * @extends {Array} + * @param {!number} size + */ +Runtime.ByteArray = function (size) {"use strict"; }; +/** + * @param {!number} start + * @param {!number} end + * @return {!Runtime.ByteArray} + */ +Runtime.ByteArray.prototype.slice = function (start, end) {"use strict"; }; +/** + * @param {!Array.} array + * @return {!Runtime.ByteArray} + */ +Runtime.prototype.byteArrayFromArray = function (array) {"use strict"; }; +/** + * @param {!string} string + * @param {!string} encoding + * @return {!Runtime.ByteArray} + */ +Runtime.prototype.byteArrayFromString = function (string, encoding) {"use strict"; }; +/** + * @param {!Runtime.ByteArray} bytearray + * @param {!string} encoding + * @return {!string} + */ +Runtime.prototype.byteArrayToString = function (bytearray, encoding) {"use strict"; }; +/** + * @param {!Runtime.ByteArray} bytearray1 + * @param {!Runtime.ByteArray} bytearray2 + * @return {!Runtime.ByteArray} + */ +Runtime.prototype.concatByteArrays = function (bytearray1, bytearray2) {"use strict"; }; +/** + * @param {!string} path + * @param {!number} offset + * @param {!number} length + * @param {!function(string,Runtime.ByteArray):undefined} callback + * @return {undefined} + */ +Runtime.prototype.read = function (path, offset, length, callback) {"use strict"; }; +/** + * Read the contents of a file. Returns the result via a callback. If the + * encoding is 'binary', the result is returned as a Runtime.ByteArray, + * otherwise, it is returned as a string. + * @param {!string} path + * @param {!string} encoding text encoding or 'binary' + * @param {!function(string,(string|Runtime.ByteArray)):undefined} callback + * @return {undefined} + */ +Runtime.prototype.readFile = function (path, encoding, callback) {"use strict"; }; +/** + * @param {!string} path + * @param {!string} encoding text encoding or 'binary' + * @return {!string} + */ +Runtime.prototype.readFileSync = function (path, encoding) {"use strict"; }; +/** + * @param {!string} path + * @param {!function((string|Document)):undefined} callback + * @return {undefined} + */ +Runtime.prototype.loadXML = function (path, callback) {"use strict"; }; +/** + * @param {!string} path + * @param {!Runtime.ByteArray} data + * @param {!function(?string):undefined} callback + * @return {undefined} + */ +Runtime.prototype.writeFile = function (path, data, callback) {"use strict"; }; +/** + * @param {!string} path + * @param {!function(boolean):undefined} callback + * @return {undefined} + */ +Runtime.prototype.isFile = function (path, callback) {"use strict"; }; +/** + * @param {!string} path + * @param {!function(number):undefined} callback + * @return {undefined} + */ +Runtime.prototype.getFileSize = function (path, callback) {"use strict"; }; +/** + * @param {!string} path + * @param {!function(?string):undefined} callback + * @return {undefined} + */ +Runtime.prototype.deleteFile = function (path, callback) {"use strict"; }; +/** + * @param {!string} msgOrCategory + * @param {!string=} msg + * @return {undefined} + */ +Runtime.prototype.log = function (msgOrCategory, msg) {"use strict"; }; +/** + * @param {!function():undefined} callback + * @param {!number} milliseconds + * @return {undefined} + */ +Runtime.prototype.setTimeout = function (callback, milliseconds) {"use strict"; }; +/** + * @return {!Array.} + */ +Runtime.prototype.libraryPaths = function () {"use strict"; }; +/** + * @return {string} + */ +Runtime.prototype.type = function () {"use strict"; }; +/** + * @return {?DOMImplementation} + */ +Runtime.prototype.getDOMImplementation = function () {"use strict"; }; +/** + * @return {?Window} + */ +Runtime.prototype.getWindow = function () {"use strict"; }; + +/** @define {boolean} */ +var IS_COMPILED_CODE = false; + +/** + * @this {Runtime} + * @param {!Runtime.ByteArray} bytearray + * @param {!string} encoding + * @return {!string} + */ +Runtime.byteArrayToString = function (bytearray, encoding) { + "use strict"; + function byteArrayToString(bytearray) { + var s = "", i, l = bytearray.length; + for (i = 0; i < l; i += 1) { + s += String.fromCharCode(bytearray[i] & 0xff); + } + return s; + } + function utf8ByteArrayToString(bytearray) { + var s = "", i, l = bytearray.length, + c0, c1, c2; + for (i = 0; i < l; i += 1) { + c0 = bytearray[i]; + if (c0 < 0x80) { + s += String.fromCharCode(c0); + } else { + i += 1; + c1 = bytearray[i]; + if (c0 < 0xe0) { + s += String.fromCharCode(((c0 & 0x1f) << 6) | (c1 & 0x3f)); + } else { + i += 1; + c2 = bytearray[i]; + s += String.fromCharCode(((c0 & 0x0f) << 12) | + ((c1 & 0x3f) << 6) | (c2 & 0x3f)); + } + } + } + return s; + } + var result; + if (encoding === "utf8") { + result = utf8ByteArrayToString(bytearray); + } else { + if (encoding !== "binary") { + this.log("Unsupported encoding: " + encoding); + } + result = byteArrayToString(bytearray); + } + return result; +}; +Runtime.getFunctionName = function getFunctionName(f) { + "use strict"; + var m; + if (f.name === undefined) { + m = new RegExp("function\\s+(\\w+)").exec(f); + return m && m[1]; + } + return f.name; +}; +/** + * @class + * @constructor + * @augments Runtime + * @implements {Runtime} + * @param {Element} logoutput + */ +function BrowserRuntime(logoutput) { + "use strict"; + var self = this, + cache = {}, + useNativeArray = window.ArrayBuffer && window.Uint8Array; + /** + * @constructor + * @augments Runtime.ByteArray + * @inner + * @extends {Runtime.ByteArray} + * @param {!number} size + */ + this.ByteArray = (useNativeArray) + // if Uint8Array is available, use that + ? function ByteArray(size) { + Uint8Array.prototype.slice = function (begin, end) { + if (end === undefined) { + if (begin === undefined) { + begin = 0; + } + end = this.length; + } + var view = this.subarray(begin, end), array, i; + end -= begin; + array = new Uint8Array(new ArrayBuffer(end)); + for (i = 0; i < end; i += 1) { + array[i] = view[i]; + } + return array; + }; + return new Uint8Array(new ArrayBuffer(size)); + } + : function ByteArray(size) { + var a = []; + a.length = size; + return a; + }; + this.concatByteArrays = (useNativeArray) + ? function (bytearray1, bytearray2) { + var i, l1 = bytearray1.length, l2 = bytearray2.length, + a = new this.ByteArray(l1 + l2); + for (i = 0; i < l1; i += 1) { + a[i] = bytearray1[i]; + } + for (i = 0; i < l2; i += 1) { + a[i + l1] = bytearray2[i]; + } + return a; + } + : function (bytearray1, bytearray2) { + return bytearray1.concat(bytearray2); + }; + function utf8ByteArrayFromString(string) { + var l = string.length, bytearray, i, n, j = 0; + // first determine the length in bytes + for (i = 0; i < l; i += 1) { + n = string.charCodeAt(i); + j += 1 + (n > 0x80) + (n > 0x800); + } + // allocate a buffer and convert to a utf8 array + bytearray = new self.ByteArray(j); + j = 0; + for (i = 0; i < l; i += 1) { + n = string.charCodeAt(i); + if (n < 0x80) { + bytearray[j] = n; + j += 1; + } else if (n < 0x800) { + bytearray[j] = 0xc0 | (n >>> 6); + bytearray[j + 1] = 0x80 | (n & 0x3f); + j += 2; + } else { + bytearray[j] = 0xe0 | ((n >>> 12) & 0x0f); + bytearray[j + 1] = 0x80 | ((n >>> 6) & 0x3f); + bytearray[j + 2] = 0x80 | (n & 0x3f); + j += 3; + } + } + return bytearray; + } + function byteArrayFromString(string) { + // ignore encoding for now + var l = string.length, + a = new self.ByteArray(l), + i; + for (i = 0; i < l; i += 1) { + a[i] = string.charCodeAt(i) & 0xff; + } + return a; + } + this.byteArrayFromArray = function (array) { + return array.slice(); + }; + this.byteArrayFromString = function (string, encoding) { + var result; + if (encoding === "utf8") { + result = utf8ByteArrayFromString(string); + } else { + if (encoding !== "binary") { + self.log("unknown encoding: " + encoding); + } + result = byteArrayFromString(string); + } + return result; + }; + this.byteArrayToString = Runtime.byteArrayToString; + + /** + * @param {!string} msgOrCategory + * @param {string=} msg + * @return {undefined} + */ + function log(msgOrCategory, msg) { + var node, doc, category; + if (msg) { + category = msgOrCategory; + } else { + msg = msgOrCategory; + } + if (logoutput) { + doc = logoutput.ownerDocument; + if (category) { + node = doc.createElement("span"); + node.className = category; + node.appendChild(doc.createTextNode(category)); + logoutput.appendChild(node); + logoutput.appendChild(doc.createTextNode(" ")); + } + node = doc.createElement("span"); + node.appendChild(doc.createTextNode(msg)); + logoutput.appendChild(node); + logoutput.appendChild(doc.createElement("br")); + } else if (console) { + console.log(msg); + } + } + function readFile(path, encoding, callback) { + if (cache.hasOwnProperty(path)) { + callback(null, cache[path]); + return; + } + var xhr = new XMLHttpRequest(); + function handleResult() { + var data; + if (xhr.readyState === 4) { + if (xhr.status === 0 && !xhr.responseText) { + // for local files there is no difference between missing + // and empty files, so empty files are considered as errors + callback("File " + path + " is empty."); + } else if (xhr.status === 200 || xhr.status === 0) { + // report file + if (encoding === "binary") { + if (typeof VBArray !== "undefined") { // IE9 + data = new VBArray(xhr.responseBody).toArray(); + } else { + data = self.byteArrayFromString(xhr.responseText, + "binary"); + } + } else { + data = xhr.responseText; + } + cache[path] = data; + callback(null, data); + } else { + // report error + callback(xhr.responseText || xhr.statusText); + } + } + } + xhr.open('GET', path, true); + xhr.onreadystatechange = handleResult; + if (xhr.overrideMimeType) { + if (encoding !== "binary") { + xhr.overrideMimeType("text/plain; charset=" + encoding); + } else { + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + } + } + try { + xhr.send(null); + } catch (e) { + callback(e.message); + } + } + function read(path, offset, length, callback) { + if (cache.hasOwnProperty(path)) { + callback(null, cache[path].slice(offset, offset + length)); + return; + } + var xhr = new XMLHttpRequest(); + function handleResult() { + var data; + if (xhr.readyState === 4) { + if (xhr.status === 0 && !xhr.responseText) { + // for local files there is no difference between missing + // and empty files, so empty files are considered as errors + callback("File " + path + " is empty."); + } else if (xhr.status === 200 || xhr.status === 0) { + // report file + if (typeof VBArray !== "undefined") { + data = new VBArray(xhr.responseBody).toArray(); + } else { + data = self.byteArrayFromString(xhr.responseText, "binary"); + } + cache[path] = data; + callback(null, data.slice(offset, offset + length)); + } else { + // report error + callback(xhr.responseText || xhr.statusText); + } + } + } + xhr.open('GET', path, true); + xhr.onreadystatechange = handleResult; + if (xhr.overrideMimeType) { + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + } + //xhr.setRequestHeader('Range', 'bytes=' + offset + '-' + + // (offset + length - 1)); + try { + xhr.send(null); + } catch (e) { + callback(e.message); + } + } + function readFileSync(path, encoding) { + var xhr = new XMLHttpRequest(), + result; + xhr.open('GET', path, false); + if (xhr.overrideMimeType) { + if (encoding !== "binary") { + xhr.overrideMimeType("text/plain; charset=" + encoding); + } else { + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + } + } + try { + xhr.send(null); + if (xhr.status === 200 || xhr.status === 0) { + result = xhr.responseText; + } + } catch (e) { + } + return result; + } + function writeFile(path, data, callback) { + cache[path] = data; + var xhr = new XMLHttpRequest(); + function handleResult() { + if (xhr.readyState === 4) { + if (xhr.status === 0 && !xhr.responseText) { + // for local files there is no difference between missing + // and empty files, so empty files are considered as errors + callback("File " + path + " is empty."); + } else if ((xhr.status >= 200 && xhr.status < 300) || + xhr.status === 0) { + // report success + callback(null); + } else { + // report error + callback("Status " + String(xhr.status) + ": " + + xhr.responseText || xhr.statusText); + } + } + } + xhr.open('PUT', path, true); + xhr.onreadystatechange = handleResult; + // ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send() + // an ArrayBuffer, In Firefox, one must use sendAsBinary with a string + if (data.buffer && !xhr.sendAsBinary) { + data = data.buffer; // webkit supports sending an ArrayBuffer + } else { + // encode into a string, this works in FireFox >= 3 + data = self.byteArrayToString(data, "binary"); + } + try { + if (xhr.sendAsBinary) { + xhr.sendAsBinary(data); + } else { + xhr.send(data); + } + } catch (e) { + self.log("HUH? " + e + " " + data); + callback(e.message); + } + } + function deleteFile(path, callback) { + var xhr = new XMLHttpRequest(); + xhr.open('DELETE', path, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status < 200 && xhr.status >= 300) { + callback(xhr.responseText); + } else { + callback(null); + } + } + }; + xhr.send(null); + } + function loadXML(path, callback) { + var xhr = new XMLHttpRequest(); + function handleResult() { + if (xhr.readyState === 4) { + if (xhr.status === 0 && !xhr.responseText) { + callback("File " + path + " is empty."); + } else if (xhr.status === 200 || xhr.status === 0) { + // report file + callback(null, xhr.responseXML); + } else { + // report error + callback(xhr.responseText); + } + } + } + xhr.open("GET", path, true); + if (xhr.overrideMimeType) { + xhr.overrideMimeType("text/xml"); + } + xhr.onreadystatechange = handleResult; + try { + xhr.send(null); + } catch (e) { + callback(e.message); + } + } + function isFile(path, callback) { + self.getFileSize(path, function (size) { + callback(size !== -1); + }); + } + function getFileSize(path, callback) { + var xhr = new XMLHttpRequest(); + xhr.open("HEAD", path, true); + xhr.onreadystatechange = function () { + if (xhr.readyState !== 4) { + return; + } + var cl = xhr.getResponseHeader("Content-Length"); + if (cl) { + callback(parseInt(cl, 10)); + } else { + callback(-1); + } + }; + xhr.send(null); + } + function wrap(nativeFunction, nargs) { + if (!nativeFunction) { + return null; + } + return function () { + // clear cache + cache = {}; + // assume the last argument is a callback function + var callback = arguments[nargs], + args = Array.prototype.slice.call(arguments, 0, nargs), + callbackname = "callback" + String(Math.random()).substring(2); + window[callbackname] = function () { + delete window[callbackname]; + callback.apply(this, arguments); + }; + args.push(callbackname); + nativeFunction.apply(this, args); + }; + } + this.readFile = readFile; + this.read = read; + this.readFileSync = readFileSync; + this.writeFile = writeFile; + this.deleteFile = deleteFile; + this.loadXML = loadXML; + this.isFile = isFile; + this.getFileSize = getFileSize; + this.log = log; + this.setTimeout = function (f, msec) { + setTimeout(function () { + f(); + }, msec); + }; + this.libraryPaths = function () { + return ["lib"]; // TODO: find a good solution + // probably let html app specify it + }; + this.setCurrentDirectory = function (dir) { + }; + this.type = function () { + return "BrowserRuntime"; + }; + this.getDOMImplementation = function () { + return window.document.implementation; + }; + this.exit = function (exitCode) { + log("Calling exit with code " + String(exitCode) + + ", but exit() is not implemented."); + }; + this.getWindow = function () { + return window; + }; +} + +/** + * @constructor + * @implements {Runtime} + */ +function NodeJSRuntime() { + "use strict"; + var self = this, + fs = require('fs'), + currentDirectory = ""; + + /** + * @constructor + * @extends {Runtime.ByteArray} + * @param {!number} size + */ + this.ByteArray = function (size) { + return new Buffer(size); + }; + + this.byteArrayFromArray = function (array) { + var ba = new Buffer(array.length), + i, + l = array.length; + for (i = 0; i < l; i += 1) { + ba[i] = array[i]; + } + return ba; + }; + + this.concatByteArrays = function (a, b) { + var ba = new Buffer(a.length + b.length); + a.copy(ba, 0, 0); + b.copy(ba, a.length, 0); + return ba; + }; + + this.byteArrayFromString = function (string, encoding) { + return new Buffer(string, encoding); + }; + + this.byteArrayToString = function (bytearray, encoding) { + return bytearray.toString(encoding); + }; + + function isFile(path, callback) { + if (currentDirectory) { + path = currentDirectory + "/" + path; + } + fs.stat(path, function (err, stats) { + callback(!err && stats.isFile()); + }); + } + function loadXML(path, callback) { + throw "Not implemented."; + } + this.readFile = function (path, encoding, callback) { + if (encoding !== "binary") { + fs.readFile(path, encoding, callback); + } else { + fs.readFile(path, null, callback); +/* + // we have to encode the returned buffer to a string + // it would be nice if we would have a blob or buffer object + fs.readFile(path, null, function (err, data) { + if (err) { + callback(err); + return; + } + callback(null, data.toString("binary")); + }); +*/ + } + }; + this.writeFile = function (path, data, callback) { + fs.writeFile(path, data, "binary", function (err) { + callback(err || null); + }); + }; + this.deleteFile = fs.unlink; + this.read = function (path, offset, length, callback) { + if (currentDirectory) { + path = currentDirectory + "/" + path; + } + fs.open(path, "r+", 666, function (err, fd) { + if (err) { + callback(err); + return; + } + var buffer = new Buffer(length); + fs.read(fd, buffer, 0, length, offset, function (err, bytesRead) { + fs.close(fd); + callback(err, buffer); + }); + }); + }; + this.readFileSync = function (path, encoding) { + if (!encoding) { + return ""; + } + return fs.readFileSync(path, encoding); + }; + this.loadXML = loadXML; + this.isFile = isFile; + this.getFileSize = function (path, callback) { + if (currentDirectory) { + path = currentDirectory + "/" + path; + } + fs.stat(path, function (err, stats) { + if (err) { + callback(-1); + } else { + callback(stats.size); + } + }); + }; + this.log = function (msg) { + process.stderr.write(msg + '\n'); + }; + this.setTimeout = function (f, msec) { + setTimeout(function () { + f(); + }, msec); + }; + this.libraryPaths = function () { + return [__dirname]; + }; + this.setCurrentDirectory = function (dir) { + currentDirectory = dir; + }; + this.currentDirectory = function () { + return currentDirectory; + }; + this.type = function () { + return "NodeJSRuntime"; + }; + this.getDOMImplementation = function () { + return null; + }; + this.exit = process.exit; + this.getWindow = function () { + return null; + }; +} + +/** + * @constructor + * @implements {Runtime} + */ +function RhinoRuntime() { + "use strict"; + var self = this, + dom = Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(), + builder, + entityresolver, + currentDirectory = ""; + dom.setValidating(false); + dom.setNamespaceAware(true); + dom.setExpandEntityReferences(false); + dom.setSchema(null); + entityresolver = Packages.org.xml.sax.EntityResolver({ + resolveEntity: function (publicId, systemId) { + var file, open = function (path) { + var reader = new Packages.java.io.FileReader(path), + source = new Packages.org.xml.sax.InputSource(reader); + return source; + }; + file = systemId; + //file = /[^\/]*$/.exec(systemId); // what should this do? + return open(file); + } + }); + //dom.setEntityResolver(entityresolver); + builder = dom.newDocumentBuilder(); + builder.setEntityResolver(entityresolver); + + /** + * @constructor + * @param {!number} size + */ + this.ByteArray = function ByteArray(size) { + return [size]; + }; + this.byteArrayFromArray = function (array) { + return array; + }; + this.byteArrayFromString = function (string, encoding) { + // ignore encoding for now + var a = [], i, l = string.length; + for (i = 0; i < l; i += 1) { + a[i] = string.charCodeAt(i) & 0xff; + } + return a; + }; + this.byteArrayToString = Runtime.byteArrayToString; + this.concatByteArrays = function (bytearray1, bytearray2) { + return bytearray1.concat(bytearray2); + }; + + function loadXML(path, callback) { + var file = new Packages.java.io.File(path), + document; + try { + document = builder.parse(file); + } catch (err) { + print(err); + callback(err); + return; + } + callback(null, document); + } + function runtimeReadFile(path, encoding, callback) { + var file = new Packages.java.io.File(path), + data, + // read binary, seems hacky but works + rhinoencoding = (encoding === "binary") ? "latin1" : encoding; + if (!file.isFile()) { + callback(path + " is not a file."); + } else { + data = readFile(path, rhinoencoding); + if (encoding === "binary") { + data = self.byteArrayFromString(data, "binary"); + } + callback(null, data); + } + } + /** + * @param {!string} path + * @param {!string} encoding + * @return {?string} + */ + function runtimeReadFileSync(path, encoding) { + var file = new Packages.java.io.File(path), data, i; + if (!file.isFile()) { + return null; + } + if (encoding === "binary") { + encoding = "latin1"; // read binary, seems hacky but works + } + return readFile(path, encoding); + } + function isFile(path, callback) { + if (currentDirectory) { + path = currentDirectory + "/" + path; + } + var file = new Packages.java.io.File(path); + callback(file.isFile()); + } + this.loadXML = loadXML; + this.readFile = runtimeReadFile; + this.writeFile = function (path, data, callback) { + var out = new Packages.java.io.FileOutputStream(path), + i, + l = data.length; + for (i = 0; i < l; i += 1) { + out.write(data[i]); + } + out.close(); + callback(null); + }; + this.deleteFile = function (path, callback) { + var file = new Packages.java.io.File(path); + if (file['delete']()) { + callback(null); + } else { + callback("Could not delete " + path); + } + }; + this.read = function (path, offset, length, callback) { + // TODO: adapt to read only a part instead of the whole file + if (currentDirectory) { + path = currentDirectory + "/" + path; + } + var data = runtimeReadFileSync(path, "binary"); + if (data) { + callback(null, this.byteArrayFromString( + data.substring(offset, offset + length), + "binary" + )); + } else { + callback("Cannot read " + path); + } + }; + this.readFileSync = function (path, encoding) { + if (!encoding) { + return ""; + } + return readFile(path, encoding); + }; + this.isFile = isFile; + this.getFileSize = function (path, callback) { + if (currentDirectory) { + path = currentDirectory + "/" + path; + } + var file = new Packages.java.io.File(path); + callback(file.length()); + }; + this.log = print; + this.setTimeout = function (f, msec) { + f(); + }; + this.libraryPaths = function () { + return ["lib"]; + }; + this.setCurrentDirectory = function (dir) { + currentDirectory = dir; + }; + this.currentDirectory = function () { + return currentDirectory; + }; + this.type = function () { + return "RhinoRuntime"; + }; + this.getDOMImplementation = function () { + return builder.getDOMImplementation(); + }; + this.exit = quit; + this.getWindow = function () { + return null; + }; +} + +/** + * @const + * @type {Runtime} + */ +var runtime = (function () { + "use strict"; + var result; + if (typeof window !== "undefined") { + result = new BrowserRuntime(window.document.getElementById("logoutput")); + } else if (typeof require !== "undefined") { + result = new NodeJSRuntime(); + } else { + result = new RhinoRuntime(); + } + return result; +}()); +/*jslint sloppy: true*/ +(function () { + var cache = {}, + dircontents = {}; + function getOrDefinePackage(packageNameComponents) { + var topname = packageNameComponents[0], + i, + pkg; + // ensure top level package exists + pkg = eval("if (typeof " + topname + " === 'undefined') {" + + "eval('" + topname + " = {};');}" + topname); + for (i = 1; i < packageNameComponents.length - 1; i += 1) { + if (!pkg.hasOwnProperty(packageNameComponents[i])) { + pkg = pkg[packageNameComponents[i]] = {}; + } + } + return pkg[packageNameComponents[packageNameComponents.length - 1]]; + } + /** + * @param {string} classpath + * @returns {undefined} + */ + runtime.loadClass = function (classpath) { + if (IS_COMPILED_CODE) { + return; + } + if (cache.hasOwnProperty(classpath)) { + return; + } + var names = classpath.split("."), + impl; + impl = getOrDefinePackage(names); + if (impl) { + cache[classpath] = true; + return; + } + function getPathFromManifests(classpath) { + var path = classpath.replace(".", "/") + ".js", + dirs = runtime.libraryPaths(), + i, + dir, + code; + if (runtime.currentDirectory) { + dirs.push(runtime.currentDirectory()); + } + for (i = 0; i < dirs.length; i += 1) { + dir = dirs[i]; + if (!dircontents.hasOwnProperty(dir)) { + code = runtime.readFileSync(dirs[i] + "/manifest.js", + "utf8"); + if (code && code.length) { + try { + dircontents[dir] = eval(code); + } catch (e1) { + dircontents[dir] = null; + runtime.log("Cannot load manifest for " + dir + + "."); + } + } else { + dircontents[dir] = null; + } + } + code = null; + dir = dircontents[dir]; + if (dir && dir.indexOf && dir.indexOf(path) !== -1) { + return dirs[i] + "/" + path; + } + } + return null; + } + function load(classpath) { + var code, path; + path = getPathFromManifests(classpath); + if (!path) { + throw classpath + " is not listed in any manifest.js."; + } + try { + code = runtime.readFileSync(path, "utf8"); + } catch (e2) { + runtime.log("Error loading " + classpath + " " + e2); + throw e2; + } + if (code === undefined) { + throw "Cannot load class " + classpath; + } + try { + code = eval(classpath + " = eval(code);"); + } catch (e4) { + runtime.log("Error loading " + classpath + " " + e4); + throw e4; + } + return code; + } + // check if the class in context already + impl = load(classpath); + if (!impl || Runtime.getFunctionName(impl) !== + names[names.length - 1]) { + runtime.log("Loaded code is not for " + names[names.length - 1]); + throw "Loaded code is not for " + names[names.length - 1]; + } + cache[classpath] = true; + }; +}()); +(function (args) { + args = Array.prototype.slice.call(args); + function run(argv) { + if (!argv.length) { + return; + } + var script = argv[0]; + runtime.readFile(script, "utf8", function (err, code) { + var path = "", + paths = runtime.libraryPaths(); + if (script.indexOf("/") !== -1) { + path = script.substring(0, script.indexOf("/")); + } + runtime.setCurrentDirectory(path); + function run() { + var script, path, paths, args, argv, result; // hide variables + // execute script and make arguments available via argv + result = eval(code); + if (result) { + runtime.exit(result); + } + return; + } + if (err) { + runtime.log(err); + runtime.exit(1); + } else { + // run the script with arguments bound to arguments parameter + run.apply(null, argv); + } + }); + } + // if rhino or node.js, run the scripts provided as arguments + if (runtime.type() === "NodeJSRuntime") { + run(process.argv.slice(2)); + } else if (runtime.type() === "RhinoRuntime") { + run(args); + } else { + run(args.slice(1)); + } +}(typeof arguments !== "undefined" && arguments)); + diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializer.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializer.js new file mode 100644 index 0000000000..12b3219f81 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializer.js @@ -0,0 +1,197 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global xmldom*/ +/*jslint sub: true*/ +if (typeof Object.create !== 'function') { + Object['create'] = function (o) { + "use strict"; + /** + * @constructor + */ + var F = function () {}; + F.prototype = o; + return new F(); + }; +} + +/** + * Partial implementation of LSSerializer + * @constructor + */ +xmldom.LSSerializer = function LSSerializer() { + "use strict"; + var /**@const@type{!LSSerializer}*/ self = this; + + /** + * @param {!string} prefix + * @param {!Attr} attr + * @return {!string} + */ + function serializeAttribute(prefix, attr) { + var /**@type{!string}*/ s = prefix + attr.localName + "=\"" + + attr.nodeValue + "\""; + return s; + } + /** + * @param {!Object.} nsmap + * @param {string} prefix + * @param {string} ns + * @return {!string} + */ + function attributePrefix(nsmap, prefix, ns) { + // TODO: check for double prefix definitions, this needs a special class + if (nsmap.hasOwnProperty(ns)) { + return nsmap[ns] + ":"; + } + if (nsmap[ns] !== prefix) { + nsmap[ns] = prefix; + } + return prefix + ":"; + } + /** + * @param {!Object.} nsmap + * @param {!Node} node + * @return {!string} + */ + function startNode(nsmap, node) { + var /**@type{!string}*/ s = "", + /**@const@type{!NamedNodeMap}*/ atts = node.attributes, + /**@const@type{!number}*/ length, + /**@type{!number}*/ i, + /**@type{!Attr}*/ attr, + /**@type{!string}*/ attstr = "", + /**@type{!number}*/ accept, + /**@type{!string}*/ prefix; + if (atts) { // ELEMENT + if (nsmap[node.namespaceURI] !== node.prefix) { + nsmap[node.namespaceURI] = node.prefix; + } + s += "<" + node.nodeName; + length = atts.length; + for (i = 0; i < length; i += 1) { + attr = /**@type{!Attr}*/(atts.item(i)); + if (attr.namespaceURI !== "http://www.w3.org/2000/xmlns/") { + accept = (self.filter) ? self.filter.acceptNode(attr) : 1; + if (accept === 1) { + // xml attributes always need a prefix for a namespace + if (attr.namespaceURI) { + prefix = attributePrefix(nsmap, attr.prefix, + attr.namespaceURI); + } else { + prefix = ""; + } + attstr += " " + serializeAttribute(prefix, attr); + } + } + } + for (i in nsmap) { + if (nsmap.hasOwnProperty(i)) { + prefix = nsmap[i]; + if (!prefix) { + s += " xmlns=\"" + i + "\""; + } else if (prefix !== "xmlns") { + s += " xmlns:" + nsmap[i] + "=\"" + i + "\""; + } + } + } + s += attstr + ">"; + } + return s; + } + /** + * @param {!Node} node + * @return {!string} + */ + function endNode(node) { + var /**@type{!string}*/ s = ""; + if (node.nodeType === 1) { // ELEMENT + s += ""; + } + return s; + } + /** + * @param {!Object.} parentnsmap + * @param {!Node} node + * @return {!string} + */ + function serializeNode(parentnsmap, node) { + var /**@type{!string}*/ s = "", + /**@const@type{!Object.}*/ nsmap + = Object.create(parentnsmap), + /**@const@type{!number}*/ accept + = (self.filter) ? self.filter.acceptNode(node) : 1, + /**@type{Node}*/child; + if (accept === 1) { + s += startNode(nsmap, node); + } + if (accept === 1 || accept === 3) { + child = node.firstChild; + while (child) { + s += serializeNode(nsmap, child); + child = child.nextSibling; + } + if (node.nodeValue) { + s += node.nodeValue; + } + } + if (accept === 1) { + s += endNode(node); + } + return s; + } + function invertMap(map) { + var m = {}, i; + for (i in map) { + if (map.hasOwnProperty(i)) { + m[map[i]] = i; + } + } + return m; + } + /** + * @type {xmldom.LSSerializerFilter} + */ + this.filter = null; + /** + * @param {!Node} node + * @param {!Object.} nsmap + * @return {!string} + */ + this.writeToString = function (node, nsmap) { + if (!node) { + return ""; + } + nsmap = nsmap ? invertMap(nsmap) : {}; + return serializeNode(nsmap, node); + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializerFilter.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializerFilter.js new file mode 100644 index 0000000000..889428b831 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/LSSerializerFilter.js @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global xmldom*/ +/** + * Partial implementation of LSSerializerFilter + * @interface + */ +xmldom.LSSerializerFilter = function LSSerializerFilter() { + "use strict"; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformDOM.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformDOM.js new file mode 100644 index 0000000000..5e9f3abacf --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformDOM.js @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global xmldom*/ +/** + * @class + * @constructor + * @augments xmldom.OperationalTransformInterface + * @implements {xmldom.OperationalTransformInterface} + * @param {Element} root + * @param {xmldom.LSSerializer} serializer + */ +xmldom.OperationalTransformDOM = function OperationalTransformDOM(root, serializer) { + "use strict"; + var pos, length; + /** + * Skip in the document + * @param {!number} amount + * @return {undefined} + */ + function retain(amount) {} + /** + * Insert characters + * Can throw an exception if the current position does not allow insertion + * of characters. + * @param {!string} chars + * @return {undefined} + */ + function insertCharacters(chars) {} + /** + * Insert element start + * @param {!string} tagname + * @param {!Object} attributes + * @return {undefined} + */ + function insertElementStart(tagname, attributes) {} + /** + * Insert element end + * @return {undefined} + */ + function insertElementEnd() {} + /** + * Delete characters + * @param {!number} amount + * @return {undefined} + */ + function deleteCharacters(amount) {} + /** + * Delete element start + * @return {undefined} + */ + function deleteElementStart() {} + /** + * Delete element end + * @return {undefined} + */ + function deleteElementEnd() {} + /** + * Replace attributes + * @param {!Object} atts + * @return {undefined} + */ + function replaceAttributes(atts) {} + /** + * Update attributes + * @param {!Object} atts + * @return {undefined} + */ + function updateAttributes(atts) {} + /** + * @return {!boolean} + */ + function atEnd() { + return pos === length; + } + this.retain = retain; + this.insertCharacters = insertCharacters; + this.insertElementStart = insertElementStart; + this.insertElementEnd = insertElementEnd; + this.deleteCharacters = deleteCharacters; + this.deleteElementStart = deleteElementStart; + this.deleteElementEnd = deleteElementEnd; + this.replaceAttributes = replaceAttributes; + this.updateAttributes = updateAttributes; + this.atEnd = atEnd; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformInterface.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformInterface.js new file mode 100644 index 0000000000..03aab1232b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/OperationalTransformInterface.js @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global xmldom*/ +/** + * This interface allows a document to be modified by operational + * transformations. The interface is modelled after Google Wave. + * Manual editing of XML documents will also be done via this interface. + * + * + * @class + * @interface + */ +xmldom.OperationalTransformInterface = function () {"use strict"; }; +/** + * Skip in the document + * @param {!number} amount + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.retain = function (amount) {"use strict"; }; +/** + * Insert characters + * Can throw an exception if the current position does not allow insertion of + * characters. + * @param {!string} chars + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.insertCharacters = function (chars) {"use strict"; }; +/** + * Insert element start + * @param {!string} tagname + * @param {!Object} attributes + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.insertElementStart = function (tagname, attributes) {"use strict"; }; +/** + * Insert element end + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.insertElementEnd = function () {"use strict"; }; +/** + * Delete characters + * @param {!number} amount + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.deleteCharacters = function (amount) {"use strict"; }; +/** + * Delete element start + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.deleteElementStart = function () {"use strict"; }; +/** + * Delete element end + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.deleteElementEnd = function () {"use strict"; }; +/** + * Replace attributes + * @param {!Object} atts + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.replaceAttributes = function (atts) {"use strict"; }; +/** + * Update attributes + * @param {!Object} atts + * @return {undefined} + */ +xmldom.OperationalTransformInterface.prototype.updateAttributes = function (atts) {"use strict"; }; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG.js new file mode 100644 index 0000000000..e04c3c7611 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG.js @@ -0,0 +1,691 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, xmldom: true*/ + +/** + * RelaxNG can check a DOM tree against a Relax NG schema + * The RelaxNG implementation is currently not complete. Relax NG should not + * report errors on valid DOM trees, but it will not check all constraints that + * a Relax NG file can define. The current implementation does not load external + * parts of a Relax NG file. + * The main purpose of this Relax NG engine is to validate runtime ODF + * documents. The DOM tree is traversed via a TreeWalker. A custom TreeWalker + * implementation can hide parts of a DOM tree. This is useful in WebODF, where + * special elements and attributes in the runtime DOM tree. + * + * implementation according to + * http://www.thaiopensource.com/relaxng/derivative.html + */ +runtime.loadClass("xmldom.RelaxNGParser"); +/** + * @constructor + */ +xmldom.RelaxNG = function RelaxNG() { + "use strict"; + var xmlnsns = "http://www.w3.org/2000/xmlns/", + createChoice, + createInterleave, + createGroup, + createAfter, + createOneOrMore, + createValue, + createAttribute, + createNameClass, + createData, + makePattern, + notAllowed = { + type: "notAllowed", + nullable: false, + hash: "notAllowed", + textDeriv: function () { return notAllowed; }, + startTagOpenDeriv: function () { return notAllowed; }, + attDeriv: function () { return notAllowed; }, + startTagCloseDeriv: function () { return notAllowed; }, + endTagDeriv: function () { return notAllowed; } + }, + empty = { + type: "empty", + nullable: true, + hash: "empty", + textDeriv: function () { return notAllowed; }, + startTagOpenDeriv: function () { return notAllowed; }, + attDeriv: function (context, attribute) { return notAllowed; }, + startTagCloseDeriv: function () { return empty; }, + endTagDeriv: function () { return notAllowed; } + }, + text = { + type: "text", + nullable: true, + hash: "text", + textDeriv: function () { return text; }, + startTagOpenDeriv: function () { return notAllowed; }, + attDeriv: function () { return notAllowed; }, + startTagCloseDeriv: function () { return text; }, + endTagDeriv: function () { return notAllowed; } + }, + applyAfter, + childDeriv, + rootPattern; + + function memoize0arg(func) { + return (function () { + var cache; + return function () { + if (cache === undefined) { + cache = func(); + } + return cache; + }; + }()); + } + function memoize1arg(type, func) { + return (function () { + var cache = {}, cachecount = 0; + return function (a) { + var ahash = a.hash || a.toString(), + v; + v = cache[ahash]; + if (v !== undefined) { + return v; + } + cache[ahash] = v = func(a); + v.hash = type + cachecount.toString(); + cachecount += 1; + return v; + }; + }()); + } + function memoizeNode(func) { + return (function () { + var cache = {}; + return function (node) { + var v, m; + m = cache[node.localName]; + if (m === undefined) { + cache[node.localName] = m = {}; + } else { + v = m[node.namespaceURI]; + if (v !== undefined) { + return v; + } + } + m[node.namespaceURI] = v = func(node); + return v; + }; + }()); + } + function memoize2arg(type, fastfunc, func) { + return (function () { + var cache = {}, cachecount = 0; + return function (a, b) { + var v = fastfunc && fastfunc(a, b), + ahash, bhash, m; + if (v !== undefined) { return v; } + ahash = a.hash || a.toString(); + bhash = b.hash || b.toString(); + m = cache[ahash]; + if (m === undefined) { + cache[ahash] = m = {}; + } else { + v = m[bhash]; + if (v !== undefined) { + return v; + } + } + m[bhash] = v = func(a, b); + v.hash = type + cachecount.toString(); + cachecount += 1; + return v; + }; + }()); + } + // this memoize function can be used for functions where the order of two + // arguments is not important + function unorderedMemoize2arg(type, fastfunc, func) { + return (function () { + var cache = {}, cachecount = 0; + return function (a, b) { + var v = fastfunc && fastfunc(a, b), + ahash, bhash, m; + if (v !== undefined) { return v; } + ahash = a.hash || a.toString(); + bhash = b.hash || b.toString(); + if (ahash < bhash) { + m = ahash; ahash = bhash; bhash = m; + m = a; a = b; b = m; + } + m = cache[ahash]; + if (m === undefined) { + cache[ahash] = m = {}; + } else { + v = m[bhash]; + if (v !== undefined) { + return v; + } + } + m[bhash] = v = func(a, b); + v.hash = type + cachecount.toString(); + cachecount += 1; + return v; + }; + }()); + } + function getUniqueLeaves(leaves, pattern) { + if (pattern.p1.type === "choice") { + getUniqueLeaves(leaves, pattern.p1); + } else { + leaves[pattern.p1.hash] = pattern.p1; + } + if (pattern.p2.type === "choice") { + getUniqueLeaves(leaves, pattern.p2); + } else { + leaves[pattern.p2.hash] = pattern.p2; + } + } + createChoice = memoize2arg("choice", function (p1, p2) { + if (p1 === notAllowed) { return p2; } + if (p2 === notAllowed) { return p1; } + if (p1 === p2) { return p1; } + }, function (p1, p2) { + function makeChoice(p1, p2) { + return { + type: "choice", + p1: p1, + p2: p2, + nullable: p1.nullable || p2.nullable, + textDeriv: function (context, text) { + return createChoice(p1.textDeriv(context, text), + p2.textDeriv(context, text)); + }, + startTagOpenDeriv: memoizeNode(function (node) { + return createChoice(p1.startTagOpenDeriv(node), + p2.startTagOpenDeriv(node)); + }), + attDeriv: function (context, attribute) { + return createChoice(p1.attDeriv(context, attribute), + p2.attDeriv(context, attribute)); + }, + startTagCloseDeriv: memoize0arg(function () { + return createChoice(p1.startTagCloseDeriv(), + p2.startTagCloseDeriv()); + }), + endTagDeriv: memoize0arg(function () { + return createChoice(p1.endTagDeriv(), p2.endTagDeriv()); + }) + }; + } + var leaves = {}, i; + getUniqueLeaves(leaves, {p1: p1, p2: p2}); + p1 = undefined; + p2 = undefined; + for (i in leaves) { + if (leaves.hasOwnProperty(i)) { + if (p1 === undefined) { + p1 = leaves[i]; + } else if (p2 === undefined) { + p2 = leaves[i]; + } else { + p2 = createChoice(p2, leaves[i]); + } + } + } + return makeChoice(p1, p2); + }); + createInterleave = unorderedMemoize2arg("interleave", function (p1, p2) { + if (p1 === notAllowed || p2 === notAllowed) { return notAllowed; } + if (p1 === empty) { return p2; } + if (p2 === empty) { return p1; } + }, function (p1, p2) { + return { + type: "interleave", + p1: p1, + p2: p2, + nullable: p1.nullable && p2.nullable, + textDeriv: function (context, text) { + return createChoice( + createInterleave(p1.textDeriv(context, text), p2), + createInterleave(p1, p2.textDeriv(context, text)) + ); + }, + startTagOpenDeriv: memoizeNode(function (node) { + return createChoice( + applyAfter(function (p) { return createInterleave(p, p2); }, + p1.startTagOpenDeriv(node)), + applyAfter(function (p) { return createInterleave(p1, p); }, + p2.startTagOpenDeriv(node))); + }), + attDeriv: function (context, attribute) { + return createChoice( + createInterleave(p1.attDeriv(context, attribute), p2), + createInterleave(p1, p2.attDeriv(context, attribute))); + }, + startTagCloseDeriv: memoize0arg(function () { + return createInterleave(p1.startTagCloseDeriv(), + p2.startTagCloseDeriv()); + }) + }; + }); + createGroup = memoize2arg("group", function (p1, p2) { + if (p1 === notAllowed || p2 === notAllowed) { return notAllowed; } + if (p1 === empty) { return p2; } + if (p2 === empty) { return p1; } + }, function (p1, p2) { + return { + type: "group", + p1: p1, + p2: p2, + nullable: p1.nullable && p2.nullable, + textDeriv: function (context, text) { + var p = createGroup(p1.textDeriv(context, text), p2); + if (p1.nullable) { + return createChoice(p, p2.textDeriv(context, text)); + } + return p; + }, + startTagOpenDeriv: function (node) { + var x = applyAfter(function (p) { return createGroup(p, p2); }, + p1.startTagOpenDeriv(node)); + if (p1.nullable) { + return createChoice(x, p2.startTagOpenDeriv(node)); + } + return x; + }, + attDeriv: function (context, attribute) { + return createChoice( + createGroup(p1.attDeriv(context, attribute), p2), + createGroup(p1, p2.attDeriv(context, attribute))); + }, + startTagCloseDeriv: memoize0arg(function () { + return createGroup(p1.startTagCloseDeriv(), + p2.startTagCloseDeriv()); + }) + }; + }); + createAfter = memoize2arg("after", function (p1, p2) { + if (p1 === notAllowed || p2 === notAllowed) { return notAllowed; } + }, function (p1, p2) { + return { + type: "after", + p1: p1, + p2: p2, + nullable: false, + textDeriv: function (context, text) { + return createAfter(p1.textDeriv(context, text), p2); + }, + startTagOpenDeriv: memoizeNode(function (node) { + return applyAfter(function (p) { return createAfter(p, p2); }, + p1.startTagOpenDeriv(node)); + }), + attDeriv: function (context, attribute) { + return createAfter(p1.attDeriv(context, attribute), p2); + }, + startTagCloseDeriv: memoize0arg(function () { + return createAfter(p1.startTagCloseDeriv(), p2); + }), + endTagDeriv: memoize0arg(function () { + return (p1.nullable) ? p2 : notAllowed; + }) + }; + }); + createOneOrMore = memoize1arg("oneormore", function (p) { + if (p === notAllowed) { return notAllowed; } + return { + type: "oneOrMore", + p: p, + nullable: p.nullable, + textDeriv: function (context, text) { + return createGroup(p.textDeriv(context, text), + createChoice(this, empty)); + }, + startTagOpenDeriv: function (node) { + var oneOrMore = this; + return applyAfter(function (pf) { + return createGroup(pf, createChoice(oneOrMore, empty)); + }, p.startTagOpenDeriv(node)); + }, + attDeriv: function (context, attribute) { + var oneOrMore = this; + return createGroup(p.attDeriv(context, attribute), + createChoice(oneOrMore, empty)); + }, + startTagCloseDeriv: memoize0arg(function () { + return createOneOrMore(p.startTagCloseDeriv()); + }) + }; + }); + function createElement(nc, p) { + return { + type: "element", + nc: nc, + nullable: false, + textDeriv: function () { return notAllowed; }, + startTagOpenDeriv: function (node) { + if (nc.contains(node)) { + return createAfter(p, empty); + } + return notAllowed; + }, + attDeriv: function (context, attribute) { return notAllowed; }, + startTagCloseDeriv: function () { return this; } + }; + } + function valueMatch(context, pattern, text) { + return (pattern.nullable && /^\s+$/.test(text)) || + pattern.textDeriv(context, text).nullable; + } + createAttribute = memoize2arg("attribute", undefined, function (nc, p) { + return { + type: "attribute", + nullable: false, + nc: nc, + p: p, + attDeriv: function (context, attribute) { + if (nc.contains(attribute) && valueMatch(context, p, + attribute.nodeValue)) { + return empty; + } + return notAllowed; + }, + startTagCloseDeriv: function () { return notAllowed; } + }; + }); + function createList() { + return { + type: "list", + nullable: false, + hash: "list", + textDeriv: function (context, text) { + return empty; + } + }; + } + createValue = memoize1arg("value", function (value) { + return { + type: "value", + nullable: false, + value: value, + textDeriv: function (context, text) { + return (text === value) ? empty : notAllowed; + }, + attDeriv: function () { return notAllowed; }, + startTagCloseDeriv: function () { return this; } + }; + }); + createData = memoize1arg("data", function (type) { + return { + type: "data", + nullable: false, + dataType: type, + textDeriv: function () { return empty; }, + attDeriv: function () { return notAllowed; }, + startTagCloseDeriv: function () { return this; } + }; + }); + function createDataExcept() { + return { + type: "dataExcept", + nullable: false, + hash: "dataExcept" + }; + } + applyAfter = function applyAfter(f, p) { + var result; + if (p.type === "after") { + result = createAfter(p.p1, f(p.p2)); + } else if (p.type === "choice") { + result = createChoice(applyAfter(f, p.p1), applyAfter(f, p.p2)); + } else { + result = p; + } + return result; + }; + function attsDeriv(context, pattern, attributes, position) { + if (pattern === notAllowed) { + return notAllowed; + } + if (position >= attributes.length) { + return pattern; + } + if (position === 0) { + // TODO: loop over attributes to update namespace mapping + position = 0; + } + var a = attributes.item(position); + while (a.namespaceURI === xmlnsns) { // always ok + position += 1; + if (position >= attributes.length) { + return pattern; + } + a = attributes.item(position); + } + a = attsDeriv(context, pattern.attDeriv(context, + attributes.item(position)), attributes, position + 1); + return a; + } + function childrenDeriv(context, pattern, walker) { + var element = walker.currentNode, + childNode = walker.firstChild(), + numberOfTextNodes = 0, + childNodes = [], i, p; + // simple incomplete implementation: only use non-empty text nodes + while (childNode) { + if (childNode.nodeType === 1) { + childNodes.push(childNode); + } else if (childNode.nodeType === 3 && + !/^\s*$/.test(childNode.nodeValue)) { + childNodes.push(childNode.nodeValue); + numberOfTextNodes += 1; + } + childNode = walker.nextSibling(); + } + // if there is no nodes at all, add an empty text node + if (childNodes.length === 0) { + childNodes = [""]; + } + p = pattern; + for (i = 0; p !== notAllowed && i < childNodes.length; i += 1) { + childNode = childNodes[i]; + if (typeof childNode === "string") { + if (/^\s*$/.test(childNode)) { + p = createChoice(p, p.textDeriv(context, childNode)); + } else { + p = p.textDeriv(context, childNode); + } + } else { + walker.currentNode = childNode; + p = childDeriv(context, p, walker); + } + } + walker.currentNode = element; + return p; + } + childDeriv = function childDeriv(context, pattern, walker) { + var childNode = walker.currentNode, p; + p = pattern.startTagOpenDeriv(childNode); + p = attsDeriv(context, p, childNode.attributes, 0); + p = p.startTagCloseDeriv(); + p = childrenDeriv(context, p, walker); + p = p.endTagDeriv(); + return p; + }; + function addNames(name, ns, pattern) { + if (pattern.e[0].a) { + name.push(pattern.e[0].text); + ns.push(pattern.e[0].a.ns); + } else { + addNames(name, ns, pattern.e[0]); + } + if (pattern.e[1].a) { + name.push(pattern.e[1].text); + ns.push(pattern.e[1].a.ns); + } else { + addNames(name, ns, pattern.e[1]); + } + } + createNameClass = function createNameClass(pattern) { + var name, ns, hash, i, result; + if (pattern.name === "name") { + name = pattern.text; + ns = pattern.a.ns; + result = { + name: name, + ns: ns, + hash: "{" + ns + "}" + name, + contains: function (node) { + return node.namespaceURI === ns && node.localName === name; + } + }; + } else if (pattern.name === "choice") { + name = []; + ns = []; + addNames(name, ns, pattern); + hash = ""; + for (i = 0; i < name.length; i += 1) { + hash += "{" + ns[i] + "}" + name[i] + ","; + } + result = { + hash: hash, + contains: function (node) { + var i; + for (i = 0; i < name.length; i += 1) { + if (name[i] === node.localName && + ns[i] === node.namespaceURI) { + return true; + } + } + return false; + } + }; + } else { + result = { + hash: "anyName", + contains: function () { return true; } + }; + } + return result; + }; + function resolveElement(pattern, elements) { + var element, p, i, hash; + // create an empty object in the store to enable circular + // dependencies + hash = "element" + pattern.id.toString(); + p = elements[pattern.id] = { hash: hash }; + element = createElement(createNameClass(pattern.e[0]), + makePattern(pattern.e[1], elements)); + // copy the properties of the new object into the predefined one + for (i in element) { + if (element.hasOwnProperty(i)) { + p[i] = element[i]; + } + } + return p; + } + makePattern = function makePattern(pattern, elements) { + var p, i; + if (pattern.name === "elementref") { + p = pattern.id || 0; + pattern = elements[p]; + if (pattern.name !== undefined) { + return resolveElement(pattern, elements); + } + return pattern; + } + switch (pattern.name) { + case 'empty': + return empty; + case 'notAllowed': + return notAllowed; + case 'text': + return text; + case 'choice': + return createChoice(makePattern(pattern.e[0], elements), + makePattern(pattern.e[1], elements)); + case 'interleave': + p = makePattern(pattern.e[0], elements); + for (i = 1; i < pattern.e.length; i += 1) { + p = createInterleave(p, makePattern(pattern.e[i], + elements)); + } + return p; + case 'group': + return createGroup(makePattern(pattern.e[0], elements), + makePattern(pattern.e[1], elements)); + case 'oneOrMore': + return createOneOrMore(makePattern(pattern.e[0], elements)); + case 'attribute': + return createAttribute(createNameClass(pattern.e[0]), + makePattern(pattern.e[1], elements)); + case 'value': + return createValue(pattern.text); + case 'data': + p = pattern.a && pattern.a.type; + if (p === undefined) { + p = ""; + } + return createData(p); + case 'list': + return createList(); + } + throw "No support for " + pattern.name; + }; + this.makePattern = function (pattern, elements) { + var copy = {}, i; + for (i in elements) { + if (elements.hasOwnProperty(i)) { + copy[i] = elements[i]; + } + } + i = makePattern(pattern, copy); + return i; + }; + /** + * Validate the elements pointed to by the TreeWalker + * @param {!TreeWalker} walker + * @param {!function(Array.):undefined} callback + * @return {undefined} + */ + this.validate = function validate(walker, callback) { + var errors; + walker.currentNode = walker.root; + errors = childDeriv(null, rootPattern, walker); + if (!errors.nullable) { + runtime.log("Error in Relax NG validation: " + errors); + callback(["Error in Relax NG validation: " + errors]); + } else { + callback(null); + } + }; + this.init = function init(rootPattern1) { + rootPattern = rootPattern1; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG2.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG2.js new file mode 100644 index 0000000000..185ef5236e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNG2.js @@ -0,0 +1,416 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, xmldom: true*/ + +/** + * RelaxNG can check a DOM tree against a Relax NG schema + * The RelaxNG implementation is currently not complete. Relax NG should not + * report errors on valid DOM trees, but it will not check all constraints that + * a Relax NG file can define. The current implementation does not load external + * parts of a Relax NG file. + * The main purpose of this Relax NG engine is to validate runtime ODF + * documents. The DOM tree is traversed via a TreeWalker. A custom TreeWalker + * implementation can hide parts of a DOM tree. This is useful in WebODF, where + * special elements and attributes in the runtime DOM tree. + */ +runtime.loadClass("xmldom.RelaxNGParser"); +/** + * @constructor + */ +xmldom.RelaxNG2 = function RelaxNG2() { + "use strict"; + var start, + validateNonEmptyPattern, + nsmap, + depth = 0, + p = " "; + + /** + * @constructor + * @param {!string} error + * @param {Node=} context + */ + function RelaxNGParseError(error, context) { + this.message = function () { + if (context) { + error += (context.nodeType === 1) ? " Element " : " Node "; + error += context.nodeName; + if (context.nodeValue) { + error += " with value '" + context.nodeValue + "'"; + } + error += "."; + } + return error; + }; +// runtime.log("[" + p.slice(0, depth) + this.message() + "]"); + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateOneOrMore(elementdef, walker, element) { + // The list of definitions in the elements list should be completely + // traversed at least once. If a second or later round fails, the walker + // should go back to the start of the last successful traversal + var node, i = 0, err; + do { + node = walker.currentNode; + err = validateNonEmptyPattern(elementdef.e[0], walker, element); + i += 1; + } while (!err && node !== walker.currentNode); + if (i > 1) { // at least one round was without error + // set position back to position of before last failed round + walker.currentNode = node; + return null; + } + return err; + } + /** + * @param {!Node} node + * @return {!string} + */ + function qName(node) { + return nsmap[node.namespaceURI] + ":" + node.localName; + } + /** + * @param {!Node} node + * @return {!boolean} + */ + function isWhitespace(node) { + return node && node.nodeType === 3 && /^\s+$/.test(node.nodeValue); + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @param {string=} data + * @return {Array.} + */ + function validatePattern(elementdef, walker, element, data) { + if (elementdef.name === "empty") { + return null; + } + return validateNonEmptyPattern(elementdef, walker, element, data); + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateAttribute(elementdef, walker, element) { + if (elementdef.e.length !== 2) { + throw "Attribute with wrong # of elements: " + elementdef.e.length; + } + var att, a, l = elementdef.localnames.length, i; + for (i = 0; i < l; i += 1) { + a = element.getAttributeNS(elementdef.namespaces[i], + elementdef.localnames[i]); + // if an element is not present, getAttributeNS will return an empty + // string but an empty string is possible attribute value, so an + // extra check is needed + if (a === "" && !element.hasAttributeNS(elementdef.namespaces[i], + elementdef.localnames[i])) { + a = undefined; + } + if (att !== undefined && a !== undefined) { + return [new RelaxNGParseError("Attribute defined too often.", + element)]; + } + att = a; + } + if (att === undefined) { + return [new RelaxNGParseError("Attribute not found: " + + elementdef.names, element)]; + } + return validatePattern(elementdef.e[1], walker, element, att); + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateTop(elementdef, walker, element) { + // notAllowed not implemented atm + return validatePattern(elementdef, walker, element); + } + /** + * Validate an element. + * Function forwards the walker until an element is met. + * If element if of the right type, it is entered and the validation + * continues inside the element. After validation, regardless of whether an + * error occurred, the walker is at the same depth in the dom tree. + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateElement(elementdef, walker, element) { + if (elementdef.e.length !== 2) { + throw "Element with wrong # of elements: " + elementdef.e.length; + } + depth += 1; + // forward until an element is seen, then check the name + var /**@type{Node}*/ node = walker.currentNode, + /**@type{number}*/ type = node ? node.nodeType : 0, + error = null; + // find the next element, skip text nodes with only whitespace + while (type > 1) { + if (type !== 8 && + (type !== 3 || + !/^\s+$/.test(walker.currentNode.nodeValue))) {// TEXT_NODE + depth -= 1; + return [new RelaxNGParseError("Not allowed node of type " + + type + ".")]; + } + node = walker.nextSibling(); + type = node ? node.nodeType : 0; + } + if (!node) { + depth -= 1; + return [new RelaxNGParseError("Missing element " + + elementdef.names)]; + } + if (elementdef.names && elementdef.names.indexOf(qName(node)) === -1) { + depth -= 1; + return [new RelaxNGParseError("Found " + node.nodeName + + " instead of " + elementdef.names + ".", node)]; + } + // the right element was found, now parse the contents + if (walker.firstChild()) { + // currentNode now points to the first child node of this element + error = validateTop(elementdef.e[1], walker, node); + // there should be no content left + while (walker.nextSibling()) { + type = walker.currentNode.nodeType; + if (!isWhitespace(walker.currentNode) && type !== 8) { + depth -= 1; + return [new RelaxNGParseError("Spurious content.", + walker.currentNode)]; + } + } + if (walker.parentNode() !== node) { + depth -= 1; + return [new RelaxNGParseError("Implementation error.")]; + } + } else { + error = validateTop(elementdef.e[1], walker, node); + } + depth -= 1; + // move to the next node + node = walker.nextSibling(); + return error; + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @param {string=} data + * @return {Array.} + */ + function validateChoice(elementdef, walker, element, data) { + // loop through child definitions and return if a match is found + if (elementdef.e.length !== 2) { + throw "Choice with wrong # of options: " + elementdef.e.length; + } + var node = walker.currentNode, err; + // if the first option is empty, just check the second one for debugging + // but the total choice is alwasy ok + if (elementdef.e[0].name === "empty") { + err = validateNonEmptyPattern(elementdef.e[1], walker, element, + data); + if (err) { + walker.currentNode = node; + } + return null; + } + err = validatePattern(elementdef.e[0], walker, element, data); + if (err) { + walker.currentNode = node; + err = validateNonEmptyPattern(elementdef.e[1], walker, element, + data); + } + return err; + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateInterleave(elementdef, walker, element) { + var l = elementdef.e.length, n = [l], err, i, todo = l, + donethisround, node, subnode, e; + // the interleave is done when all items are 'true' and no + while (todo > 0) { + donethisround = 0; + node = walker.currentNode; + for (i = 0; i < l; i += 1) { + subnode = walker.currentNode; + if (n[i] !== true && n[i] !== subnode) { + e = elementdef.e[i]; + err = validateNonEmptyPattern(e, walker, element); + if (err) { + walker.currentNode = subnode; + if (n[i] === undefined) { + n[i] = false; + } + } else if (subnode === walker.currentNode || + // this is a bit dodgy, there should be a rule to + // see if multiple elements are allowed + e.name === "oneOrMore" || + (e.name === "choice" && + (e.e[0].name === "oneOrMore" || + e.e[1].name === "oneOrMore"))) { + donethisround += 1; + n[i] = subnode; // no error and try this one again later + } else { + donethisround += 1; + n[i] = true; // no error and progress + } + } + } + if (node === walker.currentNode && donethisround === todo) { + return null; + } + if (donethisround === 0) { + for (i = 0; i < l; i += 1) { + if (n[i] === false) { + return [new RelaxNGParseError( + "Interleave does not match.", element)]; + } + } + return null; + } + todo = 0; + for (i = 0; i < l; i += 1) { + if (n[i] !== true) { + todo += 1; + } + } + } + return null; + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateGroup(elementdef, walker, element) { + if (elementdef.e.length !== 2) { + throw "Group with wrong # of members: " + elementdef.e.length; + } + //runtime.log(elementdef.e[0].name + " " + elementdef.e[1].name); + return validateNonEmptyPattern(elementdef.e[0], walker, element) || + validateNonEmptyPattern(elementdef.e[1], walker, element); + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @return {Array.} + */ + function validateText(elementdef, walker, element) { + var /**@type{Node}*/ node = walker.currentNode, + /**@type{number}*/ type = node ? node.nodeType : 0, + error = null; + // find the next element, skip text nodes with only whitespace + while (node !== element && type !== 3) { + if (type === 1) { + return [new RelaxNGParseError( + "Element not allowed here.", node)]; + } + node = walker.nextSibling(); + type = node ? node.nodeType : 0; + } + walker.nextSibling(); + return null; + } + /** + * @param elementdef + * @param walker + * @param {Element} element + * @param {string=} data + * @return {Array.} + */ + validateNonEmptyPattern = function validateNonEmptyPattern(elementdef, + walker, element, data) { + var name = elementdef.name, err = null; + if (name === "text") { + err = validateText(elementdef, walker, element); + } else if (name === "data") { + err = null; // data not implemented + } else if (name === "value") { + if (data !== elementdef.text) { + err = [new RelaxNGParseError("Wrong value, should be '" + + elementdef.text + "', not '" + data + "'", element)]; + } + } else if (name === "list") { + err = null; // list not implemented + } else if (name === "attribute") { + err = validateAttribute(elementdef, walker, element); + } else if (name === "element") { + err = validateElement(elementdef, walker, element); + } else if (name === "oneOrMore") { + err = validateOneOrMore(elementdef, walker, element); + } else if (name === "choice") { + err = validateChoice(elementdef, walker, element, data); + } else if (name === "group") { + err = validateGroup(elementdef, walker, element); + } else if (name === "interleave") { + err = validateInterleave(elementdef, walker, element); + } else { + throw name + " not allowed in nonEmptyPattern."; + } + return err; + }; + /** + * Validate the elements pointed to by the TreeWalker + * @param {!TreeWalker} walker + * @param {!function(Array.):undefined} callback + * @return {undefined} + */ + this.validate = function validate(walker, callback) { + walker.currentNode = walker.root; + var errors = validatePattern(start.e[0], walker, walker.root); + callback(errors); + }; + this.init = function init(start1, nsmap1) { + start = start1; + nsmap = nsmap1; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNGParser.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNGParser.js new file mode 100644 index 0000000000..12e37278a0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/RelaxNGParser.js @@ -0,0 +1,452 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, xmldom: true*/ + +/** + * RelaxNG can check a DOM tree against a Relax NG schema + * The RelaxNG implementation is currently not complete. Relax NG should not + * report errors on valid DOM trees, but it will not check all constraints that + * a Relax NG file can define. The current implementation does not load external + * parts of a Relax NG file. + * The main purpose of this Relax NG engine is to validate runtime ODF + * documents. The DOM tree is traversed via a TreeWalker. A custom TreeWalker + * implementation can hide parts of a DOM tree. This is useful in WebODF, where + * special elements and attributes in the runtime DOM tree. + * @constructor + */ +xmldom.RelaxNGParser = function RelaxNGParser() { + "use strict"; + var self = this, + rngns = "http://relaxng.org/ns/structure/1.0", + xmlnsns = "http://www.w3.org/2000/xmlns/", + start, + nsmap = { "http://www.w3.org/XML/1998/namespace": "xml" }, + parse; + + /** + * @constructor + * @param {!string} error + * @param {Node=} context + */ + function RelaxNGParseError(error, context) { + /** + * return {!string} + */ + this.message = function () { + if (context) { + error += (context.nodeType === 1) ? " Element " : " Node "; + error += context.nodeName; + if (context.nodeValue) { + error += " with value '" + context.nodeValue + "'"; + } + error += "."; + } + return error; + }; + } + function splitToDuos(e) { + if (e.e.length <= 2) { + return e; + } + var o = { name: e.name, e: e.e.slice(0, 2) }; + return splitToDuos({ + name: e.name, + e: [ o ].concat(e.e.slice(2)) + }); + } + /** + * @param {!string} name + * @return {!Array.} + */ + function splitQName(name) { + var r = name.split(":", 2), + prefix = "", i; + if (r.length === 1) { + r = ["", r[0]]; + } else { + prefix = r[0]; + } + for (i in nsmap) { + if (nsmap[i] === prefix) { + r[0] = i; + } + } + return r; + } + + function splitQNames(def) { + var i, l = (def.names) ? def.names.length : 0, name, + localnames = def.localnames = [l], + namespaces = def.namespaces = [l]; + for (i = 0; i < l; i += 1) { + name = splitQName(def.names[i]); + namespaces[i] = name[0]; + localnames[i] = name[1]; + } + } + + /** + * @param {!string} str + * @return {!string} + */ + function trim(str) { + str = str.replace(/^\s\s*/, ''); + var ws = /\s/, + i = str.length - 1; + while (ws.test(str.charAt(i))) { + i -= 1; + } + return str.slice(0, i + 1); + } + + /** + * @param {!Object.} atts + * @param {!string} name + * @param {!Array.} names + * @return {!Object} + */ + function copyAttributes(atts, name, names) { + var a = {}, i, att; + for (i = 0; i < atts.length; i += 1) { + att = atts.item(i); + if (!att.namespaceURI) { + if (att.localName === "name" && + (name === "element" || name === "attribute")) { + names.push(att.value); + } + if (att.localName === "name" || att.localName === "combine" || + att.localName === "type") { + att.value = trim(att.value); + } + a[att.localName] = att.value; + } else if (att.namespaceURI === xmlnsns) { + nsmap[att.value] = att.localName; + } + } + return a; + } + + function parseChildren(c, e, elements, names) { + var text = "", ce; + while (c) { + if (c.nodeType === 1 && c.namespaceURI === rngns) { + ce = parse(c, elements, e); + if (ce) { + if (ce.name === "name") { + names.push(nsmap[ce.a.ns] + ":" + ce.text); + e.push(ce); + } else if (ce.name === "choice" && ce.names && + ce.names.length) { + names = names.concat(ce.names); + delete ce.names; + e.push(ce); + } else { + e.push(ce); + } + } + } else if (c.nodeType === 3) { + text += c.nodeValue; + } + c = c.nextSibling; + } + return text; + } + + function combineDefines(combine, name, e, siblings) { + // combineDefines is called often enough that there can only be one + // other element with the same name + var i, ce; + for (i = 0; siblings && i < siblings.length; i += 1) { + ce = siblings[i]; + if (ce.name === "define" && ce.a && ce.a.name === name) { + ce.e = [ { name: combine, e: ce.e.concat(e) } ]; + return ce; + } + } + return null; + } + + parse = function parse(element, elements, siblings) { + // parse all elements from the Relax NG namespace into JavaScript + // objects + var e = [], + /**@type{Object}*/a, + ce, + i, text, name = element.localName, names = []; + a = copyAttributes(element.attributes, name, names); + a.combine = a.combine || undefined; + text = parseChildren(element.firstChild, e, elements, names); + + // 4.2 strip leading and trailing whitespace + if (name !== "value" && name !== "param") { + text = /^\s*([\s\S]*\S)?\s*$/.exec(text)[1]; + } + // 4.3 datatypeLibrary attribute + // 4.4 type attribute of value element + if (name === "value" && a.type === undefined) { + a.type = "token"; + a.datatypeLibrary = ""; + } + // 4.5 href attribute + // 4.6 externalRef element + // 4.7 include element + // 4.8 name attribute of element and attribute elements + if ((name === "attribute" || name === "element") && + a.name !== undefined) { + i = splitQName(a.name); + e = [{name: "name", text: i[1], a: {ns: i[0]}}].concat(e); + delete a.name; + } + // 4.9 ns attribute + if (name === "name" || name === "nsName" || name === "value") { + if (a.ns === undefined) { + a.ns = ""; // TODO + } + } else { + delete a.ns; + } + // 4.10 QNames + if (name === "name") { + i = splitQName(text); + a.ns = i[0]; + text = i[1]; + } + // 4.11 div element + // 4.12 Number of child elements + if (e.length > 1 && (name === "define" || name === "oneOrMore" || + name === "zeroOrMore" || name === "optional" || + name === "list" || name === "mixed")) { + e = [{name: "group", e: splitToDuos({name: "group", e: e}).e}]; + } + if (e.length > 2 && name === "element") { + e = [e[0]].concat( + {name: "group", e: splitToDuos( + {name: "group", e: e.slice(1)}).e}); + } + if (e.length === 1 && name === "attribute") { + e.push({name: "text", text: text}); + } + // if node has only one child, replace node with child + if (e.length === 1 && (name === "choice" || name === "group" || + name === "interleave")) { + name = e[0].name; + names = e[0].names; + a = e[0].a; + text = e[0].text; + e = e[0].e; + } else if (e.length > 2 && (name === "choice" || name === "group" || + name === "interleave")) { + e = splitToDuos({name: name, e: e}).e; + } + // 4.13 mixed element + if (name === "mixed") { + name = "interleave"; + e = [ e[0], { name: "text" } ]; + } + // 4.14 optional element + if (name === "optional") { + name = "choice"; + e = [ e[0], { name: "empty" } ]; + } + // 4.15 zeroOrMore element + if (name === "zeroOrMore") { + name = "choice"; + e = [ {name: "oneOrMore", e: [ e[0] ] }, { name: "empty" } ]; + } + // 4.17 combine attribute + if (name === "define" && a.combine) { + ce = combineDefines(a.combine, a.name, e, siblings); + if (ce) { + return; + } + } + + // create the definition + ce = { name: name }; + if (e && e.length > 0) { ce.e = e; } + for (i in a) { + if (a.hasOwnProperty(i)) { + ce.a = a; + break; + } + } + if (text !== undefined) { ce.text = text; } + if (names && names.length > 0) { ce.names = names; } + + // part one of 4.19 + if (name === "element") { + ce.id = elements.length; + elements.push(ce); + ce = { name: "elementref", id: ce.id }; + } + return ce; + }; + + function resolveDefines(def, defines) { + var i = 0, e, defs, end, name = def.name; + while (def.e && i < def.e.length) { + e = def.e[i]; + if (e.name === "ref") { + defs = defines[e.a.name]; + if (!defs) { + throw e.a.name + " was not defined."; + } + end = def.e.slice(i + 1); + def.e = def.e.slice(0, i); + def.e = def.e.concat(defs.e); + def.e = def.e.concat(end); + } else { + i += 1; + resolveDefines(e, defines); + } + } + e = def.e; + // 4.20 notAllowed element + // 4.21 empty element + if (name === "choice") { + if (!e || !e[1] || e[1].name === "empty") { + if (!e || !e[0] || e[0].name === "empty") { + delete def.e; + def.name = "empty"; + } else { + e[1] = e[0]; + e[0] = { name: "empty" }; + } + } + } + if (name === "group" || name === "interleave") { + if (e[0].name === "empty") { + if (e[1].name === "empty") { + delete def.e; + def.name = "empty"; + } else { + name = def.name = e[1].name; + def.names = e[1].names; + e = def.e = e[1].e; + } + } else if (e[1].name === "empty") { + name = def.name = e[0].name; + def.names = e[0].names; + e = def.e = e[0].e; + } + } + if (name === "oneOrMore" && e[0].name === "empty") { + delete def.e; + def.name = "empty"; + } + // for attributes we need to have the list of namespaces and + // localnames readily available, so we split up the qnames + if (name === "attribute") { + splitQNames(def); + } + // for interleaving validation, it is convenient to join all + // interleave elements that touch into one element + if (name === "interleave") { + // at this point the interleave will have two child elements, + // but the child interleave elements may have a different number + if (e[0].name === "interleave") { + if (e[1].name === "interleave") { + e = def.e = e[0].e.concat(e[1].e); + } else { + e = def.e = [e[1]].concat(e[0].e); + } + } else if (e[1].name === "interleave") { + e = def.e = [e[0]].concat(e[1].e); + } + } + } + + function resolveElements(def, elements) { + var i = 0, e, name; + while (def.e && i < def.e.length) { + e = def.e[i]; + if (e.name === "elementref") { + e.id = e.id || 0; + def.e[i] = elements[e.id]; + } else if (e.name !== "element") { + resolveElements(e, elements); + } + i += 1; + } + } + + /** + * @param {!Document} dom + * @param {!Function} callback + * @return {?Array} + */ + function main(dom, callback) { + var elements = [], + grammar = parse(dom && dom.documentElement, elements, undefined), + i, e, defines = {}; + + for (i = 0; i < grammar.e.length; i += 1) { + e = grammar.e[i]; + if (e.name === "define") { + defines[e.a.name] = e; + } else if (e.name === "start") { + start = e; + } + } + if (!start) { + return [new RelaxNGParseError( + "No Relax NG start element was found.")]; + } + resolveDefines(start, defines); + for (i in defines) { + if (defines.hasOwnProperty(i)) { + resolveDefines(defines[i], defines); + } + } + for (i = 0; i < elements.length; i += 1) { + resolveDefines(elements[i], defines); + } + if (callback) { + self.rootPattern = callback(start.e[0], elements); + } + resolveElements(start, elements); + for (i = 0; i < elements.length; i += 1) { + resolveElements(elements[i], elements); + } + self.start = start; + self.elements = elements; + self.nsmap = nsmap; + return null; + } + /** + * @param {!Document} dom + * @param {!Function} callback + * @return {?Array} + */ + this.parseRelaxNGDOM = main; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/XPath.js b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/XPath.js new file mode 100644 index 0000000000..28466c2184 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/lib/xmldom/XPath.js @@ -0,0 +1,383 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global xmldom, XPathResult, runtime*/ +/** + * Wrapper for XPath functions + * @constructor + */ +xmldom.XPath = (function () { + "use strict"; + var createXPathPathIterator, + parsePredicates; + /** + * @param {!number} a + * @param {!number} b + * @param {!number} c + * @return {!boolean} + */ + function isSmallestPositive(a, b, c) { + return a !== -1 && (a < b || b === -1) && (a < c || c === -1); + } + /** + * Parse a subset of xpaths. + * The xpath predicates may contain xpaths. The location may be equated to + * a value. If a parsing error occurs, null is returned. + * @param {!string} xpath + * @param {!number} pos + * @param {!number} end + * @param {!Array} steps + * @return {!number} + */ + function parseXPathStep(xpath, pos, end, steps) { + var location = "", + predicates = [], + value, + brapos = xpath.indexOf('[', pos), + slapos = xpath.indexOf('/', pos), + eqpos = xpath.indexOf('=', pos), + depth = 0, + start = 0; + // parse the location + if (isSmallestPositive(slapos, brapos, eqpos)) { + location = xpath.substring(pos, slapos); + pos = slapos + 1; + } else if (isSmallestPositive(brapos, slapos, eqpos)) { + location = xpath.substring(pos, brapos); + pos = parsePredicates(xpath, brapos, predicates); + } else if (isSmallestPositive(eqpos, slapos, brapos)) { + location = xpath.substring(pos, eqpos); + pos = eqpos; + } else { + location = xpath.substring(pos, end); + pos = end; + } + steps.push({location: location, predicates: predicates}); + return pos; + } + function parseXPath(xpath) { + var steps = [], + p = 0, + end = xpath.length, + value; + while (p < end) { + p = parseXPathStep(xpath, p, end, steps); + if (p < end && xpath[p] === '=') { + value = xpath.substring(p + 1, end); + if (value.length > 2 && + (value[0] === '\'' || value[0] === '"')) { + value = value.slice(1, value.length - 1); + } else { + try { + value = parseInt(value, 10); + } catch (e) { + } + } + p = end; + } + } + return {steps: steps, value: value}; + } + parsePredicates = function parsePredicates(xpath, start, predicates) { + var pos = start, + l = xpath.length, + selector, + depth = 0; + while (pos < l) { + if (xpath[pos] === ']') { + depth -= 1; + if (depth <= 0) { + predicates.push(parseXPath(xpath.substring(start, pos))); + } + } else if (xpath[pos] === '[') { + if (depth <= 0) { + start = pos + 1; + } + depth += 1; + } + pos += 1; + } + return pos; + }; + /** + * Iterator over nodes uses in the xpath implementation + * @class + * @interface + */ + function XPathIterator() {} + /** + * @return {Node} + */ + XPathIterator.prototype.next = function () {}; + /** + * @return {undefined} + */ + XPathIterator.prototype.reset = function () {}; + /** + * @class + * @constructor + * @augments XPathIterator + * @implements {XPathIterator} + */ + function NodeIterator() { + var node, done = false; + this.setNode = function setNode(n) { + node = n; + }; + this.reset = function () { + done = false; + }; + this.next = function next() { + var val = (done) ? null : node; + done = true; + return val; + }; + } + /** + * @class + * @constructor + * @augments XPathIterator + * @implements {XPathIterator} + * @param {XPathIterator} it + * @param {!string} namespace + * @param {!string} localName + */ + function AttributeIterator(it, namespace, localName) { + this.reset = function reset() { + it.reset(); + }; + this.next = function next() { + var node = it.next(), attr; + while (node) { + node = node.getAttributeNodeNS(namespace, localName); + if (node) { + return node; + } + node = it.next(); + } + return node; + }; + } + /** + * @class + * @constructor + * @augments XPathIterator + * @implements {XPathIterator} + * @param {XPathIterator} it + * @param {boolean} recurse + */ + function AllChildElementIterator(it, recurse) { + var root = it.next(), + node = null; + this.reset = function reset() { + it.reset(); + root = it.next(); + node = null; + }; + this.next = function next() { + while (root) { + if (node) { + if (recurse && node.firstChild) { + node = node.firstChild; + } else { + while (!node.nextSibling && node !== root) { + node = node.parentNode; + } + if (node === root) { + root = it.next(); + } else { + node = node.nextSibling; + } + } + } else { + do { +// node = (recurse) ?root :root.firstChild; + node = root.firstChild; + if (!node) { + root = it.next(); + } + } while (root && !node); + } + if (node && node.nodeType === 1) { + return node; + } + } + return null; + }; + } + /** + * @class + * @constructor + * @augments XPathIterator + * @implements {XPathIterator} + * @param {XPathIterator} it + * @param {function(Node):boolean} condition + */ + function ConditionIterator(it, condition) { + this.reset = function reset() { + it.reset(); + }; + this.next = function next() { + var n = it.next(); + while (n && !condition(n)) { + n = it.next(); + } + return n; + }; + } + /** + * @param {XPathIterator} it + * @param {string} name + * @param {function(string):string} namespaceResolver + * @return {!ConditionIterator} + */ + function createNodenameFilter(it, name, namespaceResolver) { + var s = name.split(':', 2), + namespace = namespaceResolver(s[0]), + localName = s[1]; + return new ConditionIterator(it, function (node) { + return node.localName === localName && + node.namespaceURI === namespace; + }); + } + /** + * @param {XPathIterator} it + * @param {!Object} p + * @param {function(string):string} namespaceResolver + * @return {!ConditionIterator} + */ + function createPredicateFilteredIterator(it, p, namespaceResolver) { + var nit = new NodeIterator(), + pit = createXPathPathIterator(nit, p, namespaceResolver), + value = p.value; + if (value === undefined) { + return new ConditionIterator(it, function (node) { + nit.setNode(node); + pit.reset(); + return pit.next(); + }); + } + return new ConditionIterator(it, function (node) { + nit.setNode(node); + pit.reset(); + var n = pit.next(); + // todo: distinuish between number and string + return n && n.nodeValue === value; + }); + } + /** + * @param {!XPathIterator} it + * @param {!Object} xpath + * @param {!Function} namespaceResolver + * @return {!XPathIterator} + */ + createXPathPathIterator = function createXPathPathIterator(it, xpath, + namespaceResolver) { + var i, j, step, location, namespace, localName, prefix, p; + for (i = 0; i < xpath.steps.length; i += 1) { + step = xpath.steps[i]; + location = step.location; + if (location === "") { + it = new AllChildElementIterator(it, false); + } else if (location[0] === '@') { + p = location.slice(1).split(":", 2); + it = new AttributeIterator(it, namespaceResolver(p[0]), p[1]); + } else if (location !== ".") { + it = new AllChildElementIterator(it, false); + if (location.indexOf(":") !== -1) { + it = createNodenameFilter(it, location, namespaceResolver); + } + } + for (j = 0; j < step.predicates.length; j += 1) { + p = step.predicates[j]; + it = createPredicateFilteredIterator(it, p, namespaceResolver); + } + } + return it; + }; + /** + * @param {!Element} node + * @param {!string} xpath + * @param {!Function} namespaceResolver + * @return {!Array.} + */ + function fallback(node, xpath, namespaceResolver) { + var it = new NodeIterator(), + i, + nodelist, + parsedXPath, + pos; + it.setNode(node); + parsedXPath = parseXPath(xpath); + it = createXPathPathIterator(it, parsedXPath, namespaceResolver); + nodelist = []; + i = it.next(); + while (i) { + nodelist.push(i); + i = it.next(); + } + return nodelist; + } + /** + * @param {!Element} node + * @param {!string} xpath + * @param {!Function} namespaceResolver + * @return {!Array.} + */ + function getODFElementsWithXPath(node, xpath, namespaceResolver) { + var doc = node.ownerDocument, + nodes, + elements = [], + n = null; + if (!doc || !doc.evaluate || !n) { + elements = fallback(node, xpath, namespaceResolver); + } else { + nodes = doc.evaluate(xpath, node, namespaceResolver, + XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); + n = nodes.iterateNext(); + while (n !== null) { + if (n.nodeType === 1) { + elements.push(n); + } + n = nodes.iterateNext(); + } + } + return elements; + } + /** + * @constructor + */ + xmldom.XPath = function XPath() { + this.getODFElementsWithXPath = getODFElementsWithXPath; + }; + return xmldom.XPath; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/misctests/carettest.html b/apps/files_odfviewer/src/webodf/webodf/misctests/carettest.html new file mode 100644 index 0000000000..fc7f84c926 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/misctests/carettest.html @@ -0,0 +1,135 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/misctests/selection.html b/apps/files_odfviewer/src/webodf/webodf/misctests/selection.html new file mode 100644 index 0000000000..d758237f39 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/misctests/selection.html @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/misctests/testselection.html b/apps/files_odfviewer/src/webodf/webodf/misctests/testselection.html new file mode 100644 index 0000000000..28ff15889b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/misctests/testselection.html @@ -0,0 +1,61 @@ + + + + + + +

+ + + diff --git a/apps/files_odfviewer/src/webodf/webodf/misctests/testzip.js b/apps/files_odfviewer/src/webodf/webodf/misctests/testzip.js new file mode 100644 index 0000000000..bd57807bf5 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/misctests/testzip.js @@ -0,0 +1,181 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime core*/ +runtime.loadClass("core.Zip"); +runtime.loadClass("core.Async"); + +var async = new core.Async(); + +/** + * @param {!core.Zip.ZipEntry} entry + * @param {!core.Zip} zip + * @param {function(?string):undefined} callback + * @return {undefined} + */ +function copyEntry(entry, zip, callback) { + entry.load(function (err, data) { + if (err) { + callback(err); + } else { + zip.save(entry.filename, data, false, entry.date); + callback(null); + } + }); +} + +/** + * @param {!core.Zip} zipa + * @param {!core.Zip} zipb + * @param {function(?string):undefined} callback + * @return {undefined} + */ +function compareZips(zipa, zipb, callback) { + var entriesa = zipa.getEntries(), + l = entriesa.length, + entriesb = zipb.getEntries(), + i, + j, + entrya, + entryb; + // compare the number of entries + if (entriesb.length !== l) { + callback("Number of entries is not equal."); + return; + } + // compare the meta data of the entries + for (i = 0; i < l; i += 1) { + entrya = entriesa[i]; + for (j = 0; j < l; j += 1) { + entryb = entriesb[j]; + if (entrya.filename === entryb.filename) { + break; + } + } + if (j === l) { + callback("Entry " + entrya.filename + " is not present in the " + + "second zip file."); + return; + } + if (entrya.date.valueOf() !== entryb.date.valueOf()) { + callback("Dates for entry " + entrya.filename + " is not equal: " + + entrya.date + " vs " + entryb.date); + return; + } + } + // compare the data in the entries + async.forEach(entriesa, function (entry, callback) { + entry.load(function (err, dataa) { + if (err) { + callback(err); + return; + } + zipb.load(entry.filename, function (err, datab) { + if (err) { + callback(err); + return; + } + var i = 0, l = dataa.length; + if (dataa !== datab) { + for (i = 0; i < l && dataa[i] === datab[i];) { + i += 1; + } + callback("Data is not equal for " + entry.filename + + " at position " + i + ": " + dataa.charCodeAt(i) + + " vs " + datab.charCodeAt(i) + "."); + } else { + callback(null); + } + }); + }); + }, function (err) { + callback(err); + }); +} + +function testZip(filepatha, callback) { + var zipa = new core.Zip(filepatha, function (err, zipa) { + if (err) { + runtime.log(err); + runtime.exit(1); + return; + } + // open a new zip file and copy all entries from zipa to zipb + var filepathb = "tmp323.zip", + zipb = new core.Zip(filepathb, null), + entries = zipa.getEntries(), + i, + entriesDone = 0; + async.forEach(entries, function (entry, callback) { + copyEntry(entry, zipb, callback); + }, function (err) { + if (err) { + callback(err); + return; + } + zipb.write(function (err) { + if (err) { + callback(err); + return; + } + zipb = new core.Zip(filepathb, function (err, zipb) { + if (err) { + callback(err); + return; + } + compareZips(zipa, zipb, callback); + }); + }); + }); + }); +} + +var args = arguments; +// open the arguments one by one, save them to a file, then open again and see +// if the contents matches +function doit(i) { + if (i >= args.length) { + return; + } + testZip(args[i], function (err) { + runtime.log(args[i]); + if (err) { + runtime.log(err); + return; + } + i += 1; + if (i < args.length) { + doit(i); + } + }); +} +doit(1); diff --git a/apps/files_odfviewer/src/webodf/webodf/misctests/writetest.zip b/apps/files_odfviewer/src/webodf/webodf/misctests/writetest.zip new file mode 100644 index 0000000000000000000000000000000000000000..69a14abc26f0936e933110307459d7c57e9e1670 GIT binary patch literal 153 zcmWIWW@h1H0D + + + + + + + + + + + + +
+ + diff --git a/apps/files_odfviewer/src/webodf/webodf/odfedit.html b/apps/files_odfviewer/src/webodf/webodf/odfedit.html new file mode 100644 index 0000000000..d4a5b53870 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/odfedit.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + WebODF + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/odfedit.js b/apps/files_odfviewer/src/webodf/webodf/odfedit.js new file mode 100644 index 0000000000..6dfc1cddac --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/odfedit.js @@ -0,0 +1,314 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, document: true, odf: true, window: true, Ext: true*/ +/** + * @type {odf.OdfCanvas} + */ +var odfcanvas; + +/** + * @return {undefined} + */ +function fixExtJSCSS() { + "use strict"; + // look through all stylesheets to change the selector + // ".x-viewport, .x-viewport body" + // to + // ".x-viewport, .x-viewport > body" + // The normal selector os not specific enough, office|body is also affected + // by it. To avoid this, the selector is changed so that is only applies to + // a director parent child relationship with '>' + var i, cssRules, j, rule; + for (i = 0; i < document.styleSheets.length; i += 1) { + cssRules = document.styleSheets[i].cssRules; + for (j = 0; j < cssRules.length; j += 1) { + rule = cssRules[j]; + if (rule.selectorText === ".x-viewport, .x-viewport body") { + rule = rule.cssText.replace(".x-viewport, .x-viewport body", + ".x-viewport, .x-viewport > body"); + document.styleSheets[i].deleteRule(j); + document.styleSheets[i].insertRule(rule, j); + return; + } + } + } +} +/** + * @return {undefined} + */ +function updateStyleComboBox() { + "use strict"; + var paragraphStylesBox = document.getElementById("paragraphStyleBox"); +} +/** + * @param {!Element} odfelement + * @return {undefined} + */ +function initCanvas(odfelement) { + "use strict"; + runtime.loadClass("odf.OdfCanvas"); + // if the url has a fragment (#...), try to load the file it represents + var location = String(document.location), + pos = location.indexOf('#'); +// odfelement.style.overflow = 'auto'; + odfelement.style.height = '100%'; + odfcanvas = new odf.OdfCanvas(odfelement); + if (pos === -1 || !window) { + return; + } + location = location.substr(pos + 1); + odfcanvas.onstatereadychange = function () { + /* + updateStyleComboBox(); + odfcanvas.save(function (err) { + alert(err); + }); + */ + }; + odfcanvas.load(location); + odfcanvas.addListener("selectionchange", function (element, selection) { + var formatting = odfcanvas.getFormatting(), + completelyBold = formatting.isCompletelyBold(selection), + alignment = formatting.getAlignment(selection); + runtime.log("selection changed " + completelyBold + " " + alignment); + }); +} +/** + * @return {undefined} + */ +function save() { + "use strict"; + odfcanvas.odfContainer().save(function (err) { + if (err) { + runtime.log(err); + } + }); +} +Ext.ODFEditor = Ext.extend(Ext.component.Component, { + buttonTips : { + bold : { + title: 'Bold (Ctrl+B)', + text: 'Make the selected text bold.', + cls: 'x-html-editor-tip' + }, + italic : { + title: 'Italic (Ctrl+I)', + text: 'Make the selected text italic.', + cls: 'x-html-editor-tip' + }, + underline : { + title: 'Underline (Ctrl+U)', + text: 'Underline the selected text.', + cls: 'x-html-editor-tip' + }, + increasefontsize : { + title: 'Grow Text', + text: 'Increase the font size.', + cls: 'x-html-editor-tip' + }, + decreasefontsize : { + title: 'Shrink Text', + text: 'Decrease the font size.', + cls: 'x-html-editor-tip' + }, + backcolor : { + title: 'Text Highlight Color', + text: 'Change the background color of the selected text.', + cls: 'x-html-editor-tip' + }, + forecolor : { + title: 'Font Color', + text: 'Change the color of the selected text.', + cls: 'x-html-editor-tip' + }, + justifyleft : { + title: 'Align Text Left', + text: 'Align text to the left.', + cls: 'x-html-editor-tip' + }, + justifycenter : { + title: 'Center Text', + text: 'Center text in the editor.', + cls: 'x-html-editor-tip' + }, + justifyright : { + title: 'Align Text Right', + text: 'Align text to the right.', + cls: 'x-html-editor-tip' + }, + insertunorderedlist : { + title: 'Bullet List', + text: 'Start a bulleted list.', + cls: 'x-html-editor-tip' + }, + insertorderedlist : { + title: 'Numbered List', + text: 'Start a numbered list.', + cls: 'x-html-editor-tip' + }, + createlink : { + title: 'Hyperlink', + text: 'Make the selected text a hyperlink.', + cls: 'x-html-editor-tip' + }, + sourceedit : { + title: 'Source Edit', + text: 'Switch to source editing mode.', + cls: 'x-html-editor-tip' + }, + save : { + title: 'Save (Ctrl+S)', + text: 'Save the document.', + cls: 'x-html-editor-tip' + } + } +}); + + +var ODFEditor = Ext.extend(Ext.Panel, { + initComponent: function () { + "use strict"; + var me = this, + statusMessage = new Ext.Toolbar.TextItem(''); + function buttonHandler(button, event) { + } + me.defaults = { + }; + me.initialConfig = Ext.apply({ + }, me.initialConfig); + me.items = [{ + xtype: 'box', + id: 'canvas', + autoEl: { + tag: 'div', + frameBorder: 0, + style: { + border: '0 none' + } + }, + autoScroll: true, + scroll: true + }]; + me.tbar = { + xtype: 'toolbar', + items: [{ + xtype: 'button', + icon: 'extjs/examples/shared/icons/save.gif', + handler: buttonHandler, + cls: 'x-btn-icon' + }, { + xtype: 'tbseparator' + }, { + tag: 'select', + //html: this.createFontOptions() + cls: 'x-font-select' + }, { + xtype: 'buttongroup', + cls: 'x-html-editor-tb', + frame: false, + items: [{ + xtype: 'button', + iconCls: 'x-edit-bold', + cls: 'x-btn-icon' + }, { + xtype: 'button', + iconCls: 'x-edit-italic', + cls: 'x-btn-icon' + }, { + xtype: 'button', + iconCls: 'x-edit-underline', + cls: 'x-btn-icon' + }, { + itemId: 'forecolor', + cls: 'x-btn-icon', + iconCls: 'x-edit-forecolor', + menu: { xtype: 'colormenu' } + }, { + itemId: 'backcolor', + cls: 'x-btn-icon', + iconCls: 'x-edit-backcolor', + menu: { xtype: 'colormenu' } + }, { + xtype: 'button', + iconCls: 'x-edit-justifyleft', + cls: 'x-btn-icon' + }, { + xtype: 'button', + iconCls: 'x-edit-justifycenter', + cls: 'x-btn-icon' + }, { + xtype: 'button', + iconCls: 'x-edit-justifyright', + cls: 'x-btn-icon' + }, { + xtype: 'button', + iconCls: 'x-edit-insertorderedlist', + cls: 'x-btn-icon' + }, { + xtype: 'button', + iconCls: 'x-edit-insertunorderedlist', + cls: 'x-btn-icon' + }] + }, { + xtype: 'tbfill' + }, + statusMessage + ] + }; +/* + me.bbar = { + xtype: 'toolbar', + items: [ {xtype: "tbfill" }, statusMessage ] + }; +*/ + ODFEditor.superclass.initComponent.call(this); + } +}); +Ext.onReady(function () { + "use strict"; + var canvas, viewport; + + Ext.QuickTips.init(); + + canvas = new ODFEditor({ + region: 'center' + }); + + viewport = new Ext.Viewport({ + layout: 'border', + items: [ canvas ] + }); + + fixExtJSCSS(); + initCanvas(Ext.getCmp('canvas').el.dom); +}); diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngToCPP.js b/apps/files_odfviewer/src/webodf/webodf/relaxngToCPP.js new file mode 100644 index 0000000000..064fe61b79 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngToCPP.js @@ -0,0 +1,463 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, xmldom: true*/ +runtime.loadClass("xmldom.RelaxNGParser"); + +var nsmap = { + "http://purl.org/dc/elements/1.1/": "purl", + "http://www.w3.org/1998/Math/MathML": "mathml", + "http://www.w3.org/1999/xhtml": "xhtml", + "http://www.w3.org/1999/xlink": "xlink", + "http://www.w3.org/2002/xforms": "xforms", + "http://www.w3.org/2003/g/data-view#": "dv", + "http://www.w3.org/XML/1998/namespace": "xmlns", + "urn:oasis:names:tc:opendocument:xmlns:animation:1.0": "animation", + "urn:oasis:names:tc:opendocument:xmlns:chart:1.0": "chart", + "urn:oasis:names:tc:opendocument:xmlns:config:1.0": "config", + "urn:oasis:names:tc:opendocument:xmlns:database:1.0": "database", + "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0": "datastyle", + "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0": "dr3d", + "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0": "drawing", + "urn:oasis:names:tc:opendocument:xmlns:form:1.0": "form", + "urn:oasis:names:tc:opendocument:xmlns:meta:1.0": "meta", + "urn:oasis:names:tc:opendocument:xmlns:office:1.0": "office", + "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0": "presentation", + "urn:oasis:names:tc:opendocument:xmlns:script:1.0": "script", + "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0": "smilc", + "urn:oasis:names:tc:opendocument:xmlns:style:1.0": "style", + "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0": "svgc", + "urn:oasis:names:tc:opendocument:xmlns:table:1.0": "table", + "urn:oasis:names:tc:opendocument:xmlns:text:1.0": "text", + "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0": "xslfoc" + }, + typemap = { + "string": "const QString&", + "NCName": "const QString&", + "date": "const QString&", + "time": "const QString&", + "dateTime": "const QString&", + "duration": "const QString&", + "anyURI": "const QString&", + "ID": "const QString&", + "IDREF": "const QString&", + "IDREFS": "const QString&", + "QName": "const QString&", + "token": "const QString&", + "language": "const QString&", + "positiveInteger": "quint32", + "nonNegativeInteger": "quint32", + "integer": "qint32", + "decimal": "double" + }, + args = arguments, + relaxngurl = args[1], + parser = new xmldom.RelaxNGParser(relaxngurl); + +function out(string) { + "use strict"; + runtime.log(string); +} +function toCamelCase(s) { + "use strict"; + var str = "", i, up = true; + for (i = 0; i < s.length; i += 1) { + if (up) { + str += s.substr(i, 1).toUpperCase(); + } else { + str += s.substr(i, 1); + } + up = false; + while (/\W/.test(s.substr(i + 1, 1))) { + up = true; + i += 1; + } + } + return str; +} +function getName(e) { + "use strict"; + return toCamelCase(nsmap[e.a.ns]) + toCamelCase(e.text); +} +function getNames(e, names) { + "use strict"; + if (e.name === "name") { + names.push(e); + } else if (e.name === "choice") { + getNames(e.e[0], names); + getNames(e.e[1], names); + } +} +function parseAttributes(e, att) { + "use strict"; + var i, name; + if (e.name === "choice" || e.name === "interleave" + || e.name === "group") { + for (i = 0; i < e.e.length; i += 1) { + parseAttributes(e.e[i], att); + } + } else if (e.name === "value") { + att.values.push(e.text); + } else if (e.name === "data") { + att.types.push(e.a.type); + } else if (e.name === "list") { + name = null; // todo + } else if (e.name === "empty") { + att.empty = true; + } else { + runtime.log("OOPS " + e.name); + throw null; + } +} +function writeAttributeSetter(name, type, a) { + "use strict"; + var i, s = ""; + out(" /**"); + if (a.optional) { + out(" * Set optional attribute " + a.nsname + "."); + } else { + out(" * Set required attribute " + a.nsname + "."); + } + if (a.values.length > 0) { + s = "Choose one of these values: '" + a.values[0] + "'"; + for (i = 1; i < a.values.length; i += 1) { + s += ", '" + a.values[i] + "'"; + } + out(" * " + s + "."); + } + out(" */"); + out(" inline void write" + name + "(" + type + " value) {"); + out(" xml->addAttribute(\"" + a.nsname + "\", value);"); + out(" }"); +} +function writeAttribute(name, a) { + "use strict"; + if (!a.optional) { + return; + } + var i, type, done = {}, needfallback = true; + for (i = 0; i < a.types.length; i += 1) { + needfallback = false; + type = typemap[a.types[i]] || a.types[i]; + if (!done.hasOwnProperty(type)) { + done[type] = 1; + writeAttributeSetter(name, type, a); + } + } + if (a.values.indexOf("true") !== -1 && a.values.indexOf("false") !== -1 && + done.hasOwnProperty("bool")) { + needfallback = false; + writeAttributeSetter(name, "bool", a); + } + if (needfallback) { + writeAttributeSetter(name, "const QString&", a); + } +} +function writeOptionalAttributes(atts) { + "use strict"; + var name; + for (name in atts) { + if (atts.hasOwnProperty(name)) { + writeAttribute(name, atts[name]); + } + } +} +function writeFixedRequiredAttributes(atts) { + "use strict"; + var name, a; + for (name in atts) { + if (atts.hasOwnProperty(name)) { + a = atts[name]; + if (!a.optional && a.types.length === 0 && a.values.length === 1) { + out(" xml->addAttribute(\"" + a.nsname + "\", \"" + + a.values[0] + "\");"); + } + } + } +} +function getRequiredAttributeArguments(atts) { + "use strict"; + var name, a, s = "", type; + for (name in atts) { + if (atts.hasOwnProperty(name)) { + a = atts[name]; + if (!a.optional && (a.types.length > 0 || a.values.length !== 1)) { + type = typemap[a.types[0]] || a.types[0] || "const QString&"; + if (s) { + s += ", "; + } + s += type + " " + name.toLowerCase(); + } + } + } + return s; +} +function getRequiredAttributeCall(atts) { + "use strict"; + var name, a, s = ""; + for (name in atts) { + if (atts.hasOwnProperty(name)) { + a = atts[name]; + if (!a.optional && (a.types.length > 0 || a.values.length !== 1)) { + if (s) { + s += ", "; + } + s += name.toLowerCase(); + } + } + } + return s; +} +function writeRequiredAttributesSetters(atts) { + "use strict"; + var name, a; + for (name in atts) { + if (atts.hasOwnProperty(name)) { + a = atts[name]; + if (!a.optional && (a.types.length > 0 || a.values.length !== 1)) { + out(" xml->addAttribute(\"" + a.nsname + "\", " + + name.toLowerCase() + ");"); + } + } + } +} +function writeMembers(e, atts, optional) { + "use strict"; + var ne, nsname, i, name, names; + if (e.name === "element") { + name = null; + } else if (e.name === "attribute") { + names = []; + getNames(e.e[0], names); + for (i = 0; i < names.length; i += 1) { + ne = names[i]; + name = getName(ne); + if (!atts.hasOwnProperty(name)) { + nsname = nsmap[ne.a.ns] + ":" + ne.text; + atts[name] = { + nsname: nsname, + values: [], + types: [], + optional: optional, + empty: false + }; + } + parseAttributes(e.e[1], atts[name]); + } + } else if (e.name === "choice") { + for (i = 0; i < e.e.length; i += 1) { + writeMembers(e.e[i], atts, true); + } + } else if (e.name === "interleave" || e.name === "group") { + for (i = 0; i < e.e.length; i += 1) { + writeMembers(e.e[i], atts, optional); + } + } else if (e.name === "oneOrMore") { + writeMembers(e.e[0], atts, optional); + } else if (e.name === "value") { + name = null; // todo + } else if (e.name === "data") { + name = null; // todo + } else if (e.name === "text") { + out(" void addTextNode(const QString& str) { xml->addTextNode(str); }"); + } else if (e.name === "empty") { + name = null; // todo + } else { + runtime.log("OOPS " + e.name); + throw null; + } +} +function defineClass(e, parents, children) { + "use strict"; + var c, p, i, + ne = e.e[0], + nsname = nsmap[ne.a.ns] + ":" + ne.text, + name = ne.cppname, atts = {}; + out("/**"); + out(" * Serialize a <" + nsname + "> element."); + out(" */"); + out("class " + name + "Writer {"); + for (c in children) { + if (children.hasOwnProperty(c) && c !== name) { + out("friend class " + c + "Writer;"); + } + } + out("public:"); + writeMembers(e.e[1], atts, false); + writeOptionalAttributes(atts); + e.requiredAttributes = getRequiredAttributeArguments(atts); + e.requiredAttributeCall = getRequiredAttributeCall(atts); + out("private:"); + out(" inline void start(" + e.requiredAttributes + ") {"); + out(" xml->startElement(\"" + nsname + "\");"); + if (e.requiredAttributes) { + e.requiredAttributes = ", " + e.requiredAttributes; + } + writeFixedRequiredAttributes(atts); + writeRequiredAttributesSetters(atts); + out(" }"); + out("public:"); + out(" KoXmlWriter* const xml;"); + for (p in parents) { + if (parents.hasOwnProperty(p)) { + out(" inline explicit " + name + "Writer(const " + p + + "Writer& p" + e.requiredAttributes + ");"); + } + } + out(" inline explicit " + name + "Writer(KoXmlWriter* xml_" + + e.requiredAttributes + + ") :xml(xml_) { start(" + e.requiredAttributeCall + "); }"); + out(" void end() { xml->endElement(); }"); + out(" void operator=(const " + name + "Writer&) { }"); + out("};"); +} +function defineConstructors(e, parents) { + "use strict"; + var p, + ne = e.e[0], + nsname = nsmap[ne.a.ns] + ":" + ne.text, + name = ne.cppname; + for (p in parents) { + if (parents.hasOwnProperty(p)) { + out(name + "Writer::" + name + "Writer(const " + p + + "Writer& p" + e.requiredAttributes + + ") :xml(p.xml) { start(" + e.requiredAttributeCall + "); }"); + } + } +} +function getChildren(e, children) { + "use strict"; + var name, i, names; + if (e.name === "element") { + names = []; + getNames(e.e[0], names); + for (i = 0; i < names.length; i += 1) { + children[names[i].cppname] = 1; + } + } else if (e.name === "choice" || e.name === "interleave" + || e.name === "group") { + for (i = 0; i < e.e.length; i += 1) { + getChildren(e.e[i], children); + } + } else if (e.name === "oneOrMore") { + getChildren(e.e[0], children); + } else if (e.name === "attribute" || e.name === "value" || + e.name === "data" || e.name === "text" || e.name === "empty") { + name = null; // ignore + } else { + runtime.log("OOPS " + e.name); + throw null; + } +} +function childrenToParents(childrenmap) { + "use strict"; + var p, children, c, parents = {}; + for (p in childrenmap) { + if (childrenmap.hasOwnProperty(p)) { + children = childrenmap[p]; + for (c in children) { + if (children.hasOwnProperty(c)) { + if (!parents.hasOwnProperty(c)) { + parents[c] = {}; + } + parents[c][p] = 1; + } + } + } + } + return parents; +} +function toCPP(elements) { + "use strict"; + out("#include "); + + // first get a mapping for all the parents + var children = {}, parents = {}, i, j, ce, ec, name, names, c, + elementMap = {}, sortedElementNames = []; + for (i = 0; i < elements.length; i += 1) { + ce = elements[i]; + if (ce.name !== "element") { + runtime.log("Error in parsed data."); + return; + } + names = []; + getNames(ce.e[0], names); + for (j = 0; j < names.length; j += 1) { + name = getName(names[j]); + while (elementMap.hasOwnProperty(name)) { + name = name + "_"; + } + names[j].cppname = name; + ec = {e: [names[j], ce.e[1]]}; + elementMap[name] = ec; + sortedElementNames.push(name); + } + } + sortedElementNames.sort(); + + for (i = 0; i < sortedElementNames.length; i += 1) { + name = sortedElementNames[i]; + c = {}; + getChildren(elementMap[name].e[1], c); + children[name] = c; + } + parents = childrenToParents(children); + + for (i = 0; i < sortedElementNames.length; i += 1) { + name = sortedElementNames[i]; + out("class " + name + "Writer;"); + } + for (i = 0; i < sortedElementNames.length; i += 1) { + name = sortedElementNames[i]; + defineClass(elementMap[name], parents[name], children[name]); + } + for (i = 0; i < sortedElementNames.length; i += 1) { + name = sortedElementNames[i]; + defineConstructors(elementMap[name], parents[name]); + } +} + +// load and parse the Relax NG +runtime.loadXML(relaxngurl, function (err, dom) { + "use strict"; + var parser = new xmldom.RelaxNGParser(); + if (err) { + runtime.log(err); + } else { + err = parser.parseRelaxNGDOM(dom); + if (err) { + runtime.log(err); + } else { + toCPP(parser.elements); + } + } +}); diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.rng new file mode 100644 index 0000000000..0c4e4baa8d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.rng @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + 1.2 + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.xml new file mode 100644 index 0000000000..71712e11e5 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test01.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.rng new file mode 100644 index 0000000000..ed37e255fd --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.rng @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + NamespaceTable + + + + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + chart + + + + + + + + table + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.xml new file mode 100644 index 0000000000..7e70255ed4 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test02.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.rng new file mode 100644 index 0000000000..8803f52898 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.rng @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.xml new file mode 100644 index 0000000000..a6255e802e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test03.xml @@ -0,0 +1,6 @@ + + + hello + + hi + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.rng new file mode 100644 index 0000000000..511b297efa --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.rng @@ -0,0 +1,18 @@ + + + + + + + 1.2 + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.xml new file mode 100644 index 0000000000..21ceee55b1 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test04.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.rng new file mode 100644 index 0000000000..c0c73052f2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.rng @@ -0,0 +1,42 @@ + + + + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.xml new file mode 100644 index 0000000000..38cb418bde --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test05.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.rng new file mode 100644 index 0000000000..c744850f98 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.rng @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.xml new file mode 100644 index 0000000000..a9c24656ea --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test06.xml @@ -0,0 +1,4 @@ + + + hello + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.rng new file mode 100644 index 0000000000..fb37cf8275 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.rng @@ -0,0 +1,52 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + boolean + short + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.xml new file mode 100644 index 0000000000..a5361bf155 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test07.xml @@ -0,0 +1,14 @@ + + + + + true + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.rng new file mode 100644 index 0000000000..82c2de66c5 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.rng @@ -0,0 +1,52 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + boolean + string + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.xml new file mode 100644 index 0000000000..71af08046c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test08.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.rng new file mode 100644 index 0000000000..1726996897 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.rng @@ -0,0 +1,30 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.xml new file mode 100644 index 0000000000..a54dd99e4b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test09.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.rng new file mode 100644 index 0000000000..5e271a4389 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.rng @@ -0,0 +1,50 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.xml new file mode 100644 index 0000000000..f4087a8976 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test10.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.rng new file mode 100644 index 0000000000..2df604b5b8 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.rng @@ -0,0 +1,75 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.xml new file mode 100644 index 0000000000..d272fd4e3e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test11.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.rng new file mode 100644 index 0000000000..a0e79a356e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.rng @@ -0,0 +1,97 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.xml new file mode 100644 index 0000000000..a3f2a5d725 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test12.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.rng new file mode 100644 index 0000000000..47a2161ed9 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.rng @@ -0,0 +1,71 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.xml new file mode 100644 index 0000000000..8f46daa4ce --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test13.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.rng new file mode 100644 index 0000000000..61a8c9e2b4 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.rng @@ -0,0 +1,45 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + table + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.xml new file mode 100644 index 0000000000..6c16a1d614 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test14.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.rng new file mode 100644 index 0000000000..63557c6e2b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.rng @@ -0,0 +1,47 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.xml new file mode 100644 index 0000000000..4d8361aaa6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test15.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.rng new file mode 100644 index 0000000000..32c6cb8e2c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.rng @@ -0,0 +1,46 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.xml new file mode 100644 index 0000000000..4d8361aaa6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test16.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.rng new file mode 100644 index 0000000000..ffcd9bd4f9 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.rng @@ -0,0 +1,51 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.xml new file mode 100644 index 0000000000..0947bff2b1 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test17.xml @@ -0,0 +1,17 @@ + + + + + + + 03 + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.rng new file mode 100644 index 0000000000..9ddbb9baaf --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.rng @@ -0,0 +1,25 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.xml new file mode 100644 index 0000000000..cc6ab02761 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test18.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.rng new file mode 100644 index 0000000000..ac676d982d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.rng @@ -0,0 +1,43 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + text:reference-ref + text:bookmark-ref + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.xml new file mode 100644 index 0000000000..c562015a37 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test19.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.rng new file mode 100644 index 0000000000..bd6b4e0f05 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.rng @@ -0,0 +1,32 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.xml new file mode 100644 index 0000000000..e28b855386 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test20.xml @@ -0,0 +1,11 @@ + + + + + ,, + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.rng new file mode 100644 index 0000000000..032886009d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.rng @@ -0,0 +1,47 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + misc + + + + + text:url + text:custom5 + text:year + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.xml new file mode 100644 index 0000000000..fec92948f9 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test21.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.rng new file mode 100644 index 0000000000..154c810975 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.rng @@ -0,0 +1,32 @@ + + + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.xml new file mode 100644 index 0000000000..dd84419d66 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test22.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.rng b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.rng new file mode 100644 index 0000000000..1a02206d04 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.rng @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.xml b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.xml new file mode 100644 index 0000000000..b622196b05 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/relaxngtests/test23.xml @@ -0,0 +1,4 @@ + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/roundtripodf.js b/apps/files_odfviewer/src/webodf/webodf/roundtripodf.js new file mode 100644 index 0000000000..6d16d1b2a3 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/roundtripodf.js @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, odf: true*/ +runtime.loadClass("odf.OdfContainer"); + +/** + * If the state of the OdfContainer is invalid, exit with an error message. + */ +function exitOnInvalid(odffilepath, odfcontainer) { + "use strict"; + if (odfcontainer.state === odf.OdfContainer.INVALID) { + runtime.log("Document " + odffilepath + " is invalid."); + runtime.exit(1); + } + if (odfcontainer.state === odf.OdfContainer.DONE) { + odfcontainer.save(function (err) { + if (err) { + runtime.log(err); + runtime.exit(1); + } + }); + } +} + +/** + * Load an ODF document. Report an error if there is a problem. + */ +function loadODF(odffilepath) { + "use strict"; + var odfcontainer = new odf.OdfContainer(odffilepath); + odfcontainer.onstatereadychange = function () { + exitOnInvalid(odffilepath, odfcontainer); + }; + exitOnInvalid(odffilepath, odfcontainer); +} + +// loop over arguments to load ODF +var i; +for (i = 1; i < arguments.length; i += 1) { + loadODF(arguments[i]); +} diff --git a/apps/files_odfviewer/src/webodf/webodf/roundtripzip.js b/apps/files_odfviewer/src/webodf/webodf/roundtripzip.js new file mode 100644 index 0000000000..d3fe17fc81 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/roundtripzip.js @@ -0,0 +1,64 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true*/ +runtime.loadClass("core.Zip"); + +/** + * Load an ODF document. Report an error if there is a problem. + */ +function roundTripZip(zipfilepath) { + "use strict"; + var zip = new core.Zip(zipfilepath, function (err, zip) { + if (err) { + runtime.log(err); + runtime.exit(1); + } + // the TOC of the zip is loaded at this point + // now we want to load all parts in memory so we can save them again + zip.write(function (err) { + if (err) { + runtime.log(err); + runtime.exit(1); + } + // at this point a zip file should have been written with the same + // contents as the one that was read + runtime.exit(0); + }); + }); +} + +// loop over arguments to load ODF +var i; +for (i = 1; i < arguments.length; i += 1) { + roundTripZip(arguments[i]); +} diff --git a/apps/files_odfviewer/src/webodf/webodf/styleNameRef b/apps/files_odfviewer/src/webodf/webodf/styleNameRef new file mode 100644 index 0000000000..39b2914746 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/styleNameRef @@ -0,0 +1,272 @@ +# cat styles.xml|xmlstarlet sel -N style=urn:oasis:names:tc:opendocument:xmlns:style:1.0 -t -m "//*[@style:family='graphic']/@style:name" -v . - + +gradient + draw:fill-gradient-name style:drawing-page-properties + draw:fill-gradient-name style:graphic-properties + +hatch + draw:fill-hatch-name style:drawing-page-properties + draw:fill-hatch-name style:graphic-properties + +fill-image + draw:fill-image-name style:drawing-page-properties + draw:fill-image-name style:graphic-properties + +marker + draw:marker-end style:graphic-properties + draw:marker-start style:graphic-properties + +dash + draw:stroke-dash style:graphic-properties + +opacity + draw:opacity-name style:drawing-page-properties + draw:opacity-name style:graphic-properties + +master page + draw:master-page-name draw:page + style:master-page-name style:style + style:next-style-name style:master-page + text:master-page-name text:notes-configuration + text:master-page-name text:page + +presentation-page-layout + presentation:presentation-page-layout-name draw:page + presentation:presentation-page-layout-name draw:handout-master + +page-layout + style:page-layout-name presentation:notes + style:page-layout-name style:handout-master + style:page-layout-name style:master-page + +list + text:style-name text:list + text:style-name text:numbered-paragraph + text:style-override text:list-item + style:list-style-name style:style + +data + style:data-style-name style:style + style:percentage-data-style-name style:style + style:data-style-name presentation:date-time-decl + style:data-style-name text:creation-date + style:data-style-name text:creation-time + style:data-style-name text:database-display + style:data-style-name text:date + style:data-style-name text:editing-duration + style:data-style-name text:expression + style:data-style-name text:meta-field + style:data-style-name text:modification-date + style:data-style-name text:modification-time + style:data-style-name text:print-date + style:data-style-name text:print-time + style:data-style-name text:table-formula + style:data-style-name text:time + style:data-style-name text:user-defined + style:data-style-name text:user-field-get + style:data-style-name text:user-field-input + style:data-style-name text:variable-get + style:data-style-name text:variable-input + style:data-style-name text:variable-set + +chart + chart:style-name chart:axis + chart:style-name chart:chart + chart:style-name chart:data-label + chart:style-name chart:data-point + chart:style-name chart:equation + chart:style-name chart:error-indicator + chart:style-name chart:floor + chart:style-name chart:footer + chart:style-name chart:grid + chart:style-name chart:legend + chart:style-name chart:mean-value + chart:style-name chart:plot-area + chart:style-name chart:regression-curve + chart:style-name chart:series + chart:style-name chart:stock-gain-marker + chart:style-name chart:stock-loss-marker + chart:style-name chart:stock-range-line + chart:style-name chart:subtitle + chart:style-name chart:title + chart:style-name chart:wall + +---- + +drawing-page + draw:style-name draw:page + draw:style-name presentation:notes + draw:style-name style:handout-master + draw:style-name style:master-page + +graphic + draw:style-name dr3d:cube + draw:style-name dr3d:extrude + draw:style-name dr3d:rotate + draw:style-name dr3d:scene + draw:style-name dr3d:sphere + draw:style-name draw:caption + draw:style-name draw:circle + draw:style-name draw:connector + draw:style-name draw:control + draw:style-name draw:custom-shape + draw:style-name draw:ellipse + draw:style-name draw:frame + draw:style-name draw:g + draw:style-name draw:line + draw:style-name draw:measure + draw:style-name draw:page-thumbnail + draw:style-name draw:path + draw:style-name draw:polygon + draw:style-name draw:polyline + draw:style-name draw:rect + draw:style-name draw:regular-polygon + draw:style-name office:annotation + +paragraph + draw:text-style-name draw:caption + draw:text-style-name draw:circle + draw:text-style-name draw:connector + draw:text-style-name draw:control + draw:text-style-name draw:custom-shape + draw:text-style-name draw:ellipse + draw:text-style-name draw:frame + draw:text-style-name draw:line + draw:text-style-name draw:measure + draw:text-style-name draw:path + draw:text-style-name draw:polygon + draw:text-style-name draw:polyline + draw:text-style-name draw:rect + draw:text-style-name draw:regular-polygon + draw:text-style-name office:annotation + form:text-style-name form:column + style:next-style-name style:style + table:paragraph-style-name table:body + table:paragraph-style-name table:even-columns + table:paragraph-style-name table:even-rows + table:paragraph-style-name table:first-column + table:paragraph-style-name table:first-row + table:paragraph-style-name table:last-column + table:paragraph-style-name table:last-row + table:paragraph-style-name table:odd-columns + table:paragraph-style-name table:odd-rows + text:default-style-name text:notes-configuration + text:style-name text:alphabetical-index-entry-template + text:style-name text:bibliography-entry-template + text:style-name text:h + text:style-name text:illustration-index-entry-template + text:style-name text:index-source-style + text:style-name text:object-index-entry-template + text:style-name text:p + text:style-name text:table-index-entry-template + text:style-name text:table-of-content-entry-template + text:style-name text:table-index-entry-template + text:style-name text:user-index-entry-template + style:register-truth-ref-style-name style:page-layout-properties + +presentation + presentation:style-name dr3d:cube + presentation:style-name dr3d:extrude + presentation:style-name dr3d:rotate + presentation:style-name dr3d:scene + presentation:style-name dr3d:sphere + presentation:style-name draw:caption + presentation:style-name draw:circle + presentation:style-name draw:connector + presentation:style-name draw:control + presentation:style-name draw:custom-shape + presentation:style-name draw:ellipse + presentation:style-name draw:frame + presentation:style-name draw:g + presentation:style-name draw:line + presentation:style-name draw:measure + presentation:style-name draw:page-thumbnail + presentation:style-name draw:path + presentation:style-name draw:polygon + presentation:style-name draw:polyline + presentation:style-name draw:rect + presentation:style-name draw:regular-polygon + presentation:style-name office:annotation + +ruby + text:style-name text:ruby + +section + text:style-name text:alphabetical-index + text:style-name text:bibliography + text:style-name text:illustration-index + text:style-name text:index-title + text:style-name text:object-index + text:style-name text:section + text:style-name text:table-of-content + text:style-name text:table-index + text:style-name text:user-index + +table-cell + db:default-cell-style-name db:column + table:default-cell-style-name table:table-column + table:default-cell-style-name table:table-row + table:style-name table:body + table:style-name table:covered-table-cell + table:style-name table:even-columns + table:style-name table:covered-table-cell + table:style-name table:even-columns + table:style-name table:even-rows + table:style-name table:first-column + table:style-name table:first-row + table:style-name table:last-column + table:style-name table:last-row + table:style-name table:odd-columns + table:style-name table:odd-rows + table:style-name table:table-cell + +table-row + db:default-row-style-name db:query + db:default-row-style-name db:table-representation + table:style-name table:table-row + +table-column + db:style-name db:column + table:style-name table:table-column + +table + db:style-name db:query + db:style-name db:table-representation + table:style-name table:background + table:style-name table:table + +text + style:leader-text-style style:tab-stop + style:style-name style:drop-cap + text:citation-body-style-name text:notes-configuration + text:citation-style-name text:notes-configuration + text:style-name text:a + text:style-name text:alphabetical-index + text:style-name text:linenumbering-configuration + text:style-name text:list-level-style-number + text:style-name text:ruby-text + text:style-name text:span + text:visited-style-name text:a + style:text-line-through-text-style style:text-properties + text:main-entry-style-name text:alphabetical-index-source + text:style-name text:index-entry-bibliography + text:style-name text:index-entry-chapter + text:style-name text:index-entry-link-end + text:style-name text:index-entry-link-start + text:style-name text:index-entry-page-number + text:style-name text:index-entry-span + text:style-name text:index-entry-tab-stop + text:style-name text:index-entry-text + text:style-name text:index-title-template + text:style-name text:list-level-style-bullet + text:style-name text:outline-level-style + + +--- + +conditional style + text:cond-style-name text:h + text:cond-style-name text:p + +style:apply-style-name # complicated! +style:parent-style-name # complicated! diff --git a/apps/files_odfviewer/src/webodf/webodf/styleNameRefs b/apps/files_odfviewer/src/webodf/webodf/styleNameRefs new file mode 100644 index 0000000000..e63e3562df --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/styleNameRefs @@ -0,0 +1,57 @@ +dash + draw:stroke-dash-names style:graphic-properties + +graphic + draw:class-names dr3d:cube + draw:class-names dr3d:extrude + draw:class-names dr3d:rotate + draw:class-names dr3d:scene + draw:class-names dr3d:sphere + draw:class-names draw:caption + draw:class-names draw:circle + draw:class-names draw:connector + draw:class-names draw:control + draw:class-names draw:custom-shape + draw:class-names draw:ellipse + draw:class-names draw:frame + draw:class-names draw:g + draw:class-names draw:line + draw:class-names draw:measure + draw:class-names draw:page-thumbnail + draw:class-names draw:path + draw:class-names draw:polygon + draw:class-names draw:polyline + draw:class-names draw:rect + draw:class-names draw:regular-polygon + draw:class-names office:annotation + +paragraph + text:class-names text:h + text:class-names text:p + +presentation + presentation:class-names dr3d:cube + presentation:class-names dr3d:extrude + presentation:class-names dr3d:rotate + presentation:class-names dr3d:scene + presentation:class-names dr3d:sphere + presentation:class-names draw:caption + presentation:class-names draw:circle + presentation:class-names draw:connector + presentation:class-names draw:control + presentation:class-names draw:custom-shape + presentation:class-names draw:ellipse + presentation:class-names draw:frame + presentation:class-names draw:g + presentation:class-names draw:line + presentation:class-names draw:measure + presentation:class-names draw:page-thumbnail + presentation:class-names draw:path + presentation:class-names draw:polygon + presentation:class-names draw:polyline + presentation:class-names draw:rect + presentation:class-names draw:regular-polygon + presentation:class-names office:annotation + +text + text:class-names text:span diff --git a/apps/files_odfviewer/src/webodf/webodf/testrelaxng.js b/apps/files_odfviewer/src/webodf/webodf/testrelaxng.js new file mode 100644 index 0000000000..875faa9de8 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/testrelaxng.js @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, xmldom: true*/ +runtime.loadClass("xmldom.RelaxNG"); +runtime.loadClass("xmldom.RelaxNG2"); + +function validate(relaxng, relaxng2, url) { + "use strict"; + runtime.loadXML(url, function (err, dom) { + var walker; + if (err) { + runtime.log("Could not read " + url + ": " + err); + } else { + walker = dom.createTreeWalker(dom.firstChild, 0xFFFFFFFF); + relaxng.validate(walker, function (err) { + if (err) { + var i; + runtime.log("Found " + String(err.length) + + " error validating " + url + ":"); + for (i = 0; i < err.length; i += 1) { + runtime.log(err[i].message()); + } + } + }); + relaxng2.validate(walker, function (err) { + if (err) { + var i; + runtime.log("Found " + String(err.length) + + " error validating " + url + ":"); + for (i = 0; i < err.length; i += 1) { + runtime.log(err[i].message()); + } + } + }); + } + }); +} + +var args = arguments, + relaxngurl = args[1]; + +// load and parse the Relax NG +runtime.loadXML(relaxngurl, function (err, dom) { + "use strict"; + var parser, i, relaxng, relaxng2; + if (err) { + return; + } + parser = new xmldom.RelaxNGParser(); + relaxng = new xmldom.RelaxNG(); + relaxng2 = new xmldom.RelaxNG2(); + err = parser.parseRelaxNGDOM(dom, relaxng.makePattern); + relaxng.init(parser.rootPattern); + relaxng2.init(parser.start, parser.nsmap); + + // loop over arguments to load ODF + for (i = 2; i < args.length; i += 1) { + runtime.log("Validating " + args[i] + " from " + relaxngurl); + validate(relaxng, relaxng2, args[i]); + } +}); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/core/Base64Tests.js b/apps/files_odfviewer/src/webodf/webodf/tests/core/Base64Tests.js new file mode 100644 index 0000000000..10156a1dc4 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/core/Base64Tests.js @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, runtime: true*/ +runtime.loadClass("core.Base64"); +/** + * @constructor + * @param runner {UnitTestRunner} + * @implements {core.UnitTest} + */ +core.Base64Tests = function Base64Tests(runner) { + "use strict"; + var t, r = runner, base64 = new core.Base64(); + + function testConvertByteArrayToBase64() { + t.encoded = base64.convertByteArrayToBase64([65]); + r.shouldBe(t, "t.encoded", "'QQ=='"); + t.encoded = base64.convertByteArrayToBase64([65, 65]); + r.shouldBe(t, "t.encoded", "'QUE='"); + t.encoded = base64.convertByteArrayToBase64([65, 65, 65]); + r.shouldBe(t, "t.encoded", "'QUFB'"); + } + + function testToBase64() { + t.encoded = base64.toBase64("A"); + r.shouldBe(t, "t.encoded", "'QQ=='"); + t.encoded = base64.toBase64("AA"); + r.shouldBe(t, "t.encoded", "'QUE='"); + t.encoded = base64.toBase64("AAA"); + r.shouldBe(t, "t.encoded", "'QUFB'"); + } + + function testConvertUTF8StringToUTF16String(callback) { + var bin = "1234567890"; + while (bin.length < 100000) { + bin += bin; + } + t.numcallbacks = 0; + base64.convertUTF8StringToUTF16String(bin, function (str, done) { + t.numcallbacks += 1; + t.done = done; + if (t.numcallbacks === 1) { + r.shouldBe(t, "t.done", "false"); + } else { + r.shouldBe(t, "t.done", "true"); + } + if (done) { + r.shouldBe(t, "t.numcallbacks", "2"); + t.str = str; + t.bin = bin; + r.shouldBe(t, "t.str.length", "t.bin.length"); + callback(); + } + return true; + }); + } + + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return [ + testConvertByteArrayToBase64, + testToBase64 + ]; + }; + this.asyncTests = function () { + return [ testConvertUTF8StringToUTF16String ]; + }; + this.description = function () { + return "Test the Base64 class."; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/core/CursorTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/core/CursorTests.js new file mode 100644 index 0000000000..c9f7be78a6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/core/CursorTests.js @@ -0,0 +1,238 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, runtime: true*/ +runtime.loadClass("core.Cursor"); + +/** + * @constructor + * @param {core.UnitTestRunner} runner + * @implements {core.UnitTest} + */ +core.CursorTests = function CursorTests(runner) { + "use strict"; + var r = runner, tests, t = {}, + maindoc = runtime.getWindow().document, + testarea = maindoc.getElementById("testarea"); + /** + * @param {Selection} selection + * @param {Node} startnode + * @param {number} startoffset + * @param {Node=} endnode + * @param {number=} endoffset + * @return {undefined} + */ + function setSelection(selection, startnode, startoffset, endnode, + endoffset) { + // call createRange() on the document, even if startnode is the document + var range = (startnode.ownerDocument || startnode).createRange(); + selection.removeAllRanges(); + range.setStart(startnode, startoffset); + if (endnode) { + range.setEnd(endnode, endoffset); + } else { + range.setEnd(startnode, startoffset); + } + selection.addRange(range); + if (range.startContainer !== startnode) { + runtime.log("EVIL"); + } + } + + function setupEmptyRootNode() { + var selection = runtime.getWindow().getSelection(), + root = maindoc.createElementNS("", "p"), + cursor = new core.Cursor(selection, maindoc); + testarea.appendChild(root); + t = { selection: selection, root: root, cursor: cursor }; + runner.shouldBeNonNull(t, "t.selection"); + } + + function setupSimpleTextDoc() { + setupEmptyRootNode(); + t.textnode = maindoc.createTextNode("abc"); + t.root.appendChild(t.textnode); + } + + tests = [ + // create a document, add a cursor and check that the cursor is present + function testOnEmptyNode1() { + // if the document is the container of the selection, the cursor + // can not be in the DOM + setupEmptyRootNode(); + setSelection(t.selection, t.root, 0); + t.cursor.updateToSelection(); + //r.shouldBeNull(t, "t.cursor.getNode().parentNode"); + }, + function testOnEmptyNode2() { + setupEmptyRootNode(); + setSelection(t.selection, t.root, 0); + // t.selection.focusNode = r.root; + var range = t.selection.getRangeAt(0); + t.cursor.updateToSelection(); + r.shouldBeNonNull(t, "t.cursor.getNode().parentNode"); + r.shouldBeNull(t, "t.cursor.getNode().previousSibling"); + r.shouldBeNull(t, "t.cursor.getNode().nextSibling"); + }, + function testOnSimpleText() { + setupSimpleTextDoc(); + // put the cursor at the start of the text node + setSelection(t.selection, t.textnode, 0); + t.cursor.updateToSelection(); + r.shouldBeNonNull(t, "t.cursor.getNode().parentNode"); + r.shouldBeNull(t, "t.cursor.getNode().previousSibling"); + r.shouldBe(t, "t.cursor.getNode().nextSibling.nodeValue", "'abc'"); + }, + function testOnSimpleText2() { + setupSimpleTextDoc(); + // put the cursor in the middle of the text node + setSelection(t.selection, t.textnode, 1); + t.cursor.updateToSelection(); + r.shouldBeNonNull(t, "t.cursor.getNode().parentNode"); + r.shouldBe(t, "t.cursor.getNode().previousSibling.nodeValue", "'a'"); + r.shouldBe(t, "t.cursor.getNode().nextSibling.nodeValue", "'bc'"); + }, + function testOnSimpleText3() { + setupSimpleTextDoc(); + // put the cursor at the end of the text node + setSelection(t.selection, t.textnode, 3); + t.cursor.updateToSelection(); + r.shouldBeNonNull("t.cursor.getNode().parentNode"); + r.shouldBe(t, "t.cursor.getNode().previousSibling.nodeValue", "'abc'"); + r.shouldBeNull(t, "t.cursor.getNode().nextSibling"); + }, + function testOnSimpleText4() { + var textnode2; + setupSimpleTextDoc(); + // put the cursor between 'a' and 'b', then change the selection to + // be between 'b' and 'c' and update the cursor + setSelection(t.selection, t.textnode, 1); + t.cursor.updateToSelection(); + textnode2 = t.cursor.getNode().nextSibling; + setSelection(t.selection, textnode2, 1); + t.cursor.updateToSelection(); + r.shouldBeNonNull(t, "t.cursor.getNode().parentNode"); + r.shouldBe(t, "t.cursor.getNode().previousSibling.nodeValue", "'ab'"); + r.shouldBe(t, "t.cursor.getNode().nextSibling.nodeValue", "'c'"); + }, + function testOnSimpleText5() { + var textnode2; + setupSimpleTextDoc(); + // put the cursor between 'a' and 'b', then change the selection to + // span the entire text and update the cursor + setSelection(t.selection, t.textnode, 1); + t.cursor.updateToSelection(); + textnode2 = t.cursor.getNode().nextSibling; + setSelection(t.selection, t.textnode, 0, textnode2, 2); + t.cursor.updateToSelection(); + r.shouldBe(t, "t.selection.rangeCount", "1"); +// only null if working on a separate document +// r.shouldBeNull(t, "t.cursor.getNode().parentNode"); + t.range = t.selection.getRangeAt(0); + r.shouldBe(t, "t.range.startContainer", "t.textnode"); + r.shouldBe(t, "t.range.startOffset", "0"); + r.shouldBe(t, "t.range.endContainer", "t.textnode"); + r.shouldBe(t, "t.range.endOffset", "3"); + }, + function testOnSimpleText5b() { + var textnode2; + setupSimpleTextDoc(); + setSelection(t.selection, t.textnode, 1); + t.cursor.updateToSelection(); + textnode2 = t.cursor.getNode().nextSibling; + setSelection(t.selection, t.textnode.parentNode, 1, textnode2, 2); + t.cursor.updateToSelection(); + r.shouldBe(t, "t.selection.rangeCount", "1"); +// only null if working on a separate document +// r.shouldBeNull(t, "t.cursor.getNode().parentNode"); + t.range = t.selection.getRangeAt(0); + r.shouldBe(t, "t.range.startContainer", "t.textnode"); + r.shouldBe(t, "t.range.startOffset", "1"); + r.shouldBe(t, "t.range.endContainer", "t.textnode"); + r.shouldBe(t, "t.range.endOffset", "3"); + }, + function testOnSimpleText6() { + var somenode, textnode2; + setupSimpleTextDoc(); + // add a child node to the cursor + somenode = maindoc.createElement("p"); + t.cursor.getNode().appendChild(somenode); + // select a single position so the cursor is put in the document + setSelection(t.selection, t.textnode, 1); + t.cursor.updateToSelection(); + r.shouldBeNonNull(t, "t.cursor.getNode().parentNode"); + textnode2 = t.cursor.getNode().nextSibling; + // select a range starting at the node in the cursor, but extends + // out of the the cursor + // this should have the result that the cursor is removed from the + // document and that the text nodes around the cursor are + // merged + setSelection(t.selection, somenode, 0, textnode2, 2); + t.cursor.updateToSelection(); +// only null if working on a separate document +// r.shouldBeNull(t, "t.cursor.getNode().parentNode"); + t.range = t.selection.getRangeAt(0); + r.shouldBe(t, "t.range.startContainer", "t.textnode"); + r.shouldBe(t, "t.range.startOffset", "1"); + r.shouldBe(t, "t.range.endContainer", "t.textnode"); + r.shouldBe(t, "t.range.endOffset", "3"); + r.shouldBe(t, "t.range.collapsed", "false"); + } + ]; + this.setUp = function () { + t = {}; + while (testarea.firstChild) { + testarea.removeChild(testarea.firstChild); + } + }; + this.tearDown = function () { + t = {}; + while (testarea.firstChild) { + testarea.removeChild(testarea.firstChild); + } + }; + this.tests = function () { + return tests; + }; + this.asyncTests = function () { + return []; + }; +}; +core.CursorTests.name = "CursorTests"; +core.CursorTests.prototype.description = function () { + "use strict"; + return "Test the Cursor class."; +}; +(function () { + "use strict"; + return core.CursorTests; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/core/PointWalkerTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/core/PointWalkerTests.js new file mode 100644 index 0000000000..dbb690f77e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/core/PointWalkerTests.js @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, runtime: true*/ +runtime.loadClass("core.PointWalker"); + +/** + * @constructor + * @param runner {UnitTestRunner} + * @implements {core.UnitTest} + */ +core.PointWalkerTests = function PointWalkerTests(runner) { + "use strict"; + var t, r = runner; + + function checkWalker(node, count, endpos) { + t = {}; + t.node = node; + t.walker = new core.PointWalker(node); + t.count = count; + t.countForward = 0; + t.countBackward = 0; + t.endpos = endpos; + t.walker.setPoint(t.node, 0); + while (t.walker.stepForward()) { + t.countForward += 1; + } + r.shouldBe(t, "t.countForward", "t.count"); + r.shouldBe(t, "t.walker.precedingSibling()", "t.node.lastChild"); + r.shouldBe(t, "t.walker.followingSibling()", "null"); + if (endpos !== null) { + r.shouldBe(t, "t.walker.position()", "t.endpos"); + } + t.walker.setPoint(t.node, endpos); + while (t.walker.stepBackward()) { + t.countBackward += 1; + } + r.shouldBe(t, "t.countBackward", "t.count"); + r.shouldBe(t, "t.walker.precedingSibling()", "null"); + r.shouldBe(t, "t.walker.followingSibling()", "t.node.firstChild"); + r.shouldBe(t, "t.walker.position()", "0"); + } + + function testEmptyDocument() { + var doc = runtime.getDOMImplementation().createDocument("", "p", null), + p = doc.firstChild, + textnode1, + textnode2, + textnode3, + em; + + checkWalker(doc, 2, 1); + checkWalker(p, 0, 0); + + t = {}; + t.doc = doc; + t.walker = new core.PointWalker(t.doc); + r.shouldBe(t, "t.walker.position()", "0"); + r.shouldBe(t, "t.walker.stepForward()", "true"); + r.shouldBe(t, "t.walker.position()", "0"); + r.shouldBe(t, "t.walker.stepForward()", "true"); + r.shouldBe(t, "t.walker.position()", "1"); + r.shouldBe(t, "t.walker.stepForward()", "false"); + r.shouldBe(t, "t.walker.position()", "1"); + r.shouldBe(t, "t.walker.stepBackward()", "true"); + r.shouldBe(t, "t.walker.position()", "0"); + r.shouldBe(t, "t.walker.stepBackward()", "true"); + r.shouldBe(t, "t.walker.position()", "0"); + r.shouldBe(t, "t.walker.stepBackward()", "false"); + r.shouldBe(t, "t.walker.position()", "0"); + + textnode1 = doc.createTextNode("hello, "); + textnode2 = doc.createTextNode("big "); + textnode3 = doc.createTextNode("world."); + em = doc.createElement('em'); + p.appendChild(textnode1); + p.appendChild(em); + em.appendChild(textnode2); + p.appendChild(textnode3); + + checkWalker(textnode1, 7, 7); + checkWalker(textnode2, 4, 4); + checkWalker(textnode3, 6, 6); + checkWalker(em, 6, 1); + checkWalker(p, 25, 3); + checkWalker(doc, 27, 1); + } + + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return [ + testEmptyDocument + ]; + }; + this.asyncTests = function () { + return []; + }; + this.description = function () { + return "Test the PointWalker class."; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/core/RuntimeTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/core/RuntimeTests.js new file mode 100644 index 0000000000..d3f7c2dfa2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/core/RuntimeTests.js @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, runtime: true*/ +/*jslint bitwise: true*/ + +/** + * @constructor + * @param runner {UnitTestRunner} + * @implements {core.UnitTest} + */ +core.RuntimeTests = function RuntimeTests(runner) { + "use strict"; + var t, r = runner; + + function testRead(callback) { + runtime.read("tests.js", 2, 6, function (err, data) { + t.err = err; + r.shouldBeNull(t, "t.err"); + t.data = runtime.byteArrayToString(data, "utf8"); + r.shouldBe(t, "t.data", "'global'"); + callback(); + }); + } + + /** + * Test writing a binary file and reading it back. + */ + function testWrite(callback) { + var content = new core.ByteArrayWriter("utf8"), + i, max = 1024, filename, clean; + for (i = 0; i < max; i += 1) { + content.appendArray([i]); + } + content = content.getByteArray(); + filename = "tmp" + Math.random(); + clean = new core.ByteArrayWriter("utf8"); + for (i = 0; i < max; i += 1) { + clean.appendArray([content[i] & 0xff]); + } + clean = clean.getByteArray(); + // now content has content different from what is on the server + runtime.writeFile(filename, content, function (err) { + t.err = err; + r.shouldBeNull(t, "t.err"); + runtime.readFile(filename, "binary", function (err, data) { + t.err = err; + r.shouldBeNull(t, "t.err"); + t.data = data; + t.clean = clean; + r.shouldBe(t, "t.data.length", "t.clean.length"); + i = 0; + while (i < max && data[i] === clean[i]) { + i += 1; + } + if (i !== max) { + runtime.log("at " + String(i) + " " + data[i] + " vs " + + clean[i]); + } + t.i = i; + t.max = max; + r.shouldBe(t, "t.i", "t.max"); + // cleanup + runtime.deleteFile(filename, function (err) { + callback(); + }); + }); + }); + } + + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return [ + ]; + }; + this.asyncTests = function () { + return [ + testRead, + testWrite + ]; + }; + this.description = function () { + return "Test the runtime."; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/core/ZipTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/core/ZipTests.js new file mode 100644 index 0000000000..ad2ece55ad --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/core/ZipTests.js @@ -0,0 +1,141 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global core: true, runtime: true*/ +runtime.loadClass("core.Zip"); + +/** + * @constructor + * @param {core.UnitTestRunner} runner + * @implements {core.UnitTest} + */ +core.ZipTests = function ZipTests(runner) { + "use strict"; + var r = runner, + t; + + function testNonExistingFile(callback) { + var zip = new core.Zip("whatever", function (err) { + t.err = err; + r.shouldBeNonNull(t, "t.err"); + callback(); + }); + } + + function testNonZipFile(callback) { + var path = "core/ZipTests.js"; + // check that file exists + runtime.isFile(path, function (exists) { + t.exists = exists; + r.shouldBe(t, "t.exists", "true"); + // check that zip file opening returns an error + var zip = new core.Zip("core/ZipTests.js", function (err) { + t.err = err; + r.shouldBeNonNull(t, "t.err"); + callback(); + }); + }); + } + + function testHi(path, callback) { + var zip = new core.Zip(path, function (err, zip) { + t.err = err; + t.zip = zip; + r.shouldBeNull(t, "t.err"); + zip.load("hello", function (err, data) { + t.err = err; + r.shouldBeNull(t, "t.err"); + t.data = runtime.byteArrayToString(data, "utf8"); + r.shouldBe(t, "t.data.length", "16"); + r.shouldBe(t, "t.data", "'bonjour\\nbonjour\\n'"); + callback(); + }); + }); + } + + function testHiUncompressed(callback) { + testHi("core/hi-uncompressed.zip", callback); + } + + function testHiCompressed(callback) { + testHi("core/hi-compressed.zip", callback); + } + + function testCreateZip(callback) { + var filename = "writetest.zip", + zip = new core.Zip(filename, null), + data = runtime.byteArrayFromString( + "application/vnd.oasis.opendocument.text", "utf8"); + zip.save("mimetype", data, false, new Date()); + zip.load("mimetype", function (err, newdata) { + t.err = err; + r.shouldBeNull(t, "t.err"); + t.data = data; + t.newdata = newdata; + r.shouldBe(t, "t.data", "t.newdata"); + zip.write(function (err) { + t.err = err; + r.shouldBeNull(t, "t.err"); + runtime.deleteFile(filename, function (err) { + callback(); + }); + }); + }); + } + + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return []; + }; + this.asyncTests = function () { + return [ + testNonExistingFile, + testNonZipFile, + testHiUncompressed, + testHiCompressed, + testCreateZip + ]; + }; +}; +core.ZipTests.prototype.description = function () { + "use strict"; + return "Test the Zip class."; +}; +(function () { + "use strict"; + return core.ZipTests; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/core/hi-compressed.zip b/apps/files_odfviewer/src/webodf/webodf/tests/core/hi-compressed.zip new file mode 100644 index 0000000000000000000000000000000000000000..ff6d86c158abed89f3865d3855e412ce6c08cd98 GIT binary patch literal 172 zcmWIWW@Zs#U}E54a170~P5pAhori&eK>&zZ8DtnTQgd?hLqj+jn6t!h`hak01vdjD z%NIrl1~B1$>ip?b`nr$2nl3Q}cr!A|G2=2!0%#-y15h8smPQZ@YBVdvXf$I3yjj^m OiWq^=8%TpN0|Nm1VqY!GH;kYUJ3&B@6R4dG;9&Jw@r1Hz>h+zgB?Ul + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, gui: true*/ +runtime.loadClass("gui.Caret"); + +/** + * @constructor + * @param {core.UnitTestRunner} runner + * @implements {core.UnitTest} + */ +gui.CaretTests = function CaretTests(runner) { + "use strict"; + var r = runner, + t; + + function setupEmptyDoc() { + var selection = runtime.getWindow().getSelection(), + doc = runtime.getDOMImplementation().createDocument("", "p", null), + caret = new gui.Caret(selection, doc); + t = { selection: selection, doc: doc }; //, cursor: cursor }; + runner.shouldBeNonNull(t, "t.selection"); + } + function setupSimpleTextDoc() { + setupEmptyDoc(); + t.textnode = t.doc.createTextNode("abc"); + t.doc.documentElement.appendChild(t.textnode); + } + function testOnUpDownTraversal() { + } + + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return []; + }; + this.asyncTests = function () { + return [ + ]; + }; +}; +gui.CaretTests.prototype.description = function () { + "use strict"; + return "Test the Caret class."; +}; +(function () { + "use strict"; + return gui.CaretTests; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/gui/SelectionMoverTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/gui/SelectionMoverTests.js new file mode 100644 index 0000000000..8b8275bcb8 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/gui/SelectionMoverTests.js @@ -0,0 +1,109 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, gui: true*/ +runtime.loadClass("gui.SelectionMover"); + +/** + * @constructor + * @param {core.UnitTestRunner} runner + * @implements {core.UnitTest} + */ +gui.SelectionMoverTests = function SelectionMoverTests(runner) { + "use strict"; + var r = runner, + t, testarea = runtime.getWindow().document.getElementById("testarea"); + + function setupDoc() { + var doc = testarea.ownerDocument, + selection = runtime.getWindow().getSelection(), + p = doc.createElement("p"), + walker = new core.PointWalker(p), + mover = new gui.SelectionMover(selection, walker); + testarea.appendChild(p); + p.appendChild(doc.createTextNode("MMMMM MMMMM MMMMM MMMMM MMMMM")); + p.style.width = "5em";// break line after each 'MMMMM' + selection.removeAllRanges(); + selection.addRange(doc.createRange()); + t = { doc: doc, p: p, selection: selection, mover: mover }; + } + function testUpDownTraversal() { + setupDoc(); + r.shouldBe(t, "t.selection.rangeCount", "1"); + t.r = t.selection.getRangeAt(0); + r.shouldBeNonNull(t, "t.r"); + t.r.setStart(t.p.firstChild, 0); + r.shouldBe(t, "t.r.startContainer", "t.p.firstChild"); + r.shouldBe(t, "t.r.startOffset", "0"); + t.mover.movePointForward(); + t.r = t.selection.getRangeAt(0); + r.shouldBe(t, "t.r.startContainer", "t.p.firstChild"); + r.shouldBe(t, "t.r.startOffset", "1"); + t.mover.movePointBackward(); + t.r = t.selection.getRangeAt(0); + r.shouldBe(t, "t.r.startContainer", "t.p.firstChild"); + r.shouldBe(t, "t.r.startOffset", "0"); + t.mover.moveLineForward(); +// t.selection.modify("move", "forward", "line"); + t.r = t.selection.getRangeAt(0); + r.shouldBe(t, "t.r.startContainer", "t.p.firstChild"); + r.shouldBe(t, "t.r.startOffset", "6"); + } + + this.setUp = function () { + t = {}; + while (testarea.firstChild) { + testarea.removeChild(testarea.firstChild); + } + }; + this.tearDown = function () { + t = {}; + while (testarea.firstChild) { + testarea.removeChild(testarea.firstChild); + } + }; + this.tests = function () { + return [ testUpDownTraversal ]; + }; + this.asyncTests = function () { + return [ + ]; + }; +}; +gui.SelectionMoverTests.prototype.description = function () { + "use strict"; + return "Test the SelectionMover class."; +}; +(function () { + "use strict"; + return gui.SelectionMoverTests; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/gui/XMLEditTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/gui/XMLEditTests.js new file mode 100644 index 0000000000..e253a72fea --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/gui/XMLEditTests.js @@ -0,0 +1,156 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global document: true, core: true, gui: true, runtime: true*/ +runtime.loadClass("core.PointWalker"); +runtime.loadClass("gui.XMLEdit"); + +/** + * @constructor + * @param runner {core.UnitTestRunner} + * @implements {core.UnitTest} + */ +gui.XMLEditTests = function XMLEditTests(runner) { + "use strict"; + var t, r = runner, tests; + + function checkWalker(node, count, endpos) { + t = {}; + t.node = node; + t.walker = new core.PointWalker(node); + t.count = count; + t.countForward = 0; + t.countBackward = 0; + t.endpos = endpos; + t.walker.setPoint(t.node, 0); + while (t.walker.stepForward()) { + t.countForward += 1; + } + r.shouldBe("t.countForward", "t.count"); + r.shouldBe("t.walker.precedingSibling()", "t.node.lastChild"); + r.shouldBe("t.walker.followingSibling()", "null"); + if (endpos !== null) { + r.shouldBe("t.walker.position()", "t.endpos"); + } + t.walker.setPoint(t.node, endpos); + while (t.walker.stepBackward()) { + t.countBackward += 1; + } + r.shouldBe("t.countBackward", "t.count"); + r.shouldBe("t.walker.precedingSibling()", "null"); + r.shouldBe("t.walker.followingSibling()", "t.node.firstChild"); + r.shouldBe("t.walker.position()", "0"); + } + + function testSimpleDocument(xmledit) { + var maindoc = xmledit.ownerDocument, + doc = maindoc.implementation.createDocument(null, "p", null), + p = doc.firstChild, + textnode1, + textnode2, + textnode3, + em; + + xmledit.setXML(doc); + + checkWalker(doc, 2, 1); + checkWalker(p, 0, 0); + + t = {}; + t.doc = doc; + t.walker = new core.PointWalker(t.doc); + r.shouldBe("t.walker.position()", "0"); + r.shouldBe("t.walker.stepForward()", "true"); + r.shouldBe("t.walker.position()", "0"); + r.shouldBe("t.walker.stepForward()", "true"); + r.shouldBe("t.walker.position()", "1"); + r.shouldBe("t.walker.stepForward()", "false"); + r.shouldBe("t.walker.position()", "1"); + r.shouldBe("t.walker.stepBackward()", "true"); + r.shouldBe("t.walker.position()", "0"); + r.shouldBe("t.walker.stepBackward()", "true"); + r.shouldBe("t.walker.position()", "0"); + r.shouldBe("t.walker.stepBackward()", "false"); + r.shouldBe("t.walker.position()", "0"); + + textnode1 = doc.createTextNode("hello, "); + textnode2 = doc.createTextNode("big "); + textnode3 = doc.createTextNode("world."); + em = doc.createElement('em'); + p.appendChild(textnode1); + p.appendChild(em); + em.appendChild(textnode2); + p.appendChild(textnode3); + + checkWalker(textnode1, 7, 7); + checkWalker(textnode2, 4, 4); + checkWalker(textnode3, 6, 6); + checkWalker(em, 6, 1); + checkWalker(p, 25, 3); + checkWalker(doc, 27, 1); + } + + function testXmlEdit(document) { + var head = document.getElementsByTagName("head")[0], + css = document.createElement("style"), + testarea = document.createElement("div"), + xmledit; + + // the xml edit requires an element to put the content and a sheet to put + // the style + css.type = "text/css"; + head.appendChild(css); + document.body.appendChild(testarea); + xmledit = new gui.XMLEdit(testarea, css); + + testSimpleDocument(xmledit); + + css.parentNode.removeChild(css); + testarea.parentNode.removeChild(testarea); + } + + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return [ testSimpleDocument ]; + }; + this.asyncTests = function () { + return []; + }; + this.description = function () { + return "Test the XML editor class."; + }; +}; diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/manifest.js b/apps/files_odfviewer/src/webodf/webodf/tests/manifest.js new file mode 100644 index 0000000000..6d4f151bc0 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/manifest.js @@ -0,0 +1,16 @@ +(function () { + "use strict"; +return [ + "core/Base64Tests.js", + "core/CursorTests.js", + "core/PointWalkerTests.js", + "core/RuntimeTests.js", + "core/ZipTests.js", + "gui/CaretTests.js", + "gui/SelectionMoverTests.js", + "gui/XMLEditTests.js", + "tests.js", + "xmldom/OperationalTransformDOMTests.js", + "xmldom/XPathTests.js" + ]; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/resources/js-test-style.css b/apps/files_odfviewer/src/webodf/webodf/tests/resources/js-test-style.css new file mode 100644 index 0000000000..f12147ca43 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/resources/js-test-style.css @@ -0,0 +1,12 @@ +.pass { + font-weight: bold; + color: green; +} +.fail { + font-weight: bold; + color: red; +} +#console { + white-space: pre-wrap; + font-family: monospace; +} diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/tests.html b/apps/files_odfviewer/src/webodf/webodf/tests/tests.html new file mode 100644 index 0000000000..572db60554 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/tests.html @@ -0,0 +1,22 @@ + + + WebODF unit tests + + + +

+
+
+
+ + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/tests.js b/apps/files_odfviewer/src/webodf/webodf/tests/tests.js new file mode 100644 index 0000000000..5570733de5 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/tests.js @@ -0,0 +1,94 @@ +/*global window: true, runtime: true, Runtime: true, core: true, gui: true, + xmldom: true, RuntimeTests: true*/ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +runtime.loadClass("core.RuntimeTests"); +runtime.loadClass("core.UnitTester"); +runtime.loadClass("core.PointWalkerTests"); +runtime.loadClass("core.CursorTests"); +runtime.loadClass("core.ZipTests"); +runtime.loadClass("core.Base64Tests"); +runtime.loadClass("xmldom.OperationalTransformDOMTests"); +runtime.loadClass("xmldom.XPathTests"); +runtime.loadClass("gui.CaretTests"); +runtime.loadClass("gui.XMLEditTests"); + +var tests = [ + core.RuntimeTests, // temporarily disabled, enable at next commit! + core.ZipTests, + core.Base64Tests +]; +if (runtime.type() !== "NodeJSRuntime") { + tests.push(core.PointWalkerTests); +} +if (runtime.type() === "BrowserRuntime") { + tests.push(core.PointWalkerTests); +// tests.push(core.CursorTests); + tests.push(xmldom.OperationalTransformDOMTests); + tests.push(gui.CaretTests); + tests.push(xmldom.XPathTests); +// tests.push(gui.XMLEditTests); +} +var tester = new core.UnitTester(); +/** + * @param {!Array.} tests + * @return {undefined} + */ +function runNextTest(tests) { + "use strict"; + if (tests.length === 0) { + //runtime.log(JSON.stringify(tester.results())); + runtime.log("Number of failed tests: " + + String(tester.countFailedTests())); + runtime.exit(tester.countFailedTests()); + return; + } + var test = tests[0]; + if (typeof test !== "function") { + runtime.log("Tests contain a non-function object of type " + + typeof(test) + "."); + runtime.exit(1); + return; + } + runtime.log("Running test '" + Runtime.getFunctionName(test) + "'."); + try { + tester.runTests(test, function () { + runNextTest(tests.slice(1)); + }); + } catch (e) { + runtime.log(e); + runtime.exit(1); + throw e; + } +} +runNextTest(tests); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/xmldom/OperationalTransformDOMTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/xmldom/OperationalTransformDOMTests.js new file mode 100644 index 0000000000..3866a53708 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/xmldom/OperationalTransformDOMTests.js @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, xmldom: true*/ +runtime.loadClass("xmldom.OperationalTransformDOM"); + +/** + * @constructor + * @param {core.UnitTestRunner} runner + * @implements {core.UnitTest} + */ +xmldom.OperationalTransformDOMTests = function OperationalTransformDOMTests(runner) { + "use strict"; + var r = runner, + t; + + function setupEmptyDoc() { + var doc = runtime.getDOMImplementation().createDocument("", "p", null); + t = { doc: doc }; + } + function setupSimpleTextDoc() { + setupEmptyDoc(); + t.textnode = t.doc.createTextNode("abc"); + t.doc.documentElement.appendChild(t.textnode); + } + function testSkip() { + setupEmptyDoc(); + } + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return [ testSkip ]; + }; + this.asyncTests = function () { + return [ + ]; + }; +}; +xmldom.OperationalTransformDOMTests.prototype.description = function () { + "use strict"; + return "Test the OperationalTransformDOM class."; +}; +(function () { + "use strict"; + return xmldom.OperationalTransformDOMTests; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tests/xmldom/XPathTests.js b/apps/files_odfviewer/src/webodf/webodf/tests/xmldom/XPathTests.js new file mode 100644 index 0000000000..91ebba99c6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tests/xmldom/XPathTests.js @@ -0,0 +1,112 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true, xmldom: true, odf: true, XMLSerializer*/ +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.Style2CSS"); + +/** + * @constructor + * @param {core.UnitTestRunner} runner + * @implements {core.UnitTest} + */ +xmldom.XPathTests = function XPathTests(runner) { + "use strict"; + var r = runner, + style2CSS = new odf.Style2CSS(), + t; + + function setupDoc() { + var stylens = style2CSS.namespaceResolver("style"), + svgns = style2CSS.namespaceResolver("svg"), + drawns = style2CSS.namespaceResolver("draw"), + presentationns = style2CSS.namespaceResolver("presentation"), + textns = style2CSS.namespaceResolver("text"), + doc = runtime.getDOMImplementation().createDocument("", "a", null), + r = doc.documentElement, + fontFace = doc.createElementNS(stylens, "font-face"), + fontFaceSrc = doc.createElementNS(svgns, "font-face-src"), + drawFrame = doc.createElementNS(drawns, "frame"), + p = doc.createElementNS(textns, "p"); + r.appendChild(p); + r.appendChild(fontFace); + fontFace = doc.createElementNS(stylens, "font-face"); + fontFace.appendChild(fontFaceSrc); + fontFaceSrc.setAttributeNS(textns, "anchor-type", "paragraph"); + r.appendChild(fontFace); + r.appendChild(drawFrame); + drawFrame = doc.createElementNS(drawns, "frame"); + drawFrame.setAttributeNS(presentationns, "class", "title"); + r.appendChild(drawFrame); + + t = { doc: doc, fontFace: fontFace, drawFrame: drawFrame }; + } + function test1() { + setupDoc(); + var xpath = new xmldom.XPath(), + xpaths = { + "style:font-face[svg:font-face-src]": "t.fontFace", + ".//*[*[@text:anchor-type='paragraph']]": "t.fontFace", + "./draw:frame[@presentation:class='title']": "t.drawFrame" + }, + x; + for (x in xpaths) { + if (xpaths.hasOwnProperty(x)) { + t.result = xpath.getODFElementsWithXPath(t.doc.documentElement, + x, style2CSS.namespaceResolver); + r.shouldBe(t, "t.result.length", "1"); + r.shouldBe(t, "t.result[0]", xpaths[x]); + } + } + } + this.setUp = function () { + t = {}; + }; + this.tearDown = function () { + t = {}; + }; + this.tests = function () { + return [ test1 ]; + }; + this.asyncTests = function () { + return [ + ]; + }; +}; +xmldom.XPathTests.prototype.description = function () { + "use strict"; + return "Test the XPath class."; +}; +(function () { + "use strict"; + return xmldom.XPathTests; +}()); diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/clippingTestImage.html b/apps/files_odfviewer/src/webodf/webodf/tools/clippingTestImage.html new file mode 100644 index 0000000000..67cc747737 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/clippingTestImage.html @@ -0,0 +1,39 @@ + + + + + +

This image can be used to find clipping problems. If the sides of the image are clipped asymetrically, it will obvious visually.

+ +pregenerated + + diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/externs.js b/apps/files_odfviewer/src/webodf/webodf/tools/externs.js new file mode 100644 index 0000000000..9862befe48 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/externs.js @@ -0,0 +1,348 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global Packages HTMLStyleElement window XMLHttpRequest HTMLStyleElement Document*/ +/*jslint nomen: false */ +/** + * @constructor + */ +function NodeJSObject() {} +/** + * @param {!string} path + * @param {function(...)} callback + * @return {undefined} + */ +NodeJSObject.prototype.stat = function (path, callback) {}; +/** + * @param {!string} path + * @param {?string} encoding + * @param {function(...)} callback + * @return {?string} + */ +NodeJSObject.prototype.readFile = function (path, encoding, callback) {}; +/** + * @param {!string} path + * @param {?string} encoding + * @return {?string} + */ +NodeJSObject.prototype.readFileSync = function (path, encoding) {}; +/** + * @param {!string} path + * @param {!string} flags + * @param {!number} mode + * @param {!function(string, !number):undefined} callback + * @return {undefined} + */ +NodeJSObject.prototype.open = function (path, flags, mode, callback) {}; +/** + * @param {!number} fd + * @param {!Buffer} buffer + * @param {!number} offset + * @param {!number} length + * @param {!number} position + * @param {function(string, !number)} callback + * @return {undefined} + */ +NodeJSObject.prototype.read = function (fd, buffer, offset, length, position, + callback) {}; +/** + * @param {!string} path + * @param {!string} data + * @param {!string} encoding + * @param {!function(?string):undefined} callback + * @return {undefined} + */ +NodeJSObject.prototype.writeFile = function (path, data, encoding, callback) {}; +/** + * @param {!string} path + * @param {!function(?string):undefined} callback + * @return {undefined} + */ +NodeJSObject.prototype.unlink = function (path, callback) {}; +/** + * @param {!number} fd + * @param {function(!string)} callback + * @return {undefined} + */ +NodeJSObject.prototype.close = function (fd, callback) {}; +/** + * @param {!string} className + * @return {!NodeJSObject} + */ +function require(className) {} +/** + * @constructor + */ +function NodeJSConsole() {} +/** + * @param {!string} msg + * @return {undefined} + */ +NodeJSConsole.prototype.log = function (msg) {}; +/** + * @type {!NodeJSConsole} + */ +var console; +/** + * @constructor + */ +function NodeJSProcess() {} +/** + * @param {!number} exitCode + * @return {undefined} + */ +NodeJSProcess.prototype.exit = function (exitCode) {}; +/** + * @type {!Array} + */ +NodeJSProcess.prototype.argv = []; +/** + * @type {!Object} + */ +NodeJSProcess.prototype.stderr = {}; +/** + * @type {!NodeJSProcess} + */ +var process; +/** + * @type {!string} + */ +var __dirname; +/** + * @constructor + * @param {!number|!Array.|!string} arg1 + * @param {!string=} encoding + */ +function Buffer(arg1, encoding) {} +/** + * @param {!string} msg + * @return {undefined} + */ +function print(msg) {} +/** + * @param {!string} path + * @param {!string=} encoding + * @return {?string} + */ +function readFile(path, encoding) {} +/** + * @param {!number} exitCode + * @return {undefined} + */ +function quit(exitCode) {} +/** + * @namespace + */ +Packages.javax = {}; +/** + * @namespace + */ +Packages.javax.xml = {}; +/** + * @namespace + */ +Packages.javax.xml.validation = {}; +/** + * @constructor + */ +Packages.javax.xml.validation.Schema = function () {}; +/** + * @namespace + */ +Packages.javax.xml.parsers = {}; +/** + * @constructor + */ +Packages.javax.xml.parsers.DocumentBuilder = function () {}; +/** + * @param {!Object} entityresolver + * @return {undefined} + */ +Packages.javax.xml.parsers.DocumentBuilder.prototype.setEntityResolver = + function (entityresolver) {}; +/** + * @param {!Packages.org.xml.sax.InputSource} source + * @return {Document} + */ +Packages.javax.xml.parsers.DocumentBuilder.prototype.parse = + function (source) {}; +/** + * @return {DOMImplementation} + */ +Packages.javax.xml.parsers.DocumentBuilder.prototype.getDOMImplementation = + function () {}; +/** + * @constructor + */ +Packages.javax.xml.parsers.DocumentBuilderFactory = function () {}; +/** + * @return {!Packages.javax.xml.parsers.DocumentBuilderFactory} + */ +Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance = function () {}; +/** + * @param {!boolean} value + */ +Packages.javax.xml.parsers.DocumentBuilderFactory.prototype.setValidating = + function (value) {}; +/** + * @param {!boolean} value + */ +Packages.javax.xml.parsers.DocumentBuilderFactory.prototype.setNamespaceAware = + function (value) {}; +/** + * @param {!boolean} value + */ +Packages.javax.xml.parsers.DocumentBuilderFactory.prototype + .setExpandEntityReferences = function (value) {}; +/** + * @param {?Packages.javax.xml.validation.Schema} schema + */ +Packages.javax.xml.parsers.DocumentBuilderFactory.prototype.setSchema = + function (schema) {}; +/** + * @return {!Packages.javax.xml.parsers.DocumentBuilder} + */ +Packages.javax.xml.parsers.DocumentBuilderFactory.prototype.newDocumentBuilder = + function () {}; +/** + * @namespace + */ +Packages.org = {}; +/** + * @namespace + */ +Packages.org.xml.sax = {}; +/** + * @param {!Object} definition + * @return {!Object} + */ +Packages.org.xml.sax.EntityResolver = function (definition) {}; +/** + * @namespace + */ +Packages.java.io = {}; +/** + * @constructor + * @param {!string} path + */ +Packages.java.io.FileReader = function (path) {}; +/** + * @constructor + * @param {!string} path + */ +Packages.java.io.FileOutputStream = function (path) {}; +/** + * @param {!number} b + * @return {undefined} + */ +Packages.java.io.FileOutputStream.prototype.write = function (b) {}; +/** + * @return {undefined} + */ +Packages.java.io.FileOutputStream.prototype.close = function () {}; +/** + * @constructor + * @param {!Packages.java.io.FileReader} reader + */ +Packages.org.xml.sax.InputSource = function (reader) {}; +/** + * @type {!StyleSheet} + */ +HTMLStyleElement.prototype.sheet; +XMLHttpRequest.prototype.sendAsBinary = function (data) {}; +/** + * @const@type{!string} + */ +XMLHttpRequest.prototype.responseBody; +window.nativeio = {}; +var VBArray = {}; +VBArray.prototype.toArray = function () {}; +/** + * @interface + */ +function TreeWalker() {} +/** + * @const@type{!Node} + */ +TreeWalker.prototype.root; +/** + * @const@type{number} + */ +TreeWalker.prototype.whatToShow; +/** + * @const@type{NodeFilter} + */ +TreeWalker.prototype.filter; +/** + * @const@type{boolean} + */ +TreeWalker.prototype.expandEntityReferences; +/** + * @type{Node} + */ +TreeWalker.prototype.currentNode; +/** + * @return {Node} + */ +TreeWalker.prototype.parentNode = function () {}; +/** + * @return {Node} + */ +TreeWalker.prototype.firstChild = function () {}; +/** + * @return {Node} + */ +TreeWalker.prototype.lastChild = function () {}; +/** + * @return {Node} + */ +TreeWalker.prototype.previousSibling = function () {}; +/** + * @return {Node} + */ +TreeWalker.prototype.nextSibling = function () {}; +/** + * @return {Node} + */ +TreeWalker.prototype.previousNode = function () {}; +/** + * @return {Node} + */ +TreeWalker.prototype.nextNode = function () {}; +/** + * @param {!Node} root + * @param {!number} whatToShow + * @param {NodeFilter=} filter + * @param {boolean=} entityReferenceExpansion + * @return {!TreeWalker} + */ +Document.prototype.createTreeWalker = function (root, whatToShow, filter, entityReferenceExpansion) {}; diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/extjsexterns.js b/apps/files_odfviewer/src/webodf/webodf/tools/extjsexterns.js new file mode 100644 index 0000000000..f65d0c5cdb --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/extjsexterns.js @@ -0,0 +1,171 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global Packages HTMLStyleElement window XMLHttpRequest HTMLStyleElement Document*/ +/*jslint nomen: false */ +var Ext = {}; +Ext.data = {}; +/** + * @constructor + */ +Ext.data.Model = function (settings) {}; +/** + * @param {!string} fieldName + * @return {!string} + */ +Ext.data.Model.prototype.get = function (fieldName) {}; +/** + * @return {!boolean} + */ +Ext.data.Model.isExpanded = function () {}; +/** + * @constructor + */ +Ext.data.NodeInterface = function () {}; +/** + * @param {!string} attribute + * @param {*} value + * @param {boolean=} deep + * @return {Ext.data.NodeInterface} + */ +Ext.data.NodeInterface.prototype.findChild = function (attribute, value, deep) {}; +/** + * @param {!Ext.data.NodeInterface|!Object} node + * @return {!Ext.data.NodeInterface} + */ +Ext.data.NodeInterface.prototype.appendChild = function (node) {}; +/** + * @param {!string} id + * @return {Ext.Component} + */ +Ext.getCmp = function (id) {}; +Ext.tree = {}; +/** + * @constructor + */ +Ext.tree.Panel = function (settings) {}; +/** + * @return {!Ext.data.NodeInterface} + */ +Ext.tree.Panel.prototype.getRootNode = function () {}; +Ext.component = {}; +/** + * @constructor + * @extends {Ext.Component} + */ +Ext.component.Component = function (settings) {}; +/** + * @return {!Ext.Element} + */ +Ext.component.Component.prototype.getEl = function () {}; +/** + * @constructor + */ +Ext.Button = function (settings) {}; +/** + * @constructor + */ +Ext.Component = function (settings) {}; +/** + * @type {Object} + */ +Ext.Component.prototype.superclass = {}; +/** + * @type {!Ext.Element} + */ +Ext.Component.prototype.el; +/** + * @constructor + */ +Ext.Element = function (settings) {}; +/** + * @constructor + */ +Ext.Panel = function (settings) {}; +/** + * @type {!Element} + */ +Ext.Element.prototype.dom; +Ext.QuickTips = {}; +/** + * @return {undefined} + */ +Ext.QuickTips.init = function () {}; +/** + * @constructor + */ +Ext.Slider = function (settings) {}; +Ext.util = {}; +/** + * @constructor + */ +Ext.util.MixedCollection = function () {}; +/** + * @param {!Function} f + */ +Ext.util.MixedCollection.prototype.findBy = function (f) {}; +Ext.tab = {}; +/** + * @constructor + */ +Ext.tab.Panel = function (settings) {}; +/** + * @param {!Object} component + * @return {undefined} + */ +Ext.tab.Panel.prototype.add = function (component) {}; +/** + * @return {!Ext.Component} + */ +Ext.tab.Panel.prototype.getActiveTab = function () {}; +/** + * @param {!Ext.Component} tab + * @return {undefined} + */ +Ext.tab.Panel.prototype.setActiveTab = function (tab) {}; +/** + * @type {!Ext.util.MixedCollection} + */ +Ext.tab.Panel.prototype.items; +/** + * @constructor + */ +Ext.Toolbar = function (settings) {}; +/** + * @constructor + */ +Ext.Toolbar.TextItem = function (text) {}; +/** + * @constructor + */ +Ext.Viewport = function (settings) {}; +Ext.onReady = function (callback) {}; diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/fixLicenses.py b/apps/files_odfviewer/src/webodf/webodf/tools/fixLicenses.py new file mode 100755 index 0000000000..a81c9b55c6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/fixLicenses.py @@ -0,0 +1,81 @@ +#!/usr/bin/python -Qwarnall +# -*- coding: utf-8 -*- +# +# This script checks if all files have licenses and fixes them if needed. +# The script should be run from the root directory of the webodf project. +import os, os.path + +# read the license text from the source file +# the license starts at the line ' * @licstart' and ends at ' */' +def readLicense(path): + file = open(path, "rU") + licensetext = [] + started = False + for line in file: + if line.rstrip() == ' * @licstart': + started = True + if started: + licensetext.append(line) + if line.rstrip() == ' */': + break + return licensetext + +def writeLicense(file, license, defaultcopyright): + if defaultcopyright: + file.write(defaultcopyright) + file.writelines(license) + +def fixLicense(path, license, defaultcopyright): + # read the file + file = open(path, "rU") + lines = file.readlines() + file.close() + # does the file have any copyright statement already? + hasLicense = False + hasCopyright = False + for line in lines: + if line.rstrip() == ' * @licstart': + hasLicense = True + if line[:17] == ' * Copyright (C) ': + hasCopyright = True + if hasCopyright: + defaultcopyright = None + wroteLicense = False + skip = False + # write the file with the new slice + file = open(path, "w") + for line in lines: + if not wroteLicense: + if not hasLicense: + file.write("/**\n") + writeLicense(file, license, defaultcopyright) + wroteLicense = True + elif line.rstrip() == ' * @licstart': + writeLicense(file, license, defaultcopyright) + wroteLicense = True + skip = True + if skip: + if line.rstrip() == ' */': + skip = False + else: + file.write(line) + file.close() + +# get list of *.js files +jsfiles = [] +for root, directories, files in os.walk("."): + while "extjs" in directories: + directories.remove("extjs") + for f in files: + if f[-3:] == ".js": + jsfiles.append(os.path.abspath(os.path.join(root, f))) + +# remove webodf/lib/packackages.js since it is the source for the licenses +sourcefilepath = os.path.join(os.getcwd(), "webodf/lib/packages.js") +jsfiles.remove(sourcefilepath) + +licensetext = readLicense(sourcefilepath) +defaultcopyright = " * Copyright (C) 2011 KO GmbH \n" + +for f in jsfiles: + fixLicense(f, licensetext, defaultcopyright) diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/refcheck/bootstrap.xsl b/apps/files_odfviewer/src/webodf/webodf/tools/refcheck/bootstrap.xsl new file mode 100644 index 0000000000..747e3e605b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/refcheck/bootstrap.xsl @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/refcheck/odfkeys.xml b/apps/files_odfviewer/src/webodf/webodf/tools/refcheck/odfkeys.xml new file mode 100644 index 0000000000..e2ad06941c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/refcheck/odfkeys.xml @@ -0,0 +1,455 @@ + + +

ODF reference checker

+

ODF documents use string keys and references to link different parts of the document. There are quite a few different groups of keys. The description of how these keys work in the specification is not trivial to implement, because not keys behave differently depending on the context in which they are defined. E.g. a style has a family. If the family is 'text', then only certain attributes on certain elements in certain parts of the ODF document may refer to that style.

+

For a beginning and even intermediate ODF developer or document producer, this is quite complicated. Also, there is not currently an easy way to check if all the references are correct. This document aims to make it easier to figure out what groups of keys exist and from which elements they may be linked.

+

The document consists of one <key> element for each group of keys. Each group has a name and is defined by one or more XPath expressions in <def> elements. Any string that matches the XPath expression in a particular document is part of the set of keys of that group. Each key in a set must be unique.

+

In addition, each <key> has a number of <ref> elements that define the positions in the document where a key may be referenced. Each reference must exist in the set of keys that are found via the <def> elements.

+

The format of this document is designed to be easy to read but also to make it easy to use in a reference checker. This document comes with checked implemented in XSL. The XSL is called bootstrap.xsl and is used in two transformation steps. Here is shown how to run the check with xsltproc:

+
xsltproc bootstrap.xsl odfkeys.xml > checkkeys.xsl
+
xsltproc checkkeys.xsl content.xml
+

The check can be run on content.xml files, on styles.xml files and on flat ODF files.

+

Definitions

+
+
$stylesfontfaces
+
This variable refers to the subset of font face definitions that are available to the style elements. Styles.xml may not refer to font faces defined in content.xml.
+
$fontfaces
+
This variable refers to all font face definitions.
+
$officestyles
+
This variable refers to the element office:styles.
+
$stylesautostyles
+
This variable refers to the element office:automatic-styles in styles.xml.
+
$contentautostyles
+
This variable refers to the element office:automatic-styles in content.xml. When evaluating a styles.xml document, it is an empty set.
+
$masterstyles
+
This variable refers to the office:master-styles element.
+
$body
+
This variable refers to the office:body element. When evaluating a styles.xml document, it is an empty set.
+
+

TODO

+
    +
  • implement <refs/> to check refs of type styleNameRefs
  • +
  • check for unused automatic styles
  • +
  • check that there are no circular dependencies in style inheritance
  • +
+
+ + $officestyles/draw:gradient/@draw:name + $officestyles/svg:linearGradient/@draw:name + $officestyles/svg:radialGradient/@draw:name + $officestyles//@draw:fill-gradient-name + $stylesautostyles//@draw:fill-gradient-name + $contentautostyles//@draw:fill-gradient-name + + + $officestyles/draw:hatch/@draw:name + $officestyles//@draw:fill-hatch-name + $stylesautostyles//@draw:fill-hatch-name + $contentautostyles//@draw:fill-hatch-name + + + $officestyles/draw:fill-image/@draw:name + $officestyles//@draw:fill-image-name + $stylesautostyles//@draw:fill-image-name + $contentautostyles//@draw:fill-image-name + + + $officestyles/draw:marker/@draw:name + $officestyles//@draw:marker-start + $officestyles//@draw:marker-end + $stylesautostyles//@draw:marker-start + $stylesautostyles//@draw:marker-end + $contentautostyles//@draw:marker-start + $contentautostyles//@draw:marker-end + + + $officestyles/draw:stroke-dash/@draw:name + $officestyles//@draw:stroke-dash + $stylesautostyles//@draw:stroke-dash + $contentautostyles//@draw:stroke-dash + $officestyles//@draw:stroke-dash-names + $stylesautostyles//@draw:stroke-dash-names + $contentautostyles//@draw:stroke-dash-names + + + $officestyles/draw:opacity/@draw:name + $officestyles//@draw:opacity-name + $stylesautostyles//@draw:opacity-name + $contentautostyles//@draw:opacity-name + + + $stylesfontfaces/style:font-face/@style:name + $officestyles//style:text-properties/@style:font-name + $officestyles//style:text-properties/@style:font-name-asian + $officestyles//style:text-properties/@style:font-name-complex + $officestyles//style:list-level-properties/@style:font-name + $stylesautostyles//style:text-properties/@style:font-name + $stylesautostyles//style:text-properties/@style:font-name-asian + $stylesautostyles//style:text-properties/@style:font-name-complex + $stylesautostyles//style:list-level-properties/@style:font-name + + + $fontfaces/style:font-face/@style:name + $contentautostyles//style:text-properties/@style:font-name + $contentautostyles//style:text-properties/@style:font-name-asian + $contentautostyles//style:text-properties/@style:font-name-complex + $contentautostyles//style:list-level-properties/@style:font-name + + + $masterstyles/style:master-page/@style:name + + $body/office:drawing/draw:page/@draw:master-page-name + $body/office:presentation/draw:page/@draw:master-page-name + + $officestyles/style:style[@style:family='paragraph']/@style:master-page-name + $officestyles/style:style[@style:family='table']/@style:master-page-name + $stylesautostyles/style:style[@style:family='paragraph']/@style:master-page-name + $stylesautostyles/style:style[@style:family='table']/@style:master-page-name + $contentautostyles/style:style[@style:family='paragraph']/@style:master-page-name + $contentautostyles/style:style[@style:family='table']/@style:master-page-name + + $masterstyles/style:master-page/@style:next-style-name + + $officestyles/text:notes-configuration/@text:master-page-name + $officestyles/style:default-style[@style:family='section']/style:section-properties/text:notes-configuration/@text:master-page-name + $officestyles/style:style[@style:family='section']/style:section-properties/text:notes-configuration/@text:master-page-name + $stylesautostyles/style:style[@style:family='section']/style:section-properties/text:notes-configuration/@text:master-page-name + $contentautostyles/style:style[@style:family='section']/style:section-properties/text:notes-configuration/@text:master-page-name + $body/office:text/text:page-sequence/text:page/@text:master-page-name + + + + $officestyles/style:presentation-page-layout/@style:name + $masterstyles/style:handout-master/@presentation:presentation-page-layout-name + $body/office:drawing/draw:page/@presentation:presentation-page-layout-name + $body/office:presentation/draw:page/@presentation:presentation-page-layout-name + + + $stylesautostyles/style:page-layout/@style:name + $masterstyles/style:master-page/@style:page-layout-name + $masterstyles/style:master-page/presentation:notes/@style:page-layout-name + $masterstyles/style:handout-master/@style:page-layout-name + + + $contentautostyles/style:page-layout/@style:name + $body/office:presentation/draw:page/presentation:notes/@style:page-layout-name + + + $officestyles/text:list-style/@style:name + $officestyles//style:graphic-properties/text:list-style/@style:name + $officestyles/style:style/@style:list-style-name + + + $stylesautostyles/text:list-style/@style:name + $stylesautostyles//style:graphic-properties/text:list-style/@style:name + $stylesautostyles/style:style/@style:list-style-name + $masterstyles//text:list/@text:style-name + $masterstyles//text:numbered-paragraphs/@text:style-name + $masterstyles//text:list-item/@text:style-override + + + $contentautostyles/text:list-style/@style:name + $contentautostyles//style:graphic-properties/text:list-style/@style:name + $contentautostyles/style:style/@style:list-style-name + $body//text:list/@text:style-name + $body//text:numbered-paragraphs/@text:style-name + $body//text:list-item/@text:style-override + + + $officestyles/number:number-style/@style:name + $officestyles/number:currency-style/@style:name + $officestyles/number:percentage-style/@style:name + $officestyles/number:date-style/@style:name + $officestyles/number:time-style/@style:name + $officestyles/number:boolean-style/@style:name + $officestyles/number:text-style/@style:name + $officestyles/style:style/@style:data-style-name + $officestyles/style:style/@style:percentage-data-style-name + + + $stylesautostyles/number:number-style/@style:name + $stylesautostyles/number:currency-style/@style:name + $stylesautostyles/number:percentage-style/@style:name + $stylesautostyles/number:date-style/@style:name + $stylesautostyles/number:time-style/@style:name + $stylesautostyles/number:boolean-style/@style:name + $stylesautostyles/number:text-style/@style:name + $stylesautostyles/style:style/@style:data-style-name + $stylesautostyles/style:style/@style:percentage-data-style-name + $masterstyles//text:creation-date/@style:data-style-name + $masterstyles//text:creation-time/@style:data-style-name + $masterstyles//text:database-display/@style:data-style-name + $masterstyles//text:date/@style:data-style-name + $masterstyles//text:editing-duration/@style:data-style-name + $masterstyles//text:expression/@style:data-style-name + $masterstyles//text:meta-field/@style:data-style-name + $masterstyles//text:modification-date/@style:data-style-name + $masterstyles//text:modification-time/@style:data-style-name + $masterstyles//text:print-date/@style:data-style-name + $masterstyles//text:print-time/@style:data-style-name + $masterstyles//text:table-formula/@style:data-style-name + $masterstyles//text:time/@style:data-style-name + $masterstyles//text:user-defined/@style:data-style-name + $masterstyles//text:user-field-get/@style:data-style-name + $masterstyles//text:user-field-input/@style:data-style-name + $masterstyles//text:variable-get/@style:data-style-name + $masterstyles//text:variable-input/@style:data-style-name + $masterstyles//text:variable-set/@style:data-style-name + + + $contentautostyles/number:number-style/@style:name + $contentautostyles/number:currency-style/@style:name + $contentautostyles/number:percentage-style/@style:name + $contentautostyles/number:date-style/@style:name + $contentautostyles/number:time-style/@style:name + $contentautostyles/number:boolean-style/@style:name + $contentautostyles/number:text-style/@style:name + $contentautostyles/style:style/@style:data-style-name + $contentautostyles/style:style/@style:percentage-data-style-name + $body/office:presentation/presentation:date-time-decl/@style:data-style-name + $body//text:creation-date/@style:data-style-name + $body//text:creation-time/@style:data-style-name + $body//text:database-display/@style:data-style-name + $body//text:date/@style:data-style-name + $body//text:editing-duration/@style:data-style-name + $body//text:expression/@style:data-style-name + $body//text:meta-field/@style:data-style-name + $body//text:modification-date/@style:data-style-name + $body//text:modification-time/@style:data-style-name + $body//text:print-date/@style:data-style-name + $body//text:print-time/@style:data-style-name + $body//text:table-formula/@style:data-style-name + $body//text:time/@style:data-style-name + $body//text:user-defined/@style:data-style-name + $body//text:user-field-get/@style:data-style-name + $body//text:user-field-input/@style:data-style-name + $body//text:variable-get/@style:data-style-name + $body//text:variable-input/@style:data-style-name + $body//text:variable-set/@style:data-style-name + + + $officestyles/style:style[@style:family='chart']/@style:name + $officestyles/style:style[@style:family='chart']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='chart']/@style:parent-style-name + $contentautostyles/style:style[@style:family='chart']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='chart']/@style:name + $masterstyles//chart:axis/@chart:style-name + $masterstyles//chart:chart/@chart:style-name + $masterstyles//chart:data-label/@chart:style-name + $masterstyles//chart:data-point/@chart:style-name + $masterstyles//chart:equation/@chart:style-name + $masterstyles//chart:error-indicator/@chart:style-name + $masterstyles//chart:floor/@chart:style-name + $masterstyles//chart:footer/@chart:style-name + $masterstyles//chart:grid/@chart:style-name + $masterstyles//chart:legend/@chart:style-name + $masterstyles//chart:mean-value/@chart:style-name + $masterstyles//chart:plot-area/@chart:style-name + $masterstyles//chart:regression-curve/@chart:style-name + $masterstyles//chart:series/@chart:style-name + $masterstyles//chart:stock-gain-marker/@chart:style-name + $masterstyles//chart:stock-loss-marker/@chart:style-name + $masterstyles//chart:stock-range-line/@chart:style-name + $masterstyles//chart:subtitle/@chart:style-name + $masterstyles//chart:title/@chart:style-name + $masterstyles//chart:wall/@chart:style-name + + + $contentautostyles/style:style[@style:family='chart']/@style:name + $body//chart:axis/@chart:style-name + $body//chart:chart/@chart:style-name + $body//chart:data-label/@chart:style-name + $body//chart:data-point/@chart:style-name + $body//chart:equation/@chart:style-name + $body//chart:error-indicator/@chart:style-name + $body//chart:floor/@chart:style-name + $body//chart:footer/@chart:style-name + $body//chart:grid/@chart:style-name + $body//chart:legend/@chart:style-name + $body//chart:mean-value/@chart:style-name + $body//chart:plot-area/@chart:style-name + $body//chart:regression-curve/@chart:style-name + $body//chart:series/@chart:style-name + $body//chart:stock-gain-marker/@chart:style-name + $body//chart:stock-loss-marker/@chart:style-name + $body//chart:stock-range-line/@chart:style-name + $body//chart:subtitle/@chart:style-name + $body//chart:title/@chart:style-name + $body//chart:wall/@chart:style-name + + + $officestyles/style:style[@style:family='ruby']/@style:name + $officestyles/style:style[@style:family='ruby']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='ruby']/@style:parent-style-name + $contentautostyles/style:style[@style:family='ruby']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='ruby']/@style:name + $masterstyles//text:ruby/@text:style-name + + + $contentautostyles/style:style[@style:family='ruby']/@style:name + $body//text:ruby/@text:style-name + + + + $officestyles/style:style[@style:family='text']/@style:name + $officestyles/style:style[@style:family='text']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='text']/@style:parent-style-name + $contentautostyles/style:style[@style:family='text']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='text']/@style:name + $masterstyles//text:span/@text:style-name + + + $contentautostyles/style:style[@style:family='text']/@style:name + $body//text:span/@text:style-name + + + $officestyles/style:style[@style:family='paragraph']/@style:name + $officestyles/style:style[@style:family='paragraph']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='paragraph']/@style:parent-style-name + $contentautostyles/style:style[@style:family='paragraph']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='paragraph']/@style:name + $masterstyles//text:p/@text:style-name + + + $contentautostyles/style:style[@style:family='paragraph']/@style:name + $body//text:p/@text:style-name + + + $officestyles/style:style[@style:family='section']/@style:name + $officestyles/style:style[@style:family='section']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='section']/@style:parent-style-name + $contentautostyles/style:style[@style:family='section']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='section']/@style:name + $masterstyles//text:alphabetical-index/@text:style-name + + + $contentautostyles/style:style[@style:family='section']/@style:name + $body//text:alphabetical-index/@text:style-name + + + + $officestyles/style:style[@style:family='table']/@style:name + $officestyles/style:style[@style:family='table']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='table']/@style:parent-style-name + $contentautostyles/style:style[@style:family='table']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='table']/@style:name + $masterstyles//table:table/@table:style-name + + + $contentautostyles/style:style[@style:family='table']/@style:name + $body//table:table/@table:style-name + + + + $officestyles/style:style[@style:family='table-column']/@style:name + $officestyles/style:style[@style:family='table-column']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='table-column']/@style:parent-style-name + $contentautostyles/style:style[@style:family='table-column']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='table-column']/@style:name + $masterstyles//table:table-column/@table:style-name + + + $contentautostyles/style:style[@style:family='table-column']/@style:name + $body//table:table-column/@table:style-name + + + + $officestyles/style:style[@style:family='table-row']/@style:name + $officestyles/style:style[@style:family='table-row']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='table-row']/@style:parent-style-name + $contentautostyles/style:style[@style:family='table-row']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='table-row']/@style:name + $masterstyles//table:table-row/@table:style-name + + + $contentautostyles/style:style[@style:family='table-row']/@style:name + $body//table:table-row/@table:style-name + + + + $officestyles/style:style[@style:family='table-cell']/@style:name + $officestyles/style:style[@style:family='table-cell']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='table-cell']/@style:parent-style-name + $contentautostyles/style:style[@style:family='table-cell']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='table-cell']/@style:name + $masterstyles//table:table-cell/@table:style-name + + + $contentautostyles/style:style[@style:family='table-cell']/@style:name + $body//table:table-cell/@table:style-name + + + + $officestyles/style:style[@style:family='graphic']/@style:name + $officestyles/style:style[@style:family='graphic']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='graphic']/@style:parent-style-name + $contentautostyles/style:style[@style:family='graphic']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='graphic']/@style:name + $masterstyles//draw:rect/@draw:style-name + + + $contentautostyles/style:style[@style:family='graphic']/@style:name + $body//draw:rect/@draw:style-name + + + + $officestyles/style:style[@style:family='presentation']/@style:name + $officestyles/style:style[@style:family='presentation']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='presentation']/@style:parent-style-name + $contentautostyles/style:style[@style:family='presentation']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='presentation']/@style:name + $masterstyles//draw:rect/@presentation:style-name + + + $contentautostyles/style:style[@style:family='presentation']/@style:name + $body//draw:rect/@presentation:style-name + + + + $officestyles/style:style[@style:family='drawing-page']/@style:name + $officestyles/style:style[@style:family='drawing-page']/@style:parent-style-name + $stylesautostyles/style:style[@style:family='drawing-page']/@style:parent-style-name + $contentautostyles/style:style[@style:family='drawing-page']/@style:parent-style-name + + + $stylesautostyles/style:style[@style:family='drawing-page']/@style:name + $masterstyles/style:handout-master/@draw:style-name + + + $contentautostyles/style:style[@style:family='drawing-page']/@style:name + $body/office:drawing/draw:page/@draw:style-name + $body/office:presentation/draw:page/@draw:style-name + + +
diff --git a/apps/files_odfviewer/src/webodf/webodf/tools/runjslint.js b/apps/files_odfviewer/src/webodf/webodf/tools/runjslint.js new file mode 100644 index 0000000000..c0d28dc77d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/tools/runjslint.js @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global runtime: true, core: true*/ +runtime.loadClass("core.JSLint"); + +function checkWithJSLINT(file) { + "use strict"; + var i, jslint = new core.JSLint().JSLINT, + jslintconfig = { + anon: false, // true, if the space may be omitted in anonymous function declarations + bitwise: false, // if bitwise operators should be allowed + browser: false, // if the standard browser globals should be predefined + cap: false, // if upper case HTML should be allowed + 'continue': false, // if the continuation statement should be tolerated + css: false, // if CSS workarounds should be tolerated + debug: false, // if debugger statements should be allowed + devel: false, // if logging should be allowed (console, alert, etc.) + eqeq: false, // if == should be allowed + es5: false, // if ES5 syntax should be allowed + evil: false, // if eval should be allowed + forin: false, // if for in statements need not filter + fragment: false, // if HTML fragments should be allowed + indent: 4, // the indentation factor + maxerr: 10, // the maximum number of errors to allow + //maxlen: 300, // the maximum length of a source line + newcap: false, // if constructor names capitalization is ignored + node: false, // if Node.js globals should be predefined + nomen: false, // if names may have dangling _ + on: false, // if HTML event handlers should be allowed + passfail: true, // if the scan should stop on first error + plusplus: false, // if increment/decrement should be allowed + properties: false, // if all property names must be declared with /*properties*/ + regexp: false, // if the . should be allowed in regexp literals + rhino: false, // if the Rhino environment globals should be predefined + undef: false, // if variables can be declared out of order + unparam: false, // if unused parameters should be tolerated + safe: false, // if use of some browser features should be restricted + sloppy: false, // if the 'use strict'; pragma is optional + stupid: true, // true if stupid practices are tolerated + sub: false, // if all forms of subscript notation are tolerated + vars: false, // if multiple var statements per function should be allowed + white: true, // if sloppy whitespace is tolerated + widget: false, // if the Yahoo Widgets globals should be predefined + windows: false // if MS Windows-specific globals should be predefined + }, + data, result, err; + + // these files are an exception for now + if (file === "lib/core/RawInflate.js") { + return; + } + + data = runtime.readFileSync(file, "utf-8"); + result = jslint(data, jslintconfig); + if (!result) { + for (i = 0; i < jslint.errors.length && jslint.errors[i]; i += 1) { + err = jslint.errors[i]; + runtime.log(file + ":" + err.line + ":" + err.character + + ": error: " + err.reason); + } + runtime.exit(1); + } +} + +var i; +for (i = 0; i < arguments.length; i += 1) { + checkWithJSLINT(arguments[i]); +} diff --git a/apps/files_odfviewer/src/webodf/webodf/webodf.css b/apps/files_odfviewer/src/webodf/webodf/webodf.css new file mode 100644 index 0000000000..dbd6686a26 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/webodf.css @@ -0,0 +1,200 @@ +@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0); +@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0); +@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0); +@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0); +@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0); +@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0); +@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0); +@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0); +@namespace runtimens url(urn:webodf); /* namespace for runtime only */ + +office|document > *, office|document-content > * { + display: none; +} +office|body, office|document { + display: inline-block; + position: relative; +} + +text|p, text|h { + display: block; + padding: 3px 3px 3px 3px; + margin: 5px 5px 5px 5px; +} +text|h { + font-weight: bold; +} +*[runtimens|containsparagraphanchor] { + position: relative; +} +text|s:before { /* this needs to be the number of spaces given by text:c */ + content: ' '; +} +text|tab:before { + display: inline; + content: ' '; +} +text|line-break { + content: " "; + display: block; +} +text|tracked-changes { + /*Consumers that do not support change tracking, should ignore changes.*/ + display: none; +} +office|binary-data { + display: none; +} +office|text { + display: block; + width: 216mm; /* default to A4 width */ + min-height: 279mm; + padding-left: 32mm; + padding-right: 32mm; + padding-top: 25mm; + padding-bottom: 13mm; + margin: 2px; + text-align: left; + overflow: hidden; +} +office|spreadsheet { + display: block; + border-collapse: collapse; + empty-cells: show; + font-family: sans-serif; + font-size: 10pt; + text-align: left; + page-break-inside: avoid; + overflow: hidden; +} +office|presentation { + display: inline-block; + text-align: left; +} +draw|page { + display: block; + height: 21cm; + width: 28cm; + margin: 3px; + position: relative; + overflow: hidden; +} +presentation|notes { + display: none; +} +@media print { + draw|page { + border: 1pt solid black; + page-break-inside: avoid; + } + presentation|notes { + /*TODO*/ + } +} +office|spreadsheet text|p { + border: 0px; + padding: 1px; + margin: 0px; +} +office|spreadsheet table|table { + margin: 3px; +} +office|spreadsheet table|table:after { + /* show sheet name the end of the sheet */ + /*content: attr(table|name);*/ /* gives parsing error in opera */ +} +office|spreadsheet table|table-row { + counter-increment: row; +} +office|spreadsheet table|table-row:before { + width: 3em; + background: #cccccc; + border: 1px solid black; + text-align: center; + content: counter(row); +} +office|spreadsheet table|table-cell { + border: 1px solid #cccccc; +} +table|table { + display: table; +} +draw|frame table|table { + width: 100%; + height: 100%; + background: white; +} +table|table-row { + display: table-row; +} +table|table-column { + display: table-column; +} +table|table-cell { + display: table-cell; +} +draw|frame { + display: block; +} +draw|image { + display: block; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + background-repeat: no-repeat; + background-size: 100% 100%; + -moz-background-size: 100% 100%; +} +/* only show the first image in frame */ +draw|frame > draw|image:nth-of-type(n+2) { + display: none; +} +text|list { + display: block; + padding-left: 1.5em; + counter-reset: list; +} +text|list-item { + display: block; +} +text|list-item:before { + display: inline-block; + content: '•'; + counter-increment: list; + width: 0.5em; + margin-left: -0.5em; + padding: 0px; + border: 0px; +} +text|list-item > *:first-child { + display: inline-block; +} +text|a { + color: blue; + text-decoration: underline; +} +text|note-citation { + vertical-align: super; + font-size: smaller; +} +text|note-body { + display: none; +} +text|note:hover text|note-citation { + background: #dddddd; +} +text|note:hover text|note-body { + display: block; + left:1em; + max-width: 80%; + position: absolute; + background: #ffffaa; +} +svg|title, svg|desc { + display: none; +} +video { + width:100%; + height:100% +} diff --git a/apps/files_odfviewer/src/webodf/webodf/xmledit/gui.js b/apps/files_odfviewer/src/webodf/webodf/xmledit/gui.js new file mode 100644 index 0000000000..e38c286aae --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/xmledit/gui.js @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2011 KO GmbH + * @licstart + * The JavaScript code in this page is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public License + * (GNU AGPL) as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. The code is distributed + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * + * As additional permission under GNU AGPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + * + * As a special exception to the AGPL, any HTML file which merely makes function + * calls to this code, and for that purpose includes it by reference shall be + * deemed a separate work for copyright law purposes. In addition, the copyright + * holders of this code give you permission to combine this code with free + * software libraries that are released under the GNU LGPL. You may copy and + * distribute such a system following the terms of the GNU AGPL for this code + * and the LGPL for the libraries. If you modify this code, you may extend this + * exception to your version of the code, but you are not obligated to do so. + * If you do not wish to do so, delete this exception statement from your + * version. + * + * This license applies to this entire compilation. + * @licend + * @source: http://www.webodf.org/ + * @source: http://gitorious.org/odfkit/webodf/ + */ +/*global Ext runtime gui*/ +runtime.loadClass("gui.XMLEdit"); + +function createXMLEdit(element, url) { + var head = element.ownerDocument.getElementsByTagName("head")[0], + xmlcss = element.ownerDocument.createElement("style"), + xmledt; + + xmlcss.type = "text/css"; + head.appendChild(xmlcss); + xmledt = new gui.XMLEdit(element, xmlcss); + runtime.loadXML(url, function (err, xml) { + if (xml.documentElement) { + xmledt.setXML(xml); + } + }); +} + +function loadXML(url, panel, title) { + title = title || url; + var tab = panel.find('url', url), + newTab; + if (tab.length) { + panel.setActiveTab(tab[0]); + return; + } + newTab = new Ext.BoxComponent({ + title: title, + tabTip: url, + url: url, + closable: true, + autoEl: { + tag: 'div' + }, + region: 'center' + }); + panel.add(newTab); + panel.setActiveTab(newTab); + + createXMLEdit(newTab.el.dom, url); +} + +Ext.onReady(function () { + var tabpanel, tree, viewport, attributeEditor; + + Ext.QuickTips.init(); + + tabpanel = new Ext.TabPanel({ + tbar: [ ], + region: 'center' + }); + + attributeEditor = new Ext.grid.PropertyGrid({ + title: 'Attributes', + region: 'east', + width: 200, + split: true, + autoScroll: true, + collapsible: true, + rootVisible: false, + enableTabScroll: true, + defaults: {autoScroll: true} + }); + + tree = new Ext.tree.TreePanel({ + title: 'Documents', + region: 'west', + width: 200, + split: true, + autoScroll: true, + collapsible: true, + rootVisible: false, + enableTabScroll: true, + defaults: {autoScroll: true}, + collapsed: true, + root: { nodeType: 'node' } + }); + + viewport = new Ext.Viewport({ + layout: 'border', + items: [ tabpanel, tree, attributeEditor ] + }); + + // load the xml + loadXML('requirements.xml', tabpanel); + loadXML('../content.xml', tabpanel); +}); diff --git a/apps/files_odfviewer/src/webodf/webodf/xmledit/index.html b/apps/files_odfviewer/src/webodf/webodf/xmledit/index.html new file mode 100644 index 0000000000..dd6ae4942e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/xmledit/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + XMLEdit + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.dtd b/apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.dtd new file mode 100644 index 0000000000..82cb8deb8f --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.dtd @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.xml b/apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.xml new file mode 100644 index 0000000000..cbeae4ce7e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/xmledit/requirements.xml @@ -0,0 +1,22 @@ + + + + + + + load xml document in a frame + + + show xml in a frame with a specified css + + + diff --git a/apps/files_odfviewer/src/webodf/webodf/xmledit/test.xml b/apps/files_odfviewer/src/webodf/webodf/xmledit/test.xml new file mode 100644 index 0000000000..cad3f32470 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/webodf/xmledit/test.xml @@ -0,0 +1,22 @@ + + + + + + + load xml document in a frame + + + show xml in a frame with a specified css + + +

Cn*^&C zJ(~MDe`9t6pK=oY&@Ww6NjGiVs|v2q&oI^8dxWN+Duc&33Emq6WBaTKJ|!hp1b_La zJ(*`F&-bGn?QvUc)s;sgfp4xbjE>Wnlv=XHTA=Di#Ol>ZZM&hFsjDPe$vpB|PY!WV zFH`Cgs@XdC-Ih^a=Jc$BP$i=W%}Nk0I}&3bq0|uGUu|cdk0Fw z^_Bv_wHeZt`b*4Kv*coQDuO}JNaQm>a35nTSwUJ*t>tc_S`VylT3@^s9b!>+6wpER zlwmSSlPpN{!jjGT4ZTF*S)ZkvZW>Ppkwgq1O!<33n#r%uLIe2z@+?0to0gnf{q(tL zNS?{ED|=QIQmE^hGADCM=jtz+(;4I_yOQhm4wn#IZPA(vx%aBTR^pE~s))LNgZ=9c z`D+v0Tp3{;wky%FG6ufV&n#Z+(gp)13XRh-YsuX^R^PA8I9|7^a+(v9)vY?|GD$~& z8y>s$>U!1aq;_pba6Pt*UmaCHfmv#|fhqK_j4bBu{x8*CNeaq_qbD5cMEc_`;10yQU7o%{YKMGAgQ^s?2mg;2qp68((jO78JO+#%Etny zS4FLLIT(qJ@5F`ny)Rd3n7^C+VuVoGcD`~?-=)SoN+Aa(a|vr}1K;`9;EUbdY9^Kh zz$6LJy813;j{_Z79MR8cm8;c{5XyMfzELs;+IH?$vMuwu&^-A1gMi#N*_x`$n#kS zSg2?%4SB4iK4QWgfC!?~^l$ELDK*T$3G)-KJVB}dy3jJ@Ok|8Ocy3fY&-Q=`S-e?< zo}L*b0Y2CKNUx=es*Xx3R~Z%20 zHUT_J>y8E4*c?-4&O5K}E6q~F-MKm9z*y%Gpqra!a$-_c3xg}e1LuINERf-A>{k@> z38An(h)=^TdyA+?NZx4w`Z|7@ESpz_*&*VU-X|3iC;{oO!z1&ywl9{n^B2R$37@(m zFm`9C0C=J=u@H#p@(B^xQEc?bE(P8Ci`)?0>}T)+*2|!mXK>tNOV?Zy38Oxc{njsJP?m?QXb;c3F&h$-3w@cR`6~6 zt$Cw#Rm?Asa~@k9ugd*Oqm@cY?^|Sa>GbkVa6)S-Ub>TASR5AQ4@%LU2wkfca(6DQ zOpy+x{cga2`b8$mb%vVr#TOFJ+1skW9)Uau$o(I)tq0CMJK%^O*m@{ga6o?nYFZXH z$R^OLzLK*f5;%>hJ$(6fenxmpV>qK(c-u)1Vb{1aJaa*w4?Z1tVtAc<+rP$~UnuDr zCxh^48eb+|6fd#gOlI~U9wlBk75|f?-H{YA1MWPaIQEHrk4aQuYwJ|iD_uUq=+@-6rm!*Z zlUP!YB>o~HEZvF!IquEn3~l~>-ay3ROeVh8`0;5!0#Vjls>nj6!DO7_Sjo4i%4!Oz zbSA@J{w=#!9&Bhq{%x%fe8RoLt1igsrk*C5^e7`ET$Qt4JSEDJjA!hYYZ?b#Q&KUU zNj9AuOP2#%C&ZS2RNuhfa1nejFa!}FPqvZQE}7L?9$lbc3$zARi4`jo$uSf(%tveb zP!w>8j%VFAovY6qHmI!=*Na0K!(qg$!LJ_`?J+t`;W5vEb9d)FvTl2oXeqankVo^#(M^U?nUHeT>Ol7}&BW_;Q2z%AYy;@=SnEFhSe&(m}AoA1x< zQyDD7I#gz2arKzP0iX=*UWu9rIQpGmic2g^1DCf%{68~j_?x7NsW&fk6+9=InYyuUOo5=SQ(%$M6cBDJXeEm@7p2D} zH+#!=W=^XD;w@H7c;NZai1+pnTOYW?I37`q4PxNZ7kLX^{v{^v($<;15D0C}nR_L| zU;)BdL8zZniqIEVTS=7#S&N^Cf(XaqQSJt~b=xE{ z8cQMKui*=8zCCs+zVieq(JiHaVwasOzDG}>B9zJ%=9_LwmM<#%5d6mv?=wlv{i@P_ z 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 n_J}L}1oQu||JNkY#qnZ6K`>)< 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Info.plist b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Info.plist new file mode 100644 index 0000000000..18518ec4c1 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Info.plist @@ -0,0 +1,122 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleDocumentTypes + + + CFBundleTypeIconFiles + + icon.png + + CFBundleTypeName + OpenDocument Text + CFBundleTypeRole + Viewer + LSHandlerRank + Owner + LSItemContentTypes + + org.oasis.opendocument.text + + + + CFBundleTypeIconFiles + + icon.png + + CFBundleTypeName + OpenDocument Presentation + CFBundleTypeRole + Viewer + LSHandlerRank + Owner + LSItemContentTypes + + org.oasis.opendocument.presentation + + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + icon.png + CFBundleIconFiles + + icon.png + icon@2x.png + icon-72.png + + CFBundleIdentifier + WebODF-03 + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeRight + + UTExportedTypeDeclarations + + + UTTypeConformsTo + + org.gnu.gnu-zip-archive + + UTTypeDescription + OpenDocument Text + UTTypeIdentifier + org.oasis.opendocument.text + UTTypeTagSpecification + + public.filename-extension + odt + public.mime-type + application/vnd.oasis.opendocument.text + + + + UTTypeConformsTo + + org.gnu.gnu-zip-archive + + UTTypeDescription + OpenDocument Presentation + UTTypeIdentifier + org.oasis.opendocument.presentation + UTTypeTagSpecification + + public.filename-extension + odp + public.mime-type + application/vnd.oasis.opendocument.presentation + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Prefix.pch b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Prefix.pch new file mode 100644 index 0000000000..da48b6a1fd --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/WebODF-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'WebODF' target in the 'WebODF' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/en.lproj/InfoPlist.strings b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/en.lproj/InfoPlist.strings new file mode 100644 index 0000000000..477b28ff8f --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/WebODF/main.m b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/main.m new file mode 100644 index 0000000000..bda2f99ea3 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/WebODF/main.m @@ -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. + */ +// +// main.m +// WebODF +// +// Created by KO GmbH on 2/2/12. +// Copyright __MyCompanyName__ 2012. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate"); + return retVal; +} diff --git a/apps/files_odfviewer/src/webodf/programs/ios/www/index.html b/apps/files_odfviewer/src/webodf/programs/ios/www/index.html new file mode 100644 index 0000000000..ec998a1005 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/www/index.html @@ -0,0 +1,52 @@ + + + + WebODF + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/ios/www/nativezip.js b/apps/files_odfviewer/src/webodf/programs/ios/www/nativezip.js new file mode 100644 index 0000000000..04a8ff13c7 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/www/nativezip.js @@ -0,0 +1,84 @@ +/*global PhoneGap, core*/ + +var ZipPlugin = { + loadAsString: function (zippath, entrypath, success, fail) { + "use strict"; + return PhoneGap.exec(success, fail, "ZipClass", "loadAsString", [zippath, entrypath]); + }, + loadAsDataURL: function (zippath, entrypath, mimetype, success, fail) { + "use strict"; + return PhoneGap.exec(success, fail, "ZipClass", "loadAsDataURL", [zippath, entrypath, mimetype]); + } +}; +core.Zip = function (url, entriesReadCallback) { + "use strict"; + // remove 'odf:' prefix + url = url.substr(4); + var zip = this; + this.load = function (filename, callback) { + //alert(filename); + callback(null, ""); + }; + this.loadAsString = function (filename, callback) { + alert("loadAsString"); + }; + this.loadAsDOM = function (filename, callback) { + var xhr = new XMLHttpRequest(); + function handleResult() { + var xml; + console.log("loading " + filename + " status " + xhr.status + " readyState " + xhr.readyState); + if (xhr.readyState === 4) { + xml = xhr.responseXML; + console.log("done accessing responseXML " + xml + " " + (xhr.responseText && xhr.responseText.length) + + " " + xhr.statusText); + console.log("statusText " + xhr.statusText); + if (xhr.status === 0 && !xml) { + // empty files are considered as errors + callback("File " + path + " is not valid XML."); + } else if (xhr.status === 200 || xhr.status === 0) { + try { + callback(null, xml); + } catch (e) { + console.log(e); + } + } else { + // report error + callback(xhr.responseText || xhr.statusText); + } + } + } + xhr.open('GET', "http://zipserver" + url + "?" + filename, true); + xhr.onreadystatechange = handleResult; + xhr.send(null); + }; + this.loadAsDataURL = function (filename, mimetype, callback) { + callback(null, "http://zipserver" + url + "?" + filename); + /* + ZipPlugin.loadAsDataURL(url, filename, mimetype, + function (content) { + callback(null, content); + }, + function (err) { callback(err, null); } + ); + */ + }; + this.getEntries = function () { + alert("getEntries"); + }; + this.loadContentXmlAsFragments = function (filename, handler) { + // the javascript implementation simply reads the file + zip.loadAsString(filename, function (err, data) { + if (err) { + return handler.rootElementReady(err); + } + handler.rootElementReady(null, data, true); + }); + }; + this.save = function () { + alert("save"); + }; + this.write = function () { + alert("write"); + }; + entriesReadCallback(null, this); +}; diff --git a/apps/files_odfviewer/src/webodf/programs/ios/www/phonegap-1.4.1.js b/apps/files_odfviewer/src/webodf/programs/ios/www/phonegap-1.4.1.js new file mode 100644 index 0000000000..680e180209 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/ios/www/phonegap-1.4.1.js @@ -0,0 +1,4123 @@ +/* PhoneGap v1.4.1 */ +/* + 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. +*/ + + +/* + * Some base contributions + * Copyright (c) 2011, Proyectos Equis Ka, S.L. + */ + +if (typeof PhoneGap === "undefined") { + +if (typeof(DeviceInfo) !== 'object'){ + DeviceInfo = {}; +} +/** + * This represents the PhoneGap API itself, and provides a global namespace for accessing + * information about the state of PhoneGap. + * @class + */ +PhoneGap = { + // This queue holds the currently executing command and all pending + // commands executed with PhoneGap.exec(). + commandQueue: [], + // Indicates if we're currently in the middle of flushing the command + // queue on the native side. + commandQueueFlushing: false, + _constructors: [], + documentEventHandler: {}, // Collection of custom document event handlers + windowEventHandler: {} +}; + +/** + * List of resource files loaded by PhoneGap. + * This is used to ensure JS and other files are loaded only once. + */ +PhoneGap.resources = {base: true}; + +/** + * Determine if resource has been loaded by PhoneGap + * + * @param name + * @return + */ +PhoneGap.hasResource = function(name) { + return PhoneGap.resources[name]; +}; + +/** + * Add a resource to list of loaded resources by PhoneGap + * + * @param name + */ +PhoneGap.addResource = function(name) { + PhoneGap.resources[name] = true; +}; + +/** + * Boolean flag indicating if the PhoneGap API is available and initialized. + */ // TODO: Remove this, it is unused here ... -jm +PhoneGap.available = DeviceInfo.uuid != undefined; + +/** + * Add an initialization function to a queue that ensures it will run and initialize + * application constructors only once PhoneGap has been initialized. + * @param {Function} func The function callback you want run once PhoneGap is initialized + */ +PhoneGap.addConstructor = function(func) { + var state = document.readyState; + if ( ( state == 'loaded' || state == 'complete' ) && DeviceInfo.uuid != null ) + { + func(); + } + else + { + PhoneGap._constructors.push(func); + } +}; + +(function() + { + var timer = setInterval(function() + { + + var state = document.readyState; + + if ( ( state == 'loaded' || state == 'complete' ) && DeviceInfo.uuid != null ) + { + clearInterval(timer); // stop looking + // run our constructors list + while (PhoneGap._constructors.length > 0) + { + var constructor = PhoneGap._constructors.shift(); + try + { + constructor(); + } + catch(e) + { + if (typeof(console['log']) == 'function') + { + console.log("Failed to run constructor: " + console.processMessage(e)); + } + else + { + alert("Failed to run constructor: " + e.message); + } + } + } + // all constructors run, now fire the deviceready event + var e = document.createEvent('Events'); + e.initEvent('deviceready'); + document.dispatchEvent(e); + } + }, 1); +})(); + +// session id for calls +PhoneGap.sessionKey = 0; + +// centralized callbacks +PhoneGap.callbackId = 0; +PhoneGap.callbacks = {}; +PhoneGap.callbackStatus = { + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 + }; + +/** + * Creates a gap bridge iframe used to notify the native code about queued + * commands. + * + * @private + */ +PhoneGap.createGapBridge = function() { + gapBridge = document.createElement("iframe"); + gapBridge.setAttribute("style", "display:none;"); + gapBridge.setAttribute("height","0px"); + gapBridge.setAttribute("width","0px"); + gapBridge.setAttribute("frameborder","0"); + document.documentElement.appendChild(gapBridge); + return gapBridge; +} + +/** + * Execute a PhoneGap command by queuing it and letting the native side know + * there are queued commands. The native side will then request all of the + * queued commands and execute them. + * + * Arguments may be in one of two formats: + * + * FORMAT ONE (preferable) + * The native side will call PhoneGap.callbackSuccess or + * PhoneGap.callbackError, depending upon the result of the action. + * + * @param {Function} success The success callback + * @param {Function} fail The fail callback + * @param {String} service The name of the service to use + * @param {String} action The name of the action to use + * @param {String[]} [args] Zero or more arguments to pass to the method + * + * FORMAT TWO + * @param {String} command Command to be run in PhoneGap, e.g. + * "ClassName.method" + * @param {String[]} [args] Zero or more arguments to pass to the method + * object parameters are passed as an array object + * [object1, object2] each object will be passed as + * JSON strings + */ +PhoneGap.exec = function() { + if (!PhoneGap.available) { + alert("ERROR: Attempting to call PhoneGap.exec()" + +" before 'deviceready'. Ignoring."); + return; + } + + var successCallback, failCallback, service, action, actionArgs; + var callbackId = null; + if (typeof arguments[0] !== "string") { + // FORMAT ONE + successCallback = arguments[0]; + failCallback = arguments[1]; + service = arguments[2]; + action = arguments[3]; + actionArgs = arguments[4]; + + // Since we need to maintain backwards compatibility, we have to pass + // an invalid callbackId even if no callback was provided since plugins + // will be expecting it. The PhoneGap.exec() implementation allocates + // an invalid callbackId and passes it even if no callbacks were given. + callbackId = 'INVALID'; + } else { + // FORMAT TWO + splitCommand = arguments[0].split("."); + action = splitCommand.pop(); + service = splitCommand.join("."); + actionArgs = Array.prototype.splice.call(arguments, 1); + } + + // Start building the command object. + var command = { + className: service, + methodName: action, + arguments: [] + }; + + // Register the callbacks and add the callbackId to the positional + // arguments if given. + if (successCallback || failCallback) { + callbackId = service + PhoneGap.callbackId++; + PhoneGap.callbacks[callbackId] = + {success:successCallback, fail:failCallback}; + } + if (callbackId != null) { + command.arguments.push(callbackId); + } + + for (var i = 0; i < actionArgs.length; ++i) { + var arg = actionArgs[i]; + if (arg == undefined || arg == null) { + continue; + } else if (typeof(arg) == 'object') { + command.options = arg; + } else { + command.arguments.push(arg); + } + } + + // Stringify and queue the command. We stringify to command now to + // effectively clone the command arguments in case they are mutated before + // the command is executed. + PhoneGap.commandQueue.push(JSON.stringify(command)); + + // If the queue length is 1, then that means it was empty before we queued + // the given command, so let the native side know that we have some + // commands to execute, unless the queue is currently being flushed, in + // which case the command will be picked up without notification. + if (PhoneGap.commandQueue.length == 1 && !PhoneGap.commandQueueFlushing) { + if (!PhoneGap.gapBridge) { + PhoneGap.gapBridge = PhoneGap.createGapBridge(); + } + + PhoneGap.gapBridge.src = "gap://ready"; + } +} + +/** + * Called by native code to retrieve all queued commands and clear the queue. + */ +PhoneGap.getAndClearQueuedCommands = function() { + json = JSON.stringify(PhoneGap.commandQueue); + PhoneGap.commandQueue = []; + return json; +} + +/** + * Called by native code when returning successful result from an action. + * + * @param callbackId + * @param args + * args.status - PhoneGap.callbackStatus + * args.message - return value + * args.keepCallback - 0 to remove callback, 1 to keep callback in PhoneGap.callbacks[] + */ +PhoneGap.callbackSuccess = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + + // If result is to be sent to callback + if (args.status == PhoneGap.callbackStatus.OK) { + try { + if (PhoneGap.callbacks[callbackId].success) { + PhoneGap.callbacks[callbackId].success(args.message); + } + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + +/** + * Called by native code when returning error result from an action. + * + * @param callbackId + * @param args + */ +PhoneGap.callbackError = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + try { + if (PhoneGap.callbacks[callbackId].fail) { + PhoneGap.callbacks[callbackId].fail(args.message); + } + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + + +/** + * Does a deep clone of the object. + * + * @param obj + * @return + */ +PhoneGap.clone = function(obj) { + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + var retVal = new Array(); + for(var i = 0; i < obj.length; ++i){ + retVal.push(PhoneGap.clone(obj[i])); + } + return retVal; + } + + if (obj instanceof Function) { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + if (obj instanceof Date) { + return obj; + } + + retVal = new Object(); + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = PhoneGap.clone(obj[i]); + } + } + return retVal; +}; + +// Intercept calls to document.addEventListener +PhoneGap.m_document_addEventListener = document.addEventListener; + +// Intercept calls to window.addEventListener +PhoneGap.m_window_addEventListener = window.addEventListener; + +/** + * Add a custom window event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addWindowEventHandler = function(event, callback) { + PhoneGap.windowEventHandler[event] = callback; +} + +/** + * Add a custom document event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addDocumentEventHandler = function(event, callback) { + PhoneGap.documentEventHandler[event] = callback; +} + +/** + * Intercept adding document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_addEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept adding window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_addEventListener.call(window, evt, handler, capture); +}; + +// Intercept calls to document.removeEventListener and watch for events that +// are generated by PhoneGap native code +PhoneGap.m_document_removeEventListener = document.removeEventListener; + +// Intercept calls to window.removeEventListener +PhoneGap.m_window_removeEventListener = window.removeEventListener; + +/** + * Intercept removing document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_removeEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept removing window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_removeEventListener.call(window, evt, handler, capture); +}; + +/** + * Method to fire document event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireDocumentEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + document.dispatchEvent(e); +}; + +/** + * Method to fire window event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireWindowEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + window.dispatchEvent(e); +}; + +/** + * Method to fire event from native code + * Leaving this generic version to handle problems with iOS 3.x. Is currently used by orientation and battery events + * Remove when iOS 3.x no longer supported and call fireWindowEvent or fireDocumentEvent directly + */ +PhoneGap.fireEvent = function(type, target, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + target = target || document; + if (target.dispatchEvent === undefined) { // ie window.dispatchEvent is undefined in iOS 3.x + target = document; + } + + target.dispatchEvent(e); +}; +/** + * Create a UUID + * + * @return + */ +PhoneGap.createUUID = function() { + return PhoneGap.UUIDcreatePart(4) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(6); +}; + +PhoneGap.UUIDcreatePart = function(length) { + var uuidpart = ""; + for (var i=0; i -1) { + me._batteryListener.splice(pos, 1); + } + } else if (eventType === "batterylow") { + var pos = me._lowListener.indexOf(handler); + if (pos > -1) { + me._lowListener.splice(pos, 1); + } + } else if (eventType === "batterycritical") { + var pos = me._criticalListener.indexOf(handler); + if (pos > -1) { + me._criticalListener.splice(pos, 1); + } + } + + // If there are no more registered event listeners stop the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + PhoneGap.exec(null, null, "com.phonegap.battery", "stop", []); + } + } +}; + +/** + * Callback for battery status + * + * @param {Object} info keys: level, isPlugged + */ +Battery.prototype._status = function(info) { + if (info) { + var me = this; + if (me._level != info.level || me._isPlugged != info.isPlugged) { + // Fire batterystatus event + //PhoneGap.fireWindowEvent("batterystatus", info); + // use this workaround since iOS 3.x does have window.dispatchEvent + PhoneGap.fireEvent("batterystatus", window, info); + + // Fire low battery event + if (info.level == 20 || info.level == 5) { + if (info.level == 20) { + //PhoneGap.fireWindowEvent("batterylow", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + PhoneGap.fireEvent("batterylow", window, info); + } + else { + //PhoneGap.fireWindowEvent("batterycritical", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + PhoneGap.fireEvent("batterycritical", window, info); + } + } + } + me._level = info.level; + me._isPlugged = info.isPlugged; + } +}; + +/** + * Error callback for battery start + */ +Battery.prototype._error = function(e) { + console.log("Error initializing Battery: " + e); +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.battery === "undefined") { + navigator.battery = new Battery(); + PhoneGap.addWindowEventHandler("batterystatus", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterylow", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterycritical", navigator.battery.eventHandler); + } +}); +}if (!PhoneGap.hasResource("camera")) { + PhoneGap.addResource("camera"); + + +/** + * This class provides access to the device camera. + * @constructor + */ +Camera = function() { + +} +/** + * Available Camera Options + * {boolean} allowEdit - true to allow editing image, default = false + * {number} quality 0-100 (low to high) default = 100 + * {Camera.DestinationType} destinationType default = DATA_URL + * {Camera.PictureSourceType} sourceType default = CAMERA + * {number} targetWidth - width in pixels to scale image default = 0 (no scaling) + * {number} targetHeight - height in pixels to scale image default = 0 (no scaling) + * {Camera.EncodingType} - encodingType default = JPEG + * {boolean} correctOrientation - Rotate the image to correct for the orientation of the device during capture (iOS only) + * {boolean} saveToPhotoAlbum - Save the image to the photo album on the device after capture (iOS only) + */ +/** + * Format of image that is returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.DestinationType = { + DATA_URL: 0, // Return base64 encoded string + FILE_URI: 1 // Return file uri +}; +Camera.prototype.DestinationType = Camera.DestinationType; + +/** + * Source to getPicture from. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.PictureSourceType = { + PHOTOLIBRARY : 0, // Choose image from picture library + CAMERA : 1, // Take picture from camera + SAVEDPHOTOALBUM : 2 // Choose image from picture library +}; +Camera.prototype.PictureSourceType = Camera.PictureSourceType; + +/** + * Encoding of image returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.CAMERA, + * encodingType: Camera.EncodingType.PNG}) + */ +Camera.EncodingType = { + JPEG: 0, // Return JPEG encoded image + PNG: 1 // Return PNG encoded image +}; +Camera.prototype.EncodingType = Camera.EncodingType; + +/** + * Type of pictures to select from. Only applicable when + * PictureSourceType is PHOTOLIBRARY or SAVEDPHOTOALBUM + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY, + * mediaType: Camera.MediaType.PICTURE}) + */ +Camera.MediaType = { + PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType + VIDEO: 1, // allow selection of video only, ONLY RETURNS URL + ALLMEDIA : 2 // allow selection from all media types +}; +Camera.prototype.MediaType = Camera.MediaType; + +/** + * Gets a picture from source defined by "options.sourceType", and returns the + * image as defined by the "options.destinationType" option. + + * The defaults are sourceType=CAMERA and destinationType=DATA_URL. + * + * @param {Function} successCallback + * @param {Function} errorCallback + * @param {Object} options + */ +Camera.prototype.getPicture = function(successCallback, errorCallback, options) { + // successCallback required + if (typeof successCallback != "function") { + console.log("Camera Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback != "function")) { + console.log("Camera Error: errorCallback is not a function"); + return; + } + + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.camera","getPicture",[options]); +}; + + + +PhoneGap.addConstructor(function() { + if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); +}); +}; + +if (!PhoneGap.hasResource("device")) { + PhoneGap.addResource("device"); + +/** + * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the + * phone, etc. + * @constructor + */ +Device = function() +{ + this.platform = null; + this.version = null; + this.name = null; + this.phonegap = null; + this.uuid = null; + try + { + this.platform = DeviceInfo.platform; + this.version = DeviceInfo.version; + this.name = DeviceInfo.name; + this.phonegap = DeviceInfo.gap; + this.uuid = DeviceInfo.uuid; + + } + catch(e) + { + // TODO: + } + this.available = PhoneGap.available = this.uuid != null; +} + +PhoneGap.addConstructor(function() { + if (typeof navigator.device === "undefined") { + navigator.device = window.device = new Device(); + } +}); +}; +if (!PhoneGap.hasResource("capture")) { + PhoneGap.addResource("capture"); +/** + * The CaptureError interface encapsulates all errors in the Capture API. + */ +function CaptureError() { + this.code = null; +}; + +// Capture error codes +CaptureError.CAPTURE_INTERNAL_ERR = 0; +CaptureError.CAPTURE_APPLICATION_BUSY = 1; +CaptureError.CAPTURE_INVALID_ARGUMENT = 2; +CaptureError.CAPTURE_NO_MEDIA_FILES = 3; +CaptureError.CAPTURE_NOT_SUPPORTED = 20; + +/** + * The Capture interface exposes an interface to the camera and microphone of the hosting device. + */ +function Capture() { + this.supportedAudioModes = []; + this.supportedImageModes = []; + this.supportedVideoModes = []; +}; + +/** + * Launch audio recorder application for recording audio clip(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureAudioOptions} options + * + * No audio recorder to launch for iOS - return CAPTURE_NOT_SUPPORTED + */ +Capture.prototype.captureAudio = function(successCallback, errorCallback, options) { + /*if (errorCallback && typeof errorCallback === "function") { + errorCallback({ + "code": CaptureError.CAPTURE_NOT_SUPPORTED + }); + }*/ + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.mediacapture", "captureAudio", [options]); +}; + +/** + * Launch camera application for taking image(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureImageOptions} options + */ +Capture.prototype.captureImage = function(successCallback, errorCallback, options) { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.mediacapture", "captureImage", [options]); +}; + +/** + * Casts a PluginResult message property (array of objects) to an array of MediaFile objects + * (used in Objective-C) + * + * @param {PluginResult} pluginResult + */ +Capture.prototype._castMediaFile = function(pluginResult) { + var mediaFiles = []; + var i; + for (i=0; i} categories +* @param {ContactField[]} urls contact's web sites +*/ +var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, birthday, note, photos, categories, urls) { + this.id = id || null; + this.displayName = displayName || null; + this.name = name || null; // ContactName + this.nickname = nickname || null; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.birthday = birthday || null; // JS Date + this.note = note || null; + this.photos = photos || null; // ContactField[] + this.categories = categories || null; + this.urls = urls || null; // ContactField[] +}; + +/** +* Converts Dates to milliseconds before sending to iOS +*/ +Contact.prototype.convertDatesOut = function() +{ + var dates = new Array("birthday"); + for (var i=0; i][;base64], + * + * @param file {File} File object containing file properties + */ +FileReader.prototype.readAsDataURL = function(file) { + this.fileName = ""; + + if (typeof file.fullPath === "undefined") { + this.fileName = file; + } else { + this.fileName = file.fullPath; + } + + // LOADING state + this.readyState = FileReader.LOADING; + + // If loadstart callback + if (typeof this.onloadstart === "function") { + var evt = File._createEvent("loadstart", this); + this.onloadstart(evt); + } + + var me = this; + + // Read file + navigator.fileMgr.readAsDataURL(this.fileName, + + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save result + me.result = r; + + // If onload callback + if (typeof me.onload === "function") { + evt = File._createEvent("load", me); + me.onload(evt); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + evt = File._createEvent("loadend", me); + me.onloadend(evt); + } + }, + + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + evt = File._createEvent("loadend", me); + me.onloadend(evt); + } + } + ); +}; + +/** + * Read file and return data as a binary data. + * + * @param file The name of the file + */ +FileReader.prototype.readAsBinaryString = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +/** + * Read file and return data as a binary data. + * + * @param file The name of the file + */ +FileReader.prototype.readAsArrayBuffer = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +//----------------------------------------------------------------------------- +// File Writer +//----------------------------------------------------------------------------- + +/** + * This class writes to the mobile device file system. + * + @param file {File} a File object representing a file on the file system +*/ +FileWriter = function(file) { + this.fileName = ""; + this.length = 0; + if (file) { + this.fileName = file.fullPath || file; + this.length = file.size || 0; + } + + // default is to write at the beginning of the file + this.position = 0; + + this.readyState = 0; // EMPTY + + this.result = null; + + // Error + this.error = null; + + // Event handlers + this.onwritestart = null; // When writing starts + this.onprogress = null; // While writing the file, and reporting partial file data + this.onwrite = null; // When the write has successfully completed. + this.onwriteend = null; // When the request has completed (either in success or failure). + this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method. + this.onerror = null; // When the write has failed (see errors). +} + +// States +FileWriter.INIT = 0; +FileWriter.WRITING = 1; +FileWriter.DONE = 2; + +/** + * Abort writing file. + */ +FileWriter.prototype.abort = function() { + // check for invalid state + if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) { + throw FileError.INVALID_STATE_ERR; + } + + // set error + var error = new FileError(), evt; + error.code = error.ABORT_ERR; + this.error = error; + + // If error callback + if (typeof this.onerror === "function") { + evt = File._createEvent("error", this); + this.onerror(evt); + } + // If abort callback + if (typeof this.onabort === "function") { + evt = File._createEvent("abort", this); + this.onabort(evt); + } + + this.readyState = FileWriter.DONE; + + // If write end callback + if (typeof this.onwriteend == "function") { + evt = File._createEvent("writeend", this); + this.onwriteend(evt); + } +}; + +/** + * @Deprecated: use write instead + * + * @param file to write the data to + * @param text to be written + * @param bAppend if true write to end of file, otherwise overwrite the file + */ +FileWriter.prototype.writeAsText = function(file, text, bAppend) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (bAppend !== true) { + bAppend = false; // for null values + } + + this.fileName = file; + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + + // Write file + navigator.fileMgr.writeAsText(file, text, bAppend, + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save result + me.result = r; + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); +}; + +/** + * Writes data to the file + * + * @param text to be written + */ +FileWriter.prototype.write = function(text) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + // Write file + navigator.fileMgr.write(this.fileName, text, this.position, + + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + + // position always increases by bytes written because file would be extended + me.position += r; + // The length of the file is now where we are done writing. + me.length = me.position; + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); + +}; + +/** + * Moves the file pointer to the location specified. + * + * If the offset is a negative number the position of the file + * pointer is rewound. If the offset is greater than the file + * size the position is set to the end of the file. + * + * @param offset is the location to move the file pointer to. + */ +FileWriter.prototype.seek = function(offset) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (!offset) { + return; + } + + // See back from end of file. + if (offset < 0) { + this.position = Math.max(offset + this.length, 0); + } + // Offset is bigger then file size so set position + // to the end of the file. + else if (offset > this.length) { + this.position = this.length; + } + // Offset is between 0 and file size so set the position + // to start writing. + else { + this.position = offset; + } +}; + +/** + * Truncates the file to the size specified. + * + * @param size to chop the file at. + */ +FileWriter.prototype.truncate = function(size) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + // what if no size specified? + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + // Write file + navigator.fileMgr.truncate(this.fileName, size, + + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Update the length of the file + me.length = r; + me.position = Math.min(me.position, r); + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); +}; + +LocalFileSystem = function() { +}; + +// File error codes +LocalFileSystem.TEMPORARY = 0; +LocalFileSystem.PERSISTENT = 1; +LocalFileSystem.RESOURCE = 2; +LocalFileSystem.APPLICATION = 3; + +/** + * Requests a filesystem in which to store application data. + * + * @param {int} type of file system being requested + * @param {Function} successCallback is called with the new FileSystem + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) { + if (type < 0 || type > 3) { + if (typeof errorCallback == "function") { + errorCallback({ + "code": FileError.SYNTAX_ERR + }); + } + } + else { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.file", "requestFileSystem", [type, size]); + } +}; + +/** + * + * @param {DOMString} uri referring to a local file in a filesystem + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.file", "resolveLocalFileSystemURI", [uri]); +}; + +/** +* This function is required as we need to convert raw +* JSON objects into concrete File and Directory objects. +* +* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects. +* @returns an entry +*/ +LocalFileSystem.prototype._castFS = function(pluginResult) { + var entry = null; + entry = new DirectoryEntry(); + entry.isDirectory = pluginResult.message.root.isDirectory; + entry.isFile = pluginResult.message.root.isFile; + entry.name = pluginResult.message.root.name; + entry.fullPath = pluginResult.message.root.fullPath; + pluginResult.message.root = entry; + return pluginResult; +} + +LocalFileSystem.prototype._castEntry = function(pluginResult) { + var entry = null; + if (pluginResult.message.isDirectory) { + entry = new DirectoryEntry(); + } + else if (pluginResult.message.isFile) { + entry = new FileEntry(); + } + entry.isDirectory = pluginResult.message.isDirectory; + entry.isFile = pluginResult.message.isFile; + entry.name = pluginResult.message.name; + entry.fullPath = pluginResult.message.fullPath; + pluginResult.message = entry; + return pluginResult; +} + +LocalFileSystem.prototype._castEntries = function(pluginResult) { + var entries = pluginResult.message; + var retVal = []; + for (i=0; i") +foreach(FILE ${HTML5UIFILES} ${LIBJSFILES} index.html scripts.js webodf.css) + file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/application.qrc + "www/${FILE}\n") +endforeach(FILE ${HTML5UIFILES}) +file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/application.qrc + "") +COPY_FILES(NATIVEDEPS ${CMAKE_SOURCE_DIR}/programs/touchui + ${CMAKE_CURRENT_BINARY_DIR}/www ${HTML5UIFILES}) +COPY_FILES(NATIVEDEPS ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/www scripts.js) +COPY_FILES(NATIVEDEPS ${CMAKE_SOURCE_DIR}/programs/touchui + ${CMAKE_CURRENT_BINARY_DIR}/www index.html) +COPY_FILES(NATIVEDEPS ${CMAKE_SOURCE_DIR}/webodf + ${CMAKE_CURRENT_BINARY_DIR}/www webodf.css) +COPY_FILES(NATIVEDEPS ${CMAKE_SOURCE_DIR}/webodf + ${CMAKE_CURRENT_BINARY_DIR}/www ${LIBJSFILES}) +QT4_ADD_RESOURCES(NATIVEQTCLIENT_RES + ${CMAKE_CURRENT_BINARY_DIR}/application.qrc) + +add_custom_target(nativeQtClientDepencencies ALL DEPENDS ${NATIVEDEPS}) + +add_executable(nativeQtClient + main.cpp + odfview.cpp + ../qtjsruntime/nativeio.cpp + odfpage.cpp ${NATIVEQTCLIENT_MOC} ${NATIVEQTCLIENT_UI} + ${NATIVEQTCLIENT_RES}) + +target_link_libraries(nativeQtClient ${QT_LIBRARIES}) +add_dependencies(nativeQtClient nativeQtClientDepencencies) diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/README b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/README new file mode 100644 index 0000000000..4860fa1b00 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/README @@ -0,0 +1 @@ +This is a small app that can show ODF documents using mainly javascript. Some functions that are not fast in browers are provided in C++ and it gives the ability to open files on the file system. diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/application.qrc b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/application.qrc new file mode 100644 index 0000000000..5010cdb8a8 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/application.qrc @@ -0,0 +1,18 @@ + + + www/app/app.js + www/app/controller/Files.js + www/app/model/FileSystem.js + www/app/store/FileStore.js + www/app/views/FileDetail.js + www/app/views/FilesList.js + www/app/views/OdfView.js + www/app/views/Viewport.js + www/index.html + www/scripts.js + www/sencha-touch.css + www/sencha-touch.js + www/webodf.css + www/webodf.js + + diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/main.cpp b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/main.cpp new file mode 100644 index 0000000000..62e5fa18be --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/main.cpp @@ -0,0 +1,10 @@ +#include "odfview.h" +#include +#include + +int main(int argc, char *argv[]) { + QApplication a(argc, argv); + OdfView view; + view.show(); + return a.exec(); +} diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.cpp b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.cpp new file mode 100644 index 0000000000..861014399e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.cpp @@ -0,0 +1,173 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "odfview.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + createActions(); + createToolBars(); + + QCoreApplication::setOrganizationName("KO"); + //QCoreApplication::setOrganizationDomain("example.com"); + QCoreApplication::setApplicationName("Odf Viewer"); + + QSettings settings; + + setWindowTitle(tr("Odf Viewer")); + setUnifiedTitleAndToolBarOnMac(true); + + QStringList odfNameFilter; + odfNameFilter << "*.odt" << "*.ods" << "*.odp"; + dirmodel = new QFileSystemModel(this); + dirmodel->setNameFilters(odfNameFilter); + dirmodel->setFilter(QDir::AllDirs|QDir::AllEntries|QDir::NoDotAndDotDot); + dirview = new QTreeView(this); + dirview->setModel(dirmodel); + dirview->setHeaderHidden(true); + dirview->setAnimated(true); + for (int i = 1; i < dirmodel->columnCount(); i++) { + dirview->setColumnHidden(i, true); + } + QString rootpath = settings.value("rootpath", QDir::homePath()).toString(); + dirmodel->setRootPath(rootpath); + const QModelIndex rootindex = dirmodel->index(rootpath); + dirview->setRootIndex(rootindex); + QLineEdit *dirPath = new QLineEdit(rootpath, this); + dirdock = new QDockWidget(this); + QWidget *w = new QWidget(dirdock); + QVBoxLayout *layout = new QVBoxLayout(w); + dirdock->setWidget(w); + layout->addWidget(dirPath); + layout->addWidget(dirview); + addDockWidget(Qt::LeftDockWidgetArea, dirdock); + + connect(dirview, SIGNAL(clicked(QModelIndex)), this, SLOT(loadOdf(QModelIndex))); + connect(dirPath, SIGNAL(textChanged(QString)), this, SLOT(setPath(QString))); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void +MainWindow::openFile(const QString& path) +{ + QMdiSubWindow* w = findMdiChild(path); + OdfView* v = (w) ?dynamic_cast(w->widget()) :0; + if (v == 0) { + w = ui->mdiArea->activeSubWindow(); + v = (w) ?dynamic_cast(w->widget()) :0; + } + if (v == 0) { + v = new OdfView(this); + v->showMaximized(); + w = ui->mdiArea->addSubWindow(v); + w->showMaximized(); + } + ui->mdiArea->setActiveSubWindow(w); + v->loadFile(path); +} + +void MainWindow::changeEvent(QEvent *e) +{ + QMainWindow::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} +void MainWindow::open() +{ + QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(), + tr("Office Files (*.odt *.odp *.ods)")); + if (!fileName.isEmpty()) { + QMdiSubWindow *existing = findMdiChild(fileName); + if (existing) { + ui->mdiArea->setActiveSubWindow(existing); + return; + } + + OdfView *child = createOdfView(); + if (child->loadFile(fileName)) { + statusBar()->showMessage(tr("File loaded"), 2000); + child->showMaximized(); + } else { + child->close(); + } + } +} +void MainWindow::createActions() +{ + //openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this); + openAct = new QAction(tr("&Open..."), this); + openAct->setShortcuts(QKeySequence::Open); + openAct->setStatusTip(tr("Open an existing file")); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); +} +void MainWindow::createToolBars() +{ + fileToolBar = addToolBar(tr("File")); + fileToolBar->addAction(openAct); +} +QMdiSubWindow *MainWindow::findMdiChild(const QString &fileName) +{ + QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath(); + + foreach (QMdiSubWindow *window, ui->mdiArea->subWindowList()) { + OdfView *odfView = qobject_cast(window->widget()); + if (odfView->currentFile() == canonicalFilePath) + return window; + } + return 0; +} + +OdfView *MainWindow::createOdfView() +{ + OdfView *view = new OdfView(this); + ui->mdiArea->addSubWindow(view); + return view; +} + +void +MainWindow::loadOdf(const QModelIndex& index) { + if (dirmodel->isDir(index)) { + if (dirview->isExpanded(index)) { + dirview->collapse(index); + } else { + dirview->expand(index); + } + return; + } + QString path = dirmodel->filePath(index); + path = QFileInfo(path).canonicalFilePath(); + openFile(path); +} + +void MainWindow::setPath(const QString &path) +{ + dirmodel->setRootPath(path); + const QModelIndex rootindex = dirmodel->index(path); + dirview->setRootIndex(rootindex); + QSettings settings; + settings.setValue("rootpath", path); +} + + + diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.h b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.h new file mode 100644 index 0000000000..d0bc822d03 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +namespace Ui { + class MainWindow; +} + +class OdfView; +class QFileSystemModel; +class QTreeView; +class QDockWidget; +class QModelIndex; + +class MainWindow : public QMainWindow { + Q_OBJECT +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + void openFile(const QString& path); + +private slots: + void open(); + OdfView *createOdfView(); + void loadOdf(const QModelIndex& index); + void setPath(const QString &path); + +private: + QMdiSubWindow *findMdiChild(const QString &fileName); + void createActions(); + void createToolBars(); + QToolBar *fileToolBar; + QAction *openAct; +protected: + void changeEvent(QEvent *e); + +private: + Ui::MainWindow *ui; + QFileSystemModel* dirmodel; + QTreeView* dirview; + QDockWidget* dirdock; +}; + +#endif // MAINWINDOW_H diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.ui b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.ui new file mode 100644 index 0000000000..38682c7010 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/mainwindow.ui @@ -0,0 +1,46 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + + + + + + 0 + 0 + 800 + 23 + + + + + + TopToolBarArea + + + false + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.cpp b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.cpp new file mode 100644 index 0000000000..d87a8baa2b --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.cpp @@ -0,0 +1 @@ +#include "odfpage.h" diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.h b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.h new file mode 100644 index 0000000000..487d169917 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfpage.h @@ -0,0 +1,15 @@ +#ifndef ODFPAGE_H +#define ODFPAGE_H + +#include +#include + +class OdfPage : public QWebPage { +public: + OdfPage(QObject* parent) :QWebPage(parent) {} + void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString & sourceID) { + qDebug() << sourceID << ":" << lineNumber << ":" << message; + } +}; + +#endif // ODFPAGE_H diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.cpp b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.cpp new file mode 100644 index 0000000000..97125a5537 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.cpp @@ -0,0 +1,83 @@ +#include "odfview.h" + +#include "../qtjsruntime/nativeio.h" +#include "../qtjsruntime/nam.h" + +#include "odfpage.h" + +#include +#include +#include +#include +#include +#include +#include + +OdfView::OdfView(QWidget* parent) :QWebView(parent) +{ + QString prefix = "../android/assets/"; // set this to the right value when debugging + QString htmlfile = QDir(prefix).absoluteFilePath("www/index.html"); + if (!QFileInfo(htmlfile).exists()) { + prefix = "qrc:/"; + htmlfile = "qrc:/www/index.html"; + } + setPage(new OdfPage(this)); + nativeio = new NativeIO(this, QDir(prefix), QDir::current()); + connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool))); + page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); + + connect(page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), + this, SLOT(slotInitWindowObjects())); + + // use our own networkaccessmanager that gives limited access to the local + // file system + networkaccessmanager = new NAM(this); + page()->setNetworkAccessManager(networkaccessmanager); + setUrl(QUrl(htmlfile)); + loaded = false; +} + +OdfView::~OdfView() { +} + +void +OdfView::slotInitWindowObjects() +{ + QWebFrame *frame = page()->mainFrame(); + frame->addToJavaScriptWindowObject("nativeio", nativeio); +} + +bool +OdfView::loadFile(const QString &fileName) { + curFile = fileName; + // odf->addFile(identifier, fileName); + // networkaccessmanager->setCurrentFile(odf->getOpenContainer(identifier)); + if (loaded) { + slotLoadFinished(true); + } + return true; +} +void +OdfView::slotLoadFinished(bool ok) { + if (!ok) return; + loaded = true; + QWebFrame *frame = page()->mainFrame(); + QString js = + "var originalReadFileSync = runtime.readFileSync;" + "runtime.readFileSync = function (path, encoding) {" + " if (path.substr(path.length - 3) === '.js') {" + " return originalReadFileSync.apply(runtime," + " [path, encoding]);" + " }" + " return nativeio.readFileSync(path, encoding);" + "};" + "runtime.read = function (path, offset, length, callback) {" + " var data = nativeio.read(path, offset, length);" + " data = runtime.byteArrayFromString(data, 'binary');" + " callback(nativeio.error()||null, data);" + "};" + "runtime.getFileSize = function (path, callback) {" + " callback(nativeio.getFileSize(path));" + "};"; + frame->evaluateJavaScript(js); +} diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.h b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.h new file mode 100644 index 0000000000..f61ba3c926 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/odfview.h @@ -0,0 +1,29 @@ +#ifndef ODFVIEW_H +#define ODFVIEW_H + +#include +#include +class NativeIO; + +class OdfView : public QWebView { +Q_OBJECT +public: + OdfView(QWidget* parent = 0); + ~OdfView(); + QString currentFile() { return curFile; } + +public slots: + bool loadFile(const QString &fileName); + +private slots: + void slotLoadFinished(bool ok); + void slotInitWindowObjects(); + +private: + bool loaded; + QString curFile; + QNetworkAccessManager* networkaccessmanager; + NativeIO* nativeio; +}; + +#endif // ODFVIEW_H diff --git a/apps/files_odfviewer/src/webodf/programs/nativeQtClient/scripts.js b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/scripts.js new file mode 100644 index 0000000000..ce2086bc7a --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/nativeQtClient/scripts.js @@ -0,0 +1,93 @@ +/*global alert, app, window, runtime*/ +var LocalFileSystem = { + PERSISTENT: 0, + TEMPORARY: 1 +}; +function FileEntry(name, fullPath) { + "use strict"; + this.isFile = true; + this.isDirectory = false; + this.name = name; + this.fullPath = fullPath; + this.file = function (onsuccess, onerror) { + function File(fullPath) { + this.name = name; + this.fullPath = fullPath; + this.type = ""; + this.size = -1; + this.lastModifiedDate = -1; + } + var file = new File(fullPath); + try { + onsuccess(file); + } catch (e) { + alert("Error on determining file properties: " + e); + onerror(e); + } + }; +} +function FileReader() { + "use strict"; + var fr = this; + this.readAsArrayBuffer = function (file) { + var path = file.fullPath.substr(7), + data = runtime.readFileSync(path, 'binary'); + data = runtime.byteArrayFromString(data, "binary"); + window.setTimeout(function () { + fr.onloadend({target: {result: data}}); + }, 1); + }; +} +var DirectoryReader; +function DirectoryEntry(name, fullPath) { + "use strict"; + this.isFile = false; + this.isDirectory = true; + this.name = name; + this.fullPath = fullPath; + this.createReader = function () { + var reader = new DirectoryReader(fullPath); + return reader; + }; +} +function DirectoryReader(fullPath) { + "use strict"; + this.readEntries = function (onsuccess, onerror) { + window.setTimeout(function () { + var entries = []; + entries[entries.length] = new FileEntry("welcome.odt", + "welcome.odt"); + entries[entries.length] = new FileEntry("Traktatenblad.odt", + "Traktatenblad.odt"); + try { + onsuccess(entries); + } catch (e) { + onerror(e); + } + }, 1); + }; +} +window.resolveLocalFileSystemURI = function (path, onsuccess, onerror) { + "use strict"; + var p = path.lastIndexOf("/"), + name = (p === -1) ? path : path.substr(p + 1); + onsuccess(new FileEntry(name, path)); +}; +window.requestFileSystem = function (filesystem, id, onsuccess, onerror) { + "use strict"; + var dirs = [], shared, subfolder, path; + try { + if (filesystem === LocalFileSystem.PERSISTENT) { + path = ""; + onsuccess({ + name: "root", + root: new DirectoryEntry("root", path) + }); + } else { + onerror("not defined"); + } + } catch (e) { + onerror(e); + } +}; +var device = {}; diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/playbook/CMakeLists.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/build_sign.bat b/apps/files_odfviewer/src/webodf/programs/playbook/build_sign.bat new file mode 100644 index 0000000000..34e8deeab3 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/build_sign.bat @@ -0,0 +1,23 @@ +@echo on +set WWSDK=M:\blackberrysdk\webworkssdk +set BBWP=%WWSDK%\bbwp\bbwp +set DEPLOY=%WWSDK%\bbwp\blackberry-tablet-sdk\bin\blackberry-deploy +set JAVA_HOME=%WWSDK%\jre +set PATH=%PATH%;%JAVA_HOME%\bin + +mkdir bin +mkdir signed + +zip -r webodf.zip config.xml index.html icon.png scripts.js app sencha-touch.js sencha-touch.css webodf.js webodf.css ZoomIn.png ZoomOut.png + +rem MAKE A DEBUG VERSION +del bin\webodf.bar +%BBWP% webodf.zip -d -o bin +if %errorlevel% neq 0 exit /b %errorlevel% + +%DEPLOY% -installApp -password ko -device 192.168.1.111 -package bin\webodf.bar +if %errorlevel% neq 0 exit /b %errorlevel% + +rem MAKE A SIGNED VERSION, (can be done only once for each buildId!) +rem %BBWP% webodf.zip -g U9gXpJXbGC -buildId 2 -o signed + diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/config.xml b/apps/files_odfviewer/src/webodf/programs/playbook/config.xml new file mode 100644 index 0000000000..cab7788317 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/config.xml @@ -0,0 +1,26 @@ + + + KO GmbH + WebODF + + Viewer for OpenDocument files. + + + + + + + + + access_shared + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_dispatcher.js b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_dispatcher.js new file mode 100644 index 0000000000..8c4d91c46e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_dispatcher.js @@ -0,0 +1,17 @@ +(function () { + var CUSTOM_FILEREADER_API_URL = "blackberry/custom/filereader"; + + var ARGS_PATH = "path"; + var ARGS_DATA = "data"; + + function CustomFileReader() { + }; + + CustomFileReader.prototype.readAsDataURL = function(path) { + var remoteCall = new blackberry.transport.RemoteFunctionCall(CUSTOM_FILEREADER_API_URL + "/readAsDataURL"); + remoteCall.addParam(ARGS_PATH, path); + return remoteCall.makeSyncCall(); + }; + + blackberry.Loader.javascriptLoaded("blackberry.custom.filereader", CustomFileReader); +})(); diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_ns.js b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_ns.js new file mode 100644 index 0000000000..2ae1ede11e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/js/common/custom_filereader_ns.js @@ -0,0 +1,8 @@ +(function () { + + function CustomFileReader(disp) { + this.constructor.prototype.readAsDataURL = function(path) { return disp.readAsDataURL(path); }; + }; + + blackberry.Loader.javascriptLoaded("blackberry.custom.filereader", CustomFileReader); +})(); diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/library.xml b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/library.xml new file mode 100644 index 0000000000..1f3aa52d36 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/library.xml @@ -0,0 +1,22 @@ + + + + blackberry.custom.filereader.CustomFileReader + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/src/AIR/CustomFileReader/src/blackberry/custom/filereader/CustomFileReader.as b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/src/AIR/CustomFileReader/src/blackberry/custom/filereader/CustomFileReader.as new file mode 100644 index 0000000000..3261fbcf45 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/ext/blackberry.custom.filereader/src/AIR/CustomFileReader/src/blackberry/custom/filereader/CustomFileReader.as @@ -0,0 +1,34 @@ +package blackberry.custom.filereader { + import flash.filesystem.File; + import flash.filesystem.FileMode; + import flash.filesystem.FileStream; + import flash.utils.ByteArray; + import mx.utils.Base64Encoder; + import webworks.extension.DefaultExtension; + + public class CustomFileReader extends DefaultExtension { + + public function CustomFileReader() { + super(); + } + + override public function getFeatureList():Array { + return new Array ("blackberry.custom.filereader"); + } + + public function readAsDataURL(path:String):String { + var file:File = new File(path); + if (!file.exists) { + return ""; + } + var bytes:ByteArray = new ByteArray(); + var stream:FileStream = new FileStream(); + stream.open(file, FileMode.READ); + stream.readBytes(bytes); + var btoa:Base64Encoder = new Base64Encoder(); + btoa.encodeBytes(bytes); + stream.close(); + return "data:;base64," + btoa.toString(); + } + } +} \ No newline at end of file diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/icon.png b/apps/files_odfviewer/src/webodf/programs/playbook/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b7ccb848e3949b55361f2fb30dfe3a39756aa387 GIT binary patch literal 19269 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 literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/index.html b/apps/files_odfviewer/src/webodf/programs/playbook/index.html new file mode 100644 index 0000000000..77d331c12e --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/index.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + WebODF + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/playbook/scripts.js b/apps/files_odfviewer/src/webodf/programs/playbook/scripts.js new file mode 100644 index 0000000000..e7913527d6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/playbook/scripts.js @@ -0,0 +1,146 @@ +/*global blackberry, alert, document, window, app*/ +var LocalFileSystem = { + PERSISTENT: 0, + TEMPORARY: 1 +}; +function FileWriter(fullPath) { + "use strict"; + this.write = function (data) { + var blob; + try { + blob = blackberry.utils.stringToBlob(data, "UTF-8"); + blackberry.io.file.saveFile(fullPath, blob); + } catch (e) { + } + }; +} +function FileEntry(name, fullPath) { + "use strict"; + this.isFile = true; + this.isDirectory = false; + this.name = name; + this.fullPath = fullPath; + this.file = function (onsuccess, onerror) { + function File(fullPath) { + this.name = name; + this.fullPath = fullPath; + this.type = ""; + this.size = -1; + this.lastModifiedDate = -1; + } + var file = new File(fullPath), + properties; + try { + properties = blackberry.io.file.getFileProperties(fullPath); + file.type = properties.mimeType; + file.size = properties.size; + file.lastModifiedDate = properties.dateModified; + onsuccess(file); + } catch (e) { + alert("Error on determining file properties: " + e); + onerror(e); + } + }; + this.createWriter = function (onsuccess, onerror) { + onsuccess(new FileWriter(fullPath)); + }; +} +function FileReader() { + "use strict"; + var fr = this; + this.readAsDataURL = function (file) { + var path = file.fullPath.substr(7); + window.setTimeout(function () { + try { + var data = blackberry.custom.filereader.readAsDataURL(path); + fr.onloadend({target: {result: data}}); + } catch (e) { + alert("Error on reading file: " + e + " " + file.fullPath); + } + }, 1); + }; + this.readAsText = function (file) { + var path = file.fullPath.substr(7); + try { + blackberry.io.file.readFile(path, function (fullPath, blob) { + var str = blackberry.utils.blobToString(blob, "UTF-8"); + fr.onloadend({target: {result: str}}); + }, true); + } catch (e) { + fr.onloadend({target: {result: "[]"}}); + } + }; +} +var DirectoryReader; +function DirectoryEntry(name, fullPath) { + "use strict"; + this.isFile = false; + this.isDirectory = true; + this.name = name; + this.fullPath = fullPath; + this.createReader = function () { + var reader = new DirectoryReader(fullPath); + return reader; + }; +} +function DirectoryReader(fullPath) { + "use strict"; + this.readEntries = function (onsuccess, onerror) { + window.setTimeout(function () { + var entries = [], + dirs = blackberry.io.dir.listDirectories(fullPath), + files = blackberry.io.dir.listFiles(fullPath), + i; + try { + for (i = 0; i < dirs.length; i += 1) { + entries[entries.length] = new DirectoryEntry(dirs[i], + fullPath + "/" + dirs[i]); + } + for (i = 0; i < files.length; i += 1) { + entries[entries.length] = new FileEntry(files[i], + fullPath + "/" + files[i]); + } + onsuccess(entries); + } catch (e) { + onerror(e); + } + }, 1); + }; +} +window.resolveLocalFileSystemURI = function (path, onsuccess, onerror) { + "use strict"; + var p = path.lastIndexOf("/"), + name; + if (p === -1) { + name = path; + path = blackberry.io.dir.appDirs.shared.documents.path + "/" + path; + } else { + name = path.substr(p + 1); + } + onsuccess(new FileEntry(name, path)); +}; +window.requestFileSystem = function (filesystem, id, onsuccess, onerror) { + "use strict"; + var dirs = [], shared, subfolder; + try { + if (filesystem === LocalFileSystem.PERSISTENT) { + shared = blackberry.io.dir.appDirs.shared; + for (subfolder in shared) { + if (shared.hasOwnProperty(subfolder)) { + dirs[dirs.length] = subfolder; + } + } + onsuccess({ + name: "root", + root: new DirectoryEntry("root", shared.documents.path + //+ "/kofficetests/odf/odt" + ) + }); + } else { + onerror("not defined"); + } + } catch (e) { + onerror(e); + } +}; +var device = {}; diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/CMakeLists.txt new file mode 100644 index 0000000000..ec8026741c --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/CMakeLists.txt @@ -0,0 +1,4 @@ +include(${QT_USE_FILE}) +QT4_WRAP_CPP(QTJSRUNTIME_MOC nam.h pagerunner.h nativeio.h) +add_executable(qtjsruntime qtjsruntime.cpp pagerunner.cpp nativeio.cpp ${QTJSRUNTIME_MOC}) +target_link_libraries(qtjsruntime ${QT_LIBRARIES}) diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nam.h b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nam.h new file mode 100644 index 0000000000..ebb62f261a --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nam.h @@ -0,0 +1,48 @@ +#ifndef NAM_H +#define NAM_H + +#include +#include + +class NAM : public QNetworkAccessManager { +Q_OBJECT +private: + const QString host; + const int port; + int outstandingRequests; +public: + NAM(QObject* parent, const QString& host_ = QString(), int port_ = -1) + :QNetworkAccessManager(parent), host(host_), port(port_) { + outstandingRequests = 0; + connect(this, SIGNAL(finished(QNetworkReply*)), + this, SLOT(requestFinished())); + } + QNetworkReply* createRequest(QNetworkAccessManager::Operation o, + QNetworkRequest const& r, QIODevice* d) { + outstandingRequests += 1; + bool samehost = false; + if (port > 0) { + samehost = r.url().host() == host + || r.url().host().endsWith("." + host) + || host.endsWith("." + r.url().host()); + samehost &= r.url().port() != port; + } else { + // use host string as a prefix + samehost = r.url().toString().startsWith(host); + } + if (!samehost) { + // if not same host or domain and port, block + return QNetworkAccessManager::createRequest(o, QNetworkRequest(), + d); + } + return QNetworkAccessManager::createRequest(o, r, d); + } + bool hasOutstandingRequests() { + return outstandingRequests > 0; + } +public slots: + void requestFinished() { + outstandingRequests -= 1; + } +}; +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.cpp b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.cpp new file mode 100644 index 0000000000..0657a0c711 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.cpp @@ -0,0 +1,106 @@ +#include "nativeio.h" +#include +#include +#include + +NativeIO::NativeIO(QObject* parent, const QDir& runtimedir_, + const QDir& cwd_, + const QMap& pathPermissions_) + :QObject(parent), runtimedir(runtimedir_), cwd(cwd_), + pathPermissions(pathPermissions_) { +} +QString +NativeIO::readFileSync(const QString& path, const QString& encoding) { + errstr = QString(); + QFile file(cwd.absoluteFilePath(path)); + QByteArray data; + if (file.open(QIODevice::ReadOnly)) { + data = file.readAll(); + } + QString out; + if (encoding != "binary") { + QTextCodec *codec = QTextCodec::codecForName(encoding.toAscii()); + if (codec) { + out = codec->toUnicode(data); + } + } + if (out.length() == 0 && data.length() > 0) { + out = QString(data.length(), 0); + for (int i = 0; i < data.length(); ++i) { + out[i] = data[i]; + } + } + return out; +} +QString +NativeIO::read(const QString& path, int offset, int length) { + errstr = QString(); + QFile file(cwd.absoluteFilePath(path)); + QByteArray data; + if (file.open(QIODevice::ReadOnly) && (offset == 0 || file.seek(offset))) { + int lastLength = 0; + do { + lastLength = data.length(); + data += file.read(length - data.length()); + } while (data.length() < length && data.length() != lastLength); + } + if (length != data.length()) { + errstr = "Not enough data: " + QString::number(length) + + " instead of " + QString::number(data.length()); + return QString(); + } + QString out(length, 0); + for (int i = 0; i < length; ++i) { + out[i] = data[i]; + } + return out; +} +void +NativeIO::writeFile(const QString& path, const QString& data) { + QFile file(cwd.absoluteFilePath(path)); + errstr = QString(); + if (!file.open(QIODevice::WriteOnly)) { + errstr = "Could not open file for writing."; + return; + } + int length = data.length(); + QByteArray out(length, 0); + for (int i = 0; i < length; ++i) { + out[i] = data[i].unicode(); + } + if (file.write(out) != out.length()) { + errstr = "Could not write to file."; + } + return; +} +void +NativeIO::unlink(const QString& path) { + errstr = QString(); + QFile file(cwd.absoluteFilePath(path)); + if (!file.remove()) { + errstr = "Could not delete file"; + } +} +int +NativeIO::getFileSize(const QString& path) { + errstr = QString(); + QFile file(cwd.absoluteFilePath(path)); + if (!file.exists()) { + errstr = "Could not determine file size."; + } + return file.size(); +} +void +NativeIO::exit(int exitcode) { + qApp->exit(exitcode); +} +QString +NativeIO::currentDirectory() const { + return QDir::currentPath(); +} +QStringList +NativeIO::libraryPaths() const { + QStringList paths; + paths << runtimedir.absolutePath() << cwd.absolutePath(); + return paths; +} diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.h b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.h new file mode 100644 index 0000000000..b699744226 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/nativeio.h @@ -0,0 +1,41 @@ +#ifndef NATIVEIO_H +#define NATIVEIO_H + +#include +#include +#include + +class QWebPage; + +// class that exposes filesystem to web environment +class NativeIO : public QObject { +Q_OBJECT +private: + QWebPage* webpage; + QString errstr; + const QDir runtimedir; + const QDir cwd; + const QMap pathPermissions; +public: + typedef QMap PathMap; + PathMap v; + NativeIO(QObject* parent, const QDir& runtimedir, const QDir& cwd, + const PathMap& pathPermissions = PathMap()); +public slots: + /** + * Return the last error. + */ + QString error() { + return errstr; + } + QString readFileSync(const QString& path, const QString& encoding); + QString read(const QString& path, int offset, int length); + void writeFile(const QString& path, const QString& data); + void unlink(const QString& path); + int getFileSize(const QString& path); + void exit(int exitcode); + QString currentDirectory() const; + QStringList libraryPaths() const; +}; + +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.cpp b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.cpp new file mode 100644 index 0000000000..a91794d9a2 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.cpp @@ -0,0 +1,191 @@ +#include "pagerunner.h" + +#include "nam.h" +#include "nativeio.h" +#include +#include +#include +#include +#include +#include +#include +#include + +QByteArray getRuntimeBindings() { + return + "if (typeof(runtime) !== 'undefined') {" + " runtime.readFileSync = function (path, encoding) {" + " return nativeio.readFileSync(path, encoding);" + " };" + " runtime.read = function (path, offset, length, callback) {" + " var data = nativeio.read(path, offset, length);" + " data = runtime.byteArrayFromString(data, 'binary');" + " callback(nativeio.error()||null, data);" + " };" + " runtime.writeFile = function (path, data, callback) {" + " data = runtime.byteArrayToString(data, 'binary');" + " nativeio.writeFile(path, data);" + " callback(nativeio.error()||null);" + " };" + " runtime.deleteFile = function (path, callback) {" + " nativeio.unlink(path);" + " callback(nativeio.error()||null);" + " };" + " runtime.getFileSize = function (path, callback) {" + " callback(nativeio.getFileSize(path));" + " };" + " runtime.exit = function (exitCode) {" + " nativeio.exit(exitCode);" + " };" + " runtime.currentDirectory = function () {" + " return nativeio.currentDirectory();" + " };" + "}"; +} + +PageRunner::PageRunner(const QStringList& args) + : QWebPage(0), + out(stdout), + err(stderr), + view(new QWidget()) { + + QMap settings = parseArguments(args); + QStringList arguments = args.mid(settings.size() * 2); + exportpdf = settings.value("export-pdf"); + exportpng = settings.value("export-png"); + url = QUrl(arguments[0]); + nativeio = new NativeIO(this, QFileInfo(arguments[0]).dir(), + QDir::current()); + if (url.scheme() == "file" || url.isRelative()) { + QFileInfo info(url.toLocalFile()); + if (!info.isReadable() || !info.isFile()) { + QTextStream err(stderr); + err << "Cannot read file '" + url.toString() + "'.\n"; + qApp->exit(1); + } + } + nam = new NAM(this, QUrl(url).host(), QUrl(url).port()); + + setNetworkAccessManager(nam); + connect(this, SIGNAL(loadFinished(bool)), this, SLOT(finished(bool))); + connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), + this, SLOT(slotInitWindowObjects())); + sawJSError = false; + + setView(view); + scriptMode = arguments[0].endsWith(".js"); + if (scriptMode) { + QByteArray html = "'" + arguments[0].toUtf8().replace('\'', "\\'") + + "'"; + for (int i = 1; i < arguments.length(); ++i) { + html += ",'" + arguments[i].toUtf8().replace('\'', "\\'") + "'"; + } + html = "" + "" + "" + ""; + if (arguments[0].endsWith("runtime.js")) { + // add runtime modification + html += ""; + } + html += "\n"; + QTemporaryFile tmp("XXXXXX.html"); + tmp.setAutoRemove(true); + tmp.open(); + tmp.write(html); + tmp.close(); + mainFrame()->load(tmp.fileName()); + } else { + // Make the url absolute. If it is not done here, QWebFrame will do + // it, and it will lose the query and fragment part. + QUrl absurl; + if (url.isRelative()) { + absurl = QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath()); + absurl.setQueryItems(url.queryItems()); + absurl.setFragment(url.fragment()); + } else { + absurl = url; + } + mainFrame()->load(absurl); + } +} +PageRunner::~PageRunner() { + delete view; +} +void PageRunner::finished(bool ok) { + // bind nativeio + if (!ok) { + qApp->exit(1); + } + if (!scriptMode) { + mainFrame()->evaluateJavaScript(getRuntimeBindings()); + } + + // connect signals + connect(this, SIGNAL(contentsChanged()), this, SLOT(noteChange())); + connect(this, SIGNAL(downloadRequested(QNetworkRequest)), + this, SLOT(noteChange())); + connect(this, SIGNAL(repaintRequested(QRect)), + this, SLOT(noteChange())); + connect(mainFrame(), SIGNAL(pageChanged()), this, SLOT(noteChange())); + connect(this, SIGNAL(geometryChangeRequested(QRect)), + this, SLOT(noteChange())); + QTimer::singleShot(150, this, SLOT(reallyFinished())); + changed = false; + time.start(); +} +void PageRunner::reallyFinished() { + int latency = time.restart(); + // err << latency << " " << changed << " " << nam->hasOutstandingRequests() << endl; + if (changed || latency >= 152 || nam->hasOutstandingRequests()) { + QTimer::singleShot(150, this, SLOT(reallyFinished())); + changed = false; + return; + } + if (!exportpdf.isEmpty() || !exportpng.isEmpty()) { + setViewportSize(mainFrame()->contentsSize()); + } + if (!exportpng.isEmpty()) { + renderToFile(exportpng); + } + if (!exportpdf.isEmpty()) { + printToFile(exportpdf); + } + qApp->exit(sawJSError); +} +QMap PageRunner::parseArguments(const QStringList& args) { + int i = 0; + QMap settings; + while (i + 2 < args.length()) { + if (args[i].startsWith("--")) { + settings[args[i].mid(2)] = args[i+1]; + } + i += 2; + } + return settings; +} +void PageRunner::slotInitWindowObjects() { + mainFrame()->addToJavaScriptWindowObject("nativeio", nativeio); +} +void PageRunner::renderToFile(const QString& filename) { + QImage pixmap(mainFrame()->contentsSize().boundedTo(QSize(10000,10000)), + QImage::Format_ARGB32_Premultiplied); + QPainter painter(&pixmap); + mainFrame()->render(&painter, QWebFrame::ContentsLayer); + painter.end(); + pixmap.save(filename); +} +void PageRunner::printToFile(const QString& filename) { + QPrinter printer(QPrinter::HighResolution); + printer.setFontEmbeddingEnabled(true); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(filename); + mainFrame()->print(&printer); +} diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.h b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.h new file mode 100644 index 0000000000..9c848acc10 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/pagerunner.h @@ -0,0 +1,68 @@ +#ifndef PAGERUNNER_H +#define PAGERUNNER_H + +#include +#include +#include + +class NAM; +class NativeIO; + +class PageRunner : public QWebPage { +Q_OBJECT +private: + QUrl url; + NAM* nam; + QTextStream out; + QTextStream err; + bool changed; + QWidget* const view; + QTime time; + bool scriptMode; + NativeIO* nativeio; + QString exportpdf; + QString exportpng; + bool sawJSError; +public: + PageRunner(const QStringList& args); + ~PageRunner(); +private slots: + void finished(bool ok); + void noteChange() { + changed = true; + } + void reallyFinished(); + void slotInitWindowObjects(); + bool shouldInterruptJavaScript() { + changed = true; + return false; + } +private: + void javaScriptConsoleMessage(const QString& message, int lineNumber, + const QString& sourceID) { + changed = true; + if (scriptMode) { + err << message << endl; + } else { + err << sourceID << ":" << lineNumber << " " << message << endl; + } + sawJSError = true; + } + void javaScriptAlert(QWebFrame* /*frame*/, const QString& msg) { + changed = true; + err << "ALERT: " << msg << endl; + } + bool javaScriptPrompt(QWebFrame*, const QString&, const QString&, QString*){ + changed = true; + return false; + } + void renderToFile(const QString& filename); + void printToFile(const QString& filename); + // overload because default impl was causing a crash + QString userAgentForUrl(const QUrl&) const { + return QString(); + } + QMap parseArguments(const QStringList& args); +}; + +#endif diff --git a/apps/files_odfviewer/src/webodf/programs/qtjsruntime/qtjsruntime.cpp b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/qtjsruntime.cpp new file mode 100644 index 0000000000..35d04da146 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/qtjsruntime/qtjsruntime.cpp @@ -0,0 +1,20 @@ +/** + * Small executable that loads a javascript or html page from local a URI. + * If the URI ends in .js it will be run in QtScript engine, otherwise, it will + * be assumed to be a webpage that will be opened in + */ +#include "pagerunner.h" +#include +int +main(int argc, char** argv) { + if (argc < 2) { + QTextStream err(stderr); + err << "Usage: " << argv[0] << " [--export-pdf pdffile] " + "[--export-png pngfile] html/javascripfile [arguments]\n"; + return 1; + } + QApplication app(argc, argv); + app.setApplicationName(argv[0]); + PageRunner p(QCoreApplication::arguments().mid(1)); + return app.exec(); +} diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/CMakeLists.txt b/apps/files_odfviewer/src/webodf/programs/touchui/CMakeLists.txt new file mode 100644 index 0000000000..0a18076273 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/CMakeLists.txt @@ -0,0 +1,7 @@ +COPY_FILES(TOUCHUIDEPS ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} ${HTML5UIFILES}) +COPY_FILES(TOUCHUIDEPS ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} index.html scripts.js welcome.odt) +COPY_FILES(TOUCHUIDEPS ${CMAKE_SOURCE_DIR}/webodf + ${CMAKE_CURRENT_BINARY_DIR} webodf.css ${LIBJSFILES}) +add_custom_target(touchuiDepencencies ALL DEPENDS ${TOUCHUIDEPS}) diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/ZoomIn.png b/apps/files_odfviewer/src/webodf/programs/touchui/ZoomIn.png new file mode 100644 index 0000000000000000000000000000000000000000..6041c6ff937666e4266abf66970328fdbc080e20 GIT binary patch literal 670 zcmV;P0%84$P)f(71&&Iji~^qf^{lzW|Kj(oSogZJs2YSNh1S`&0}`neAekz zK%VCwTzs%Qyt=p)gJoce<2Z-jwE;wjU`w!5ZU+Ij1{+wFsk@G7Wh5BIn19i=(3uT3isA3K@PUDSRe{8RAukISBQQTW~tDMPL()U0NGF?s1adYJTXk z;d{5xos`{N%dP1v*ANhK4W@>{ zSg`3u)B6^W14fo-B!X)SvKedx3som5q7===Qtn%JZW-q1Bj>C*%P$YXI^bUD>_fCg zd}whTU_yir@LD5Y5a_z1=eOmI!%5t!n$J;iAtBHoky4|Y<^+phoGt0)GNIBD?}&HA zJK`Pjj<^l+n>=B{avlZnvx<9`Z2$lO07*qoM6N<$ Ef*6}H!TQ~YUOeb*9)qSL??OftZ04Yy8MKaOlalUtVwwSbl zQYwVU0_+i=GyG`}b^*(U5QoXN0Yn3^1guarNU#)ael5ZYlIRLeJ{XE@2zFFF(0@7_ zg0NKlSaWd{2BGaM0yE))@8p#=EzB67F1&(J-?;_n5?cngBd zM#^0KjnVdTD7kalB1*RMH?=g9yuNUFdZxDGOZ0g@{pnyrd;`JK(0pcHN&jz?LVOvP z_e7uiy%)oJN$8j)JWTEoQ(F$|Ev+rT5q*}H^%zAlj*orJzK$8)e5v}NRX^@_tuT(qs{D7e@n&|i@nCd8&2EPingq?dkDWh6clABm5|N8%%K3h|q~ tVZwGEV|%|Z)FOV{>0uyVR0;nGFaU{VsG5a2Ob!45002ovPDHLkV1ih@3se9A literal 0 HcmV?d00001 diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/app.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/app.js new file mode 100644 index 0000000000..60da480a5f --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/app.js @@ -0,0 +1,40 @@ +/*global Ext, invokeString, document*/ +/** + * When the application has been initialized, this function is called, if + * it has been set. By default, it will start scanning the files in the + * files sytem. It can be overridden by e.g. PhoneGap to wait until the device + * is ready. + */ +var onApplicationLaunch = function (app) { + "use strict"; + app.startScanningDirectories(); +}; +Ext.application({ + name : 'WebODFApp', + models: ['FileSystem'], + views: ['Viewport', 'FilesList', 'FileDetail', 'OdfView'], + controllers: ['Files'], + stores: ['FileStore'], + launch: function () { + 'use strict'; + var app = this; + Ext.create('WebODFApp.view.Viewport'); + app.openUrl = function (url) { + var proxy = Ext.getStore("FileStore").getProxy(); + proxy.getRecord(url, function (record) { + var controller; + if (!record) { + alert("Cannot open " + url); + } else { + controller = app.getController('Files'); + controller.show(null, null, null, record); + } + }); + }; + this.startScanningDirectories = function () { + var proxy = Ext.getStore("FileStore").getProxy(); + proxy.startScanningDirectories(); + }; + onApplicationLaunch(this); + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/controller/Files.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/controller/Files.js new file mode 100644 index 0000000000..22e06f85b6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/controller/Files.js @@ -0,0 +1,82 @@ +/*global Ext, runtime*/ +Ext.define('WebODFApp.controller.Files', { + extend: 'Ext.app.Controller', + + config: { + refs: { + mainView: 'mainview', + filesList: 'fileslist list', + fileDetail: 'filedetail', + openButton: '#openButton', + odfView: 'odfview', + title: 'titlebar' + }, + control: { + mainView: { + pop: 'pop', + push: 'push', + back: 'back' + }, + filesList: { + itemtap: 'show' + }, + openButton: { + tap: 'open' + } + } + }, + back: function () { + "use strict"; + this.odfView.hideCanvas(); + }, + push: function (view, item) { + "use strict"; + if (item.xtype === "filedetail") { + this.getOpenButton().show(); + } else { + this.getOpenButton().hide(); + } + }, + pop: function (view, item) { + "use strict"; + if (item.xtype === "odfview") { // going to filedetail + this.getOpenButton().show(); + } else { + this.getOpenButton().hide(); + } + this.getFilesList().deselectAll(); + }, + show: function (list, index, target, record, e) { + "use strict"; + // set the record in the details view and the file view + // this way, document starts loading in the background + var c = this; + if (!this.fileDetail) { + this.fileDetail = Ext.create('WebODFApp.view.FileDetail'); + } + if (!this.odfView) { + this.odfView = Ext.create('WebODFApp.view.OdfView'); + this.odfView.addCanvasListener(this.fileDetail.canvasListener); + } + this.odfView.hideCanvas(); + this.fileDetail.odfView = this.odfView; + this.fileDetail.setRecord(record); + this.getMainView().push(this.fileDetail); + runtime.setTimeout(function () { + c.odfView.setRecord(record); + }, 300); + }, + open: function (options) { + "use strict"; + var c = this; + if (!this.odfView) { + this.odfView = Ext.create('WebODFApp.view.OdfView'); + } + this.odfView.hideCanvas(); + this.odfView.setRecord(this.fileDetail.getRecord()); + this.getMainView().push(this.odfView); + runtime.setTimeout(function () { + c.odfView.showCanvas(); + }, 300); + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/model/FileSystem.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/model/FileSystem.js new file mode 100644 index 0000000000..3346008f1a --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/model/FileSystem.js @@ -0,0 +1,265 @@ +/*global Ext, console, app, window, LocalFileSystem, JSON, FileReader, runtime*/ +Ext.define("WebODFApp.model.FileSystemProxy", (function () { + "use strict"; + var self = this, + scanner; + function Scanner(proxy) { + var todo = [], + done = false, + fileSystems, + files, + cachedList = [], + dirs = {}, + lastUpdate = 0, + lastUpdateTime = new Date(); + + function getFileId(fullPath) { + var i; + if (!files) { + return -1; + } + for (i = 0; i < files.length; i += 1) { + if (files[i].get('fullPath') === fullPath) { + return i; + } + } + return -1; + } + this.getFileId = getFileId; + function addFileEntry(entry, callback) { + function fail() { + callback(-1); + } + var id = getFileId(entry.fullPath); + if (id !== -1) { + return callback(id); + } + entry.file(function (file) { + var id = files.length; + files.push(Ext.create('WebODFApp.model.FileSystem', { + id: id, + fileName: entry.name, + fullPath: entry.fullPath, + size: file.size + })); + callback(id); + }, fail); + } + function parseCachedFileList(pos, callback) { + if (pos === cachedList.length) { + return callback(); + } + window.resolveLocalFileSystemURI(cachedList[pos], function (entry) { + addFileEntry(entry, function () { + parseCachedFileList(pos + 1, callback); + }); + }, function () { + parseCachedFileList(pos + 1, callback); + }); + } + function readCachedFileList(callback) { + window.resolveLocalFileSystemURI("cachedODFList.json", + function (fileentry) { + var reader = new FileReader(); + reader.onloadend = function (evt) { + cachedList = []; + try { + cachedList = JSON.parse(evt.target.result); + } catch (e) { + alert(e); + } + parseCachedFileList(0, callback); + }; + reader.readAsText(fileentry); + }, function () { + callback(); + }); + } + function writeCachedFileList() { + var i, + l = files.length; + cachedList.length = files.length; + for (i = 0; i < l; i += 1) { + cachedList[i] = files[i].get('fullPath'); + } + window.resolveLocalFileSystemURI("cachedODFList.json", + function (fileentry) { + fileentry.createWriter(function (writer) { + writer.write(JSON.stringify(cachedList)); + }, function (e) { + runtime.log(JSON.stringify(e)); + }); + }, function (e) { + runtime.log(JSON.stringify(e)); + }); + } + function filter(name) { + var suffix = name.substr(name.length - 4); + return suffix === ".odt" || suffix === ".odp" || suffix === ".ods"; + } + function errorCallback(err) { + console.log("FILE READ ERROR " + err + " " + todo.length); + done = true; + } + function load(entry, callback) { + function fail() { + callback(-1); + } + if (entry.isDirectory) { + entry.createReader().readEntries(function (entries) { + var i = 0; + for (i = 0; i < entries.length; i += 1) { + entry = entries[i]; + if (entry.isDirectory + && !dirs.hasOwnProperty(entry.fullPath)) { + todo.push(entry); + dirs[entry.fullPath] = entry; + } else if (filter(entry.name)) { + todo.push(entry); + } + } + callback(-1); + }, fail); + } else if (entry.isFile) { + addFileEntry(entry, callback); + } else { + fail(); + } + } + function addFileSystem(fileSystem) { + var dir = fileSystems[fileSystem.name] = {}; + todo.push(fileSystem.root); + function callback() { + var now = new Date(), + // a limit is needed, otherwise the # of files too large to + // be handled by sencha touch + done = todo.length === 0 || files.length > 2000, + store = Ext.getStore('FileStore'); + if (done || lastUpdate === 0 || (files.length - lastUpdate > 0 + && now - lastUpdateTime > files.length * 100)) { + store.load(); + lastUpdate = files.length; + lastUpdateTime = now; + } + if (done) { + writeCachedFileList(); + } else { + load(todo.shift(), callback); + } + } + load(todo.shift(), callback); + } + function addFileSystems() { + window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, + addFileSystem, errorCallback); + window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, + addFileSystem, function () {}); + } + this.scan = function () { + if (fileSystems !== undefined) { + return; + } + fileSystems = {}; + readCachedFileList(function () { + addFileSystems(); + }); + }; + this.load = load; + this.files = files = []; + } + function finishOperation(proxy, operation, callback, scope) { + if (operation) { + var i = 0, + recs = operation.getRecords(), + len = recs.length; + + for (i; i < len; i += 1) { + recs[i].commit(); + } + operation.setSuccessful(); + + Ext.callback(callback, scope || proxy, [operation]); + } + } + return { + extend: "Ext.data.proxy.Proxy", + xtype: 'filesystemproxy', + constructor: function (config) { + this.initConfig(config); + scanner = new Scanner(this); + this.startScanningDirectories = function () { + scanner.scan(); + }; + this.getRecord = function (url, callback) { + var id = scanner.getFileId(url); + if (id !== -1) { + return callback(scanner.files[id]); + } + window.resolveLocalFileSystemURI(url, + function (fileentry) { + scanner.load(fileentry, function (id) { + Ext.getStore('FileStore').load(); + callback(scanner.files[id]); + }); + }, + function (evt) { + callback(null); + }); + }; + }, + + create: function (operation, callback, scope) { + finishOperation(this, operation, callback, scope); + }, + + read: function (operation, callback, scope) { + var me = this, + records = scanner.files; + if (!records) { + return; + } + // return model instances in a resultset + operation.setResultSet(new Ext.data.ResultSet({ + //total: records.length, + count: records.length, + records: records, + success: true + })); + + // announce success + operation.setSuccessful(); + operation.setCompleted(); + + // finish with callback + Ext.callback(callback, scope || me, [operation]); + }, + + update: function (operation, callback, scope) { + finishOperation(this, operation, callback, scope); + }, + + destroy: function (operation, callback, scope) { + finishOperation(this, operation, callback, scope); + } + }; +}())); + +Ext.define("WebODFApp.model.FileSystem", { + extend: 'Ext.data.Model', + config: { + idProperty: 'id', + fields: [ { + name: "id", + type: "auto" + }, { + name: "fullPath", + type: "string" + }, { + name: "fileName", + type: "string" + }, { + name: "size", + type: "int" + } ] + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/store/FileStore.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/store/FileStore.js new file mode 100644 index 0000000000..d2932c8989 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/store/FileStore.js @@ -0,0 +1,30 @@ +/*global Ext*/ +Ext.define('WebODFApp.store.FileStore', { + extend: 'Ext.data.Store', + config: { + storeId: 'FileStore', + model: 'WebODFApp.model.FileSystem', + autoLoad: true, + grouper: { + groupFn: function (record) { + "use strict"; + return record.get('fileName')[0].toUpperCase(); + } + }, + proxy: { + xtype: 'filesystemproxy' + }, + sorters: function (a, b) { + "use strict"; + a = a.get('fileName').toUpperCase(); + b = b.get('fileName').toUpperCase(); + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; + } + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/views/FileDetail.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/FileDetail.js new file mode 100644 index 0000000000..b79876c6de --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/FileDetail.js @@ -0,0 +1,122 @@ +/*global Ext, app, runtime, xmldom, odf*/ +runtime.loadClass("xmldom.XPath"); +runtime.loadClass("odf.Style2CSS"); +Ext.define('WebODFApp.view.FileDetail', (function () { + "use strict"; + var panel, + style2CSS = new odf.Style2CSS(), + xpath = new xmldom.XPath(), + fileDetail, + title, + image, + list, + emptyImageUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAAXNSR0IArs4c6QAAAAtJREFUCB1jYGAAAAADAAFPSAqvAAAAAElFTkSuQmCC"; + function getTitle(body) { + var ps, + title; + ps = xpath.getODFElementsWithXPath(body, + ".//text:h", style2CSS.namespaceResolver); + title = ""; + if (ps && ps.length) { + title = ps[0].nodeValue; + } else { + ps = xpath.getODFElementsWithXPath(body, + ".//text:p", style2CSS.namespaceResolver); + if (ps && ps.length) { + title = ps[0].nodeValue; + } + } + return title; + } + function metaToJSON(body, meta) { + var json = [], + title = body && getTitle(body), + e = meta && meta.firstChild, + name; + if (title) { + json.push({name: "title", value: title}); + } + while (e) { + if (e.nodeType === 1 && e.textContent) { + if (e.localName === "user-defined") { + name = e.getAttributeNS( + "urn:oasis:names:tc:opendocument:xmlns:meta:1.0", + "name" + ); + } else { + name = e.localName; + } + json.push({ + name: name, + value: e.textContent + }); + } + e = e.nextSibling; + } + return json; + } + return { + extend: 'Ext.Panel', + xtype: 'filedetail', + config: { + title: 'File details', + layout: 'vbox', + items: [{ + id: "title", + dock: 'top', + xtype: 'toolbar' + }, { + id: 'details', + xtype: 'container', + layout: 'hbox', + flex: 1, + items: [{ + id: 'thumbnail', + xtype: 'image', + width: 256, + maxWidth: "50%" + }, { + id: 'metalist', + xtype: 'list', + store: { + fields: ["name", "value"], + data: [] + }, + itemTpl: "{name}: {value}", + flex: 1 + }] + }], + listeners: { + initialize: function () { + fileDetail = this.query("#details")[0]; + title = this.query("#title")[0]; + image = fileDetail.query('#thumbnail')[0]; + list = fileDetail.query('#metalist')[0]; + } + } + }, + updateRecord: function (record) { + if (record) { + fileDetail.setMasked({ + xtype: 'loadmask', + message: 'Loading...' + }); + title.setTitle(record.get('fileName')); + } + }, + canvasListener: function (odfcanvas) { + var view = this, + odfcontainer = odfcanvas.odfContainer(), + part = odfcontainer.getPart("Thumbnails/thumbnail.png"), + metajson = []; + metajson = metaToJSON(odfcontainer.rootElement.body, + odfcontainer.rootElement.meta); + part.onstatereadychange = function (part) { + image.setSrc(part.url || emptyImageUrl); + }; + part.load(); + list.getStore().setData(metajson); + fileDetail.unmask(); + } + }; +}())); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/views/FilesList.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/FilesList.js new file mode 100644 index 0000000000..1a82a2e8b6 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/FilesList.js @@ -0,0 +1,47 @@ +/*global Ext, app, filestore */ +Ext.define("WebODFApp.view.FilesList", { + extend: "Ext.Panel", + xtype: 'fileslist', + config: { + layout: 'fit', + items: [{ + xtype: 'list', + store: 'FileStore', +/* + store: { + fields: ['fileName', 'fullPath'], + grouper: { + groupFn: function (record) { + "use strict"; + return record.get('fileName')[0].toUpperCase(); + } + }, + data: [ + {fileName: 'Cowper', fullPath: '-'}, + {fileName: 'Everett', fullPath: '-'}, + {fileName: 'University', fullPath: '-'}, + {fileName: 'Forest', fullPath: '-'} + ] + }, +*/ +/* + listeners: { + 'itemtap': function (view, number, item) { + "use strict"; + var record = view.getStore().getAt(number); + if (record) { + Ext.app.dispatch({ + controller: 'Files', //app.controllers.files, + action: 'show', + id: record.getId() + }); + } + } + }, +*/ + itemTpl: '{fileName}
{fullPath}', + grouped: true, + indexBar: true + }] + } +}); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/views/OdfView.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/OdfView.js new file mode 100644 index 0000000000..2098304d32 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/OdfView.js @@ -0,0 +1,170 @@ +/*global Ext, runtime, core, odf, window, FileReader, PhoneGap, gui*/ +runtime.loadClass('odf.OdfCanvas'); + +Ext.define('WebODFApp.view.OdfView', (function () { + "use strict"; + var currentPath, + overridePath, + overridePathPrefix = "odf:", + data, + globalreadfunction, + globalfilesizefunction, + odfcanvas, + zoom = 1, + dom, + canvasListeners = [], + view; + function signalCanvasChange() { + var i; + for (i = 0; i < canvasListeners.length; i += 1) { + canvasListeners[i](odfcanvas); + } + } + function initCanvas() { + var cmp; + if (globalreadfunction === undefined) { + // overload the global read function with one that only reads + // the data from this canvas + globalreadfunction = runtime.read; + globalfilesizefunction = runtime.getFileSize; + runtime.read = function (path, offset, length, callback) { + if (path !== overridePath) { + globalreadfunction.apply(runtime, + [path, offset, length, callback]); + } else { + callback(null, data.slice(offset, offset + length)); + } + }; + runtime.getFileSize = function (path, callback) { + if (path !== overridePath) { + globalfilesizefunction.apply(runtime, [path, callback]); + } else { + callback(data.length); + } + }; + dom = Ext.getCmp('webodf').element.dom; + odfcanvas = new odf.OdfCanvas(dom); + odfcanvas.addListener("statereadychange", signalCanvasChange); + } + } + function load(path) { + if (path === currentPath) { + return; + } + currentPath = path; + overridePath = overridePathPrefix + path; + data = null; + window.resolveLocalFileSystemURI("file://" + path, function (file) { + var reader = new FileReader(); + // so far phonegap is very limited, ideally it would implement + // readAsArrayBuffer and slice() on the File object + // right now, it has a dummy function, hence breaking simple + // detection of which features are implemented + if (reader.readAsArrayBuffer + && (typeof PhoneGap === "undefined")) { + reader.onloadend = function (evt) { + data = evt.target.result; + odfcanvas.load(overridePath); + }; + reader.readAsArrayBuffer(file); + } else { + reader.onloadend = function (evt) { + var b = new core.Base64(); + data = evt.target.result; + data = data.substr(data.indexOf(",") + 1); + data = b.convertBase64ToUTF8Array(data); + odfcanvas.load(overridePath); + }; + reader.readAsDataURL(file); + } + }, function () { + runtime.log("COULD NOT RESOLVE " + path); + }); + } + function tapHandler(button) { + var id = button.getId(), + dom = Ext.getCmp('odfcontainer').element.dom, + width = dom.offsetWidth, + height = dom.offsetHeight; + if (id === 'zoomin') { + odfcanvas.setZoomLevel(odfcanvas.getZoomLevel() * 1.25); + } else if (id === 'zoomout') { + odfcanvas.setZoomLevel(odfcanvas.getZoomLevel() * 0.8); + } else if (id === 'fit-best') { + odfcanvas.fitToContainingElement(width, height); + } else if (id === 'fit-width') { + odfcanvas.fitToWidth(width); + } else if (id === 'fit-height') { + odfcanvas.fitToHeight(height); + } else if (id === 'next') { + odfcanvas.showNextPage(); + } else if (id === 'previous') { + odfcanvas.showPreviousPage(); + } + } + return { + extend: 'Ext.Container', + xtype: 'odfview', + id: 'odfcontainer', + config: { + scrollable: 'both', + items: [{ + id: 'webodf' + }, { + xtype : 'toolbar', + docked: 'bottom', + scrollable: false, + defaults: { + iconMask: false, + ui : 'plain', + handler: tapHandler + }, + items: [ + { id: 'previous', icon: 'go-previous.png'}, + { id: 'next', icon: 'go-next.png' }, + { id: 'zoomin', icon: 'ZoomIn.png'}, + { id: 'zoomout', icon: 'ZoomOut.png' }, + { id: 'fit-best', icon: 'zoom-fit-best.png' }, + { id: 'fit-height', icon: 'zoom-fit-height.png' }, + { id: 'fit-width', icon: 'zoom-fit-width.png' } + ], + layout: { + pack : 'center', + align: 'center' + } + }], + listeners: { + painted: function () { + // make sure the viewport is the right size + odfcanvas.setZoomLevel(odfcanvas.getZoomLevel()); + } + } + }, + updateRecord: function (record) { + view = this; + initCanvas(); + load(record.get('fullPath')); + }, + addCanvasListener: function (listener) { + canvasListeners.push(listener); + }, + hideCanvas: function () { + if (dom) { + dom.style.display = "none"; + } + if (view) { + view.setMasked({ + xtype: 'loadmask', + message: 'Loading...' + }); + } + }, + showCanvas: function () { + if (view) { + view.unmask(); + } + dom.style.display = "inline-block"; + odfcanvas.setZoomLevel(odfcanvas.getZoomLevel()); + } + }; +}())); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/app/views/Viewport.js b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/Viewport.js new file mode 100644 index 0000000000..3023ddc017 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/app/views/Viewport.js @@ -0,0 +1,54 @@ +/*global Ext, app*/ +Ext.define("WebODFApp.view.Viewport", { + extend: "Ext.navigation.View", + xtype: "mainview", + requires: [ + "WebODFApp.view.FilesList", + "WebODFApp.view.FileDetail" + ], + config: { + fullscreen: true, + autoDestroy: false, + navigationBar: { + items: [{ + xtype: 'button', + id: 'openButton', + text: 'Open', + align: 'right', + hidden: true + }] + }, + items: [ + { title: 'Files', xtype: 'fileslist' } + ] + } +/* + initComponent: function () { + + //put instances of cards into app.views namespace + Ext.apply(app.views, { + filesList: new app.views.FilesList(), + fileDetail: new app.views.FileDetail(), + odfView: new app.views.OdfView() + }); + //put instances of cards into viewport + Ext.apply(this, { + items: [ + app.views.filesList, + app.views.fileDetail, + app.views.odfView + ] + }); + app.views.Viewport.superclass.initComponent.apply(this, arguments); + }, + listeners: { + afterlayout: function () { + if (app.stores.filesystem.initialUrl) { + app.openUrl(app.stores.filesystem.initialUrl); + app.stores.filesystem.initialUrl = undefined; + } + } + } + }; +*/ +}); diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/go-next.png b/apps/files_odfviewer/src/webodf/programs/touchui/go-next.png new file mode 100644 index 0000000000000000000000000000000000000000..c4da8a9a3d787dcded3a357a062e92ee9f59d71d GIT binary patch literal 1473 zcmV;y1wQ(TP)lWjE>obx@^XPW9K&fEOrq7G_VIumIdU zKJJ;dj}1l#Alx*vj*DE*Mb`B(bH+nhxn%mdp((41M3hf>ZlgJ{0=zCt?!k44t_O$K z!-f}O<*PHTlF1`iDZwkr8)F7m044W4A0BnU^@tRGAu#)?hfy|r^0b1uabnW*Tj$)a z0PXUSHx%G!Nq|oR0!?2>O)YH9=wd9HJ7wtjQOVtt=6|)0gyi4UTTya+x~1Ys)v872S)6*!O~xkGE0qKnm^eWdp*L{R#CFG^ii?YVXwtZA+j0t@Q5m(|@=z=N|^ zsCQSCq9f~p6m$~|iV+b}MMqe#4%nidSxgkgjlo3T31q6wp1!^y3aH=8wJp)@@ zzkOlb^-ZV*y0R{rDx4`N3i!T25XguMoKxf!g(j_gD0}wlGk(DJGqg8c4`W9dczjA~ zP9o1ZIdT4$>F5Ou5f~&gSqEGiP#~%(hVLd(g=An%5g8QFyY&$zgdlQVJw*P_JPhBM5bw4CM;7yarZr`?(C$w43(7a*$O|A`0$^SKQK|uk6 z#8BZ$`vWF|_xlN;U3w!O)DN=k7*%f(ZP=C;pyyBQHG4sy1tLqpBtd4BJW8yqPNWiO z>u@gyf|p&ce7g#SeggDdi3ST>Zt1IN6Jxes>n^aU14{K&AAJTOm5jPXjIL~6K^)Gt z46d|v>`*Y4G*zv>*6$XaY|WXkEnkJSN}?b?g~UCDNET8|CXpA9BOZ^ziaH=&4yC_v zv`pbGmxUPVy z_vXp(lzQ}=HOp}$&9HRwf%Kw<$X@cp)n8w zl+k^s6=TTQ68kH6qIU0|6F}0a!52Zn@G5PAPRn#=?(?|LVJLQZ8RL}bZFctU zz2}^@_TFosJ4d5ieEok2tliohnm4mBZ0PLJlEyN7(g;+o{D?SF>&df`x5^8uv)Xt4 z)XO=at0+qP2~;fKp5xl_cf!TN$66nqO|IWhy?saTA)1%|5>zaEyOCV;yDM=u4F+BvTR(Cf0G~V94XnOwis%ez4ZBk$o78fTjQ}0^Q zf0qD&{RnYOX(+H}>3z3ThEJujSVDr~5BNy}T;8GtHzt5=$qAUxZ%UwQRc9?D{z+3^ zer?_KTugSzG$A*Ik;2#n0+(5Mc8qdoJj@l%M@;t<)BL2s6XuZT(j(7rqq+5!2SKDk z1fg9gYO&awoJ_W5{_H$|&J>+uag$V4CB}py-NF=>qIgcPy}6mV=aI)@F3fY`U2na1JsUm8HfK94K@Cq?uoC_io2#7L_j9CEn z#z7qi-m&3f&UGwZs6|tQ9KaS9(Mj`=Doqi+E)}mzFogh* z1^=o8E~9rb9{2=&0DIDG3ue3I(-{W36Ge#L7XIa&3~NJmAu&UxOF0ct6v8yQ$g z0%Jh3=D1}5XW}^wFRs{lGvZy+dmv7gR*=YjYSa@%Gp0SLI?Vei1#T39Bc8( zA!n1$osF^K6KZC_Pq}%y6buGwN)AyLhG{xUFb!%nG>v>2I_bI&ZJ;ZXWpF{jM!2S+ zfwZ5Gj8Xqk1OzTp3@n6cVj)V&z#qHTIdCr(FKpZG3l?^&idk}DI7)F-sM@8>EQbP_ z?j;L2cV!NMS@Is0Nhv|f)!(yu zIMn#u%7HUuPX_a{w-%O^W-%se%|Jx99XykU1rhxv5^{`*wHXLNu&(04d*lhxs~*fH z2nX+7Dl0FhzQf0>JX?7U>GsE3x=lUQ@EnEw~Wee{xLe&_rcM;x+j``Jb3Vx!tlWQ+SyGE zyPVikr8(#v+p;AQ`6a|^CTbt~{eW`4HD3VPO(e(vy|3YgA9mVs8yu_UtMg}0bj(@s zU{R63f^6GC+9f#Z?MM-N21B$rUa}42+WyJ!fsvoT*vqRH*X{eP^Zn|E#+Leq2Z) + + + + WebODF + + + + + + + + + + + + + + + + + diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/scripts.js b/apps/files_odfviewer/src/webodf/programs/touchui/scripts.js new file mode 100644 index 0000000000..2683bc83b4 --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/scripts.js @@ -0,0 +1,130 @@ +/*global alert, app, window, runtime*/ +var LocalFileSystem = { + PERSISTENT: 0, + TEMPORARY: 1 +}; +function FileWriter(fullPath) { + "use strict"; + this.write = function (data) { + data = runtime.byteArrayFromString(data, "utf8"); + runtime.writeFile(fullPath, data, function () {}); + }; +} +function FileEntry(name, fullPath) { + "use strict"; + this.isFile = true; + this.isDirectory = false; + this.name = name; + this.fullPath = fullPath; + this.file = function (onsuccess, onerror) { + function File(fullPath) { + this.name = name; + this.fullPath = fullPath; + this.type = ""; + this.size = -1; + this.lastModifiedDate = -1; + } + var file = new File(fullPath); + try { + onsuccess(file); + } catch (e) { + alert("Error on determining file properties: " + e); + onerror(e); + } + }; + this.createWriter = function (onsuccess, onerror) { + onsuccess(new FileWriter(fullPath)); + }; +} +function FileReader() { + "use strict"; + var fr = this; + this.readAsArrayBuffer = function (file) { + var path = file.fullPath; + if (path.substr(0, 7) === "file://") { + path = path.substr(7); + } + runtime.readFile(path, 'binary', function (error, data) { + fr.onloadend({target: {result: data}}); + }); + }; + this.readAsText = function (file) { + var path = file.fullPath; + if (path.substr(0, 7) === "file://") { + path = path.substr(7); + } + runtime.readFile(path, 'utf8', function (error, data) { + fr.onloadend({target: {result: data}}); + }); + }; +} +var DirectoryReader; +function DirectoryEntry(name, fullPath) { + "use strict"; + this.isFile = false; + this.isDirectory = true; + this.name = name; + this.fullPath = fullPath; + this.createReader = function () { + var reader = new DirectoryReader(fullPath); + return reader; + }; +} +function DirectoryReader(fullPath) { + "use strict"; + this.readEntries = function (onsuccess, onerror) { + window.setTimeout(function () { + var entries = []; + entries[entries.length] = new FileEntry("welcome.odt", + "welcome.odt"); + entries[entries.length] = new FileEntry("Traktatenblad.odt", + "Traktatenblad.odt"); + entries[entries.length] = new FileEntry("DanskTest01.odt", + "DanskTest01.odt"); + entries[entries.length] = new FileEntry("plugfest-gouda.odp", + "plugfest-gouda.odp"); + entries[entries.length] = new FileEntry("OpenDocument-v1.2.odt", + "OpenDocument-v1.2.odt"); + entries[entries.length] = new FileEntry("OpenDocument-v1.2-part1.odt", + "OpenDocument-v1.2-part1.odt"); + entries[entries.length] = new FileEntry("OpenDocument-v1.2-part2.odt", + "OpenDocument-v1.2-part2.odt"); + try { + onsuccess(entries); + } catch (e) { + onerror(e); + } + }, 1); + }; +} +window.resolveLocalFileSystemURI = function (path, onsuccess, onerror) { + "use strict"; + var p = path.lastIndexOf("/"), + name = (p === -1) ? path : path.substr(p + 1); + onsuccess(new FileEntry(name, path)); +}; +window.requestFileSystem = function (filesystem, id, onsuccess, onerror) { + "use strict"; + var dirs = [], shared, subfolder, path; + try { + if (filesystem === LocalFileSystem.PERSISTENT) { + path = ""; + onsuccess({ + name: "root", + root: new DirectoryEntry("root", path) + }); + } else { + onerror("not defined"); + } + } catch (e) { + onerror(e); + } +}; +var device = {}; +/* + * override launch function to quickly open a file for testing +onApplicationLaunch = function (app) { + "use strict"; + app.openUrl("plugfest-gouda.odp"); +}; +*/ diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.css b/apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.css new file mode 100644 index 0000000000..7227e268be --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.css @@ -0,0 +1 @@ +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}li{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:""}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:text-top}sub{vertical-align:text-bottom}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit}*:focus{outline:none}html,body{font-family:"Helvetica Neue", HelveticaNeue, "Helvetica-Neue", Helvetica, "BBAlpha Sans", sans-serif;font-weight:normal;position:relative;-webkit-text-size-adjust:none}body.x-desktop{overflow:hidden}*,*:after,*:before{-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);-webkit-user-select:none;-webkit-touch-callout:none;-webkit-user-drag:none}.x-ios.x-tablet .x-landscape *{-webkit-text-stroke:1px transparent}body{font-size:104%}body.x-ios{-webkit-backface-visibility:hidden}body.x-android.x-phone{font-size:116%}body.x-android.x-phone.x-silk{font-size:130%}body.x-ios.x-phone{font-size:114%}body.x-desktop{font-size:114%}input,textarea{-webkit-user-select:text}.x-hidden-visibility{visibility:hidden !important}.x-hidden-display,.x-field-hidden{display:none !important}.x-hidden-offsets{position:absolute !important;left:-10000em;top:-10000em;visibility:hidden}.x-fullscreen{position:absolute !important}.x-desktop .x-body-stretcher{margin-bottom:0px}.x-mask{position:absolute;top:0;left:0;bottom:0;right:0;height:100%;z-index:10;display:-webkit-box;display:box;-webkit-box-align:center;box-align:center;-webkit-box-pack:center;box-pack:center;background:rgba(0, 0, 0, 0.3) center center no-repeat}.x-mask.x-mask-gray{background-color:rgba(0, 0, 0, 0.5)}.x-mask.x-mask-transparent{background-color:transparent}.x-mask .x-mask-inner{background:rgba(0, 0, 0, 0.25);color:#fff;text-align:center;padding:.4em;font-size:.95em;font-weight:bold;-webkit-border-radius:0.5em;border-radius:0.5em}.x-mask .x-loading-spinner-outer{display:-webkit-box;display:box;-webkit-box-orient:vertical;box-orient:vertical;-webkit-box-align:center;box-align:center;-webkit-box-pack:center;box-pack:center;width:100%;min-width:8.5em;height:8.5em}.x-mask.x-indicator-hidden .x-loading-spinner-outer{display:none}.x-mask .x-mask-message{text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0;-webkit-box-flex:0 !important;max-width:13em;min-width:8.5em}.x-draggable{z-index:1}.x-dragging{opacity:0.7}.x-panel-list{background-color:#bacfe8}.x-html{-webkit-user-select:auto;-webkit-touch-callout:inherit;line-height:1.5;color:#333;font-size:.8em;padding:1.2em}.x-html body{line-height:1.5;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;color:#333333;font-size:75%}.x-html h1,.x-html h2,.x-html h3,.x-html h4,.x-html h5,.x-html h6{font-weight:normal;color:#222222}.x-html h1 img,.x-html h2 img,.x-html h3 img,.x-html h4 img,.x-html h5 img,.x-html h6 img{margin:0}.x-html h1{font-size:3em;line-height:1;margin-bottom:0.50em}.x-html h2{font-size:2em;margin-bottom:0.75em}.x-html h3{font-size:1.5em;line-height:1;margin-bottom:1.00em}.x-html h4{font-size:1.2em;line-height:1.25;margin-bottom:1.25em}.x-html h5{font-size:1em;font-weight:bold;margin-bottom:1.50em}.x-html h6{font-size:1em;font-weight:bold}.x-html p{margin:0 0 1.5em}.x-html p .left{display:inline;float:left;margin:1.5em 1.5em 1.5em 0;padding:0}.x-html p .right{display:inline;float:right;margin:1.5em 0 1.5em 1.5em;padding:0}.x-html a{text-decoration:underline;color:#0066cc}.x-html a:visited{color:#004c99}.x-html a:focus{color:#0099ff}.x-html a:hover{color:#0099ff}.x-html a:active{color:#bf00ff}.x-html blockquote{margin:1.5em;color:#666666;font-style:italic}.x-html strong,.x-html dfn{font-weight:bold}.x-html em,.x-html dfn{font-style:italic}.x-html sup,.x-html sub{line-height:0}.x-html abbr,.x-html acronym{border-bottom:1px dotted #666666}.x-html address{margin:0 0 1.5em;font-style:italic}.x-html del{color:#666666}.x-html pre{margin:1.5em 0;white-space:pre}.x-html pre,.x-html code,.x-html tt{font:1em "andale mono", "lucida console", monospace;line-height:1.5}.x-html li ul,.x-html li ol{margin:0}.x-html ul,.x-html ol{margin:0 1.5em 1.5em 0;padding-left:1.5em}.x-html ul{list-style-type:disc}.x-html ol{list-style-type:decimal}.x-html dl{margin:0 0 1.5em 0}.x-html dl dt{font-weight:bold}.x-html dd{margin-left:1.5em}.x-html table{margin-bottom:1.4em;width:100%}.x-html th{font-weight:bold}.x-html thead th{background:#c3d9ff}.x-html th,.x-html td,.x-html caption{padding:4px 10px 4px 5px}.x-html table.striped tr:nth-child(even) td,.x-html table tr.even td{background:#e5ecf9}.x-html tfoot{font-style:italic}.x-html caption{background:#eeeeee}.x-html .quiet{color:#666666}.x-html .loud{color:#111111}.x-html ul li{list-style-type:circle}.x-html ol li{list-style-type:decimal}.x-video{background-color:#000}.x-sortable .x-dragging{opacity:1;z-index:5}.x-layout-card-item{background:#eeeeee}.x-map{background-color:#edeae2}.x-map *{-webkit-box-sizing:content-box;box-sizing:content-box}.x-mask-map{background:transparent !important}.x-img{background-repeat:no-repeat}.x-video{height:100%;width:100%}.x-video > *{height:100%;width:100%;position:absolute}.x-video-ghost{-webkit-background-size:100% auto;background:black url() center center no-repeat}audio{width:100%}.x-panel,.x-msgbox,.x-panel-body{position:relative}.x-panel.x-floating,.x-msgbox.x-floating,.x-form.x-floating{padding:6px;-webkit-border-radius:0.3em;border-radius:0.3em;-webkit-box-shadow:rgba(0, 0, 0, 0.8) 0 0.2em 0.6em;background-color:black;background-image:none}.x-panel.x-floating.x-floating-light,.x-msgbox.x-floating.x-floating-light,.x-form.x-floating.x-floating-light{background-color:#354f6e;background-image:none}.x-panel.x-floating > .x-panel-inner,.x-panel.x-floating .x-scroll-view,.x-panel.x-floating .x-body,.x-msgbox.x-floating > .x-panel-inner,.x-msgbox.x-floating .x-scroll-view,.x-msgbox.x-floating .x-body,.x-form.x-floating > .x-panel-inner,.x-form.x-floating .x-scroll-view,.x-form.x-floating .x-body{background-color:#fff;-webkit-border-radius:0.3em;border-radius:0.3em}.x-anchor{width:1.631em;height:0.7em;position:absolute;left:0;top:0;z-index:1;-webkit-mask:0 0 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAPCAYAAABut3YUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPZJREFUeNpi/PX7LwOFwAyIG6HseiA+Ra5BjBQ6xg+IVwAxJ5T/HYgjgHgTOYYxUeCQUiBeh+QQBih7HVSOLiHDDMSTgTiTgLrpQJwLxH9p5RhOaLT4EakeFF3RQPyF2o6RhkaBGYkheRmIPYH4KbXSjC4QnyTDIch6danhGCcgPgwNGXKBNNQMb0ocEwXE24GYn4FyADJjI76Ej88x7UC8FIjZGKgHQDlxGtRsZmISMMjy+dBQoSXYBC0gv+NyDD80xzgx0AeAqg4fIH6NHk0qQHyMjg6B1WvHYDkNFjIgwS1ALMowMOAjEAeBHINe2Q0U+AUQYACQ10C2QNhRogAAAABJRU5ErkJggg==') no-repeat;-webkit-mask-size:1.631em 0.7em;overflow:hidden;background-color:black;-webkit-transform-origin:0% 0%}.x-anchor.x-anchor-top{margin-left:-0.816em;margin-top:-0.7em}.x-anchor.x-anchor-bottom{-webkit-transform:rotate(180deg);margin-left:0.816em;margin-top:0.6em}.x-anchor.x-anchor-left{-webkit-transform:rotate(270deg);margin-left:-0.7em;margin-top:-0.1em}.x-anchor.x-anchor-right{-webkit-transform:rotate(90deg);margin-left:0.7em;margin-top:0}.x-floating.x-panel-light:after{background-color:#354f6e}.x-button{-webkit-background-clip:padding;background-clip:padding-box;-webkit-border-radius:0.4em;border-radius:0.4em;display:-webkit-box;display:box;-webkit-box-align:center;box-align:center;min-height:1.8em !important;padding:.3em .6em;position:relative;overflow:hidden;-webkit-user-select:none}.x-button,.x-toolbar .x-button{border:1px solid #999999;border-top-color:#a6a6a6;color:black}.x-button.x-button-back:before,.x-button.x-button-forward:before,.x-toolbar .x-button.x-button-back:before,.x-toolbar .x-button.x-button-forward:before{background:#999999}.x-button,.x-button.x-button-back:after,.x-button.x-button-forward:after,.x-toolbar .x-button,.x-toolbar .x-button.x-button-back:after,.x-toolbar .x-button.x-button-forward:after{background-color:#ccc;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #dedede), color-stop(100%, #bababa));background-image:-webkit-linear-gradient(#ffffff,#dedede 2%,#bababa);background-image:linear-gradient(#ffffff,#dedede 2%,#bababa)}.x-button .x-button-icon.x-icon-mask,.x-toolbar .x-button .x-button-icon.x-icon-mask{background-color:black;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(2%, #121212), color-stop(100%, #000000));background-image:-webkit-linear-gradient(#4d4d4d,#121212 2%,#000000);background-image:linear-gradient(#4d4d4d,#121212 2%,#000000)}.x-button.x-button-pressing,.x-button.x-button-pressing:after,.x-button.x-button-pressed,.x-button.x-button-pressed:after,.x-button.x-button-active,.x-button.x-button-active:after,.x-toolbar .x-button.x-button-pressing,.x-toolbar .x-button.x-button-pressing:after,.x-toolbar .x-button.x-button-pressed,.x-toolbar .x-button.x-button-pressed:after,.x-toolbar .x-button.x-button-active,.x-toolbar .x-button.x-button-active:after{background-color:#c4c4c4;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ababab), color-stop(10%, #b8b8b8), color-stop(65%, #c4c4c4), color-stop(100%, #c6c6c6));background-image:-webkit-linear-gradient(#ababab,#b8b8b8 10%,#c4c4c4 65%,#c6c6c6);background-image:linear-gradient(#ababab,#b8b8b8 10%,#c4c4c4 65%,#c6c6c6)}.x-button .x-button-icon{width:2.1em;height:2.1em;background-repeat:no-repeat;background-position:center;display:block}.x-button .x-button-icon.x-icon-mask{width:1.3em;height:1.3em;-webkit-mask-size:1.3em}.x-button.x-item-disabled .x-button-label,.x-button.x-item-disabled .x-hasbadge .x-badge,.x-hasbadge .x-button.x-item-disabled .x-badge,.x-button.x-item-disabled .x-button-icon{opacity:.5}.x-button-round,.x-button.x-button-action-round,.x-button.x-button-confirm-round,.x-button.x-button-decline-round{-webkit-border-radius:0.9em;border-radius:0.9em;padding:0.1em 0.9em}.x-iconalign-left,.x-icon-align-right{-webkit-box-orient:horizontal;box-orient:horizontal}.x-iconalign-top,.x-iconalign-bottom{-webkit-box-orient:vertical;box-orient:vertical}.x-iconalign-bottom,.x-iconalign-right{-webkit-box-direction:reverse;box-direction:reverse}.x-iconalign-center{-webkit-box-pack:center;box-pack:center}.x-iconalign-left .x-button-label,.x-iconalign-left .x-hasbadge .x-badge,.x-hasbadge .x-iconalign-left .x-badge{margin-left:0.3em}.x-iconalign-right .x-button-label,.x-iconalign-right .x-hasbadge .x-badge,.x-hasbadge .x-iconalign-right .x-badge{margin-right:0.3em}.x-iconalign-top .x-button-label,.x-iconalign-top .x-hasbadge .x-badge,.x-hasbadge .x-iconalign-top .x-badge{margin-top:0.3em}.x-iconalign-bottom .x-button-label,.x-iconalign-bottom .x-hasbadge .x-badge,.x-hasbadge .x-iconalign-bottom .x-badge{margin-bottom:0.3em}.x-button-label,.x-hasbadge .x-badge{-webkit-box-flex:1;box-flex:1;-webkit-box-align:center;box-align:center;white-space:nowrap;text-overflow:ellipsis;text-align:center;font-weight:bold;line-height:1.2em;display:block;overflow:hidden}.x-toolbar .x-button{margin:0 .2em;padding:.3em .6em}.x-toolbar .x-button .x-button-label,.x-toolbar .x-button .x-hasbadge .x-badge,.x-hasbadge .x-toolbar .x-button .x-badge{font-size:.7em}.x-button-small,.x-button.x-button-action-small,.x-button.x-button-confirm-small,.x-button.x-button-decline-small,.x-toolbar .x-button-small,.x-toolbar .x-button.x-button-action-small,.x-toolbar .x-button.x-button-confirm-small,.x-toolbar .x-button.x-button-decline-small{-webkit-border-radius:0.3em;border-radius:0.3em;padding:.2em .4em;min-height:0}.x-button-small .x-button-label,.x-button.x-button-action-small .x-button-label,.x-button.x-button-confirm-small .x-button-label,.x-button.x-button-decline-small .x-button-label,.x-button-small .x-hasbadge .x-badge,.x-hasbadge .x-button-small .x-badge,.x-button.x-button-action-small .x-hasbadge .x-badge,.x-hasbadge .x-button.x-button-action-small .x-badge,.x-button.x-button-confirm-small .x-hasbadge .x-badge,.x-hasbadge .x-button.x-button-confirm-small .x-badge,.x-button.x-button-decline-small .x-hasbadge .x-badge,.x-hasbadge .x-button.x-button-decline-small .x-badge,.x-toolbar .x-button-small .x-button-label,.x-toolbar .x-button.x-button-action-small .x-button-label,.x-toolbar .x-button.x-button-confirm-small .x-button-label,.x-toolbar .x-button.x-button-decline-small .x-button-label,.x-toolbar .x-button-small .x-hasbadge .x-badge,.x-hasbadge .x-toolbar .x-button-small .x-badge,.x-toolbar .x-button.x-button-action-small .x-hasbadge .x-badge,.x-hasbadge .x-toolbar .x-button.x-button-action-small .x-badge,.x-toolbar .x-button.x-button-confirm-small .x-hasbadge .x-badge,.x-hasbadge .x-toolbar .x-button.x-button-confirm-small .x-badge,.x-toolbar .x-button.x-button-decline-small .x-hasbadge .x-badge,.x-hasbadge .x-toolbar .x-button.x-button-decline-small .x-badge{font-size:.6em}.x-button-small .x-button-icon,.x-button.x-button-action-small .x-button-icon,.x-button.x-button-confirm-small .x-button-icon,.x-button.x-button-decline-small .x-button-icon,.x-toolbar .x-button-small .x-button-icon,.x-toolbar .x-button.x-button-action-small .x-button-icon,.x-toolbar .x-button.x-button-confirm-small .x-button-icon,.x-toolbar .x-button.x-button-decline-small .x-button-icon{width:.75em;height:.75em}.x-button-forward,.x-button-back{position:relative;overflow:visible;height:1.8em;z-index:1}.x-button-forward:before,.x-button-forward:after,.x-button-back:before,.x-button-back:after{content:"";position:absolute;width:0.773em;height:1.8em;top:-0.1em;left:auto;z-index:2;-webkit-mask:0.145em 0 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAABGCAYAAADb7SQ4AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAiNJREFUeNrEWb9LQlEUvj5BcHoQvMnVKXD1D3CLwqBJbHJsazQaWoSCxgbHJiMIAiNok6AhCDdXVycnJ8EQOgeOYaG+d39998KH+HyP753zzjnfd325xfdSgVeV8B6BScuEV0IRSbxHeCMk/AVFXCA8ScQKSXxPqK0fQBBfE5r/D+Y8VzUT9jb94DPimqRYIYkrhGcpKhhxIqTxrpNcExdlQJTTTnRJnCc8ykhUSOIOoZ71ZFfEZ4S2zgUu+rguxZRHEnPbfKRVsOtUl0RtYpOLTYljIS2Z3nVk2DY9SbNCEt8RDm0rUpe4La1jvXSqmtum72raZI24KuNQIYl/nSGSOJb0Jq61M0pxhjwK9304hUjHGSKILzc5Q5drUzttdYY+I97pDH1FzG0zNFUb04gTG4kzJS5kdYauiZtZnaFr4ooKsCIVaDHxKAQxt1NBnGIVHfGCcEQYh3jGU8KBfMKLiyM+lgzAq/qT0ArVTg+Ei1B9fEPoovV4fcfQd2HedScX39GprwGTNjJn0maTELN6IuSzECLB6T5x2eM66jQgnIeSxa60GnS3uL56tr7b1Ai0JPVwYi6yho2U2lgfKym19VxjMRHzEGbvS9K+RBPzetGVUpf29lZHSl2/DMnLvwh1ZMQrKW3Ic4fvJOZS6ZMQW5hpmpT63DvtlFLfm7bBNruM2C2yXb7y3U6ZpRS5P/4jpUjihRTbCJ3q1eL3GMMfAQYAJmB6SBO619IAAAAASUVORK5CYII=') no-repeat;-webkit-mask-size:0.773em 1.8em;overflow:hidden}.x-button-back,.x-toolbar .x-button-back{margin-left:0.828em;padding-left:.4em}.x-button-back:before,.x-toolbar .x-button-back:before{left:-0.693em}.x-button-back:after,.x-toolbar .x-button-back:after{left:-0.628em}.x-button-forward,.x-toolbar .x-button-forward{margin-right:0.828em;padding-right:.4em}.x-button-forward:before,.x-button-forward:after,.x-toolbar .x-button-forward:before,.x-toolbar .x-button-forward:after{-webkit-mask:-0.145em 0 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAABGCAYAAADb7SQ4AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXlJREFUaN7lmTFqAlEQhh8EhFSCYJXW1law9QAewMrWAwQWAmmtbPcGHiCQ1gPYCla2QsDKSsgmQecvFqImu2/fzry/2OLb9mt23vwz47Kvn5MwEFxM8DkLB6HHEIOd0GGIwUpoMcRgyRKDOUsMJizxpzBiiMFR6DPEeZl1GWKwFh4ZYvAmPDDEqmVWVQxmLPG3MGaIVcosVAz2whNDDDZCmyEG7yFlpiEGKUsMEpb4XKXMtMXeiVVb7J1YLcRgW1ZmVuLSxGopLkys1mLwwhL/mVhjie8Sayxx3kp7DPFVYo0tzhNriyEGU5Z40TjxtDE/F6WcDowHBE/msDFNImG0xZQRBAonDCvxhhH2vKZIZ9Ds+7EDfaWFnKZ4xhja5owxdcnYCAQv1p1Gi4sprn08cZbDt6ZYZasXIn5mLFHTjLCvVt1V+4rVt/M+4r3FPaJMbHaBKRKb3pyKxKZXtv/Er4yjZpRL6q042u34tzh4xV9H/FHnqBHKBQeEd6aqqwD6AAAAAElFTkSuQmCC') no-repeat}.x-button-forward:before,.x-toolbar .x-button-forward:before{right:-0.693em}.x-button-forward:after,.x-toolbar .x-button-forward:after{right:-0.628em}.x-button.x-button-plain,.x-toolbar .x-button.x-button-plain{background:none;border:0 none;-webkit-border-radius:none;border-radius:none;min-height:0;text-shadow:none;line-height:auto;height:auto;padding:0.5em}.x-button.x-button-plain > *,.x-toolbar .x-button.x-button-plain > *{overflow:visible}.x-button.x-button-plain .x-button-icon,.x-toolbar .x-button.x-button-plain .x-button-icon{-webkit-mask-size:1.4em;width:1.4em;height:1.4em}.x-button.x-button-plain.x-button-pressing,.x-button.x-button-plain.x-button-pressed,.x-toolbar .x-button.x-button-plain.x-button-pressing,.x-toolbar .x-button.x-button-plain.x-button-pressed{background:none;background-image:-webkit-gradient(radial, 50% 50%, 0, 50% 50%, 24, color-stop(0%, rgba(119,178,248,0.7)), color-stop(100%, rgba(119,178,248,0)));background-image:-webkit-radial-gradient(rgba(119,178,248,0.7),rgba(119,178,248,0) 24px);background-image:radial-gradient(rgba(119,178,248,0.7),rgba(119,178,248,0) 24px)}.x-button.x-button-plain.x-button-pressing .x-button-icon.x-button-mask,.x-button.x-button-plain.x-button-pressed .x-button-icon.x-button-mask,.x-toolbar .x-button.x-button-plain.x-button-pressing .x-button-icon.x-button-mask,.x-toolbar .x-button.x-button-plain.x-button-pressed .x-button-icon.x-button-mask{background-color:#fff;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e6e6e6), color-stop(10%, #f2f2f2), color-stop(65%, #ffffff), color-stop(100%, #ffffff));background-image:-webkit-linear-gradient(#e6e6e6,#f2f2f2 10%,#ffffff 65%,#ffffff);background-image:linear-gradient(#e6e6e6,#f2f2f2 10%,#ffffff 65%,#ffffff)}.x-segmentedbutton .x-button{margin:0;-webkit-border-radius:0;border-radius:0}.x-segmentedbutton .x-button.x-first{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em;-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em}.x-segmentedbutton .x-button.x-last{-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em}.x-segmentedbutton .x-button:not(:first-child){border-left:0}.x-hasbadge{overflow:visible}.x-hasbadge .x-badge{-webkit-border-radius:1em;border-radius:1em;-webkit-background-clip:padding;background-clip:padding-box;padding:.15em .25em;z-index:2;text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0;-webkit-box-shadow:#000 0 .1em .2em;overflow:hidden;color:#fff;border:2px solid #fff;position:absolute;width:auto;min-width:2em;height:2em;line-height:1.2em;font-size:.6em;top:-0.15em;right:0px;max-width:100%;background-color:#990000;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e60000), color-stop(50%, #b30000), color-stop(51%, #990000), color-stop(100%, #800000));background-image:-webkit-linear-gradient(#e60000,#b30000 50%,#990000 51%,#800000);background-image:linear-gradient(#e60000,#b30000 50%,#990000 51%,#800000);display:inline-block}.x-tab .x-button-icon.action,.x-button .x-button-icon.x-icon-mask.action{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAFI0lEQVRoBe2YW4hVVRjHZ0yzq6lFEaMlE0PShYRAJIl6iEqKHnqI6WJB0IvdICkfEk0aIyo0KFCph8giCitI7CkoohQL7SoZDaQmXSgKo4uWNf1+zt7DOXvOOXuvvc85bc+cD36ssy/r+77/Xmt9e+3TOzIy0jORbNJEEqvWruBOH/HuCHdHuMOeQOmmdO+ozaA5oxXPunSC2Re4MbgCNiB6vvqbKbx0giNxp9BeBU/BIJqnRecLN2UVrLDj4GIYgscRfSltYSuzYMUdA/0wCI8ieglM5XduK7vgWJhTegGshucRfQHkyj1XpziLNrfmOh2ug1dhMaJn0gbZZDpNpsexQb2y3azfKXCAwns4W5dMd7m2B2ANLCT/x/A/nKknN5mUhWFp1g4Z7vM14jrbBZvgEwi1tAdkDEf3ZrgI0S/RrkP4IdqGpuA+cJo0yw7iyNfJmzAcMrokfjp93HC4XrPYCdzkgPXDPPqvJN7eRh0VrBWqfKMuev6k3Qzr4SP4HWqOFIkZ73iYA/NhLpwPZ4LLS+FZzUp+GtwAA/heS/sGwv+irWnXc9bdTRF20/8eOBWmEKwnCectOrPhSlgF2+Bb+Bl+AxP8B/6FvLn8Td8fYQXMSubgsVZU8Cv4mAeNhC7k+jLYCopzrRURlvZA9P8WLIJJlcI5zi1Ypw+Dr4oqp3EAzlsbLCjfg1PeEUxLtlnXXU4/wQboq8gpl2BHx2l5UuyosuW8I6rQb8Bp1iwRefy4VN6FReaopU3pX7jnhwSO7MmVIiNnJ3L+DtgHCm3ltA0RH4/26rhKk1tdu4kr7yeuHkKgU3rMqI5ncfAQDIKbg14oi1nJv4OvTShthC9LjmTyGB8XwhZw+oQ8+Xbc68C8AOboK6+YYPpfDV+B06YdAkJiuMtzhvrOP1JYafMLpu/Z8CmEJNGOe60fz0J/cjZmWcP0G2+sWZ/aUnCqhFosOq7gyf6uOT888th+Ot0HmxF7MOkgt2AcXQNLkg5rHPv+dffjVvPX6PdeWtf7MJhUssD578ZtEGL6sY4MIfTjeh1zCWZ0Z+DwQXAkapkjtzviPdoPYB+JuJVMNfy7QQkR7MbGPfRaYhi7ruUSjLcbwe1k0tw2vgivwy6C70/ekPE4JK+N+HySWDuz+A5xXOnvlsqD6Lf/QjwBnxNc4a02YwzBeuIdyBosWDDT7RKcn1MRYA+/V8ImAv9Rcb5VP53ufoQ8AB8S0+PMFiwYz5fDzCjCF7SLCbojOm514zZ3HViYLIZVxmD4h8B0rtWtFXkEn4tTv22thPe2SawVeDs8TTz/NqoyhLqDGoC7wervt3lNCxKMY/fIc+BLuJXgn9G20pyuVuA1sJF4vt7GjHx8nZnT7XAXzIXnoK4FCcbLVHAqLW+DWF8v78Aq2EY8v7zGDK2+EmfBI3AtTAPNTU1dCxXs/a6ht+t6bM4FNykvw/0IdYSrDLHu8iyeQ7Cg6mLKQahgd0pbSOJwit/cl6Np6p+BrxGn6hNUp1z3m/tOWAH+DrIgwSTQcBcTFLnOzcRwSjZ6j/vdvQyCxRrSanu0mWvZqp3LjkbBuYTGnSac4CxreCQqJPFD+r/bhq+dtOSyCO7DyWzIcm9avKLXXb+FcskiYjlBfB0lP9KLJp+nv6N7ZL+cp7N9sgg+L6/zMvabcEWrK7iM07CZOXVHuJlPs4y+rNJ74JkyJpczp62N+vWOfpw0uqWzrnXXcGeN53g13REe/0w660x3hDtrPMer+Q9LNCcV91c+jgAAAABJRU5ErkJggg==')}.x-tab .x-button-icon.add,.x-button .x-button-icon.x-icon-mask.add{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAABqUlEQVRoBe2awWnDUBBE843B4NxcQSAFOC4lJeTkoxtJDykgvRhcgCFNJCFgIs+ChEHSJX93YT6ZD4ssmR3NztNFH5Wu6+6iVynlEZpbp+4J3s5OjWm7DRxZuMMCdUB9oyzNmrJe01hEejMtM5exIh6bCI3JbFkDT27EckEDs5DI8iHCWcmy6IowC4ksHyKclSyLrgizkMjyIcJZybLoijALiSwfIpyVLItuOGFso/xiuEvAgJdeK0DqJrHEhtsTTh9ul9y/ChR2KE+Y1ruDt2ccI7d6PszcK+oFFblWELt3Cn6i/8epMW5/W+LKGrUZ/0NwboF5QxuPsfY8dmOxJs41cBOYHCZF2BFeE60i3AQmh0kRdoTXRKsIN4HJYVKEHeE10frvCNvr4RH1HojH3rGHr3hqA7VdkxPKvuKJ3AA4hn7BM3xxA5N71Fdv1gz/tax3P+hFHmsJwM/8wraMadqOh5GuXda76rVqNWb7wgeevQvRRQ1MBCPFiginxEokKsJEMFKsiHBKrESiIkwEI8WKCKfESiQqwkQwUqyIcEqsRKIiTAQjxcoVrP83/9czD9EAAAAASUVORK5CYII=')}.x-tab .x-button-icon.arrow_down,.x-button .x-button-icon.x-icon-mask.arrow_down{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGRTdGMTE3NDA3MjA2ODExOTJDQUMyNUQwRUE4NjdEQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxQTFBMDFDQ0I5NEYxMURGQUU1RjlGMEFERUNDQTVEMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyMkRCMDIxMkI5NEUxMURGQUU1RjlGMEFERUNDQTVEMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMwRTE0QzVBNDIyMjY4MTFCQ0ZCOTAzOTcwNzcyRkVCIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFN0YxMTc0MDcyMDY4MTE5MkNBQzI1RDBFQTg2N0RCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+HfrH/AAAAeVJREFUeNrs2cFHBGEUAPA3zYqIiIhOnTpFRHSKrp26RqeuEV077R/QqWtE166dOkVERHRa9hQRnZalFcv0Hk/W1Mx+38z3vvlm5j3eZW+/9+abne+9KEkSaFPMQMtCwQpWsIIVrGAFK1jBClawgo2ik/4hiqJGwLKuvfpIc5xSkWqYr5hzU1s/mRNxXTPsJ+ZqluvXlwOmSj3XBDvG3M1rpAmYYoUrFzr4ZNqTawqm2MH8Dhh7ZXJUbcAUx4FinzBnJcAUl4FhP/jIgRSYKvkYCJaO2LbNv08RMMUy5nsA4COTLy0XYIqtil9iF6aflq7AwBWuAvuQ9ZKSBgNX2ieWjtKSzeXBNZgqfe8J+4W5aXtbcg0GrvibB/BhkeuhBJhigzsghT0veh+WAlMcCGHvMOMQwcCdcIntYy6WmXhIg2PuiAvsEHO97IhHGgzckb4D8L6LmZYPMHBnhiWwXVdDPF9g4A4Vwd66nFr6BAN3ygbbw1yoMzjmjplgB5hrrufSvsHAHesZDOD2JAbxVYCBOzfIAZ9JbR6qAgN3cPwP9kZy1VIlGLiTdluCmoOBO/pnS9Bk8DzmS3pL4BMcpZEe1qX0GI/atC4dQYXRMa1MU0IX4gpWsIIVrGAFK1jBCnYUPwIMAPUPAyFL+nRdAAAAAElFTkSuQmCC')}.x-tab .x-button-icon.arrow_left,.x-button .x-button-icon.x-icon-mask.arrow_left{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGRTdGMTE3NDA3MjA2ODExOTJDQUMyNUQwRUE4NjdEQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGMDZEQTFBREFDOTMxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGMDZEQTFBQ0FDOTMxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkFGQzJEMjQxRjIyMDY4MTE4QTZEQzUxMDg5Q0Y0RTRFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFN0YxMTc0MDcyMDY4MTE5MkNBQzI1RDBFQTg2N0RCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+FXGmxAAAAghJREFUeNrsm09ERFEUxt+rxBAxqyFm1SqiRYpMSpFapUVaRGpTRIpIbWLaFJEoRZtilChRWiRKsyklilYRERERERGZvsN57Wfmvnnnznkfv+WM+bn3e/ePN24mk3E0pcRRllC42FOWy4dc1w30R+fz3LFthEs1TelZ0KlBuAIcgmRgHS5gqlm2RsNTmqbvrUlZycLT4BhUiliWfEwEbII+UeuwT4nzqNZq2Gm1gTu/ZaUIj4NTEBW7tTTY1zUwKH4vbaive6BBw2kpAa6DkA1CeBicgZhVx8McUg5WWNi+83CWiXFfE9ZeAGQR6ukBqJKyu/Gzw7TcXEiS9UuYbiWWeU8ckXYqMT2lozyFW6SeOU0K1/FhPS75RsHUlKbj3KV0WRPC1Nd5sCuxr6anNPV12zFwk2jLCCdtk81XeAIsahL+BVOgH3xrEPayA5rAixZhyj2oB2ktwpR30A5WtQh7vR4DQ+BHg7CXLdAMXrUIU26411dahClvoBVsaBF2uMsjYFRCrwt5a7kOOnjUVQg7vE43cr9VCDu8I6Nep7QIO7z3HgCTvHYXvbCXJe71hxZhyjmv1w9ahCnP/DDb1yLs9boXzGgR9rIAusCnFmHKCff6UYsw5Ymlj7QIU75AN5gz9YVuLu8eB/S+dA+v1+l83pe2Sfg/BRe2OeGfPELhUDgUtip/AgwAw4tbozZtKFwAAAAASUVORK5CYII=')}.x-tab .x-button-icon.arrow_right,.x-button .x-button-icon.x-icon-mask.arrow_right{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGRTdGMTE3NDA3MjA2ODExOTJDQUMyNUQwRUE4NjdEQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGMDZEQTFCMUFDOTMxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGMDZEQTFCMEFDOTMxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkFGQzJEMjQxRjIyMDY4MTE4QTZEQzUxMDg5Q0Y0RTRFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFN0YxMTc0MDcyMDY4MTE5MkNBQzI1RDBFQTg2N0RCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+xvZexwAAAhhJREFUeNrsm8FHRFEUxu9rxhARsxqiVauYXWoTpTYtUkRqlWkz0WaiTW2iNi3atGhTm4k2E5GYSJRaZcZQtIqIISIiYhgyfZdv/oF59913X+cdfst5733u+c495743XqvVUpKiSwmLWPB/j2QnP/I8L9SH9lN3/KxwQlpKT4FtaR7eAhegR1LRmgEVMCCpSg+CGtNczLbUC8pgQ9I+rCv3LiiBbkmNxwJ93S+p08qCRzAhqbVMg2tQkNRLa1/vg6ILvrY5POTAXdi+tj0tDbOYjUoaDzPgBuQlzcMpcEhSkg4A8lztjBTBin6u0d8iBOvoYwXPSRGsuEcXuWcnJAhuR4G+TksRrGOMfXhWimDFjqzCyUuE4LavS5yxExIEt0OfopRN+DpKbx6MHAtHSfAeWPN7kWQEhDbAMjg1cTHXBdfBLHiSUKXvwZBJsS4LPgCT4NP0hV1L6SZYAcdB3cAlwe9gDlQlTEsP9Gs16Bu5IPgIjIOP/34AoP26Ss82bd00LA/r1Vzk1mM1whCsfTrPpsJ62E7pE/q1HpaPbAn+Betgib1xaGEjpb+Ywrcu7H9BC35m8//mSncTZEqfgRGXxAYpeJNp3FCOhemU/ub+euXqzGlS8AuYBq8unyiYSulLNv9OizUleIcr+6MiEF4n3x7ze2n9OkSfE5/bfmg/30v7ERxaWBcc5Yj/5BELjgXHgiMVfwIMAGPkXbHq6ClAAAAAAElFTkSuQmCC')}.x-tab .x-button-icon.arrow_up,.x-button .x-button-icon.x-icon-mask.arrow_up{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGRTdGMTE3NDA3MjA2ODExOTJDQUMyNUQwRUE4NjdEQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpDQUZBQUM3NEFDOTMxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpDQUZBQUM3M0FDOTMxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkFGQzJEMjQxRjIyMDY4MTE4QTZEQzUxMDg5Q0Y0RTRFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFN0YxMTc0MDcyMDY4MTE5MkNBQzI1RDBFQTg2N0RCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+ar3jxgAAAbFJREFUeNrs2j9ExGEcx/H71YmmpoiIaIq4KSKi6dabbo1oiqamm1qboimiNZpuuikiIqLppiPipqYjIuLp+/D95vy6X/frfr/n730e3sst53XP9x7u+V2ilKpM05qpTNkCGGCAAQYYYIABBhhggAEGeNSqpl9IkiQKWNbvfBc7PDdNIz1PPVK7Trd+OMPrRr8l9Uat2nT9+CyCW4yVnnnHowTXqa8UWHcdI3iNGozASscxgReo7h9YxTtfjwXcHoOVBjwJQYNPcmKlLk9EkODGP7FSO0TwOvU+IVjxZAQD1iPZK4CVGiGAZ6lOCVjFE7LhO/i0JKzUK3KImQY3S8ZKHZ4cr8A16sMQWPHkeANepF4MYqWmD2A9arcWsIonqOYafGYJK73yRDkB71nGSnd5r4jKBG9Sn47AunOb4CWq7xAr7dsA61G69wCreMK2TIMvPMFKfZ44I+ADz7DSQ9YhVgS87fiQGtdlmeBlvkNWnndYBljfGT8FgJVDbKco+CoQrBp6mrEyKfgoMOyvpxlZ4CT9vcXj0shWNe8nE8vCfzwABhhggAEGGGCATa1vAQYAZekAmr8OukgAAAAASUVORK5CYII=')}.x-tab .x-button-icon.compose,.x-button .x-button-icon.x-icon-mask.compose{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.delete,.x-button .x-button-icon.x-icon-mask.delete{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.organize,.x-button .x-button-icon.x-icon-mask.organize{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAEdUlEQVRoBe2aS2xMURjHjbbqUaLoI7RChQUiGo9YaEqkoolIkCASSki68dixsLIVYmHbkJA03UgkFRI2QgRBKl4RgtJFK0jUI+o5fv/p68ztmUlHzpzO9PZLfjP3fOfcO9//fOeee+69E4lGo6PCZKPDJFZaQyc4N1mGI5FIMfUVkAfZMPaVwE54yqn6i+8BllQwravgAEyEv5DppsQ8gYPw3hqsJi0bNJ4El0GZzSa6iHcbjLbpsp7DDGX5V8ByyDbLJ+CdUGQLPNGQnkzj3TDFspN68BNkwhDPIY5poG/T1lBYR+LOkuW4uSeR4KXssN48grF9h20NdeukYLRL96Y6vAD2wCwwbQyFvXARPpoVA85fKnXiN4HtvP2Gf0tPG3XWUKNYT4E6PxjvD3x1EDHPZZvgxTTSDBc8gMrKbql5gKHeJh7NM6/AFu91/EVmjHGTFmN+HA3qYSoE7SuO8+zcEawY4vJdfr8Z/ljiqMS3AV2RvjpTPc7V0A623rqJv8RsnynbxDUXXieJuy/LfRmmEzSd7wKtroL2Hcc5BL4LVmRCmbheEIfmHduVQ1muQV/3BN2bJZyqaANbdm/jL+xtm4nfxKcsP08Q/zX8MxV3TDXqx+PYBGUQNHVAI9AsYrsuB9sPVflDT5xH+O7OZn8kK9msJf6G3ooFOOr66+O2NOVL6A7oP/njmmREQcN5LGhy1cLJtBwK++FSLqrVSGvPcrCZGu8DZTqTBSs+zUkarTZTUrerYh50gHYY7rSpRxZCCYTByvouS2FQK42hE9w7S/tKsOaIt/AGfoMWO3OgFLyYb8FaGByHl6C1r27jlsAh8HaN14LD1+x8jN/KNVdqlAvhgq8YfJ/DLYjVUDatk8J905HObd+Cf1rEaHTp5sSL+RacaKWWyO+8E3wLdi4g1QOOCE61x7Kt/UiGsy1jqcY7kuFUeyzF9ok6WA8ZvJjLtbQWEI/hXpLIW4N1rLyiPHV5hP9MsM4or2V7hlH+702XghWE3gAcTRKN3mjY7AZOdZbNCnAug4wTrNXSItCrmmYSZ3tGTNVAo+1nvCLOyLyeT9WC7WlqXNtUCq7vlpTlGkQMeG+Vio9j6NbxMOjtn8u7udjzaJcH1H3uLViVikCzLftqEtsKbeAyNh3LuWAdVM+yr8JsU8hgt9mvGh6ATousEKwgdcvXCMWDFap2mOYBTWK6b3YtNvYDrs9hM0i9BTgB+YMRTbvp0AS6bzaP43I7LUPaDFBvHPVmIy+ZaOp1+TkJX8Dc3/V22gUrYF1jN4L1r0T4NSPXg+sZ2dZZXgRr5m6BymCW8en6rc54BrYAXfu8CFbQmoQ0c1eYoilXw0NQp7gWZzueN8H68S44DbG/IPA9H66AL7FR12tpYk9qetOwGfSaVjcMNVAFie6iqHJv6bws2YaUfLpctYP+S5WoTVr8vjOMvphN4FN4N69Dybs6yw+OCLZ0yrByhS7DmrRaoQE0Kw5707JOf/UvH/ZKewTG/kscFrHSGbpzOHSC/wHSRhVOrpN3ggAAAABJRU5ErkJggg==')}.x-tab .x-button-icon.refresh,.x-button .x-button-icon.x-icon-mask.refresh{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.reply,.x-button .x-button-icon.x-icon-mask.reply{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAES0lEQVRoBe2ZSWgUQRSGM24YTdSo4AYRTcxBEZJDJCoigrtGg6CIgihqogfRgEERguhB40UP6kHw4kEET4J4E9wPAdeg4ALigjuKcSMuMX7/mAmdSU/SXdM9PTPpBx/T3al67/31urq6K5G2trac3mR9epNYaQ0FZ3vFwwqHFc6yEQhv6SwraBc5YYW7DEmWXUhZhSORSC7UwKIgxzAlghE5CZFHoAEKgxTcz8/gCI3gfzHsh6l+xnLq2zfBaC0miXpYDvmgu+kXBGqeC0aohK2D7TAF+kPamKeCETseZdugGgZDSp4RxHFsnghGqKo4H/aB5uoASEtLWjBiZ6KsFlaAHlJpbUkJRmwl6rTcFKW1SktyRoIROhofdbARhlr8OTkMdBPNlWCE6iG0AA5AqRN1Nm1cxbTpn9Qlx8ERO4pIG0Br6yDDqH3pV4kvPdRewCd4C+/ZPdWx7xZxsk1LgqvIZDeUeZzRT/xJ8Dt4BQ/gGjSSVzO/3psEJ4JoY+A4fATNvVTwhjh34RSshMGJ8jO5biuWIJqrc6AJ/kIqhNrF+EFs3fqHYRoMMxFp7dNFME5Hwi5QMLskgrqmgb8M+hgZYRXh5riTYBxpFM9CUKKcxlWOSyHPjVi1jQqmYy7shQ/gNGjQ7f6Q6yWY7UY07XNK4CK0QtAiTOK/J29tLOQ7EU67nIGgtfU1mARMhz6a3zegtCfRHXOYxhXtndJBgGkOT9FQ1Z3oDsFqhBXAFngJpkGD7veN3NclEt1JcKwRHaaD3niCTt40vh6+q2N6rL+2gtUA03p8FL6AaeAg++ntsNwqNqor/kL8OZ2WgF71vEpeq8FvC36uDveJM8qqyenHwzg67oE1MAxMTeLOQyNod0SDqO2hCaDVIma6u3R9OAxq/9WxW9PT+wRsQ7RiE7Gbj4f4v9F8Fujxb1ptfR2tj/cbf04bfbbqZWgsFEM5LITNcBLc3HF6iM2IxXAlWJ0wJXEQfoFb4RJcEwtu8kv/PCiEGdAAevFQJbvL5Rh/j351uRbcLloVmA83ewgUn0TSgq2DRGzloVt9E9yDFoiPqfOvUBHN3erA7TFOtG6fBqdfVp4KtuZLDqr8DrgDdqIPcb2/UYXjAmmu1cLDBIGswX0THMuJHIrgDGglsMZu4nxI0oItgcbjUHP7MyRaanwXrHywvlAFj8E6v+dqZ8MTI9BzHO2DtaC9KY1wIEYurXCO4JrbjyA6CvzO80wwznS3tMAFDpfBKdArnkY4ECOXqwTWUqZvA1mJp4L/+4wKf8ZxDeyE26AlLBBD9HUC14GWr8mezWEc2/oiiNZM/TumGbRLkdQ6nChOT9eJWw3ffakwjjuMRF5wUg9b4QnE5hOHKTVNsSuO3qW9SosN/Yn4KmAQbnnl040f4pelVLCb5Pxq6/st7Vfipn5DwaYjlyn9wgpnSqVM8wwrbDpymdIvrHCmVMo0z15X4X9rh8wHLEjawQAAAABJRU5ErkJggg==')}.x-tab .x-button-icon.search,.x-button .x-button-icon.x-icon-mask.search{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.settings,.x-button .x-button-icon.x-icon-mask.settings{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.star,.x-button .x-button-icon.x-icon-mask.star{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAFfUlEQVRoBd2aXahVRRTHz/Ujv+2mZRGZB7W6mtpFikC7+UWUZiqBD0JPFdRL1EMFPfjoU4baS0FUD/UWZBEVShA+BCpmWApRSkgllNpDmZWZt9//eOay72afvWfWOTPn3rvgz8yeWbPW+s/XmT379AwODtZSSQ+CryVgA/gVfIx/pelEhFMBVlvBOaBeFo6Cean8y09KsnMg932TqCOs9M2UhMfhMJVsxtHcAmcbmekLCsqjFKUkvAYG1xSwmEHZqoLyKEVJCDOCNxH9HUCbVl6mULAuXxjrOQlhgl8Bbi0h0Uen3FBS37GqVIQHiHh2SdR16jTlo0t0woycpuxiUDSdHcFeMv3uIWYanTDB3wIWVZBQHP10zuQKvbarUxDWT1HRz1E++Ds99fLtgp6jEmbExhPNcs+IbkZPiCpRCRP5TPCQJ4MJ6A3QSUqjSWzC2ozuC4j+fnSnB+gHq8YmvJKIJgVEpRPX9QH6waqxCa8PjEhHT981H2j6qno0wqzF63BhOUxsom3Zb7aJqGsUjTAONFJlpysXQz7VuXpavrBTzzEJaz1adlzNjHs6RTBvJyZhjZTF/kTaWZZCnlvhsyWgQkPZQpagzsX1bFlAXjGtDdAPUu1p3PPQhCCXkdwG/mta0PWLds060AuAnqtEOjpdbQR3VymX1P9F3UfgGJA9X9F92c/ADaQ2P8V0DJ4/kDbeYKaSvgI2AN0+OGJK1VAbSIhTOXEOybYll2kte77yD4rqrHyb85S9Cl4HtReAyI11/A7HpRq5PSD6oR0f3Rad+H7S1DvV7UgS+tc1cU3n3V/AWJ/SX8BxVuMinow2rNNjlPQVeH0GFg378kDBfLAPXARjZbTPwmUXmOG+bgz71EKFfqKeAUWfREZbJxyCxyOOqEuHER4qrNUWovwy0CFktBHV4eNZMNvxyaaFhKWAaBt/HJwEo4W0luSKLMF8viVhp4iBeeBd8CcYqcQ1qi+CKS7uVmklYdcQY0+C42Ckkf6EmO51cVal3oRlCFkCdKgfCWtbo7obDO3AVWQbHHyUsjo40E6uq9cvQbdG+wN892fj8s0HjXDWKA51/t4JUo72H/jTDtybjSUkbyYsJ0gdfAtSjfTn+JoWQjCv2+57a4M1QaQSvZvrMsIs7RJejGcdUlLJUhzpZsYsZsJcCen6ZwCE3IaYA2021OfUdU3fJltmwni7Fvh+KDMF16KR3ux0lWuSdgjPxeNdJq/tNdKNqJaSSUyEmVK6JNPomtqbIh3eSKNsEmvAarfJ5LEzjbbR59MtpqyEb8eZjpndkhtxvNri3Er4YZxpx+yW6Jdhi8V5MOHm+n0QZ9afo0u0fQO8A5S3iPaQ1cTSG9w4f/SqesZBH/gRWI6T+gyyxfkgvw2cMdrS+/lTzpZvGnyWxsnTwHLRd4R2a/OBqQyoztKBe/P2qp6DCBOUptKHhuA+pU1fq2Co0/F0L9CVaghxXTbWW9ktKg8lrFfCrwODeh/9wgu1bEDo6OT2Fvgb+JLWq+nQEsnaa5UPJbwKBxc8A9KXPG1O3u+u6E4F24GvD3XMDjCxFcF8uTdhjGpHfwn49L42lCeAdyDZwGi3HpwAPr6+Q29htn1ZPoSwfuz3ewShXVcBNz62lzkvq6O9DjZHgQ9p72kdQljvob9VBPAN9Q+UEQmpw5b+Sf8e0FotI/4a9ZN8bIcQXlnh9AD1y3ychuhgU0tpJyhb14epn+ljN+Sk9S9G1ct50d8SdgF9x9EO3lHB5hXwPEYfA8dbGD9LuWZBtfj0inSQWUDTKzu1dAB5Dkz2tdOOHn70LvwVyMag/FYwzse295Rukq5j+G1wEOib66PAy5FPMD46+NPmqTV7CpwGGvkJPm2l8z8GWDNDloqpGQAAAABJRU5ErkJggg==')}.x-tab .x-button-icon.trash,.x-button .x-button-icon.x-icon-mask.trash{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAFBElEQVRoBe2aS4gdRRRA8+L/m0QIJkYNLlQUNOAvigpRcCEIcSsiCLoLLoILcaM7QVBX4koRshDxt9CFKCoiuvGDCP5QkxCiJhInRo2Ovzie80gPNWX1dL3uesM09IUz3V1169a9daur+031aG5ubkUpGY1GK7G1Dq4Cz9vKiIY74Sv8+72tkWQ7Ay4Bxo+Hu2E3/AuOZBf+ov2TsL6Ef5WNUsGazXvgEHQJMm77N/aeg3Mrh7seOweMM2bWYH+B2OES1/9g9w0oEnSngHHCYO+FGSgRXJ0NM/0idA565BRpKyxSt9J2B5xWY+Mw5Udq6uqKT6XimESlmX4d7sTnA4n6rKJjs7QSSgTrSno7nJyodtFyGr4AP4G6TeLIHweb4A44C0LR1xtgCzwP7aTtIkBvLlSfQjwNZyl7FNa0sU077V4DX0Js25X7cRjPzDb2Nd5FnK7xPbGXskdwxsxOLLRzdnwIj8GvkQFnypqobKLLrgGnOjMzP6cqJijzfn0NXPljmXRNWNC+dcBHM7HA2NELp10nwbaz5iC4OsdidTyrYp3a68ZFi7XJFfNsOBGcUmFnPpbiBWkVZefT7g+OXcTF0EUsFPtaje0Lw0LOzfoM49B4Gy36WMKwK+WDcC2cAmGwXK7YAAYdym9c+NiIdUOdnHODc6DjpPioix9LBvwtPE3QOzjWi7MjBS0M8CGY1huUA1ISg/4cNqXiqcqSwVqJ3AQ/QEmnpm3LR+IzsLYKMD4mA6bBOfAKuFpO28nS9v0Bcxckn9V1Ad9Pg2m/H5cONLT3Mf5fFGfX63hBQG8s7/LXxcdV0nvjMtgKp0MojuaroM60xYB8Z78ZTog6c515B1ylXey+ARe3/0tqFNCy0RjrkdvgOwhH0TeiB2A1uMBNGx9Ta+FZiP34mrIrQR39cECSUzqZYYIcR0mjJtmFwmHUvdenLjwmnUl7Eh05+LP40fjvoGTACYN1Rc6CecGhM7lw2lt+AA7Fg4fOespXgYO0j3pvnXmh3rY+/52+vrXtRSd841rQJ/WV1JVX9eNj14DnjeHnJVw8DBeAnX8A2ynfXwXN+cWUPQUOjNl6i7Jt1I9nCOe+1V0NT4AB/wkvw31QRIoFjDfnwRXgfVbJGZzsry44boTNUGVjlvOToPpV5FvbjXApKE7VLZ6UkpWlDGHH+96pV93/4TSsujGA8MeF51Xw6njuO3soKTth/UTnJQOeqONFlKsBW0SlfdVyDLh9NBkth4AzBqnXKkOGe52+DOeHDGcMUq9Vhgz3On0Zzg8ZzhikXqsMGe51+jKcHzKcMUi9Vhky3Ov0ZTg/ZDhjkHqtMmS41+nLcH7IcMYg9VplOWY4/Md88cEtHbDOVg5Xx9jpsM9Yx52JeAcw1ontTXRdcm9pFz3vBveHdNJN6YPVRhrnivtMlruZ5g7DFxBuXLut8j7sA/d43Yr5CIpJsYAJ7DN2/27Bsw1gwAb3I8wLOp+g4w6+nw/6HddOyszqWDg/Qv2bXFwH4+1SyhyUYtI1YLc85wXn/ORAagWdPVRKUqh3AJwtdTLeWq2rbCoP76cm3bjeLG6ELjZim03XJujyJqXF6rtmeDvGNzMN/ajEAZi2rKOD67t00jVgN7+3dnFgqdsu5XRc6tiS/eUGvBTTNengBIVZPuYG7LcYPjdluYk++bTw++pGyQ34bSy9B35Vs5zEYGfgJfg+x7H/ADoy2VfnrtXoAAAAAElFTkSuQmCC')}.x-tab .x-button-icon.maps,.x-button .x-button-icon.x-icon-mask.maps{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAADl0lEQVRoBe2b24tNURzHjfutXEPycDAltwhJbuMSJUqSB/HiES/+AK9ePc6T8uCFkImQW5KGkdwSxYyMGkZu45bbDOPzyZyTrJnjnDkGrVm/+szas2bv397f33ftPS+/Vdba2toj5igj0NcfRkG/3qWIJdcIrs/AO6gDq7cKPkOjUNAmxr8ePJsix8NUWAvLoapowSQawIUzYCZUwAqohF3QAjtgGTyCy5x/nfEu1MNDCmAxuiS4Vy8ST4DZMB9WwiTIRUGC26q1gKtWwyyYBsPB5aLIL5CNTxzotDeWTeA5DUKuO4xXoQbxHpcUbSIzJFkDi0EzdLYnBNGuYJJ4ch+YAhvB5TAORsKvib4x97vwPpk2FjJuhibu85zxAlyCangBLRQib06u68t5vk4uVYVqgO+oqy9v5ASTRLd0LQNLYB24bAfBnw5zikX0HtuhGW5ANY9ylvEBvIY3FOArcz7rWHCpboBFMAxyGjguKIZy1jzYCqfAD5BLslB8J3dCP/AdOgo+fKHXd3Sebh+EctCMieBK6Oj8QuYrXZ7roQr88PiSD4b/IVyyfhB9jQy/uppTUijYhANLytJ1F/sxzL7POpg97vQdFfwVTNYtQsHdKpLg2O1ODieHI6tAWtKRGRrISQ4HJYlsIjkcmaGBnORwUJLIJpLDkRkayEkOByWJbCI5HJmhgZzkcFCSyCaSw5EZGshJDgcliWwiORyZoYGc5HBQksgmksORGRrISQ4HJYlsIjkcmaGBnORwUJLIJpLDkRkayEkOByWJbKLbOVx0r3E7httIbttwNvzddt//JWxIfQynYX8pgu2TbgBbjw9Ds53sNHJv49gOehu5bUe2DfjXojDVpWG/9iu4CEegBp7xfO+LFfyGC5+AiQ7BFXj/c8s+xw+Z24PwvYwKnQxLoQLccGEB7Hsu9t5ckjcU2QjuozgA5+Apz9PCmItCbvqWs2vhJpwBl8ZrEuVtOebPtiWLbf2ymyL0ZVT8XJgDbgHIgFsPOhPmr4d7oAnHue9txg6jI8EfueIaHIOrcAuafieSc/IG19vw7TYD6UEBbE4vhwxMB7cizIYhYPT6MeR+WjBFPoCToEgF1hb6bD8LNpHLwT0L56EOGkhUchc6edoNcruvQWoQ7/6GMTAa3E2zACxGNjRhH9wHV4zP9oGxqCjj7C0wA06Ay/YliRT/T4MCuGnEfQ4feJ5mfvdfaG+OXSWdju+VpAoIK3D9tAAAAABJRU5ErkJggg==')}.x-tab .x-button-icon.locate,.x-button .x-button-icon.x-icon-mask.locate{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.home,.x-button .x-button-icon.x-icon-mask.home{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAEK0lEQVRoBe2Zy28NURzHe/vwqEepYkFIQzxWaCOC2HhELEgQImhXIrqyIEXikVQi+gdIwx9AItg1NiJELMSGhKQbobY2VY9Srfp8m5lmTO/cOXN7Zu656f0ln8zMnTNnft/z+505j5sbGxurmk5WPZ3ESuu0E1xbigjncrka3jsbftClIvsU5RZ65aLK5Lj/C75SzSjHWCuJYLxqhPXwBgYhylq4sRaixChDP8EzGIJ4UwNnCR6tgFswANegKer93LsLim4herm/JKqO8O+ZRdhL42acOwunYAacg2Hu3ePYj3Ph1A1fU2ySmZSZeCiTjxaC1LAboRs6QGJl8+AKXIU1kLqlHmHEqlFboQv2gD40QdPHqx3qKdtJkD8Hb9o+TzXCXmT1cboB+cT6evTVPgIXeWYl6DoVSy3COF2Hx0rjTthp4L0a/4xXrofn33OeqH8avKMqFcE4O4uXb4ULsNfEEa+M0v00LIIuCKc/P03NrAtGrD5Iiuh10Dia1JTOR0EZsjjpw3HlrQpGbD0v3AzFig36e4CLkeAPNs6tCUbsHBxS+mpsLSayYT2KtLBqVgQjdgFe7QP1u9VWPbRc2ZQFe2LV5zSBWG7ZP+vVTUkwYhvx6DicB+fFqvWKFuyJ1QxJ00It48rCNNgnNi+N23hQaVw2YiU0cYQRq9Q9CJdBKV1q02zMeEaWSDBil1L5JTgBDeCCzcUJ8cXImfACOeqayjbBffgDfqu6cPyJP3dgVZTvwd9jdzuoSFmgicRDGAYXRIZ9+I5fPbA6KC7feUHBVKD5rJZ1EutaZMOiv+HjbWjJJ9T/LVIwDyqyh+ApuC7WFy/RCk4r5HyRwWNewRSW2N3wGv6CX2E5HBWcB9AaFOqfTxJMQa1lNewosqNQDiLDPmqv+hFsgzpfrI7/CeamVjwnQZEtV7G+eEX6MeyHGl/0hGB+1MJdYt+B/1C5H9UdX8J2qJ6IMBfz4Ri8hXIXGfZfmdoLWr5W1zJ7ktg2aId18BuiTHNvDVUumQSNxDikLSdtBzdok0yCD8MyiLNmCqhxXBL9An+egNI3yqRT9z+O92FO/O2UuOMuymoqF06bUl53489MQw21Gm8lWmkRa6R/oVaMfT6lAmrsUVMNRa2HU3I8k2orgjNp5hK+ZLwPp/x+fR+0ONfMp9BfJ+qLmulpyze1zMtC8AACbkI/xAneQZkO0JiZimUheAjPn0MfxAnWVo3RiEG5oiwLwXJsmGFDK5iCxrCnGZNSOzVLra+EPDZ9T6EMCFVZ3KWpI8XV7uBTFcEOBsWqS5UIW21OByurRNjBoFh1qRJhq83pYGWVCDsYFKsuVSJstTkdrGz8L0VTv1i+NVF2CyTJDC0LX7E8HIx7D/Vrb3wDaLvY1D5QsI/6jXZUEwk29cDlckki5bIOY9+mneB/GfbU3e4Ey5kAAAAASUVORK5CYII=')}.x-button.x-button-action,.x-toolbar .x-button.x-button-action,.x-button.x-button-action-round,.x-toolbar .x-button.x-button-action-round,.x-button.x-button-action-small,.x-toolbar .x-button.x-button-action-small{border:1px solid #010509;border-top-color:#021022;color:white}.x-button.x-button-action.x-button-back:before,.x-button.x-button-action.x-button-forward:before,.x-toolbar .x-button.x-button-action.x-button-back:before,.x-toolbar .x-button.x-button-action.x-button-forward:before,.x-button.x-button-action-round.x-button-back:before,.x-button.x-button-action-round.x-button-forward:before,.x-toolbar .x-button.x-button-action-round.x-button-back:before,.x-toolbar .x-button.x-button-action-round.x-button-forward:before,.x-button.x-button-action-small.x-button-back:before,.x-button.x-button-action-small.x-button-forward:before,.x-toolbar .x-button.x-button-action-small.x-button-back:before,.x-toolbar .x-button.x-button-action-small.x-button-forward:before{background:#010509}.x-button.x-button-action,.x-button.x-button-action.x-button-back:after,.x-button.x-button-action.x-button-forward:after,.x-toolbar .x-button.x-button-action,.x-toolbar .x-button.x-button-action.x-button-back:after,.x-toolbar .x-button.x-button-action.x-button-forward:after,.x-button.x-button-action-round,.x-button.x-button-action-round.x-button-back:after,.x-button.x-button-action-round.x-button-forward:after,.x-toolbar .x-button.x-button-action-round,.x-toolbar .x-button.x-button-action-round.x-button-back:after,.x-toolbar .x-button.x-button-action-round.x-button-forward:after,.x-button.x-button-action-small,.x-button.x-button-action-small.x-button-back:after,.x-button.x-button-action-small.x-button-forward:after,.x-toolbar .x-button.x-button-action-small,.x-toolbar .x-button.x-button-action-small.x-button-back:after,.x-toolbar .x-button.x-button-action-small.x-button-forward:after{background-color:#06346a;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #167bf3), color-stop(2%, #07448c), color-stop(100%, #042348));background-image:-webkit-linear-gradient(#167bf3,#07448c 2%,#042348);background-image:linear-gradient(#167bf3,#07448c 2%,#042348)}.x-button.x-button-action .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-action .x-button-icon.x-icon-mask,.x-button.x-button-action-round .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-action-round .x-button-icon.x-icon-mask,.x-button.x-button-action-small .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-action-small .x-button-icon.x-icon-mask{background-color:white;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #ffffff), color-stop(100%, #ddecfd));background-image:-webkit-linear-gradient(#ffffff,#ffffff 2%,#ddecfd);background-image:linear-gradient(#ffffff,#ffffff 2%,#ddecfd)}.x-button.x-button-action.x-button-pressing,.x-button.x-button-action.x-button-pressing:after,.x-button.x-button-action.x-button-pressed,.x-button.x-button-action.x-button-pressed:after,.x-button.x-button-action.x-button-active,.x-button.x-button-action.x-button-active:after,.x-toolbar .x-button.x-button-action.x-button-pressing,.x-toolbar .x-button.x-button-action.x-button-pressing:after,.x-toolbar .x-button.x-button-action.x-button-pressed,.x-toolbar .x-button.x-button-action.x-button-pressed:after,.x-toolbar .x-button.x-button-action.x-button-active,.x-toolbar .x-button.x-button-action.x-button-active:after,.x-button.x-button-action-round.x-button-pressing,.x-button.x-button-action-round.x-button-pressing:after,.x-button.x-button-action-round.x-button-pressed,.x-button.x-button-action-round.x-button-pressed:after,.x-button.x-button-action-round.x-button-active,.x-button.x-button-action-round.x-button-active:after,.x-toolbar .x-button.x-button-action-round.x-button-pressing,.x-toolbar .x-button.x-button-action-round.x-button-pressing:after,.x-toolbar .x-button.x-button-action-round.x-button-pressed,.x-toolbar .x-button.x-button-action-round.x-button-pressed:after,.x-toolbar .x-button.x-button-action-round.x-button-active,.x-toolbar .x-button.x-button-action-round.x-button-active:after,.x-button.x-button-action-small.x-button-pressing,.x-button.x-button-action-small.x-button-pressing:after,.x-button.x-button-action-small.x-button-pressed,.x-button.x-button-action-small.x-button-pressed:after,.x-button.x-button-action-small.x-button-active,.x-button.x-button-action-small.x-button-active:after,.x-toolbar .x-button.x-button-action-small.x-button-pressing,.x-toolbar .x-button.x-button-action-small.x-button-pressing:after,.x-toolbar .x-button.x-button-action-small.x-button-pressed,.x-toolbar .x-button.x-button-action-small.x-button-pressed:after,.x-toolbar .x-button.x-button-action-small.x-button-active,.x-toolbar .x-button.x-button-action-small.x-button-active:after{background-color:#052d5c;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #02152b), color-stop(10%, #042144), color-stop(65%, #052d5c), color-stop(100%, #052e5e));background-image:-webkit-linear-gradient(#02152b,#042144 10%,#052d5c 65%,#052e5e);background-image:linear-gradient(#02152b,#042144 10%,#052d5c 65%,#052e5e)}.x-button.x-button-confirm,.x-toolbar .x-button.x-button-confirm,.x-button.x-button-confirm-round,.x-toolbar .x-button.x-button-confirm-round,.x-button.x-button-confirm-small,.x-toolbar .x-button.x-button-confirm-small{border:1px solid #263501;border-top-color:#374e02;color:white}.x-button.x-button-confirm.x-button-back:before,.x-button.x-button-confirm.x-button-forward:before,.x-toolbar .x-button.x-button-confirm.x-button-back:before,.x-toolbar .x-button.x-button-confirm.x-button-forward:before,.x-button.x-button-confirm-round.x-button-back:before,.x-button.x-button-confirm-round.x-button-forward:before,.x-toolbar .x-button.x-button-confirm-round.x-button-back:before,.x-toolbar .x-button.x-button-confirm-round.x-button-forward:before,.x-button.x-button-confirm-small.x-button-back:before,.x-button.x-button-confirm-small.x-button-forward:before,.x-toolbar .x-button.x-button-confirm-small.x-button-back:before,.x-toolbar .x-button.x-button-confirm-small.x-button-forward:before{background:#263501}.x-button.x-button-confirm,.x-button.x-button-confirm.x-button-back:after,.x-button.x-button-confirm.x-button-forward:after,.x-toolbar .x-button.x-button-confirm,.x-toolbar .x-button.x-button-confirm.x-button-back:after,.x-toolbar .x-button.x-button-confirm.x-button-forward:after,.x-button.x-button-confirm-round,.x-button.x-button-confirm-round.x-button-back:after,.x-button.x-button-confirm-round.x-button-forward:after,.x-toolbar .x-button.x-button-confirm-round,.x-toolbar .x-button.x-button-confirm-round.x-button-back:after,.x-toolbar .x-button.x-button-confirm-round.x-button-forward:after,.x-button.x-button-confirm-small,.x-button.x-button-confirm-small.x-button-back:after,.x-button.x-button-confirm-small.x-button-forward:after,.x-toolbar .x-button.x-button-confirm-small,.x-toolbar .x-button.x-button-confirm-small.x-button-back:after,.x-toolbar .x-button.x-button-confirm-small.x-button-forward:after{background-color:#6c9804;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c2fa3b), color-stop(2%, #85bb05), color-stop(100%, #547503));background-image:-webkit-linear-gradient(#c2fa3b,#85bb05 2%,#547503);background-image:linear-gradient(#c2fa3b,#85bb05 2%,#547503)}.x-button.x-button-confirm .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-confirm .x-button-icon.x-icon-mask,.x-button.x-button-confirm-round .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-confirm-round .x-button-icon.x-icon-mask,.x-button.x-button-confirm-small .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-confirm-small .x-button-icon.x-icon-mask{background-color:white;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #ffffff), color-stop(100%, #f4fedc));background-image:-webkit-linear-gradient(#ffffff,#ffffff 2%,#f4fedc);background-image:linear-gradient(#ffffff,#ffffff 2%,#f4fedc)}.x-button.x-button-confirm.x-button-pressing,.x-button.x-button-confirm.x-button-pressing:after,.x-button.x-button-confirm.x-button-pressed,.x-button.x-button-confirm.x-button-pressed:after,.x-button.x-button-confirm.x-button-active,.x-button.x-button-confirm.x-button-active:after,.x-toolbar .x-button.x-button-confirm.x-button-pressing,.x-toolbar .x-button.x-button-confirm.x-button-pressing:after,.x-toolbar .x-button.x-button-confirm.x-button-pressed,.x-toolbar .x-button.x-button-confirm.x-button-pressed:after,.x-toolbar .x-button.x-button-confirm.x-button-active,.x-toolbar .x-button.x-button-confirm.x-button-active:after,.x-button.x-button-confirm-round.x-button-pressing,.x-button.x-button-confirm-round.x-button-pressing:after,.x-button.x-button-confirm-round.x-button-pressed,.x-button.x-button-confirm-round.x-button-pressed:after,.x-button.x-button-confirm-round.x-button-active,.x-button.x-button-confirm-round.x-button-active:after,.x-toolbar .x-button.x-button-confirm-round.x-button-pressing,.x-toolbar .x-button.x-button-confirm-round.x-button-pressing:after,.x-toolbar .x-button.x-button-confirm-round.x-button-pressed,.x-toolbar .x-button.x-button-confirm-round.x-button-pressed:after,.x-toolbar .x-button.x-button-confirm-round.x-button-active,.x-toolbar .x-button.x-button-confirm-round.x-button-active:after,.x-button.x-button-confirm-small.x-button-pressing,.x-button.x-button-confirm-small.x-button-pressing:after,.x-button.x-button-confirm-small.x-button-pressed,.x-button.x-button-confirm-small.x-button-pressed:after,.x-button.x-button-confirm-small.x-button-active,.x-button.x-button-confirm-small.x-button-active:after,.x-toolbar .x-button.x-button-confirm-small.x-button-pressing,.x-toolbar .x-button.x-button-confirm-small.x-button-pressing:after,.x-toolbar .x-button.x-button-confirm-small.x-button-pressed,.x-toolbar .x-button.x-button-confirm-small.x-button-pressed:after,.x-toolbar .x-button.x-button-confirm-small.x-button-active,.x-toolbar .x-button.x-button-confirm-small.x-button-active:after{background-color:#628904;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #3e5702), color-stop(10%, #507003), color-stop(65%, #628904), color-stop(100%, #648c04));background-image:-webkit-linear-gradient(#3e5702,#507003 10%,#628904 65%,#648c04);background-image:linear-gradient(#3e5702,#507003 10%,#628904 65%,#648c04)}.x-button.x-button-decline,.x-toolbar .x-button.x-button-decline,.x-button.x-button-decline-round,.x-toolbar .x-button.x-button-decline-round,.x-button.x-button-decline-small,.x-toolbar .x-button.x-button-decline-small{border:1px solid #630303;border-top-color:#7c0303;color:white}.x-button.x-button-decline.x-button-back:before,.x-button.x-button-decline.x-button-forward:before,.x-toolbar .x-button.x-button-decline.x-button-back:before,.x-toolbar .x-button.x-button-decline.x-button-forward:before,.x-button.x-button-decline-round.x-button-back:before,.x-button.x-button-decline-round.x-button-forward:before,.x-toolbar .x-button.x-button-decline-round.x-button-back:before,.x-toolbar .x-button.x-button-decline-round.x-button-forward:before,.x-button.x-button-decline-small.x-button-back:before,.x-button.x-button-decline-small.x-button-forward:before,.x-toolbar .x-button.x-button-decline-small.x-button-back:before,.x-toolbar .x-button.x-button-decline-small.x-button-forward:before{background:#630303}.x-button.x-button-decline,.x-button.x-button-decline.x-button-back:after,.x-button.x-button-decline.x-button-forward:after,.x-toolbar .x-button.x-button-decline,.x-toolbar .x-button.x-button-decline.x-button-back:after,.x-toolbar .x-button.x-button-decline.x-button-forward:after,.x-button.x-button-decline-round,.x-button.x-button-decline-round.x-button-back:after,.x-button.x-button-decline-round.x-button-forward:after,.x-toolbar .x-button.x-button-decline-round,.x-toolbar .x-button.x-button-decline-round.x-button-back:after,.x-toolbar .x-button.x-button-decline-round.x-button-forward:after,.x-button.x-button-decline-small,.x-button.x-button-decline-small.x-button-back:after,.x-button.x-button-decline-small.x-button-forward:after,.x-toolbar .x-button.x-button-decline-small,.x-toolbar .x-button.x-button-decline-small.x-button-back:after,.x-toolbar .x-button.x-button-decline-small.x-button-forward:after{background-color:#c70505;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #fb6a6a), color-stop(2%, #ea0606), color-stop(100%, #a40404));background-image:-webkit-linear-gradient(#fb6a6a,#ea0606 2%,#a40404);background-image:linear-gradient(#fb6a6a,#ea0606 2%,#a40404)}.x-button.x-button-decline .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-decline .x-button-icon.x-icon-mask,.x-button.x-button-decline-round .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-decline-round .x-button-icon.x-icon-mask,.x-button.x-button-decline-small .x-button-icon.x-icon-mask,.x-toolbar .x-button.x-button-decline-small .x-button-icon.x-icon-mask{background-color:white;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #ffffff), color-stop(100%, #fedcdc));background-image:-webkit-linear-gradient(#ffffff,#ffffff 2%,#fedcdc);background-image:linear-gradient(#ffffff,#ffffff 2%,#fedcdc)}.x-button.x-button-decline.x-button-pressing,.x-button.x-button-decline.x-button-pressing:after,.x-button.x-button-decline.x-button-pressed,.x-button.x-button-decline.x-button-pressed:after,.x-button.x-button-decline.x-button-active,.x-button.x-button-decline.x-button-active:after,.x-toolbar .x-button.x-button-decline.x-button-pressing,.x-toolbar .x-button.x-button-decline.x-button-pressing:after,.x-toolbar .x-button.x-button-decline.x-button-pressed,.x-toolbar .x-button.x-button-decline.x-button-pressed:after,.x-toolbar .x-button.x-button-decline.x-button-active,.x-toolbar .x-button.x-button-decline.x-button-active:after,.x-button.x-button-decline-round.x-button-pressing,.x-button.x-button-decline-round.x-button-pressing:after,.x-button.x-button-decline-round.x-button-pressed,.x-button.x-button-decline-round.x-button-pressed:after,.x-button.x-button-decline-round.x-button-active,.x-button.x-button-decline-round.x-button-active:after,.x-toolbar .x-button.x-button-decline-round.x-button-pressing,.x-toolbar .x-button.x-button-decline-round.x-button-pressing:after,.x-toolbar .x-button.x-button-decline-round.x-button-pressed,.x-toolbar .x-button.x-button-decline-round.x-button-pressed:after,.x-toolbar .x-button.x-button-decline-round.x-button-active,.x-toolbar .x-button.x-button-decline-round.x-button-active:after,.x-button.x-button-decline-small.x-button-pressing,.x-button.x-button-decline-small.x-button-pressing:after,.x-button.x-button-decline-small.x-button-pressed,.x-button.x-button-decline-small.x-button-pressed:after,.x-button.x-button-decline-small.x-button-active,.x-button.x-button-decline-small.x-button-active:after,.x-toolbar .x-button.x-button-decline-small.x-button-pressing,.x-toolbar .x-button.x-button-decline-small.x-button-pressing:after,.x-toolbar .x-button.x-button-decline-small.x-button-pressed,.x-toolbar .x-button.x-button-decline-small.x-button-pressed:after,.x-toolbar .x-button.x-button-decline-small.x-button-active,.x-toolbar .x-button.x-button-decline-small.x-button-active:after{background-color:#b80505;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #860303), color-stop(10%, #9f0404), color-stop(65%, #b80505), color-stop(100%, #ba0505));background-image:-webkit-linear-gradient(#860303,#9f0404 10%,#b80505 65%,#ba0505);background-image:linear-gradient(#860303,#9f0404 10%,#b80505 65%,#ba0505)}.x-sheet,.x-sheet-action{padding:0.7em;border-top:1px solid #030507;height:auto;background-color:rgba(0, 0, 0, 0.9);background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(50,74,103,0.9)), color-stop(2%, rgba(12,17,24,0.9)), color-stop(100%, rgba(0,0,0,0.9)));background-image:-webkit-linear-gradient(rgba(50,74,103,0.9),rgba(12,17,24,0.9) 2%,rgba(0,0,0,0.9));background-image:linear-gradient(rgba(50,74,103,0.9),rgba(12,17,24,0.9) 2%,rgba(0,0,0,0.9));-webkit-border-radius:0;border-radius:0}.x-sheet-inner > .x-button,.x-sheet-action-inner > .x-button{margin-bottom:0.5em}.x-sheet-inner > .x-button:last-child,.x-sheet-action-inner > .x-button:last-child{margin-bottom:0}.x-sheet.x-picker{padding:0}.x-sheet.x-picker .x-sheet-inner{position:relative;background-color:#fff;-webkit-border-radius:0.4em;border-radius:0.4em;-webkit-background-clip:padding;background-clip:padding-box;overflow:hidden;margin:0.7em}.x-sheet.x-picker .x-sheet-inner:before,.x-sheet.x-picker .x-sheet-inner:after{z-index:1;content:"";position:absolute;width:100%;height:30%;top:0;left:0}.x-sheet.x-picker .x-sheet-inner:before{top:auto;-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em;bottom:0;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #bbbbbb));background-image:-webkit-linear-gradient(#ffffff,#bbbbbb);background-image:linear-gradient(#ffffff,#bbbbbb)}.x-sheet.x-picker .x-sheet-inner:after{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em;-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #bbbbbb), color-stop(100%, #ffffff));background-image:-webkit-linear-gradient(#bbbbbb,#ffffff);background-image:linear-gradient(#bbbbbb,#ffffff)}.x-sheet.x-picker .x-sheet-inner .x-picker-slot .x-body{border-left:1px solid #999999;border-right:1px solid #ACACAC}.x-sheet.x-picker .x-sheet-inner .x-picker-slot:first-child .x-body{border-left:0}.x-sheet.x-picker .x-sheet-inner .x-picker-slot:last-child .x-body{border-left:0;border-right:0}.x-picker-slot .x-scroll-view{z-index:2;position:relative;-webkit-box-shadow:rgba(0, 0, 0, 0.4) -1px 0 1px}.x-picker-slot .x-scroll-view:first-child{-webkit-box-shadow:none}.x-picker-mask{position:absolute;top:0;left:0;right:0;bottom:0;z-index:3;display:-webkit-box;display:box;-webkit-box-align:stretch;box-align:stretch;-webkit-box-orient:vertical;box-orient:vertical;-webkit-box-pack:center;box-pack:center;pointer-events:none}.x-picker-bar{border-top:0.12em solid #06346a;border-bottom:0.12em solid #06346a;height:2.5em;background-color:rgba(13, 117, 242, 0.3);background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(158,200,250,0.3)), color-stop(2%, rgba(47,137,244,0.3)), color-stop(100%, rgba(11,101,208,0.3)));background-image:-webkit-linear-gradient(rgba(158,200,250,0.3),rgba(47,137,244,0.3) 2%,rgba(11,101,208,0.3));background-image:linear-gradient(rgba(158,200,250,0.3),rgba(47,137,244,0.3) 2%,rgba(11,101,208,0.3));-webkit-box-shadow:rgba(0, 0, 0, 0.2) 0 0.2em 0.2em}.x-use-titles .x-picker-bar{margin-top:1.5em}.x-picker-slot-title{height:1.5em;position:relative;z-index:2;background-color:#345b89;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #85a7d1), color-stop(2%, #3e6ca3), color-stop(100%, #2a496f));background-image:-webkit-linear-gradient(#85a7d1,#3e6ca3 2%,#2a496f);background-image:linear-gradient(#85a7d1,#3e6ca3 2%,#2a496f);border-top:1px solid #345b89;border-bottom:1px solid #182a3f;-webkit-box-shadow:0px 0.1em 0.3em rgba(0, 0, 0, 0.3);padding:0.2em 1.02em}.x-picker-slot-title > div{font-weight:bold;font-size:0.8em;color:#0d1116;text-shadow:rgba(255, 255, 255, 0.25) 0 0.08em 0}.x-picker-slot .x-dataview-inner{width:100%}.x-picker-slot .x-dataview-item{vertical-align:middle;height:2.5em;line-height:2.5em;font-weight:bold;padding:0 10px}.x-picker-slot .x-picker-item{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.x-picker-right{text-align:right}.x-picker-center{text-align:center}.x-picker-left{text-align:left}.x-tabbar.x-docked-top{border-bottom:.1em solid;height:2.6em;padding:0 .8em}.x-tabbar.x-docked-top .x-tab{padding:0.4em 0.8em;height:1.8em;-webkit-border-radius:0.9em;border-radius:0.9em}.x-tabbar.x-docked-top .x-button-label,.x-tabbar.x-docked-top .x-hasbadge .x-badge,.x-hasbadge .x-tabbar.x-docked-top .x-badge{font-size:.8em;line-height:1.2em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}.x-tabbar.x-docked-bottom{border-top:.1em solid;height:3em;padding:0}.x-tabbar.x-docked-bottom .x-tab{-webkit-border-radius:0.25em;border-radius:0.25em;min-width:3.3em;position:relative;padding-top:.2em}.x-tabbar.x-docked-bottom .x-tab .x-button-icon{-webkit-mask-size:1.65em;width:1.65em;height:1.65em;display:block;margin:0 auto;position:relative}.x-tabbar.x-docked-bottom .x-tab .x-button-label,.x-tabbar.x-docked-bottom .x-tab .x-hasbadge .x-badge,.x-hasbadge .x-tabbar.x-docked-bottom .x-tab .x-badge{margin:0;padding:.1em 0 .2em 0;font-size:9px;line-height:12px;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}.x-tab .x-button-icon.bookmarks,.x-button .x-button-icon.x-icon-mask.bookmarks{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.download,.x-button .x-button-icon.x-icon-mask.download{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.favorites,.x-button .x-button-icon.x-icon-mask.favorites{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAFfUlEQVRoBd2aXahVRRTHz/Ujv+2mZRGZB7W6mtpFikC7+UWUZiqBD0JPFdRL1EMFPfjoU4baS0FUD/UWZBEVShA+BCpmWApRSkgllNpDmZWZt9//eOay72afvWfWOTPn3rvgz8yeWbPW+s/XmT379AwODtZSSQ+CryVgA/gVfIx/pelEhFMBVlvBOaBeFo6Cean8y09KsnMg932TqCOs9M2UhMfhMJVsxtHcAmcbmekLCsqjFKUkvAYG1xSwmEHZqoLyKEVJCDOCNxH9HUCbVl6mULAuXxjrOQlhgl8Bbi0h0Uen3FBS37GqVIQHiHh2SdR16jTlo0t0woycpuxiUDSdHcFeMv3uIWYanTDB3wIWVZBQHP10zuQKvbarUxDWT1HRz1E++Ds99fLtgp6jEmbExhPNcs+IbkZPiCpRCRP5TPCQJ4MJ6A3QSUqjSWzC2ozuC4j+fnSnB+gHq8YmvJKIJgVEpRPX9QH6waqxCa8PjEhHT981H2j6qno0wqzF63BhOUxsom3Zb7aJqGsUjTAONFJlpysXQz7VuXpavrBTzzEJaz1adlzNjHs6RTBvJyZhjZTF/kTaWZZCnlvhsyWgQkPZQpagzsX1bFlAXjGtDdAPUu1p3PPQhCCXkdwG/mta0PWLds060AuAnqtEOjpdbQR3VymX1P9F3UfgGJA9X9F92c/ADaQ2P8V0DJ4/kDbeYKaSvgI2AN0+OGJK1VAbSIhTOXEOybYll2kte77yD4rqrHyb85S9Cl4HtReAyI11/A7HpRq5PSD6oR0f3Rad+H7S1DvV7UgS+tc1cU3n3V/AWJ/SX8BxVuMinow2rNNjlPQVeH0GFg378kDBfLAPXARjZbTPwmUXmOG+bgz71EKFfqKeAUWfREZbJxyCxyOOqEuHER4qrNUWovwy0CFktBHV4eNZMNvxyaaFhKWAaBt/HJwEo4W0luSKLMF8viVhp4iBeeBd8CcYqcQ1qi+CKS7uVmklYdcQY0+C42Ckkf6EmO51cVal3oRlCFkCdKgfCWtbo7obDO3AVWQbHHyUsjo40E6uq9cvQbdG+wN892fj8s0HjXDWKA51/t4JUo72H/jTDtybjSUkbyYsJ0gdfAtSjfTn+JoWQjCv2+57a4M1QaQSvZvrMsIs7RJejGcdUlLJUhzpZsYsZsJcCen6ZwCE3IaYA2021OfUdU3fJltmwni7Fvh+KDMF16KR3ux0lWuSdgjPxeNdJq/tNdKNqJaSSUyEmVK6JNPomtqbIh3eSKNsEmvAarfJ5LEzjbbR59MtpqyEb8eZjpndkhtxvNri3Er4YZxpx+yW6Jdhi8V5MOHm+n0QZ9afo0u0fQO8A5S3iPaQ1cTSG9w4f/SqesZBH/gRWI6T+gyyxfkgvw2cMdrS+/lTzpZvGnyWxsnTwHLRd4R2a/OBqQyoztKBe/P2qp6DCBOUptKHhuA+pU1fq2Co0/F0L9CVaghxXTbWW9ktKg8lrFfCrwODeh/9wgu1bEDo6OT2Fvgb+JLWq+nQEsnaa5UPJbwKBxc8A9KXPG1O3u+u6E4F24GvD3XMDjCxFcF8uTdhjGpHfwn49L42lCeAdyDZwGi3HpwAPr6+Q29htn1ZPoSwfuz3ewShXVcBNz62lzkvq6O9DjZHgQ9p72kdQljvob9VBPAN9Q+UEQmpw5b+Sf8e0FotI/4a9ZN8bIcQXlnh9AD1y3ychuhgU0tpJyhb14epn+ljN+Sk9S9G1ct50d8SdgF9x9EO3lHB5hXwPEYfA8dbGD9LuWZBtfj0inSQWUDTKzu1dAB5Dkz2tdOOHn70LvwVyMag/FYwzse295Rukq5j+G1wEOib66PAy5FPMD46+NPmqTV7CpwGGvkJPm2l8z8GWDNDloqpGQAAAABJRU5ErkJggg==')}.x-tab .x-button-icon.info,.x-button .x-button-icon.x-icon-mask.info{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.more,.x-button .x-button-icon.x-icon-mask.more{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAADJ0lEQVRoBe2YS2sUQRSFp5MgvmLU+CAMiBJFDBHcCeoPEFciuHMjroMK4lZBcONG0JW60U1UEgRx59IXuNMoKEElKL7GRwyIqNHxO0N66FT3UNU9IHRNFXz0VNW5t+vW6RcT1ev1Sie1rk4qVrWGgn13PDgcHPZsB8Il7ZmhqXKCw6kt8WwgOOyZoalygsOpLfFsIDjsmaGpcoLDqS3xbCA47JmhqXKCw6kt8Wyg6XAURV2wEy7BM5iFtzAKu2BB0dqJ7YEtcBYmQblfwzjshUVt5O4mfhjOwwQodw3GYA8snpd77n9pFXMYvoP+qDaZZewcVKXPAzE64Qn4CmZe9f/AFSiSu4e4IzANrXJfZ24gXjO/KxEcg9+QFZQcU/CSONh2RKsraMQhr85xE/psOeN5tCr2APyA5Bqzfl9D06tYtX3wC7KE5pg2ZX98UtsR7XZo5ayZW/1DENnyzi18CO1nyMqTNXYcrTapcitHkBLJiZW2RaGRuxcg6+Stxu6i73fI3Y3uZM7cU+hXQeVvzsBP6Dc5LupxztzaiEGH3AvR3S+Qe4dc0D2cp/Uj1oPI1pR7g030n+erWlTe9pMA3cu2Jre+2ERtzBdZe01BL3Ke9Al6vQZsTbfKQ5vImH9PXxtqa3qVPbWJjHk94J6r4DPGhK17A8EHm4j7UAWP2nTG/GX6NWMs1SW3rrCroLeLaxtDqDdG4368zbHVkzM5Polus+2hEs+j7YNxx9zv0FkfhoncvegvOuZ+iW6rYhtfTXTWgV7OyeLM3w+Y3xaf0PVIzAqwFf0IzW7XnLGOmLUg58y1JvsTzA83Y5o/eLcyMQISJAN0z56G9bE275HYNXAU7kAy9xv6p2Bj3pyxntjVcBDuQTL3FH19Dg/FWh0bXzUMNhsf23JkOQzCK9B1P4NY39OFG3kjgpeB8g/AR/gG0+3mJkeF9Lp9lkIVZkDfC1r3vPs8VTAir1uRd1mpNyQUXGr7HBYfHHbYpFJLgsOlts9h8cFhh00qtSQ4XGr7HBYfHHbYpFJLgsOlts9h8cFhh00qtSQ4XGr7HBYfHHbYpFJLOs7hf5j4Vg3iLoGkAAAAAElFTkSuQmCC')}.x-tab .x-button-icon.time,.x-button .x-button-icon.x-icon-mask.time{-webkit-mask-image:url('data:image/png;base64,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')}.x-tab .x-button-icon.user,.x-button .x-button-icon.x-icon-mask.user{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAEWElEQVRoBe2aS0gVYRiGO1lmF8nQQlETutGFokAiqEV0ISKwgmrdMtzUpnW7drWKbFGbQAKpJIhuUGIUFUkW0T1Jq4V2U4ui7GLPexpDD+ecuX1jHqcPHseZ+f9vvnf++e8n0d/fPyZONjZOYqU1doLHRV3CiURCz5gMxTANJsJg+8XJJ+iBt9BHNdO1SCwRZR1GbAFRl8F8WAFLoRwGLME/ffAM7kETvIYPxPWDo7lFIhiheURaCVtgBywHXXOzbhJcggZoRvR7twy+76uELSEAtQsqySPwGdQN+KWDPHuh2DI2+TIVm3T455M9G0Bk6ktRvd4NBZaiTQUT3AQnSNW/VAFBzl/iZw0kq56FcOtuaQHB7QIv9ZVkrqZ2YA9Mck3pMYGZYKeh2sBz1SJb2mqcmfk0E0xQ6l9rwNoKcWjm11JwEYFVW6t1/K218mspeB5B5VsFluKnIuU88Kml4PGBo3DPqBGZiVkKNgvKRFkGJ5aCv2Z4xoi6bCm4DWUaXERhZhMJS8FfolDq+DSbRFgKjrIOa8poYpaCTQKK2sl/wSHfcFSNlll1sSzhn7ys3pAvLFP275lu+L1uKVhBPfYbgMf0zz2mc01mKfgbT7vi+kT/CeT3sv9s6XNYCtbg4CJ0pX9U4Kv3yXk3cO6UjGaCWX5Rg/UArqY8I8yp1qdPQ08YJ4Pzmgl2nCqwc2DVyKjunuddqkE0MVPBBKYSuQ7tJtEhFj9apDczU8FOVB0ctZiuHYUw9obMjbxErW2bmblgApTQengVIkq1B83QEsJH2qzmgp2n3ObYCEGndZ3krbcuXcUWiWACldCjoA0yv6a8J6HJb0Yv6SMRrAcj+gmHA+B3aneDPHXk/8jR3LR3a2rOfnAlTmfDVPDb6Khrq8bPDI5PoRPxZpMSk+1SgtOKpTa8l8BC0JaLmAkloA1xr/aOhJqEtINGWeqW7jjHXrQHbRdw4WxSJf8L8Aeh2m1QaWoBfiUsA61PTwGtUYeZ1qlP1zhan3YraBSnz/0mdAUVHqiEESoxKs0a2AxloJIMI5DsWU0vQH2z2oZToAnFI7+fu2/BiF3PgzbCKqgC1bXhNH3S6rba4BocR7TquifzLBih5XjcCSrROaAGKbJWHt9uJuGq67fgAki4zrNaVsGIzCP3dNgE20B1VJ+uro8UUz3Xr39UvxugCeEZl3UzCkZsBZn1+W6HRaB6qtZ4pJp2PtTna+58DFoR3sVxqHFxyM8euFsIW6EeXoDeoPrBXEEbAlpqqoN1kD9YY6rYxSQ4DGoE9KOSXBGZLk4NYB7CfigZEP1XMBfVEJ0BJUznIFevaSBzEEolOimYkyo4AfocclVYtrjViB0C9SzJEdE+jrn+CWcTrHvdUKuRUSm0gPrZ0W7tGjjMhTiIVWFWSbAGEnGxhAT/y+HhsL9oiVWFjo3FqnRVqrETrG5pFmiSEAuTYC3TFMVCLSIzTg9H6wuIXR2OneDfMJq1NmzzbS8AAAAASUVORK5CYII=')}.x-tab .x-button-icon.team,.x-button .x-button-icon.x-icon-mask.team{-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAFI0lEQVRoBe2ZSYgdVRSG+yUmnagRQYU4NbZKNLYKWTgg4gQOaDYqJIIGl4LixhBwoy50LSIiulEjCkpAUBBRURpdGceFMQ7YtgkOJE4xTjGa9vuedUl1Vd2qevSrFqvrwJ97695zzj3/PXd6nd7MzMzIQpJFC4msXDvCbc94l+Euwy2bgW5JtyyhOTpdhnNT0rKGLsMtS2iOTpfh3JS0rOGQ+eLT6/VWMNYJ4NjUmN9T/xLs4WfqvPxO7TU9DkTdNmvBbeAskJ7kv/n+AjwKXiSW7yibFQk3BSIPZHdTl5xZzML238DDYFlTsQS/jZF1AGQ1mAZZkkXfe9FbGwJrqmz6lL4cEmOgjhyO0jq2gGVj0hhhAl9M1FeB3gDRn4Pu/5NwQnJ0ALKqrgKHDmgzkHpjGR4oioPKP1H96+Dn8GvpKyLqneV5Lp0XgnHggTMFJjlYPqAcpnyLsz/LHBLL0fRfCzwbvNN3gLeI5WXKaik7DbF2/20A28HPYF+CPZQfg9tj9vS5h18DRSdyrO0j9FeW+PQenwTe138AJ+d34OPFa215zDa0l15LOLgamM0DIBukbQ60JjhLl7RL+HWQtSv7jhLGz1FgM3DJZ30Yy69gYzqGonrVHr4eJ+OgB7Ji2xi4lGUW8+PsD0vOwNGNwInMirF42K0nlmXZzvR3LNARDN3fx6WVI3VJF50Fzvr7EZtY8zQdLtUiOYXGIrJpXUmvTDdk61HCKEqiagD9SSwnLCeX3RYwSJafRd/zoUj2FzVm2hyzMJ6gV0Y46Myl/BzjeqfnyMg36G5NJqpoTPvnLGWEnS0f9lVStL/7NgT/C5XNoHTW6XesV4En/1wlGo+Oo4QJ1ivoxxqju+fKCG2lf1uFH7P3eEl2K8xndRt3VKKEE4sPKWOHiCreg28TaPR1RN/X6GwEO0GReJ3cg95kUWeqzT8W6KtMpujcVaZQRfgFjL8qcbCDvndi/Zz0h4Hr6L8JHBHRW0L7DejdAU6K6Nj8CfBQi4mH4xYmrmy1sXlK/gCAAyfkQaAT91kWj9HW/6tJ8MO3NmeC+4CHlqdu1q7o25Xk5Hqynw+WBp+hpO1K4JItsnfr5GyCbSirCHstnQpcKulBXMK+o1frCPGgWAomwL2gLsm0z3S9ny38XARWgEXJOI7xNMiS9ns9MN5ZCQhEQ1lIGCOXmZf4ZeAW8C4IAblv3wBXAIn6sjkZ3Arc80FvGKW/nu4H/nhZDiR0IngI+LYPY3i43gWuAeNgFBQSn0UYJZejRH3CPQ8cMDi19Jp6AviuVfd48ADwRZXWG3Z9J/6fApeAJUm2TYRE02OZjPfA3WAM9HVDdvt2iXHI1HkoPQd2g7SjUHef+NyU7AXgFRD65qOcZrybQXgFmtUDIDu2xE3CBuCWWBxIU+8vk9MozdQukDUO3x4qm5IJOp36ZyW6waaJci/jrkviWEV9qiQOdd8Ebr/+T0fKkYvBp6AqOB2fnQz0SA39Kn9z6Z9mfPeze/UlUOXrB3Q2AW36a77KwP7tYCwh7Mupjk1TOmZuNInlyZqxuN8n3ItrQF1xryvRl9W/3Y3/60QGCTGF71h5JB0Tbn7vsDqyP6Vkva5dymxoVQ+lIE6+3+lJCH3Zcp+E78y2Fny7Evw7kstC8YA7BtQZRP1hiwTDKnuGun8aSiekaDxXwrbG/zOtaOT/ss3MLSjpCLc93V2Guwy3bAa6Jd2yhObodBnOTUnLGroMtyyhOTpdhnNT0rKGfwD3f6JVZi/xSQAAAABJRU5ErkJggg==')}.x-tabbar-light{background-color:#475c76;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #96a9c0), color-stop(2%, #546e8c), color-stop(100%, #394b5f));background-image:-webkit-linear-gradient(#96a9c0,#546e8c 2%,#394b5f);background-image:linear-gradient(#96a9c0,#546e8c 2%,#394b5f);border-color:#3d5066}.x-tabbar-light .x-tab{color:#b6c3d3}.x-tabbar-light .x-tab-active{color:white}.x-tabbar-light .x-tab-pressed{color:white}.x-tabbar-light.x-docked-bottom .x-tab{text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-tabbar-light.x-docked-bottom .x-tab .x-button-icon{background-color:#768fad;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #d5dde6), color-stop(2%, #8ca1ba), color-stop(100%, #607d9f));background-image:-webkit-linear-gradient(#d5dde6,#8ca1ba 2%,#607d9f);background-image:linear-gradient(#d5dde6,#8ca1ba 2%,#607d9f)}.x-tabbar-light.x-docked-bottom .x-tab-active{background-color:#506986;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #a6b6c9), color-stop(2%, #5e7a9c), color-stop(100%, #43576f));background-image:-webkit-linear-gradient(#a6b6c9,#5e7a9c 2%,#43576f);background-image:linear-gradient(#a6b6c9,#5e7a9c 2%,#43576f);text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-tabbar-light.x-docked-bottom .x-tab-active .x-button-icon{background-color:#003370;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0056bd), color-stop(50%, #003f8a), color-stop(51%, #003370), color-stop(100%, #002757));background-image:-webkit-linear-gradient(#0056bd,#003f8a 50%,#003370 51%,#002757);background-image:linear-gradient(#0056bd,#003f8a 50%,#003370 51%,#002757)}.x-tabbar-light.x-docked-top .x-tab-active{background-color:#3d5066;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2a3746), color-stop(10%, #344356), color-stop(65%, #3d5066), color-stop(100%, #3e5167));background-image:-webkit-linear-gradient(#2a3746,#344356 10%,#3d5066 65%,#3e5167);background-image:linear-gradient(#2a3746,#344356 10%,#3d5066 65%,#3e5167);color:white}.x-tabbar-dark{background-color:#141e29;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #466890), color-stop(2%, #1f2f41), color-stop(100%, #080c11));background-image:-webkit-linear-gradient(#466890,#1f2f41 2%,#080c11);background-image:linear-gradient(#466890,#1f2f41 2%,#080c11);border-color:#0c1118}.x-tabbar-dark .x-tab{color:#5a81af}.x-tabbar-dark .x-tab-active{color:white}.x-tabbar-dark .x-tab-pressed{color:white}.x-tabbar-dark.x-docked-bottom .x-tab{text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-tabbar-dark.x-docked-bottom .x-tab .x-button-icon{background-color:#354f6e;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #7c9bc0), color-stop(2%, #416086), color-stop(100%, #293e56));background-image:-webkit-linear-gradient(#7c9bc0,#416086 2%,#293e56);background-image:linear-gradient(#7c9bc0,#416086 2%,#293e56)}.x-tabbar-dark.x-docked-bottom .x-tab-active{background-color:#1c2a3a;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4e74a2), color-stop(2%, #283b52), color-stop(100%, #111922));background-image:-webkit-linear-gradient(#4e74a2,#283b52 2%,#111922);background-image:linear-gradient(#4e74a2,#283b52 2%,#111922);text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-tabbar-dark.x-docked-bottom .x-tab-active .x-button-icon{background-color:#0a7aff;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #57a3ff), color-stop(50%, #2488ff), color-stop(51%, #0a7aff), color-stop(100%, #006df0));background-image:-webkit-linear-gradient(#57a3ff,#2488ff 50%,#0a7aff 51%,#006df0);background-image:linear-gradient(#57a3ff,#2488ff 50%,#0a7aff 51%,#006df0)}.x-tabbar-dark.x-docked-top .x-tab-active{background-color:#0c1118;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #000000), color-stop(10%, #030507), color-stop(65%, #0c1118), color-stop(100%, #0c121a));background-image:-webkit-linear-gradient(#000000,#030507 10%,#0c1118 65%,#0c121a);background-image:linear-gradient(#000000,#030507 10%,#0c1118 65%,#0c121a);color:white}.x-tab.x-item-disabled span.x-button-label,.x-tab.x-item-disabled .x-hasbadge span.x-badge,.x-hasbadge .x-tab.x-item-disabled span.x-badge,.x-tab.x-item-disabled .x-button-icon{opacity:.5}.x-tab.x-draggable{opacity:.7}.x-tab{-webkit-user-select:none;overflow:visible !important}.x-toolbar{padding:0 0.2em;overflow:hidden;position:relative;height:2.6em}.x-toolbar > *{z-index:1}.x-toolbar.x-docked-top{border-bottom:.1em solid}.x-toolbar.x-docked-bottom{border-top:.1em solid}.x-toolbar.x-docked-left{width:7em;height:auto;padding:0.2em;border-right:.1em solid}.x-toolbar.x-docked-right{width:7em;height:auto;padding:0.2em;border-left:.1em solid}.x-title{line-height:2.1em;font-size:1.2em;text-align:center;font-weight:bold;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0 0.3em;max-width:100%}.x-title .x-innerhtml{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:0 .3em}.x-toolbar-dark{background-color:#24364c;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5a81af), color-stop(2%, #304864), color-stop(100%, #192533));background-image:-webkit-linear-gradient(#5a81af,#304864 2%,#192533);background-image:linear-gradient(#5a81af,#304864 2%,#192533);border-color:black}.x-toolbar-dark .x-title{color:white;text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-toolbar-dark.x-docked-top{border-bottom-color:black}.x-toolbar-dark.x-docked-bottom{border-top-color:black}.x-toolbar-dark.x-docked-left{border-right-color:black}.x-toolbar-dark.x-docked-right{border-left-color:black}.x-toolbar-dark .x-button,.x-toolbar .x-toolbar-dark .x-button,.x-toolbar-dark .x-field-select .x-component-outer,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer,.x-toolbar-dark .x-field-select .x-component-outer:before,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before{border:1px solid black;border-top-color:black;color:white}.x-toolbar-dark .x-button.x-button-back:before,.x-toolbar-dark .x-button.x-button-forward:before,.x-toolbar .x-toolbar-dark .x-button.x-button-back:before,.x-toolbar .x-toolbar-dark .x-button.x-button-forward:before,.x-toolbar-dark .x-field-select .x-component-outer.x-button-back:before,.x-toolbar-dark .x-field-select .x-component-outer.x-button-forward:before,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-back:before,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-forward:before,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-back:before,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-forward:before,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-back:before,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-forward:before{background:black}.x-toolbar-dark .x-button,.x-toolbar-dark .x-button.x-button-back:after,.x-toolbar-dark .x-button.x-button-forward:after,.x-toolbar .x-toolbar-dark .x-button,.x-toolbar .x-toolbar-dark .x-button.x-button-back:after,.x-toolbar .x-toolbar-dark .x-button.x-button-forward:after,.x-toolbar-dark .x-field-select .x-component-outer,.x-toolbar-dark .x-field-select .x-component-outer.x-button-back:after,.x-toolbar-dark .x-field-select .x-component-outer.x-button-forward:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-back:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-forward:after,.x-toolbar-dark .x-field-select .x-component-outer:before,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-back:after,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-forward:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-back:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-forward:after{background-color:#141e29;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #466890), color-stop(2%, #1f2f41), color-stop(100%, #080c11));background-image:-webkit-linear-gradient(#466890,#1f2f41 2%,#080c11);background-image:linear-gradient(#466890,#1f2f41 2%,#080c11)}.x-toolbar-dark .x-button .x-button-icon.x-icon-mask,.x-toolbar .x-toolbar-dark .x-button .x-button-icon.x-icon-mask,.x-toolbar-dark .x-field-select .x-component-outer .x-button-icon.x-icon-mask,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer .x-button-icon.x-icon-mask,.x-toolbar-dark .x-field-select .x-component-outer:before .x-button-icon.x-icon-mask,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before .x-button-icon.x-icon-mask{background-color:white;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #ffffff), color-stop(100%, #e7edf3));background-image:-webkit-linear-gradient(#ffffff,#ffffff 2%,#e7edf3);background-image:linear-gradient(#ffffff,#ffffff 2%,#e7edf3)}.x-toolbar-dark .x-button.x-button-pressing,.x-toolbar-dark .x-button.x-button-pressing:after,.x-toolbar-dark .x-button.x-button-pressed,.x-toolbar-dark .x-button.x-button-pressed:after,.x-toolbar-dark .x-button.x-button-active,.x-toolbar-dark .x-button.x-button-active:after,.x-toolbar .x-toolbar-dark .x-button.x-button-pressing,.x-toolbar .x-toolbar-dark .x-button.x-button-pressing:after,.x-toolbar .x-toolbar-dark .x-button.x-button-pressed,.x-toolbar .x-toolbar-dark .x-button.x-button-pressed:after,.x-toolbar .x-toolbar-dark .x-button.x-button-active,.x-toolbar .x-toolbar-dark .x-button.x-button-active:after,.x-toolbar-dark .x-field-select .x-component-outer.x-button-pressing,.x-toolbar-dark .x-field-select .x-component-outer.x-button-pressing:after,.x-toolbar-dark .x-field-select .x-component-outer.x-button-pressed,.x-toolbar-dark .x-field-select .x-component-outer.x-button-pressed:after,.x-toolbar-dark .x-field-select .x-component-outer.x-button-active,.x-toolbar-dark .x-field-select .x-component-outer.x-button-active:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-pressing,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-pressing:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-pressed,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-pressed:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-active,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer.x-button-active:after,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressing,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressing:after,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressed,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressed:after,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-active,.x-toolbar-dark .x-field-select .x-component-outer:before.x-button-active:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressing,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressing:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressed,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-pressed:after,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-active,.x-toolbar .x-toolbar-dark .x-field-select .x-component-outer:before.x-button-active:after{background-color:#0f161f;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #000000), color-stop(10%, #070a0e), color-stop(65%, #0f161f), color-stop(100%, #101721));background-image:-webkit-linear-gradient(#000000,#070a0e 10%,#0f161f 65%,#101721);background-image:linear-gradient(#000000,#070a0e 10%,#0f161f 65%,#101721)}.x-toolbar-dark .x-form-label{color:white;text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-toolbar-light{background-color:#354f6e;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #7c9bc0), color-stop(2%, #416086), color-stop(100%, #293e56));background-image:-webkit-linear-gradient(#7c9bc0,#416086 2%,#293e56);background-image:linear-gradient(#7c9bc0,#416086 2%,#293e56);border-color:black}.x-toolbar-light .x-title{color:white;text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-toolbar-light.x-docked-top{border-bottom-color:black}.x-toolbar-light.x-docked-bottom{border-top-color:black}.x-toolbar-light.x-docked-left{border-right-color:black}.x-toolbar-light.x-docked-right{border-left-color:black}.x-toolbar-light .x-button,.x-toolbar .x-toolbar-light .x-button,.x-toolbar-light .x-field-select .x-component-outer,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer,.x-toolbar-light .x-field-select .x-component-outer:before,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before{border:1px solid #030507;border-top-color:#0c1118;color:white}.x-toolbar-light .x-button.x-button-back:before,.x-toolbar-light .x-button.x-button-forward:before,.x-toolbar .x-toolbar-light .x-button.x-button-back:before,.x-toolbar .x-toolbar-light .x-button.x-button-forward:before,.x-toolbar-light .x-field-select .x-component-outer.x-button-back:before,.x-toolbar-light .x-field-select .x-component-outer.x-button-forward:before,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-back:before,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-forward:before,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-back:before,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-forward:before,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-back:before,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-forward:before{background:#030507}.x-toolbar-light .x-button,.x-toolbar-light .x-button.x-button-back:after,.x-toolbar-light .x-button.x-button-forward:after,.x-toolbar .x-toolbar-light .x-button,.x-toolbar .x-toolbar-light .x-button.x-button-back:after,.x-toolbar .x-toolbar-light .x-button.x-button-forward:after,.x-toolbar-light .x-field-select .x-component-outer,.x-toolbar-light .x-field-select .x-component-outer.x-button-back:after,.x-toolbar-light .x-field-select .x-component-outer.x-button-forward:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-back:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-forward:after,.x-toolbar-light .x-field-select .x-component-outer:before,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-back:after,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-forward:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-back:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-forward:after{background-color:#24364c;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5a81af), color-stop(2%, #304864), color-stop(100%, #192533));background-image:-webkit-linear-gradient(#5a81af,#304864 2%,#192533);background-image:linear-gradient(#5a81af,#304864 2%,#192533)}.x-toolbar-light .x-button .x-button-icon.x-icon-mask,.x-toolbar .x-toolbar-light .x-button .x-button-icon.x-icon-mask,.x-toolbar-light .x-field-select .x-component-outer .x-button-icon.x-icon-mask,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer .x-button-icon.x-icon-mask,.x-toolbar-light .x-field-select .x-component-outer:before .x-button-icon.x-icon-mask,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before .x-button-icon.x-icon-mask{background-color:white;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #ffffff), color-stop(100%, #e7edf3));background-image:-webkit-linear-gradient(#ffffff,#ffffff 2%,#e7edf3);background-image:linear-gradient(#ffffff,#ffffff 2%,#e7edf3)}.x-toolbar-light .x-button.x-button-pressing,.x-toolbar-light .x-button.x-button-pressing:after,.x-toolbar-light .x-button.x-button-pressed,.x-toolbar-light .x-button.x-button-pressed:after,.x-toolbar-light .x-button.x-button-active,.x-toolbar-light .x-button.x-button-active:after,.x-toolbar .x-toolbar-light .x-button.x-button-pressing,.x-toolbar .x-toolbar-light .x-button.x-button-pressing:after,.x-toolbar .x-toolbar-light .x-button.x-button-pressed,.x-toolbar .x-toolbar-light .x-button.x-button-pressed:after,.x-toolbar .x-toolbar-light .x-button.x-button-active,.x-toolbar .x-toolbar-light .x-button.x-button-active:after,.x-toolbar-light .x-field-select .x-component-outer.x-button-pressing,.x-toolbar-light .x-field-select .x-component-outer.x-button-pressing:after,.x-toolbar-light .x-field-select .x-component-outer.x-button-pressed,.x-toolbar-light .x-field-select .x-component-outer.x-button-pressed:after,.x-toolbar-light .x-field-select .x-component-outer.x-button-active,.x-toolbar-light .x-field-select .x-component-outer.x-button-active:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-pressing,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-pressing:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-pressed,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-pressed:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-active,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer.x-button-active:after,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressing,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressing:after,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressed,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressed:after,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-active,.x-toolbar-light .x-field-select .x-component-outer:before.x-button-active:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressing,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressing:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressed,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-pressed:after,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-active,.x-toolbar .x-toolbar-light .x-field-select .x-component-outer:before.x-button-active:after{background-color:#1f2f41;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0f161f), color-stop(10%, #172330), color-stop(65%, #1f2f41), color-stop(100%, #203043));background-image:-webkit-linear-gradient(#0f161f,#172330 10%,#1f2f41 65%,#203043);background-image:linear-gradient(#0f161f,#172330 10%,#1f2f41 65%,#203043)}.x-toolbar-light .x-form-label{color:white;text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-navigation-bar .x-container{overflow:visible}.x-desktop .x-toolbar .x-field-search{padding-left:1.06em}.x-spinner .x-input-el,.x-field-select .x-input-el{-webkit-text-fill-color:#000;-webkit-opacity:1}.x-spinner.x-item-disabled .x-input-el,.x-field-select.x-item-disabled .x-input-el{-webkit-text-fill-color:currentcolor}.x-toolbar .x-field-select .x-input-el{-webkit-text-fill-color:#fff}.x-toolbar .x-field-select.x-item-disabled .x-input-el{-webkit-text-fill-color:rgba(255, 255, 255, 0.6)}.x-toolbar .x-form-field-container{padding:0 .3em}.x-toolbar .x-field{width:13em;margin:.5em;min-height:0;border-bottom:0}.x-toolbar .x-field .x-clear-icon{background-size:50% 50%;right:-0.8em;margin-top:-1.06em}.x-toolbar .x-field-input{padding-right:1.6em !important}.x-toolbar .x-field-textarea .x-component-outer,.x-toolbar .x-field-text .x-component-outer,.x-toolbar .x-field-number .x-component-outer,.x-toolbar .x-field-search .x-component-outer{-webkit-border-radius:0.3em;border-radius:0.3em;background-color:white;-webkit-box-shadow:inset rgba(0, 0, 0, 0.5) 0 0.1em 0, inset rgba(0, 0, 0, 0.5) 0 -0.1em 0, inset rgba(0, 0, 0, 0.5) 0.1em 0 0, inset rgba(0, 0, 0, 0.5) -0.1em 0 0, inset rgba(0, 0, 0, 0.5) 0 0.15em 0.4em}.x-toolbar .x-form-label{background:transparent;border:0;padding:0;line-height:1.4em}.x-toolbar .x-form-field{height:1.6em;color:#6e6e6e;background:transparent;min-height:0;-webkit-appearance:none;padding:0em .3em;margin:0}.x-toolbar .x-form-field:focus{color:black}.x-toolbar .x-field-select .x-component-outer,.x-toolbar .x-field-search .x-component-outer{-webkit-border-radius:0.8em;border-radius:0.8em}.x-toolbar .x-field-search .x-field-input{background-position:.5em 50%}.x-toolbar .x-field-select{-webkit-box-shadow:none}.x-toolbar .x-field-select .x-form-field{height:1.4em}.x-toolbar .x-field-select{background:transparent}.x-toolbar .x-field-select .x-component-outer:after{right:.4em}.x-toolbar .x-field-select.x-item-disabled .x-component-outer:after{opacity:.6}.x-toolbar .x-field-select .x-component-outer:before{width:3em;border-left:none;-webkit-border-top-right-radius:0.8em;border-top-right-radius:0.8em;-webkit-border-bottom-right-radius:0.8em;border-bottom-right-radius:0.8em;-webkit-mask:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAABCAYAAACc0f2yAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADJJREFUeNpi/P//PwMjIyMbAwMDOxRzAjEXFHMDMQ8a5kXC6HLcSHo5kcwEmU9TABBgAOcTBAFcRiSpAAAAAElFTkSuQmCC');-webkit-mask-position:right top;-webkit-mask-repeat:repeat-y;-webkit-mask-size:3em 0.05em}.x-toolbar .x-field-select .x-input-text{color:#fff}.x-android .x-field-search .x-field-input{padding-left:.2em !important;padding-right:2.2em !important}.x-indexbar-wrapper{-webkit-box-pack:end !important;box-pack:end !important;pointer-events:none}.x-indexbar-vertical{width:1.1em;-webkit-box-orient:vertical;box-orient:vertical;margin-right:8px}.x-indexbar-horizontal{height:1.1em;-webkit-box-orient:horizontal;box-orient:horizontal;margin-bottom:8px}.x-indexbar{pointer-events:auto;z-index:2;padding:.3em 0;min-height:0 !important;height:auto !important;-webkit-box-flex:0 !important}.x-indexbar > div{color:#1e2a38;font-size:0.6em;text-align:center;line-height:1.1em;font-weight:bold;display:block}.x-phone.x-landscape .x-indexbar > div{font-size:0.38em;line-height:1em}.x-indexbar-pressed{-webkit-border-radius:0.55em;border-radius:0.55em;background-color:rgba(143, 152, 163, 0.8)}.x-list{position:relative;background-color:#f7f7f7}.x-list .x-list-inner{width:100%}.x-list .x-list-disclosure{position:absolute;bottom:0.44em;right:0.44em}.x-list .x-list-disclosure{overflow:visible;-webkit-mask:0 0 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpFNkNCM0JGNTZFMjI2ODExQkNGQjkwMzk3MDc3MkZFQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3M0MzQUU1QUFDQkQxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3M0MzQUU1OUFDQkQxMURGOEQ2MUVDMjM0MzY2NTBDQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU3Q0IzQkY1NkUyMjY4MTFCQ0ZCOTAzOTcwNzcyRkVCIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2Q0IzQkY1NkUyMjY4MTFCQ0ZCOTAzOTcwNzcyRkVCIi8+IDwvcmRmOkRlc2NyaXB0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') no-repeat;-webkit-mask-size:1.7em;background-color:#003370;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0a7aff), color-stop(2%, #004394), color-stop(100%, #00234c));background-image:-webkit-linear-gradient(#0a7aff,#004394 2%,#00234c);background-image:linear-gradient(#0a7aff,#004394 2%,#00234c);width:1.7em;height:1.7em}.x-list.x-list-indexed .x-list-disclosure{margin-right:1em}.x-list .x-item-selected .x-list-disclosure{background:#fff none}.x-list .x-list-item{position:relative;color:black}.x-list .x-list-item .x-list-item-label{min-height:2.6em;padding:0.7em 0.8em}.x-list .x-list-item.x-item-pressed .x-list-item-label{background:#77b2f8 none}.x-list .x-list-item.x-item-selected .x-list-item-label{background-color:#06346a;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #167bf3), color-stop(2%, #07448c), color-stop(100%, #042348));background-image:-webkit-linear-gradient(#167bf3,#07448c 2%,#042348);background-image:linear-gradient(#167bf3,#07448c 2%,#042348);color:white;text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-list-header{position:relative}.x-list-header-swap{position:absolute;left:0;width:100%;z-index:1}.x-ios .x-list-header-swap{-webkit-transform:translate3d(0, 0, 0)}.x-list-normal .x-list-header{background-color:#4d80bc;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #bccfe6), color-stop(2%, #6792c5), color-stop(100%, #3f6ea6));background-image:-webkit-linear-gradient(#bccfe6,#6792c5 2%,#3f6ea6);background-image:linear-gradient(#bccfe6,#6792c5 2%,#3f6ea6);color:#1f3651;text-shadow:rgba(255, 255, 255, 0.25) 0 0.08em 0;border-top:1px solid #4d80bc;border-bottom:1px solid #2d4e76;font-weight:bold;font-size:0.8em;padding:0.2em 1.02em;text-shadow:rgba(255, 255, 255, 0.25) 0 0.08em 0}.x-list-normal .x-list-item .x-list-item-label{border-top:1px solid #d1d1d1}.x-list-normal .x-list-item:first-child{border-top:none}.x-list-normal .x-list-item:last-child .x-list-item-label{border-bottom:1px solid #d1d1d1}.x-list-normal .x-list-item.x-item-pressed .x-list-item-label{border-top-color:#77b2f8}.x-list-normal .x-list-item.x-item-selected .x-list-item-label{border-top-color:#084b9b;border-bottom-color:#021022}.x-list-round .x-scroll-view{background-color:#EEEEEE !important}.x-list-round .x-list-disclosure{-webkit-mask:0 0 url('data:image/png;base64,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') no-repeat;background-color:#777777;background-image:none}.x-list-round .x-list-header{color:#777;font-size:1em;font-weight:bold;padding-left:26px;line-height:1.7em;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #eeeeee), color-stop(30%, rgba(238,238,238,0.9)), color-stop(100%, rgba(238,238,238,0.4)));background-image:-webkit-linear-gradient(top, #eeeeee,rgba(238,238,238,0.9) 30%,rgba(238,238,238,0.4));background-image:linear-gradient(top, #eeeeee,rgba(238,238,238,0.9) 30%,rgba(238,238,238,0.4))}.x-list-round .x-list-container{padding:13px 13px 0 13px}.x-list-round .x-list-container .x-list-header{padding-left:13px;background-image:none}.x-list-round.x-list-ungrouped .x-list-item-label,.x-list-round.x-list-grouped .x-list-item-label{border:solid #DDDDDD;border-width:1px 1px 0 1px;background:#fff}.x-list-round.x-list-ungrouped .x-list-item:first-child .x-list-item-label{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em;-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em}.x-list-round.x-list-ungrouped .x-list-item:last-child{margin-bottom:13px}.x-list-round.x-list-ungrouped .x-list-item:last-child .x-list-item-label{-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em;border-width:1px}.x-list-round.x-list-grouped .x-list-header-item .x-list-item-label{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em;-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em}.x-list-round.x-list-grouped .x-list-footer-item{margin-bottom:13px}.x-list-round.x-list-grouped .x-list-footer-item .x-list-item-label{border-width:1px;-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em}.x-dataview-inlineblock .x-dataview-item{display:inline-block !important}.x-dataview-nowrap .x-dataview-container{white-space:nowrap !important}.x-list-inlineblock .x-list-item{display:inline-block !important}.x-list-nowrap .x-list-inner{width:auto}.x-list-nowrap .x-list-container{white-space:nowrap !important}.x-list-paging{height:50px}.x-list-paging .x-loading-spinner{display:none;margin:auto}.x-list-paging .x-list-paging-msg{text-align:center;color:#06346a;padding-top:10px;-webkit-border-radius:6px;border-radius:6px}.x-list-paging.x-loading .x-loading-spinner{display:block}.x-list-paging.x-loading .x-list-paging-msg{display:none}.x-list-pullrefresh{display:-webkit-box;display:box;-webkit-box-orient:horizontal;box-orient:horizontal;-webkit-box-align:center;box-align:center;-webkit-box-pack:center;box-pack:center;position:absolute;top:-5em;left:0;width:100%;height:4.5em}.x-list-pullrefresh .x-loading-spinner{display:none}.x-list-pullrefresh-arrow{width:2.5em;height:4.5em;background:center center url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAA8CAYAAAAUufjgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNrsmU8oREEYwOexdtNuKBfFwdVhCyfuysnFiXISS+1BLopyUpKLXETkRLaUi1LK3Q2lpPbiQLnIn03a/Hm+z86Ttv0zM++bfbOar36Hbad5v535Zp7v47iuy0wOpyoEHccRHV9L9NxPkUE/bhKCOKiOSPAdn69DsJ5I8E2HYA0QJRJ8Bb50CDYRCT7pEMQD0kwk+CByUFQEW4gE73UIhoA2IsFb4ENEMCQ5MdU1IxwygpT3oKNLMGyyYFVscdhusc8tDpu+xRG7xf95BW0O2kNiV1AgIvaQ2BzUJNgJNJYZGyUU7OG1cal4Bi68oqkDPszy2teEwJp5Cdyu/lZ1g8CwIYJ7wEF+2YmrNw90Byx3BizgKhaqizEP1wg7CLLxCEzy/CtauMeBlQDyEfNuGrgU6SyM8F9SyVgHdmRaH6tAb4XkToEp2d4M5mOK0TWMigU2koa8vJMRZPxEb2ss2LEVPMpPLlMRxBgDZjQJLgNbxb6Uab9tAn3EcifAeKkBMoLY+j0GWonk7oB+lmsFkwhidAGHBPmIeTcAnJcbKCuIMQEs+hScAzZEBqoIYuzyFVCJI36lMJ2CDfxibZeUu+EX/4uMIFP8ZyLejxkgK0hG5a8kP4IYSZbr1IuQVHmAX0HGX4VuGfZVJ6cQxPd1uoRcWqDW0SroFVzZAnJZ/h0LWhAjUUAw4XdSSsH8fExRTEgtGAOuOTETBb16Jk412e+bxOSwglYw6PgWYABvLk8P7zGJFwAAAABJRU5ErkJggg==') no-repeat;background-size:2em 3em;-webkit-transform:rotate(0deg)}.x-list-pullrefresh-release .x-list-pullrefresh-arrow{-webkit-transform:rotate(-180deg)}.x-list-pullrefresh-wrap{width:20em;font-size:0.7em}.x-list-pullrefresh-message{font-weight:bold;font-size:1.3em;margin-bottom:0.1em;text-align:center}.x-list-pullrefresh-updated{text-align:center}html,body{width:100%;height:100%}.x-translatable{position:absolute;top:100%;left:100%;z-index:1}.x-translatable-container{position:relative}.x-translatable-wrapper{width:100%;height:100%;position:absolute;overflow:hidden}.x-translatable-stretcher{width:300%;height:300%;position:absolute;visibility:hidden;z-index:-1}.x-translatable-nested-stretcher{width:100%;height:100%;left:100%;top:100%;position:absolute;visibility:hidden;z-index:-1}.x-layout-fit,.x-layout-card{position:relative;overflow:hidden}.x-layout-fit-item,.x-layout-card-item{position:absolute !important;width:100%;height:100%}.x-layout-hbox,.x-layout-vbox{display:-webkit-box}.x-layout-hbox > *,.x-layout-vbox > *{-webkit-box-flex:0}.x-layout-hbox{-webkit-box-orient:horizontal}.x-layout-vbox{-webkit-box-orient:vertical}.x-layout-hbox > .x-layout-box-item{width:0 !important}.x-layout-vbox > .x-layout-box-item{height:0 !important}.x-table-inner{display:table !important;width:100%;height:100%}.x-table-inner.x-table-fixed{table-layout:fixed !important}.x-table-row{display:table-row !important}.x-table-row > *{display:table-cell !important;vertical-align:middle}.x-container,.x-body{display:-webkit-box}.x-body{overflow:hidden;-webkit-box-flex:1;min-width:100%;min-height:100%}.x-body > .x-inner,.x-container > .x-inner{-webkit-box-flex:1;min-width:100%;min-height:100%;position:relative}.x-docking-horizontal{display:-webkit-box;-webkit-box-flex:1;-webkit-box-orient:horizontal;min-width:100%;min-height:100%}.x-docking-vertical{display:-webkit-box;-webkit-box-flex:1;-webkit-box-orient:vertical;min-width:100%;min-height:100%}.x-centered{position:absolute !important;width:100%;height:100%;display:-webkit-box;-webkit-box-align:center;-webkit-box-pack:center}.x-floating{position:absolute !important}.x-centered > *{position:relative !important;-webkit-box-flex:0 !important}.x-size-change-detector{visibility:hidden;position:absolute;left:0;top:0;z-index:-1;width:100%;height:100%;overflow:hidden}.x-size-change-detector > *{visibility:hidden}.x-size-change-detector-shrink > *{width:200%;height:200%}.x-size-change-detector-expand > *{width:100000px;height:100000px}.x-scroll-view{position:relative;display:block}.x-scroll-container{position:absolute;overflow:hidden;width:100%;height:100%}.x-scroll-scroller{position:absolute;min-width:100%;min-height:100%}.x-ios .x-scroll-scroller{-webkit-transform:translate3d(0, 0, 0)}.x-scroll-stretcher{position:absolute;visibility:hidden}.x-scroll-bar-grid-wrapper{position:absolute;width:100%;height:100%}.x-scroll-bar-grid{display:table;width:100%;height:100%}.x-scroll-bar-grid > *{display:table-row}.x-scroll-bar-grid > * > *{display:table-cell}.x-scroll-bar-grid > :first-child > :first-child{width:100%;height:100%}.x-scroll-bar-grid > :first-child > :nth-child(2){padding:3px 3px 0 0}.x-scroll-bar-grid > :nth-child(2) > :first-child{padding:0 0 3px 3px}.x-scroll-bar{position:relative;overflow:hidden}.x-scroll-bar-stretcher{position:absolute;visibility:hidden;width:100%;height:100%}.x-scroll-bar-x{width:100%}.x-scroll-bar-x > .x-scroll-bar-stretcher{width:300%}.x-scroll-bar-x.active{height:6px}.x-scroll-bar-y{height:100%}.x-scroll-bar-y > .x-scroll-bar-stretcher{height:300%}.x-scroll-bar-y.active{width:6px}.x-scroll-indicator{background:#333;position:absolute;z-index:2;opacity:0.5}.x-scroll-indicator.default{-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.x-list-light .x-scroll-indicator,.x-dataview-light .x-scroll-indicator{background:#fff;opacity:1}.x-scroll-indicator-x{height:100%}.x-scroll-indicator-y{width:100%}.x-scroll-indicator.csstransform{background:none}.x-scroll-indicator.csstransform > *{position:absolute;background-color:#333}.x-scroll-indicator.csstransform > :nth-child(2){-webkit-transform-origin:0% 0%;background:none;content:url(data:image/bmp;base64,Qk08AAAAAAAAADYAAAAoAAAAAQAAAAEAAAABABAAAAAAAAYAAAASCwAAEgsAAAAAAAAAAAAAxhgAAAAA)}.x-scroll-indicator.csstransform.x-scroll-indicator-light > *{background-color:#eee}.x-scroll-indicator.csstransform.x-scroll-indicator-light > :nth-child(2){content:url(data:image/bmp;base64,Qk08AAAAAAAAADYAAAAoAAAAAQAAAAEAAAABABAAAAAAAAYAAAASCwAAEgsAAAAAAAAAAAAAvXcAAAAA)}.x-scroll-indicator.csstransform.x-scroll-indicator-y > *{width:100%}.x-scroll-indicator.csstransform.x-scroll-indicator-y > :first-child{height:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.x-scroll-indicator.csstransform.x-scroll-indicator-y > :nth-child(2){height:1px}.x-scroll-indicator.csstransform.x-scroll-indicator-y > :last-child{height:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.x-scroll-indicator.csstransform.x-scroll-indicator-x > *{height:100%}.x-scroll-indicator.csstransform.x-scroll-indicator-x > :first-child{width:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px}.x-scroll-indicator.csstransform.x-scroll-indicator-x > :nth-child(2){width:1px}.x-scroll-indicator.csstransform.x-scroll-indicator-x > :last-child{width:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.x-carousel{position:relative;overflow:hidden}.x-carousel-item{position:absolute;width:100%;height:100%}.x-carousel-item > *{position:absolute;width:100%;height:100%}.x-carousel-indicator{padding:0;-webkit-border-radius:0;border-radius:0;-webkit-box-shadow:none;background-color:transparent;background-image:none}.x-carousel-indicator{-webkit-box-flex:1;display:-webkit-box;display:box;-webkit-box-pack:center;box-pack:center;-webkit-box-align:center;box-align:center}.x-carousel-indicator span{display:block;width:0.5em;height:0.5em;-webkit-border-radius:0.25em;border-radius:0.25em;margin:0.2em}.x-carousel-indicator-horizontal{height:1.5em;width:100%}.x-carousel-indicator-vertical{-webkit-box-orient:vertical;box-orient:vertical;width:1.5em;height:100%}.x-carousel-indicator-light span{background-color:rgba(255, 255, 255, 0.1);background-image:none}.x-carousel-indicator-light span.x-carousel-indicator-active{background-color:rgba(255, 255, 255, 0.3);background-image:none}.x-carousel-indicator-dark span{background-color:rgba(0, 0, 0, 0.1);background-image:none}.x-carousel-indicator-dark span.x-carousel-indicator-active{background-color:rgba(0, 0, 0, 0.3);background-image:none}.x-form .x-scroll-container{background-color:#eeeeee}.x-form .x-scroll-container > .x-inner{padding:1em}.x-form-label{text-shadow:#fff 0 1px 1px;color:#333333;text-shadow:rgba(255, 255, 255, 0.25) 0 0.08em 0;padding:0.6em;display:none !important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.x-form-label span{font-size:.8em;font-weight:bold}.x-field{min-height:2.5em}.x-field .x-field-input{position:relative}.x-field .x-field-input,.x-field .x-input-el{width:100%}.x-field.x-field-labeled .x-form-label{display:block !important}.x-field:last-child{border-bottom:0}.x-label-align-left .x-component-outer,.x-label-align-right .x-component-outer{-webkit-box-flex:1;box-flex:1}.x-label-align-left:first-child .x-form-label{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em}.x-label-align-left:last-child .x-form-label{-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em}.x-label-align-right{-webkit-box-direction:reverse;box-direction:reverse}.x-label-align-right:first-child .x-form-label{-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em}.x-label-align-right:last-child{border-bottom:0}.x-label-align-right:last-child .x-form-label{-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em}.x-label-align-top,.x-label-align-bottom{-webkit-box-orient:vertical;box-orient:vertical}.x-label-align-top:first-child .x-form-label{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em;-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em}.x-label-align-bottom:last-child .x-form-label{-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em}.x-input-el{padding:.4em;min-height:2.5em;display:block;border-width:0;background:transparent;-webkit-appearance:none}.x-field-mask{position:absolute;top:0;right:0;bottom:0;left:0}.x-field-required label:after,.x-field-required .x-form-label:after{content:"*";display:inline}.x-item-disabled label:after,.x-item-disabled .x-form-label:after{color:#666 !important}.x-field-textarea textarea{min-height:6em;padding-top:.5em}.x-checkmark-base,.x-field .x-input-radio:after,.x-field .x-input-checkbox:after,.x-field .x-input-radio:checked:after,.x-field .x-input-checkbox:checked:after,.x-field.x-item-disabled .x-input-radio:checked:after,.x-field.x-item-disabled .x-input-checkbox:checked:after,.x-select-overlay .x-item-selected .x-list-item-label:before,.x-select-overlay .x-item-selected .x-list-item-label:after{content:"";position:absolute;width:1.4em;height:1.4em;top:50%;left:auto;right:1.1em;-webkit-mask-size:1.4em;-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAE+klEQVRoBe2aS28URxRGsY0h2FmwCQuEWLHjvUNgZAQ4PMwrEkIRIGEgySKwB8QvYIvEP+ANO0CwsJAA88wGBEKBZJUVQkJCQrwJ5nxN31Z5pnpc7e4ZT9vT0peqqanquqfurVvlIW3Dw8NTJtPTPplgxdoCnugeb3m45eEJtgJTJwJPGw8cP8V6TfmC4/Z/H9uEAAZsIdqHZiMBn2UNbvigSw8M2AIAD6PtqBPpmYe+8t1NoL9GLfYf3bTKKhiWo9PoA9KV0dUgn/tRh8tXWg/Hnj0KUB8yz1JNnjXUuhFd264A/f0O7dKXpQ7EIiTPfkKuVyvrSlx3US+KPF26cMbwxeg8Gg3W4LWHFd6rUUepQprQnI/Rh9A25AtjmqseHVkK7w59UxpgYFdg7wH0CwqFpWvyrKI23GZ7OWluwgqwOnqOobVoWh4Tm97DwCpBHUFp2TiUX3v5QVMnLQzMmqAsUVWWyta3UX/TAmOcwjjk6KmE830W7GbU0ZTAGKYEJdj3yAcQ2qYw1jmsG9e0KF8122UDw/SHwFX0EYWC+fpZGG/hPcn1sqk8jGHas+dQ6KXCB6o2g91IPfKsObZpgDGsqAT1hXdpz25A7QZqZU1gBsxFSh5zbEA9yniOU5R5PSvvCnYTSsLYtdkLTGf9uKdD/gS6gI6jPndgUXXe24OKSFAK4zsoSVA+G6uAGaC758/oBrIs+Zb6rbg9up35Xpa1jffpUqEEldezysbJ0VPLjhHADOpEfUiw2gtuUtAKDiGtYNXeqDWJ7zveYQnqM3V3nqx1s2s97xmRoLzzWqMgkLLaTVQJa0ZoJe+hXjRmaMYKVlslr2dlp5wgu4PsiTyszmg5qgVr0CqvoZW2WFlKxhV5gxJsdIMKtYH+Eew6yksoNLy0soJeFzqR+vEI9gx6h9wFzFoPSlA+25g3SlChnnUNU3grkWmxRg0n+ihBnUR5w9j2bCbPGjzzR3sgbc+6gL66TV4zkTHHEqSfZSzr+94V0mbzKUF1GkSWknG5QktGyoj7qBdVeZo2S1Ch2yUNXOMVUcEJyrcQjOeP4vzQCu9BpBtOck5T70HybN4w1iJcR7ouem9QPjhfG+On7EBPUNrKhrYLWp7+FS1FCjtdKvJ6VvM/Q9o2uWC1AHq60QB6hELh0voJ+im6iHReF+FZwe5HP/g8lrXNzuEfeeFu9C9Kg8nSrr9lBZ9ljK/v37xjL5qRFSytf3K15KXy9EH0D/JN3ui2Qj1rC5AAq4FnJvoDPUSNBnTnUy4YQF1maFHlCOAYuouJFN6PkWtEo+ryrH5sL2TPVi5UFXAMrfDegxrtae3ZfWh6paFFffYCx9BKZLtQo/a0YLXIhSUo3yKlAsfQ8vSBBkALtrCjxwdqbTWBY2glst9REee0Lw/ULUEZpFuOChxD1yuRybNbUV0SlAtq9SDgGFp7ushEJlhdKuqWoAzSLYOBHeidGPkc+cIztE2wA6iuCcoFtXom4Bha4f0nGmv2FqyOnoaFscFG9rsfQusYq0T2G8qayASrbdEdOlfR/TJ72AzAaHla5/QD9BnVCucvfK/fjZXtx8WzZneu/+WBf53XOb0G6XetHjQXyfv2vKLyH7qLLqMhJn5DOW5PLmBZDfRUilloGUoD/ovvXgIrT4/rkxt4XK0fw+TtYxhT6iEt4FK7L8D4locDFqnUXSadh78Bx5bEl2CLG+8AAAAASUVORK5CYII=');margin-top:-0.7em}.x-field .x-input-radio,.x-field .x-input-checkbox{position:relative}.x-field .x-input-radio:after,.x-field .x-input-checkbox:after{background-color:#dddddd}.x-field .x-input-radio:checked:after,.x-field .x-input-checkbox:checked:after{background-color:#06346a}.x-field.x-item-disabled .x-input-radio:checked:after,.x-field.x-item-disabled .x-input-checkbox:checked:after{background-color:#9caaba}.x-spinner .x-component-outer{display:-webkit-box;display:box}.x-spinner .x-component-outer > *{width:auto}.x-spinner .x-field-input{-webkit-box-flex:1}.x-spinner .x-field-input .x-input-el{-webkit-text-fill-color:#000;padding:0;width:100%;text-align:center}.x-spinner .x-field-input input::-webkit-outer-spin-button,.x-spinner .x-field-input input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.x-spinner.x-item-disabled .x-input-el{-webkit-text-fill-color:#B3B3B3}.x-spinner.x-item-disabled .x-spinner-button{color:#aaa !important}.x-spinner.x-item-disabled .x-spinner-button,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button{border:1px solid #c4c4c4;border-top-color:#d0d0d0;color:black}.x-spinner.x-item-disabled .x-spinner-button.x-button-back:before,.x-spinner.x-item-disabled .x-spinner-button.x-button-forward:before,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-back:before,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-forward:before{background:#c4c4c4}.x-spinner.x-item-disabled .x-spinner-button,.x-spinner.x-item-disabled .x-spinner-button.x-button-back:after,.x-spinner.x-item-disabled .x-spinner-button.x-button-forward:after,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-back:after,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-forward:after{background-color:#f7f7f7;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #ffffff), color-stop(100%, #e5e5e5));background-image:-webkit-linear-gradient(#ffffff,#ffffff 2%,#e5e5e5);background-image:linear-gradient(#ffffff,#ffffff 2%,#e5e5e5)}.x-spinner.x-item-disabled .x-spinner-button .x-button-icon.x-icon-mask,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button .x-button-icon.x-icon-mask{background-color:black;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(2%, #121212), color-stop(100%, #000000));background-image:-webkit-linear-gradient(#4d4d4d,#121212 2%,#000000);background-image:linear-gradient(#4d4d4d,#121212 2%,#000000)}.x-spinner.x-item-disabled .x-spinner-button.x-button-pressing,.x-spinner.x-item-disabled .x-spinner-button.x-button-pressing:after,.x-spinner.x-item-disabled .x-spinner-button.x-button-pressed,.x-spinner.x-item-disabled .x-spinner-button.x-button-pressed:after,.x-spinner.x-item-disabled .x-spinner-button.x-button-active,.x-spinner.x-item-disabled .x-spinner-button.x-button-active:after,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-pressing,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-pressing:after,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-pressed,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-pressed:after,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-active,.x-toolbar .x-spinner.x-item-disabled .x-spinner-button.x-button-active:after{background-color:#efefef;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #d5d5d5), color-stop(10%, #e2e2e2), color-stop(65%, #efefef), color-stop(100%, #f0f0f0));background-image:-webkit-linear-gradient(#d5d5d5,#e2e2e2 10%,#efefef 65%,#f0f0f0);background-image:linear-gradient(#d5d5d5,#e2e2e2 10%,#efefef 65%,#f0f0f0)}.x-spinner .x-spinner-button{width:3em;padding:.65em 0;font-weight:bold;text-align:center}.x-spinner .x-spinner-button,.x-toolbar .x-spinner .x-spinner-button{border:1px solid #aaaaaa;border-top-color:#b7b7b7;color:black}.x-spinner .x-spinner-button.x-button-back:before,.x-spinner .x-spinner-button.x-button-forward:before,.x-toolbar .x-spinner .x-spinner-button.x-button-back:before,.x-toolbar .x-spinner .x-spinner-button.x-button-forward:before{background:#aaaaaa}.x-spinner .x-spinner-button,.x-spinner .x-spinner-button.x-button-back:after,.x-spinner .x-spinner-button.x-button-forward:after,.x-toolbar .x-spinner .x-spinner-button,.x-toolbar .x-spinner .x-spinner-button.x-button-back:after,.x-toolbar .x-spinner .x-spinner-button.x-button-forward:after{background-color:#dddddd;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #efefef), color-stop(100%, #cbcbcb));background-image:-webkit-linear-gradient(#ffffff,#efefef 2%,#cbcbcb);background-image:linear-gradient(#ffffff,#efefef 2%,#cbcbcb)}.x-spinner .x-spinner-button .x-button-icon.x-icon-mask,.x-toolbar .x-spinner .x-spinner-button .x-button-icon.x-icon-mask{background-color:black;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(2%, #121212), color-stop(100%, #000000));background-image:-webkit-linear-gradient(#4d4d4d,#121212 2%,#000000);background-image:linear-gradient(#4d4d4d,#121212 2%,#000000)}.x-spinner .x-spinner-button.x-button-pressing,.x-spinner .x-spinner-button.x-button-pressing:after,.x-spinner .x-spinner-button.x-button-pressed,.x-spinner .x-spinner-button.x-button-pressed:after,.x-spinner .x-spinner-button.x-button-active,.x-spinner .x-spinner-button.x-button-active:after,.x-toolbar .x-spinner .x-spinner-button.x-button-pressing,.x-toolbar .x-spinner .x-spinner-button.x-button-pressing:after,.x-toolbar .x-spinner .x-spinner-button.x-button-pressed,.x-toolbar .x-spinner .x-spinner-button.x-button-pressed:after,.x-toolbar .x-spinner .x-spinner-button.x-button-active,.x-toolbar .x-spinner .x-spinner-button.x-button-active:after{background-color:#d5d5d5;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #bcbcbc), color-stop(10%, #c9c9c9), color-stop(65%, #d5d5d5), color-stop(100%, #d7d7d7));background-image:-webkit-linear-gradient(#bcbcbc,#c9c9c9 10%,#d5d5d5 65%,#d7d7d7);background-image:linear-gradient(#bcbcbc,#c9c9c9 10%,#d5d5d5 65%,#d7d7d7)}.x-spinner .x-spinner-button-down{border:0 !important;border-right:1px solid #dddddd !important}.x-spinner .x-spinner-button-up{border:0 !important;border-left:1px solid #dddddd !important}.x-phone .x-select-overlay{min-width:14em;min-height:12.5em}.x-select-overlay{min-width:18em;min-height:22em}.x-select-overlay .x-list-item-label{height:2.6em}.x-select-overlay .x-list-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}.x-select-overlay .x-item-selected .x-list-label{margin-right:2.6em}.x-select-overlay .x-item-selected .x-list-item-label:before{background-color:rgba(0, 0, 0, 0.3);margin-top:-0.8em}.x-select-overlay .x-item-selected .x-list-item-label:after{background-color:#dddddd}.x-slider-field .x-component-outer,.x-toggle-field .x-component-outer{padding:0.6em}.x-slider,.x-toggle{position:relative;height:2.2em;min-height:0;min-width:0}.x-slider > *,.x-toggle > *{position:absolute;width:100%;height:100%}.x-slider.x-item-disabled{opacity:.6}.x-thumb{position:absolute;height:2.2em;width:2.2em}.x-thumb:before{content:"";position:absolute;width:1.85em;height:1.85em;top:0.175em;left:0.175em;border:1px solid #919191;-webkit-border-radius:0.925em;border-radius:0.925em;background-color:#dddddd;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #efefef), color-stop(100%, #cbcbcb));background-image:-webkit-linear-gradient(#ffffff,#efefef 2%,#cbcbcb);background-image:linear-gradient(#ffffff,#efefef 2%,#cbcbcb);-webkit-background-clip:padding;background-clip:padding-box}.x-thumb.x-dragging{opacity:1}.x-thumb.x-dragging:before{background-color:#d0d0d0;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(2%, #e2e2e2), color-stop(100%, #bebebe));background-image:-webkit-linear-gradient(#ffffff,#e2e2e2 2%,#bebebe);background-image:linear-gradient(#ffffff,#e2e2e2 2%,#bebebe)}.x-slider:after{content:"";position:absolute;width:auto;height:0.8em;top:0.737em;left:0;right:0;margin:0 0.925em;background-color:#dddddd;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c4c4c4), color-stop(10%, #d0d0d0), color-stop(65%, #dddddd), color-stop(100%, #dedede));background-image:-webkit-linear-gradient(#c4c4c4,#d0d0d0 10%,#dddddd 65%,#dedede);background-image:linear-gradient(#c4c4c4,#d0d0d0 10%,#dddddd 65%,#dedede);border:0.1em solid rgba(0, 0, 0, 0.1);border-bottom:0;-webkit-box-shadow:rgba(255, 255, 255, 0.7) 0 0.1em 0;-webkit-border-radius:0.4em;border-radius:0.4em}.x-toggle{width:4.4em;-webkit-border-radius:1.1em;border-radius:1.1em;overflow:hidden;border:1px solid #b7b7b7;background-color:#ddd;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c4c4c4), color-stop(10%, #d0d0d0), color-stop(65%, #dddddd), color-stop(100%, #dedede));background-image:-webkit-linear-gradient(#c4c4c4,#d0d0d0 10%,#dddddd 65%,#dedede);background-image:linear-gradient(#c4c4c4,#d0d0d0 10%,#dddddd 65%,#dedede);-webkit-box-flex:0}.x-toggle .x-thumb.x-dragging{opacity:1}.x-toggle .x-thumb:before{top:0.175em}.x-toggle-on{background-color:#92cf00;background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #6e9c00), color-stop(10%, #80b500), color-stop(65%, #92cf00), color-stop(100%, #94d200));background-image:-webkit-linear-gradient(#6e9c00,#80b500 10%,#92cf00 65%,#94d200);background-image:linear-gradient(#6e9c00,#80b500 10%,#92cf00 65%,#94d200)}input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}.x-field-number input::-webkit-outer-spin-button,.x-field-number input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.x-field-search .x-field-input{position:relative}.x-field-search .x-field-input:before{content:"";position:absolute;width:0.86em;height:0.86em;top:50%;left:0.5em;-webkit-mask-image:url('data:image/png;base64,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');-webkit-mask-size:.86em;background-color:#ccc;-webkit-mask-repeat:no-repeat;margin-top:-0.43em}.x-field-search .x-field-input .x-form-field{margin-left:1.0em}.x-field-input .x-clear-icon{display:none;background:url('data:image/png;base64,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') no-repeat;background-position:center center;background-size:55% 55%;width:2.2em;height:2.2em;margin:.5em;margin-top:-1.1em;position:absolute;top:50%;right:-0.5em}.x-field-clearable .x-clear-icon{display:block}.x-field-clearable .x-field-input{padding-right:2.2em}.x-android .x-input-el{-webkit-text-fill-color:#000}.x-android .x-empty .x-input-el{-webkit-text-fill-color:#A9A9A9}.x-item-disabled .x-form-label span,.x-item-disabled input,.x-item-disabled .x-input-el,.x-item-disabled .x-spinner-body,.x-item-disabled select,.x-item-disabled textarea,.x-item-disabled .x-field-clear-container{color:#b3b3b3;-webkit-text-fill-color:#b3b3b3;pointer-events:none}.x-form-fieldset{margin:0 0 1.5em}.x-form-fieldset .x-form-label{background-color:#f7f7f7;border-top:1px solid white}.x-form-fieldset .x-form-fieldset-inner{border:1px solid #dddddd;background:#fff;padding:0;-webkit-border-radius:0.4em;border-radius:0.4em;overflow:hidden}.x-form-fieldset .x-field{border-bottom:1px solid #dddddd}.x-form-fieldset .x-field:first-child{-webkit-border-top-left-radius:0.4em;border-top-left-radius:0.4em;-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em}.x-form-fieldset .x-field:last-child{border-bottom:0;-webkit-border-bottom-left-radius:0.4em;border-bottom-left-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em}.x-form-fieldset-title{text-shadow:#fff 0 1px 1px;color:#333333;margin:1em 0.7em 0.3em;color:#333333;font-weight:bold;white-space:nowrap}.x-form-fieldset-instructions{text-shadow:#fff 0 1px 1px;color:#333333;color:gray;margin:1em 0.7em 0.3em;font-size:.8em;text-align:center}.x-selectmark-base,.x-field-select .x-component-outer:after{content:"";position:absolute;width:1em;height:1em;top:50%;left:auto;right:0.7em;-webkit-mask-size:1em;-webkit-mask-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGRTdGMTE3NDA3MjA2ODExOTJDQUMyNUQwRUE4NjdEQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxQTFBMDFDQ0I5NEYxMURGQUU1RjlGMEFERUNDQTVEMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyMkRCMDIxMkI5NEUxMURGQUU1RjlGMEFERUNDQTVEMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMwRTE0QzVBNDIyMjY4MTFCQ0ZCOTAzOTcwNzcyRkVCIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFN0YxMTc0MDcyMDY4MTE5MkNBQzI1RDBFQTg2N0RCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+HfrH/AAAAeVJREFUeNrs2cFHBGEUAPA3zYqIiIhOnTpFRHSKrp26RqeuEV077R/QqWtE166dOkVERHRa9hQRnZalFcv0Hk/W1Mx+38z3vvlm5j3eZW+/9+abne+9KEkSaFPMQMtCwQpWsIIVrGAFK1jBClawgo2ik/4hiqJGwLKuvfpIc5xSkWqYr5hzU1s/mRNxXTPsJ+ZqluvXlwOmSj3XBDvG3M1rpAmYYoUrFzr4ZNqTawqm2MH8Dhh7ZXJUbcAUx4FinzBnJcAUl4FhP/jIgRSYKvkYCJaO2LbNv08RMMUy5nsA4COTLy0XYIqtil9iF6aflq7AwBWuAvuQ9ZKSBgNX2ieWjtKSzeXBNZgqfe8J+4W5aXtbcg0GrvibB/BhkeuhBJhigzsghT0veh+WAlMcCGHvMOMQwcCdcIntYy6WmXhIg2PuiAvsEHO97IhHGgzckb4D8L6LmZYPMHBnhiWwXVdDPF9g4A4Vwd66nFr6BAN3ygbbw1yoMzjmjplgB5hrrufSvsHAHesZDOD2JAbxVYCBOzfIAZ9JbR6qAgN3cPwP9kZy1VIlGLiTdluCmoOBO/pnS9Bk8DzmS3pL4BMcpZEe1qX0GI/atC4dQYXRMa1MU0IX4gpWsIIVrGAFK1jBCnYUPwIMAPUPAyFL+nRdAAAAAElFTkSuQmCC');margin-top:-0.5em}.x-field-select{position:relative}.x-field-select .x-component-outer:after{background-color:#dddddd;z-index:2}.x-field-select .x-component-outer:before,.x-field-select .x-component-outer:after{pointer-events:none;position:absolute;display:block}.x-field-select .x-component-outer:before{content:"";position:absolute;width:4em;height:auto;top:0;left:auto;right:0;bottom:0;-webkit-border-top-right-radius:0.4em;border-top-right-radius:0.4em;-webkit-border-bottom-right-radius:0.4em;border-bottom-right-radius:0.4em;background:-webkit-gradient(linear, 0% 0%, 100% 0%, from(rgba(255, 255, 255, 0)), color-stop(0.5, white));z-index:1}.x-msgbox{min-width:15em;max-width:20em;padding:0.8em;-webkit-box-shadow:rgba(0, 0, 0, 0.4) 0 0.1em 0.5em;-webkit-border-radius:0.3em;border-radius:0.3em;border:0.15em solid #354f6e}.x-msgbox .x-icon{margin-left:1.3em}.x-msgbox .x-title{font-size:.9em;line-height:1.4em}.x-msgbox .x-body{background:transparent !important}.x-msgbox .x-toolbar{background:transparent none;-webkit-box-shadow:none}.x-msgbox .x-toolbar.x-docked-top{border-bottom:0;height:1.3em}.x-msgbox .x-toolbar.x-docked-bottom{border-top:0}.x-msgbox .x-field{min-height:2em;background:#fff;-webkit-border-radius:0.2em;border-radius:0.2em}.x-msgbox .x-form-field{min-height:1.5em;padding-right:0 !important;-webkit-appearance:none}.x-msgbox .x-field-input{padding-right:2.2em}.x-msgbox-text{text-align:center;padding:6px 0;line-height:1.4em}.x-msgbox-buttons{padding:0.4em 0;height:auto}.x-msgbox-buttons .x-button{min-width:4.5em}.x-msgbox-buttons .x-button-normal span{opacity:.7}.x-msgbox-dark .x-msgbox-text{color:rgba(186, 202, 222, 0.9);text-shadow:rgba(0, 0, 0, 0.5) 0 -0.08em 0}.x-msgbox-dark .x-msgbox-input{background-color:rgba(186, 202, 222, 0.9);background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(152,176,205,0.9)), color-stop(10%, rgba(169,189,214,0.9)), color-stop(65%, rgba(186,202,222,0.9)), color-stop(100%, rgba(188,204,223,0.9)));background-image:-webkit-linear-gradient(rgba(152,176,205,0.9),rgba(169,189,214,0.9) 10%,rgba(186,202,222,0.9) 65%,rgba(188,204,223,0.9));background-image:linear-gradient(rgba(152,176,205,0.9),rgba(169,189,214,0.9) 10%,rgba(186,202,222,0.9) 65%,rgba(188,204,223,0.9));border:0.1em solid rgba(66, 99, 138, 0.9)}.x-loading-spinner{font-size:250%;height:1em;width:1em;position:relative;-webkit-transform-origin:0.5em 0.5em}.x-loading-spinner > span,.x-loading-spinner > span:before,.x-loading-spinner > span:after{display:block;position:absolute;width:0.1em;height:0.25em;top:0;-webkit-transform-origin:0.05em 0.5em;-webkit-border-radius:0.05em;border-radius:0.05em;content:" "}.x-loading-spinner > span.x-loading-top{background-color:rgba(170, 170, 170, 0.99)}.x-loading-spinner > span.x-loading-top::after{background-color:rgba(170, 170, 170, 0.9)}.x-loading-spinner > span.x-loading-left::before{background-color:rgba(170, 170, 170, 0.8)}.x-loading-spinner > span.x-loading-left{background-color:rgba(170, 170, 170, 0.7)}.x-loading-spinner > span.x-loading-left::after{background-color:rgba(170, 170, 170, 0.6)}.x-loading-spinner > span.x-loading-bottom::before{background-color:rgba(170, 170, 170, 0.5)}.x-loading-spinner > span.x-loading-bottom{background-color:rgba(170, 170, 170, 0.4)}.x-loading-spinner > span.x-loading-bottom::after{background-color:rgba(170, 170, 170, 0.35)}.x-loading-spinner > span.x-loading-right::before{background-color:rgba(170, 170, 170, 0.3)}.x-loading-spinner > span.x-loading-right{background-color:rgba(170, 170, 170, 0.25)}.x-loading-spinner > span.x-loading-right::after{background-color:rgba(170, 170, 170, 0.2)}.x-loading-spinner > span.x-loading-top::before{background-color:rgba(170, 170, 170, 0.15)}.x-loading-spinner > span{left:50%;margin-left:-0.05em}.x-loading-spinner > span.x-loading-top{-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg)}.x-loading-spinner > span.x-loading-right{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg)}.x-loading-spinner > span.x-loading-bottom{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg)}.x-loading-spinner > span.x-loading-left{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg)}.x-loading-spinner > span::before{-webkit-transform:rotate(30deg);-moz-transform:rotate(30deg)}.x-loading-spinner > span::after{-webkit-transform:rotate(-30deg);-moz-transform:rotate(-30deg)}.x-loading-spinner{-webkit-animation-name:x-loading-spinner-rotate;-webkit-animation-duration:.5s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear}@-webkit-keyframes x-loading-spinner-rotate{0%{-webkit-transform:rotate(0deg)}8.32%{-webkit-transform:rotate(0deg)}8.33%{-webkit-transform:rotate(30deg)}16.65%{-webkit-transform:rotate(30deg)}16.66%{-webkit-transform:rotate(60deg)}24.99%{-webkit-transform:rotate(60deg)}25%{-webkit-transform:rotate(90deg)}33.32%{-webkit-transform:rotate(90deg)}33.33%{-webkit-transform:rotate(120deg)}41.65%{-webkit-transform:rotate(120deg)}41.66%{-webkit-transform:rotate(150deg)}49.99%{-webkit-transform:rotate(150deg)}50%{-webkit-transform:rotate(180deg)}58.32%{-webkit-transform:rotate(180deg)}58.33%{-webkit-transform:rotate(210deg)}66.65%{-webkit-transform:rotate(210deg)}66.66%{-webkit-transform:rotate(240deg)}74.99%{-webkit-transform:rotate(240deg)}75%{-webkit-transform:rotate(270deg)}83.32%{-webkit-transform:rotate(270deg)}83.33%{-webkit-transform:rotate(300deg)}91.65%{-webkit-transform:rotate(300deg)}91.66%{-webkit-transform:rotate(330deg)}100%{-webkit-transform:rotate(330deg)}} diff --git a/apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.js b/apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.js new file mode 100644 index 0000000000..caf8e4541d --- /dev/null +++ b/apps/files_odfviewer/src/webodf/programs/touchui/sencha-touch.js @@ -0,0 +1,15 @@ +/* + +This file is part of Sencha Touch 2 + +Copyright (c) 2012 Sencha Inc + +Contact: http://www.sencha.com/contact + +Commercial Usage +Licensees holding valid commercial licenses may use this file in accordance with the Commercial Software License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Sencha. + +If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact. + +*/ +(function(){var global=this,objectPrototype=Object.prototype,toString=objectPrototype.toString,enumerables=true,enumerablesTest={toString:1},emptyFn=function(){},i;if(typeof Ext==="undefined"){global.Ext={}}Ext.global=global;for(i in enumerablesTest){enumerables=null}if(enumerables){enumerables=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"]}Ext.enumerables=enumerables;Ext.apply=function(object,config,defaults){if(defaults){Ext.apply(object,defaults)}if(object&&config&&typeof config==="object"){var i,j,k;for(i in config){object[i]=config[i]}if(enumerables){for(j=enumerables.length;j--;){k=enumerables[j];if(config.hasOwnProperty(k)){object[k]=config[k]}}}}return object};Ext.buildSettings=Ext.apply({baseCSSPrefix:"x-",scopeResetCSS:false},Ext.buildSettings||{});Ext.apply(Ext,{emptyFn:emptyFn,baseCSSPrefix:Ext.buildSettings.baseCSSPrefix,applyIf:function(object,config){var property;if(object){for(property in config){if(object[property]===undefined){object[property]=config[property]}}}return object},iterate:function(object,fn,scope){if(Ext.isEmpty(object)){return}if(scope===undefined){scope=object}if(Ext.isIterable(object)){Ext.Array.each.call(Ext.Array,object,fn,scope)}else{Ext.Object.each.call(Ext.Object,object,fn,scope)}}});Ext.apply(Ext,{extend:function(){var objectConstructor=objectPrototype.constructor,inlineOverrides=function(o){for(var m in o){if(!o.hasOwnProperty(m)){continue}this[m]=o[m]}};return function(subclass,superclass,overrides){if(Ext.isObject(superclass)){overrides=superclass;superclass=subclass;subclass=overrides.constructor!==objectConstructor?overrides.constructor:function(){superclass.apply(this,arguments)}}var F=function(){},subclassProto,superclassProto=superclass.prototype;F.prototype=superclassProto;subclassProto=subclass.prototype=new F();subclassProto.constructor=subclass;subclass.superclass=superclassProto;if(superclassProto.constructor===objectConstructor){superclassProto.constructor=superclass}subclass.override=function(overrides){Ext.override(subclass,overrides)};subclassProto.override=inlineOverrides;subclassProto.proto=subclassProto;subclass.override(overrides);subclass.extend=function(o){return Ext.extend(subclass,o)};return subclass}}(),override:function(cls,overrides){if(cls.$isClass){return cls.override(overrides)}else{Ext.apply(cls.prototype,overrides)}}});Ext.apply(Ext,{valueFrom:function(value,defaultValue,allowBlank){return Ext.isEmpty(value,allowBlank)?defaultValue:value},typeOf:function(value){if(value===null){return"null"}var type=typeof value;if(type==="undefined"||type==="string"||type==="number"||type==="boolean"){return type}var typeToString=toString.call(value);switch(typeToString){case"[object Array]":return"array";case"[object Date]":return"date";case"[object Boolean]":return"boolean";case"[object Number]":return"number";case"[object RegExp]":return"regexp"}if(type==="function"){return"function"}if(type==="object"){if(value.nodeType!==undefined){if(value.nodeType===3){return(/\S/).test(value.nodeValue)?"textnode":"whitespace"}else{return"element"}}return"object"}},isEmpty:function(value,allowEmptyString){return(value===null)||(value===undefined)||(!allowEmptyString?value==="":false)||(Ext.isArray(value)&&value.length===0)},isArray:("isArray" in Array)?Array.isArray:function(value){return toString.call(value)==="[object Array]"},isDate:function(value){return toString.call(value)==="[object Date]"},isObject:(toString.call(null)==="[object Object]")?function(value){return value!==null&&value!==undefined&&toString.call(value)==="[object Object]"&&value.ownerDocument===undefined}:function(value){return toString.call(value)==="[object Object]"},isSimpleObject:function(value){return value instanceof Object&&value.constructor===Object},isPrimitive:function(value){var type=typeof value;return type==="string"||type==="number"||type==="boolean"},isFunction:(typeof document!=="undefined"&&typeof document.getElementsByTagName("body")==="function")?function(value){return toString.call(value)==="[object Function]"}:function(value){return typeof value==="function"},isNumber:function(value){return typeof value==="number"&&isFinite(value)},isNumeric:function(value){return !isNaN(parseFloat(value))&&isFinite(value)},isString:function(value){return typeof value==="string"},isBoolean:function(value){return typeof value==="boolean"},isElement:function(value){return value?value.nodeType===1:false},isTextNode:function(value){return value?value.nodeName==="#text":false},isDefined:function(value){return typeof value!=="undefined"},isIterable:function(value){return(value&&typeof value!=="string")?value.length!==undefined:false}});Ext.apply(Ext,{clone:function(item){if(item===null||item===undefined){return item}if(item.nodeType&&item.cloneNode){return item.cloneNode(true)}var type=toString.call(item);if(type==="[object Date]"){return new Date(item.getTime())}var i,j,k,clone,key;if(type==="[object Array]"){i=item.length;clone=[];while(i--){clone[i]=Ext.clone(item[i])}}else{if(type==="[object Object]"&&item.constructor===Object){clone={};for(key in item){clone[key]=Ext.clone(item[key])}if(enumerables){for(j=enumerables.length;j--;){k=enumerables[j];clone[k]=item[k]}}}}return clone||item},getUniqueGlobalNamespace:function(){var uniqueGlobalNamespace=this.uniqueGlobalNamespace;if(uniqueGlobalNamespace===undefined){var i=0;do{uniqueGlobalNamespace="ExtBox"+(++i)}while(Ext.global[uniqueGlobalNamespace]!==undefined);Ext.global[uniqueGlobalNamespace]=Ext;this.uniqueGlobalNamespace=uniqueGlobalNamespace}return uniqueGlobalNamespace},functionFactory:function(){var args=Array.prototype.slice.call(arguments),ln=args.length;if(ln>0){args[ln-1]="var Ext=window."+this.getUniqueGlobalNamespace()+";"+args[ln-1]}return Function.prototype.constructor.apply(Function.prototype,args)},globalEval:("execScript" in global)?function(code){global.execScript(code)}:function(code){(function(){eval(code)})()},});Ext.type=Ext.typeOf})();(function(){var a="4.1.0",b;Ext.Version=b=Ext.extend(Object,{constructor:function(d){var c=this.toNumber,f,e;if(d instanceof b){return d}this.version=this.shortVersion=String(d).toLowerCase().replace(/_/g,".").replace(/[\-+]/g,"");e=this.version.search(/([^\d\.])/);if(e!==-1){this.release=this.version.substr(e,d.length);this.shortVersion=this.version.substr(0,e)}this.shortVersion=this.shortVersion.replace(/[^\d]/g,"");f=this.version.split(".");this.major=c(f.shift());this.minor=c(f.shift());this.patch=c(f.shift());this.build=c(f.shift());return this},toNumber:function(c){c=parseInt(c||0,10);if(isNaN(c)){c=0}return c},toString:function(){return this.version},valueOf:function(){return this.version},getMajor:function(){return this.major||0},getMinor:function(){return this.minor||0},getPatch:function(){return this.patch||0},getBuild:function(){return this.build||0},getRelease:function(){return this.release||""},isGreaterThan:function(c){return b.compare(this.version,c)===1},isGreaterThanOrEqual:function(c){return b.compare(this.version,c)>=0},isLessThan:function(c){return b.compare(this.version,c)===-1},isLessThanOrEqual:function(c){return b.compare(this.version,c)<=0},equals:function(c){return b.compare(this.version,c)===0},match:function(c){c=String(c);return this.version.substr(0,c.length)===c},toArray:function(){return[this.getMajor(),this.getMinor(),this.getPatch(),this.getBuild(),this.getRelease()]},getShortVersion:function(){return this.shortVersion},gt:function(){return this.isGreaterThan.apply(this,arguments)},lt:function(){return this.isLessThan.apply(this,arguments)},gtEq:function(){return this.isGreaterThanOrEqual.apply(this,arguments)},ltEq:function(){return this.isLessThanOrEqual.apply(this,arguments)}});Ext.apply(b,{releaseValueMap:{dev:-6,alpha:-5,a:-5,beta:-4,b:-4,rc:-3,"#":-2,p:-1,pl:-1},getComponentValue:function(c){return !c?0:(isNaN(c)?this.releaseValueMap[c]||c:parseInt(c,10))},compare:function(g,f){var d,e,c;g=new b(g).toArray();f=new b(f).toArray();for(c=0;ce){return 1}}}return 0}});Ext.apply(Ext,{versions:{},lastRegisteredVersion:null,setVersion:function(d,c){Ext.versions[d]=new b(c);Ext.lastRegisteredVersion=Ext.versions[d];return this},getVersion:function(c){if(c===undefined){return Ext.lastRegisteredVersion}return Ext.versions[c]},deprecate:function(c,e,f,d){if(b.compare(Ext.getVersion(c),e)<1){f.call(d)}}});Ext.setVersion("core",a)})();Ext.String={trimRegex:/^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,escapeRe:/('|\\)/g,formatRe:/\{(\d+)\}/g,escapeRegexRe:/([-.*+?^${}()|[\]\/\\])/g,htmlEncode:(function(){var d={"&":"&",">":">","<":"<",'"':"""},b=[],c,a;for(c in d){b.push(c)}a=new RegExp("("+b.join("|")+")","g");return function(e){return(!e)?e:String(e).replace(a,function(g,f){return d[f]})}})(),htmlDecode:(function(){var d={"&":"&",">":">","<":"<",""":'"'},b=[],c,a;for(c in d){b.push(c)}a=new RegExp("("+b.join("|")+"|&#[0-9]{1,5};)","g");return function(e){return(!e)?e:String(e).replace(a,function(g,f){if(f in d){return d[f]}else{return String.fromCharCode(parseInt(f.substr(2),10))}})}})(),urlAppend:function(b,a){if(!Ext.isEmpty(a)){return b+(b.indexOf("?")===-1?"?":"&")+a}return b},trim:function(a){return a.replace(Ext.String.trimRegex,"")},capitalize:function(a){return a.charAt(0).toUpperCase()+a.substr(1)},ellipsis:function(c,a,d){if(c&&c.length>a){if(d){var e=c.substr(0,a-2),b=Math.max(e.lastIndexOf(" "),e.lastIndexOf("."),e.lastIndexOf("!"),e.lastIndexOf("?"));if(b!==-1&&b>=(a-15)){return e.substr(0,b)+"..."}}return c.substr(0,a-3)+"..."}return c},escapeRegex:function(a){return a.replace(Ext.String.escapeRegexRe,"\\$1")},escape:function(a){return a.replace(Ext.String.escapeRe,"\\$1")},toggle:function(b,c,a){return b===c?a:c},leftPad:function(b,c,d){var a=String(b);d=d||" ";while(a.lengthH){for(C=e;C--;){F[z+C]=F[H+C]}}}if(J&&G===B){F.length=B;F.push.apply(F,I)}else{F.length=B+J;for(C=0;C-1;y--){if(A.call(z||C[y],C[y],y,C)===false){return y}}}return true},forEach:i?function(z,y,e){return z.forEach(y,e)}:function(B,z,y){var e=0,A=B.length;for(;ee){e=z}}}return e},mean:function(e){return e.length>0?a.sum(e)/e.length:undefined},sum:function(B){var y=0,e,A,z;for(e=0,A=B.length;e=c){f+=c}else{if(b*2<-c){f-=c}}}return Ext.Number.constrain(f,d,g)},toFixed:function(d,b){if(a){b=b||0;var c=Math.pow(10,b);return(Math.round(d*c)/c).toFixed(b)}return d.toFixed(b)},from:function(c,b){if(isFinite(c)){c=parseFloat(c)}return !isNaN(c)?c:b}}})();Ext.num=function(){return Ext.Number.from.apply(this,arguments)};(function(){var a=function(){};var b=Ext.Object={chain:function(d){a.prototype=d;var c=new a();a.prototype=null;return c},toQueryObjects:function(e,j,d){var c=b.toQueryObjects,h=[],f,g;if(Ext.isArray(j)){for(f=0,g=j.length;f0){h=n.split("=");v=decodeURIComponent(h[0]);m=(h[1]!==undefined)?decodeURIComponent(h[1]):"";if(!q){if(t.hasOwnProperty(v)){if(!Ext.isArray(t[v])){t[v]=[t[v]]}t[v].push(m)}else{t[v]=m}}else{g=v.match(/(\[):?([^\]]*)\]/g);s=v.match(/^([^\[]+)/);v=s[0];k=[];if(g===null){t[v]=m;continue}for(o=0,c=g.length;o0){return setTimeout(e,c)}e();return 0},createSequence:function(b,c,a){if(!c){return b}else{return function(){var d=b.apply(this,arguments);c.apply(a||this,arguments);return d}}},createBuffered:function(e,b,d,c){var a;return function(){if(!d){d=this}if(!c){c=Array.prototype.slice.call(arguments)}if(a){clearTimeout(a);a=null}a=setTimeout(function(){e.apply(d,c)},b)}},createThrottled:function(e,b,d){var f,a,c,h,g=function(){e.apply(d||this,c);f=new Date().getTime()};return function(){a=new Date().getTime()-f;c=arguments;clearTimeout(h);if(!f||(a>=b)){g()}else{h=setTimeout(g,b-a)}}},interceptBefore:function(b,a,c){var d=b[a]||Ext.emptyFn;return b[a]=function(){var e=c.apply(this,arguments);d.apply(this,arguments);return e}},interceptAfter:function(b,a,c){var d=b[a]||Ext.emptyFn;return b[a]=function(){d.apply(this,arguments);return c.apply(this,arguments)}}};Ext.defer=Ext.Function.alias(Ext.Function,"defer");Ext.pass=Ext.Function.alias(Ext.Function,"pass");Ext.bind=Ext.Function.alias(Ext.Function,"bind");Ext.JSON=new (function(){var useHasOwn=!!{}.hasOwnProperty,isNative=function(){var useNative=null;return function(){if(useNative===null){useNative=Ext.USE_NATIVE_JSON&&window.JSON&&JSON.toString()=="[object JSON]"}return useNative}}(),pad=function(n){return n<10?"0"+n:n},doDecode=function(json){return eval("("+json+")")},doEncode=function(o){if(!Ext.isDefined(o)||o===null){return"null"}else{if(Ext.isArray(o)){return encodeArray(o)}else{if(Ext.isDate(o)){return Ext.JSON.encodeDate(o)}else{if(Ext.isString(o)){return encodeString(o)}else{if(typeof o=="number"){return isFinite(o)?String(o):"null"}else{if(Ext.isBoolean(o)){return String(o)}else{if(Ext.isObject(o)){return encodeObject(o)}else{if(typeof o==="function"){return"null"}}}}}}}}return"undefined"},m={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\","\x0b":"\\u000b"},charToReplace=/[\\\"\x00-\x1f\x7f-\uffff]/g,encodeString=function(s){return'"'+s.replace(charToReplace,function(a){var c=m[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"'},encodeArray=function(o){var a=["[",""],len=o.length,i;for(i=0;i0){for(d=0;d0){if(l===k){return n[l]}m=n[l];k=k.substring(l.length+1)}if(m.length>0){m+="/"}return m.replace(/\/\.\//g,"/")+k.replace(/\./g,"/")+".js"},getPrefix:function(l){var n=this.config.paths,m,k="";if(n.hasOwnProperty(l)){return l}for(m in n){if(n.hasOwnProperty(m)&&m+"."===l.substring(0,m.length+1)){if(m.length>k.length){k=m}}}return k},require:function(m,l,k,n){if(l){l.call(k)}},syncRequire:function(){},exclude:function(l){var k=this;return{require:function(o,n,m){return k.require(o,n,m,l)},syncRequire:function(o,n,m){return k.syncRequire(o,n,m,l)}}},onReady:function(n,m,o,k){var l;if(o!==false&&Ext.onDocumentReady){l=n;n=function(){Ext.onDocumentReady(l,m,k)}}n.call(m)}};Ext.apply(b,{documentHead:typeof document!="undefined"&&(document.head||document.getElementsByTagName("head")[0]),isLoading:false,queue:[],isClassFileLoaded:{},isFileLoaded:{},readyListeners:[],optionalRequires:[],requiresMap:{},numPendingFiles:0,numLoadedFiles:0,hasFileLoadError:false,classNameToFilePathMap:{},syncModeEnabled:false,scriptElements:{},refreshQueue:function(){var k=this.queue,q=k.length,n,p,l,o,m;if(q===0){this.triggerReady();return}for(n=0;nthis.numLoadedFiles){continue}l=0;do{if(a.isCreated(o[l])){f(o,l,1)}else{l++}}while(l=200&&o<300){Ext.globalEval(u.responseText+"\n//@ sourceURL="+l);s.call(w)}else{}}u=null}},syncRequire:function(){var k=this.syncModeEnabled;if(!k){this.syncModeEnabled=true}this.require.apply(this,arguments);if(!k){this.syncModeEnabled=false}this.refreshQueue()},require:function(F,t,n,q){var v={},m={},y=this.queue,C=this.classNameToFilePathMap,A=this.isClassFileLoaded,s=[],H=[],E=[],l=[],r,G,x,w,k,p,D,B,z,u,o;if(q){q=h(q);for(B=0,u=q.length;B0){s=a.getNamesByExpression(k);for(z=0,o=s.length;z0){r=function(){var K=[],J,L,I;for(J=0,L=l.length;J0){H=a.getNamesByExpression(w);o=H.length;for(z=0;z0){if(!this.config.enabled){throw new Error("Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing required class"+((E.length>1)?"es":"")+": "+E.join(", "))}}else{r.call(n);return this}G=this.syncModeEnabled;if(!G){y.push({requires:E.slice(),callback:r,scope:n})}u=E.length;for(B=0;B');document.write('');document.write('');if(Ext.isString(d)){document.write('')}if(l&&j){document.write('')}if(q&&!j){document.write('')}if(Ext.isString(o)||Ext.isString(k)||Ext.isString(m)){o={"57":k||m||o,"72":m||k||o,"114":k||m||o}}g=(s.glossOnIcon===false)?"-precomposed":"";if(o){var t=o["72"],e=o["57"],h=o["114"],r='')}else{if(!j){if(e){document.write(r+g+'" href="'+e+'">')}if(h){document.write(r+g+'" sizes="114x114" href="'+h+'">')}}}}}},application:function(a){var c,b;if(!a){a={}}Ext.Loader.setPath(a.name,a.appFolder||"app");a.requires=Ext.Array.from(a.requires);a.requires.push("Ext.app.Application");c=a.onReady;b=a.scope;a.onReady=function(){new Ext.app.Application(a);if(c){c.call(b)}};Ext.setup(a)},factoryConfig:function(a,l){var g=Ext.isSimpleObject(a);if(g&&a.xclass){var f=a.xclass;delete a.xclass;Ext.require(f,function(){Ext.factoryConfig(a,function(i){l(Ext.create(f,i))})});return}var d=Ext.isArray(a),m=[],k,j,c,e;if(g||d){if(g){for(k in a){if(a.hasOwnProperty(k)){j=a[k];if(Ext.isSimpleObject(j)||Ext.isArray(j)){m.push(k)}}}}else{for(c=0,e=a.length;c=e){l(a);return}k=m[c];j=a[k];Ext.factoryConfig(j,h)}b();return}l(a)},factory:function(b,e,a,f){var d=Ext.ClassManager,c;if(!b||b.isInstance){if(a&&a!==b){a.destroy()}return b}if(f){if(typeof b=="string"){return d.instantiateByAlias(f+"."+b)}else{if(Ext.isObject(b)&&"type" in b){return d.instantiateByAlias(f+"."+b.type,b)}}}else{if(typeof b=="string"){return Ext.getCmp(b)}}if(b===true){if(a){return a}else{return d.instantiate(e)}}if("xtype" in b){c=d.instantiateByAlias("widget."+b.xtype,b)}if("xclass" in b){c=d.instantiate(b.xclass,b)}if(c){if(a){a.destroy()}return c}if(a){return a.setConfig(b)}return d.instantiate(e,b)},deprecateClassMember:function(b,c,a,d){return this.deprecateProperty(b.prototype,c,a,d)},deprecateClassMembers:function(b,c){var d=b.prototype,e,a;for(e in c){if(c.hasOwnProperty(e)){a=c[e];this.deprecateProperty(d,e,a)}}},deprecateProperty:function(b,c,a,d){if(!d){d="'"+c+"' is deprecated"}if(a){d+=", please use '"+a+"' instead"}if(a){Ext.Object.defineProperty(b,c,{get:function(){return this[a]},set:function(e){this[a]=e},configurable:true})}},deprecatePropertyValue:function(b,a,d,c){Ext.Object.defineProperty(b,a,{get:function(){return d},configurable:true})},deprecateMethod:function(b,a,d,c){b[a]=function(){if(d){return d.apply(this,arguments)}}},deprecateClassMethod:function(a,b,h,d){if(typeof b!="string"){var g,f;for(g in b){if(b.hasOwnProperty(g)){f=b[g];Ext.deprecateClassMethod(a,g,f)}}return}var c=typeof h=="string",e;if(!d){d="'"+b+"()' is deprecated, please use '"+(c?h:h.name)+"()' instead"}if(c){e=function(){return this[h].apply(this,arguments)}}else{e=function(){return h.apply(this,arguments)}}if(b in a.prototype){Ext.Object.defineProperty(a.prototype,b,{value:null,writable:true,configurable:true})}a.addMember(b,e)},isReady:false,readyListeners:[],triggerReady:function(){var b=Ext.readyListeners,a,c,d;if(!Ext.isReady){Ext.isReady=true;for(a=0,c=b.length;a0){return b+Ext.String.capitalize(a)}return a}},function(){var a=Ext.browser=new this(Ext.global.navigator.userAgent)});Ext.define("Ext.env.OS",{requires:["Ext.Version"],statics:{names:{ios:"iOS",android:"Android",webos:"webOS",blackberry:"BlackBerry",rimTablet:"RIMTablet",mac:"MacOS",win:"Windows",linux:"Linux",bada:"Bada",other:"Other"},prefixes:{ios:"i(?:Pad|Phone|Pod)(?:.*)CPU(?: iPhone)? OS ",android:"(Android |HTC_|Silk/)",blackberry:"BlackBerry(?:.*)Version/",rimTablet:"RIM Tablet OS ",webos:"(?:webOS|hpwOS)/",bada:"Bada/"}},is:Ext.emptyFn,name:null,version:null,setFlag:function(a,b){if(typeof b=="undefined"){b=true}this.is[a]=b;this.is[a.toLowerCase()]=b;return this},constructor:function(m,b){var k=this.statics(),j=k.names,c=k.prefixes,a,h="",d,g,f,l,e;e=this.is=function(i){return this.is[i]===true};for(d in c){if(c.hasOwnProperty(d)){g=c[d];f=m.match(new RegExp("(?:"+g+")([^\\s;]+)"));if(f){a=j[d];if(f[1]&&(f[1]=="HTC_"||f[1]=="Silk/")){h=new Ext.Version("2.3")}else{h=new Ext.Version(f[f.length-1])}break}}}if(!a){a=j[(m.toLowerCase().match(/mac|win|linux/)||["other"])[0]];h=new Ext.Version("")}this.name=a;this.version=h;if(b){this.setFlag(b)}this.setFlag(a);if(h){this.setFlag(a+(h.getMajor()||""));this.setFlag(a+h.getShortVersion())}for(d in j){if(j.hasOwnProperty(d)){l=j[d];if(!e.hasOwnProperty(a)){this.setFlag(l,(a===l))}}}return this}},function(){var a=Ext.global.navigator,e=a.userAgent,b,g,d;Ext.os=b=new this(e,a.platform);g=b.name;var c=window.location.search.match(/deviceType=(Tablet|Phone)/),f=window.deviceType;if(c&&c[1]){d=c[1]}else{if(f==="iPhone"){d="Phone"}else{if(f==="iPad"){d="Tablet"}else{if(!b.is.Android&&!b.is.iOS&&/Windows|Linux|MacOS/.test(g)){d="Desktop"}else{if(b.is.iPad||b.is.Android3||(b.is.Android4&&e.search(/mobile/i)==-1)){d="Tablet"}else{d="Phone"}}}}}b.setFlag(d,true);b.deviceType=d});Ext.define("Ext.env.Feature",{requires:["Ext.env.Browser","Ext.env.OS"],constructor:function(){this.testElements={};this.has=function(a){return !!this.has[a]};return this},getTestElement:function(a,b){if(a===undefined){a="div"}else{if(typeof a!=="string"){return a}}if(b){return document.createElement(a)}if(!this.testElements[a]){this.testElements[a]=document.createElement(a)}return this.testElements[a]},isStyleSupported:function(c,b){var d=this.getTestElement(b).style,a=Ext.String.capitalize(c);if(typeof d[c]!=="undefined"||typeof d[Ext.browser.getStylePrefix(c)+a]!=="undefined"){return true}return false},isEventSupported:function(c,a){if(a===undefined){a=window}var e=this.getTestElement(a),b="on"+c.toLowerCase(),d=(b in e);if(!d){if(e.setAttribute&&e.removeAttribute){e.setAttribute(b,"");d=typeof e[b]==="function";if(typeof e[b]!=="undefined"){e[b]=undefined}e.removeAttribute(b)}}return d},getSupportedPropertyName:function(b,a){var c=Ext.browser.getVendorProperyName(a);if(c in b){return c}else{if(a in b){return a}}return null},registerTest:Ext.Function.flexSetter(function(a,b){this.has[a]=b.call(this);return this})},function(){Ext.feature=new this;var a=Ext.feature.has;Ext.feature.registerTest({Canvas:function(){var b=this.getTestElement("canvas");return !!(b&&b.getContext&&b.getContext("2d"))},Svg:function(){var b=document;return !!(b.createElementNS&&!!b.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect)},Vml:function(){var c=this.getTestElement(),b=false;c.innerHTML="";b=(c.childNodes.length===1);c.innerHTML="";return b},Touch:function(){return this.isEventSupported("touchstart")&&!(Ext.os&&Ext.os.name.match(/Windows|MacOSX|Linux/))},Orientation:function(){return("orientation" in window)&&this.isEventSupported("orientationchange")},OrientationChange:function(){return this.isEventSupported("orientationchange")},DeviceMotion:function(){return this.isEventSupported("devicemotion")},Geolocation:function(){return"geolocation" in window.navigator},SqlDatabase:function(){return"openDatabase" in window},WebSockets:function(){return"WebSocket" in window},Range:function(){return !!document.createRange},CreateContextualFragment:function(){var b=!!document.createRange?document.createRange():false;return b&&!!b.createContextualFragment},History:function(){return("history" in window&&"pushState" in window.history)},CssTransforms:function(){return this.isStyleSupported("transform")},Css3dTransforms:function(){return this.has("CssTransforms")&&this.isStyleSupported("perspective")&&!Ext.os.is.Android2},CssAnimations:function(){return this.isStyleSupported("animationName")},CssTransitions:function(){return this.isStyleSupported("transitionProperty")},Audio:function(){return !!this.getTestElement("audio").canPlayType},Video:function(){return !!this.getTestElement("video").canPlayType},ClassList:function(){return"classList" in this.getTestElement()}})});Ext.define("Ext.dom.Query",{select:function(h,b){var g=[],d,f,e,c,a;b=b||document;if(typeof b=="string"){b=document.getElementById(b)}h=h.split(",");for(f=0,c=h.length;f")}else{c.push(">");if((h=d.tpl)){h.applyOut(d.tplData,c)}if((h=d.html)){c.push(h)}if((h=d.cn||d.children)){g.generateMarkup(h,c)}f=g.closeTags;c.push(f[a]||(f[a]=""))}}}return c},generateStyles:function(e,c){var b=c||[],d;for(d in e){if(e.hasOwnProperty(d)){b.push(this.decamelizeName(d),":",e[d],";")}}return c||b.join("")},markup:function(a){if(typeof a=="string"){return a}var b=this.generateMarkup(a,[]);return b.join("")},applyStyles:function(a,b){Ext.fly(a).applyStyles(b)},createContextualFragment:function(c){var f=document.createElement("div"),a=document.createDocumentFragment(),b=0,d,e;f.innerHTML=c;e=f.childNodes;d=e.length;for(;b0){this.id=b=a.id}else{a.id=b=this.mixins.identifiable.getUniqueId.call(this)}this.self.cache[b]=this}return b},setId:function(c){var a=this.id,b=this.self.cache;if(a){delete b[a]}this.dom.id=c;this.id=c;b[c]=this;return this},setHtml:function(a){this.dom.innerHTML=a},getHtml:function(){return this.dom.innerHTML},setText:function(a){this.dom.textContent=a},redraw:function(){var b=this.dom,a=b.style;a.display="none";b.offsetHeight;a.display=""},isPainted:function(){return Boolean(this.dom.offsetParent)},set:function(a,b){var e=this.dom,c,d;for(c in a){if(a.hasOwnProperty(c)){d=a[c];if(c=="style"){this.applyStyles(d)}else{if(c=="cls"){e.className=d}else{if(b!==false){if(d===undefined){e.removeAttribute(c)}else{e.setAttribute(c,d)}}else{e[c]=d}}}}}return this},is:function(a){return Ext.DomQuery.is(this.dom,a)},getValue:function(b){var a=this.dom.value;return b?parseInt(a,10):a},getAttribute:function(a,b){var c=this.dom;return c.getAttributeNS(b,a)||c.getAttribute(b+":"+a)||c.getAttribute(a)||c[a]},destroy:function(){this.isDestroyed=true;var a=Ext.Element.cache,b=this.dom;if(b&&b.parentNode&&b.tagName!="BODY"){b.parentNode.removeChild(b)}delete a[this.id];delete this.dom}},function(a){Ext.elements=Ext.cache=a.cache;this.addStatics({Fly:new Ext.Class({extend:a,constructor:function(b){this.dom=b}}),_flyweights:{},fly:function(d,b){var e=null,c=a._flyweights;b=b||"_global";d=Ext.getDom(d);if(d){e=c[b]||(c[b]=new a.Fly());e.dom=d;e.isSynchronized=false}return e}});Ext.get=function(b){return a.get.call(a,b)};Ext.fly=function(){return a.fly.apply(a,arguments)};Ext.ClassManager.onCreated(function(){a.mixin("observable",Ext.mixin.Observable)},null,"Ext.mixin.Observable")});Ext.dom.Element.addStatics({unitRe:/\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,camelRe:/(-[a-z])/gi,cssRe:/([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,opacityRe:/alpha\(opacity=(.*)\)/i,propertyCache:{},defaultUnit:"px",borders:{l:"border-left-width",r:"border-right-width",t:"border-top-width",b:"border-bottom-width"},paddings:{l:"padding-left",r:"padding-right",t:"padding-top",b:"padding-bottom"},margins:{l:"margin-left",r:"margin-right",t:"margin-top",b:"margin-bottom"},addUnits:function(b,a){if(Ext.isNumber(b)){return b+(a||this.defaultUnit||"px")}if(b===""||b=="auto"||b===undefined||b===null){return b||""}if(!this.unitRe.test(b)){return b||""}return b},isAncestor:function(b,d){var a=false;b=Ext.getDom(b);d=Ext.getDom(d);if(b&&d){if(b.contains){return b.contains(d)}else{if(b.compareDocumentPosition){return !!(b.compareDocumentPosition(d)&16)}else{while((d=d.parentNode)){a=d==b||a}}}}return a},parseBox:function(b){if(typeof b!="string"){b=b.toString()}var c=b.split(" "),a=c.length;if(a==1){c[1]=c[2]=c[3]=c[0]}else{if(a==2){c[2]=c[0];c[3]=c[1]}else{if(a==3){c[3]=c[1]}}}return{top:parseFloat(c[0])||0,right:parseFloat(c[1])||0,bottom:parseFloat(c[2])||0,left:parseFloat(c[3])||0}},unitizeBox:function(f,e){var d=this.addUnits,c=this.parseBox(f);return d(c.top,e)+" "+d(c.right,e)+" "+d(c.bottom,e)+" "+d(c.left,e)},camelReplaceFn:function(b,c){return c.charAt(1).toUpperCase()},normalize:function(a){return this.propertyCache[a]||(this.propertyCache[a]=a.replace(this.camelRe,this.camelReplaceFn))},fromPoint:function(a,b){return Ext.get(document.elementFromPoint(a,b))},parseStyles:function(c){var a={},b=this.cssRe,d;if(c){b.lastIndex=0;while((d=b.exec(c))){a[d[1]]=d[2]}}return a}});Ext.dom.Element.addMembers({appendChild:function(a){this.dom.appendChild(Ext.getDom(a));return this},removeChild:function(a){this.dom.removeChild(Ext.getDom(a));return this},append:function(){this.appendChild.apply(this,arguments)},appendTo:function(a){Ext.getDom(a).appendChild(this.dom);return this},insertBefore:function(a){a=Ext.getDom(a);a.parentNode.insertBefore(this.dom,a);return this},insertAfter:function(a){a=Ext.getDom(a);a.parentNode.insertBefore(this.dom,a.nextSibling);return this},insertFirst:function(b){var a=Ext.getDom(b),d=this.dom,c=d.firstChild;if(!c){d.appendChild(a)}else{d.insertBefore(a,c)}return this},insertSibling:function(e,c,d){var f=this,b,a=(c||"before").toLowerCase()=="after",g;if(Ext.isArray(e)){g=f;Ext.each(e,function(h){b=Ext.fly(g,"_internal").insertSibling(h,c,d);if(a){g=b}});return b}e=e||{};if(e.nodeType||e.dom){b=f.dom.parentNode.insertBefore(Ext.getDom(e),a?f.dom.nextSibling:f.dom);if(!d){b=Ext.get(b)}}else{if(a&&!f.dom.nextSibling){b=Ext.core.DomHelper.append(f.dom.parentNode,e,!d)}else{b=Ext.core.DomHelper[a?"insertAfter":"insertBefore"](f.dom,e,!d)}}return b},replace:function(a){a=Ext.get(a);this.insertBefore(a);a.remove();return this},replaceWith:function(a){var b=this;if(a.nodeType||a.dom||typeof a=="string"){a=Ext.get(a);b.dom.parentNode.insertBefore(a,b.dom)}else{a=Ext.core.DomHelper.insertBefore(b.dom,a)}delete Ext.cache[b.id];Ext.removeNode(b.dom);b.id=Ext.id(b.dom=a);Ext.dom.Element.addToCache(b.isFlyweight?new Ext.dom.Element(b.dom):b);return b},createChild:function(b,a,c){b=b||{tag:"div"};if(a){return Ext.core.DomHelper.insertBefore(a,b,c!==true)}else{return Ext.core.DomHelper[!this.dom.firstChild?"insertFirst":"append"](this.dom,b,c!==true)}},wrap:function(b,c){var e=this.dom,f=this.self.create(b,c),d=(c)?f:f.dom,a=e.parentNode;if(a){a.insertBefore(d,e)}d.appendChild(e);return f},wrapAllChildren:function(a){var d=this.dom,b=d.childNodes,e=this.self.create(a),c=e.dom;while(b.length>0){c.appendChild(d.firstChild)}d.appendChild(c);return e},unwrapAllChildren:function(){var c=this.dom,b=c.childNodes,a=c.parentNode;if(a){while(b.length>0){a.insertBefore(c,c.firstChild)}this.destroy()}},unwrap:function(){var c=this.dom,a=c.parentNode,b;if(a){b=a.parentNode;b.insertBefore(c,a);b.removeChild(a)}else{b=document.createDocumentFragment();b.appendChild(c)}return this},insertHtml:function(b,c,a){var d=Ext.core.DomHelper.insertHtml(b,this.dom,c);return a?Ext.get(d):d}});Ext.dom.Element.override({getX:function(a){return this.getXY(a)[0]},getY:function(a){return this.getXY(a)[1]},getXY:function(){var a=window.webkitConvertPointFromNodeToPage;if(a){return function(){var b=a(this.dom,new WebKitPoint(0,0));return[b.x,b.y]}}else{return function(){var c=this.dom.getBoundingClientRect(),b=Math.round;return[b(c.left+window.pageXOffset),b(c.top+window.pageYOffset)]}}}(),getOffsetsTo:function(a){var c=this.getXY(),b=Ext.fly(a,"_internal").getXY();return[c[0]-b[0],c[1]-b[1]]},setX:function(a){return this.setXY([a,this.getY()])},setY:function(a){return this.setXY([this.getX(),a])},setXY:function(d){var b=this;if(arguments.length>1){d=[d,arguments[1]]}var c=b.translatePoints(d),a=b.dom.style;for(d in c){if(!c.hasOwnProperty(d)){continue}if(!isNaN(c[d])){a[d]=c[d]+"px"}}return b},getLeft:function(){return parseInt(this.getStyle("left"),10)||0},getRight:function(){return parseInt(this.getStyle("right"),10)||0},getTop:function(){return parseInt(this.getStyle("top"),10)||0},getBottom:function(){return parseInt(this.getStyle("bottom"),10)||0},translatePoints:function(a,g){g=isNaN(a[1])?g:a[1];a=isNaN(a[0])?a:a[0];var d=this,e=d.isStyle("position","relative"),f=d.getXY(),b=parseInt(d.getStyle("left"),10),c=parseInt(d.getStyle("top"),10);b=!isNaN(b)?b:(e?0:d.dom.offsetLeft);c=!isNaN(c)?c:(e?0:d.dom.offsetTop);return{left:(a-f[0]+b),top:(g-f[1]+c)}},setBox:function(d){var c=this,b=d.width,a=d.height,f=d.top,e=d.left;if(e!==undefined){c.setLeft(e)}if(f!==undefined){c.setTop(f)}if(b!==undefined){c.setWidth(b)}if(a!==undefined){c.setHeight(a)}return this},getBox:function(g,j){var h=this,e=h.dom,c=e.offsetWidth,k=e.offsetHeight,n,f,d,a,m,i;if(!j){n=h.getXY()}else{if(g){n=[0,0]}else{n=[parseInt(h.getStyle("left"),10)||0,parseInt(h.getStyle("top"),10)||0]}}if(!g){f={x:n[0],y:n[1],0:n[0],1:n[1],width:c,height:k}}else{d=h.getBorderWidth.call(h,"l")+h.getPadding.call(h,"l");a=h.getBorderWidth.call(h,"r")+h.getPadding.call(h,"r");m=h.getBorderWidth.call(h,"t")+h.getPadding.call(h,"t");i=h.getBorderWidth.call(h,"b")+h.getPadding.call(h,"b");f={x:n[0]+d,y:n[1]+m,0:n[0]+d,1:n[1]+m,width:c-(d+a),height:k-(m+i)}}f.left=f.x;f.top=f.y;f.right=f.x+f.width;f.bottom=f.y+f.height;return f},getPageBox:function(e){var g=this,c=g.dom,j=c.offsetWidth,f=c.offsetHeight,m=g.getXY(),k=m[1],a=m[0]+j,i=m[1]+f,d=m[0];if(!c){return new Ext.util.Region()}if(e){return new Ext.util.Region(k,a,i,d)}else{return{left:d,top:k,width:j,height:f,right:a,bottom:i}}}});Ext.dom.Element.addMembers({WIDTH:"width",HEIGHT:"height",MIN_WIDTH:"min-width",MIN_HEIGHT:"min-height",MAX_WIDTH:"max-width",MAX_HEIGHT:"max-height",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left",VISIBILITY:1,DISPLAY:2,OFFSETS:3,SEPARATOR:"-",trimRe:/^\s+|\s+$/g,wordsRe:/\w/g,spacesRe:/\s+/,styleSplitRe:/\s*(?::|;)\s*/,transparentRe:/^(?:transparent|(?:rgba[(](?:\s*\d+\s*[,]){3}\s*0\s*[)]))$/i,classNameSplitRegex:/[\s]+/,borders:{t:"border-top-width",r:"border-right-width",b:"border-bottom-width",l:"border-left-width"},paddings:{t:"padding-top",r:"padding-right",b:"padding-bottom",l:"padding-left"},margins:{t:"margin-top",r:"margin-right",b:"margin-bottom",l:"margin-left"},defaultUnit:"px",isSynchronized:false,synchronize:function(){var g=this.dom,a={},d=g.className,f,c,e,b;if(d.length>0){f=g.className.split(this.classNameSplitRegex);for(c=0,e=f.length;c0?a:0},getWidth:function(a){var c=this.dom,b=a?(c.clientWidth-this.getPadding("lr")):c.offsetWidth;return b>0?b:0},getBorderWidth:function(a){return this.addStyles(a,this.borders)},getPadding:function(a){return this.addStyles(a,this.paddings)},applyStyles:function(d){if(d){var e=this.dom,c,b,a;if(typeof d=="function"){d=d.call()}c=typeof d;if(c=="string"){d=Ext.util.Format.trim(d).split(this.styleSplitRe);for(b=0,a=d.length;b "+a,c.dom);return b?d:Ext.get(d)},parent:function(a,b){return this.matchNode("parentNode","parentNode",a,b)},next:function(a,b){return this.matchNode("nextSibling","nextSibling",a,b)},prev:function(a,b){return this.matchNode("previousSibling","previousSibling",a,b)},first:function(a,b){return this.matchNode("nextSibling","firstChild",a,b)},last:function(a,b){return this.matchNode("previousSibling","lastChild",a,b)},matchNode:function(b,e,a,c){if(!this.dom){return null}var d=this.dom[e];while(d){if(d.nodeType==1&&(!a||Ext.DomQuery.is(d,a))){return !c?Ext.get(d):d}d=d[b]}return null},isAncestor:function(a){return this.self.isAncestor.call(this.self,this.dom,a)}});Ext.define("Ext.dom.CompositeElementLite",{alternateClassName:["Ext.CompositeElementLite","Ext.CompositeElement"],requires:["Ext.dom.Element"],statics:{importElementMethods:function(){}},constructor:function(b,a){this.elements=[];this.add(b,a);this.el=new Ext.dom.Element.Fly()},isComposite:true,getElement:function(a){return this.el.attach(a)},transformElement:function(a){return Ext.getDom(a)},getCount:function(){return this.elements.length},add:function(c,a){var e=this.elements,b,d;if(!c){return this}if(typeof c=="string"){c=Ext.dom.Element.selectorFunction(c,a)}else{if(c.isComposite){c=c.elements}else{if(!Ext.isIterable(c)){c=[c]}}}for(b=0,d=c.length;b-1){c=Ext.getDom(c);if(a){f=this.elements[b];f.parentNode.insertBefore(c,f);Ext.removeNode(f)}Ext.Array.splice(this.elements,b,1,c)}return this},clear:function(){this.elements=[]},addElements:function(c,a){if(!c){return this}if(typeof c=="string"){c=Ext.dom.Element.selectorFunction(c,a)}var b=this.elements;Ext.each(c,function(d){b.push(Ext.get(d))});return this},first:function(){return this.item(0)},last:function(){return this.item(this.getCount()-1)},contains:function(a){return this.indexOf(a)!=-1},removeElement:function(c,e){var b=this,d=this.elements,a;Ext.each(c,function(f){if((a=(d[f]||d[f=b.indexOf(f)]))){if(e){if(a.dom){a.remove()}else{Ext.removeNode(a)}}Ext.Array.erase(d,f,1)}});return this}},function(){var a=Ext.dom.Element,d=a.prototype,c=this.prototype,b;for(b in d){if(typeof d[b]=="function"){(function(e){c[e]=c[e]||function(){return this.invoke(e,arguments)}}).call(c,b)}}c.on=c.addListener;if(Ext.DomQuery){a.selectorFunction=Ext.DomQuery.select}a.select=function(e,f){var g;if(typeof e=="string"){g=a.selectorFunction(e,f)}else{if(e.length!==undefined){g=e}else{}}return new Ext.CompositeElementLite(g)};Ext.select=function(){return a.select.apply(a,arguments)}});Ext.define("Ext.ComponentManager",{alternateClassName:"Ext.ComponentMgr",singleton:true,constructor:function(){var a={};this.all={map:a,getArray:function(){var b=[],c;for(c in a){b.push(a[c])}return b}};this.map=a},register:function(a){this.map[a.getId()]=a},unregister:function(a){delete this.map[a.getId()]},isRegistered:function(a){return this.map[a]!==undefined},get:function(a){return this.map[a]},create:function(a,c){if(a.isComponent){return a}else{if(Ext.isString(a)){return Ext.createByAlias("widget."+a)}else{var b=a.xtype||c;return Ext.createByAlias("widget."+b,a)}}},registerType:Ext.emptyFn});Ext.define("Ext.ComponentQuery",{singleton:true,uses:["Ext.ComponentManager"]},function(){var g=this,j=["var r = [],","i = 0,","it = items,","l = it.length,","c;","for (; i < l; i++) {","c = it[i];","if (c.{0}) {","r.push(c);","}","}","return r;"].join(""),e=function(o,n){return n.method.apply(this,[o].concat(n.args))},a=function(p,t){var n=[],q=0,s=p.length,r,o=t!==">";for(;q\^])\s?|\s|$)/,c=/^(#)?([\w\-]+|\*)(?:\((true|false)\))?/,b=[{re:/^\.([\w\-]+)(?:\((true|false)\))?/,method:l},{re:/^(?:[\[](?:@)?([\w\-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]])/,method:m},{re:/^#([\w\-]+)/,method:d},{re:/^\:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/,method:k},{re:/^(?:\{([^\}]+)\})/,method:j}];g.Query=Ext.extend(Object,{constructor:function(n){n=n||{};Ext.apply(this,n)},execute:function(o){var q=this.operations,r=0,s=q.length,p,n;if(!o){n=Ext.ComponentManager.all.getArray()}else{if(Ext.isArray(o)){n=o}}for(;r1){for(q=0,r=s.length;q1){r=q.length;for(p=0;p]*)\>)|(?:<\/tpl>)/g,actionsRe:/\s*(elif|elseif|if|for|exec|switch|case|eval)\s*\=\s*(?:(?:["]([^"]*)["])|(?:[']([^']*)[']))\s*/g,defaultRe:/^\s*default\s*$/,elseRe:/^\s*else\s*$/});Ext.define("Ext.app.Action",{config:{scope:null,application:null,controller:null,action:null,args:[],url:undefined,data:{},title:null,beforeFilters:[],currentFilterIndex:-1},constructor:function(a){this.initConfig(a);this.getUrl()},execute:function(){this.resume()},resume:function(){var b=this.getCurrentFilterIndex()+1,c=this.getBeforeFilters(),a=this.getController(),d=c[b];if(d){this.setCurrentFilterIndex(b);d.call(a,this)}else{a[this.getAction()].apply(a,this.getArgs())}},applyUrl:function(a){if(a===null||a===undefined){a=this.urlEncode()}return a},applyController:function(a){var c=this.getApplication(),b=c.getCurrentProfile();if(Ext.isString(a)){a=c.getController(a,b?b.getNamespace():null)}return a},urlEncode:function(){var a=this.getController(),b;if(a instanceof Ext.app.Controller){b=a.$className.split(".");a=b[b.length-1]}return a+"/"+this.getAction()}});Ext.define("Ext.app.Route",{config:{conditions:{},url:null,controller:null,action:null,initialized:false},constructor:function(a){this.initConfig(a)},recognize:function(b){if(!this.getInitialized()){this.initialize()}if(this.recognizes(b)){var c=this.matchesFor(b),a=b.match(this.matcherRegex);a.shift();return Ext.applyIf(c,{controller:this.getController(),action:this.getAction(),historyUrl:b,args:a})}},initialize:function(){this.paramMatchingRegex=new RegExp(/:([0-9A-Za-z\_]*)/g);this.paramsInMatchString=this.getUrl().match(this.paramMatchingRegex)||[];this.matcherRegex=this.createMatcherRegex(this.getUrl());this.setInitialized(true)},recognizes:function(a){return this.matcherRegex.test(a)},matchesFor:function(b){var f={},e=this.paramsInMatchString,a=b.match(this.matcherRegex),d=e.length,c;a.shift();for(c=0;c0){f.timeout=setTimeout(Ext.bind(i.handleTimeout,i,[f]),l)}i.setupErrorHandling(f);i[k]=Ext.bind(i.handleResponse,i,[f],true);i.loadScript(f);return f},abort:function(b){var c=this.statics().requests,a;if(b){if(!b.id){b=c[b]}this.abort(b)}else{for(a in c){if(c.hasOwnProperty(a)){this.abort(c[a])}}}},setupErrorHandling:function(a){a.script.onerror=Ext.bind(this.handleError,this,[a])},handleAbort:function(a){a.errorType="abort";this.handleResponse(null,a)},handleError:function(a){a.errorType="error";this.handleResponse(null,a)},cleanupErrorHandling:function(a){a.script.onerror=null},handleTimeout:function(a){a.errorType="timeout";this.handleResponse(null,a)},handleResponse:function(a,b){var c=true;if(b.timeout){clearTimeout(b.timeout)}delete this[b.callbackName];delete this.statics()[b.id];this.cleanupErrorHandling(b);Ext.fly(b.script).destroy();if(b.errorType){c=false;Ext.callback(b.failure,b.scope,[b.errorType])}else{Ext.callback(b.success,b.scope,[a])}Ext.callback(b.callback,b.scope,[c,a,b.errorType])},createScript:function(c,d,b){var a=document.createElement("script");a.setAttribute("src",Ext.urlAppend(c,Ext.Object.toQueryString(d)));a.setAttribute("async",true);a.setAttribute("type","text/javascript");return a},loadScript:function(a){Ext.getHead().appendChild(a.script)}});Ext.define("Ext.data.Operation",{config:{synchronous:true,action:null,filters:null,sorters:null,grouper:null,start:null,limit:null,batch:null,callback:null,scope:null,resultSet:null,records:null,request:null,response:null,withCredentials:null,params:null,url:null,page:null,node:null,model:undefined,addRecords:false},started:false,running:false,complete:false,success:undefined,exception:false,error:undefined,constructor:function(a){this.initConfig(a)},applyModel:function(a){if(typeof a=="string"){a=Ext.data.ModelManager.getModel(a);if(!a){Ext.Logger.error("Model with name "+arguments[0]+" doesnt exist.")}}if(a&&!a.prototype.isModel&&Ext.isObject(a)){a=Ext.data.ModelManager.registerType(a.storeId||a.id||Ext.id(),a)}return a},getRecords:function(){var a=this.getResultSet();return this._records||(a?a.getRecords():[])},setStarted:function(){this.started=true;this.running=true},setCompleted:function(){this.complete=true;this.running=false},setSuccessful:function(){this.success=true},setException:function(a){this.exception=true;this.success=false;this.running=false;this.error=a},hasException:function(){return this.exception===true},getError:function(){return this.error},isStarted:function(){return this.started===true},isRunning:function(){return this.running===true},isComplete:function(){return this.complete===true},wasSuccessful:function(){return this.isComplete()&&this.success===true},allowWrite:function(){return this.getAction()!="read"},process:function(d,b,c,a){if(b.getSuccess()!==false){this.setResponse(a);this.setResultSet(b);this.setCompleted();this.setSuccessful()}else{return false}return this["process"+Ext.String.capitalize(d)].call(this,b,c,a)},processRead:function(d){var b=d.getRecords(),g=[],f=this.getModel(),e=b.length,c,a;for(c=0;c]+>/gi,none:function(a){return a},asText:function(a){return String(a).replace(this.stripTagsRE,"")},asUCText:function(a){return String(a).toUpperCase().replace(this.stripTagsRE,"")},asUCString:function(a){return String(a).toUpperCase()},asDate:function(a){if(!a){return 0}if(Ext.isDate(a)){return a.getTime()}return Date.parse(String(a))},asFloat:function(a){a=parseFloat(String(a).replace(/,/g,""));return isNaN(a)?0:a},asInt:function(a){a=parseInt(String(a).replace(/,/g,""),10);return isNaN(a)?0:a}});Ext.define("Ext.data.Types",{singleton:true,requires:["Ext.data.SortTypes"],stripRe:/[\$,%]/g,dashesRe:/-/g,iso8601TestRe:/\d\dT\d\d/,iso8601SplitRe:/[- :T\.Z\+]/},function(){var b=this,a=Ext.data.SortTypes;Ext.apply(b,{AUTO:{convert:function(c){return c},sortType:a.none,type:"auto"},STRING:{convert:function(c){return(c===undefined||c===null)?(this.getAllowNull()?null:""):String(c)},sortType:a.asUCString,type:"string"},INT:{convert:function(c){return(c!==undefined&&c!==null&&c!=="")?((typeof c==="number")?parseInt(c,10):parseInt(String(c).replace(b.stripRe,""),10)):(this.getAllowNull()?null:0)},sortType:a.none,type:"int"},FLOAT:{convert:function(c){return(c!==undefined&&c!==null&&c!=="")?((typeof c==="number")?c:parseFloat(String(c).replace(b.stripRe,""),10)):(this.getAllowNull()?null:0)},sortType:a.none,type:"float"},BOOL:{convert:function(c){if((c===undefined||c===null||c==="")&&this.getAllowNull()){return null}return c===true||c==="true"||c==1},sortType:a.none,type:"bool"},DATE:{convert:function(e){var c=this.getDateFormat(),d;if(!e){return null}if(Ext.isDate(e)){return e}if(c){if(c=="timestamp"){return new Date(e*1000)}if(c=="time"){return new Date(parseInt(e,10))}return Ext.Date.parse(e,c)}d=new Date(Date.parse(e));if(isNaN(d)){if(b.iso8601TestRe.test(e)){d=e.split(b.iso8601SplitRe);d=new Date(d[0],d[1]-1,d[2],d[3],d[4],d[5])}if(isNaN(d)){d=new Date(Date.parse(e.replace(this.dashesRe,"/")))}}return isNaN(d)?null:d},sortType:a.asDate,type:"date"}});Ext.apply(b,{BOOLEAN:this.BOOL,INTEGER:this.INT,NUMBER:this.FLOAT})});Ext.define("Ext.data.Validations",{alternateClassName:"Ext.data.validations",singleton:true,config:{presenceMessage:"must be present",lengthMessage:"is the wrong length",formatMessage:"is the wrong format",inclusionMessage:"is not included in the list of acceptable values",exclusionMessage:"is not an acceptable value",emailMessage:"is not a valid email address"},constructor:function(a){this.initConfig(a)},getMessage:function(a){var b=this["get"+a[0].toUpperCase()+a.slice(1)+"Message"];if(b){return b.call(this)}return""},emailRe:/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,presence:function(a,b){if(b===undefined){b=a}return !!b||b===0},length:function(b,e){if(e===undefined||e===null){return false}var d=e.length,c=b.min,a=b.max;if((c&&da)){return false}else{return true}},email:function(b,a){return Ext.data.validations.emailRe.test(a)},format:function(a,b){return !!(a.matcher&&a.matcher.test(b))},inclusion:function(a,b){return a.list&&Ext.Array.indexOf(a.list,b)!=-1},exclusion:function(a,b){return a.list&&Ext.Array.indexOf(a.list,b)==-1}});Ext.define("Ext.data.identifier.Simple",{alias:"data.identifier.simple",statics:{AUTO_ID:1},config:{prefix:"ext-record-"},constructor:function(a){this.initConfig(a)},generate:function(a){return this._prefix+this.self.AUTO_ID++}});Ext.define("Ext.data.identifier.Uuid",{extend:"Ext.data.identifier.Simple",alias:"data.identifier.uuid",config:{id:undefined,salt:null,timestamp:null,version:4},applyId:function(a){if(a===undefined){return Ext.data.identifier.Uuid.Global}return a},constructor:function(){var a=this;a.callParent(arguments);a.parts=[];a.init()},reconfigure:function(a){this.setConfig(a);this.init()},generate:function(){var c=this,e=c.parts,a=c.getVersion(),b=c.getSalt(),d=c.getTimestamp();e[0]=c.toHex(d.lo,8);e[1]=c.toHex(d.hi&65535,4);e[2]=c.toHex(((d.hi>>>16)&4095)|(a<<12),4);e[3]=c.toHex(128|((c.clockSeq>>>8)&63),2)+c.toHex(c.clockSeq&255,2);e[4]=c.toHex(b.hi,4)+c.toHex(b.lo,8);if(a==4){c.init()}else{++d.lo;if(d.lo>=c.twoPow32){d.lo=0;++d.hi}}return e.join("-").toLowerCase()},init:function(){var b=this,a=b.getSalt(),c=b.getTimestamp();if(b.getVersion()==4){b.clockSeq=b.rand(0,b.twoPow14-1);if(!a){a={};b.setSalt(a)}if(!c){c={};b.setTimestamp(c)}a.lo=b.rand(0,b.twoPow32-1);a.hi=b.rand(0,b.twoPow16-1);c.lo=b.rand(0,b.twoPow32-1);c.hi=b.rand(0,b.twoPow28-1)}else{b.setSalt(b.split(b.getSalt()));b.setTimestamp(b.split(b.getTimestamp()));b.getSalt().hi|=256}},twoPow14:Math.pow(2,14),twoPow16:Math.pow(2,16),twoPow28:Math.pow(2,28),twoPow32:Math.pow(2,32),toHex:function(c,b){var a=c.toString(16);if(a.length>b){a=a.substring(a.length-b)}else{if(a.length")}for(;c");for(j in k){if(k.hasOwnProperty(j)){d.push("<",j,">",k[j],"")}}d.push("")}if(h){d.push("")}a.setXmlData(d.join(""));return a}});Ext.define("Ext.direct.RemotingMethod",{config:{name:null,params:null,formHandler:null,len:null,ordered:true},constructor:function(a){this.initConfig(a)},applyParams:function(f){if(Ext.isNumber(f)){this.setLen(f)}else{if(Ext.isArray(f)){this.setOrdered(false);var d=f.length,b=[],c,e,a;for(c=0;c0){if(a){for(c=0,d=a.length;c0){k.apply(m,l)}if(a){k.call(m,e)}if(c.length>0){k.apply(m,c)}if(b){k.call(m,e)}if(o.length>0){k.apply(m,o)}}else{for(f=0;f0){k.apply(m,l)}}if(a){k.call(m,e)}for(f=0;f0){k.apply(m,c)}}if(b){k.call(m,e)}for(f=0;f0){k.apply(m,o)}}}if(m.length===0){return this}if(!h){h=[]}d.length=0;d.push.apply(d,h);d.push(null,this);this.doFire();return this},doFire:function(){var k=this.firingListeners,c=this.firingArguments,g=c.length-2,d,f,b,o,h,n,a,j,l,e,m;this.isPausing=false;this.isPaused=false;this.isStopped=false;this.isFiring=true;for(d=0,f=k.length;d0){this.isPaused=false;this.doFire()}if(a){a.resume()}return this},isInterrupted:function(){return this.isStopped||this.isPaused},stop:function(){var a=this.connectingController;this.isStopped=true;if(a){this.connectingController=null;a.stop()}this.isFiring=false;this.listenerStacks=null;return this},pause:function(){var a=this.connectingController;this.isPausing=true;if(a){a.pause()}return this}});Ext.define("Ext.event.Event",{alternateClassName:"Ext.EventObject",isStopped:false,set:function(a,b){if(arguments.length===1&&typeof a!="string"){var c=a;for(a in c){if(c.hasOwnProperty(a)){this[a]=c[a]}}}else{this[a]=c[a]}},stopEvent:function(){return this.stopPropagation()},stopPropagation:function(){this.isStopped=true;return this}});Ext.define("Ext.event.ListenerStack",{currentOrder:"current",length:0,constructor:function(){this.listeners={before:[],current:[],after:[]};this.lateBindingMap={};return this},add:function(h,j,k,e){var a=this.lateBindingMap,g=this.getAll(e),f=g.length,b,d,c;if(typeof h=="string"&&j.isIdentifiable){c=j.getId();b=a[c];if(b){if(b[h]){return false}else{b[h]=true}}else{a[c]=b={};b[h]=true}}else{if(f>0){while(f--){d=g[f];if(d.fn===h&&d.scope===j){d.options=k;return false}}}}d=this.create(h,j,k,e);if(k&&k.prepend){delete k.prepend;g.unshift(d)}else{g.push(d)}this.length++;return true},getAt:function(b,a){return this.getAll(a)[b]},getAll:function(a){if(!a){a=this.currentOrder}return this.listeners[a]},count:function(a){return this.getAll(a).length},create:function(d,c,b,a){return{stack:this,fn:d,firingFn:false,boundFn:false,isLateBinding:typeof d=="string",scope:c,options:b||{},order:a}},remove:function(h,j,e){var g=this.getAll(e),f=g.length,b=false,a=this.lateBindingMap,d,c;if(f>0){while(f--){d=g[f];if(d.fn===h&&d.scope===j){g.splice(f,1);b=true;this.length--;if(typeof h=="string"&&j.isIdentifiable){c=j.getId();if(a[c]&&a[c][h]){delete a[c][h]}}break}}}return b}});Ext.define("Ext.event.publisher.Publisher",{targetType:"",idSelectorRegex:/^#([\w\-]+)$/i,constructor:function(){var b=this.handledEvents,a,c,e,d;a=this.handledEventsMap={};for(c=0,e=b.length;cb){this.isEnded=true;return this.getEndValue()}else{return this.getStartValue()+((a/b)*this.distance)}}});Ext.define("Ext.fx.easing.Momentum",{extend:"Ext.fx.easing.Abstract",config:{acceleration:30,friction:0,startVelocity:0},alpha:0,updateFriction:function(b){var a=Math.log(1-(b/10));this.theta=a;this.alpha=a/this.getAcceleration()},updateStartVelocity:function(a){this.velocity=a*this.getAcceleration()},updateAcceleration:function(a){this.velocity=this.getStartVelocity()*a;this.alpha=this.theta/a},getValue:function(){return this.getStartValue()-this.velocity*(1-this.getFrictionFactor())/this.theta},getFrictionFactor:function(){var a=Ext.Date.now()-this.getStartTime();return Math.exp(a*this.alpha)},getVelocity:function(){return this.getFrictionFactor()*this.velocity}});Ext.define("Ext.mixin.Mixin",{onClassExtended:function(b,e){var a=e.mixinConfig,d,f,c;if(a){d=b.superclass.mixinConfig;if(d){a=e.mixinConfig=Ext.merge({},d,a)}e.mixinId=a.id;f=a.beforeHooks;c=a.hooks||a.afterHooks;if(f||c){Ext.Function.interceptBefore(e,"onClassMixedIn",function(h){var g=this.prototype;if(f){Ext.Object.each(f,function(j,i){h.override(i,function(){if(g[j].apply(this,arguments)!==false){return this.callOverridden(arguments)}})})}if(c){Ext.Object.each(c,function(j,i){h.override(i,function(){var k=this.callOverridden(arguments);g[j].apply(this,arguments);return k})})}})}}}});Ext.define("Ext.mixin.Selectable",{extend:"Ext.mixin.Mixin",mixinConfig:{id:"selectable",hooks:{updateStore:"updateStore"}},config:{disableSelection:null,mode:"SINGLE",allowDeselect:false,lastSelected:null,lastFocused:null,deselectOnContainerClick:true},modes:{SINGLE:true,SIMPLE:true,MULTI:true},selectableEventHooks:{addrecords:"onSelectionStoreAdd",removerecords:"onSelectionStoreRemove",updaterecord:"onSelectionStoreUpdate",load:"refreshSelection",refresh:"refreshSelection"},constructor:function(){this.selected=new Ext.util.MixedCollection();this.callParent(arguments)},applyMode:function(a){a=a?a.toUpperCase():"SINGLE";return this.modes[a]?a:"SINGLE"},updateStore:function(a,c){var b=this,d=Ext.apply({},b.selectableEventHooks,{scope:b});if(c&&Ext.isObject(c)&&c.isStore){if(c.autoDestroy){c.destroy()}else{c.un(d)}}if(a){a.on(d);b.refreshSelection()}},selectAll:function(a){var e=this,c=e.getStore().getRange(),d=c.length,b=0;for(;bd){f=d;d=l;l=f}for(e=l;e<=d;e++){if(g.isSelected(k.getAt(e))){c++}}if(!b){a=-1}else{a=(b=="up")?l:d}for(e=l;e<=d;e++){if(c==(d-l+1)){if(e!=a){g.deselect(e,true)}}else{g.select(e,true)}}},select:function(c,e,b){var d=this,a;if(d.getDisableSelection()){return}if(typeof c==="number"){c=[d.getStore().getAt(c)]}if(!c){return}if(d.getMode()=="SINGLE"&&c){a=c.length?c[0]:c;d.doSingleSelect(a,b)}else{d.doMultiSelect(c,e,b)}},doSingleSelect:function(a,b){var d=this,c=d.selected;if(d.getDisableSelection()){return}if(d.isSelected(a)){return}if(c.getCount()>0){d.deselect(d.getLastSelected(),b)}c.add(a);d.setLastSelected(a);d.onItemSelect(a,b);d.setLastFocused(a);d.fireSelectionChange(!b)},doMultiSelect:function(a,j,h){if(a===null||this.getDisableSelection()){return}a=!Ext.isArray(a)?[a]:a;var f=this,b=f.selected,e=a.length,g=false,c=0,d;if(!j&&b.getCount()>0){g=true;f.deselect(f.getSelection(),true)}for(;c0},refreshSelection:function(){var b=this,a=b.getSelection();b.deselectAll(true);if(a.length){b.select(a,false,true)}},onSelectionStoreClear:function(){var b=this,a=b.selected;if(a.getCount()>0){a.clear();b.setLastSelected(null);b.setLastFocused(null);b.fireSelectionChange(true)}},onSelectionStoreRemove:function(b,a){var d=this,c=d.selected;if(d.getDisableSelection()){return}if(c.remove(a)){if(d.getLastSelected()==a){d.setLastSelected(null)}if(d.getLastFocused()==a){d.setLastFocused(null)}d.fireSelectionChange(true)}},getSelectionCount:function(){return this.selected.getCount()},onSelectionStoreAdd:Ext.emptyFn,onSelectionStoreUpdate:Ext.emptyFn,onItemSelect:Ext.emptyFn,onItemDeselect:Ext.emptyFn,onLastFocusChanged:Ext.emptyFn,onEditorKey:Ext.emptyFn},function(){});Ext.define("Ext.mixin.Traversable",{extend:"Ext.mixin.Mixin",mixinConfig:{id:"traversable"},setParent:function(a){this.parent=a;return this},hasParent:function(){return Boolean(this.parent)},getParent:function(){return this.parent},getAncestors:function(){var b=[],a=this.getParent();while(a){b.push(a);a=a.getParent()}return b},getAncestorIds:function(){var b=[],a=this.getParent();while(a){b.push(a.getId());a=a.getParent()}return b}});Ext.define("Ext.util.DelayedTask",{config:{interval:null,delay:null,fn:null,scope:null,args:null},constructor:function(d,c,b){var a={fn:d,scope:c,args:b};this.initConfig(a)},delay:function(b,f,e,a){var d=this;d.cancel();d.setConfig({delay:b,fn:f,scope:e,args:a});var c=function(){d.getFn().apply(d.getScope(),d.getArgs()||[]);d.cancel()};d.setInterval(setInterval(c,d.getDelay()))},cancel:function(){this.setInterval(null)},updateInterval:function(a,b){if(b){clearInterval(b)}},applyArgs:function(a){if(!Ext.isArray(a)){a=[a]}return a}});Ext.define("Ext.util.Filter",{isFilter:true,config:{property:null,value:null,filterFn:Ext.emptyFn,anyMatch:false,exactMatch:false,caseSensitive:false,root:null,id:undefined,scope:null},applyId:function(a){if(!a){if(this.getProperty()){a=this.getProperty()+"-"+String(this.getValue())}if(!a){a=Ext.id(null,"ext-filter-")}}return a},constructor:function(a){this.initConfig(a)},applyFilterFn:function(b){if(b===Ext.emptyFn){b=this.getInitialConfig("filter");if(b){return b}var a=this.getValue();if(!this.getProperty()&&!a&&a!==0){return Ext.emptyFn}else{return this.createFilterFn()}}return b},createFilterFn:function(){var a=this,b=a.createValueMatcher();return function(d){var c=a.getRoot(),e=a.getProperty();if(c){d=d[c]}return b.test(d[e])}},createValueMatcher:function(){var d=this,e=d.getValue(),f=d.getAnyMatch(),c=d.getExactMatch(),a=d.getCaseSensitive(),b=Ext.String.escapeRegex;if(e===null||e===undefined||!e.exec){e=String(e);if(f===true){e=b(e)}else{e="^"+b(e);if(c===true){e+="$"}}e=new RegExp(e,a?"":"i")}return e}});Ext.define("Ext.util.Point",{radianToDegreeConstant:180/Math.PI,statics:{fromEvent:function(b){var a=b.changedTouches,c=(a&&a.length>0)?a[0]:b;return this.fromTouch(c)},fromTouch:function(a){return new this(a.pageX,a.pageY)},from:function(a){if(!a){return new this(0,0)}if(!(a instanceof this)){return new this(a.x,a.y)}return a}},constructor:function(a,b){if(typeof a=="undefined"){a=0}if(typeof b=="undefined"){b=0}this.x=a;this.y=b;return this},clone:function(){return new this.self(this.x,this.y)},copy:function(){return this.clone.apply(this,arguments)},copyFrom:function(a){this.x=a.x;this.y=a.y;return this},toString:function(){return"Point["+this.x+","+this.y+"]"},equals:function(a){return(this.x===a.x&&this.y===a.y)},isCloseTo:function(c,b){if(typeof b=="number"){b={x:b};b.y=b.x}var a=c.x,f=c.y,e=b.x,d=b.y;return(this.x<=a+e&&this.x>=a-e&&this.y<=f+d&&this.y>=f-d)},isWithin:function(){return this.isCloseTo.apply(this,arguments)},translate:function(a,b){this.x+=a;this.y+=b;return this},roundedEquals:function(a){return(Math.round(this.x)===Math.round(a.x)&&Math.round(this.y)===Math.round(a.y))},getDistanceTo:function(b){var c=this.x-b.x,a=this.y-b.y;return Math.sqrt(c*c+a*a)},getAngleTo:function(b){var c=this.x-b.x,a=this.y-b.y;return Math.atan2(a,c)*this.radianToDegreeConstant}});Ext.define("Ext.util.Region",{statics:{getRegion:function(a){return Ext.fly(a).getPageBox(true)},from:function(a){return new this(a.top,a.right,a.bottom,a.left)}},constructor:function(d,f,a,c){var e=this;e.top=d;e[1]=d;e.right=f;e.bottom=a;e.left=c;e[0]=c},contains:function(b){var a=this;return(b.left>=a.left&&b.right<=a.right&&b.top>=a.top&&b.bottom<=a.bottom)},intersect:function(g){var f=this,d=Math.max(f.top,g.top),e=Math.min(f.right,g.right),a=Math.min(f.bottom,g.bottom),c=Math.max(f.left,g.left);if(a>d&&e>c){return new Ext.util.Region(d,e,a,c)}else{return false}},union:function(g){var f=this,d=Math.min(f.top,g.top),e=Math.max(f.right,g.right),a=Math.max(f.bottom,g.bottom),c=Math.min(f.left,g.left);return new Ext.util.Region(d,e,a,c)},constrainTo:function(b){var a=this,c=Ext.util.Numbers.constrain;a.top=c(a.top,b.top,b.bottom);a.bottom=c(a.bottom,b.top,b.bottom);a.left=c(a.left,b.left,b.right);a.right=c(a.right,b.left,b.right);return a},adjust:function(d,f,a,c){var e=this;e.top+=d;e.left+=c;e.right+=f;e.bottom+=a;return e},getOutOfBoundOffset:function(a,b){if(!Ext.isObject(a)){if(a=="x"){return this.getOutOfBoundOffsetX(b)}else{return this.getOutOfBoundOffsetY(b)}}else{b=a;var c=new Ext.util.Offset();c.x=this.getOutOfBoundOffsetX(b.x);c.y=this.getOutOfBoundOffsetY(b.y);return c}},getOutOfBoundOffsetX:function(a){if(a<=this.left){return this.left-a}else{if(a>=this.right){return this.right-a}}return 0},getOutOfBoundOffsetY:function(a){if(a<=this.top){return this.top-a}else{if(a>=this.bottom){return this.bottom-a}}return 0},isOutOfBound:function(a,b){if(!Ext.isObject(a)){if(a=="x"){return this.isOutOfBoundX(b)}else{return this.isOutOfBoundY(b)}}else{b=a;return(this.isOutOfBoundX(b.x)||this.isOutOfBoundY(b.y))}},isOutOfBoundX:function(a){return(athis.right)},isOutOfBoundY:function(a){return(athis.bottom)},restrict:function(b,d,a){if(Ext.isObject(b)){var c;a=d;d=b;if(d.copy){c=d.copy()}else{c={x:d.x,y:d.y}}c.x=this.restrictX(d.x,a);c.y=this.restrictY(d.y,a);return c}else{if(b=="x"){return this.restrictX(d,a)}else{return this.restrictY(d,a)}}},restrictX:function(b,a){if(!a){a=1}if(b<=this.left){b-=(b-this.left)*a}else{if(b>=this.right){b-=(b-this.right)*a}}return b},restrictY:function(b,a){if(!a){a=1}if(b<=this.top){b-=(b-this.top)*a}else{if(b>=this.bottom){b-=(b-this.bottom)*a}}return b},getSize:function(){return{width:this.right-this.left,height:this.bottom-this.top}},copy:function(){return new Ext.util.Region(this.top,this.right,this.bottom,this.left)},toString:function(){return"Region["+this.top+","+this.right+","+this.bottom+","+this.left+"]"},translateBy:function(a){this.left+=a.x;this.right+=a.x;this.top+=a.y;this.bottom+=a.y;return this},round:function(){this.top=Math.round(this.top);this.right=Math.round(this.right);this.bottom=Math.round(this.bottom);this.left=Math.round(this.left);return this},equals:function(a){return(this.top==a.top&&this.right==a.right&&this.bottom==a.bottom&&this.left==a.left)}});Ext.define("Ext.util.Sorter",{isSorter:true,config:{property:null,sorterFn:null,root:null,transform:null,direction:"ASC",id:undefined},constructor:function(a){this.initConfig(a)},applyId:function(a){if(!a){a=this.getProperty();if(!a){a=Ext.id(null,"ext-sorter-")}}return a},createSortFunction:function(b){var c=this,a=c.getDirection().toUpperCase()=="DESC"?-1:1;return function(e,d){return a*b.call(c,e,d)}},defaultSortFn:function(e,c){var g=this,f=g._transform,b=g._root,d,a,h=g._property;if(b!==null){e=e[b];c=c[b]}d=e[h];a=c[h];if(f){d=f(d);a=f(a)}return d>a?1:(d -1 || Ext.isDate(values) ? values : ""'}else{if(e=="#"){c="xindex"}else{if(e.substr(0,7)=="parent."){c=e}else{if((e.indexOf(".")!==-1)&&(e.indexOf("-")===-1)){c="values."+e}else{c="values['"+e+"']"}}}}if(f){c="("+c+f+")"}if(g&&this.useFormat){d=d?","+d:"";if(g.substr(0,5)!="this."){g="fm."+g+"("}else{g+="("}}else{d="";g="("+c+" === undefined ? '' : "}return g+c+d+")"},evalTpl:function($){eval($);return $},newLineRe:/\r\n|\r|\n/g,aposRe:/[']/g,intRe:/^\s*(\d+)\s*$/,tagRe:/([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?/},function(){var a=this.prototype;a.fnArgs="out,values,parent,xindex,xcount";a.callFn=".call(this,"+a.fnArgs+")"});Ext.define("Ext.data.Field",{requires:["Ext.data.Types","Ext.data.SortTypes"],alias:"data.field",isField:true,config:{name:null,type:"auto",convert:undefined,dateFormat:null,allowNull:true,defaultValue:undefined,mapping:null,sortType:undefined,sortDir:"ASC",allowBlank:true,persist:true,encode:null,decode:null},constructor:function(a){if(Ext.isString(a)){a={name:a}}this.initConfig(a)},applyType:function(c){var b=Ext.data.Types,a=b.AUTO;if(c){if(Ext.isString(c)){return b[c.toUpperCase()]||a}else{return c}}return a},updateType:function(a,b){var c=this.getConvert();if(b&&c===b.convert){this.setConvert(a.convert)}},applySortType:function(d){var c=Ext.data.SortTypes,a=this.getType(),b=a.sortType;if(d){if(Ext.isString(d)){return c[d]||b}else{return d}}return b},applyConvert:function(b){var a=this.getType().convert;if(b&&b!==a){this._hasCustomConvert=true;return b}else{this._hasCustomConvert=false;return a}},hasCustomConvert:function(){return this._hasCustomConvert}});Ext.define("Ext.data.identifier.Sequential",{extend:"Ext.data.identifier.Simple",alias:"data.identifier.sequential",config:{prefix:"",seed:1},constructor:function(){var a=this;a.callParent(arguments);a.parts=[a.getPrefix(),""]},generate:function(b){var c=this,d=c.parts,a=c.getSeed()+1;c.setSeed(a);d[1]=a;return d.join("")}});Ext.define("Ext.data.writer.Json",{extend:"Ext.data.writer.Writer",alternateClassName:"Ext.data.JsonWriter",alias:"writer.json",config:{root:undefined,encode:false,allowSingle:true,encodeRequest:false},applyRoot:function(a){if(!a&&(this.getEncode()||this.getEncodeRequest())){a="data"}return a},writeRecords:function(d,e){var a=this.getRoot(),f=d.getParams(),b=this.getAllowSingle(),c;if(this.getAllowSingle()&&e&&e.length==1){e=e[0]}if(this.getEncodeRequest()){c=d.getJsonData()||{};if(e&&(e.length||(b&&Ext.isObject(e)))){c[a]=e}d.setJsonData(Ext.apply(c,f||{}));d.setParams(null);d.setMethod("POST");return d}if(!e||!(e.length||(b&&Ext.isObject(e)))){return d}if(this.getEncode()){if(a){f[a]=Ext.encode(e)}else{}}else{c=d.getJsonData()||{};if(a){c[a]=e}else{c=e}d.setJsonData(c)}return d}});Ext.define("Ext.event.Dispatcher",{requires:["Ext.event.ListenerStack","Ext.event.Controller"],statics:{getInstance:function(){if(!this.instance){this.instance=new this()}return this.instance},setInstance:function(a){this.instance=a;return this}},config:{publishers:{}},wildcard:"*",constructor:function(a){this.listenerStacks={};this.activePublishers={};this.publishersCache={};this.noActivePublishers=[];this.controller=null;this.initConfig(a);return this},getListenerStack:function(e,g,c,b){var d=this.listenerStacks,f=d[e],a;b=Boolean(b);if(!f){if(b){d[e]=f={}}else{return null}}f=f[g];if(!f){if(b){d[e][g]=f={}}else{return null}}a=f[c];if(!a){if(b){f[c]=a=new Ext.event.ListenerStack()}else{return null}}return a},getController:function(d,f,c,b){var a=this.controller,e={targetType:d,target:f,eventName:c};if(!a){this.controller=a=new Ext.event.Controller()}if(a.isFiring){a=new Ext.event.Controller()}a.setInfo(e);if(b&&a!==b){a.connect(b)}return a},applyPublishers:function(c){var a,b;this.publishersCache={};for(a in c){if(c.hasOwnProperty(a)){b=c[a];this.registerPublisher(b)}}return c},registerPublisher:function(b){var a=this.activePublishers,c=b.getTargetType(),d=a[c];if(!d){a[c]=d=[]}d.push(b);b.setDispatcher(this);return this},getCachedActivePublishers:function(c,b){var a=this.publishersCache,d;if((d=a[c])&&(d=d[b])){return d}return null},cacheActivePublishers:function(c,b,d){var a=this.publishersCache;if(!a[c]){a[c]={}}a[c][b]=d;return d},getActivePublishers:function(f,b){var g,a,c,e,d;if((g=this.getCachedActivePublishers(f,b))){return g}a=this.activePublishers[f];if(a){g=[];for(c=0,e=a.length;c0}return false},addListener:function(d,e,a){var f=this.getActivePublishers(d,a),c=f.length,b;if(c>0){for(b=0;b0){for(b=0;b0){for(b=0;b0)){return true}delete d[f];if(--d.$length===0){delete this.subscribers[a]}return true},onBeforeComponentRenderedChange:function(b,d,g){var f=this.eventNames,c=g?f.painted:f.erased,e=this.getSubscribers(c),a;if(e&&e.$length>0){this.renderedQueue[d.getId()]=a=[];this.publish(e,d,c,a)}},onBeforeComponentHiddenChange:function(c,d){var f=this.eventNames,b=d?f.erased:f.painted,e=this.getSubscribers(b),a;if(e&&e.$length>0){this.hiddenQueue[c.getId()]=a=[];this.publish(e,c,b,a)}},onComponentRenderedChange:function(b,c){var d=this.renderedQueue,e=c.getId(),a;if(!d.hasOwnProperty(e)){return}a=d[e];delete d[e];if(a.length>0){this.dispatchQueue(a)}},onComponentHiddenChange:function(c){var b=this.hiddenQueue,d=c.getId(),a;if(!b.hasOwnProperty(d)){return}a=b[d];delete b[d];if(a.length>0){this.dispatchQueue(a)}},dispatchQueue:function(g){var l=this.dispatcher,a=this.targetType,b=this.eventNames,e=g.slice(),f=e.length,c,k,h,d,j;g.length=0;if(f>0){for(c=0;c0)){return true}delete c[i];c.$length--}else{if(!d.hasOwnProperty(i)||(!j&&--d[i]>0)){return true}delete d[i];d.$length--}}else{if(g===this.SELECTOR_ALL){if(j){a.all=0}else{a.all--}}else{if(!b.hasOwnProperty(g)||(!j&&--b[g]>0)){return true}delete b[g];Ext.Array.remove(b,g)}}a.$length--;return true},getElementTarget:function(a){if(a.nodeType!==1){a=a.parentNode;if(!a||a.nodeType!==1){return null}}return a},getBubblingTargets:function(b){var a=[];if(!b){return a}do{a[a.length]=b;b=b.parentNode}while(b&&b.nodeType===1);return a},dispatch:function(c,a,b){b.push(b[0].target);this.callParent(arguments)},publish:function(b,a,c){var d=this.getSubscribers(b),e;if(d.$length===0||!this.doPublish(d,b,a,c)){e=this.getSubscribers("*");if(e.$length>0){this.doPublish(e,b,a,c)}}return this},doPublish:function(f,h,x,u){var r=f.id,g=f.className,b=f.selector,p=r.$length>0,a=g.$length>0,l=b.length>0,o=f.all>0,y={},e=[u],q=false,m=this.classNameSplitRegex,v,k,t,d,z,n,c,w,s;for(v=0,k=x.length;v0){c=a.slice(0);a.length=0;for(b=0;b0){this.processEvent(this.mergeEvents(d));d.length=0}this.processEvent(e)}}if(d.length>0){this.processEvent(this.mergeEvents(d));d.length=0}}},mergeEvents:function(c){var b=[],f=c.length,a,e,d;d=c[f-1];if(f===1){return d}for(a=0;ah){for(d=0;dh){return}}for(d=0;da){this.end(d)}}},onTouchEnd:function(a){this.end(a)},start:function(){if(!this.isTracking){this.isTracking=true;this.isStarted=false}},end:function(a){if(this.isTracking){this.isTracking=false;if(this.isStarted){this.isStarted=false;this.fireEnd(a)}}}});Ext.define("Ext.event.recognizer.Pinch",{extend:"Ext.event.recognizer.MultiTouch",requiredTouchesCount:2,handledEvents:["pinchstart","pinch","pinchend"],startDistance:0,lastTouches:null,onTouchMove:function(c){if(!this.isTracking){return}var b=Array.prototype.slice.call(c.touches),d,a,f;d=b[0].point;a=b[1].point;f=d.getDistanceTo(a);if(f===0){return}if(!this.isStarted){this.isStarted=true;this.startDistance=f;this.fire("pinchstart",c,b,{touches:b,distance:f,scale:1})}else{this.fire("pinch",c,b,{touches:b,distance:f,scale:f/this.startDistance})}this.lastTouches=b},fireEnd:function(a){this.fire("pinchend",a,this.lastTouches)},fail:function(){return this.callParent(arguments)}});Ext.define("Ext.event.recognizer.Rotate",{extend:"Ext.event.recognizer.MultiTouch",requiredTouchesCount:2,handledEvents:["rotatestart","rotate","rotateend"],startAngle:0,lastTouches:null,lastAngle:null,onTouchMove:function(h){if(!this.isTracking){return}var g=Array.prototype.slice.call(h.touches),b=this.lastAngle,d,f,c,a,i,j;d=g[0].point;f=g[1].point;c=d.getAngleTo(f);if(b!==null){j=Math.abs(b-c);a=c+360;i=c-360;if(Math.abs(a-b)1){return this.fail(this.self.NOT_SINGLE_TOUCH)}}});Ext.define("Ext.event.recognizer.DoubleTap",{extend:"Ext.event.recognizer.SingleTouch",config:{maxDuration:300},handledEvents:["singletap","doubletap"],singleTapTimer:null,onTouchStart:function(a){if(this.callParent(arguments)===false){return false}this.startTime=a.time;clearTimeout(this.singleTapTimer)},onTouchMove:function(){return this.fail(this.self.TOUCH_MOVED)},onEnd:function(g){var c=this,b=this.getMaxDuration(),h=g.changedTouches[0],f=g.time,a=this.lastTapTime,d;this.lastTapTime=f;if(a){d=f-a;if(d<=b){this.lastTapTime=0;this.fire("doubletap",g,[h],{touch:h,duration:d});return}}if(f-this.startTime>b){this.fireSingleTap(g,h)}else{this.singleTapTimer=setTimeout(function(){c.fireSingleTap(g,h)},b)}},fireSingleTap:function(a,b){this.fire("singletap",a,[b],{touch:b})}});Ext.define("Ext.event.recognizer.Drag",{extend:"Ext.event.recognizer.SingleTouch",isStarted:false,startPoint:null,previousPoint:null,lastPoint:null,handledEvents:["dragstart","drag","dragend"],onTouchStart:function(b){var c,a;if(this.callParent(arguments)===false){if(this.isStarted&&this.lastMoveEvent!==null){this.onTouchEnd(this.lastMoveEvent)}return false}this.startTouches=c=b.changedTouches;this.startTouch=a=c[0];this.startPoint=a.point},onTouchMove:function(d){var c=d.changedTouches,f=c[0],a=f.point,b=d.time;if(this.lastPoint){this.previousPoint=this.lastPoint}if(this.lastTime){this.previousTime=this.lastTime}this.lastTime=b;this.lastPoint=a;this.lastMoveEvent=d;if(!this.isStarted){this.isStarted=true;this.startTime=b;this.previousTime=b;this.previousPoint=this.startPoint;this.fire("dragstart",d,this.startTouches,this.getInfo(d,this.startTouch))}else{this.fire("drag",d,c,this.getInfo(d,f))}},onTouchEnd:function(c){if(this.isStarted){var b=c.changedTouches,d=b[0],a=d.point;this.isStarted=false;this.lastPoint=a;this.fire("dragend",c,b,this.getInfo(c,d));this.startTime=0;this.previousTime=0;this.lastTime=0;this.startPoint=null;this.previousPoint=null;this.lastPoint=null;this.lastMoveEvent=null}},getInfo:function(j,i){var d=j.time,a=this.startPoint,f=this.previousPoint,b=this.startTime,k=this.previousTime,l=this.lastPoint,h=l.x-a.x,g=l.y-a.y,c={touch:i,startX:a.x,startY:a.y,previousX:f.x,previousY:f.y,pageX:l.x,pageY:l.y,deltaX:h,deltaY:g,absDeltaX:Math.abs(h),absDeltaY:Math.abs(g),previousDeltaX:l.x-f.x,previousDeltaY:l.y-f.y,time:d,startTime:b,previousTime:k,deltaTime:d-b,previousDeltaTime:d-k};return c}});Ext.define("Ext.event.recognizer.LongPress",{extend:"Ext.event.recognizer.SingleTouch",inheritableStatics:{DURATION_NOT_ENOUGH:32},config:{minDuration:1000},handledEvents:["longpress"],fireLongPress:function(a){var b=a.changedTouches[0];this.fire("longpress",a,[b],{touch:b,duration:this.getMinDuration()});this.isLongPress=true},onTouchStart:function(b){var a=this;if(this.callParent(arguments)===false){return false}this.isLongPress=false;this.timer=setTimeout(function(){a.fireLongPress(b)},this.getMinDuration())},onTouchMove:function(){return this.fail(this.self.TOUCH_MOVED)},onTouchEnd:function(){if(!this.isLongPress){return this.fail(this.self.DURATION_NOT_ENOUGH)}},fail:function(){clearTimeout(this.timer);return this.callParent(arguments)}},function(){});Ext.define("Ext.event.recognizer.Tap",{handledEvents:["tap"],extend:"Ext.event.recognizer.SingleTouch",onTouchMove:function(){return this.fail(this.self.TOUCH_MOVED)},onTouchEnd:function(a){var b=a.changedTouches[0];this.fire("tap",a,[b])}},function(){});(function(){function b(d){var c=Array.prototype.slice.call(arguments,1);return d.replace(/\{(\d+)\}/g,function(e,f){return c[f]})}Ext.DateExtras={now:Date.now||function(){return +new Date()},getElapsed:function(d,c){return Math.abs(d-(c||new Date()))},useStrict:false,formatCodeToRegex:function(d,c){var e=a.parseCodes[d];if(e){e=typeof e=="function"?e():e;a.parseCodes[d]=e}return e?Ext.applyIf({c:e.c?b(e.c,c||"{0}"):e.c},e):{g:0,c:null,s:Ext.String.escapeRegex(d)}},parseFunctions:{MS:function(d,c){var e=new RegExp("\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/");var f=(d||"").match(e);return f?new Date(((f[1]||"")+f[2])*1):null}},parseRegexes:[],formatFunctions:{MS:function(){return"\\/Date("+this.getTime()+")\\/"}},y2kYear:50,MILLI:"ms",SECOND:"s",MINUTE:"mi",HOUR:"h",DAY:"d",MONTH:"mo",YEAR:"y",defaults:{},dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNumbers:{Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11},defaultFormat:"m/d/Y",getShortMonthName:function(c){return a.monthNames[c].substring(0,3)},getShortDayName:function(c){return a.dayNames[c].substring(0,3)},getMonthNumber:function(c){return a.monthNumbers[c.substring(0,1).toUpperCase()+c.substring(1,3).toLowerCase()]},formatCodes:{d:"Ext.String.leftPad(this.getDate(), 2, '0')",D:"Ext.Date.getShortDayName(this.getDay())",j:"this.getDate()",l:"Ext.Date.dayNames[this.getDay()]",N:"(this.getDay() ? this.getDay() : 7)",S:"Ext.Date.getSuffix(this)",w:"this.getDay()",z:"Ext.Date.getDayOfYear(this)",W:"Ext.String.leftPad(Ext.Date.getWeekOfYear(this), 2, '0')",F:"Ext.Date.monthNames[this.getMonth()]",m:"Ext.String.leftPad(this.getMonth() + 1, 2, '0')",M:"Ext.Date.getShortMonthName(this.getMonth())",n:"(this.getMonth() + 1)",t:"Ext.Date.getDaysInMonth(this)",L:"(Ext.Date.isLeapYear(this) ? 1 : 0)",o:"(this.getFullYear() + (Ext.Date.getWeekOfYear(this) == 1 && this.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(this) >= 52 && this.getMonth() < 11 ? -1 : 0)))",Y:"Ext.String.leftPad(this.getFullYear(), 4, '0')",y:"('' + this.getFullYear()).substring(2, 4)",a:"(this.getHours() < 12 ? 'am' : 'pm')",A:"(this.getHours() < 12 ? 'AM' : 'PM')",g:"((this.getHours() % 12) ? this.getHours() % 12 : 12)",G:"this.getHours()",h:"Ext.String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",H:"Ext.String.leftPad(this.getHours(), 2, '0')",i:"Ext.String.leftPad(this.getMinutes(), 2, '0')",s:"Ext.String.leftPad(this.getSeconds(), 2, '0')",u:"Ext.String.leftPad(this.getMilliseconds(), 3, '0')",O:"Ext.Date.getGMTOffset(this)",P:"Ext.Date.getGMTOffset(this, true)",T:"Ext.Date.getTimezone(this)",Z:"(this.getTimezoneOffset() * -60)",c:function(){for(var j="Y-m-dTH:i:sP",g=[],f=0,d=j.length;f= 0 && y >= 0){","v = Ext.Date.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);","v = !strict? v : (strict === true && (z <= 364 || (Ext.Date.isLeapYear(v) && z <= 365))? Ext.Date.add(v, Ext.Date.DAY, z) : null);","}else if(strict === true && !Ext.Date.isValid(y, m + 1, d, h, i, s, ms)){","v = null;","}else{","v = Ext.Date.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);","}","}","}","if(v){","if(zz != null){","v = Ext.Date.add(v, Ext.Date.SECOND, -v.getTimezoneOffset() * 60 - zz);","}else if(o){","v = Ext.Date.add(v, Ext.Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));","}","}","return v;"].join("\n");return function(l){var e=a.parseRegexes.length,m=1,f=[],k=[],j=false,d="";for(var h=0;h Ext.Date.y2kYear ? 1900 + ty : 2000 + ty;\n",s:"(\\d{1,2})"},a:{g:1,c:"if (/(am)/i.test(results[{0}])) {\nif (!h || h == 12) { h = 0; }\n} else { if (!h || h < 12) { h = (h || 0) + 12; }}",s:"(am|pm|AM|PM)"},A:{g:1,c:"if (/(am)/i.test(results[{0}])) {\nif (!h || h == 12) { h = 0; }\n} else { if (!h || h < 12) { h = (h || 0) + 12; }}",s:"(AM|PM|am|pm)"},g:function(){return a.formatCodeToRegex("G")},G:{g:1,c:"h = parseInt(results[{0}], 10);\n",s:"(\\d{1,2})"},h:function(){return a.formatCodeToRegex("H")},H:{g:1,c:"h = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},i:{g:1,c:"i = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},s:{g:1,c:"s = parseInt(results[{0}], 10);\n",s:"(\\d{2})"},u:{g:1,c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",s:"(\\d+)"},O:{g:1,c:["o = results[{0}];","var sn = o.substring(0,1),","hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),","mn = o.substring(3,5) % 60;","o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),s:"([+-]\\d{4})"},P:{g:1,c:["o = results[{0}];","var sn = o.substring(0,1),","hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),","mn = o.substring(4,6) % 60;","o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n"].join("\n"),s:"([+-]\\d{2}:\\d{2})"},T:{g:0,c:null,s:"[A-Z]{1,4}"},Z:{g:1,c:"zz = results[{0}] * 1;\nzz = (-43200 <= zz && zz <= 50400)? zz : null;\n",s:"([+-]?\\d{1,5})"},c:function(){var e=[],c=[a.formatCodeToRegex("Y",1),a.formatCodeToRegex("m",2),a.formatCodeToRegex("d",3),a.formatCodeToRegex("h",4),a.formatCodeToRegex("i",5),a.formatCodeToRegex("s",6),{c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"},{c:["if(results[8]) {","if(results[8] == 'Z'){","zz = 0;","}else if (results[8].indexOf(':') > -1){",a.formatCodeToRegex("P",8).c,"}else{",a.formatCodeToRegex("O",8).c,"}","}"].join("\n")}];for(var f=0,d=c.length;f0?"-":"+")+Ext.String.leftPad(Math.floor(Math.abs(e)/60),2,"0")+(d?":":"")+Ext.String.leftPad(Math.abs(e%60),2,"0")},getDayOfYear:function(f){var e=0,h=Ext.Date.clone(f),c=f.getMonth(),g;for(g=0,h.setDate(1),h.setMonth(0);g28){e=Math.min(e,Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(g),"mo",h)).getDate())}i.setDate(e);i.setMonth(g.getMonth()+h);break;case Ext.Date.YEAR:i.setFullYear(g.getFullYear()+h);break}return i},between:function(d,f,c){var e=d.getTime();return f.getTime()<=e&&e<=c.getTime()}};var a=Ext.DateExtras;Ext.apply(Ext.Date,a)})();Ext.define("Ext.fx.Easing",{requires:["Ext.fx.easing.Linear"],constructor:function(a){return Ext.factory(a,Ext.fx.easing.Linear,null,"easing")}});Ext.define("Ext.fx.easing.BoundMomentum",{extend:"Ext.fx.easing.Abstract",requires:["Ext.fx.easing.Momentum","Ext.fx.easing.Bounce"],config:{momentum:null,bounce:null,minMomentumValue:0,maxMomentumValue:0,minVelocity:0.01,startVelocity:0},applyMomentum:function(a,b){return Ext.factory(a,Ext.fx.easing.Momentum,b)},applyBounce:function(a,b){return Ext.factory(a,Ext.fx.easing.Bounce,b)},updateStartTime:function(a){this.getMomentum().setStartTime(a);this.callParent(arguments)},updateStartVelocity:function(a){this.getMomentum().setStartVelocity(a)},updateStartValue:function(a){this.getMomentum().setStartValue(a)},reset:function(){this.lastValue=null;this.isBouncingBack=false;this.isOutOfBound=false;return this.callParent(arguments)},getValue:function(){var a=this.getMomentum(),j=this.getBounce(),e=a.getStartVelocity(),f=e>0?1:-1,g=this.getMinMomentumValue(),d=this.getMaxMomentumValue(),c=(f==1)?d:g,h=this.lastValue,i,b;if(e===0){return this.getStartValue()}if(!this.isOutOfBound){i=a.getValue();b=a.getVelocity();if(Math.abs(b)=g&&i<=d){return i}this.isOutOfBound=true;j.setStartTime(Ext.Date.now()).setStartVelocity(b).setStartValue(c)}i=j.getValue();if(!this.isEnded){if(!this.isBouncingBack){if(h!==null){if((f==1&&ih)){this.isBouncingBack=true}}}else{if(Math.round(i)==c){this.isEnded=true}}}this.lastValue=i;return i}});Ext.define("Ext.fx.easing.EaseIn",{extend:"Ext.fx.easing.Linear",alias:"easing.ease-in",config:{exponent:4,duration:1500},getValue:function(){var c=Ext.Date.now()-this.getStartTime(),g=this.getDuration(),b=this.getStartValue(),a=this.getEndValue(),h=this.distance,e=c/g,d=Math.pow(e,this.getExponent()),f=b+(d*h);if(c>=g){this.isEnded=true;return a}return f}});Ext.define("Ext.fx.easing.EaseOut",{extend:"Ext.fx.easing.Linear",alias:"easing.ease-out",config:{exponent:4,duration:1500},getValue:function(){var f=Ext.Date.now()-this.getStartTime(),d=this.getDuration(),b=this.getStartValue(),h=this.getEndValue(),a=this.distance,c=f/d,g=1-c,e=1-Math.pow(g,this.getExponent()),i=b+(e*a);if(f>=d){this.isEnded=true;return h}return i}});Ext.define("Ext.mixin.Filterable",{extend:"Ext.mixin.Mixin",requires:["Ext.util.Filter"],mixinConfig:{id:"filterable"},config:{filters:null,filterRoot:null},dirtyFilterFn:false,filterFn:null,filtered:false,applyFilters:function(a,b){if(!b){b=this.createFiltersCollection()}b.clear();this.filtered=false;this.dirtyFilterFn=true;if(a){this.addFilters(a)}return b},createFiltersCollection:function(){this._filters=Ext.create("Ext.util.Collection",function(a){return a.getId()});return this._filters},addFilter:function(a){this.addFilters([a])},addFilters:function(b){var a=this.getFilters();return this.insertFilters(a?a.length:0,b)},insertFilter:function(a,b){return this.insertFilters(a,[b])},insertFilters:function(h,c){if(!Ext.isArray(c)){c=[c]}var j=c.length,a=this.getFilterRoot(),d=this.getFilters(),e=[],f,g,b;if(!d){d=this.createFiltersCollection()}for(g=0;g=200&&a<300)||a==304||a==0,b=false;if(!c){switch(a){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:b=true;break}}return{success:c,isException:b}},createResponse:function(c){var g=c.xhr,a={},h,d,i,e,f,b;if(c.timedout||c.aborted){c.success=false;h=[]}else{h=g.getAllResponseHeaders().replace(this.lineBreakRe,"\n").split("\n")}d=h.length;while(d--){i=h[d];e=i.indexOf(":");if(e>=0){f=i.substr(0,e).toLowerCase();if(i.charAt(e+1)==" "){++e}a[f]=i.substr(e+1)}}c.xhr=null;delete c.xhr;b={request:c,requestId:c.id,status:g.status,statusText:g.statusText,getResponseHeader:function(j){return a[j.toLowerCase()]},getAllResponseHeaders:function(){return a},responseText:g.responseText,responseXML:g.responseXML};g=null;return b},createException:function(a){return{request:a,requestId:a.id,status:a.aborted?-1:0,statusText:a.aborted?"transaction aborted":"communication failure",aborted:a.aborted,timedout:a.timedout}}});Ext.define("Ext.Ajax",{extend:"Ext.data.Connection",singleton:true,autoAbort:false});Ext.define("Ext.data.reader.Reader",{requires:["Ext.data.ResultSet"],alternateClassName:["Ext.data.Reader","Ext.data.DataReader"],mixins:["Ext.mixin.Observable"],isReader:true,config:{idProperty:undefined,clientIdProperty:"clientId",totalProperty:"total",successProperty:"success",messageProperty:null,rootProperty:"",implicitIncludes:true,model:undefined},constructor:function(a){this.initConfig(a)},fieldCount:0,applyModel:function(a){if(typeof a=="string"){a=Ext.data.ModelManager.getModel(a);if(!a){Ext.Logger.error("Model with name "+arguments[0]+" doesnt exist.")}}if(a&&!a.prototype.isModel&&Ext.isObject(a)){a=Ext.data.ModelManager.registerType(a.storeId||a.id||Ext.id(),a)}return a},applyIdProperty:function(a){if(!a&&this.getModel()){a=this.getModel().getIdProperty()}return a},updateModel:function(a){if(a){if(!this.getIdProperty()){this.setIdProperty(a.getIdProperty())}this.buildExtractors()}},createAccessor:Ext.emptyFn,createFieldAccessExpression:function(){return"undefined"},buildExtractors:function(){if(!this.getModel()){return}var b=this,c=b.getTotalProperty(),a=b.getSuccessProperty(),d=b.getMessageProperty();if(c){b.getTotal=b.createAccessor(c)}if(a){b.getSuccess=b.createAccessor(a)}if(d){b.getMessage=b.createAccessor(d)}b.extractRecordData=b.buildRecordDataExtractor()},buildRecordDataExtractor:function(){var k=this,e=k.getModel(),g=e.getFields(),j=g.length,a=[],h=k.getModel().getClientIdProperty(),f="__field",b=["var me = this,\n"," fields = me.getModel().getFields(),\n"," idProperty = me.getIdProperty(),\n",' idPropertyIsFn = (typeof idProperty == "function"),'," value,\n"," internalId"],d,l,c,m;g=g.items;for(d=0;d=0){return Ext.functionFactory("obj","var value; try {value = obj"+(b>0?".":"")+c+"} catch(e) {}; return value;")}}return function(d){return d[c]}}}(),createFieldAccessExpression:function(g,b,c){var f=this,h=f.objectRe,e=(g.getMapping()!==null),a=e?g.getMapping():g.getName(),i,d;if(typeof a==="function"){i=b+".getMapping()("+c+", this)"}else{if(f.getUseSimpleAccessors()===true||((d=String(a).search(h))<0)){if(!e||isNaN(a)){a='"'+a+'"'}i=c+"["+a+"]"}else{i=c+(d>0?".":"")+a}}return i}});Ext.define("Ext.data.proxy.Proxy",{extend:"Ext.Evented",alias:"proxy.proxy",alternateClassName:["Ext.data.DataProxy","Ext.data.Proxy"],requires:["Ext.data.reader.Json","Ext.data.writer.Json"],uses:["Ext.data.Batch","Ext.data.Operation","Ext.data.Model"],config:{batchOrder:"create,update,destroy",batchActions:true,model:null,reader:{type:"json"},writer:{type:"json"}},isProxy:true,applyModel:function(a){if(typeof a=="string"){a=Ext.data.ModelManager.getModel(a);if(!a){Ext.Logger.error("Model with name "+arguments[0]+" doesnt exist.")}}if(a&&!a.prototype.isModel&&Ext.isObject(a)){a=Ext.data.ModelManager.registerType(a.storeId||a.id||Ext.id(),a)}return a},updateModel:function(b){if(b){var a=this.getReader();if(a&&!a.getModel()){a.setModel(b)}}},applyReader:function(b,a){return Ext.factory(b,Ext.data.Reader,a,"reader")},updateReader:function(a){if(a){var b=this.getModel();if(!b){b=a.getModel();if(b){this.setModel(b)}}else{a.setModel(b)}if(a.onMetaChange){a.onMetaChange=Ext.Function.createSequence(a.onMetaChange,this.onMetaChange,this)}}},onMetaChange:function(b){var a=this.getReader().getModel();if(!this.getModel()&&a){this.setModel(a)}this.fireEvent("metachange",this,b)},applyWriter:function(b,a){return Ext.factory(b,Ext.data.Writer,a,"writer")},create:Ext.emptyFn,read:Ext.emptyFn,update:Ext.emptyFn,destroy:Ext.emptyFn,onDestroy:function(){Ext.destroy(this.getReader(),this.getWriter())},batch:function(e,f){var g=this,d=g.getBatchActions(),c=this.getModel(),b,a;if(e.operations===undefined){e={operations:e,batch:{listeners:f}}}if(e.batch){if(e.batch.isBatch){e.batch.setProxy(g)}else{e.batch.proxy=g}}else{e.batch={proxy:g,listeners:e.listeners||{}}}if(!b){b=new Ext.data.Batch(e.batch)}b.on("complete",Ext.bind(g.onBatchComplete,g,[e],0));Ext.each(g.getBatchOrder().split(","),function(h){a=e.operations[h];if(a){if(d){b.add(new Ext.data.Operation({action:h,records:a,model:c}))}else{Ext.each(a,function(i){b.add(new Ext.data.Operation({action:h,records:[i],model:c}))})}}},g);b.start();return b},onBatchComplete:function(a,b){var c=a.scope||this;if(b.hasException){if(Ext.isFunction(a.failure)){Ext.callback(a.failure,c,[b,a])}}else{if(Ext.isFunction(a.success)){Ext.callback(a.success,c,[b,a])}}if(Ext.isFunction(a.callback)){Ext.callback(a.callback,c,[b,a])}}},function(){});Ext.define("Ext.data.proxy.Client",{extend:"Ext.data.proxy.Proxy",alternateClassName:"Ext.proxy.ClientProxy",clear:function(){}});Ext.define("Ext.data.proxy.Memory",{extend:"Ext.data.proxy.Client",alias:"proxy.memory",alternateClassName:"Ext.data.MemoryProxy",isMemoryProxy:true,config:{data:[]},finishOperation:function(b,f,d){if(b){var c=0,e=b.getRecords(),a=e.length;for(c;c0){if(o){h[e]=m[0].getProperty();h[b]=m[0].getDirection()}else{h[e]=n.encodeSorters(m)}}if(c&&f&&f.length>0){h[c]=n.encodeFilters(f)}return h},buildUrl:function(c){var b=this,a=b.getUrl(c);if(b.getNoCache()){a=Ext.urlAppend(a,Ext.String.format("{0}={1}",b.getCacheString(),Ext.Date.now()))}return a},getUrl:function(a){return a?a.getUrl()||this.getApi()[a.getAction()]||this._url:this._url},doRequest:function(a,c,b){},afterRequest:Ext.emptyFn});Ext.define("Ext.data.proxy.JsonP",{extend:"Ext.data.proxy.Server",alternateClassName:"Ext.data.ScriptTagProxy",alias:["proxy.jsonp","proxy.scripttag"],requires:["Ext.data.JsonP"],config:{defaultWriterType:"base",callbackKey:"callback",recordParam:"records",autoAppendParams:true},doRequest:function(a,g,b){var d=this,e=d.getWriter(),c=d.buildRequest(a),f=c.getParams();if(a.allowWrite()){c=e.write(c)}c.setConfig({callbackKey:d.getCallbackKey(),timeout:d.getTimeout(),scope:d,callback:d.createRequestCallback(c,a,g,b)});if(d.getAutoAppendParams()){c.setParams({})}c.setJsonP(Ext.data.JsonP.request(c.getCurrentConfig()));c.setParams(f);a.setStarted();d.lastRequest=c;return c},createRequestCallback:function(d,a,e,b){var c=this;return function(h,f,g){delete c.lastRequest;c.processResponse(h,a,d,f,e,b)}},setException:function(b,a){b.setException(b.getRequest().getJsonP().errorType)},buildUrl:function(f){var h=this,a=h.callParent(arguments),e=Ext.apply({},f.getParams()),c=e.filters,d,b,g,j;delete e.filters;if(h.getAutoAppendParams()){a=Ext.urlAppend(a,Ext.Object.toQueryString(e))}if(c&&c.length){for(g=0;g0){a=Ext.urlAppend(a,Ext.String.format("{0}={1}",h.getRecordParam(),h.encodeRecords(d)))}return a},destroy:function(){this.abort();this.callParent(arguments)},abort:function(){var a=this.lastRequest;if(a){Ext.data.JsonP.abort(a.getJsonP())}},encodeRecords:function(b){var d="",c=0,a=b.length;for(;c1){this.endAnimationCounter=0;this.fireEvent("animationend",this)}},applyInAnimation:function(b,a){return Ext.factory(b,Ext.fx.Animation,a)},applyOutAnimation:function(b,a){return Ext.factory(b,Ext.fx.Animation,a)},updateInAnimation:function(a){a.setScope(this)},updateOutAnimation:function(a){a.setScope(this)},onActiveItemChange:function(a,e,h,i,d){var b=this.getInAnimation(),g=this.getOutAnimation(),f,c;if(e&&h&&h.isPainted()){f=e.renderElement;c=h.renderElement;b.setElement(f);g.setElement(c);g.setOnBeforeEnd(function(j,k){if(k||Ext.Animator.hasRunningAnimations(j)){d.firingArguments[1]=null;d.firingArguments[2]=null}});g.setOnEnd(function(){d.resume()});f.dom.style.setProperty("visibility","hidden","!important");e.show();Ext.Animator.run([g,b]);d.pause()}}});Ext.define("Ext.fx.layout.card.Cover",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.cover",config:{reverse:null,inAnimation:{before:{"z-index":100},after:{"z-index":0},type:"slide",easing:"ease-out"},outAnimation:{easing:"ease-out",from:{opacity:0.99},to:{opacity:1},out:true}},updateReverse:function(a){this.getInAnimation().setReverse(a);this.getOutAnimation().setReverse(a)}});Ext.define("Ext.fx.layout.card.Cube",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.cube",config:{reverse:null,inAnimation:{type:"cube"},outAnimation:{type:"cube",out:true}}});Ext.define("Ext.fx.layout.card.Fade",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.fade",config:{reverse:null,inAnimation:{type:"fade",easing:"ease-out"},outAnimation:{type:"fade",easing:"ease-out",out:true}}});Ext.define("Ext.fx.layout.card.Flip",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.flip",config:{duration:500,inAnimation:{type:"flip",half:true,easing:"ease-out",before:{"backface-visibility":"hidden"},after:{"backface-visibility":null}},outAnimation:{type:"flip",half:true,easing:"ease-in",before:{"backface-visibility":"hidden"},after:{"backface-visibility":null},out:true}},updateDuration:function(d){var c=d/2,b=this.getInAnimation(),a=this.getOutAnimation();b.setDelay(c);b.setDuration(c);a.setDuration(c)}});Ext.define("Ext.fx.layout.card.Pop",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.pop",config:{duration:500,inAnimation:{type:"pop",easing:"ease-out"},outAnimation:{type:"pop",easing:"ease-in",out:true}},updateDuration:function(d){var c=d/2,b=this.getInAnimation(),a=this.getOutAnimation();b.setDelay(c);b.setDuration(c);a.setDuration(c)}});Ext.define("Ext.fx.layout.card.Reveal",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.reveal",config:{inAnimation:{easing:"ease-out",from:{opacity:0.99},to:{opacity:1}},outAnimation:{before:{"z-index":100},after:{"z-index":0},type:"slide",easing:"ease-out",out:true}},updateReverse:function(a){this.getInAnimation().setReverse(a);this.getOutAnimation().setReverse(a)}});Ext.define("Ext.fx.layout.card.Slide",{extend:"Ext.fx.layout.card.Style",alias:"fx.layout.card.slide",config:{inAnimation:{type:"slide",easing:"ease-out"},outAnimation:{type:"slide",easing:"ease-out",out:true}},updateReverse:function(a){this.getInAnimation().setReverse(a);this.getOutAnimation().setReverse(a)}});Ext.define("Ext.fx.layout.Card",{requires:["Ext.fx.layout.card.Slide","Ext.fx.layout.card.Cover","Ext.fx.layout.card.Reveal","Ext.fx.layout.card.Fade","Ext.fx.layout.card.Flip","Ext.fx.layout.card.Pop","Ext.fx.layout.card.Cube","Ext.fx.layout.card.Scroll"],constructor:function(b){var a=Ext.fx.layout.card.Abstract,c;if(!b){return null}if(typeof b=="string"){c=b;b={}}else{if(b.type){c=b.type}}b.elementBox=false;if(c){if(Ext.os.is.Android2){if(c!="fade"){c="scroll"}}else{if(c==="slide"&&Ext.browser.is.ChromeMobile){c="scroll"}}a=Ext.ClassManager.getByAlias("fx.layout.card."+c)}return Ext.factory(b,a)}});Ext.define("Ext.fx.runner.Css",{extend:"Ext.Evented",requires:["Ext.fx.Animation"],prefixedProperties:{transform:true,"transform-origin":true,perspective:true,"transform-style":true,transition:true,"transition-property":true,"transition-duration":true,"transition-timing-function":true,"transition-delay":true,animation:true,"animation-name":true,"animation-duration":true,"animation-iteration-count":true,"animation-direction":true,"animation-timing-function":true,"animation-delay":true},lengthProperties:{top:true,right:true,bottom:true,left:true,width:true,height:true,"max-height":true,"max-width":true,"min-height":true,"min-width":true,"margin-bottom":true,"margin-left":true,"margin-right":true,"margin-top":true,"padding-bottom":true,"padding-left":true,"padding-right":true,"padding-top":true,"border-bottom-width":true,"border-left-width":true,"border-right-width":true,"border-spacing":true,"border-top-width":true,"border-width":true,"outline-width":true,"letter-spacing":true,"line-height":true,"text-indent":true,"word-spacing":true,"font-size":true,translate:true,translateX:true,translateY:true,translateZ:true,translate3d:true},durationProperties:{"transition-duration":true,"transition-delay":true,"animation-duration":true,"animation-delay":true},angleProperties:{rotate:true,rotateX:true,rotateY:true,rotateZ:true,skew:true,skewX:true,skewY:true},lengthUnitRegex:/([a-z%]*)$/,DEFAULT_UNIT_LENGTH:"px",DEFAULT_UNIT_ANGLE:"deg",DEFAULT_UNIT_DURATION:"ms",formattedNameCache:{},constructor:function(){var a=Ext.feature.has.Css3dTransforms;if(a){this.transformMethods=["translateX","translateY","translateZ","rotate","rotateX","rotateY","rotateZ","skewX","skewY","scaleX","scaleY","scaleZ"]}else{this.transformMethods=["translateX","translateY","rotate","skewX","skewY","scaleX","scaleY"]}this.vendorPrefix=Ext.browser.getStyleDashPrefix();this.ruleStylesCache={};return this},getStyleSheet:function(){var c=this.styleSheet,a,b;if(!c){a=document.createElement("style");a.type="text/css";(document.head||document.getElementsByTagName("head")[0]).appendChild(a);b=document.styleSheets;this.styleSheet=c=b[b.length-1]}return c},applyRules:function(i){var g=this.getStyleSheet(),k=this.ruleStylesCache,j=g.cssRules,c,e,h,b,d,a,f;for(c in i){e=i[c];h=k[c];if(h===undefined){d=j.length;g.insertRule(c+"{}",d);h=k[c]=j.item(d).style}b=h.$cache;if(!b){b=h.$cache={}}for(a in e){f=this.formatValue(e[a],a);a=this.formatName(a);if(b[a]!==f){b[a]=f;if(f===null){h.removeProperty(a)}else{h.setProperty(a,f,"important")}}}}return this},applyStyles:function(d){var g,c,f,b,a,e;for(g in d){c=document.getElementById(g);if(!c){return this}f=c.style;b=d[g];for(a in b){e=this.formatValue(b[a],a);a=this.formatName(a);if(e===null){f.removeProperty(a)}else{f.setProperty(a,e,"important")}}}return this},formatName:function(b){var a=this.formattedNameCache,c=a[b];if(!c){if(this.prefixedProperties[b]){c=this.vendorPrefix+b}else{c=b}a[b]=c}return c},formatValue:function(j,b){var g=typeof j,l=this.DEFAULT_UNIT_LENGTH,e,a,d,f,c,k,h;if(g=="string"){if(this.lengthProperties[b]){h=j.match(this.lengthUnitRegex)[1];if(h.length>0){}else{return j+l}}return j}else{if(g=="number"){if(j==0){return"0"}if(this.lengthProperties[b]){return j+l}if(this.angleProperties[b]){return j+this.DEFAULT_UNIT_ANGLE}if(this.durationProperties[b]){return j+this.DEFAULT_UNIT_DURATION}}else{if(b==="transform"){e=this.transformMethods;c=[];for(d=0,f=e.length;d0)?k.join(", "):"none"}}}}return j}});Ext.define("Ext.fx.runner.CssTransition",{extend:"Ext.fx.runner.Css",listenersAttached:false,constructor:function(){this.runningAnimationsData={};return this.callParent(arguments)},attachListeners:function(){this.listenersAttached=true;this.getEventDispatcher().addListener("element","*","transitionend","onTransitionEnd",this)},onTransitionEnd:function(b){var a=b.target,c=a.id;if(c&&this.runningAnimationsData.hasOwnProperty(c)){this.refreshRunningAnimationsData(Ext.get(a),[b.browserEvent.propertyName])}},onAnimationEnd:function(g,f,d,j,n){var b=g.getId(),k=this.runningAnimationsData[b],c=k.nameMap,o={},m={},h,e,l,a;o[b]=m;if(f.onBeforeEnd){f.onBeforeEnd.call(f.scope||this,g,j)}d.fireEvent("animationbeforeend",d,g,j);this.fireEvent("animationbeforeend",this,d,g,j);if(n||(!j&&!f.preserveEndState)){h=f.toPropertyNames;for(e=0,l=h.length;e0},refreshRunningAnimationsData:function(d,k,t,p){var g=d.getId(),q=this.runningAnimationsData,a=q[g],m=a.nameMap,s=a.nameList,b=a.sessions,f,h,e,u,l,c,r,o,n=false;t=Boolean(t);p=Boolean(p);if(!b){return this}f=b.length;if(f===0){return this}if(p){a.nameMap={};s.length=0;for(l=0;l");d.close();this.testElement=c=d.createElement("div");c.style.setProperty("position","absolute","!important");d.body.appendChild(c);this.testElementComputedStyle=window.getComputedStyle(c)}return c},getCssStyleValue:function(b,e){var d=this.getTestElement(),a=this.testElementComputedStyle,c=d.style;c.setProperty(b,e);e=a.getPropertyValue(b);c.removeProperty(b);return e},run:function(o){var E=this,h=this.lengthProperties,w={},D={},F={},d,r,x,e,t,H,u,p,q,a,z,y,n,A,l,s,g,B,G,k,f,v,m,c,C,b;if(!this.listenersAttached){this.attachListeners()}o=Ext.Array.from(o);for(z=0,n=o.length;z0){this.refreshRunningAnimationsData(d,Ext.Array.merge(H,u),true,F.replacePrevious)}c=a.nameMap;C=a.nameList;s={};for(y=0;y0){H=Ext.Array.difference(C,H);u=Ext.Array.merge(H,u);x["transition-property"]=H}D[r]=e=Ext.Object.chain(e);e["transition-property"]=u;e["transition-duration"]=F.duration;e["transition-timing-function"]=F.easing;e["transition-delay"]=F.delay;A.startTime=Date.now()}q=this.$className;this.applyStyles(w);p=function(i){if(i.data===q&&i.source===window){window.removeEventListener("message",p,false);E.applyStyles(D)}};window.addEventListener("message",p,false);window.postMessage(q,"*")}});Ext.define("Ext.fx.Runner",{requires:["Ext.fx.runner.CssTransition"],constructor:function(){return new Ext.fx.runner.CssTransition()}});(function(a){Ext.define("Ext.layout.Default",{extend:"Ext.Evented",alternateClassName:["Ext.layout.AutoContainerLayout","Ext.layout.ContainerLayout"],alias:["layout.auto","layout.default"],isLayout:true,hasDockedItemsCls:a+"hasdocked",centeredItemCls:a+"centered",floatingItemCls:a+"floating",dockingWrapperCls:a+"docking",dockingInnerCls:a+"docking-inner",maskCls:a+"mask",positionMap:{top:"start",left:"start",bottom:"end",right:"end"},positionDirectionMap:{top:"vertical",bottom:"vertical",left:"horizontal",right:"horizontal"},DIRECTION_VERTICAL:"vertical",DIRECTION_HORIZONTAL:"horizontal",POSITION_START:"start",POSITION_END:"end",config:{animation:null},constructor:function(b,c){this.container=b;this.innerItems=[];this.centeringWrappers={};this.initConfig(c)},reapply:Ext.emptyFn,unapply:Ext.emptyFn,onItemAdd:function(){this.doItemAdd.apply(this,arguments)},onItemRemove:function(){this.doItemRemove.apply(this,arguments)},onItemMove:function(){this.doItemMove.apply(this,arguments)},onItemCenteredChange:function(){this.doItemCenteredChange.apply(this,arguments)},onItemFloatingChange:function(){this.doItemFloatingChange.apply(this,arguments)},onItemDockedChange:function(){this.doItemDockedChange.apply(this,arguments)},doItemAdd:function(c,b){var d=c.getDocked();if(d!==null){this.dockItem(c,d)}else{if(c.isCentered()){this.centerItem(c,b)}else{this.insertItem(c,b)}}if(c.isFloating()){this.onItemFloatingChange(c,true)}},doItemRemove:function(b){if(b.isDocked()){this.undockItem(b)}else{if(b.isCentered()){this.uncenterItem(b)}}Ext.Array.remove(this.innerItems,b);this.container.innerElement.dom.removeChild(b.renderElement.dom)},doItemMove:function(c,d,b){if(c.isCentered()){c.setZIndex((d+1)*2)}else{if(c.isFloating()){c.setZIndex((d+1)*2)}this.insertItem(c,d)}},doItemCenteredChange:function(c,b){if(b){this.centerItem(c)}else{this.uncenterItem(c)}},doItemFloatingChange:function(d,e){var c=d.element,b=this.floatingItemCls;if(e){if(d.getZIndex()===null){d.setZIndex((this.container.indexOf(d)+1)*2)}c.addCls(b)}else{d.setZIndex(null);c.removeCls(b)}},doItemDockedChange:function(b,d,c){if(c){this.undockItem(b,c)}if(d){this.dockItem(b,d)}},centerItem:function(b){this.insertItem(b,0);if(b.getZIndex()===null){b.setZIndex((this.container.indexOf(b)+1)*2)}this.createCenteringWrapper(b);b.element.addCls(this.floatingItemCls)},uncenterItem:function(b){this.destroyCenteringWrapper(b);b.setZIndex(null);this.insertItem(b,this.container.indexOf(b));b.element.removeCls(this.floatingItemCls)},dockItem:function(f,b){var c=this.container,g=f.renderElement,e=f.element,d=this.dockingInnerElement;if(!d){c.setUseBodyElement(true);this.dockingInnerElement=d=c.bodyElement}this.getDockingWrapper(b);if(this.positionMap[b]===this.POSITION_START){g.insertBefore(d)}else{g.insertAfter(d)}e.addCls(a+"docked-"+b)},undockItem:function(b,c){this.insertItem(b,this.container.indexOf(b));b.element.removeCls(a+"docked-"+c)},getDockingWrapper:function(b){var e=this.currentDockingDirection,d=this.positionDirectionMap[b],c=this.dockingWrapper;if(e!==d){this.currentDockingDirection=d;this.dockingWrapper=c=this.createDockingWrapper(d)}return c},createDockingWrapper:function(b){return this.dockingInnerElement.wrap({classList:[this.dockingWrapperCls+"-"+b]},true)},createCenteringWrapper:function(c){var f=c.getId(),d=this.centeringWrappers,b=c.renderElement,e;d[f]=e=b.wrap({className:this.centeredItemCls});return e},destroyCenteringWrapper:function(c){var f=c.getId(),d=this.centeringWrappers,b=c.renderElement,e=d[f];b.unwrap();e.destroy();delete d[f];return this},insertItem:function(k,g){var d=this.container,j=d.getItems().items,e=this.innerItems,c=d.innerElement.dom,i=k.renderElement.dom,h,f,b;if(d.has(k)){Ext.Array.remove(e,k)}if(typeof g=="number"){h=j[g];if(h===k){h=j[++g]}while(h&&(h.isCentered()||h.isDocked())){h=j[++g]}if(h){b=e.indexOf(h);if(b!==-1){while(h&&(h.isCentered()||h.isDocked())){h=e[++b]}if(h){e.splice(b,0,k);f=h.renderElement.dom;c.insertBefore(i,f);return this}}}}e.push(k);c.appendChild(i);return this}})})(Ext.baseCSSPrefix);Ext.define("Ext.layout.AbstractBox",{extend:"Ext.layout.Default",config:{align:"stretch",pack:null},flexItemCls:Ext.baseCSSPrefix+"layout-box-item",positionMap:{middle:"center",left:"start",top:"start",right:"end",bottom:"end"},constructor:function(a){this.callParent(arguments);a.innerElement.addCls(this.cls);a.on(this.sizeChangeEventName,"onItemSizeChange",this,{delegate:"> component"})},reapply:function(){this.container.innerElement.addCls(this.cls);this.updatePack(this.getPack());this.updateAlign(this.getAlign())},unapply:function(){this.container.innerElement.removeCls(this.cls);this.updatePack(null);this.updateAlign(null)},doItemAdd:function(d,b){this.callParent(arguments);if(d.isInnerItem()){var c=d.getConfig(this.sizePropertyName),a=d.config;if(!c&&("flex" in a)){this.setItemFlex(d,a.flex)}}},doItemRemove:function(a){if(a.isInnerItem()){this.setItemFlex(a,null)}this.callParent(arguments)},onItemSizeChange:function(a){this.setItemFlex(a,null)},doItemCenteredChange:function(b,a){if(a){this.setItemFlex(b,null)}this.callParent(arguments)},doItemFloatingChange:function(a,b){if(b){this.setItemFlex(a,null)}this.callParent(arguments)},doItemDockedChange:function(a,b){if(b){this.setItemFlex(a,null)}this.callParent(arguments)},redrawContainer:function(){var a=this.container,b=a.renderElement.dom.parentNode;if(b&&b.nodeType!==11){a.innerElement.redraw()}},setItemFlex:function(c,a){var b=c.element,d=this.flexItemCls;if(a){b.addCls(d)}else{if(b.hasCls(d)){this.redrawContainer();b.removeCls(d)}}b.dom.style.webkitBoxFlex=a},convertPosition:function(a){if(this.positionMap.hasOwnProperty(a)){return this.positionMap[a]}return a},applyAlign:function(a){return this.convertPosition(a)},updateAlign:function(a){this.container.innerElement.dom.style.webkitBoxAlign=a},applyPack:function(a){return this.convertPosition(a)},updatePack:function(a){this.container.innerElement.dom.style.webkitBoxPack=a}});Ext.define("Ext.layout.Fit",{extend:"Ext.layout.Default",alternateClassName:"Ext.layout.FitLayout",alias:"layout.fit",cls:Ext.baseCSSPrefix+"layout-fit",itemCls:Ext.baseCSSPrefix+"layout-fit-item",constructor:function(a){this.callParent(arguments);this.apply()},apply:function(){this.container.innerElement.addCls(this.cls)},reapply:function(){this.apply()},unapply:function(){this.container.innerElement.removeCls(this.cls)},doItemAdd:function(b,a){if(b.isInnerItem()){b.addCls(this.itemCls)}this.callParent(arguments)},doItemRemove:function(a){if(a.isInnerItem()){a.removeCls(this.itemCls)}this.callParent(arguments)}});Ext.define("Ext.layout.Card",{extend:"Ext.layout.Fit",alternateClassName:"Ext.layout.CardLayout",isCard:true,requires:["Ext.fx.layout.Card"],alias:"layout.card",cls:Ext.baseCSSPrefix+"layout-card",itemCls:Ext.baseCSSPrefix+"layout-card-item",constructor:function(){this.callParent(arguments);this.container.onInitialized(this.onContainerInitialized,this)},applyAnimation:function(a){return new Ext.fx.layout.Card(a)},updateAnimation:function(b,a){if(b&&b.isAnimation){b.setLayout(this)}if(a){a.destroy()}},doItemAdd:function(b,a){if(b.isInnerItem()){b.hide()}this.callParent(arguments)},doItemRemove:function(c,a,b){this.callParent(arguments);if(!b&&c.isInnerItem()){c.show()}},onContainerInitialized:function(a){var b=a.getActiveItem();if(b){b.show()}a.on("activeitemchange","onContainerActiveItemChange",this)},onContainerActiveItemChange:function(a){this.relayEvent(arguments,"doActiveItemChange")},doActiveItemChange:function(b,c,a){if(a){a.hide()}if(c){c.show()}},doItemDockedChange:function(b,c){var a=b.element;if(c){a.removeCls(this.itemCls)}else{a.addCls(this.itemCls)}this.callParent(arguments)}});Ext.define("Ext.layout.HBox",{extend:"Ext.layout.AbstractBox",alternateClassName:"Ext.layout.HBoxLayout",alias:"layout.hbox",sizePropertyName:"width",sizeChangeEventName:"widthchange",cls:Ext.baseCSSPrefix+"layout-hbox"});Ext.define("Ext.layout.VBox",{extend:"Ext.layout.AbstractBox",alternateClassName:"Ext.layout.VBoxLayout",alias:"layout.vbox",sizePropertyName:"height",sizeChangeEventName:"heightchange",cls:Ext.baseCSSPrefix+"layout-vbox"});Ext.define("Ext.layout.Layout",{requires:["Ext.layout.Fit","Ext.layout.Card","Ext.layout.HBox","Ext.layout.VBox"],constructor:function(a,b){var c=Ext.layout.Default,d,e;if(typeof b=="string"){d=b;b={}}else{if("type" in b){d=b.type}}if(d){c=Ext.ClassManager.getByAlias("layout."+d)}return new c(a,b)}});Ext.define("Ext.mixin.Sortable",{extend:"Ext.mixin.Mixin",requires:["Ext.util.Sorter"],mixinConfig:{id:"sortable"},config:{sorters:null,defaultSortDirection:"ASC",sortRoot:null},dirtySortFn:false,sortFn:null,sorted:false,applySorters:function(a,b){if(!b){b=this.createSortersCollection()}b.clear();this.sorted=false;if(a){this.addSorters(a)}return b},createSortersCollection:function(){this._sorters=Ext.create("Ext.util.Collection",function(a){return a.getId()});return this._sorters},addSorter:function(b,a){this.addSorters([b],a)},addSorters:function(c,a){var b=this.getSorters();return this.insertSorters(b?b.length:0,c,a)},insertSorter:function(a,c,b){return this.insertSorters(a,[c],b)},insertSorters:function(e,h,a){if(!Ext.isArray(h)){h=[h]}var f=h.length,j=a||this.getDefaultSortDirection(),c=this.getSortRoot(),k=this.getSorters(),l=[],g,b,m,d;if(!k){k=this.createSortersCollection()}for(b=0;b>1;f=d(e,b[c]);if(f>=0){h=c+1}else{if(f<0){a=c-1}}}return h}});Ext.define("Ext.util.AbstractMixedCollection",{requires:["Ext.util.Filter"],mixins:{observable:"Ext.util.Observable"},constructor:function(b,a){var c=this;c.items=[];c.map={};c.keys=[];c.length=0;c.allowFunctions=b===true;if(a){c.getKey=a}c.mixins.observable.constructor.call(c)},allowFunctions:false,add:function(b,e){var d=this,f=e,c=b,a;if(arguments.length==1){f=c;c=d.getKey(f)}if(typeof c!="undefined"&&c!==null){a=d.map[c];if(typeof a!="undefined"){return d.replace(c,f)}d.map[c]=f}d.length++;d.items.push(f);d.keys.push(c);d.fireEvent("add",d.length-1,f,c);return f},getKey:function(a){return a.id},replace:function(c,e){var d=this,a,b;if(arguments.length==1){e=arguments[0];c=d.getKey(e)}a=d.map[c];if(typeof c=="undefined"||c===null||typeof a=="undefined"){return d.add(c,e)}b=d.indexOfKey(c);d.items[b]=e;d.map[c]=e;d.fireEvent("replace",c,a,e);return e},addAll:function(f){var e=this,d=0,b,a,c;if(arguments.length>1||Ext.isArray(f)){b=arguments.length>1?arguments:f;for(a=b.length;d=d.length){return d.add(c,f)}d.length++;Ext.Array.splice(d.items,a,0,f);if(typeof c!="undefined"&&c!==null){d.map[c]=f}Ext.Array.splice(d.keys,a,0,c);d.fireEvent("add",a,f,c);return f},remove:function(a){return this.removeAt(this.indexOf(a))},removeAll:function(a){Ext.each(a||[],function(b){this.remove(b)},this);return this},removeAt:function(a){var c=this,d,b;if(a=0){c.length--;d=c.items[a];Ext.Array.erase(c.items,a,1);b=c.keys[a];if(typeof b!="undefined"){delete c.map[b]}Ext.Array.erase(c.keys,a,1);c.fireEvent("remove",d,b);return d}return false},removeAtKey:function(a){return this.removeAt(this.indexOfKey(a))},getCount:function(){return this.length},indexOf:function(a){return Ext.Array.indexOf(this.items,a)},indexOfKey:function(a){return Ext.Array.indexOf(this.keys,a)},get:function(b){var d=this,a=d.map[b],c=a!==undefined?a:(typeof b=="number")?d.items[b]:undefined;return typeof c!="function"||d.allowFunctions?c:null},getAt:function(a){return this.items[a]},getByKey:function(a){return this.map[a]},contains:function(a){return Ext.Array.contains(this.items,a)},containsKey:function(a){return typeof this.map[a]!="undefined"},clear:function(){var a=this;a.length=0;a.items=[];a.keys=[];a.map={};a.fireEvent("clear")},first:function(){return this.items[0]},last:function(){return this.items[this.length-1]},sum:function(g,b,h,a){var c=this.extractValues(g,b),f=c.length,e=0,d;h=h||0;a=(a||a===0)?a:f-1;for(d=h;d<=a;d++){e+=c[d]}return e},collect:function(j,e,g){var k=this.extractValues(j,e),a=k.length,b={},c=[],h,f,d;for(d=0;d=a;d--){b[b.length]=c[d]}}return b},filter:function(d,c,f,a){var b=[],e;if(Ext.isString(d)){b.push(Ext.create("Ext.util.Filter",{property:d,value:c,anyMatch:f,caseSensitive:a}))}else{if(Ext.isArray(d)||d instanceof Ext.util.Filter){b=b.concat(d)}}e=function(g){var m=true,n=b.length,h;for(h=0;h=e.length||(a&&e.getAutoSort())){return e.add(d,f)}this.all.push(f);if(typeof d!="undefined"&&d!==null){e.map[d]=f}if(b&&this.getAutoFilter()&&filterable.isFiltered.call(e,f)){return null}e.length++;Ext.Array.splice(e.items,c,0,f);Ext.Array.splice(e.keys,c,0,d);e.dirtyIndices=true;return f},insertAll:function(g,d){if(g>=this.items.length||(this.sorted&&this.getAutoSort())){return this.addAll(d)}var s=this,h=this.filtered,a=this.sorted,b=this.all,m=this.items,l=this.keys,r=this.map,n=this.getAutoFilter(),o=this.getAutoSort(),t=[],j=[],f=[],c=this.mixins.filterable,e=false,k,u,p,q;if(a&&this.getAutoSort()){}if(Ext.isObject(d)){for(u in d){if(d.hasOwnProperty(u)){j.push(m[u]);t.push(u)}}}else{j=d;k=d.length;for(p=0;p=0){e=a[b];c=f[b];if(typeof c!="undefined"){delete g.map[c]}Ext.Array.erase(a,b,1);Ext.Array.erase(f,b,1);Ext.Array.remove(d,e);g.length--;this.dirtyIndices=true;return e}return false},removeAtKey:function(a){return this.removeAt(this.indexOfKey(a))},getCount:function(){return this.length},indexOf:function(b){if(this.dirtyIndices){this.updateIndices()}var a=this.indices[this.getKey(b)];return(a===undefined)?-1:a},indexOfKey:function(b){if(this.dirtyIndices){this.updateIndices()}var a=this.indices[b];return(a===undefined)?-1:a},updateIndices:function(){var a=this.items,e=a.length,f=this.indices={},c,d,b;for(c=0;c=a;d--){b[b.length]=c[d]}}return b},findIndexBy:function(d,c,h){var g=this,f=g.keys,a=g.items,b=h||0,e=a.length;for(;b1){for(c=a.length;ba){if(d){var e=c.substr(0,a-2),b=Math.max(e.lastIndexOf(" "),e.lastIndexOf("."),e.lastIndexOf("!"),e.lastIndexOf("?"));if(b!=-1&&b>=(a-15)){return e.substr(0,b)+"..."}}return c.substr(0,a-3)+"..."}return c},escapeRegex:function(a){return a.replace(Ext.util.Format.escapeRegexRe,"\\$1")},escape:function(a){return a.replace(Ext.util.Format.escapeRe,"\\$1")},toggle:function(b,c,a){return b==c?a:c},trim:function(a){return a.replace(Ext.util.Format.trimRe,"")},leftPad:function(d,b,c){var a=String(d);c=c||" ";while(a.length/g,">").replace(/").replace(/</g,"<").replace(/"/g,'"').replace(/&/g,"&")},date:function(b,c){var a=b;if(!b){return""}if(!Ext.isDate(b)){a=new Date(Date.parse(b));if(isNaN(a)){if(this.iso8601TestRe.test(b)){a=b.split(this.iso8601SplitRe);a=new Date(a[0],a[1]-1,a[2],a[3],a[4],a[5])}if(isNaN(a)){a=new Date(Date.parse(b.replace(this.dashesRe,"/")))}}b=a}return Ext.Date.format(b,c||Ext.util.Format.defaultDateFormat)}});Ext.define("Ext.Template",{requires:["Ext.dom.Helper","Ext.util.Format"],inheritableStatics:{from:function(b,a){b=Ext.getDom(b);return new this(b.value||b.innerHTML,a||"")}},constructor:function(d){var f=this,b=arguments,a=[],c=0,e=b.length,g;f.initialConfig={};if(e>1){for(;cf)?1:((ba?1:(d0},isExpandable:function(){var a=this;if(a.get("expandable")){return !(a.isLeaf()||(a.isLoaded()&&!a.hasChildNodes()))}return false},appendChild:function(b,j,h){var f=this,c,e,d,g,a;if(Ext.isArray(b)){for(c=0,e=b.length;c0){Ext.Array.sort(d,f);for(c=0;cMath.max(c,b)||jMath.max(a,q)||eMath.max(p,n)||eMath.max(k,h)){return null}return new Ext.util.Point(j,e)},toString:function(){return this.point1.toString()+" "+this.point2.toString()}});Ext.define("Ext.util.SizeMonitor",{extend:"Ext.Evented",config:{element:null,detectorCls:Ext.baseCSSPrefix+"size-change-detector",callback:Ext.emptyFn,scope:null,args:[]},constructor:function(d){this.initConfig(d);this.doFireSizeChangeEvent=Ext.Function.bind(this.doFireSizeChangeEvent,this);var g=this,e=this.getElement().dom,b=this.getDetectorCls(),c=Ext.Element.create({classList:[b,b+"-expand"],children:[{}]},true),h=Ext.Element.create({classList:[b,b+"-shrink"],children:[{}]},true),a=function(i){g.onDetectorScroll("expand",i)},f=function(i){g.onDetectorScroll("shrink",i)};e.appendChild(c);e.appendChild(h);c.addEventListener("scroll",a,true);h.addEventListener("scroll",f,true);this.detectors={expand:c,shrink:h};this.position={expand:{left:0,top:0},shrink:{left:0,top:0}};this.listeners={expand:a,shrink:f};this.refresh()},applyElement:function(a){if(a){return Ext.get(a)}},refreshPosition:function(b){var e=this.detectors[b],a=this.position[b],d,c;a.left=d=e.scrollWidth-e.offsetWidth;a.top=c=e.scrollHeight-e.offsetHeight;e.scrollLeft=d;e.scrollTop=c},refresh:function(){this.refreshPosition("expand");this.refreshPosition("shrink")},onDetectorScroll:function(b){var c=this.detectors[b],a=this.position[b];if(c.scrollLeft!==a.left||c.scrollTop!==a.top){this.refresh();this.fireSizeChangeEvent()}},fireSizeChangeEvent:function(){clearTimeout(this.sizeChangeThrottleTimer);this.sizeChangeThrottleTimer=setTimeout(this.doFireSizeChangeEvent,1)},doFireSizeChangeEvent:function(){this.getCallback().apply(this.getScope(),this.getArgs())},destroyDetector:function(a){var c=this.detectors[a],b=this.listeners[a];c.removeEventListener("scroll",b,true);Ext.removeNode(c)},destroy:function(){this.callParent(arguments);this.destroyDetector("expand");this.destroyDetector("shrink");delete this.listeners;delete this.detectors}});Ext.define("Ext.event.publisher.ComponentSize",{extend:"Ext.event.publisher.Publisher",requires:["Ext.ComponentManager","Ext.util.SizeMonitor"],targetType:"component",handledEvents:["resize"],constructor:function(){this.callParent(arguments);this.sizeMonitors={}},subscribe:function(g){var c=g.match(this.idSelectorRegex),f=this.subscribers,a=this.sizeMonitors,d=this.dispatcher,e=this.targetType,b;if(!c){return false}if(!f.hasOwnProperty(g)){f[g]=0;d.addListener(e,g,"painted","onComponentPainted",this,null,"before");b=Ext.ComponentManager.get(c[1]);a[g]=new Ext.util.SizeMonitor({element:b.element,callback:this.onComponentSizeChange,scope:this,args:[this,g]})}f[g]++;return true},unsubscribe:function(h,b,e){var c=h.match(this.idSelectorRegex),g=this.subscribers,d=this.dispatcher,f=this.targetType,a=this.sizeMonitors;if(!c){return false}if(!g.hasOwnProperty(h)||(!e&&--g[h]>0)){return true}a[h].destroy();delete a[h];d.removeListener(f,h,"painted","onComponentPainted",this,"before");delete g[h];return true},onComponentPainted:function(b){var c=b.getObservableId(),a=this.sizeMonitors[c];a.refresh()},onComponentSizeChange:function(a,b){this.dispatcher.doDispatchEvent(this.targetType,b,"resize",[a])}});Ext.define("Ext.util.Sortable",{isSortable:true,defaultSortDirection:"ASC",requires:["Ext.util.Sorter"],initSortable:function(){var a=this,b=a.sorters;a.sorters=Ext.create("Ext.util.AbstractMixedCollection",false,function(c){return c.id||c.property});if(b){a.sorters.addAll(a.decodeSorters(b))}},sort:function(g,f,c,e){var d=this,h,b,a;if(Ext.isArray(g)){e=c;c=f;a=g}else{if(Ext.isObject(g)){e=c;c=f;a=[g]}else{if(Ext.isString(g)){h=d.sorters.get(g);if(!h){h={property:g,direction:f};a=[h]}else{if(f===undefined){h.toggle()}else{h.setDirection(f)}}}}}if(a&&a.length){a=d.decodeSorters(a);if(Ext.isString(c)){if(c==="prepend"){g=d.sorters.clone().items;d.sorters.clear();d.sorters.addAll(a);d.sorters.addAll(g)}else{d.sorters.addAll(a)}}else{d.sorters.clear();d.sorters.addAll(a)}if(e!==false){d.onBeforeSort(a)}}if(e!==false){g=d.sorters.items;if(g.length){b=function(l,k){var j=g[0].sort(l,k),n=g.length,m;for(m=1;me?1:(f0){g=f.data.items;r=g.length;for(k=0;k0){b.create=e;f=true}if(c.length>0){b.update=c;f=true}if(a.length>0){b.destroy=a;f=true}if(f&&d.fireEvent("beforesync",this,b)!==false){d.getProxy().batch({operations:b,listeners:d.getBatchListeners()})}return{added:e,updated:c,removed:a}},first:function(){return this.data.first()},last:function(){return this.data.last()},sum:function(e){var d=0,c=0,b=this.data.items,a=b.length;for(;c0){c=b[0].get(f)}for(;d0){a=c[0].get(f)}for(;da){a=e}}return a},average:function(e){var c=0,b=this.data.items,a=b.length,d=0;if(b.length>0){for(;ce){return 1}else{if(fa.data.index)?1:-1},applyFilters:function(b){var a=this;return function(c){return a.isVisible(c)}},applyProxy:function(a){},applyNode:function(a){if(a){a=Ext.data.NodeInterface.decorate(a)}return a},updateNode:function(a,c){if(c){c.un({append:"onNodeAppend",insert:"onNodeInsert",remove:"onNodeRemove",load:"onNodeLoad",scope:this});c.unjoin(this)}if(a){a.on({scope:this,append:"onNodeAppend",insert:"onNodeInsert",remove:"onNodeRemove",load:"onNodeLoad"});a.join(this);var b=[];if(a.childNodes.length){b=b.concat(this.retrieveChildNodes(a))}if(this.getRootVisible()){b.push(a)}else{if(a.isLoaded()||a.isLoading()){a.set("expanded",true)}}this.data.clear();this.fireEvent("clear",this);this.suspendEvents();this.add(b);this.resumeEvents();this.fireEvent("refresh",this,this.data)}},retrieveChildNodes:function(a){var d=this.getNode(),b=this.getRecursive(),c=[],e=a;if(!a.childNodes.length||(!b&&a!==d)){return c}if(!b){return a.childNodes}while(e){if(e._added){delete e._added;if(e===a){break}else{e=e.nextSibling||e.parentNode}}else{if(e!==a){c.push(e)}if(e.firstChild){e._added=true;e=e.firstChild}else{e=e.nextSibling||e.parentNode}}}return c},isVisible:function(b){var a=b.parentNode;while(a){if(!a.isExpanded()){return false}if(a===this.getNode()){break}a=a.parentNode}return true}});Ext.define("Ext.data.TreeStore",{extend:"Ext.data.NodeStore",alias:"store.tree",config:{root:undefined,clearOnLoad:true,nodeParam:"node",defaultRootId:"root",defaultRootProperty:"children",recursive:true},applyProxy:function(){return Ext.data.Store.prototype.applyProxy.apply(this,arguments)},applyRoot:function(a){var b=this;a=a||{};a=Ext.apply({},a);if(!a.isModel){Ext.applyIf(a,{id:b.getDefaultRootId(),text:"Root",allowDrag:false});a=Ext.data.ModelManager.create(a,b.getModel())}Ext.data.NodeInterface.decorate(a);a.set(a.raw);return a},handleTreeInsertionIndex:function(a,b,d,c){if(b.parentNode){b.parentNode.sort(d.getSortFn(),true,true)}return this.callParent(arguments)},handleTreeSort:function(a,b){if(this._sorting){return a}this._sorting=true;this.getNode().sort(b.getSortFn(),true,true);delete this._sorting;return this.callParent(arguments)},updateRoot:function(a,b){if(b){b.unBefore({expand:"onNodeBeforeExpand",scope:this});b.unjoin(this)}a.onBefore({expand:"onNodeBeforeExpand",scope:this});this.onNodeAppend(null,a);this.setNode(a);if(!a.isLoaded()&&!a.isLoading()&&a.isExpanded()){this.load({node:a})}this.fireEvent("rootchange",this,a,b)},getNodeById:function(a){return this.data.getByKey(a)},onNodeBeforeExpand:function(b,a,c){if(b.isLoading()){c.pause();this.on("load",function(){c.resume()},this,{single:true})}else{if(!b.isLoaded()){c.pause();this.load({node:b,callback:function(){c.resume()}})}}},onNodeAppend:function(l,b){var j=this.getProxy(),g=j.getReader(),e=b.raw,c=[],a=g.getRootProperty(),k,f,d,h;if(!b.isLeaf()){k=g.getRoot(e);if(k){f=g.extractData(k);for(d=0,h=f.length;d0){this.sendRequest(b==1?a[0]:a);this.callBuffer=[]}}});Ext.define("Ext.util.TapRepeater",{requires:["Ext.DateExtras"],mixins:{observable:"Ext.mixin.Observable"},config:{el:null,accelerate:true,interval:10,delay:250,preventDefault:true,stopDefault:false,timer:0,pressCls:null},constructor:function(a){var b=this;b.initConfig(a)},updateEl:function(c,b){var a={touchstart:"onTouchStart",touchend:"onTouchEnd",tap:"eventOptions",scope:this};if(b){b.un(a)}c.on(a)},eventOptions:function(a){if(this.getPreventDefault()){a.preventDefault()}if(this.getStopDefault()){a.stopEvent()}},destroy:function(){this.clearListeners();Ext.destroy(this.el)},onTouchStart:function(c){var b=this,a=b.getPressCls();clearTimeout(b.getTimer());if(a){b.getEl().addCls(a)}b.tapStartTime=new Date();b.fireEvent("touchstart",b,c);b.fireEvent("tap",b,c);if(b.getAccelerate()){b.delay=400}b.setTimer(Ext.defer(b.tap,b.getDelay()||b.getInterval(),b,[c]))},tap:function(b){var a=this;a.fireEvent("tap",a,b);a.setTimer(Ext.defer(a.tap,a.getAccelerate()?a.easeOutExpo(Ext.Date.getElapsed(a.tapStartTime),400,-390,12000):a.getInterval(),a,[b]))},easeOutExpo:function(e,a,g,f){return(e==f)?a+g:g*(-Math.pow(2,-10*e/f)+1)+a},onTouchEnd:function(b){var a=this;clearTimeout(a.getTimer());a.getEl().removeCls(a.getPressCls());a.fireEvent("touchend",a,b)}});Ext.define("Ext.util.translatable.Abstract",{extend:"Ext.Evented",requires:["Ext.fx.easing.Linear"],config:{element:null,easing:null,easingX:null,easingY:null,fps:60},constructor:function(a){var b;this.doAnimationFrame=Ext.Function.bind(this.doAnimationFrame,this);this.x=0;this.y=0;this.activeEasingX=null;this.activeEasingY=null;this.initialConfig=a;if(a&&a.element){b=a.element;this.setElement(b)}},applyElement:function(a){if(!a){return}return Ext.get(a)},updateElement:function(a){this.initConfig(this.initialConfig);this.refresh()},factoryEasing:function(a){return Ext.factory(a,Ext.fx.easing.Linear,null,"easing")},applyEasing:function(a){if(!this.getEasingX()){this.setEasingX(this.factoryEasing(a))}if(!this.getEasingY()){this.setEasingY(this.factoryEasing(a))}},applyEasingX:function(a){return this.factoryEasing(a)},applyEasingY:function(a){return this.factoryEasing(a)},updateFps:function(a){this.animationInterval=1000/a},doTranslate:function(a,b){if(typeof a=="number"){this.x=a}if(typeof b=="number"){this.y=b}return this},translate:function(a,c,b){if(Ext.isObject(a)){throw new Error()}this.stopAnimation();if(b!==undefined){return this.translateAnimated(a,c,b)}return this.doTranslate(a,c)},animate:function(b,a){this.activeEasingX=b;this.activeEasingY=a;this.isAnimating=true;this.animationTimer=setInterval(this.doAnimationFrame,this.animationInterval);this.fireEvent("animationstart",this,this.x,this.y);return this},translateAnimated:function(b,g,e){if(Ext.isObject(b)){throw new Error()}if(!Ext.isObject(e)){e={}}var d=Ext.Date.now(),f=e.easing,c=(typeof b=="number")?(e.easingX||this.getEasingX()||f||true):null,a=(typeof g=="number")?(e.easingY||this.getEasingY()||f||true):null;if(c){c=this.factoryEasing(c);c.setStartTime(d);c.setStartValue(this.x);c.setEndValue(b);if("duration" in e){c.setDuration(e.duration)}}if(a){a=this.factoryEasing(a);a.setStartTime(d);a.setStartValue(this.y);a.setEndValue(g);if("duration" in e){a.setDuration(e.duration)}}return this.animate(c,a)},doAnimationFrame:function(){if(!this.isAnimating){return}var c=this.activeEasingX,b=this.activeEasingY,a,d;if(c===null&&b===null){this.stopAnimation();return}if(c!==null){this.x=a=Math.round(c.getValue());if(c.isEnded){this.activeEasingX=null;this.fireEvent("axisanimationend",this,"x",a)}}else{a=this.x}if(b!==null){this.y=d=Math.round(b.getValue());if(b.isEnded){this.activeEasingY=null;this.fireEvent("axisanimationend",this,"y",d)}}else{d=this.y}this.doTranslate(a,d);this.fireEvent("animationframe",this,a,d)},stopAnimation:function(){if(!this.isAnimating){return}this.activeEasingX=null;this.activeEasingY=null;this.isAnimating=false;clearInterval(this.animationTimer);this.fireEvent("animationend",this,this.x,this.y)},refresh:function(){this.translate(this.x,this.y)}});Ext.define("Ext.util.translatable.CssTransform",{extend:"Ext.util.translatable.Abstract",doTranslate:function(a,c){var b=this.getElement().dom.style;if(typeof a!="number"){a=this.x}if(typeof c!="number"){c=this.y}b.webkitTransform="translate3d("+a+"px, "+c+"px, 0px)";return this.callParent(arguments)},destroy:function(){var a=this.getElement();if(a&&!a.isDestroyed){a.dom.style.webkitTransform=null}this.callParent(arguments)}});Ext.define("Ext.util.translatable.ScrollPosition",{extend:"Ext.util.translatable.Abstract",wrapperWidth:0,wrapperHeight:0,baseCls:"x-translatable",config:{useWrapper:true},getWrapper:function(){var e=this.wrapper,c=this.baseCls,b=this.getElement(),d,a;if(!e){a=b.getParent();if(!a){return null}if(this.getUseWrapper()){e=b.wrap({className:c+"-wrapper"},true)}else{e=a.dom}e.appendChild(Ext.Element.create({className:c+"-stretcher"},true));this.nestedStretcher=d=Ext.Element.create({className:c+"-nested-stretcher"},true);b.appendChild(d);b.addCls(c);a.addCls(c+"-container");this.container=a;this.wrapper=e;this.refresh()}return e},doTranslate:function(a,c){var b=this.getWrapper();if(b){if(typeof a=="number"){b.scrollLeft=this.wrapperWidth-a}if(typeof c=="number"){b.scrollTop=this.wrapperHeight-c}}return this.callParent(arguments)},refresh:function(){var a=this.getWrapper();if(a){this.wrapperWidth=a.offsetWidth;this.wrapperHeight=a.offsetHeight;this.callParent(arguments)}},destroy:function(){var b=this.getElement(),a=this.baseCls;if(this.wrapper){if(this.getUseWrapper()){b.unwrap()}this.container.removeCls(a+"-container");b.removeCls(a);b.removeChild(this.nestedStretcher)}this.callParent(arguments)}});Ext.define("Ext.util.Translatable",{requires:["Ext.util.translatable.CssTransform","Ext.util.translatable.ScrollPosition"],constructor:function(a){var c=Ext.util.translatable,e=c.CssTransform,d=c.ScrollPosition,b;if(typeof a=="object"&&"translationMethod" in a){if(a.translationMethod==="scrollposition"){b=d}else{if(a.translationMethod==="csstransform"){b=e}}}if(!b){if(Ext.os.is.Android2||Ext.browser.is.ChromeMobile){b=d}else{b=e}}return new b(a)}});Ext.define("Ext.behavior.Translatable",{extend:"Ext.behavior.Behavior",requires:["Ext.util.Translatable"],constructor:function(){this.listeners={painted:"onComponentPainted",scope:this};this.callParent(arguments)},onComponentPainted:function(){this.translatable.refresh()},setConfig:function(c){var a=this.translatable,b=this.component;if(c){if(!a){this.translatable=a=new Ext.util.Translatable(c);a.setElement(b.renderElement);a.on("destroy","onTranslatableDestroy",this);if(b.isPainted()){this.onComponentPainted(b)}b.on(this.listeners)}else{if(Ext.isObject(c)){a.setConfig(c)}}}else{if(a){a.destroy()}}return this},getTranslatable:function(){return this.translatable},onTranslatableDestroy:function(){var a=this.component;delete this.translatable;a.un(this.listeners)},onComponentDestroy:function(){var a=this.translatable;if(a){a.destroy()}}});Ext.define("Ext.scroll.Scroller",{extend:"Ext.Evented",requires:["Ext.fx.easing.BoundMomentum","Ext.fx.easing.EaseOut","Ext.util.SizeMonitor","Ext.util.Translatable"],config:{element:null,direction:"auto",translationMethod:"auto",fps:"auto",disabled:null,directionLock:false,momentumEasing:{momentum:{acceleration:30,friction:0.5},bounce:{acceleration:30,springTension:0.3},minVelocity:1},bounceEasing:{duration:400},outOfBoundRestrictFactor:0.5,startMomentumResetTime:300,maxAbsoluteVelocity:6,containerSize:"auto",containerScrollSize:"auto",size:"auto",autoRefresh:true,initialOffset:{x:0,y:0},slotSnapSize:{x:0,y:0},slotSnapOffset:{x:0,y:0},slotSnapEasing:{duration:150}},cls:Ext.baseCSSPrefix+"scroll-scroller",containerCls:Ext.baseCSSPrefix+"scroll-container",dragStartTime:0,dragEndTime:0,isDragging:false,isAnimating:false,constructor:function(a){var b=a&&a.element;this.doAnimationFrame=Ext.Function.bind(this.doAnimationFrame,this);this.stopAnimation=Ext.Function.bind(this.stopAnimation,this);this.listeners={scope:this,touchstart:"onTouchStart",touchend:"onTouchEnd",dragstart:"onDragStart",drag:"onDrag",dragend:"onDragEnd"};this.minPosition={x:0,y:0};this.startPosition={x:0,y:0};this.size={x:0,y:0};this.position={x:0,y:0};this.velocity={x:0,y:0};this.isAxisEnabledFlags={x:false,y:false};this.flickStartPosition={x:0,y:0};this.flickStartTime={x:0,y:0};this.lastDragPosition={x:0,y:0};this.dragDirection={x:0,y:0};this.initialConfig=a;if(b){this.setElement(b)}return this},applyElement:function(a){if(!a){return}return Ext.get(a)},updateElement:function(a){this.initialize();a.addCls(this.cls);if(!this.getDisabled()){this.attachListeneners()}this.onConfigUpdate(["containerSize","size"],"refreshMaxPosition");this.on("maxpositionchange","snapToBoundary");this.on("minpositionchange","snapToBoundary");return this},getTranslatable:function(){if(!this.hasOwnProperty("translatable")){var a=this.getBounceEasing();this.translatable=new Ext.util.Translatable({translationMethod:this.getTranslationMethod(),element:this.getElement(),easingX:a.x,easingY:a.y,useWrapper:false,listeners:{animationframe:"onAnimationFrame",animationend:"onAnimationEnd",axisanimationend:"onAxisAnimationEnd",scope:this}})}return this.translatable},updateFps:function(a){if(a!=="auto"){this.getTranslatable().setFps(a)}},attachListeneners:function(){this.getContainer().on(this.listeners)},detachListeners:function(){this.getContainer().un(this.listeners)},updateDisabled:function(a){if(a){this.detachListeners()}else{this.attachListeneners()}},updateInitialOffset:function(c){if(typeof c=="number"){c={x:c,y:c}}var b=this.position,a,d;b.x=a=c.x;b.y=d=c.y;this.getTranslatable().doTranslate(-a,-d)},applyDirection:function(a){var e=this.getMinPosition(),d=this.getMaxPosition(),c,b;this.givenDirection=a;if(a==="auto"){c=d.x>e.x;b=d.y>e.y;if(c&&b){a="both"}else{if(c){a="horizontal"}else{a="vertical"}}}return a},updateDirection:function(b){var a=this.isAxisEnabledFlags;a.x=(b==="both"||b==="horizontal");a.y=(b==="both"||b==="vertical")},isAxisEnabled:function(a){this.getDirection();return this.isAxisEnabledFlags[a]},applyMomentumEasing:function(b){var a=Ext.fx.easing.BoundMomentum;return{x:Ext.factory(b,a),y:Ext.factory(b,a)}},applyBounceEasing:function(b){var a=Ext.fx.easing.EaseOut;return{x:Ext.factory(b,a),y:Ext.factory(b,a)}},applySlotSnapEasing:function(b){var a=Ext.fx.easing.EaseOut;return{x:Ext.factory(b,a),y:Ext.factory(b,a)}},getMinPosition:function(){var a=this.minPosition;if(!a){this.minPosition=a={x:0,y:0};this.fireEvent("minpositionchange",this,a)}return a},getMaxPosition:function(){var c=this.maxPosition,a,b;if(!c){a=this.getSize();b=this.getContainerSize();this.maxPosition=c={x:Math.max(0,a.x-b.x),y:Math.max(0,a.y-b.y)};this.fireEvent("maxpositionchange",this,c)}return c},refreshMaxPosition:function(){this.maxPosition=null;this.getMaxPosition()},applyContainerSize:function(b){var c,a,d;this.givenContainerSize=b;if(b==="auto"){c=this.getContainer().dom;a=c.offsetWidth;d=c.offsetHeight}else{a=b.x;d=b.y}return{x:a,y:d}},applySize:function(b){var c,a,d;this.givenSize=b;if(b==="auto"){c=this.getElement().dom;a=c.offsetWidth;d=c.offsetHeight}else{a=b.x;d=b.y}return{x:a,y:d}},applyContainerScrollSize:function(b){var c,a,d;this.givenContainerScrollSize=b;if(b==="auto"){c=this.getContainer().dom;a=c.scrollWidth;d=c.scrollHeight}else{a=b.x;d=b.y}return{x:a,y:d}},updateAutoRefresh:function(b){var c=Ext.util.SizeMonitor,a;if(b){this.sizeMonitors={element:new c({element:this.getElement(),callback:this.doRefresh,scope:this}),container:new c({element:this.getContainer(),callback:this.doRefresh,scope:this})}}else{a=this.sizeMonitors;if(a){a.element.destroy();a.container.destroy()}}},applySlotSnapSize:function(a){if(typeof a=="number"){return{x:a,y:a}}return a},applySlotSnapOffset:function(a){if(typeof a=="number"){return{x:a,y:a}}return a},getContainer:function(){var a=this.container;if(!a){this.container=a=this.getElement().getParent();a.addCls(this.containerCls)}return a},doRefresh:function(){this.stopAnimation();this.getTranslatable().refresh();this.setSize(this.givenSize);this.setContainerSize(this.givenContainerSize);this.setContainerScrollSize(this.givenContainerScrollSize);this.setDirection(this.givenDirection);this.fireEvent("refresh",this)},refresh:function(){var a=this.sizeMonitors;if(a){a.element.refresh();a.container.refresh()}this.doRefresh();return this},scrollTo:function(c,h,g){var b=this.getTranslatable(),a=this.position,d=false,f,e;if(this.isAxisEnabled("x")){if(typeof c!="number"){c=a.x}else{if(a.x!==c){a.x=c;d=true}}f=-c}if(this.isAxisEnabled("y")){if(typeof h!="number"){h=a.y}else{if(a.y!==h){a.y=h;d=true}}e=-h}if(d){if(g!==undefined){b.translateAnimated(f,e,g)}else{this.fireEvent("scroll",this,a.x,a.y);b.doTranslate(f,e)}}return this},scrollToTop:function(b){var a=this.getInitialOffset();return this.scrollTo(a.x,a.y,b)},scrollToEnd:function(a){return this.scrollTo(0,this.getSize().y-this.getContainerSize().y,a)},scrollBy:function(b,d,c){var a=this.position;b=(typeof b=="number")?b+a.x:null;d=(typeof d=="number")?d+a.y:null;return this.scrollTo(b,d,c)},onTouchStart:function(){this.isTouching=true;this.stopAnimation()},onTouchEnd:function(){var a=this.position;this.isTouching=false;if(!this.isDragging&&this.snapToSlot()){this.fireEvent("scrollstart",this,a.x,a.y)}},onDragStart:function(l){var o=this.getDirection(),g=l.absDeltaX,f=l.absDeltaY,j=this.getDirectionLock(),i=this.startPosition,d=this.flickStartPosition,k=this.flickStartTime,h=this.lastDragPosition,c=this.position,b=this.dragDirection,n=c.x,m=c.y,a=Ext.Date.now();this.isDragging=true;if(j&&o!=="both"){if((o==="horizontal"&&g>f)||(o==="vertical"&&f>g)){l.stopPropagation()}else{this.isDragging=false;return}}h.x=n;h.y=m;d.x=n;d.y=m;i.x=n;i.y=m;k.x=a;k.y=a;b.x=0;b.y=0;this.dragStartTime=a;this.isDragging=true;this.fireEvent("scrollstart",this,n,m)},onAxisDrag:function(i,q){if(!this.isAxisEnabled(i)){return}var h=this.flickStartPosition,l=this.flickStartTime,j=this.lastDragPosition,e=this.dragDirection,g=this.position[i],k=this.getMinPosition()[i],o=this.getMaxPosition()[i],d=this.startPosition[i],p=j[i],n=d-q,c=e[i],m=this.getOutOfBoundRestrictFactor(),f=this.getStartMomentumResetTime(),b=Ext.Date.now(),a;if(no){a=n-o;n=o+a*m}}if(n>p){e[i]=1}else{if(nf){h[i]=g;l[i]=b}j[i]=n},onDrag:function(b){if(!this.isDragging){return}var a=this.lastDragPosition;this.onAxisDrag("x",b.deltaX);this.onAxisDrag("y",b.deltaY);this.scrollTo(a.x,a.y)},onDragEnd:function(c){var b,a;if(!this.isDragging){return}this.dragEndTime=Ext.Date.now();this.onDrag(c);this.isDragging=false;b=this.getAnimationEasing("x");a=this.getAnimationEasing("y");if(b||a){this.getTranslatable().animate(b,a)}else{this.onScrollEnd()}},getAnimationEasing:function(g){if(!this.isAxisEnabled(g)){return null}var e=this.position[g],f=this.flickStartPosition[g],k=this.flickStartTime[g],c=this.getMinPosition()[g],j=this.getMaxPosition()[g],a=this.getMaxAbsoluteVelocity(),d=null,b=this.dragEndTime,l,i,h;if(ej){d=j}}if(d!==null){l=this.getBounceEasing()[g];l.setConfig({startTime:b,startValue:-e,endValue:-d});return l}h=b-k;if(h===0){return null}i=(e-f)/(b-k);if(i===0){return null}if(i<-a){i=-a}else{if(i>a){i=a}}l=this.getMomentumEasing()[g];l.setConfig({startTime:b,startValue:-e,startVelocity:-i,minMomentumValue:-j,maxMomentumValue:0});return l},onAnimationFrame:function(c,b,d){var a=this.position;a.x=-b;a.y=-d;this.fireEvent("scroll",this,a.x,a.y)},onAxisAnimationEnd:function(a){},onAnimationEnd:function(){this.snapToBoundary();this.onScrollEnd()},stopAnimation:function(){this.getTranslatable().stopAnimation()},onScrollEnd:function(){var a=this.position;if(this.isTouching||!this.snapToSlot()){this.fireEvent("scrollend",this,a.x,a.y)}},snapToSlot:function(){var b=this.getSnapPosition("x"),a=this.getSnapPosition("y"),c=this.getSlotSnapEasing();if(b!==null||a!==null){this.scrollTo(b,a,{easingX:c.x,easingY:c.y});return true}return false},getSnapPosition:function(c){var g=this.getSlotSnapSize()[c],d=null,a,f,e,b;if(g!==0&&this.isAxisEnabled(c)){a=this.position[c];f=this.getSlotSnapOffset()[c];e=this.getMaxPosition()[c];b=(a-f)%g;if(b!==0){if(Math.abs(b)>g/2){d=a+((b>0)?g-b:b-g);if(d>e){d=a-b}}else{d=a-b}}}return d},snapToBoundary:function(){var g=this.position,c=this.getMinPosition(),f=this.getMaxPosition(),e=c.x,d=c.y,b=f.x,a=f.y,i=Math.round(g.x),h=Math.round(g.y);if(ib){i=b}}if(ha){h=a}}this.scrollTo(i,h)},destroy:function(){var b=this.getElement(),a=this.sizeMonitors;if(a){a.element.destroy();a.container.destroy()}if(b&&!b.isDestroyed){b.removeCls(this.cls);this.getContainer().removeCls(this.containerCls)}Ext.destroy(this.translatable);this.callParent(arguments)}},function(){});Ext.define("Ext.util.Draggable",{isDraggable:true,mixins:["Ext.mixin.Observable"],requires:["Ext.util.SizeMonitor","Ext.util.Translatable"],config:{cls:Ext.baseCSSPrefix+"draggable",draggingCls:Ext.baseCSSPrefix+"dragging",element:null,constraint:"container",disabled:null,direction:"both",translatable:{}},DIRECTION_BOTH:"both",DIRECTION_VERTICAL:"vertical",DIRECTION_HORIZONTAL:"horizontal",constructor:function(a){var b;this.sizeMonitors={};this.extraConstraint={};this.initialConfig=a;this.offset={x:0,y:0};this.listeners={dragstart:"onDragStart",drag:"onDrag",dragend:"onDragEnd",scope:this};if(a&&a.element){b=a.element;delete a.element;this.setElement(b)}return this},applyElement:function(a){if(!a){return}return Ext.get(a)},updateElement:function(a){a.on(this.listeners);this.sizeMonitors.element=new Ext.util.SizeMonitor({element:a,callback:this.doRefresh,scope:this});this.initConfig(this.initialConfig)},updateCls:function(a){this.getElement().addCls(a)},applyTranslatable:function(a,b){a=Ext.factory(a,Ext.util.Translatable,b);a.setElement(this.getElement());return a},setExtraConstraint:function(a){this.extraConstraint=a||{};this.refreshConstraint();return this},addExtraConstraint:function(a){Ext.merge(this.extraConstraint,a);this.refreshConstraint();return this},applyConstraint:function(b,a){this.currentConstraint=b;if(b==="container"){return Ext.merge(this.getContainerConstraint(),this.extraConstraint)}return Ext.merge({},this.extraConstraint,b)},updateConstraint:function(){this.refreshOffset()},getContainerConstraint:function(){var b=this.getContainer();if(!b){return{min:{x:-Infinity,y:-Infinity},max:{x:Infinity,y:Infinity}}}var g=this.getElement().dom,f=b.dom,c=g.offsetWidth,a=g.offsetHeight,e=f.offsetWidth,d=f.offsetHeight;return{min:{x:0,y:0},max:{x:e-c,y:d-a}}},getContainer:function(){var a=this.container;if(!a){a=this.getElement().getParent();if(a){this.sizeMonitors.container=new Ext.util.SizeMonitor({element:a,callback:this.doRefresh,scope:this});this.container=a}}return a},detachListeners:function(){this.getElement().un(this.listeners)},isAxisEnabled:function(a){var b=this.getDirection();if(a==="x"){return(b===this.DIRECTION_BOTH||b===this.DIRECTION_HORIZONTAL)}return(b===this.DIRECTION_BOTH||b===this.DIRECTION_VERTICAL)},onDragStart:function(a){if(this.getDisabled()){return false}var b=this.offset;this.fireAction("dragstart",[this,a,b.x,b.y],this.initDragStart)},initDragStart:function(b,c,a,d){this.dragStartOffset={x:a,y:d};this.isDragging=true;this.getElement().addCls(this.getDraggingCls())},onDrag:function(b){if(!this.isDragging){return}var a=this.dragStartOffset;this.fireAction("drag",[this,b,a.x+b.deltaX,a.y+b.deltaY],this.doDrag)},doDrag:function(b,c,a,d){b.setOffset(a,d)},onDragEnd:function(a){if(!this.isDragging){return}this.onDrag(a);this.isDragging=false;this.getElement().removeCls(this.getDraggingCls());this.fireEvent("dragend",this,a,this.offset.x,this.offset.y)},setOffset:function(i,h,b){var f=this.offset,a=this.getConstraint(),e=a.min,c=a.max,d=Math.min,g=Math.max;if(this.isAxisEnabled("x")&&typeof i=="number"){i=d(g(i,e.x),c.x)}else{i=f.x}if(this.isAxisEnabled("y")&&typeof h=="number"){h=d(g(h,e.y),c.y)}else{h=f.y}f.x=i;f.y=h;this.getTranslatable().translate(i,h,b)},getOffset:function(){return this.offset},refreshConstraint:function(){this.setConstraint(this.currentConstraint)},refreshOffset:function(){var a=this.offset;this.setOffset(a.x,a.y)},doRefresh:function(){this.refreshConstraint();this.getTranslatable().refresh();this.refreshOffset()},refresh:function(){var a=this.sizeMonitors;if(a.element){a.element.refresh()}if(a.container){a.container.refresh()}this.doRefresh()},enable:function(){return this.setDisabled(false)},disable:function(){return this.setDisabled(true)},destroy:function(){var b=this.sizeMonitors,a=this.getTranslatable();if(b.element){b.element.destroy()}if(b.container){b.container.destroy()}var c=this.getElement();if(c&&!c.isDestroyed){c.removeCls(this.getCls())}this.detachListeners();if(a){a.destroy()}}},function(){});Ext.define("Ext.behavior.Draggable",{extend:"Ext.behavior.Behavior",requires:["Ext.util.Draggable"],constructor:function(){this.listeners={painted:"onComponentPainted",scope:this};this.callParent(arguments)},onComponentPainted:function(){this.draggable.refresh()},setConfig:function(c){var a=this.draggable,b=this.component;if(c){if(!a){b.setTranslatable(true);this.draggable=a=new Ext.util.Draggable(c);a.setTranslatable(b.getTranslatable());a.setElement(b.renderElement);a.on("destroy","onDraggableDestroy",this);if(b.isPainted()){this.onComponentPainted(b)}b.on(this.listeners)}else{if(Ext.isObject(c)){a.setConfig(c)}}}else{if(a){a.destroy()}}return this},getDraggable:function(){return this.draggable},onDraggableDestroy:function(){var a=this.component;delete this.draggable;a.un(this.listeners)},onComponentDestroy:function(){var a=this.draggable;if(a){a.destroy()}}});(function(a){Ext.define("Ext.Component",{extend:"Ext.AbstractComponent",alternateClassName:"Ext.lib.Component",mixins:["Ext.mixin.Traversable"],requires:["Ext.ComponentManager","Ext.XTemplate","Ext.dom.Element","Ext.behavior.Translatable","Ext.behavior.Draggable"],xtype:"component",observableType:"component",cachedConfig:{baseCls:null,cls:null,floatingCls:null,hiddenCls:a+"item-hidden",ui:null,margin:null,padding:null,border:null,styleHtmlCls:a+"html",styleHtmlContent:null},eventedConfig:{left:null,top:null,right:null,bottom:null,width:null,height:null,minWidth:null,minHeight:null,maxWidth:null,maxHeight:null,docked:null,centered:null,hidden:null,disabled:null},config:{style:null,html:null,draggable:null,translatable:null,renderTo:null,zIndex:null,tpl:null,enterAnimation:null,exitAnimation:null,showAnimation:null,hideAnimation:null,tplWriteMode:"overwrite",data:null,disabledCls:a+"item-disabled",contentEl:null,itemId:undefined,record:null,plugins:null},listenerOptionsRegex:/^(?:delegate|single|delay|buffer|args|prepend|element)$/,alignmentRegex:/^([a-z]+)-([a-z]+)(\?)?$/,isComponent:true,floating:false,rendered:false,dockPositions:{top:true,right:true,bottom:true,left:true},innerElement:null,element:null,template:[],constructor:function(c){var d=this,b=d.config,e;d.onInitializedListeners=[];d.initialConfig=c;if(c!==undefined&&"id" in c){e=c.id}else{if("id" in b){e=b.id}else{e=d.getId()}}d.id=e;d.setId(e);Ext.ComponentManager.register(d);d.initElement();d.initConfig(d.initialConfig);d.initialize();d.triggerInitialized();if("fullscreen" in d.config){d.fireEvent("fullscreen",d)}d.fireEvent("initialize",d)},beforeInitConfig:function(b){this.beforeInitialize.apply(this,arguments)},beforeInitialize:Ext.emptyFn,initialize:Ext.emptyFn,getTemplate:function(){return this.template},getElementConfig:function(){return{reference:"element",children:this.getTemplate()}},triggerInitialized:function(){var c=this.onInitializedListeners,d=c.length,e,b;if(!this.initialized){this.initialized=true;if(d>0){for(b=0;b0){this.pressedTimeout=setTimeout(function(){if(a){a.addCls(b)}},c)}else{a.addCls(b)}}},onTouchMove:function(a){return},onRelease:function(a){this.fireAction("release",[this,a],"doRelease")},doRelease:function(a,b){if(!a.isPressed){return}a.isPressed=false;if(a.hasOwnProperty("pressedTimeout")){clearTimeout(a.pressedTimeout);delete a.pressedTimeout}a.releasedTimeout=setTimeout(function(){if(a&&a.element){a.element.removeCls(a.getPressedCls())}},10)},onTap:function(a){if(this.getDisabled()){return false}this.fireAction("tap",[this,a],"doTap")},doTap:function(c,d){var b=c.getHandler(),a=c.getScope()||c;if(!b){return}if(typeof b=="string"){b=a[b]}d.preventDefault();b.apply(a,arguments)}},function(){});Ext.define("Ext.Decorator",{extend:"Ext.Component",isDecorator:true,config:{component:{}},statics:{generateProxySetter:function(a){return function(c){var b=this.getComponent();b[a].call(b,c);return this}},generateProxyGetter:function(a){return function(){var b=this.getComponent();return b[a].call(b)}}},onClassExtended:function(c,e){if(!e.hasOwnProperty("proxyConfig")){return}var f=Ext.Class,i=e.proxyConfig,d=e.config;e.config=(d)?Ext.applyIf(d,i):i;var b,h,g,a;for(b in i){if(i.hasOwnProperty(b)){h=f.getConfigNameMap(b);g=h.set;a=h.get;e[g]=this.generateProxySetter(g);e[a]=this.generateProxyGetter(a)}}},applyComponent:function(a){return Ext.factory(a,Ext.Component)},updateComponent:function(a,b){if(b){if(this.isRendered()&&b.setRendered(false)){b.fireAction("renderedchange",[this,b,false],"doUnsetComponent",this,{args:[b]})}else{this.doUnsetComponent(b)}}if(a){if(this.isRendered()&&a.setRendered(true)){a.fireAction("renderedchange",[this,a,true],"doSetComponent",this,{args:[a]})}else{this.doSetComponent(a)}}},doUnsetComponent:function(a){if(a.renderElement.dom){this.innerElement.dom.removeChild(a.renderElement.dom)}},doSetComponent:function(a){if(a.renderElement.dom){this.innerElement.dom.appendChild(a.renderElement.dom)}},setRendered:function(b){var a;if(this.callParent(arguments)){a=this.getComponent();if(a){a.setRendered(b)}return true}return false},setDisabled:function(a){this.callParent(arguments);this.getComponent().setDisabled(a)},destroy:function(){Ext.destroy(this.getComponent());this.callParent()}});Ext.define("Ext.Img",{extend:"Ext.Component",xtype:["image","img"],config:{src:null,baseCls:Ext.baseCSSPrefix+"img",mode:"background"},beforeInitialize:function(){var a=this;a.onLoad=Ext.Function.bind(a.onLoad,a);a.onError=Ext.Function.bind(a.onError,a)},initialize:function(){var a=this;a.callParent();a.relayEvents(a.renderElement,"*");a.element.on({tap:"onTap",scope:a})},hide:function(){this.callParent();this.hiddenSrc=this.hiddenSrc||this.getSrc();this.setSrc(null)},show:function(){this.callParent();if(this.hiddenSrc){this.setSrc(this.hiddenSrc);delete this.hiddenSrc}},updateMode:function(a){if(a==="background"){if(this.imageElement){this.imageElement.destroy();delete this.imageElement;this.updateSrc(this.getSrc())}}else{this.imageElement=this.element.createChild({tag:"img"})}},onTap:function(a){this.fireEvent("tap",this,a)},onAfterRender:function(){this.updateSrc(this.getSrc())},updateSrc:function(a){var b=this,c;if(b.getMode()==="background"){c=this.imageObject||new Image()}else{c=b.imageElement.dom}this.imageObject=c;c.setAttribute("src",Ext.isString(a)?a:"");c.addEventListener("load",b.onLoad,false);c.addEventListener("error",b.onError,false)},detachListeners:function(){var a=this.imageObject;if(a){a.removeEventListener("load",this.onLoad,false);a.removeEventListener("error",this.onError,false)}},onLoad:function(a){this.detachListeners();if(this.getMode()==="background"){this.element.dom.style.backgroundImage='url("'+this.imageObject.src+'")'}this.fireEvent("load",this,a)},onError:function(a){this.detachListeners();this.fireEvent("error",this,a)},doSetWidth:function(b){var a=(this.getMode()==="background")?this.element:this.imageElement;a.setWidth(b);this.callParent(arguments)},doSetHeight:function(b){var a=(this.getMode()==="background")?this.element:this.imageElement;a.setHeight(b);this.callParent(arguments)},destroy:function(){this.detachListeners();Ext.destroy(this.imageObject);delete this.imageObject;this.callParent()}});Ext.define("Ext.Label",{extend:"Ext.Component",xtype:"label",config:{}});Ext.define("Ext.Map",{extend:"Ext.Component",xtype:"map",requires:["Ext.util.GeoLocation"],isMap:true,config:{baseCls:Ext.baseCSSPrefix+"map",useCurrentLocation:false,map:null,geo:null,mapOptions:{}},constructor:function(){this.callParent(arguments);this.options={};this.element.setVisibilityMode(Ext.Element.OFFSETS);if(!(window.google||{}).maps){this.setHtml("Google Maps API is required")}},initialize:function(){this.callParent();this.on({painted:"doResize",scope:this});this.element.on("touchstart","onTouchStart",this)},onTouchStart:function(a){a.makeUnpreventable()},applyMapOptions:function(a){return Ext.merge({},this.options,a)},updateMapOptions:function(c){var b=(window.google||{}).maps,a=this.getMap();if(b&&a){a.setOptions(c)}},getMapOptions:function(){return Ext.merge({},this.options)},updateUseCurrentLocation:function(a){this.setGeo(a);if(!a){this.renderMap()}},applyGeo:function(a){return Ext.factory(a,Ext.util.GeoLocation,this.getGeo())},updateGeo:function(b,a){var c={locationupdate:"onGeoUpdate",locationerror:"onGeoError",scope:this};if(a){a.un(c)}if(b){b.on(c);b.updateLocation()}},doResize:function(){var b=(window.google||{}).maps,a=this.getMap();if(b&&a){b.event.trigger(a,"resize")}},renderMap:function(){var d=this,f=(window.google||{}).maps,b=d.element,a=d.getMapOptions(),e=d.getMap(),c;if(f){if(Ext.os.is.iPad){Ext.merge({navigationControlOptions:{style:f.NavigationControlStyle.ZOOM_PAN}},a)}a=Ext.merge({zoom:12,mapTypeId:f.MapTypeId.ROADMAP},a);if(!a.hasOwnProperty("center")){a.center=new f.LatLng(37.381592,-122.135672)}if(b.dom.firstChild){Ext.fly(b.dom.firstChild).destroy()}if(e){f.event.clearInstanceListeners(e)}d.setMap(new f.Map(b.dom,a));e=d.getMap();c=f.event;c.addListener(e,"zoom_changed",Ext.bind(d.onZoomChange,d));c.addListener(e,"maptypeid_changed",Ext.bind(d.onTypeChange,d));c.addListener(e,"center_changed",Ext.bind(d.onCenterChange,d));d.fireEvent("maprender",d,e)}},onGeoUpdate:function(a){if(a){this.setMapCenter(new google.maps.LatLng(a.getLatitude(),a.getLongitude()))}},onGeoError:Ext.emptyFn,setMapCenter:function(d){var a=this,c=a.getMap(),b=(window.google||{}).maps;if(b){if(!a.isPainted()){a.un("painted","setMapCenter",this);a.on("painted","setMapCenter",this,{single:true,args:[d]});return}d=d||new b.LatLng(37.381592,-122.135672);if(d&&!(d instanceof b.LatLng)&&"longitude" in d){d=new b.LatLng(d.latitude,d.longitude)}if(!c){a.renderMap();c=a.getMap()}if(c&&d instanceof b.LatLng){c.panTo(d)}else{this.options=Ext.apply(this.getMapOptions(),{center:d})}}},onZoomChange:function(){var a=this.getMapOptions(),c=this.getMap(),b;b=(c&&c.getZoom)?c.getZoom():a.zoom||10;this.options=Ext.apply(a,{zoom:b});this.fireEvent("zoomchange",this,c,b)},onTypeChange:function(){var b=this.getMapOptions(),c=this.getMap(),a;a=(c&&c.getMapTypeId)?c.getMapTypeId():b.mapTypeId;this.options=Ext.apply(b,{mapTypeId:a});this.fireEvent("typechange",this,c,a)},onCenterChange:function(){var b=this.getMapOptions(),c=this.getMap(),a;a=(c&&c.getCenter)?c.getCenter():b.center;this.options=Ext.apply(b,{center:a});this.fireEvent("centerchange",this,c,a)},destroy:function(){Ext.destroy(this.getGeo());var a=this.getMap();if(a&&(window.google||{}).maps){google.maps.event.clearInstanceListeners(a)}this.callParent()}},function(){});Ext.define("Ext.Mask",{extend:"Ext.Component",xtype:"mask",config:{baseCls:Ext.baseCSSPrefix+"mask",transparent:false,top:0,left:0,right:0,bottom:0},initialize:function(){this.callParent();this.on({painted:"onPainted",erased:"onErased"})},onPainted:function(){this.element.on("*","onEvent",this)},onErased:function(){this.element.un("*","onEvent",this)},onEvent:function(b){var a=arguments[arguments.length-1];if(a.info.eventName==="tap"){this.fireEvent("tap",this,b);return false}if(b&&b.stopEvent){b.stopEvent()}return false},updateTransparent:function(a){this[a?"addCls":"removeCls"](this.getBaseCls()+"-transparent")}});Ext.define("Ext.LoadMask",{extend:"Ext.Mask",xtype:"loadmask",config:{message:"Loading...",messageCls:Ext.baseCSSPrefix+"mask-message",indicator:true,listeners:{painted:"onPainted",erased:"onErased"}},getTemplate:function(){var a=Ext.baseCSSPrefix;return[{reference:"innerElement",cls:a+"mask-inner",children:[{reference:"indicatorElement",cls:a+"loading-spinner-outer",children:[{cls:a+"loading-spinner",children:[{tag:"span",cls:a+"loading-top"},{tag:"span",cls:a+"loading-right"},{tag:"span",cls:a+"loading-bottom"},{tag:"span",cls:a+"loading-left"}]}]},{reference:"messageElement"}]}]},updateMessage:function(a){this.messageElement.setHtml(a)},updateMessageCls:function(b,a){this.messageElement.replaceCls(a,b)},updateIndicator:function(a){this[a?"removeCls":"addCls"](Ext.baseCSSPrefix+"indicator-hidden")},onPainted:function(){this.getParent().on({scope:this,resize:this.refreshPosition});this.refreshPosition()},onErased:function(){this.getParent().un({scope:this,resize:this.refreshPosition})},refreshPosition:function(){var c=this.getParent(),d=c.getScrollable(),a=(d)?d.getScroller():null,f=(a)?a.position:{x:0,y:0},e=c.element.getSize(),b=this.element.getSize();this.innerElement.setStyle({marginTop:Math.round(e.height-b.height+(f.y*2))+"px",marginLeft:Math.round(e.width-b.width+f.x)+"px"})}},function(){});Ext.define("Ext.Media",{extend:"Ext.Component",xtype:"media",config:{url:"",enableControls:Ext.os.is.Android?false:true,autoResume:false,autoPause:true,preload:true,loop:false,media:null,playing:false,volume:1,muted:false},initialize:function(){var a=this;a.callParent();a.on({scope:a,activate:a.onActivate,deactivate:a.onDeactivate});a.addMediaListener({play:"onPlay",pause:"onPause",ended:"onEnd",volumechange:"onVolumeChange",timeupdate:"onTimeUpdate"})},addMediaListener:function(d,b){var c=this,e=c.media.dom,f=Ext.Function.bind;if(!Ext.isObject(d)){var a=d;d={};d[a]=b}Ext.Object.each(d,function(h,g){if(typeof g!=="function"){g=c[g]}if(typeof g=="function"){g=f(g,c);e.addEventListener(h,g)}})},onPlay:function(){this.fireEvent("play",this)},onPause:function(){this.fireEvent("pause",this,this.getCurrentTime())},onEnd:function(){this.fireEvent("ended",this,this.getCurrentTime())},onVolumeChange:function(){this.fireEvent("volumechange",this,this.media.dom.volume)},onTimeUpdate:function(){this.fireEvent("timeupdate",this,this.getCurrentTime())},isPlaying:function(){return this.getPlaying()},onActivate:function(){var a=this;if(a.getAutoResume()&&!a.isPlaying()){a.play()}},onDeactivate:function(){var a=this;if(a.getAutoResume()&&a.isPlaying()){a.pause()}},updateUrl:function(a){var b=this.media.dom;b.src=a;b.load();if(this.getPlaying()){this.play()}},updateEnableControls:function(a){this.media.dom.controls=a?"controls":false},updateLoop:function(a){this.media.dom.loop=a?"loop":false},play:function(){this.media.dom.play();this.setPlaying(true)},pause:function(){this.media.dom.pause();this.setPlaying(false)},toggle:function(){if(this.isPlaying()){this.pause()}else{this.play()}},stop:function(){var a=this;a.setCurrentTime(0);a.fireEvent("stop",a);a.pause()},updateVolume:function(a){this.media.dom.volume=a},updateMuted:function(a){this.fireEvent("mutedchange",this,a);this.media.dom.muted=a},getCurrentTime:function(){return this.media.dom.currentTime},setCurrentTime:function(a){this.media.dom.currentTime=a;return a},getDuration:function(){return this.media.dom.duration},destroy:function(){var a=this;Ext.Object.each(event,function(c,b){if(typeof b!=="function"){b=a[b]}if(typeof b=="function"){b=bind(b,a);dom.removeEventListener(c,b)}})}});Ext.define("Ext.Audio",{extend:"Ext.Media",xtype:"audio",config:{cls:Ext.baseCSSPrefix+"audio"},onActivate:function(){var a=this;a.callParent();if(Ext.os.is.Phone){a.element.show()}},onDeactivate:function(){var a=this;a.callParent();if(Ext.os.is.Phone){a.element.hide()}},template:[{reference:"media",preload:"auto",tag:"audio",cls:Ext.baseCSSPrefix+"component"}]});Ext.define("Ext.Spacer",{extend:"Ext.Component",alias:"widget.spacer",config:{},constructor:function(a){a=a||{};if(!a.width){a.flex=1}this.callParent([a])}});Ext.define("Ext.Title",{extend:"Ext.Component",xtype:"title",config:{baseCls:"x-title",title:""},updateTitle:function(a){this.setHtml(a)}});Ext.define("Ext.Video",{extend:"Ext.Media",xtype:"video",config:{posterUrl:null,cls:Ext.baseCSSPrefix+"video"},template:[{reference:"ghost",classList:[Ext.baseCSSPrefix+"video-ghost"]},{tag:"video",reference:"media",classList:[Ext.baseCSSPrefix+"media"]}],initialize:function(){var a=this;a.callParent();a.media.hide();a.onBefore({erased:"onErased",scope:a});a.ghost.on({tap:"onGhostTap",scope:a});a.media.on({pause:"onPause",scope:a});if(Ext.os.is.Android4||Ext.os.is.iPad){this.isInlineVideo=true}},applyUrl:function(a){return[].concat(a)},updateUrl:function(f){var c=this,e=c.media,g=f.length,d=e.query("source"),b=d.length,a;for(a=0;a0){a.pop().destroy()}},setActiveIndex:function(b){var e=this.indicators,d=this.activeIndex,a=e[d],f=e[b],c=this.getBaseCls();if(a){a.removeCls(c,null,"active")}if(f){f.addCls(c,null,"active")}this.activeIndex=b;return this},onTap:function(f){var g=f.touch,a=this.element.getPageBox(),d=a.left+(a.width/2),b=a.top+(a.height/2),c=this.getDirection();if((c==="horizontal"&&g.pageX>=d)||(c==="vertical"&&g.pageY>=b)){this.fireEvent("next",this)}else{this.fireEvent("previous",this)}},destroy:function(){var d=this.indicators,b,c,a;for(b=0,c=d.length;bd.bottom||a.yd.right||a.x div",scope:this})},initialize:function(){this.callParent();this.doInitialize()},updateBaseCls:function(a,b){var c=this;c.callParent([a+"-container",b])},onItemTouchStart:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);Ext.get(c).on({touchmove:"onItemTouchMove",scope:b,single:true});b.fireEvent("itemtouchstart",b,Ext.get(c),a,d)},onItemTouchEnd:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);Ext.get(c).un({touchmove:"onItemTouchMove",scope:b});b.fireEvent("itemtouchend",b,Ext.get(c),a,d)},onItemTouchMove:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);b.fireEvent("itemtouchmove",b,Ext.get(c),a,d)},onItemTap:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);b.fireEvent("itemtap",b,Ext.get(c),a,d)},onItemTapHold:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);b.fireEvent("itemtaphold",b,Ext.get(c),a,d)},onItemDoubleTap:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);b.fireEvent("itemdoubletap",b,Ext.get(c),a,d)},onItemSwipe:function(d){var b=this,c=d.getTarget(),a=b.getViewItems().indexOf(c);b.fireEvent("itemswipe",b,Ext.get(c),a,d)},updateListItem:function(b,d){var c=this,a=c.dataview,e=a.prepareData(b.getData(true),a.getStore().indexOf(b),b);d.innerHTML=c.dataview.getItemTpl().apply(e)},addListItem:function(e,c){var h=this,d=h.dataview,a=d.prepareData(c.getData(true),d.getStore().indexOf(c),c),b=h.element,i=b.dom.childNodes,g=i.length,f;f=Ext.Element.create(this.getItemElementConfig(e,a));if(!g||e==g){f.appendTo(b)}else{f.insertBefore(i[e])}},getItemElementConfig:function(c,e){var b=this.dataview,d=b.getItemCls(),a=b.getBaseCls()+"-item";if(d){a+=" "+d}return{cls:a,html:b.getItemTpl().apply(e)}},doRemoveItemCls:function(a){var d=this.getViewItems(),c=d.length,b=0;for(;b=0;b--){c=a[f+b];c.parentNode.removeChild(c)}if(d.getViewItems().length==0){this.dataview.showEmptyText()}},moveItemsFromCache:function(d){var g=this,b=g.dataview,c=b.getStore(),f=d.length,e,a;if(f){b.hideEmptyText()}for(e=0;eh._tmpIndex?1:-1});for(e=0;e(?:[\s]*)|(?:\s*))([\w\-]+)$/i,handledEvents:["*"],getSubscribers:function(b,a){var d=this.subscribers,c=d[b];if(!c&&a){c=d[b]={type:{$length:0},selector:[],$length:0}}return c},subscribe:function(g,f){if(this.idSelectorRegex.test(g)){return false}var e=g.match(this.optimizedSelectorRegex),a=this.getSubscribers(f,true),k=a.type,c=a.selector,d,i,j,b,h;if(e!==null){d=e[1];i=e[2].indexOf(">")===-1;j=e[3];b=k[j];if(!b){k[j]=b={descendents:{$length:0},children:{$length:0},$length:0}}h=i?b.descendents:b.children;if(h.hasOwnProperty(d)){h[d]++;return true}h[d]=1;h.$length++;b.$length++;k.$length++}else{if(c.hasOwnProperty(g)){c[g]++;return true}c[g]=1;c.push(g)}a.$length++;return true},unsubscribe:function(g,f,k){var a=this.getSubscribers(f);if(!a){return false}var e=g.match(this.optimizedSelectorRegex),l=a.type,c=a.selector,d,i,j,b,h;k=Boolean(k);if(e!==null){d=e[1];i=e[2].indexOf(">")===-1;j=e[3];b=l[j];if(!b){return true}h=i?b.descendents:b.children;if(!h.hasOwnProperty(d)||(!k&&--h[d]>0)){return true}delete h[d];h.$length--;b.$length--;l.$length--}else{if(!c.hasOwnProperty(g)||(!k&&--c[g]>0)){return true}delete c[g];Ext.Array.remove(c,g)}if(--a.$length===0){delete this.subscribers[f]}return true},notify:function(d,a){var c=this.getSubscribers(a),e,b;if(!c||c.$length===0){return false}e=d.substr(1);b=Ext.ComponentManager.get(e);if(b){this.dispatcher.doAddListener(this.targetType,d,a,"publish",this,{args:[a,b]},"before")}},matchesSelector:function(b,a){return Ext.ComponentQuery.is(b,a)},dispatch:function(d,b,c,a){this.dispatcher.doDispatchEvent(this.targetType,d,b,c,null,a)},publish:function(g,k){var e=this.getSubscribers(g);if(!e){return}var p=arguments[arguments.length-1],o=e.type,b=e.selector,d=Array.prototype.slice.call(arguments,2,-2),l=k.xtypesChain,s,n,t,a,m,v,r,u,h,f,q,c;for(u=0,h=l.length;u0){s=e.descendents;if(s.$length>0){if(!a){a=k.getAncestorIds()}for(q=0,c=a.length;q0){if(!t){if(a){t=a[0]}else{v=k.getParent();if(v){t=v.getId()}}}if(t){if(n.hasOwnProperty(t)){this.dispatch("#"+t+" > "+f,g,d,p)}}}}}h=b.length;if(h>0){for(u=0;uf){d=e}}c.setValue(d);d=c.getValue();c.fireEvent("spin",c,d,g);c.fireEvent("spin"+g,c,d)},doSetDisabled:function(a){Ext.Component.prototype.doSetDisabled.apply(this,arguments)},setDisabled:function(){Ext.Component.prototype.setDisabled.apply(this,arguments)},reset:function(){this.setValue(this.getDefaultValue())},destroy:function(){var a=this;Ext.destroy(a.downRepeater,a.upRepeater,a.spinDownButton,a.spinUpButton);a.callParent(arguments)}},function(){});Ext.define("Ext.field.TextAreaInput",{extend:"Ext.field.Input",xtype:"textareainput",tag:"textarea"});Ext.define("Ext.field.TextArea",{extend:"Ext.field.Text",xtype:"textareafield",requires:["Ext.field.TextAreaInput"],alternateClassName:"Ext.form.TextArea",config:{ui:"textarea",autoCapitalize:false,component:{xtype:"textareainput"},maxRows:null},updateMaxRows:function(a){this.getComponent().setMaxRows(a)},doSetHeight:function(a){this.callParent(arguments);var b=this.getComponent();b.input.setHeight(a)},doSetWidth:function(b){this.callParent(arguments);var a=this.getComponent();a.input.setWidth(b)},doKeyUp:function(a){var b=a.getValue();a[b?"showClearIcon":"hideClearIcon"]()}});Ext.define("Ext.field.Url",{extend:"Ext.field.Text",xtype:"urlfield",alternateClassName:"Ext.form.Url",config:{autoCapitalize:false,component:{type:"url"}}});Ext.define("Ext.plugin.ListPaging",{extend:"Ext.Component",alias:"plugin.listpaging",config:{autoPaging:false,loadMoreText:"Load More...",noMoreRecordsText:"No More Records",loadTpl:['