From 872192923463820529e6e77963afb4bfcfb5ce53 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Fri, 13 Sep 2024 21:16:04 +0900 Subject: Rename private q* headers into equivalent tq* Signed-off-by: Michele Calgaro --- doc/changes.doc | 4 +- doc/html/index | 18 +- doc/html/tqaccessible-h.html | 2 +- doc/html/tqfont-h.html | 4 +- include/private/qcom_p.h | 1 - include/private/qcomlibrary_p.h | 1 - include/private/qcriticalsection_p.h | 1 - include/private/qeffects_p.h | 1 - include/private/qinternal_p.h | 1 - include/private/qpluginmanager_p.h | 1 - include/private/qpsprinter_p.h | 1 - include/private/qrichtext_p.h | 1 - include/private/qscriptengine_p.h | 1 - include/private/qsvgdevice_p.h | 1 - include/private/qt_x11_p.h | 1 - include/private/qtitlebar_p.h | 1 - include/private/qucom_p.h | 1 - include/private/qucomextra_p.h | 1 - include/private/qunicodetables_p.h | 1 - include/private/tqcom_p.h | 1 + include/private/tqcomlibrary_p.h | 1 + include/private/tqcriticalsection_p.h | 1 + include/private/tqeffects_p.h | 1 + include/private/tqinternal_p.h | 1 + include/private/tqpluginmanager_p.h | 1 + include/private/tqpsprinter_p.h | 1 + include/private/tqrichtext_p.h | 1 + include/private/tqscriptengine_p.h | 1 + include/private/tqsvgdevice_p.h | 1 + include/private/tqt_x11_p.h | 1 + include/private/tqtitlebar_p.h | 1 + include/private/tqucom_p.h | 1 + include/private/tqucomextra_p.h | 1 + include/private/tqunicodetables_p.h | 1 + .../src/accessible/widgets/tqaccessiblewidget.cpp | 2 +- plugins/src/inputmethods/xim/qximinputcontext.h | 2 +- qmake/Makefile.unix | 6 +- qmake/Makefile.win32-g++ | 6 +- src/codecs/tqtextcodecfactory.cpp | 2 +- src/codecs/tqtextcodecinterface_p.h | 4 +- src/dialogs/tqdialog.cpp | 2 +- src/inputmethod/tqinputcontextfactory.cpp | 2 +- src/inputmethod/tqinputcontextinterface_p.h | 2 +- src/kernel/makepsheader.pl | 4 +- src/kernel/qapplication_x11.cpp | 8 +- src/kernel/qdnd_x11.cpp | 2 +- src/kernel/qinternal.cpp | 787 -- src/kernel/qinternal_p.h | 213 - src/kernel/qpsprinter.cpp | 6574 --------- src/kernel/qpsprinter.ps | 805 -- src/kernel/qpsprinter_p.h | 92 - src/kernel/qrichtext.cpp | 8258 ------------ src/kernel/qrichtext_p.cpp | 655 - src/kernel/qrichtext_p.h | 2142 --- src/kernel/qscriptengine.cpp | 1622 --- src/kernel/qscriptengine_p.h | 83 - src/kernel/qscriptengine_x11.cpp | 3744 ------ src/kernel/qt_kernel.pri | 22 +- src/kernel/qt_pch.h | 2 +- src/kernel/qt_x11.pri | 23 - src/kernel/qt_x11_p.h | 280 - src/kernel/qtaddons_x11.cpp | 2 +- src/kernel/qucomextra.cpp | 177 - src/kernel/qucomextra_p.h | 111 - src/kernel/tqaccessible.cpp | 2 +- src/kernel/tqaccessible.h | 2 +- src/kernel/tqclipboard_x11.cpp | 2 +- src/kernel/tqcolor_x11.cpp | 2 +- src/kernel/tqcursor_x11.cpp | 2 +- src/kernel/tqdesktopwidget_x11.cpp | 2 +- src/kernel/tqeventloop_x11.cpp | 2 +- src/kernel/tqeventloop_x11_glib.cpp | 2 +- src/kernel/tqfont.cpp | 2 +- src/kernel/tqfont.h | 4 +- src/kernel/tqfont_x11.cpp | 4 +- src/kernel/tqfontdatabase.cpp | 2 +- src/kernel/tqfontdatabase_x11.cpp | 2 +- src/kernel/tqfontengine_p.h | 4 +- src/kernel/tqfontengine_x11.cpp | 6 +- src/kernel/tqgplugin.cpp | 2 +- src/kernel/tqgplugin.h | 4 +- src/kernel/tqimage.cpp | 2 +- src/kernel/tqimageformatinterface_p.h | 2 +- src/kernel/tqinputcontext_p.h | 2 +- src/kernel/tqinputcontext_x11.cpp | 2 +- src/kernel/tqinternal.cpp | 787 ++ src/kernel/tqinternal_p.h | 213 + src/kernel/tqmotifdnd_x11.cpp | 2 +- src/kernel/tqobject.cpp | 4 +- src/kernel/tqpaintdevice_x11.cpp | 2 +- src/kernel/tqpainter.cpp | 2 +- src/kernel/tqpainter_x11.cpp | 2 +- src/kernel/tqpicture.cpp | 2 +- src/kernel/tqpixmap.cpp | 2 +- src/kernel/tqpixmap_x11.cpp | 2 +- src/kernel/tqprinter_unix.cpp | 2 +- src/kernel/tqprocess.cpp | 2 +- src/kernel/tqprocess_unix.cpp | 2 +- src/kernel/tqpsprinter.cpp | 6574 +++++++++ src/kernel/tqpsprinter.ps | 805 ++ src/kernel/tqpsprinter_p.h | 92 + src/kernel/tqregion_x11.cpp | 2 +- src/kernel/tqrichtext.cpp | 8258 ++++++++++++ src/kernel/tqrichtext_p.cpp | 655 + src/kernel/tqrichtext_p.h | 2142 +++ src/kernel/tqscriptengine.cpp | 1622 +++ src/kernel/tqscriptengine_p.h | 83 + src/kernel/tqscriptengine_x11.cpp | 3744 ++++++ src/kernel/tqsimplerichtext.cpp | 2 +- src/kernel/tqsizegrip.cpp | 2 +- src/kernel/tqstylesheet.cpp | 2 +- src/kernel/tqt3.h | 26 +- src/kernel/tqt_x11.pri | 23 + src/kernel/tqt_x11_p.h | 280 + src/kernel/tqtextengine.cpp | 4 +- src/kernel/tqucomextra.cpp | 177 + src/kernel/tqucomextra_p.h | 111 + src/kernel/tqwidget_x11.cpp | 2 +- src/kernel/tqwidgetcreate_x11.cpp | 2 +- src/libqt.map | 6 +- src/moc/moc.pro | 2 +- src/moc/moc.y | 2 +- src/moc/moc_yacc.cpp | 2 +- src/network/tqhttp.cpp | 2 +- src/network/tqsocket.cpp | 2 +- src/opengl/tqgl.cpp | 2 +- src/qt.pro | 6 +- src/sql/drivers/odbc/tqsql_odbc.cpp | 2 +- src/sql/tqsqldatabase.cpp | 2 +- src/sql/tqsqldriverinterface_p.h | 2 +- src/styles/tqcommonstyle.cpp | 2 +- src/styles/tqstylefactory.cpp | 2 +- src/styles/tqstyleinterface_p.h | 2 +- src/tools/qcom_p.h | 344 - src/tools/qcomlibrary.cpp | 538 - src/tools/qcomlibrary_p.h | 82 - src/tools/qcriticalsection_p.cpp | 76 - src/tools/qcriticalsection_p.h | 83 - src/tools/qpluginmanager_p.h | 76 - src/tools/qt_tools.pri | 18 +- src/tools/qucom.cpp | 573 - src/tools/qucom_p.h | 472 - src/tools/qunicodetables.cpp | 13257 ------------------- src/tools/qunicodetables_p.h | 266 - src/tools/tqcom_p.h | 344 + src/tools/tqcomlibrary.cpp | 538 + src/tools/tqcomlibrary_p.h | 82 + src/tools/tqcomponentfactory.cpp | 2 +- src/tools/tqcomponentfactory_p.h | 2 +- src/tools/tqcriticalsection_p.cpp | 76 + src/tools/tqcriticalsection_p.h | 83 + src/tools/tqgpluginmanager.cpp | 4 +- src/tools/tqgpluginmanager_p.h | 2 +- src/tools/tqpluginmanager_p.h | 76 + src/tools/tqstring.cpp | 2 +- src/tools/tqucom.cpp | 573 + src/tools/tqucom_p.h | 472 + src/tools/tqunicodetables.cpp | 13257 +++++++++++++++++++ src/tools/tqunicodetables_p.h | 266 + src/widgets/qeffects.cpp | 675 - src/widgets/qeffects_p.h | 81 - src/widgets/qt_widgets.pri | 6 +- src/widgets/qtitlebar.cpp | 671 - src/widgets/qtitlebar_p.h | 139 - src/widgets/tqbutton.cpp | 2 +- src/widgets/tqcombobox.cpp | 2 +- src/widgets/tqdatetimeedit.cpp | 4 +- src/widgets/tqdockwindow.cpp | 2 +- src/widgets/tqeffects.cpp | 675 + src/widgets/tqeffects_p.h | 81 + src/widgets/tqiconview.cpp | 2 +- src/widgets/tqlineedit.cpp | 2 +- src/widgets/tqlistview.cpp | 2 +- src/widgets/tqmenubar.cpp | 2 +- src/widgets/tqmultilineedit.cpp | 2 +- src/widgets/tqpopupmenu.cpp | 2 +- src/widgets/tqprogressbar.cpp | 2 +- src/widgets/tqsyntaxhighlighter.cpp | 2 +- src/widgets/tqsyntaxhighlighter_p.h | 2 +- src/widgets/tqtabbar.cpp | 2 +- src/widgets/tqtextbrowser.cpp | 2 +- src/widgets/tqtextedit.cpp | 4 +- src/widgets/tqtitlebar.cpp | 671 + src/widgets/tqtitlebar_p.h | 139 + src/widgets/tqtooltip.cpp | 2 +- src/widgets/tqwidgetinterface_p.h | 2 +- src/workspace/tqworkspace.cpp | 2 +- src/xml/qsvgdevice.cpp | 1591 --- src/xml/qsvgdevice_p.h | 140 - src/xml/qt_xml.pri | 4 +- src/xml/tqsvgdevice.cpp | 1591 +++ src/xml/tqsvgdevice_p.h | 140 + tools/designer/designer/designer.pro | 4 +- tools/designer/designer/designer_pch.h | 2 +- tools/designer/designer/hierarchyview.h | 2 +- tools/designer/designer/mainwindow.cpp | 2 +- tools/designer/designer/mainwindow.h | 2 +- tools/designer/designer/metadatabase.cpp | 2 +- tools/designer/designer/multilineeditorimpl.cpp | 2 +- tools/designer/designer/multilineeditorimpl.h | 2 +- tools/designer/designer/project.h | 2 +- tools/designer/designer/qcompletionedit.cpp | 217 - tools/designer/designer/qcompletionedit.h | 86 - tools/designer/designer/resource.cpp | 2 +- tools/designer/designer/syntaxhighlighter_html.h | 2 +- tools/designer/designer/tqcompletionedit.cpp | 217 + tools/designer/designer/tqcompletionedit.h | 86 + tools/designer/designer/workspace.cpp | 2 +- tools/designer/editor/browser.cpp | 2 +- tools/designer/editor/cindent.h | 2 +- tools/designer/editor/completion.cpp | 2 +- tools/designer/editor/editor.cpp | 2 +- tools/designer/editor/markerwidget.cpp | 2 +- tools/designer/editor/paragdata.h | 2 +- tools/designer/editor/parenmatcher.cpp | 2 +- tools/designer/editor/viewmanager.cpp | 2 +- tools/designer/interfaces/actioninterface.h | 2 +- tools/designer/interfaces/classbrowserinterface.h | 2 +- tools/designer/interfaces/designerinterface.h | 2 +- tools/designer/interfaces/editorinterface.h | 2 +- tools/designer/interfaces/filterinterface.h | 2 +- tools/designer/interfaces/interpreterinterface.h | 2 +- tools/designer/interfaces/languageinterface.h | 2 +- tools/designer/interfaces/preferenceinterface.h | 2 +- tools/designer/interfaces/projectsettingsiface.h | 2 +- tools/designer/interfaces/sourcetemplateiface.h | 2 +- tools/designer/interfaces/templatewizardiface.h | 2 +- tools/designer/plugins/cppeditor/cppbrowser.cpp | 2 +- .../plugins/cppeditor/editorinterfaceimpl.cpp | 2 +- .../plugins/cppeditor/syntaxhighliter_cpp.h | 2 +- tools/designer/shared/widgetdatabase.h | 2 +- tools/designer/tools/tqtconv2ui/main.cpp | 2 +- tools/designer/uilib/tqwidgetfactory.cpp | 2 +- tools/linguist/linguist/msgedit.cpp | 2 +- translations/qt_ar.ts | 2 +- translations/qt_ca.ts | 2 +- translations/qt_cs.ts | 2 +- translations/qt_de.ts | 2 +- translations/qt_es.ts | 2 +- translations/qt_fr.ts | 2 +- translations/qt_he.ts | 2 +- translations/qt_it.ts | 2 +- translations/qt_ja.ts | 2 +- translations/qt_nb.ts | 2 +- translations/qt_pt-br.ts | 2 +- translations/qt_pt.ts | 2 +- translations/qt_ru.ts | 2 +- translations/qt_sk.ts | 2 +- translations/qt_tr.ts | 2 +- translations/qt_zh-cn.ts | 2 +- translations/qt_zh-tw.ts | 2 +- translations/template.ts | 2 +- 252 files changed, 45172 insertions(+), 45172 deletions(-) delete mode 120000 include/private/qcom_p.h delete mode 120000 include/private/qcomlibrary_p.h delete mode 120000 include/private/qcriticalsection_p.h delete mode 120000 include/private/qeffects_p.h delete mode 120000 include/private/qinternal_p.h delete mode 120000 include/private/qpluginmanager_p.h delete mode 120000 include/private/qpsprinter_p.h delete mode 120000 include/private/qrichtext_p.h delete mode 120000 include/private/qscriptengine_p.h delete mode 120000 include/private/qsvgdevice_p.h delete mode 120000 include/private/qt_x11_p.h delete mode 120000 include/private/qtitlebar_p.h delete mode 120000 include/private/qucom_p.h delete mode 120000 include/private/qucomextra_p.h delete mode 120000 include/private/qunicodetables_p.h create mode 120000 include/private/tqcom_p.h create mode 120000 include/private/tqcomlibrary_p.h create mode 120000 include/private/tqcriticalsection_p.h create mode 120000 include/private/tqeffects_p.h create mode 120000 include/private/tqinternal_p.h create mode 120000 include/private/tqpluginmanager_p.h create mode 120000 include/private/tqpsprinter_p.h create mode 120000 include/private/tqrichtext_p.h create mode 120000 include/private/tqscriptengine_p.h create mode 120000 include/private/tqsvgdevice_p.h create mode 120000 include/private/tqt_x11_p.h create mode 120000 include/private/tqtitlebar_p.h create mode 120000 include/private/tqucom_p.h create mode 120000 include/private/tqucomextra_p.h create mode 120000 include/private/tqunicodetables_p.h delete mode 100644 src/kernel/qinternal.cpp delete mode 100644 src/kernel/qinternal_p.h delete mode 100644 src/kernel/qpsprinter.cpp delete mode 100644 src/kernel/qpsprinter.ps delete mode 100644 src/kernel/qpsprinter_p.h delete mode 100644 src/kernel/qrichtext.cpp delete mode 100644 src/kernel/qrichtext_p.cpp delete mode 100644 src/kernel/qrichtext_p.h delete mode 100644 src/kernel/qscriptengine.cpp delete mode 100644 src/kernel/qscriptengine_p.h delete mode 100644 src/kernel/qscriptengine_x11.cpp delete mode 100644 src/kernel/qt_x11.pri delete mode 100644 src/kernel/qt_x11_p.h delete mode 100644 src/kernel/qucomextra.cpp delete mode 100644 src/kernel/qucomextra_p.h create mode 100644 src/kernel/tqinternal.cpp create mode 100644 src/kernel/tqinternal_p.h create mode 100644 src/kernel/tqpsprinter.cpp create mode 100644 src/kernel/tqpsprinter.ps create mode 100644 src/kernel/tqpsprinter_p.h create mode 100644 src/kernel/tqrichtext.cpp create mode 100644 src/kernel/tqrichtext_p.cpp create mode 100644 src/kernel/tqrichtext_p.h create mode 100644 src/kernel/tqscriptengine.cpp create mode 100644 src/kernel/tqscriptengine_p.h create mode 100644 src/kernel/tqscriptengine_x11.cpp create mode 100644 src/kernel/tqt_x11.pri create mode 100644 src/kernel/tqt_x11_p.h create mode 100644 src/kernel/tqucomextra.cpp create mode 100644 src/kernel/tqucomextra_p.h delete mode 100644 src/tools/qcom_p.h delete mode 100644 src/tools/qcomlibrary.cpp delete mode 100644 src/tools/qcomlibrary_p.h delete mode 100644 src/tools/qcriticalsection_p.cpp delete mode 100644 src/tools/qcriticalsection_p.h delete mode 100644 src/tools/qpluginmanager_p.h delete mode 100644 src/tools/qucom.cpp delete mode 100644 src/tools/qucom_p.h delete mode 100644 src/tools/qunicodetables.cpp delete mode 100644 src/tools/qunicodetables_p.h create mode 100644 src/tools/tqcom_p.h create mode 100644 src/tools/tqcomlibrary.cpp create mode 100644 src/tools/tqcomlibrary_p.h create mode 100644 src/tools/tqcriticalsection_p.cpp create mode 100644 src/tools/tqcriticalsection_p.h create mode 100644 src/tools/tqpluginmanager_p.h create mode 100644 src/tools/tqucom.cpp create mode 100644 src/tools/tqucom_p.h create mode 100644 src/tools/tqunicodetables.cpp create mode 100644 src/tools/tqunicodetables_p.h delete mode 100644 src/widgets/qeffects.cpp delete mode 100644 src/widgets/qeffects_p.h delete mode 100644 src/widgets/qtitlebar.cpp delete mode 100644 src/widgets/qtitlebar_p.h create mode 100644 src/widgets/tqeffects.cpp create mode 100644 src/widgets/tqeffects_p.h create mode 100644 src/widgets/tqtitlebar.cpp create mode 100644 src/widgets/tqtitlebar_p.h delete mode 100644 src/xml/qsvgdevice.cpp delete mode 100644 src/xml/qsvgdevice_p.h create mode 100644 src/xml/tqsvgdevice.cpp create mode 100644 src/xml/tqsvgdevice_p.h delete mode 100644 tools/designer/designer/qcompletionedit.cpp delete mode 100644 tools/designer/designer/qcompletionedit.h create mode 100644 tools/designer/designer/tqcompletionedit.cpp create mode 100644 tools/designer/designer/tqcompletionedit.h diff --git a/doc/changes.doc b/doc/changes.doc index 211f01f61..6ce47761c 100644 --- a/doc/changes.doc +++ b/doc/changes.doc @@ -128,7 +128,7 @@ terms of Qt's signals/slots mechanism directly in TQt Designer. The TQLibrary class provides a platform independent wrapper for runtime loading of shared libraries. Access to the shared libraries uses a -COM-like interface. QPluginManager makes it trivial to implement +COM-like interface. TQPluginManager makes it trivial to implement plugin support in applications. The TQt library is able to load additional styles, database drivers and text codecs from plugins which implement the relevant interfaces, e.g. TQStyleFactoryInterface, @@ -146,7 +146,7 @@ component. \section2 Plugins The TQLibrary class provides a platform independent wrapper for runtime -loading of shared libraries. QPluginManager makes it trivial to implement +loading of shared libraries. TQPluginManager makes it trivial to implement plugin support in applications. The TQt library is able to load additional styles, database drivers and text codecs from plugins. diff --git a/doc/html/index b/doc/html/index index 681eade10..d9bd1fa4d 100644 --- a/doc/html/index +++ b/doc/html/index @@ -4541,7 +4541,7 @@ "TQPlatinumStyle" tqplatinumstyle.html "TQPlatinumStyle::drawRiffles" tqplatinumstyle.html#drawRiffles "TQPlatinumStyle::mixedColor" tqplatinumstyle.html#mixedColor -"QPluginManager::queryInterface" qpluginmanager.html#queryInterface +"TQPluginManager::queryInterface" tqpluginmanager.html#queryInterface "TQPoint" tqpoint.html "TQPoint::isNull" tqpoint.html#isNull "TQPoint::manhattanLength" tqpoint.html#manhattanLength @@ -6085,14 +6085,14 @@ "TQStyleSheetItem::verticalAlignment" tqstylesheetitem.html#verticalAlignment "TQStyleSheetItem::whiteSpaceMode" tqstylesheetitem.html#whiteSpaceMode "TQStyleSheetItem::~TQStyleSheetItem" tqstylesheetitem.html#~TQStyleSheetItem -"QSvgDevice::boundingRect" qsvgdevice.html#boundingRect -"QSvgDevice::load" qsvgdevice.html#load -"QSvgDevice::metric" qsvgdevice.html#metric -"QSvgDevice::play" qsvgdevice.html#play -"QSvgDevice::save" qsvgdevice.html#save -"QSvgDevice::setBoundingRect" qsvgdevice.html#setBoundingRect -"QSvgDevice::toString" qsvgdevice.html#toString -"QSvgDevice::~QSvgDevice" qsvgdevice.html#~QSvgDevice +"TQSvgDevice::boundingRect" tqsvgdevice.html#boundingRect +"TQSvgDevice::load" tqsvgdevice.html#load +"TQSvgDevice::metric" tqsvgdevice.html#metric +"TQSvgDevice::play" tqsvgdevice.html#play +"TQSvgDevice::save" tqsvgdevice.html#save +"TQSvgDevice::setBoundingRect" tqsvgdevice.html#setBoundingRect +"TQSvgDevice::toString" tqsvgdevice.html#toString +"TQSvgDevice::~TQSvgDevice" tqsvgdevice.html#~TQSvgDevice "TQSyntaxHighlighter" tqsyntaxhighlighter.html "TQSyntaxHighlighter::currentParagraph" tqsyntaxhighlighter.html#currentParagraph "TQSyntaxHighlighter::highlightParagraph" tqsyntaxhighlighter.html#highlightParagraph diff --git a/doc/html/tqaccessible-h.html b/doc/html/tqaccessible-h.html index a8f91de1e..10ceff028 100644 --- a/doc/html/tqaccessible-h.html +++ b/doc/html/tqaccessible-h.html @@ -77,7 +77,7 @@ body { background: #ffffff; color: black; } #ifndef QT_H #include "tqobject.h" -#include <private/qcom_p.h> +#include <private/tqcom_p.h> #include "tqrect.h" #include "tqguardedptr.h" #include "tqmemarray.h" diff --git a/doc/html/tqfont-h.html b/doc/html/tqfont-h.html index 211c05854..d05fe7182 100644 --- a/doc/html/tqfont-h.html +++ b/doc/html/tqfont-h.html @@ -229,9 +229,9 @@ public: static void cleanup(); static void cacheStatistics(); - // a copy of this lives in qunicodetables.cpp, as we can't include + // a copy of this lives in tqunicodetables.cpp, as we can't include // tqfont.h it in tools/. Do not modify without changing the script - // enum in qunicodetable_p.h aswell. + // enum in tqunicodetable_p.h aswell. enum Script { // European Alphabetic Scripts Latin, diff --git a/include/private/qcom_p.h b/include/private/qcom_p.h deleted file mode 120000 index 6c63b4c86..000000000 --- a/include/private/qcom_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/tools/qcom_p.h \ No newline at end of file diff --git a/include/private/qcomlibrary_p.h b/include/private/qcomlibrary_p.h deleted file mode 120000 index 895c52cba..000000000 --- a/include/private/qcomlibrary_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/tools/qcomlibrary_p.h \ No newline at end of file diff --git a/include/private/qcriticalsection_p.h b/include/private/qcriticalsection_p.h deleted file mode 120000 index b8cdb3bc2..000000000 --- a/include/private/qcriticalsection_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/tools/qcriticalsection_p.h \ No newline at end of file diff --git a/include/private/qeffects_p.h b/include/private/qeffects_p.h deleted file mode 120000 index dddcf5a9f..000000000 --- a/include/private/qeffects_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/widgets/qeffects_p.h \ No newline at end of file diff --git a/include/private/qinternal_p.h b/include/private/qinternal_p.h deleted file mode 120000 index 26720c757..000000000 --- a/include/private/qinternal_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/kernel/qinternal_p.h \ No newline at end of file diff --git a/include/private/qpluginmanager_p.h b/include/private/qpluginmanager_p.h deleted file mode 120000 index c1574c9aa..000000000 --- a/include/private/qpluginmanager_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/tools/qpluginmanager_p.h \ No newline at end of file diff --git a/include/private/qpsprinter_p.h b/include/private/qpsprinter_p.h deleted file mode 120000 index 399bc547b..000000000 --- a/include/private/qpsprinter_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/kernel/qpsprinter_p.h \ No newline at end of file diff --git a/include/private/qrichtext_p.h b/include/private/qrichtext_p.h deleted file mode 120000 index 19f04da65..000000000 --- a/include/private/qrichtext_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/kernel/qrichtext_p.h \ No newline at end of file diff --git a/include/private/qscriptengine_p.h b/include/private/qscriptengine_p.h deleted file mode 120000 index eaeb684c5..000000000 --- a/include/private/qscriptengine_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/kernel/qscriptengine_p.h \ No newline at end of file diff --git a/include/private/qsvgdevice_p.h b/include/private/qsvgdevice_p.h deleted file mode 120000 index 91514333f..000000000 --- a/include/private/qsvgdevice_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/xml/qsvgdevice_p.h \ No newline at end of file diff --git a/include/private/qt_x11_p.h b/include/private/qt_x11_p.h deleted file mode 120000 index 4ff3ba1f3..000000000 --- a/include/private/qt_x11_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/kernel/qt_x11_p.h \ No newline at end of file diff --git a/include/private/qtitlebar_p.h b/include/private/qtitlebar_p.h deleted file mode 120000 index 7334f9d5e..000000000 --- a/include/private/qtitlebar_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/widgets/qtitlebar_p.h \ No newline at end of file diff --git a/include/private/qucom_p.h b/include/private/qucom_p.h deleted file mode 120000 index c26c7f2ba..000000000 --- a/include/private/qucom_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/tools/qucom_p.h \ No newline at end of file diff --git a/include/private/qucomextra_p.h b/include/private/qucomextra_p.h deleted file mode 120000 index e0dbd21c8..000000000 --- a/include/private/qucomextra_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/kernel/qucomextra_p.h \ No newline at end of file diff --git a/include/private/qunicodetables_p.h b/include/private/qunicodetables_p.h deleted file mode 120000 index cdc5ef8bd..000000000 --- a/include/private/qunicodetables_p.h +++ /dev/null @@ -1 +0,0 @@ -../../src/tools/qunicodetables_p.h \ No newline at end of file diff --git a/include/private/tqcom_p.h b/include/private/tqcom_p.h new file mode 120000 index 000000000..7df32dfb7 --- /dev/null +++ b/include/private/tqcom_p.h @@ -0,0 +1 @@ +../../src/tools/tqcom_p.h \ No newline at end of file diff --git a/include/private/tqcomlibrary_p.h b/include/private/tqcomlibrary_p.h new file mode 120000 index 000000000..621dc9f72 --- /dev/null +++ b/include/private/tqcomlibrary_p.h @@ -0,0 +1 @@ +../../src/tools/tqcomlibrary_p.h \ No newline at end of file diff --git a/include/private/tqcriticalsection_p.h b/include/private/tqcriticalsection_p.h new file mode 120000 index 000000000..6c11336c8 --- /dev/null +++ b/include/private/tqcriticalsection_p.h @@ -0,0 +1 @@ +../../src/tools/tqcriticalsection_p.h \ No newline at end of file diff --git a/include/private/tqeffects_p.h b/include/private/tqeffects_p.h new file mode 120000 index 000000000..d37580369 --- /dev/null +++ b/include/private/tqeffects_p.h @@ -0,0 +1 @@ +../../src/widgets/tqeffects_p.h \ No newline at end of file diff --git a/include/private/tqinternal_p.h b/include/private/tqinternal_p.h new file mode 120000 index 000000000..bdd99f012 --- /dev/null +++ b/include/private/tqinternal_p.h @@ -0,0 +1 @@ +../../src/kernel/tqinternal_p.h \ No newline at end of file diff --git a/include/private/tqpluginmanager_p.h b/include/private/tqpluginmanager_p.h new file mode 120000 index 000000000..b661d0399 --- /dev/null +++ b/include/private/tqpluginmanager_p.h @@ -0,0 +1 @@ +../../src/tools/tqpluginmanager_p.h \ No newline at end of file diff --git a/include/private/tqpsprinter_p.h b/include/private/tqpsprinter_p.h new file mode 120000 index 000000000..9c1c61fd0 --- /dev/null +++ b/include/private/tqpsprinter_p.h @@ -0,0 +1 @@ +../../src/kernel/tqpsprinter_p.h \ No newline at end of file diff --git a/include/private/tqrichtext_p.h b/include/private/tqrichtext_p.h new file mode 120000 index 000000000..72b48fc79 --- /dev/null +++ b/include/private/tqrichtext_p.h @@ -0,0 +1 @@ +../../src/kernel/tqrichtext_p.h \ No newline at end of file diff --git a/include/private/tqscriptengine_p.h b/include/private/tqscriptengine_p.h new file mode 120000 index 000000000..f4a4687fa --- /dev/null +++ b/include/private/tqscriptengine_p.h @@ -0,0 +1 @@ +../../src/kernel/tqscriptengine_p.h \ No newline at end of file diff --git a/include/private/tqsvgdevice_p.h b/include/private/tqsvgdevice_p.h new file mode 120000 index 000000000..a659160f6 --- /dev/null +++ b/include/private/tqsvgdevice_p.h @@ -0,0 +1 @@ +../../src/xml/tqsvgdevice_p.h \ No newline at end of file diff --git a/include/private/tqt_x11_p.h b/include/private/tqt_x11_p.h new file mode 120000 index 000000000..8c6e4c1d4 --- /dev/null +++ b/include/private/tqt_x11_p.h @@ -0,0 +1 @@ +../../src/kernel/tqt_x11_p.h \ No newline at end of file diff --git a/include/private/tqtitlebar_p.h b/include/private/tqtitlebar_p.h new file mode 120000 index 000000000..6fedbb5d5 --- /dev/null +++ b/include/private/tqtitlebar_p.h @@ -0,0 +1 @@ +../../src/widgets/tqtitlebar_p.h \ No newline at end of file diff --git a/include/private/tqucom_p.h b/include/private/tqucom_p.h new file mode 120000 index 000000000..bd307b7a1 --- /dev/null +++ b/include/private/tqucom_p.h @@ -0,0 +1 @@ +../../src/tools/tqucom_p.h \ No newline at end of file diff --git a/include/private/tqucomextra_p.h b/include/private/tqucomextra_p.h new file mode 120000 index 000000000..ba9b4aa05 --- /dev/null +++ b/include/private/tqucomextra_p.h @@ -0,0 +1 @@ +../../src/kernel/tqucomextra_p.h \ No newline at end of file diff --git a/include/private/tqunicodetables_p.h b/include/private/tqunicodetables_p.h new file mode 120000 index 000000000..3ad77b7eb --- /dev/null +++ b/include/private/tqunicodetables_p.h @@ -0,0 +1 @@ +../../src/tools/tqunicodetables_p.h \ No newline at end of file diff --git a/plugins/src/accessible/widgets/tqaccessiblewidget.cpp b/plugins/src/accessible/widgets/tqaccessiblewidget.cpp index 2aedf5468..232ff05f8 100644 --- a/plugins/src/accessible/widgets/tqaccessiblewidget.cpp +++ b/plugins/src/accessible/widgets/tqaccessiblewidget.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include TQString buddyString( TQWidget *widget ) diff --git a/plugins/src/inputmethods/xim/qximinputcontext.h b/plugins/src/inputmethods/xim/qximinputcontext.h index 1471f8315..3cef8dd81 100644 --- a/plugins/src/inputmethods/xim/qximinputcontext.h +++ b/plugins/src/inputmethods/xim/qximinputcontext.h @@ -65,7 +65,7 @@ class TQString; #ifdef TQ_WS_X11 #include "tqmemarray.h" #include "tqwindowdefs.h" -#include +#include #endif class TQXIMInputContext : public TQInputContext diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 880015693..cf47f314b 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -9,7 +9,7 @@ QOBJS=tqstring.o tqtextstream.o tqiodevice.o tqglobal.o tqgdict.o tqcstring.o \ tqdatastream.o tqgarray.o tqbuffer.o tqglist.o tqptrcollection.o tqfile.o \ tqfile_unix.o tqregexp.o tqgvector.o tqgcache.o tqbitarray.o tqdir.o tquuid.o \ tqfileinfo_unix.o tqdir_unix.o tqfileinfo.o tqdatetime.o tqstringlist.o tqmap.o \ - qconfig.o qunicodetables.o tqsettings.o tqlocale.o @QMAKE_QTOBJS@ + qconfig.o tqunicodetables.o tqsettings.o tqlocale.o @QMAKE_QTOBJS@ #all sources, used for the depend target DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp qtmd5.cpp generators/makefile.cpp generators/unix/unixmake2.cpp \ @@ -93,8 +93,8 @@ tqlocale.o: @SOURCE_PATH@/src/tools/tqlocale.cpp tqdatastream.o: @SOURCE_PATH@/src/tools/tqdatastream.cpp $(CXX) -c -o $@ $(CXXFLAGS) @SOURCE_PATH@/src/tools/tqdatastream.cpp -qunicodetables.o: @SOURCE_PATH@/src/tools/qunicodetables.cpp - $(CXX) -c -o $@ $(CXXFLAGS) @SOURCE_PATH@/src/tools/qunicodetables.cpp +tqunicodetables.o: @SOURCE_PATH@/src/tools/tqunicodetables.cpp + $(CXX) -c -o $@ $(CXXFLAGS) @SOURCE_PATH@/src/tools/tqunicodetables.cpp tqgarray.o: @SOURCE_PATH@/src/tools/tqgarray.cpp $(CXX) -c -o $@ $(CXXFLAGS) @SOURCE_PATH@/src/tools/tqgarray.cpp diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index dae71ed8c..cfb7b43d2 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -22,7 +22,7 @@ OBJS=project.o main.o makefile.o unixmake.o unixmake2.o borland_bmake.o mingw_ma QTOBJS=tqstring.o tquuid.o tqtextstream.o tqiodevice.o tqglobal.o tqgdict.o tqcstring.o tqdatastream.o \ tqgarray.o tqbuffer.o tqglist.o tqptrcollection.o tqfile.o tqfile_win.o tqregexp.o tqgvector.o \ tqgcache.o tqbitarray.o tqdir.o tqfileinfo_win.o tqdir_win.o tqfileinfo.o tqdatetime.o \ - tqstringlist.o tqmap.o tqlibrary.o tqlibrary_win.o qconfig.o tqsettings.o tqsettings_win.o qunicodetables.o \ + tqstringlist.o tqmap.o tqlibrary.o tqlibrary_win.o qconfig.o tqsettings.o tqsettings_win.o tqunicodetables.o \ tqlocale.o @@ -139,8 +139,8 @@ tqstringlist.o: ..\src\tools\tqstringlist.cpp tqmap.o: ..\src\tools\tqmap.cpp $(CXX) $(CXXFLAGS) ..\src\tools\tqmap.cpp -qunicodetables.o: ..\src\tools\qunicodetables.cpp - $(CXX) $(CXXFLAGS) ..\src\tools\qunicodetables.cpp +tqunicodetables.o: ..\src\tools\tqunicodetables.cpp + $(CXX) $(CXXFLAGS) ..\src\tools\tqunicodetables.cpp makefile.o: generators\makefile.cpp $(CXX) $(CXXFLAGS) generators\makefile.cpp diff --git a/src/codecs/tqtextcodecfactory.cpp b/src/codecs/tqtextcodecfactory.cpp index 9e081c51c..36782644f 100644 --- a/src/codecs/tqtextcodecfactory.cpp +++ b/src/codecs/tqtextcodecfactory.cpp @@ -45,7 +45,7 @@ #ifndef TQT_NO_COMPONENT #include "ntqapplication.h" #include "tqcleanuphandler.h" -#include +#include #include "tqtextcodecinterface_p.h" #ifdef TQT_THREAD_SUPPORT diff --git a/src/codecs/tqtextcodecinterface_p.h b/src/codecs/tqtextcodecinterface_p.h index 541889e2d..714c1567d 100644 --- a/src/codecs/tqtextcodecinterface_p.h +++ b/src/codecs/tqtextcodecinterface_p.h @@ -44,7 +44,7 @@ // ------------- // // This file is not part of the TQt API. It exists for the convenience -// of qpsprinter.cpp and tqprinter_x11.cpp. +// of tqpsprinter.cpp and tqprinter_x11.cpp. // This header file may change from version to version without notice, // or even be removed. // @@ -53,7 +53,7 @@ // #ifndef QT_H -#include +#include #endif // QT_H #ifndef TQT_NO_TEXTCODEC diff --git a/src/dialogs/tqdialog.cpp b/src/dialogs/tqdialog.cpp index 42853e00a..919a1ed38 100644 --- a/src/dialogs/tqdialog.cpp +++ b/src/dialogs/tqdialog.cpp @@ -673,7 +673,7 @@ bool TQDialog::event( TQEvent *e ) #if defined(TQ_WS_X11) extern "C" { int XSetTransientForHint( Display *, unsigned long, unsigned long ); } -#include +#include #undef FocusIn // defined in qapplication_x11.cpp extern Atom qt_net_wm_full_placement; diff --git a/src/inputmethod/tqinputcontextfactory.cpp b/src/inputmethod/tqinputcontextfactory.cpp index 95fc40766..e6f1fb3af 100644 --- a/src/inputmethod/tqinputcontextfactory.cpp +++ b/src/inputmethod/tqinputcontextfactory.cpp @@ -50,7 +50,7 @@ #include #include "tqcleanuphandler.h" -#include +#include #ifndef TQT_NO_COMPONENT diff --git a/src/inputmethod/tqinputcontextinterface_p.h b/src/inputmethod/tqinputcontextinterface_p.h index 195be7fe9..e21a016da 100644 --- a/src/inputmethod/tqinputcontextinterface_p.h +++ b/src/inputmethod/tqinputcontextinterface_p.h @@ -49,7 +49,7 @@ // #ifndef QT_H -#include +#include #endif // QT_H #ifndef TQT_NO_IM diff --git a/src/kernel/makepsheader.pl b/src/kernel/makepsheader.pl index b842e1465..4452b8404 100755 --- a/src/kernel/makepsheader.pl +++ b/src/kernel/makepsheader.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl -open(INPUT, 'qpsprinter.ps') - or die "Can't open qpsprinter.ps"; +open(INPUT, 'tqpsprinter.ps') + or die "Can't open tqpsprinter.ps"; $dontcompress = 1; while() { diff --git a/src/kernel/qapplication_x11.cpp b/src/kernel/qapplication_x11.cpp index c1d8345b1..ec94e78b5 100644 --- a/src/kernel/qapplication_x11.cpp +++ b/src/kernel/qapplication_x11.cpp @@ -92,7 +92,7 @@ #ifndef TQT_NO_IM #include "tqinputcontext.h" #endif // TQT_NO_IM -#include "qinternal_p.h" // shared double buffer cleanup +#include "tqinternal_p.h" // shared double buffer cleanup #if defined(TQT_THREAD_SUPPORT) # include "tqthread.h" @@ -102,7 +102,7 @@ # include "tqfile.h" #endif -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #if !defined(TQT_NO_XFTFREETYPE) // XFree86 4.0.3 implementation is missing XftInitFtLibrary forward @@ -849,7 +849,7 @@ void qt_x11_intern_atom( const char *name, Atom *result) } -static void qt_x11_process_intern_atoms() +static void tqt_x11_process_intern_atoms() { if ( atoms_to_be_created ) { #if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6) @@ -2084,7 +2084,7 @@ void tqt_init_internal( int *argcptr, char **argv, qt_x11_motifdnd_init(); // Finally create all atoms - qt_x11_process_intern_atoms(); + tqt_x11_process_intern_atoms(); // look for broken window managers qt_detect_broken_window_manager(); diff --git a/src/kernel/qdnd_x11.cpp b/src/kernel/qdnd_x11.cpp index 4d4dad5f5..571045f48 100644 --- a/src/kernel/qdnd_x11.cpp +++ b/src/kernel/qdnd_x11.cpp @@ -55,7 +55,7 @@ #include "tqbitmap.h" #include "tqpainter.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" // conflict resolution diff --git a/src/kernel/qinternal.cpp b/src/kernel/qinternal.cpp deleted file mode 100644 index 96297bb8d..000000000 --- a/src/kernel/qinternal.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/**************************************************************************** -** -** Implementation of some internal classes -** -** Created : 010427 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "private/qinternal_p.h" -#include "tqwidget.h" -#include "tqpixmap.h" -#include "tqpainter.h" -#include "tqcleanuphandler.h" - -// Modern systems (year 2011) have very large screens in excess of 1000 pixels wide -// Some may even have screens in excess of 4000 pixels wide(!) -// Prevent drawing artifacts on such screens -#define USE_HUGE_QT_SHARED_DOUBLE_BUFFERS 1 - -static TQPixmap* qdb_shared_pixmap = 0; -static TQPixmap *qdb_force_pixmap = 0; -static TQSharedDoubleBuffer* qdb_owner = 0; - -TQCleanupHandler qdb_pixmap_cleanup; - -#ifdef TQ_WS_MACX -bool TQSharedDoubleBuffer::dblbufr = FALSE; -#else -bool TQSharedDoubleBuffer::dblbufr = TRUE; -#endif - - -/* - hardLimitWidth/Height: if >= 0, the maximum number of pixels that - get double buffered. - - sharedLimitWidth/Height: if >= 0, the maximum number of pixels the - shared double buffer can keep. - - For x with sharedLimitSize < x <= hardLimitSize, temporary buffers - are constructed. - */ -static const int hardLimitWidth = -1; -static const int hardLimitHeight = -1; -#if defined( TQ_WS_MAC9 ) -// Small in Mac9 - 5K on 32bpp -static const int sharedLimitWidth = 64; -static const int sharedLimitHeight = 20; -#else -#ifdef USE_HUGE_QT_SHARED_DOUBLE_BUFFERS -// 24M on 32bpp -static const int sharedLimitWidth = 6400; -static const int sharedLimitHeight = 1000; -#else -// 240K on 32bpp -static const int sharedLimitWidth = 640; -static const int sharedLimitHeight = 100; -#endif -#endif - -// ******************************************************************* -// TQSharedDoubleBufferCleaner declaration and implementation -// ******************************************************************* - -/* \internal - This class is responsible for cleaning up the pixmaps created by the - TQSharedDoubleBuffer class. When TQSharedDoubleBuffer creates a - pixmap larger than the shared limits, this class deletes it after a - specified amount of time. - - When the large pixmap is created/used, you must call start(). If the - large pixmap is ever deleted, you must call stop(). The start() - method always restarts the timer, so if the large pixmap is - constantly in use, the timer will never fire, and the pixmap will - not be constantly created and destroyed. -*/ - -static const int shared_double_buffer_cleanup_timeout = 30000; // 30 seconds - -// declaration - -class TQSharedDoubleBufferCleaner : public TQObject -{ -public: - TQSharedDoubleBufferCleaner( void ); - - void start( void ); - void stop( void ); - - void doCleanup( void ); - - bool event( TQEvent *e ); - -private: - int timer_id; -}; - -// implementation - -/* \internal - Creates a TQSharedDoubleBufferCleaner object. The timer is not - started when creating the object. -*/ -TQSharedDoubleBufferCleaner::TQSharedDoubleBufferCleaner( void ) - : TQObject( 0, "internal shared double buffer cleanup object" ), - timer_id( -1 ) -{ -} - -/* \internal - Starts the cleanup timer. Any previously running timer is stopped. -*/ -void TQSharedDoubleBufferCleaner::start( void ) -{ - stop(); - timer_id = startTimer( shared_double_buffer_cleanup_timeout ); -} - -/* \internal - Stops the cleanup timer, if it is running. -*/ -void TQSharedDoubleBufferCleaner::stop( void ) -{ - if ( timer_id != -1 ) - killTimer( timer_id ); - timer_id = -1; -} - -/* \internal - */ -void TQSharedDoubleBufferCleaner::doCleanup( void ) -{ - qdb_pixmap_cleanup.remove( &qdb_force_pixmap ); - delete qdb_force_pixmap; - qdb_force_pixmap = 0; -} - -/* \internal - Event handler reimplementation. Calls doCleanup() when the timer - fires. -*/ -bool TQSharedDoubleBufferCleaner::event( TQEvent *e ) -{ - if ( e->type() != TQEvent::Timer ) - return FALSE; - - TQTimerEvent *event = (TQTimerEvent *) e; - if ( event->timerId() == timer_id ) { - doCleanup(); - stop(); - } -#ifdef QT_CHECK_STATE - else { - tqWarning( "TQSharedDoubleBufferCleaner::event: invalid timer event received." ); - return FALSE; - } -#endif // QT_CHECK_STATE - - return TRUE; -} - -// static instance -static TQSharedDoubleBufferCleaner *static_cleaner = 0; -TQSingleCleanupHandler cleanup_static_cleaner; - -inline static TQSharedDoubleBufferCleaner *staticCleaner() -{ - if ( ! static_cleaner ) { - static_cleaner = new TQSharedDoubleBufferCleaner(); - cleanup_static_cleaner.set( &static_cleaner ); - } - return static_cleaner; -} - - -// ******************************************************************* -// TQSharedDoubleBuffer implementation -// ******************************************************************* - -/* \internal - \enum DoubleBufferFlags - - \value InitBG initialize the background of the double buffer. - - \value Force disable shared buffer size limits. - - \value Default InitBG and Force are used by default. -*/ - -/* \internal - \enum DoubleBufferState - - \value Active indicates that the buffer may be used. - - \value BufferActive indicates that painting with painter() will be - double buffered. - - \value ExternalPainter indicates that painter() will return a - painter that was not created by TQSharedDoubleBuffer. -*/ - -/* \internal - \class TQSharedDoubleBuffer - - This class provides a single, reusable double buffer. This class - is used internally by TQt widgets that need double buffering, which - prevents each individual widget form creating a double buffering - pixmap. - - Using a single pixmap double buffer and sharing it across all - widgets is nicer on window system resources. -*/ - -/* \internal - Creates a TQSharedDoubleBuffer with flags \f. - - \sa DoubleBufferFlags -*/ -TQSharedDoubleBuffer::TQSharedDoubleBuffer( DBFlags f ) - : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), - p( 0 ), external_p( 0 ), pix( 0 ) -{ -} - -/* \internal - Creates a TQSharedDoubleBuffer with flags \f. The \a widget, \a x, - \a y, \a w and \a h arguments are passed to begin(). - - \sa DoubleBufferFlags begin() -*/ -TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQWidget* widget, - int x, int y, int w, int h, - DBFlags f ) - : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), - p( 0 ), external_p( 0 ), pix( 0 ) -{ - begin( widget, x, y, w, h ); -} - -/* \internal - Creates a TQSharedDoubleBuffer with flags \f. The \a painter, \a x, - \a y, \a w and \a h arguments are passed to begin(). - - \sa DoubleBufferFlags begin() -*/ -TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQPainter* painter, - int x, int y, int w, int h, - DBFlags f) - : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), - p( 0 ), external_p( 0 ), pix( 0 ) -{ - begin( painter, x, y, w, h ); -} - -/* \internal - Creates a TQSharedDoubleBuffer with flags \f. The \a widget and - \a r arguments are passed to begin(). - - \sa DoubleBufferFlags begin() -*/ -TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQWidget *widget, const TQRect &r, DBFlags f ) - : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), - p( 0 ), external_p( 0 ), pix( 0 ) -{ - begin( widget, r ); -} - -/* \internal - Creates a TQSharedDoubleBuffer with flags \f. The \a painter and - \a r arguments are passed to begin(). - - \sa DoubleBufferFlags begin() -*/ -TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQPainter *painter, const TQRect &r, DBFlags f ) - : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), - p( 0 ), external_p( 0 ), pix( 0 ) -{ - begin( painter, r ); -} - -/* \internal - Destructs the TQSharedDoubleBuffer and calls end() if the buffer is - active. - - \sa isActive() end() -*/ -TQSharedDoubleBuffer::~TQSharedDoubleBuffer() -{ - if ( isActive() ) - end(); -} - -/* \internal - Starts double buffered painting in the area specified by \a x, - \a y, \a w and \a h on \a painter. Painting should be done using the - TQPainter returned by TQSharedDoubleBuffer::painter(). - - The double buffered area will be updated when calling end(). - - \sa painter() isActive() end() -*/ -bool TQSharedDoubleBuffer::begin( TQPainter* painter, int x, int y, int w, int h ) -{ - if ( isActive() ) { -#if defined(QT_CHECK_STATE) - tqWarning( "TQSharedDoubleBuffer::begin: Buffer is already active." - "\n\tYou must end() the buffer before a second begin()" ); -#endif // QT_CHECK_STATE - return FALSE; - } - - external_p = painter; - - if ( painter->device()->devType() == TQInternal::Widget ) - return begin( (TQWidget *) painter->device(), x, y, w, h ); - - state = Active; - - rx = x; - ry = y; - rw = w; - rh = h; - - if ( ( pix = getPixmap() ) ) { -#ifdef TQ_WS_X11 - if ( painter->device()->x11Screen() != pix->x11Screen() ) - pix->x11SetScreen( painter->device()->x11Screen() ); - TQPixmap::x11SetDefaultScreen( pix->x11Screen() ); -#endif // TQ_WS_X11 - - state |= BufferActive; - p = new TQPainter( pix ); - if ( p->isActive() ) { - p->setPen( external_p->pen() ); - p->setBackgroundColor( external_p->backgroundColor() ); - p->setFont( external_p->font() ); - } - } else { - state |= ExternalPainter; - p = external_p; - } - - return TRUE; -} - -/* \internal - - - Starts double buffered painting in the area specified by \a x, - \a y, \a w and \a h on \a widget. Painting should be done using the - TQPainter returned by TQSharedDoubleBuffer::painter(). - - The double buffered area will be updated when calling end(). - - \sa painter() isActive() end() -*/ -bool TQSharedDoubleBuffer::begin( TQWidget* widget, int x, int y, int w, int h ) -{ - if ( isActive() ) { -#if defined(QT_CHECK_STATE) - tqWarning( "TQSharedDoubleBuffer::begin: Buffer is already active." - "\n\tYou must end() the buffer before a second begin()" ); -#endif // QT_CHECK_STATE - return FALSE; - } - - state = Active; - - wid = widget; - rx = x; - ry = y; - rw = w <= 0 ? wid->width() : w; - rh = h <= 0 ? wid->height() : h; - - if ( ( pix = getPixmap() ) ) { -#ifdef TQ_WS_X11 - if ( wid->x11Screen() != pix->x11Screen() ) - pix->x11SetScreen( wid->x11Screen() ); - TQPixmap::x11SetDefaultScreen( pix->x11Screen() ); -#endif // TQ_WS_X11 - - state |= BufferActive; - if ( flags & InitBG ) { - pix->fill( wid, rx, ry ); - } - p = new TQPainter( pix, wid ); - // newly created painters should be translated to the origin - // of the widget, so that paint methods can draw onto the double - // buffered painter in widget coordinates. - p->setBrushOrigin( -rx, -ry ); - p->translate( -rx, -ry ); - } else { - if ( external_p ) { - state |= ExternalPainter; - p = external_p; - } else { - p = new TQPainter( wid ); - } - - if ( flags & InitBG ) { - wid->erase( rx, ry, rw, rh ); - } - } - return TRUE; -} - -/* \internal - Ends double buffered painting. The contents of the shared double - buffer pixmap are drawn onto the destination by calling flush(), - and ownership of the shared double buffer pixmap is released. - - \sa begin() flush() -*/ -bool TQSharedDoubleBuffer::end() -{ - if ( ! isActive() ) { -#if defined(QT_CHECK_STATE) - tqWarning( "TQSharedDoubleBuffer::end: Buffer is not active." - "\n\tYou must call begin() before calling end()." ); -#endif // QT_CHECK_STATE - return FALSE; - } - - if ( ! ( state & ExternalPainter ) ) { - p->end(); - delete p; - } - - flush(); - - if ( pix ) { - releasePixmap(); - } - - wid = 0; - rx = ry = rw = rh = 0; - // do not reset flags! - state = 0; - - p = external_p = 0; - pix = 0; - - return TRUE; -} - -/* \internal - Paints the contents of the shared double buffer pixmap onto the - destination. The destination is determined from the arguments - based to begin(). - - Note: You should not need to call this function, since it is called - from end(). - - \sa begin() end() -*/ -void TQSharedDoubleBuffer::flush() -{ - if ( ! isActive() || ! ( state & BufferActive ) ) - return; - - if ( external_p ) - external_p->drawPixmap( rx, ry, *pix, 0, 0, rw, rh ); - else if ( wid && wid->isVisible() ) - bitBlt( wid, rx, ry, pix, 0, 0, rw, rh ); -} - -/* \internal - Acquire ownership of the shared double buffer pixmap, subject to the - following conditions: - - \list 1 - \i double buffering is enabled globally. - \i the shared double buffer pixmap is not in use. - \i the size specified in begin() is valid, and within limits. - \endlist - - If all of these conditions are met, then this TQSharedDoubleBuffer - object becomes the owner of the shared double buffer pixmap. The - shared double buffer pixmap is resize if necessary, and this - function returns a pointer to the pixmap. Ownership must later be - relinquished by calling releasePixmap(). - - If none of the above conditions are met, this function returns - zero. - - \sa releasePixmap() -*/ -TQPixmap *TQSharedDoubleBuffer::getPixmap() -{ - if ( isDisabled() ) { - // double buffering disabled globally - return 0; - } - - if ( qdb_owner ) { - // shared pixmap already in use - return 0; - } - - if ( rw <= 0 || rh <= 0 || - ( hardLimitWidth > 0 && rw >= hardLimitWidth ) || - ( hardLimitHeight > 0 && rh >= hardLimitHeight ) ) { - // invalid size, or hard limit reached - return 0; - } - - if ( rw >= sharedLimitWidth || rh >= sharedLimitHeight ) { - if ( flags & Force ) { -#ifdef USE_HUGE_QT_SHARED_DOUBLE_BUFFERS - rw = TQMIN(rw, 16000); - rh = TQMIN(rh, 16000); -#else - rw = TQMIN(rw, 8000); - rh = TQMIN(rh, 8000); -#endif - // need to create a big pixmap and start the cleaner - if ( ! qdb_force_pixmap ) { - qdb_force_pixmap = new TQPixmap( rw, rh ); - qdb_pixmap_cleanup.add( &qdb_force_pixmap ); - } else if ( qdb_force_pixmap->width () < rw || - qdb_force_pixmap->height() < rh ) { - qdb_force_pixmap->resize( rw, rh ); - } - qdb_owner = this; - staticCleaner()->start(); - return qdb_force_pixmap; - } - - // size is outside shared limit - return 0; - } - - if ( ! qdb_shared_pixmap ) { - qdb_shared_pixmap = new TQPixmap( rw, rh ); - qdb_pixmap_cleanup.add( &qdb_shared_pixmap ); - } else if ( qdb_shared_pixmap->width() < rw || - qdb_shared_pixmap->height() < rh ) { - qdb_shared_pixmap->resize( rw, rh ); - } - qdb_owner = this; - return qdb_shared_pixmap; -} - -/* \internal - Releases ownership of the shared double buffer pixmap. - - \sa getPixmap() -*/ -void TQSharedDoubleBuffer::releasePixmap() -{ - if ( qdb_owner != this ) { - // sanity check - -#ifdef QT_CHECK_STATE - tqWarning( "TQSharedDoubleBuffer::releasePixmap: internal error." - "\n\t%p does not own shared pixmap, %p does.", - (void*)this, (void*)qdb_owner ); -#endif // QT_CHECK_STATE - - return; - } - - qdb_owner = 0; -} - -/* \internal - \fn bool TQSharedDoubleBuffer::isDisabled() - - Returns TRUE if double buffering is disabled globally, FALSE otherwise. -*/ - -/* \internal - \fn void TQSharedDoubleBuffer::setDisabled( bool off ) - - Disables global double buffering \a off is TRUE, otherwise global - double buffering is enabled. -*/ - -/* \internal - Deletes the shared double buffer pixmap. You should not need to - call this function, since it is called from the TQApplication - destructor. -*/ -void TQSharedDoubleBuffer::cleanup() -{ - qdb_pixmap_cleanup.remove( &qdb_shared_pixmap ); - qdb_pixmap_cleanup.remove( &qdb_force_pixmap ); - delete qdb_shared_pixmap; - delete qdb_force_pixmap; - qdb_shared_pixmap = 0; - qdb_force_pixmap = 0; - qdb_owner = 0; -} - -/* \internal - \fn bool TQSharedDoubleBuffer::begin( TQWidget *widget, const TQRect &r ) - \overload -*/ - -/* \internal - \fn bool TQSharedDoubleBuffer::begin( TQPainter *painter, const TQRect &r ) - \overload -*/ - -/* \internal - \fn TQPainter *TQSharedDoubleBuffer::painter() const - - Returns the active painter on the double buffered area, - or zero if double buffered painting is not active. -*/ - -/* \internal - \fn bool TQSharedDoubleBuffer::isActive() const - - Returns TRUE if double buffered painting is active, FALSE otherwise. -*/ - -/* \internal - \fn bool TQSharedDoubleBuffer::isBuffered() const - - Returns TRUE if painting is double buffered, FALSE otherwise. -*/ - - -// ******************************************************************* -// TQMembuf declaration and implementation -// ******************************************************************* - -/* \internal - This class implements an efficient buffering of data that is often used by - asynchronous IO classes like TQSocket, TQHttp and TQProcess. -*/ - -TQMembuf::TQMembuf() : _size(0), _index(0) -{ - buf = new TQPtrList; - buf->setAutoDelete( TRUE ); -} - -TQMembuf::~TQMembuf() -{ - delete buf; -} - -/*! \internal - This function consumes \a nbytes bytes of data from the - buffer and copies it into \a sink. If \a sink is a 0 pointer - the data goes into the nirvana. -*/ -bool TQMembuf::consumeBytes( TQ_ULONG nbytes, char *sink ) -{ - if ( nbytes <= 0 || nbytes > _size ) - return FALSE; - _size -= nbytes; - for ( ;; ) { - TQByteArray *a = buf->first(); - if ( _index + nbytes >= a->size() ) { - // Here we skip the whole byte array and get the next later - int len = a->size() - _index; - if ( sink ) { - memcpy( sink, a->data()+_index, len ); - sink += len; - } - nbytes -= len; - buf->remove(); - _index = 0; - if ( nbytes == 0 ) - break; - } else { - // Here we skip only a part of the first byte array - if ( sink ) - memcpy( sink, a->data()+_index, nbytes ); - _index += nbytes; - break; - } - } - return TRUE; -} - -/*! \internal - Scans for any occurrence of '\n' in the buffer. If \a store - is not 0 the text up to the first '\n' (or terminating 0) is - written to \a store, and a terminating 0 is appended to \a store - if necessary. Returns TRUE if a '\n' was found; otherwise returns - FALSE. -*/ -bool TQMembuf::scanNewline( TQByteArray *store ) -{ - if ( _size == 0 ) - return FALSE; - int i = 0; // index into 'store' - TQByteArray *a = 0; - char *p; - int n; - for ( ;; ) { - if ( !a ) { - a = buf->first(); - if ( !a || a->size() == 0 ) - return FALSE; - p = a->data() + _index; - n = a->size() - _index; - } else { - a = buf->next(); - if ( !a || a->size() == 0 ) - return FALSE; - p = a->data(); - n = a->size(); - } - if ( store ) { - while ( n-- > 0 ) { - *(store->data()+i) = *p; - if ( ++i == (int)store->size() ) - store->resize( store->size() < 256 - ? 1024 : store->size()*4 ); - switch ( *p ) { - case '\0': - store->resize( i ); - return FALSE; - case '\n': - *(store->data()+i) = '\0'; - store->resize( i ); - return TRUE; - } - p++; - } - } else { - while ( n-- > 0 ) { - switch ( *p++ ) { - case '\0': - return FALSE; - case '\n': - return TRUE; - } - } - } - } -} - -int TQMembuf::ungetch( int ch ) -{ - if ( buf->isEmpty() || _index==0 ) { - // we need a new TQByteArray - TQByteArray *ba = new TQByteArray( 1 ); - buf->insert( 0, ba ); - _size++; - ba->at( 0 ) = ch; - } else { - // we can reuse a place in the buffer - TQByteArray *ba = buf->first(); - _index--; - _size++; - ba->at( _index ) = ch; - } - return ch; -} diff --git a/src/kernel/qinternal_p.h b/src/kernel/qinternal_p.h deleted file mode 100644 index d8c29cc67..000000000 --- a/src/kernel/qinternal_p.h +++ /dev/null @@ -1,213 +0,0 @@ -/**************************************************************************** -** -** Definition of some shared interal classes -** -** Created : 010427 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQINTERNAL_P_H -#define TQINTERNAL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of a number of TQt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// -#ifndef QT_H -#include "tqnamespace.h" -#include "tqrect.h" -#include "tqptrlist.h" -#include "tqcstring.h" -#include "tqiodevice.h" -#endif // QT_H - -class TQWidget; -class TQPainter; -class TQPixmap; - -class TQ_EXPORT TQSharedDoubleBuffer -{ -public: - enum DoubleBufferFlags { - NoFlags = 0x00, - InitBG = 0x01, - Force = 0x02, - Default = InitBG | Force - }; - typedef uint DBFlags; - - TQSharedDoubleBuffer( DBFlags f = Default ); - TQSharedDoubleBuffer( TQWidget* widget, - int x = 0, int y = 0, int w = -1, int h = -1, - DBFlags f = Default ); - TQSharedDoubleBuffer( TQPainter* painter, - int x = 0, int y = 0, int w = -1, int h = -1, - DBFlags f = Default ); - TQSharedDoubleBuffer( TQWidget *widget, const TQRect &r, DBFlags f = Default ); - TQSharedDoubleBuffer( TQPainter *painter, const TQRect &r, DBFlags f = Default ); - ~TQSharedDoubleBuffer(); - - bool begin( TQWidget* widget, int x = 0, int y = 0, int w = -1, int h = -1 ); - bool begin( TQPainter* painter, int x = 0, int y = 0, int w = -1, int h = -1); - bool begin( TQWidget* widget, const TQRect &r ); - bool begin( TQPainter* painter, const TQRect &r ); - bool end(); - - TQPainter* painter() const; - - bool isActive() const; - bool isBuffered() const; - void flush(); - - static bool isDisabled() { return !dblbufr; } - static void setDisabled( bool off ) { dblbufr = !off; } - - static void cleanup(); - -private: - enum DoubleBufferState { - Active = 0x0100, - BufferActive = 0x0200, - ExternalPainter = 0x0400 - }; - typedef uint DBState; - - TQPixmap *getPixmap(); - void releasePixmap(); - - TQWidget *wid; - int rx, ry, rw, rh; - DBFlags flags; - DBState state; - - TQPainter *p, *external_p; - TQPixmap *pix; - - static bool dblbufr; -}; - -inline bool TQSharedDoubleBuffer::begin( TQWidget* widget, const TQRect &r ) -{ return begin( widget, r.x(), r.y(), r.width(), r.height() ); } - -inline bool TQSharedDoubleBuffer::begin( TQPainter *painter, const TQRect &r ) -{ return begin( painter, r.x(), r.y(), r.width(), r.height() ); } - -inline TQPainter* TQSharedDoubleBuffer::painter() const -{ return p; } - -inline bool TQSharedDoubleBuffer::isActive() const -{ return ( state & Active ); } - -inline bool TQSharedDoubleBuffer::isBuffered() const -{ return ( state & BufferActive ); } - - -class TQVirtualDestructor { -public: - virtual ~TQVirtualDestructor() {} -}; - -template -class TQAutoDeleter : public TQVirtualDestructor { -public: - TQAutoDeleter( T* p ) : ptr( p ) {} - ~TQAutoDeleter() { delete ptr; } - T* data() const { return ptr; } -private: - T* ptr; -}; - -template -T* qAutoDeleterData( TQAutoDeleter* ad ) -{ - if ( !ad ) - return 0; - return ad->data(); -} - -template -TQAutoDeleter* qAutoDeleter( T* p ) -{ - return new TQAutoDeleter( p ); -} - -class TQ_EXPORT TQMembuf -{ -public: - TQMembuf(); - ~TQMembuf(); - - void append( TQByteArray *ba ); - void clear(); - - bool consumeBytes( TQ_ULONG nbytes, char *sink ); - TQByteArray readAll(); - bool scanNewline( TQByteArray *store ); - bool canReadLine() const; - - int ungetch( int ch ); - - TQIODevice::Offset size() const; - -private: - - TQPtrList *buf; - TQIODevice::Offset _size; - TQIODevice::Offset _index; -}; - -inline void TQMembuf::append( TQByteArray *ba ) -{ buf->append( ba ); _size += ba->size(); } - -inline void TQMembuf::clear() -{ buf->clear(); _size=0; _index=0; } - -inline TQByteArray TQMembuf::readAll() -{ TQByteArray ba(_size); consumeBytes(_size,ba.data()); return ba; } - -inline bool TQMembuf::canReadLine() const -{ return ((TQMembuf*)this)->scanNewline( 0 ); } - -inline TQIODevice::Offset TQMembuf::size() const -{ return _size; } - -#endif // TQINTERNAL_P_H diff --git a/src/kernel/qpsprinter.cpp b/src/kernel/qpsprinter.cpp deleted file mode 100644 index 3d18d6008..000000000 --- a/src/kernel/qpsprinter.cpp +++ /dev/null @@ -1,6574 +0,0 @@ -/********************************************************************** -** -** Implementation of TQPSPrinter class -** -** Created : 941003 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qplatformdefs.h" - -// POSIX Large File Support redefines open -> open64 -#if defined(open) -# undef open -#endif - -// POSIX Large File Support redefines truncate -> truncate64 -#if defined(truncate) -# undef truncate -#endif - -#include "qpsprinter_p.h" - -#ifndef TQT_NO_PRINTER - -#undef Q_PRINTER_USE_TYPE42 - -#include "tqpainter.h" -#include "ntqapplication.h" -#include "tqpaintdevicemetrics.h" -#include "tqimage.h" -#include "tqdatetime.h" -#include "tqstring.h" -#include "tqdict.h" -#include "tqmemarray.h" -#include "tqfile.h" -#include "tqbuffer.h" -#include "tqintdict.h" -#include "tqtextcodec.h" -#include "tqsettings.h" -#include "tqmap.h" -#include "tqfontdatabase.h" -#include "tqregexp.h" -#include "tqbitmap.h" -#include - -#if defined(Q_OS_WIN32) -#include -#ifdef Q_PRINTER_USE_TYPE42 -#include -#endif -#else -#include -#include -#endif - -#ifdef TQ_WS_X11 -#include "qt_x11_p.h" -#ifdef None -#undef None -#endif -#ifdef GrayScale -#undef GrayScale -#endif -#endif - -#if defined( TQ_WS_X11 ) -#include "tqfontdata_p.h" -#include "tqfontengine_p.h" -#include "tqtextlayout_p.h" -#include "tqtextengine_p.h" -extern bool tqt_has_xft; -#endif - -static bool qt_gen_epsf = FALSE; -static bool embedFonts = TRUE; - -TQ_EXPORT void tqt_generate_epsf( bool b ) -{ - qt_gen_epsf = b; -} - -static const char *const ps_header = -"/d/def load def/D{bind d}bind d/d2{dup dup}D/B{0 d2}D/W{255 d2}D/ED{exch d}D\n" -"/D0{0 ED}D/LT{lineto}D/MT{moveto}D/S{stroke}D/F{setfont}D/SW{setlinewidth}D\n" -"/CP{closepath}D/RL{rlineto}D/NP{newpath}D/CM{currentmatrix}D/SM{setmatrix}D\n" -"/TR{translate}D/SD{setdash}D/SC{aload pop setrgbcolor}D/CR{currentfile read\n" -"pop}D/i{index}D/bs{bitshift}D/scs{setcolorspace}D/DB{dict dup begin}D/DE{end\n" -"d}D/ie{ifelse}D/sp{astore pop}D/BSt 0 d/LWi 1 d/PSt 1 d/Cx 0 d/Cy 0 d/WFi\n" -"false d/OMo false d/BCol[1 1 1]d/PCol[0 0 0]d/BkCol[1 1 1]d/BDArr[0.94 0.88\n" -"0.63 0.50 0.37 0.12 0.06]d/defM matrix d/nS 0 d/GPS{PSt 1 ge PSt 5 le and{{\n" -"LArr PSt 1 sub 2 mul get}{LArr PSt 2 mul 1 sub get}ie}{[]}ie}D/QS{PSt 0 ne{\n" -"gsave LWi SW true GPS 0 SD S OMo PSt 1 ne and{BkCol SC false GPS dup 0 get\n" -"SD S}if grestore}if}D/r28{{CR dup 32 gt{exit}if pop}loop 3{CR}repeat 0 4{7\n" -"bs exch dup 128 gt{84 sub}if 42 sub 127 and add}repeat}D/rA 0 d/rL 0 d/rB{rL\n" -"0 eq{/rA r28 d/rL 28 d}if dup rL gt{rA exch rL sub rL exch/rA 0 d/rL 0 d rB\n" -"exch bs add}{dup rA 16#fffffff 3 -1 roll bs not and exch dup rL exch sub/rL\n" -"ED neg rA exch bs/rA ED}ie}D/uc{/rL 0 d 0{dup 2 i length ge{exit}if 1 rB 1\n" -"eq{3 rB dup 3 ge{1 add dup rB 1 i 5 ge{1 i 6 ge{1 i 7 ge{1 i 8 ge{128 add}if\n" -"64 add}if 32 add}if 16 add}if 3 add exch pop}if 3 add exch 10 rB 1 add{dup 3\n" -"i lt{dup}{2 i}ie 4 i 3 i 3 i sub 2 i getinterval 5 i 4 i 3 -1 roll\n" -"putinterval dup 4 -1 roll add 3 1 roll 4 -1 roll exch sub dup 0 eq{exit}if 3\n" -"1 roll}loop pop pop}{3 rB 1 add{2 copy 8 rB put 1 add}repeat}ie}loop pop}D\n" -"/sl D0/TQCIgray D0/TQCIcolor D0/TQCIindex D0/TQCI{/colorimage where{pop false 3\n" -"colorimage}{exec/TQCIcolor ED/TQCIgray TQCIcolor length 3 idiv string d 0 1\n" -"TQCIcolor length 3 idiv 1 sub{/TQCIindex ED/x TQCIindex 3 mul d TQCIgray\n" -"TQCIindex TQCIcolor x get 0.30 mul TQCIcolor x 1 add get 0.59 mul TQCIcolor x 2\n" -"add get 0.11 mul add add cvi put}for TQCIgray image}ie}D/di{gsave TR 1 i 1 eq\n" -"{false eq{pop true 3 1 roll 4 i 4 i false 4 i 4 i imagemask BkCol SC\n" -"imagemask}{pop false 3 1 roll imagemask}ie}{dup false ne{/languagelevel\n" -"where{pop languagelevel 3 ge}{false}ie}{false}ie{/ma ED 8 eq{/dc[0 1]d\n" -"/DeviceGray}{/dc[0 1 0 1 0 1]d/DeviceRGB}ie scs/im ED/mt ED/h ED/w ED/id 7\n" -"DB/ImageType 1 d/Width w d/Height h d/ImageMatrix mt d/DataSource im d\n" -"/BitsPerComponent 8 d/Decode dc d DE/md 7 DB/ImageType 1 d/Width w d/Height\n" -"h d/ImageMatrix mt d/DataSource ma d/BitsPerComponent 1 d/Decode[0 1]d DE 4\n" -"DB/ImageType 3 d/DataDict id d/MaskDict md d/InterleaveType 3 d end image}{\n" -"pop 8 4 1 roll 8 eq{image}{TQCI}ie}ie}ie grestore}d/BF{gsave BSt 1 eq{BCol SC\n" -"WFi{fill}{eofill}ie}if BSt 2 ge BSt 8 le and{BDArr BSt 2 sub get/sc ED BCol{\n" -"1. exch sub sc mul 1. exch sub}forall 3 array astore SC WFi{fill}{eofill}ie}\n" -"if BSt 9 ge BSt 14 le and{WFi{clip}{eoclip}ie defM SM pathbbox 3 i 3 i TR 4\n" -"2 roll 3 2 roll exch sub/h ED sub/w ED OMo{NP 0 0 MT 0 h RL w 0 RL 0 h neg\n" -"RL CP BkCol SC fill}if BCol SC 0.3 SW NP BSt 9 eq BSt 11 eq or{0 4 h{dup 0\n" -"exch MT w exch LT}for}if BSt 10 eq BSt 11 eq or{0 4 w{dup 0 MT h LT}for}if\n" -"BSt 12 eq BSt 14 eq or{w h gt{0 6 w h add{dup 0 MT h sub h LT}for}{0 6 w h\n" -"add{dup 0 exch MT w sub w exch LT}for}ie}if BSt 13 eq BSt 14 eq or{w h gt{0\n" -"6 w h add{dup h MT h sub 0 LT}for}{0 6 w h add{dup w exch MT w sub 0 exch LT\n" -"}for}ie}if S}if BSt 24 eq{}if grestore}D/mat matrix d/ang1 D0/ang2 D0/w D0/h\n" -"D0/x D0/y D0/ARC{/ang2 ED/ang1 ED/h ED/w ED/y ED/x ED mat CM pop x w 2 div\n" -"add y h 2 div add TR 1 h w div neg scale ang2 0 ge{0 0 w 2 div ang1 ang1\n" -"ang2 add arc}{0 0 w 2 div ang1 ang1 ang2 add arcn}ie mat SM}D/C D0/P{NP MT\n" -"0.5 0.5 rmoveto 0 -1 RL -1 0 RL 0 1 RL CP fill}D/M{/Cy ED/Cx ED}D/L{NP Cx Cy\n" -"MT/Cy ED/Cx ED Cx Cy LT QS}D/DL{NP MT LT QS}D/HL{1 i DL}D/VL{2 i exch DL}D/R\n" -"{/h ED/w ED/y ED/x ED NP x y MT 0 h RL w 0 RL 0 h neg RL CP BF QS}D/ACR{/h\n" -"ED/w ED/y ED/x ED x y MT 0 h RL w 0 RL 0 h neg RL CP}D/xr D0/yr D0/rx D0/ry\n" -"D0/rx2 D0/ry2 D0/RR{/yr ED/xr ED/h ED/w ED/y ED/x ED xr 0 le yr 0 le or{x y\n" -"w h R}{xr 100 ge yr 100 ge or{x y w h E}{/rx xr w mul 200 div d/ry yr h mul\n" -"200 div d/rx2 rx 2 mul d/ry2 ry 2 mul d NP x rx add y MT x y rx2 ry2 180 -90\n" -"x y h add ry2 sub rx2 ry2 270 -90 x w add rx2 sub y h add ry2 sub rx2 ry2 0\n" -"-90 x w add rx2 sub y rx2 ry2 90 -90 ARC ARC ARC ARC CP BF QS}ie}ie}D/E{/h\n" -"ED/w ED/y ED/x ED mat CM pop x w 2 div add y h 2 div add TR 1 h w div scale\n" -"NP 0 0 w 2 div 0 360 arc mat SM BF QS}D/A{16 div exch 16 div exch NP ARC QS}\n" -"D/PIE{/ang2 ED/ang1 ED/h ED/w ED/y ED/x ED NP x w 2 div add y h 2 div add MT\n" -"x y w h ang1 16 div ang2 16 div ARC CP BF QS}D/CH{16 div exch 16 div exch NP\n" -"ARC CP BF QS}D/BZ{curveto QS}D/CRGB{255 div 3 1 roll 255 div 3 1 roll 255\n" -"div 3 1 roll}D/BC{CRGB BkCol sp}D/BR{CRGB BCol sp/BSt ED}D/WB{1 W BR}D/NB{0\n" -"B BR}D/PE{setlinejoin setlinecap CRGB PCol sp/LWi ED/PSt ED LWi 0 eq{0.25\n" -"/LWi ED}if PCol SC}D/P1{1 0 5 2 roll 0 0 PE}D/ST{defM SM concat}D/MF{true\n" -"exch true exch{exch pop exch pop dup 0 get dup findfont dup/FontName get 3\n" -"-1 roll eq{exit}if}forall exch dup 1 get/fxscale ED 2 get/fslant ED exch\n" -"/fencoding ED[fxscale 0 fslant 1 0 0]makefont fencoding false eq{}{dup\n" -"maxlength dict begin{1 i/FID ne{def}{pop pop}ifelse}forall/Encoding\n" -"fencoding d currentdict end}ie definefont pop}D/MFEmb{findfont dup length\n" -"dict begin{1 i/FID ne{d}{pop pop}ifelse}forall/Encoding ED currentdict end\n" -"definefont pop}D/DF{findfont/fs 3 -1 roll d[fs 0 0 fs -1 mul 0 0]makefont d}\n" -"D/ty 0 d/Y{/ty ED}D/Tl{gsave SW NP 1 i exch MT 1 i 0 RL S grestore}D/XYT{ty\n" -"MT/xyshow where{pop pop xyshow}{exch pop 1 i dup length 2 div exch\n" -"stringwidth pop 3 -1 roll exch sub exch div exch 0 exch ashow}ie}D/AT{ty MT\n" -"1 i dup length 2 div exch stringwidth pop 3 -1 roll exch sub exch div exch 0\n" -"exch ashow}D/QI{/C save d pageinit/Cx 0 d/Cy 0 d/OMo false d}D/QP{C restore\n" -"showpage}D/SPD{/setpagedevice where{1 DB 3 1 roll d end setpagedevice}{pop\n" -"pop}ie}D/SV{BSt LWi PSt Cx Cy WFi OMo BCol PCol BkCol/nS nS 1 add d gsave}D\n" -"/RS{nS 0 gt{grestore/BkCol ED/PCol ED/BCol ED/OMo ED/WFi ED/Cy ED/Cx ED/PSt\n" -"ED/LWi ED/BSt ED/nS nS 1 sub d}if}D/CLSTART{/clipTmp matrix CM d defM SM NP}\n" -"D/CLEND{clip NP clipTmp SM}D/CLO{grestore gsave defM SM}D\n"; - -// the next table is derived from a list provided by Adobe on its web -// server: http://partners.adobe.com/asn/developer/typeforum/glyphlist.txt - -// the start of the header comment: -// -// Name: Adobe Glyph List -// Table version: 1.2 -// Date: 22 Oct 1998 -// -// Description: -// -// The Adobe Glyph List (AGL) list relates Unicode values (UVs) to glyph -// names, and should be used only as described in the document "Unicode and -// Glyph Names," at -// http://partners.adobe.com:80/asn/developer/type/unicodegn.html -// -// IMPORTANT NOTE: -// the list contains glyphs in the private use area of unicode. These should get removed when regenerating the glyphlist. -// also 0 shout be mapped to .notdef -static const struct { - TQ_UINT16 u; - const char * g; -} unicodetoglyph[] = { - // grep '^[0-9A-F][0-9A-F][0-9A-F][0-9A-F];' < /tmp/glyphlist.txt | sed -e 's/;/, "/' -e 's-;-" }, // -' -e 's/^/ { 0x/' | sort - { 0x0000, ".notdef" }, - { 0x0020, "space" }, // SPACE - { 0x0021, "exclam" }, // EXCLAMATION MARK - { 0x0022, "quotedbl" }, // QUOTATION MARK - { 0x0023, "numbersign" }, // NUMBER SIGN - { 0x0024, "dollar" }, // DOLLAR SIGN - { 0x0025, "percent" }, // PERCENT SIGN - { 0x0026, "ampersand" }, // AMPERSAND - { 0x0027, "quotesingle" }, // APOSTROPHE - { 0x0028, "parenleft" }, // LEFT PARENTHESIS - { 0x0029, "parenright" }, // RIGHT PARENTHESIS - { 0x002A, "asterisk" }, // ASTERISK - { 0x002B, "plus" }, // PLUS SIGN - { 0x002C, "comma" }, // COMMA - { 0x002D, "hyphen" }, // HYPHEN-MINUS - { 0x002E, "period" }, // FULL STOP - { 0x002F, "slash" }, // SOLIDUS - { 0x0030, "zero" }, // DIGIT ZERO - { 0x0031, "one" }, // DIGIT ONE - { 0x0032, "two" }, // DIGIT TWO - { 0x0033, "three" }, // DIGIT THREE - { 0x0034, "four" }, // DIGIT FOUR - { 0x0035, "five" }, // DIGIT FIVE - { 0x0036, "six" }, // DIGIT SIX - { 0x0037, "seven" }, // DIGIT SEVEN - { 0x0038, "eight" }, // DIGIT EIGHT - { 0x0039, "nine" }, // DIGIT NINE - { 0x003A, "colon" }, // COLON - { 0x003B, "semicolon" }, // SEMICOLON - { 0x003C, "less" }, // LESS-THAN SIGN - { 0x003D, "equal" }, // EQUALS SIGN - { 0x003E, "greater" }, // GREATER-THAN SIGN - { 0x003F, "question" }, // QUESTION MARK - { 0x0040, "at" }, // COMMERCIAL AT - { 0x0041, "A" }, // LATIN CAPITAL LETTER A - { 0x0042, "B" }, // LATIN CAPITAL LETTER B - { 0x0043, "C" }, // LATIN CAPITAL LETTER C - { 0x0044, "D" }, // LATIN CAPITAL LETTER D - { 0x0045, "E" }, // LATIN CAPITAL LETTER E - { 0x0046, "F" }, // LATIN CAPITAL LETTER F - { 0x0047, "G" }, // LATIN CAPITAL LETTER G - { 0x0048, "H" }, // LATIN CAPITAL LETTER H - { 0x0049, "I" }, // LATIN CAPITAL LETTER I - { 0x004A, "J" }, // LATIN CAPITAL LETTER J - { 0x004B, "K" }, // LATIN CAPITAL LETTER K - { 0x004C, "L" }, // LATIN CAPITAL LETTER L - { 0x004D, "M" }, // LATIN CAPITAL LETTER M - { 0x004E, "N" }, // LATIN CAPITAL LETTER N - { 0x004F, "O" }, // LATIN CAPITAL LETTER O - { 0x0050, "P" }, // LATIN CAPITAL LETTER P - { 0x0051, "Q" }, // LATIN CAPITAL LETTER Q - { 0x0052, "R" }, // LATIN CAPITAL LETTER R - { 0x0053, "S" }, // LATIN CAPITAL LETTER S - { 0x0054, "T" }, // LATIN CAPITAL LETTER T - { 0x0055, "U" }, // LATIN CAPITAL LETTER U - { 0x0056, "V" }, // LATIN CAPITAL LETTER V - { 0x0057, "W" }, // LATIN CAPITAL LETTER W - { 0x0058, "X" }, // LATIN CAPITAL LETTER X - { 0x0059, "Y" }, // LATIN CAPITAL LETTER Y - { 0x005A, "Z" }, // LATIN CAPITAL LETTER Z - { 0x005B, "bracketleft" }, // LEFT SQUARE BRACKET - { 0x005C, "backslash" }, // REVERSE SOLIDUS - { 0x005D, "bracketright" }, // RIGHT SQUARE BRACKET - { 0x005E, "asciicircum" }, // CIRCUMFLEX ACCENT - { 0x005F, "underscore" }, // LOW LINE - { 0x0060, "grave" }, // GRAVE ACCENT - { 0x0061, "a" }, // LATIN SMALL LETTER A - { 0x0062, "b" }, // LATIN SMALL LETTER B - { 0x0063, "c" }, // LATIN SMALL LETTER C - { 0x0064, "d" }, // LATIN SMALL LETTER D - { 0x0065, "e" }, // LATIN SMALL LETTER E - { 0x0066, "f" }, // LATIN SMALL LETTER F - { 0x0067, "g" }, // LATIN SMALL LETTER G - { 0x0068, "h" }, // LATIN SMALL LETTER H - { 0x0069, "i" }, // LATIN SMALL LETTER I - { 0x006A, "j" }, // LATIN SMALL LETTER J - { 0x006B, "k" }, // LATIN SMALL LETTER K - { 0x006C, "l" }, // LATIN SMALL LETTER L - { 0x006D, "m" }, // LATIN SMALL LETTER M - { 0x006E, "n" }, // LATIN SMALL LETTER N - { 0x006F, "o" }, // LATIN SMALL LETTER O - { 0x0070, "p" }, // LATIN SMALL LETTER P - { 0x0071, "q" }, // LATIN SMALL LETTER Q - { 0x0072, "r" }, // LATIN SMALL LETTER R - { 0x0073, "s" }, // LATIN SMALL LETTER S - { 0x0074, "t" }, // LATIN SMALL LETTER T - { 0x0075, "u" }, // LATIN SMALL LETTER U - { 0x0076, "v" }, // LATIN SMALL LETTER V - { 0x0077, "w" }, // LATIN SMALL LETTER W - { 0x0078, "x" }, // LATIN SMALL LETTER X - { 0x0079, "y" }, // LATIN SMALL LETTER Y - { 0x007A, "z" }, // LATIN SMALL LETTER Z - { 0x007B, "braceleft" }, // LEFT CURLY BRACKET - { 0x007C, "bar" }, // VERTICAL LINE - { 0x007D, "braceright" }, // RIGHT CURLY BRACKET - { 0x007E, "asciitilde" }, // TILDE - { 0x00A0, "space" }, // NO-BREAK SPACE;Duplicate - { 0x00A1, "exclamdown" }, // INVERTED EXCLAMATION MARK - { 0x00A2, "cent" }, // CENT SIGN - { 0x00A3, "sterling" }, // POUND SIGN - { 0x00A4, "currency" }, // CURRENCY SIGN - { 0x00A5, "yen" }, // YEN SIGN - { 0x00A6, "brokenbar" }, // BROKEN BAR - { 0x00A7, "section" }, // SECTION SIGN - { 0x00A8, "dieresis" }, // DIAERESIS - { 0x00A9, "copyright" }, // COPYRIGHT SIGN - { 0x00AA, "ordfeminine" }, // FEMININE ORDINAL INDICATOR - { 0x00AB, "guillemotleft" }, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - { 0x00AC, "logicalnot" }, // NOT SIGN - { 0x00AD, "hyphen" }, // SOFT HYPHEN;Duplicate - { 0x00AE, "registered" }, // REGISTERED SIGN - { 0x00AF, "macron" }, // MACRON - { 0x00B0, "degree" }, // DEGREE SIGN - { 0x00B1, "plusminus" }, // PLUS-MINUS SIGN - { 0x00B2, "twosuperior" }, // SUPERSCRIPT TWO - { 0x00B3, "threesuperior" }, // SUPERSCRIPT THREE - { 0x00B4, "acute" }, // ACUTE ACCENT - { 0x00B5, "mu" }, // MICRO SIGN - { 0x00B6, "paragraph" }, // PILCROW SIGN - { 0x00B7, "periodcentered" }, // MIDDLE DOT - { 0x00B8, "cedilla" }, // CEDILLA - { 0x00B9, "onesuperior" }, // SUPERSCRIPT ONE - { 0x00BA, "ordmasculine" }, // MASCULINE ORDINAL INDICATOR - { 0x00BB, "guillemotright" }, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - { 0x00BC, "onequarter" }, // VULGAR FRACTION ONE QUARTER - { 0x00BD, "onehalf" }, // VULGAR FRACTION ONE HALF - { 0x00BE, "threequarters" }, // VULGAR FRACTION THREE QUARTERS - { 0x00BF, "questiondown" }, // INVERTED QUESTION MARK - { 0x00C0, "Agrave" }, // LATIN CAPITAL LETTER A WITH GRAVE - { 0x00C1, "Aacute" }, // LATIN CAPITAL LETTER A WITH ACUTE - { 0x00C2, "Acircumflex" }, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX - { 0x00C3, "Atilde" }, // LATIN CAPITAL LETTER A WITH TILDE - { 0x00C4, "Adieresis" }, // LATIN CAPITAL LETTER A WITH DIAERESIS - { 0x00C5, "Aring" }, // LATIN CAPITAL LETTER A WITH RING ABOVE - { 0x00C6, "AE" }, // LATIN CAPITAL LETTER AE - { 0x00C7, "Ccedilla" }, // LATIN CAPITAL LETTER C WITH CEDILLA - { 0x00C8, "Egrave" }, // LATIN CAPITAL LETTER E WITH GRAVE - { 0x00C9, "Eacute" }, // LATIN CAPITAL LETTER E WITH ACUTE - { 0x00CA, "Ecircumflex" }, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX - { 0x00CB, "Edieresis" }, // LATIN CAPITAL LETTER E WITH DIAERESIS - { 0x00CC, "Igrave" }, // LATIN CAPITAL LETTER I WITH GRAVE - { 0x00CD, "Iacute" }, // LATIN CAPITAL LETTER I WITH ACUTE - { 0x00CE, "Icircumflex" }, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX - { 0x00CF, "Idieresis" }, // LATIN CAPITAL LETTER I WITH DIAERESIS - { 0x00D0, "Eth" }, // LATIN CAPITAL LETTER ETH - { 0x00D1, "Ntilde" }, // LATIN CAPITAL LETTER N WITH TILDE - { 0x00D2, "Ograve" }, // LATIN CAPITAL LETTER O WITH GRAVE - { 0x00D3, "Oacute" }, // LATIN CAPITAL LETTER O WITH ACUTE - { 0x00D4, "Ocircumflex" }, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX - { 0x00D5, "Otilde" }, // LATIN CAPITAL LETTER O WITH TILDE - { 0x00D6, "Odieresis" }, // LATIN CAPITAL LETTER O WITH DIAERESIS - { 0x00D7, "multiply" }, // MULTIPLICATION SIGN - { 0x00D8, "Oslash" }, // LATIN CAPITAL LETTER O WITH STROKE - { 0x00D9, "Ugrave" }, // LATIN CAPITAL LETTER U WITH GRAVE - { 0x00DA, "Uacute" }, // LATIN CAPITAL LETTER U WITH ACUTE - { 0x00DB, "Ucircumflex" }, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX - { 0x00DC, "Udieresis" }, // LATIN CAPITAL LETTER U WITH DIAERESIS - { 0x00DD, "Yacute" }, // LATIN CAPITAL LETTER Y WITH ACUTE - { 0x00DE, "Thorn" }, // LATIN CAPITAL LETTER THORN - { 0x00DF, "germandbls" }, // LATIN SMALL LETTER SHARP S - { 0x00E0, "agrave" }, // LATIN SMALL LETTER A WITH GRAVE - { 0x00E1, "aacute" }, // LATIN SMALL LETTER A WITH ACUTE - { 0x00E2, "acircumflex" }, // LATIN SMALL LETTER A WITH CIRCUMFLEX - { 0x00E3, "atilde" }, // LATIN SMALL LETTER A WITH TILDE - { 0x00E4, "adieresis" }, // LATIN SMALL LETTER A WITH DIAERESIS - { 0x00E5, "aring" }, // LATIN SMALL LETTER A WITH RING ABOVE - { 0x00E6, "ae" }, // LATIN SMALL LETTER AE - { 0x00E7, "ccedilla" }, // LATIN SMALL LETTER C WITH CEDILLA - { 0x00E8, "egrave" }, // LATIN SMALL LETTER E WITH GRAVE - { 0x00E9, "eacute" }, // LATIN SMALL LETTER E WITH ACUTE - { 0x00EA, "ecircumflex" }, // LATIN SMALL LETTER E WITH CIRCUMFLEX - { 0x00EB, "edieresis" }, // LATIN SMALL LETTER E WITH DIAERESIS - { 0x00EC, "igrave" }, // LATIN SMALL LETTER I WITH GRAVE - { 0x00ED, "iacute" }, // LATIN SMALL LETTER I WITH ACUTE - { 0x00EE, "icircumflex" }, // LATIN SMALL LETTER I WITH CIRCUMFLEX - { 0x00EF, "idieresis" }, // LATIN SMALL LETTER I WITH DIAERESIS - { 0x00F0, "eth" }, // LATIN SMALL LETTER ETH - { 0x00F1, "ntilde" }, // LATIN SMALL LETTER N WITH TILDE - { 0x00F2, "ograve" }, // LATIN SMALL LETTER O WITH GRAVE - { 0x00F3, "oacute" }, // LATIN SMALL LETTER O WITH ACUTE - { 0x00F4, "ocircumflex" }, // LATIN SMALL LETTER O WITH CIRCUMFLEX - { 0x00F5, "otilde" }, // LATIN SMALL LETTER O WITH TILDE - { 0x00F6, "odieresis" }, // LATIN SMALL LETTER O WITH DIAERESIS - { 0x00F7, "divide" }, // DIVISION SIGN - { 0x00F8, "oslash" }, // LATIN SMALL LETTER O WITH STROKE - { 0x00F9, "ugrave" }, // LATIN SMALL LETTER U WITH GRAVE - { 0x00FA, "uacute" }, // LATIN SMALL LETTER U WITH ACUTE - { 0x00FB, "ucircumflex" }, // LATIN SMALL LETTER U WITH CIRCUMFLEX - { 0x00FC, "udieresis" }, // LATIN SMALL LETTER U WITH DIAERESIS - { 0x00FD, "yacute" }, // LATIN SMALL LETTER Y WITH ACUTE - { 0x00FE, "thorn" }, // LATIN SMALL LETTER THORN - { 0x00FF, "ydieresis" }, // LATIN SMALL LETTER Y WITH DIAERESIS - { 0x0100, "Amacron" }, // LATIN CAPITAL LETTER A WITH MACRON - { 0x0101, "amacron" }, // LATIN SMALL LETTER A WITH MACRON - { 0x0102, "Abreve" }, // LATIN CAPITAL LETTER A WITH BREVE - { 0x0103, "abreve" }, // LATIN SMALL LETTER A WITH BREVE - { 0x0104, "Aogonek" }, // LATIN CAPITAL LETTER A WITH OGONEK - { 0x0105, "aogonek" }, // LATIN SMALL LETTER A WITH OGONEK - { 0x0106, "Cacute" }, // LATIN CAPITAL LETTER C WITH ACUTE - { 0x0107, "cacute" }, // LATIN SMALL LETTER C WITH ACUTE - { 0x0108, "Ccircumflex" }, // LATIN CAPITAL LETTER C WITH CIRCUMFLEX - { 0x0109, "ccircumflex" }, // LATIN SMALL LETTER C WITH CIRCUMFLEX - { 0x010A, "Cdotaccent" }, // LATIN CAPITAL LETTER C WITH DOT ABOVE - { 0x010B, "cdotaccent" }, // LATIN SMALL LETTER C WITH DOT ABOVE - { 0x010C, "Ccaron" }, // LATIN CAPITAL LETTER C WITH CARON - { 0x010D, "ccaron" }, // LATIN SMALL LETTER C WITH CARON - { 0x010E, "Dcaron" }, // LATIN CAPITAL LETTER D WITH CARON - { 0x010F, "dcaron" }, // LATIN SMALL LETTER D WITH CARON - { 0x0110, "Dcroat" }, // LATIN CAPITAL LETTER D WITH STROKE - { 0x0111, "dcroat" }, // LATIN SMALL LETTER D WITH STROKE - { 0x0112, "Emacron" }, // LATIN CAPITAL LETTER E WITH MACRON - { 0x0113, "emacron" }, // LATIN SMALL LETTER E WITH MACRON - { 0x0114, "Ebreve" }, // LATIN CAPITAL LETTER E WITH BREVE - { 0x0115, "ebreve" }, // LATIN SMALL LETTER E WITH BREVE - { 0x0116, "Edotaccent" }, // LATIN CAPITAL LETTER E WITH DOT ABOVE - { 0x0117, "edotaccent" }, // LATIN SMALL LETTER E WITH DOT ABOVE - { 0x0118, "Eogonek" }, // LATIN CAPITAL LETTER E WITH OGONEK - { 0x0119, "eogonek" }, // LATIN SMALL LETTER E WITH OGONEK - { 0x011A, "Ecaron" }, // LATIN CAPITAL LETTER E WITH CARON - { 0x011B, "ecaron" }, // LATIN SMALL LETTER E WITH CARON - { 0x011C, "Gcircumflex" }, // LATIN CAPITAL LETTER G WITH CIRCUMFLEX - { 0x011D, "gcircumflex" }, // LATIN SMALL LETTER G WITH CIRCUMFLEX - { 0x011E, "Gbreve" }, // LATIN CAPITAL LETTER G WITH BREVE - { 0x011F, "gbreve" }, // LATIN SMALL LETTER G WITH BREVE - { 0x0120, "Gdotaccent" }, // LATIN CAPITAL LETTER G WITH DOT ABOVE - { 0x0121, "gdotaccent" }, // LATIN SMALL LETTER G WITH DOT ABOVE - { 0x0122, "Gcommaaccent" }, // LATIN CAPITAL LETTER G WITH CEDILLA - { 0x0123, "gcommaaccent" }, // LATIN SMALL LETTER G WITH CEDILLA - { 0x0124, "Hcircumflex" }, // LATIN CAPITAL LETTER H WITH CIRCUMFLEX - { 0x0125, "hcircumflex" }, // LATIN SMALL LETTER H WITH CIRCUMFLEX - { 0x0126, "Hbar" }, // LATIN CAPITAL LETTER H WITH STROKE - { 0x0127, "hbar" }, // LATIN SMALL LETTER H WITH STROKE - { 0x0128, "Itilde" }, // LATIN CAPITAL LETTER I WITH TILDE - { 0x0129, "itilde" }, // LATIN SMALL LETTER I WITH TILDE - { 0x012A, "Imacron" }, // LATIN CAPITAL LETTER I WITH MACRON - { 0x012B, "imacron" }, // LATIN SMALL LETTER I WITH MACRON - { 0x012C, "Ibreve" }, // LATIN CAPITAL LETTER I WITH BREVE - { 0x012D, "ibreve" }, // LATIN SMALL LETTER I WITH BREVE - { 0x012E, "Iogonek" }, // LATIN CAPITAL LETTER I WITH OGONEK - { 0x012F, "iogonek" }, // LATIN SMALL LETTER I WITH OGONEK - { 0x0130, "Idotaccent" }, // LATIN CAPITAL LETTER I WITH DOT ABOVE - { 0x0131, "dotlessi" }, // LATIN SMALL LETTER DOTLESS I - { 0x0132, "IJ" }, // LATIN CAPITAL LIGATURE IJ - { 0x0133, "ij" }, // LATIN SMALL LIGATURE IJ - { 0x0134, "Jcircumflex" }, // LATIN CAPITAL LETTER J WITH CIRCUMFLEX - { 0x0135, "jcircumflex" }, // LATIN SMALL LETTER J WITH CIRCUMFLEX - { 0x0136, "Kcommaaccent" }, // LATIN CAPITAL LETTER K WITH CEDILLA - { 0x0137, "kcommaaccent" }, // LATIN SMALL LETTER K WITH CEDILLA - { 0x0138, "kgreenlandic" }, // LATIN SMALL LETTER KRA - { 0x0139, "Lacute" }, // LATIN CAPITAL LETTER L WITH ACUTE - { 0x013A, "lacute" }, // LATIN SMALL LETTER L WITH ACUTE - { 0x013B, "Lcommaaccent" }, // LATIN CAPITAL LETTER L WITH CEDILLA - { 0x013C, "lcommaaccent" }, // LATIN SMALL LETTER L WITH CEDILLA - { 0x013D, "Lcaron" }, // LATIN CAPITAL LETTER L WITH CARON - { 0x013E, "lcaron" }, // LATIN SMALL LETTER L WITH CARON - { 0x013F, "Ldot" }, // LATIN CAPITAL LETTER L WITH MIDDLE DOT - { 0x0140, "ldot" }, // LATIN SMALL LETTER L WITH MIDDLE DOT - { 0x0141, "Lslash" }, // LATIN CAPITAL LETTER L WITH STROKE - { 0x0142, "lslash" }, // LATIN SMALL LETTER L WITH STROKE - { 0x0143, "Nacute" }, // LATIN CAPITAL LETTER N WITH ACUTE - { 0x0144, "nacute" }, // LATIN SMALL LETTER N WITH ACUTE - { 0x0145, "Ncommaaccent" }, // LATIN CAPITAL LETTER N WITH CEDILLA - { 0x0146, "ncommaaccent" }, // LATIN SMALL LETTER N WITH CEDILLA - { 0x0147, "Ncaron" }, // LATIN CAPITAL LETTER N WITH CARON - { 0x0148, "ncaron" }, // LATIN SMALL LETTER N WITH CARON - { 0x0149, "napostrophe" }, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE - { 0x014A, "Eng" }, // LATIN CAPITAL LETTER ENG - { 0x014B, "eng" }, // LATIN SMALL LETTER ENG - { 0x014C, "Omacron" }, // LATIN CAPITAL LETTER O WITH MACRON - { 0x014D, "omacron" }, // LATIN SMALL LETTER O WITH MACRON - { 0x014E, "Obreve" }, // LATIN CAPITAL LETTER O WITH BREVE - { 0x014F, "obreve" }, // LATIN SMALL LETTER O WITH BREVE - { 0x0150, "Ohungarumlaut" }, // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE - { 0x0151, "ohungarumlaut" }, // LATIN SMALL LETTER O WITH DOUBLE ACUTE - { 0x0152, "OE" }, // LATIN CAPITAL LIGATURE OE - { 0x0153, "oe" }, // LATIN SMALL LIGATURE OE - { 0x0154, "Racute" }, // LATIN CAPITAL LETTER R WITH ACUTE - { 0x0155, "racute" }, // LATIN SMALL LETTER R WITH ACUTE - { 0x0156, "Rcommaaccent" }, // LATIN CAPITAL LETTER R WITH CEDILLA - { 0x0157, "rcommaaccent" }, // LATIN SMALL LETTER R WITH CEDILLA - { 0x0158, "Rcaron" }, // LATIN CAPITAL LETTER R WITH CARON - { 0x0159, "rcaron" }, // LATIN SMALL LETTER R WITH CARON - { 0x015A, "Sacute" }, // LATIN CAPITAL LETTER S WITH ACUTE - { 0x015B, "sacute" }, // LATIN SMALL LETTER S WITH ACUTE - { 0x015C, "Scircumflex" }, // LATIN CAPITAL LETTER S WITH CIRCUMFLEX - { 0x015D, "scircumflex" }, // LATIN SMALL LETTER S WITH CIRCUMFLEX - { 0x015E, "Scedilla" }, // LATIN CAPITAL LETTER S WITH CEDILLA - { 0x015F, "scedilla" }, // LATIN SMALL LETTER S WITH CEDILLA - { 0x0160, "Scaron" }, // LATIN CAPITAL LETTER S WITH CARON - { 0x0161, "scaron" }, // LATIN SMALL LETTER S WITH CARON - { 0x0162, "Tcommaaccent" }, // LATIN CAPITAL LETTER T WITH CEDILLA - { 0x0163, "tcommaaccent" }, // LATIN SMALL LETTER T WITH CEDILLA - { 0x0164, "Tcaron" }, // LATIN CAPITAL LETTER T WITH CARON - { 0x0165, "tcaron" }, // LATIN SMALL LETTER T WITH CARON - { 0x0166, "Tbar" }, // LATIN CAPITAL LETTER T WITH STROKE - { 0x0167, "tbar" }, // LATIN SMALL LETTER T WITH STROKE - { 0x0168, "Utilde" }, // LATIN CAPITAL LETTER U WITH TILDE - { 0x0169, "utilde" }, // LATIN SMALL LETTER U WITH TILDE - { 0x016A, "Umacron" }, // LATIN CAPITAL LETTER U WITH MACRON - { 0x016B, "umacron" }, // LATIN SMALL LETTER U WITH MACRON - { 0x016C, "Ubreve" }, // LATIN CAPITAL LETTER U WITH BREVE - { 0x016D, "ubreve" }, // LATIN SMALL LETTER U WITH BREVE - { 0x016E, "Uring" }, // LATIN CAPITAL LETTER U WITH RING ABOVE - { 0x016F, "uring" }, // LATIN SMALL LETTER U WITH RING ABOVE - { 0x0170, "Uhungarumlaut" }, // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE - { 0x0171, "uhungarumlaut" }, // LATIN SMALL LETTER U WITH DOUBLE ACUTE - { 0x0172, "Uogonek" }, // LATIN CAPITAL LETTER U WITH OGONEK - { 0x0173, "uogonek" }, // LATIN SMALL LETTER U WITH OGONEK - { 0x0174, "Wcircumflex" }, // LATIN CAPITAL LETTER W WITH CIRCUMFLEX - { 0x0175, "wcircumflex" }, // LATIN SMALL LETTER W WITH CIRCUMFLEX - { 0x0176, "Ycircumflex" }, // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX - { 0x0177, "ycircumflex" }, // LATIN SMALL LETTER Y WITH CIRCUMFLEX - { 0x0178, "Ydieresis" }, // LATIN CAPITAL LETTER Y WITH DIAERESIS - { 0x0179, "Zacute" }, // LATIN CAPITAL LETTER Z WITH ACUTE - { 0x017A, "zacute" }, // LATIN SMALL LETTER Z WITH ACUTE - { 0x017B, "Zdotaccent" }, // LATIN CAPITAL LETTER Z WITH DOT ABOVE - { 0x017C, "zdotaccent" }, // LATIN SMALL LETTER Z WITH DOT ABOVE - { 0x017D, "Zcaron" }, // LATIN CAPITAL LETTER Z WITH CARON - { 0x017E, "zcaron" }, // LATIN SMALL LETTER Z WITH CARON - { 0x017F, "longs" }, // LATIN SMALL LETTER LONG S - { 0x0192, "florin" }, // LATIN SMALL LETTER F WITH HOOK - { 0x01A0, "Ohorn" }, // LATIN CAPITAL LETTER O WITH HORN - { 0x01A1, "ohorn" }, // LATIN SMALL LETTER O WITH HORN - { 0x01AF, "Uhorn" }, // LATIN CAPITAL LETTER U WITH HORN - { 0x01B0, "uhorn" }, // LATIN SMALL LETTER U WITH HORN - { 0x01E6, "Gcaron" }, // LATIN CAPITAL LETTER G WITH CARON - { 0x01E7, "gcaron" }, // LATIN SMALL LETTER G WITH CARON - { 0x01FA, "Aringacute" }, // LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE - { 0x01FB, "aringacute" }, // LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE - { 0x01FC, "AEacute" }, // LATIN CAPITAL LETTER AE WITH ACUTE - { 0x01FD, "aeacute" }, // LATIN SMALL LETTER AE WITH ACUTE - { 0x01FE, "Oslashacute" }, // LATIN CAPITAL LETTER O WITH STROKE AND ACUTE - { 0x01FF, "oslashacute" }, // LATIN SMALL LETTER O WITH STROKE AND ACUTE - { 0x0218, "Scommaaccent" }, // LATIN CAPITAL LETTER S WITH COMMA BELOW - { 0x0219, "scommaaccent" }, // LATIN SMALL LETTER S WITH COMMA BELOW - { 0x021A, "Tcommaaccent" }, // LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate - { 0x021B, "tcommaaccent" }, // LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate - { 0x02BC, "afii57929" }, // MODIFIER LETTER APOSTROPHE - { 0x02BD, "afii64937" }, // MODIFIER LETTER REVERSED COMMA - { 0x02C6, "circumflex" }, // MODIFIER LETTER CIRCUMFLEX ACCENT - { 0x02C7, "caron" }, // CARON - { 0x02C9, "macron" }, // MODIFIER LETTER MACRON;Duplicate - { 0x02D8, "breve" }, // BREVE - { 0x02D9, "dotaccent" }, // DOT ABOVE - { 0x02DA, "ring" }, // RING ABOVE - { 0x02DB, "ogonek" }, // OGONEK - { 0x02DC, "tilde" }, // SMALL TILDE - { 0x02DD, "hungarumlaut" }, // DOUBLE ACUTE ACCENT - { 0x0300, "gravecomb" }, // COMBINING GRAVE ACCENT - { 0x0301, "acutecomb" }, // COMBINING ACUTE ACCENT - { 0x0303, "tildecomb" }, // COMBINING TILDE - { 0x0309, "hookabovecomb" }, // COMBINING HOOK ABOVE - { 0x0323, "dotbelowcomb" }, // COMBINING DOT BELOW - { 0x0384, "tonos" }, // GREEK TONOS - { 0x0385, "dieresistonos" }, // GREEK DIALYTIKA TONOS - { 0x0386, "Alphatonos" }, // GREEK CAPITAL LETTER ALPHA WITH TONOS - { 0x0387, "anoteleia" }, // GREEK ANO TELEIA - { 0x0388, "Epsilontonos" }, // GREEK CAPITAL LETTER EPSILON WITH TONOS - { 0x0389, "Etatonos" }, // GREEK CAPITAL LETTER ETA WITH TONOS - { 0x038A, "Iotatonos" }, // GREEK CAPITAL LETTER IOTA WITH TONOS - { 0x038C, "Omicrontonos" }, // GREEK CAPITAL LETTER OMICRON WITH TONOS - { 0x038E, "Upsilontonos" }, // GREEK CAPITAL LETTER UPSILON WITH TONOS - { 0x038F, "Omegatonos" }, // GREEK CAPITAL LETTER OMEGA WITH TONOS - { 0x0390, "iotadieresistonos" }, // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS - { 0x0391, "Alpha" }, // GREEK CAPITAL LETTER ALPHA - { 0x0392, "Beta" }, // GREEK CAPITAL LETTER BETA - { 0x0393, "Gamma" }, // GREEK CAPITAL LETTER GAMMA - { 0x0394, "Delta" }, // GREEK CAPITAL LETTER DELTA;Duplicate - { 0x0395, "Epsilon" }, // GREEK CAPITAL LETTER EPSILON - { 0x0396, "Zeta" }, // GREEK CAPITAL LETTER ZETA - { 0x0397, "Eta" }, // GREEK CAPITAL LETTER ETA - { 0x0398, "Theta" }, // GREEK CAPITAL LETTER THETA - { 0x0399, "Iota" }, // GREEK CAPITAL LETTER IOTA - { 0x039A, "Kappa" }, // GREEK CAPITAL LETTER KAPPA - { 0x039B, "Lambda" }, // GREEK CAPITAL LETTER LAMDA - { 0x039C, "Mu" }, // GREEK CAPITAL LETTER MU - { 0x039D, "Nu" }, // GREEK CAPITAL LETTER NU - { 0x039E, "Xi" }, // GREEK CAPITAL LETTER XI - { 0x039F, "Omicron" }, // GREEK CAPITAL LETTER OMICRON - { 0x03A0, "Pi" }, // GREEK CAPITAL LETTER PI - { 0x03A1, "Rho" }, // GREEK CAPITAL LETTER RHO - { 0x03A3, "Sigma" }, // GREEK CAPITAL LETTER SIGMA - { 0x03A4, "Tau" }, // GREEK CAPITAL LETTER TAU - { 0x03A5, "Upsilon" }, // GREEK CAPITAL LETTER UPSILON - { 0x03A6, "Phi" }, // GREEK CAPITAL LETTER PHI - { 0x03A7, "Chi" }, // GREEK CAPITAL LETTER CHI - { 0x03A8, "Psi" }, // GREEK CAPITAL LETTER PSI - { 0x03A9, "Omega" }, // GREEK CAPITAL LETTER OMEGA;Duplicate - { 0x03AA, "Iotadieresis" }, // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA - { 0x03AB, "Upsilondieresis" }, // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA - { 0x03AC, "alphatonos" }, // GREEK SMALL LETTER ALPHA WITH TONOS - { 0x03AD, "epsilontonos" }, // GREEK SMALL LETTER EPSILON WITH TONOS - { 0x03AE, "etatonos" }, // GREEK SMALL LETTER ETA WITH TONOS - { 0x03AF, "iotatonos" }, // GREEK SMALL LETTER IOTA WITH TONOS - { 0x03B0, "upsilondieresistonos" }, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS - { 0x03B1, "alpha" }, // GREEK SMALL LETTER ALPHA - { 0x03B2, "beta" }, // GREEK SMALL LETTER BETA - { 0x03B3, "gamma" }, // GREEK SMALL LETTER GAMMA - { 0x03B4, "delta" }, // GREEK SMALL LETTER DELTA - { 0x03B5, "epsilon" }, // GREEK SMALL LETTER EPSILON - { 0x03B6, "zeta" }, // GREEK SMALL LETTER ZETA - { 0x03B7, "eta" }, // GREEK SMALL LETTER ETA - { 0x03B8, "theta" }, // GREEK SMALL LETTER THETA - { 0x03B9, "iota" }, // GREEK SMALL LETTER IOTA - { 0x03BA, "kappa" }, // GREEK SMALL LETTER KAPPA - { 0x03BB, "lambda" }, // GREEK SMALL LETTER LAMDA - { 0x03BC, "mu" }, // GREEK SMALL LETTER MU;Duplicate - { 0x03BD, "nu" }, // GREEK SMALL LETTER NU - { 0x03BE, "xi" }, // GREEK SMALL LETTER XI - { 0x03BF, "omicron" }, // GREEK SMALL LETTER OMICRON - { 0x03C0, "pi" }, // GREEK SMALL LETTER PI - { 0x03C1, "rho" }, // GREEK SMALL LETTER RHO - { 0x03C2, "sigma1" }, // GREEK SMALL LETTER FINAL SIGMA - { 0x03C3, "sigma" }, // GREEK SMALL LETTER SIGMA - { 0x03C4, "tau" }, // GREEK SMALL LETTER TAU - { 0x03C5, "upsilon" }, // GREEK SMALL LETTER UPSILON - { 0x03C6, "phi" }, // GREEK SMALL LETTER PHI - { 0x03C7, "chi" }, // GREEK SMALL LETTER CHI - { 0x03C8, "psi" }, // GREEK SMALL LETTER PSI - { 0x03C9, "omega" }, // GREEK SMALL LETTER OMEGA - { 0x03CA, "iotadieresis" }, // GREEK SMALL LETTER IOTA WITH DIALYTIKA - { 0x03CB, "upsilondieresis" }, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA - { 0x03CC, "omicrontonos" }, // GREEK SMALL LETTER OMICRON WITH TONOS - { 0x03CD, "upsilontonos" }, // GREEK SMALL LETTER UPSILON WITH TONOS - { 0x03CE, "omegatonos" }, // GREEK SMALL LETTER OMEGA WITH TONOS - { 0x03D1, "theta1" }, // GREEK THETA SYMBOL - { 0x03D2, "Upsilon1" }, // GREEK UPSILON WITH HOOK SYMBOL - { 0x03D5, "phi1" }, // GREEK PHI SYMBOL - { 0x03D6, "omega1" }, // GREEK PI SYMBOL - { 0x0401, "afii10023" }, // CYRILLIC CAPITAL LETTER IO - { 0x0402, "afii10051" }, // CYRILLIC CAPITAL LETTER DJE - { 0x0403, "afii10052" }, // CYRILLIC CAPITAL LETTER GJE - { 0x0404, "afii10053" }, // CYRILLIC CAPITAL LETTER UKRAINIAN IE - { 0x0405, "afii10054" }, // CYRILLIC CAPITAL LETTER DZE - { 0x0406, "afii10055" }, // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I - { 0x0407, "afii10056" }, // CYRILLIC CAPITAL LETTER YI - { 0x0408, "afii10057" }, // CYRILLIC CAPITAL LETTER JE - { 0x0409, "afii10058" }, // CYRILLIC CAPITAL LETTER LJE - { 0x040A, "afii10059" }, // CYRILLIC CAPITAL LETTER NJE - { 0x040B, "afii10060" }, // CYRILLIC CAPITAL LETTER TSHE - { 0x040C, "afii10061" }, // CYRILLIC CAPITAL LETTER KJE - { 0x040E, "afii10062" }, // CYRILLIC CAPITAL LETTER SHORT U - { 0x040F, "afii10145" }, // CYRILLIC CAPITAL LETTER DZHE - { 0x0410, "afii10017" }, // CYRILLIC CAPITAL LETTER A - { 0x0411, "afii10018" }, // CYRILLIC CAPITAL LETTER BE - { 0x0412, "afii10019" }, // CYRILLIC CAPITAL LETTER VE - { 0x0413, "afii10020" }, // CYRILLIC CAPITAL LETTER GHE - { 0x0414, "afii10021" }, // CYRILLIC CAPITAL LETTER DE - { 0x0415, "afii10022" }, // CYRILLIC CAPITAL LETTER IE - { 0x0416, "afii10024" }, // CYRILLIC CAPITAL LETTER ZHE - { 0x0417, "afii10025" }, // CYRILLIC CAPITAL LETTER ZE - { 0x0418, "afii10026" }, // CYRILLIC CAPITAL LETTER I - { 0x0419, "afii10027" }, // CYRILLIC CAPITAL LETTER SHORT I - { 0x041A, "afii10028" }, // CYRILLIC CAPITAL LETTER KA - { 0x041B, "afii10029" }, // CYRILLIC CAPITAL LETTER EL - { 0x041C, "afii10030" }, // CYRILLIC CAPITAL LETTER EM - { 0x041D, "afii10031" }, // CYRILLIC CAPITAL LETTER EN - { 0x041E, "afii10032" }, // CYRILLIC CAPITAL LETTER O - { 0x041F, "afii10033" }, // CYRILLIC CAPITAL LETTER PE - { 0x0420, "afii10034" }, // CYRILLIC CAPITAL LETTER ER - { 0x0421, "afii10035" }, // CYRILLIC CAPITAL LETTER ES - { 0x0422, "afii10036" }, // CYRILLIC CAPITAL LETTER TE - { 0x0423, "afii10037" }, // CYRILLIC CAPITAL LETTER U - { 0x0424, "afii10038" }, // CYRILLIC CAPITAL LETTER EF - { 0x0425, "afii10039" }, // CYRILLIC CAPITAL LETTER HA - { 0x0426, "afii10040" }, // CYRILLIC CAPITAL LETTER TSE - { 0x0427, "afii10041" }, // CYRILLIC CAPITAL LETTER CHE - { 0x0428, "afii10042" }, // CYRILLIC CAPITAL LETTER SHA - { 0x0429, "afii10043" }, // CYRILLIC CAPITAL LETTER SHCHA - { 0x042A, "afii10044" }, // CYRILLIC CAPITAL LETTER HARD SIGN - { 0x042B, "afii10045" }, // CYRILLIC CAPITAL LETTER YERU - { 0x042C, "afii10046" }, // CYRILLIC CAPITAL LETTER SOFT SIGN - { 0x042D, "afii10047" }, // CYRILLIC CAPITAL LETTER E - { 0x042E, "afii10048" }, // CYRILLIC CAPITAL LETTER YU - { 0x042F, "afii10049" }, // CYRILLIC CAPITAL LETTER YA - { 0x0430, "afii10065" }, // CYRILLIC SMALL LETTER A - { 0x0431, "afii10066" }, // CYRILLIC SMALL LETTER BE - { 0x0432, "afii10067" }, // CYRILLIC SMALL LETTER VE - { 0x0433, "afii10068" }, // CYRILLIC SMALL LETTER GHE - { 0x0434, "afii10069" }, // CYRILLIC SMALL LETTER DE - { 0x0435, "afii10070" }, // CYRILLIC SMALL LETTER IE - { 0x0436, "afii10072" }, // CYRILLIC SMALL LETTER ZHE - { 0x0437, "afii10073" }, // CYRILLIC SMALL LETTER ZE - { 0x0438, "afii10074" }, // CYRILLIC SMALL LETTER I - { 0x0439, "afii10075" }, // CYRILLIC SMALL LETTER SHORT I - { 0x043A, "afii10076" }, // CYRILLIC SMALL LETTER KA - { 0x043B, "afii10077" }, // CYRILLIC SMALL LETTER EL - { 0x043C, "afii10078" }, // CYRILLIC SMALL LETTER EM - { 0x043D, "afii10079" }, // CYRILLIC SMALL LETTER EN - { 0x043E, "afii10080" }, // CYRILLIC SMALL LETTER O - { 0x043F, "afii10081" }, // CYRILLIC SMALL LETTER PE - { 0x0440, "afii10082" }, // CYRILLIC SMALL LETTER ER - { 0x0441, "afii10083" }, // CYRILLIC SMALL LETTER ES - { 0x0442, "afii10084" }, // CYRILLIC SMALL LETTER TE - { 0x0443, "afii10085" }, // CYRILLIC SMALL LETTER U - { 0x0444, "afii10086" }, // CYRILLIC SMALL LETTER EF - { 0x0445, "afii10087" }, // CYRILLIC SMALL LETTER HA - { 0x0446, "afii10088" }, // CYRILLIC SMALL LETTER TSE - { 0x0447, "afii10089" }, // CYRILLIC SMALL LETTER CHE - { 0x0448, "afii10090" }, // CYRILLIC SMALL LETTER SHA - { 0x0449, "afii10091" }, // CYRILLIC SMALL LETTER SHCHA - { 0x044A, "afii10092" }, // CYRILLIC SMALL LETTER HARD SIGN - { 0x044B, "afii10093" }, // CYRILLIC SMALL LETTER YERU - { 0x044C, "afii10094" }, // CYRILLIC SMALL LETTER SOFT SIGN - { 0x044D, "afii10095" }, // CYRILLIC SMALL LETTER E - { 0x044E, "afii10096" }, // CYRILLIC SMALL LETTER YU - { 0x044F, "afii10097" }, // CYRILLIC SMALL LETTER YA - { 0x0451, "afii10071" }, // CYRILLIC SMALL LETTER IO - { 0x0452, "afii10099" }, // CYRILLIC SMALL LETTER DJE - { 0x0453, "afii10100" }, // CYRILLIC SMALL LETTER GJE - { 0x0454, "afii10101" }, // CYRILLIC SMALL LETTER UKRAINIAN IE - { 0x0455, "afii10102" }, // CYRILLIC SMALL LETTER DZE - { 0x0456, "afii10103" }, // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I - { 0x0457, "afii10104" }, // CYRILLIC SMALL LETTER YI - { 0x0458, "afii10105" }, // CYRILLIC SMALL LETTER JE - { 0x0459, "afii10106" }, // CYRILLIC SMALL LETTER LJE - { 0x045A, "afii10107" }, // CYRILLIC SMALL LETTER NJE - { 0x045B, "afii10108" }, // CYRILLIC SMALL LETTER TSHE - { 0x045C, "afii10109" }, // CYRILLIC SMALL LETTER KJE - { 0x045E, "afii10110" }, // CYRILLIC SMALL LETTER SHORT U - { 0x045F, "afii10193" }, // CYRILLIC SMALL LETTER DZHE - { 0x0462, "afii10146" }, // CYRILLIC CAPITAL LETTER YAT - { 0x0463, "afii10194" }, // CYRILLIC SMALL LETTER YAT - { 0x0472, "afii10147" }, // CYRILLIC CAPITAL LETTER FITA - { 0x0473, "afii10195" }, // CYRILLIC SMALL LETTER FITA - { 0x0474, "afii10148" }, // CYRILLIC CAPITAL LETTER IZHITSA - { 0x0475, "afii10196" }, // CYRILLIC SMALL LETTER IZHITSA - { 0x0490, "afii10050" }, // CYRILLIC CAPITAL LETTER GHE WITH UPTURN - { 0x0491, "afii10098" }, // CYRILLIC SMALL LETTER GHE WITH UPTURN - { 0x04D9, "afii10846" }, // CYRILLIC SMALL LETTER SCHWA - { 0x05B0, "afii57799" }, // HEBREW POINT SHEVA - { 0x05B1, "afii57801" }, // HEBREW POINT HATAF SEGOL - { 0x05B2, "afii57800" }, // HEBREW POINT HATAF PATAH - { 0x05B3, "afii57802" }, // HEBREW POINT HATAF TQAMATS - { 0x05B4, "afii57793" }, // HEBREW POINT HIRIQ - { 0x05B5, "afii57794" }, // HEBREW POINT TSERE - { 0x05B6, "afii57795" }, // HEBREW POINT SEGOL - { 0x05B7, "afii57798" }, // HEBREW POINT PATAH - { 0x05B8, "afii57797" }, // HEBREW POINT TQAMATS - { 0x05B9, "afii57806" }, // HEBREW POINT HOLAM - { 0x05BB, "afii57796" }, // HEBREW POINT TQUBUTS - { 0x05BC, "afii57807" }, // HEBREW POINT DAGESH OR MAPIQ - { 0x05BD, "afii57839" }, // HEBREW POINT METEG - { 0x05BE, "afii57645" }, // HEBREW PUNCTUATION MATQAF - { 0x05BF, "afii57841" }, // HEBREW POINT RAFE - { 0x05C0, "afii57842" }, // HEBREW PUNCTUATION PASEQ - { 0x05C1, "afii57804" }, // HEBREW POINT SHIN DOT - { 0x05C2, "afii57803" }, // HEBREW POINT SIN DOT - { 0x05C3, "afii57658" }, // HEBREW PUNCTUATION SOF PASUQ - { 0x05D0, "afii57664" }, // HEBREW LETTER ALEF - { 0x05D1, "afii57665" }, // HEBREW LETTER BET - { 0x05D2, "afii57666" }, // HEBREW LETTER GIMEL - { 0x05D3, "afii57667" }, // HEBREW LETTER DALET - { 0x05D4, "afii57668" }, // HEBREW LETTER HE - { 0x05D5, "afii57669" }, // HEBREW LETTER VAV - { 0x05D6, "afii57670" }, // HEBREW LETTER ZAYIN - { 0x05D7, "afii57671" }, // HEBREW LETTER HET - { 0x05D8, "afii57672" }, // HEBREW LETTER TET - { 0x05D9, "afii57673" }, // HEBREW LETTER YOD - { 0x05DA, "afii57674" }, // HEBREW LETTER FINAL KAF - { 0x05DB, "afii57675" }, // HEBREW LETTER KAF - { 0x05DC, "afii57676" }, // HEBREW LETTER LAMED - { 0x05DD, "afii57677" }, // HEBREW LETTER FINAL MEM - { 0x05DE, "afii57678" }, // HEBREW LETTER MEM - { 0x05DF, "afii57679" }, // HEBREW LETTER FINAL NUN - { 0x05E0, "afii57680" }, // HEBREW LETTER NUN - { 0x05E1, "afii57681" }, // HEBREW LETTER SAMEKH - { 0x05E2, "afii57682" }, // HEBREW LETTER AYIN - { 0x05E3, "afii57683" }, // HEBREW LETTER FINAL PE - { 0x05E4, "afii57684" }, // HEBREW LETTER PE - { 0x05E5, "afii57685" }, // HEBREW LETTER FINAL TSADI - { 0x05E6, "afii57686" }, // HEBREW LETTER TSADI - { 0x05E7, "afii57687" }, // HEBREW LETTER TQOF - { 0x05E8, "afii57688" }, // HEBREW LETTER RESH - { 0x05E9, "afii57689" }, // HEBREW LETTER SHIN - { 0x05EA, "afii57690" }, // HEBREW LETTER TAV - { 0x05F0, "afii57716" }, // HEBREW LIGATURE YIDDISH DOUBLE VAV - { 0x05F1, "afii57717" }, // HEBREW LIGATURE YIDDISH VAV YOD - { 0x05F2, "afii57718" }, // HEBREW LIGATURE YIDDISH DOUBLE YOD - { 0x060C, "afii57388" }, // ARABIC COMMA - { 0x061B, "afii57403" }, // ARABIC SEMICOLON - { 0x061F, "afii57407" }, // ARABIC QUESTION MARK - { 0x0621, "afii57409" }, // ARABIC LETTER HAMZA - { 0x0622, "afii57410" }, // ARABIC LETTER ALEF WITH MADDA ABOVE - { 0x0623, "afii57411" }, // ARABIC LETTER ALEF WITH HAMZA ABOVE - { 0x0624, "afii57412" }, // ARABIC LETTER WAW WITH HAMZA ABOVE - { 0x0625, "afii57413" }, // ARABIC LETTER ALEF WITH HAMZA BELOW - { 0x0626, "afii57414" }, // ARABIC LETTER YEH WITH HAMZA ABOVE - { 0x0627, "afii57415" }, // ARABIC LETTER ALEF - { 0x0628, "afii57416" }, // ARABIC LETTER BEH - { 0x0629, "afii57417" }, // ARABIC LETTER TEH MARBUTA - { 0x062A, "afii57418" }, // ARABIC LETTER TEH - { 0x062B, "afii57419" }, // ARABIC LETTER THEH - { 0x062C, "afii57420" }, // ARABIC LETTER JEEM - { 0x062D, "afii57421" }, // ARABIC LETTER HAH - { 0x062E, "afii57422" }, // ARABIC LETTER KHAH - { 0x062F, "afii57423" }, // ARABIC LETTER DAL - { 0x0630, "afii57424" }, // ARABIC LETTER THAL - { 0x0631, "afii57425" }, // ARABIC LETTER REH - { 0x0632, "afii57426" }, // ARABIC LETTER ZAIN - { 0x0633, "afii57427" }, // ARABIC LETTER SEEN - { 0x0634, "afii57428" }, // ARABIC LETTER SHEEN - { 0x0635, "afii57429" }, // ARABIC LETTER SAD - { 0x0636, "afii57430" }, // ARABIC LETTER DAD - { 0x0637, "afii57431" }, // ARABIC LETTER TAH - { 0x0638, "afii57432" }, // ARABIC LETTER ZAH - { 0x0639, "afii57433" }, // ARABIC LETTER AIN - { 0x063A, "afii57434" }, // ARABIC LETTER GHAIN - { 0x0640, "afii57440" }, // ARABIC TATWEEL - { 0x0641, "afii57441" }, // ARABIC LETTER FEH - { 0x0642, "afii57442" }, // ARABIC LETTER TQAF - { 0x0643, "afii57443" }, // ARABIC LETTER KAF - { 0x0644, "afii57444" }, // ARABIC LETTER LAM - { 0x0645, "afii57445" }, // ARABIC LETTER MEEM - { 0x0646, "afii57446" }, // ARABIC LETTER NOON - { 0x0647, "afii57470" }, // ARABIC LETTER HEH - { 0x0648, "afii57448" }, // ARABIC LETTER WAW - { 0x0649, "afii57449" }, // ARABIC LETTER ALEF MAKSURA - { 0x064A, "afii57450" }, // ARABIC LETTER YEH - { 0x064B, "afii57451" }, // ARABIC FATHATAN - { 0x064C, "afii57452" }, // ARABIC DAMMATAN - { 0x064D, "afii57453" }, // ARABIC KASRATAN - { 0x064E, "afii57454" }, // ARABIC FATHA - { 0x064F, "afii57455" }, // ARABIC DAMMA - { 0x0650, "afii57456" }, // ARABIC KASRA - { 0x0651, "afii57457" }, // ARABIC SHADDA - { 0x0652, "afii57458" }, // ARABIC SUKUN - { 0x0660, "afii57392" }, // ARABIC-INDIC DIGIT ZERO - { 0x0661, "afii57393" }, // ARABIC-INDIC DIGIT ONE - { 0x0662, "afii57394" }, // ARABIC-INDIC DIGIT TWO - { 0x0663, "afii57395" }, // ARABIC-INDIC DIGIT THREE - { 0x0664, "afii57396" }, // ARABIC-INDIC DIGIT FOUR - { 0x0665, "afii57397" }, // ARABIC-INDIC DIGIT FIVE - { 0x0666, "afii57398" }, // ARABIC-INDIC DIGIT SIX - { 0x0667, "afii57399" }, // ARABIC-INDIC DIGIT SEVEN - { 0x0668, "afii57400" }, // ARABIC-INDIC DIGIT EIGHT - { 0x0669, "afii57401" }, // ARABIC-INDIC DIGIT NINE - { 0x066A, "afii57381" }, // ARABIC PERCENT SIGN - { 0x066D, "afii63167" }, // ARABIC FIVE POINTED STAR - { 0x0679, "afii57511" }, // ARABIC LETTER TTEH - { 0x067E, "afii57506" }, // ARABIC LETTER PEH - { 0x0686, "afii57507" }, // ARABIC LETTER TCHEH - { 0x0688, "afii57512" }, // ARABIC LETTER DDAL - { 0x0691, "afii57513" }, // ARABIC LETTER RREH - { 0x0698, "afii57508" }, // ARABIC LETTER JEH - { 0x06A4, "afii57505" }, // ARABIC LETTER VEH - { 0x06AF, "afii57509" }, // ARABIC LETTER GAF - { 0x06BA, "afii57514" }, // ARABIC LETTER NOON GHUNNA - { 0x06D2, "afii57519" }, // ARABIC LETTER YEH BARREE - { 0x06D5, "afii57534" }, // ARABIC LETTER AE - { 0x1E80, "Wgrave" }, // LATIN CAPITAL LETTER W WITH GRAVE - { 0x1E81, "wgrave" }, // LATIN SMALL LETTER W WITH GRAVE - { 0x1E82, "Wacute" }, // LATIN CAPITAL LETTER W WITH ACUTE - { 0x1E83, "wacute" }, // LATIN SMALL LETTER W WITH ACUTE - { 0x1E84, "Wdieresis" }, // LATIN CAPITAL LETTER W WITH DIAERESIS - { 0x1E85, "wdieresis" }, // LATIN SMALL LETTER W WITH DIAERESIS - { 0x1EF2, "Ygrave" }, // LATIN CAPITAL LETTER Y WITH GRAVE - { 0x1EF3, "ygrave" }, // LATIN SMALL LETTER Y WITH GRAVE - { 0x200C, "afii61664" }, // ZERO WIDTH NON-JOINER - { 0x200D, "afii301" }, // ZERO WIDTH JOINER - { 0x200E, "afii299" }, // LEFT-TO-RIGHT MARK - { 0x200F, "afii300" }, // RIGHT-TO-LEFT MARK - { 0x2012, "figuredash" }, // FIGURE DASH - { 0x2013, "endash" }, // EN DASH - { 0x2014, "emdash" }, // EM DASH - { 0x2015, "afii00208" }, // HORIZONTAL BAR - { 0x2017, "underscoredbl" }, // DOUBLE LOW LINE - { 0x2018, "quoteleft" }, // LEFT SINGLE QUOTATION MARK - { 0x2019, "quoteright" }, // RIGHT SINGLE QUOTATION MARK - { 0x201A, "quotesinglbase" }, // SINGLE LOW-9 QUOTATION MARK - { 0x201B, "quotereversed" }, // SINGLE HIGH-REVERSED-9 QUOTATION MARK - { 0x201C, "quotedblleft" }, // LEFT DOUBLE QUOTATION MARK - { 0x201D, "quotedblright" }, // RIGHT DOUBLE QUOTATION MARK - { 0x201E, "quotedblbase" }, // DOUBLE LOW-9 QUOTATION MARK - { 0x2020, "dagger" }, // DAGGER - { 0x2021, "daggerdbl" }, // DOUBLE DAGGER - { 0x2022, "bullet" }, // BULLET - { 0x2024, "onedotenleader" }, // ONE DOT LEADER - { 0x2025, "twodotenleader" }, // TWO DOT LEADER - { 0x2026, "ellipsis" }, // HORIZONTAL ELLIPSIS - { 0x202C, "afii61573" }, // POP DIRECTIONAL FORMATTING - { 0x202D, "afii61574" }, // LEFT-TO-RIGHT OVERRIDE - { 0x202E, "afii61575" }, // RIGHT-TO-LEFT OVERRIDE - { 0x2030, "perthousand" }, // PER MILLE SIGN - { 0x2032, "minute" }, // PRIME - { 0x2033, "second" }, // DOUBLE PRIME - { 0x2039, "guilsinglleft" }, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - { 0x203A, "guilsinglright" }, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - { 0x203C, "exclamdbl" }, // DOUBLE EXCLAMATION MARK - { 0x2044, "fraction" }, // FRACTION SLASH - { 0x2070, "zerosuperior" }, // SUPERSCRIPT ZERO - { 0x2074, "foursuperior" }, // SUPERSCRIPT FOUR - { 0x2075, "fivesuperior" }, // SUPERSCRIPT FIVE - { 0x2076, "sixsuperior" }, // SUPERSCRIPT SIX - { 0x2077, "sevensuperior" }, // SUPERSCRIPT SEVEN - { 0x2078, "eightsuperior" }, // SUPERSCRIPT EIGHT - { 0x2079, "ninesuperior" }, // SUPERSCRIPT NINE - { 0x207D, "parenleftsuperior" }, // SUPERSCRIPT LEFT PARENTHESIS - { 0x207E, "parenrightsuperior" }, // SUPERSCRIPT RIGHT PARENTHESIS - { 0x207F, "nsuperior" }, // SUPERSCRIPT LATIN SMALL LETTER N - { 0x2080, "zeroinferior" }, // SUBSCRIPT ZERO - { 0x2081, "oneinferior" }, // SUBSCRIPT ONE - { 0x2082, "twoinferior" }, // SUBSCRIPT TWO - { 0x2083, "threeinferior" }, // SUBSCRIPT THREE - { 0x2084, "fourinferior" }, // SUBSCRIPT FOUR - { 0x2085, "fiveinferior" }, // SUBSCRIPT FIVE - { 0x2086, "sixinferior" }, // SUBSCRIPT SIX - { 0x2087, "seveninferior" }, // SUBSCRIPT SEVEN - { 0x2088, "eightinferior" }, // SUBSCRIPT EIGHT - { 0x2089, "nineinferior" }, // SUBSCRIPT NINE - { 0x208D, "parenleftinferior" }, // SUBSCRIPT LEFT PARENTHESIS - { 0x208E, "parenrightinferior" }, // SUBSCRIPT RIGHT PARENTHESIS - { 0x20A1, "colonmonetary" }, // COLON SIGN - { 0x20A3, "franc" }, // FRENCH FRANC SIGN - { 0x20A4, "lira" }, // LIRA SIGN - { 0x20A7, "peseta" }, // PESETA SIGN - { 0x20AA, "afii57636" }, // NEW SHETQEL SIGN - { 0x20AB, "dong" }, // DONG SIGN - { 0x20AC, "Euro" }, // EURO SIGN - { 0x2105, "afii61248" }, // CARE OF - { 0x2111, "Ifraktur" }, // BLACK-LETTER CAPITAL I - { 0x2113, "afii61289" }, // SCRIPT SMALL L - { 0x2116, "afii61352" }, // NUMERO SIGN - { 0x2118, "weierstrass" }, // SCRIPT CAPITAL P - { 0x211C, "Rfraktur" }, // BLACK-LETTER CAPITAL R - { 0x211E, "prescription" }, // PRESCRIPTION TAKE - { 0x2122, "trademark" }, // TRADE MARK SIGN - { 0x2126, "Omega" }, // OHM SIGN - { 0x212E, "estimated" }, // ESTIMATED SYMBOL - { 0x2135, "aleph" }, // ALEF SYMBOL - { 0x2153, "onethird" }, // VULGAR FRACTION ONE THIRD - { 0x2154, "twothirds" }, // VULGAR FRACTION TWO THIRDS - { 0x215B, "oneeighth" }, // VULGAR FRACTION ONE EIGHTH - { 0x215C, "threeeighths" }, // VULGAR FRACTION THREE EIGHTHS - { 0x215D, "fiveeighths" }, // VULGAR FRACTION FIVE EIGHTHS - { 0x215E, "seveneighths" }, // VULGAR FRACTION SEVEN EIGHTHS - { 0x2190, "arrowleft" }, // LEFTWARDS ARROW - { 0x2191, "arrowup" }, // UPWARDS ARROW - { 0x2192, "arrowright" }, // RIGHTWARDS ARROW - { 0x2193, "arrowdown" }, // DOWNWARDS ARROW - { 0x2194, "arrowboth" }, // LEFT RIGHT ARROW - { 0x2195, "arrowupdn" }, // UP DOWN ARROW - { 0x21A8, "arrowupdnbse" }, // UP DOWN ARROW WITH BASE - { 0x21B5, "carriagereturn" }, // DOWNWARDS ARROW WITH CORNER LEFTWARDS - { 0x21D0, "arrowdblleft" }, // LEFTWARDS DOUBLE ARROW - { 0x21D1, "arrowdblup" }, // UPWARDS DOUBLE ARROW - { 0x21D2, "arrowdblright" }, // RIGHTWARDS DOUBLE ARROW - { 0x21D3, "arrowdbldown" }, // DOWNWARDS DOUBLE ARROW - { 0x21D4, "arrowdblboth" }, // LEFT RIGHT DOUBLE ARROW - { 0x2200, "universal" }, // FOR ALL - { 0x2202, "partialdiff" }, // PARTIAL DIFFERENTIAL - { 0x2203, "existential" }, // THERE EXISTS - { 0x2205, "emptyset" }, // EMPTY SET - { 0x2206, "Delta" }, // INCREMENT - { 0x2207, "gradient" }, // NABLA - { 0x2208, "element" }, // ELEMENT OF - { 0x2209, "notelement" }, // NOT AN ELEMENT OF - { 0x220B, "suchthat" }, // CONTAINS AS MEMBER - { 0x220F, "product" }, // N-ARY PRODUCT - { 0x2211, "summation" }, // N-ARY SUMMATION - { 0x2212, "minus" }, // MINUS SIGN - { 0x2215, "fraction" }, // DIVISION SLASH;Duplicate - { 0x2217, "asteriskmath" }, // ASTERISK OPERATOR - { 0x2219, "periodcentered" }, // BULLET OPERATOR;Duplicate - { 0x221A, "radical" }, // SQUARE ROOT - { 0x221D, "proportional" }, // PROPORTIONAL TO - { 0x221E, "infinity" }, // INFINITY - { 0x221F, "orthogonal" }, // RIGHT ANGLE - { 0x2220, "angle" }, // ANGLE - { 0x2227, "logicaland" }, // LOGICAL AND - { 0x2228, "logicalor" }, // LOGICAL OR - { 0x2229, "intersection" }, // INTERSECTION - { 0x222A, "union" }, // UNION - { 0x222B, "integral" }, // INTEGRAL - { 0x2234, "therefore" }, // THEREFORE - { 0x223C, "similar" }, // TILDE OPERATOR - { 0x2245, "congruent" }, // APPROXIMATELY EQUAL TO - { 0x2248, "approxequal" }, // ALMOST EQUAL TO - { 0x2260, "notequal" }, // NOT EQUAL TO - { 0x2261, "equivalence" }, // IDENTICAL TO - { 0x2264, "lessequal" }, // LESS-THAN OR EQUAL TO - { 0x2265, "greaterequal" }, // GREATER-THAN OR EQUAL TO - { 0x2282, "propersubset" }, // SUBSET OF - { 0x2283, "propersuperset" }, // SUPERSET OF - { 0x2284, "notsubset" }, // NOT A SUBSET OF - { 0x2286, "reflexsubset" }, // SUBSET OF OR EQUAL TO - { 0x2287, "reflexsuperset" }, // SUPERSET OF OR EQUAL TO - { 0x2295, "circleplus" }, // CIRCLED PLUS - { 0x2297, "circlemultiply" }, // CIRCLED TIMES - { 0x22A5, "perpendicular" }, // UP TACK - { 0x22C5, "dotmath" }, // DOT OPERATOR - { 0x2302, "house" }, // HOUSE - { 0x2310, "revlogicalnot" }, // REVERSED NOT SIGN - { 0x2320, "integraltp" }, // TOP HALF INTEGRAL - { 0x2321, "integralbt" }, // BOTTOM HALF INTEGRAL - { 0x2329, "angleleft" }, // LEFT-POINTING ANGLE BRACKET - { 0x232A, "angleright" }, // RIGHT-POINTING ANGLE BRACKET - { 0x2500, "SF100000" }, // BOX DRAWINGS LIGHT HORIZONTAL - { 0x2502, "SF110000" }, // BOX DRAWINGS LIGHT VERTICAL - { 0x250C, "SF010000" }, // BOX DRAWINGS LIGHT DOWN AND RIGHT - { 0x2510, "SF030000" }, // BOX DRAWINGS LIGHT DOWN AND LEFT - { 0x2514, "SF020000" }, // BOX DRAWINGS LIGHT UP AND RIGHT - { 0x2518, "SF040000" }, // BOX DRAWINGS LIGHT UP AND LEFT - { 0x251C, "SF080000" }, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT - { 0x2524, "SF090000" }, // BOX DRAWINGS LIGHT VERTICAL AND LEFT - { 0x252C, "SF060000" }, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - { 0x2534, "SF070000" }, // BOX DRAWINGS LIGHT UP AND HORIZONTAL - { 0x253C, "SF050000" }, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - { 0x2550, "SF430000" }, // BOX DRAWINGS DOUBLE HORIZONTAL - { 0x2551, "SF240000" }, // BOX DRAWINGS DOUBLE VERTICAL - { 0x2552, "SF510000" }, // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE - { 0x2553, "SF520000" }, // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE - { 0x2554, "SF390000" }, // BOX DRAWINGS DOUBLE DOWN AND RIGHT - { 0x2555, "SF220000" }, // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE - { 0x2556, "SF210000" }, // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE - { 0x2557, "SF250000" }, // BOX DRAWINGS DOUBLE DOWN AND LEFT - { 0x2558, "SF500000" }, // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE - { 0x2559, "SF490000" }, // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE - { 0x255A, "SF380000" }, // BOX DRAWINGS DOUBLE UP AND RIGHT - { 0x255B, "SF280000" }, // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE - { 0x255C, "SF270000" }, // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE - { 0x255D, "SF260000" }, // BOX DRAWINGS DOUBLE UP AND LEFT - { 0x255E, "SF360000" }, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - { 0x255F, "SF370000" }, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - { 0x2560, "SF420000" }, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT - { 0x2561, "SF190000" }, // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE - { 0x2562, "SF200000" }, // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - { 0x2563, "SF230000" }, // BOX DRAWINGS DOUBLE VERTICAL AND LEFT - { 0x2564, "SF470000" }, // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - { 0x2565, "SF480000" }, // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE - { 0x2566, "SF410000" }, // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - { 0x2567, "SF450000" }, // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - { 0x2568, "SF460000" }, // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - { 0x2569, "SF400000" }, // BOX DRAWINGS DOUBLE UP AND HORIZONTAL - { 0x256A, "SF540000" }, // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE - { 0x256B, "SF530000" }, // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - { 0x256C, "SF440000" }, // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL - { 0x2580, "upblock" }, // UPPER HALF BLOCK - { 0x2584, "dnblock" }, // LOWER HALF BLOCK - { 0x2588, "block" }, // FULL BLOCK - { 0x258C, "lfblock" }, // LEFT HALF BLOCK - { 0x2590, "rtblock" }, // RIGHT HALF BLOCK - { 0x2591, "ltshade" }, // LIGHT SHADE - { 0x2592, "shade" }, // MEDIUM SHADE - { 0x2593, "dkshade" }, // DARK SHADE - { 0x25A0, "filledbox" }, // BLACK SQUARE - { 0x25A1, "H22073" }, // WHITE SQUARE - { 0x25AA, "H18543" }, // BLACK SMALL SQUARE - { 0x25AB, "H18551" }, // WHITE SMALL SQUARE - { 0x25AC, "filledrect" }, // BLACK RECTANGLE - { 0x25B2, "triagup" }, // BLACK UP-POINTING TRIANGLE - { 0x25BA, "triagrt" }, // BLACK RIGHT-POINTING POINTER - { 0x25BC, "triagdn" }, // BLACK DOWN-POINTING TRIANGLE - { 0x25C4, "triaglf" }, // BLACK LEFT-POINTING POINTER - { 0x25CA, "lozenge" }, // LOZENGE - { 0x25CB, "circle" }, // WHITE CIRCLE - { 0x25CF, "H18533" }, // BLACK CIRCLE - { 0x25D8, "invbullet" }, // INVERSE BULLET - { 0x25D9, "invcircle" }, // INVERSE WHITE CIRCLE - { 0x25E6, "openbullet" }, // WHITE BULLET - { 0x263A, "smileface" }, // WHITE SMILING FACE - { 0x263B, "invsmileface" }, // BLACK SMILING FACE - { 0x263C, "sun" }, // WHITE SUN WITH RAYS - { 0x2640, "female" }, // FEMALE SIGN - { 0x2642, "male" }, // MALE SIGN - { 0x2660, "spade" }, // BLACK SPADE SUIT - { 0x2663, "club" }, // BLACK CLUB SUIT - { 0x2665, "heart" }, // BLACK HEART SUIT - { 0x2666, "diamond" }, // BLACK DIAMOND SUIT - { 0x266A, "musicalnote" }, // EIGHTH NOTE - { 0x266B, "musicalnotedbl" }, // BEAMED EIGHTH NOTES - // The names below are in the PU area of Unicode, but needed to get a correct mapping of the symbol font - { 0xF6D9, "copyrightserif" }, - { 0xF6DA, "registerserif" }, - { 0xF6DB, "trademarkserif" }, - { 0xF8E5, "radicalex" }, - { 0xF8E6, "arrowvertex" }, - { 0xF8E7, "arrowhorizex" }, - { 0xF8E8, "registersans" }, - { 0xF8E9, "copyrightsans" }, - { 0xF8EA, "trademarksans" }, - { 0xF8EB, "parenlefttp" }, - { 0xF8EC, "parenleftex" }, - { 0xF8ED, "parenleftbt" }, - { 0xF8EE, "bracketlefttp" }, - { 0xF8EF, "bracketleftex" }, - { 0xF8F0, "bracketleftbt" }, - { 0xF8F1, "bracelefttp" }, - { 0xF8F2, "braceleftmid" }, - { 0xF8F3, "braceleftbt" }, - { 0xF8F4, "braceex" }, - { 0xF8F5, "integralex" }, - { 0xF8F6, "parenrighttp" }, - { 0xF8F7, "parenrightex" }, - { 0xF8F8, "parenrightbt" }, - { 0xF8F9, "bracketrighttp" }, - { 0xF8FA, "bracketrightex" }, - { 0xF8FB, "bracketrightbt" }, - { 0xF8FC, "bracerighttp" }, - { 0xF8FD, "bracerightmid" }, - { 0xF8FE, "bracerightbt" }, - // End of extensions needed for symbols - { 0xFB00, "ff" }, // LATIN SMALL LIGATURE FF - { 0xFB01, "fi" }, // LATIN SMALL LIGATURE FI - { 0xFB02, "fl" }, // LATIN SMALL LIGATURE FL - { 0xFB03, "ffi" }, // LATIN SMALL LIGATURE FFI - { 0xFB04, "ffl" }, // LATIN SMALL LIGATURE FFL - { 0xFB1F, "afii57705" }, // HEBREW LIGATURE YIDDISH YOD YOD PATAH - { 0xFB2A, "afii57694" }, // HEBREW LETTER SHIN WITH SHIN DOT - { 0xFB2B, "afii57695" }, // HEBREW LETTER SHIN WITH SIN DOT - { 0xFB35, "afii57723" }, // HEBREW LETTER VAV WITH DAGESH - { 0xFB4B, "afii57700" }, // HEBREW LETTER VAV WITH HOLAM - // end of stuff from glyphlist.txt - { 0xFFFF, 0 } -}; - -// --------------------------------------------------------------------- -// postscript font substitution dictionary. We assume every postscript printer has at least -// Helvetica, Times, Courier and Symbol - -struct psfont { - const char *psname; - float slant; - float xscale; -}; - -static const psfont Arial[] = { - {"Arial", 0, 84.04 }, - { "Arial-Italic", 0, 84.04 }, - { "Arial-Bold", 0, 88.65 }, - { "Arial-BoldItalic", 0, 88.65 } -}; - -static const psfont AvantGarde[] = { - { "AvantGarde-Book", 0, 87.43 }, - { "AvantGarde-BookOblique", 0, 88.09 }, - { "AvantGarde-Demi", 0, 88.09 }, - { "AvantGarde-DemiOblique", 0, 87.43 }, -}; - -static const psfont Bookman [] = { - { "Bookman-Light", 0, 93.78 }, - { "Bookman-LightItalic", 0, 91.42 }, - { "Bookman-Demi", 0, 99.86 }, - { "Bookman-DemiItalic", 0, 101.54 } -}; - -static const psfont Charter [] = { - { "CharterBT-Roman", 0, 84.04 }, - { "CharterBT-Italic", 0.0, 81.92 }, - { "CharterBT-Bold", 0, 88.99 }, - { "CharterBT-BoldItalic", 0.0, 88.20 } -}; - -static const psfont Courier [] = { - { "Courier", 0, 100. }, - { "Courier-Oblique", 0, 100. }, - { "Courier-Bold", 0, 100. }, - { "Courier-BoldOblique", 0, 100. } -}; - -static const psfont Garamond [] = { - { "Garamond-Antiqua", 0, 78.13 }, - { "Garamond-Kursiv", 0, 78.13 }, - { "Garamond-Halbfett", 0, 78.13 }, - { "Garamond-KursivHalbfett", 0, 78.13 } -}; - -static const psfont GillSans [] = { // ### some estimated value for xstretch - { "GillSans", 0, 82 }, - { "GillSans-Italic", 0, 82 }, - { "GillSans-Bold", 0, 82 }, - { "GillSans-BoldItalic", 0, 82 } -}; - -static const psfont Helvetica [] = { - { "Helvetica", 0, 84.04 }, - { "Helvetica-Oblique", 0, 84.04 }, - { "Helvetica-Bold", 0, 88.65 }, - { "Helvetica-BoldOblique", 0, 88.65 } -}; - -static const psfont Letter [] = { - { "LetterGothic", 0, 83.32 }, - { "LetterGothic-Italic", 0, 83.32 }, - { "LetterGothic-Bold", 0, 83.32 }, - { "LetterGothic-Bold", 0.2, 83.32 } -}; - -static const psfont LucidaSans [] = { - { "LucidaSans", 0, 94.36 }, - { "LucidaSans-Oblique", 0, 94.36 }, - { "LucidaSans-Demi", 0, 98.10 }, - { "LucidaSans-DemiOblique", 0, 98.08 } -}; - -static const psfont LucidaSansTT [] = { - { "LucidaSans-Typewriter", 0, 100.50 }, - { "LucidaSans-TypewriterOblique", 0, 100.50 }, - { "LucidaSans-TypewriterBold", 0, 100.50 }, - { "LucidaSans-TypewriterBoldOblique", 0, 100.50 } -}; - -static const psfont LucidaBright [] = { - { "LucidaBright", 0, 93.45 }, - { "LucidaBright-Italic", 0, 91.98 }, - { "LucidaBright-Demi", 0, 96.22 }, - { "LucidaBright-DemiItalic", 0, 96.98 } -}; - -static const psfont Palatino [] = { - { "Palatino-Roman", 0, 82.45 }, - { "Palatino-Italic", 0, 76.56 }, - { "Palatino-Bold", 0, 83.49 }, - { "Palatino-BoldItalic", 0, 81.51 } -}; - -static const psfont Symbol [] = { - { "Symbol", 0, 82.56 }, - { "Symbol", 0.2, 82.56 }, - { "Symbol", 0, 82.56 }, - { "Symbol", 0.2, 82.56 } -}; - -static const psfont Tahoma [] = { - { "Tahoma", 0, 83.45 }, - { "Tahoma", 0.2, 83.45 }, - { "Tahoma-Bold", 0, 95.59 }, - { "Tahoma-Bold", 0.2, 95.59 } -}; - -static const psfont Times [] = { - { "Times-Roman", 0, 82.45 }, - { "Times-Italic", 0, 82.45 }, - { "Times-Bold", 0, 82.45 }, - { "Times-BoldItalic", 0, 82.45 } -}; - -static const psfont Verdana [] = { - { "Verdana", 0, 96.06 }, - { "Verdana-Italic", 0, 96.06 }, - { "Verdana-Bold", 0, 107.12 }, - { "Verdana-BoldItalic", 0, 107.10 } -}; - -static const psfont Utopia [] = { // ### - { "Utopia-Regular", 0, 84.70 }, - { "Utopia-Regular", 0.2, 84.70 }, - { "Utopia-Bold", 0, 88.01 }, - { "Utopia-Bold", 0.2, 88.01 } -}; - -static const psfont * const SansSerifReplacements[] = { - Helvetica, 0 - }; -static const psfont * const SerifReplacements[] = { - Times, 0 - }; -static const psfont * const FixedReplacements[] = { - Courier, 0 - }; -static const psfont * const TahomaReplacements[] = { - Verdana, AvantGarde, Helvetica, 0 - }; -static const psfont * const VerdanaReplacements[] = { - Tahoma, AvantGarde, Helvetica, 0 - }; - -static const struct { - const char * input; // spaces are stripped in here, and everything lowercase - const psfont * ps; - const psfont *const * replacements; -} postscriptFonts [] = { - { "arial", Arial, SansSerifReplacements }, - { "arialmt", Arial, SansSerifReplacements }, - { "arialunicodems", Arial, SansSerifReplacements }, - { "avantgarde", AvantGarde, SansSerifReplacements }, - { "bookman", Bookman, SerifReplacements }, - { "charter", Charter, SansSerifReplacements }, - { "bitstreamcharter", Charter, SansSerifReplacements }, - { "bitstreamcyberbit", Times, SerifReplacements }, // ### - { "courier", Courier, 0 }, - { "couriernew", Courier, 0 }, - { "fixed", Courier, 0 }, - { "garamond", Garamond, SerifReplacements }, - { "gillsans", GillSans, SansSerifReplacements }, - { "helvetica", Helvetica, 0 }, - { "letter", Letter, FixedReplacements }, - { "lucida", LucidaSans, SansSerifReplacements }, - { "lucidasans", LucidaSans, SansSerifReplacements }, - { "lucidabright", LucidaBright, SerifReplacements }, - { "lucidasanstypewriter", LucidaSansTT, FixedReplacements }, - { "luciduxsans", LucidaSans, SansSerifReplacements }, - { "luciduxserif", LucidaBright, SerifReplacements }, - { "luciduxmono", LucidaSansTT, FixedReplacements }, - { "palatino", Palatino, SerifReplacements }, - { "symbol", Symbol, 0 }, - { "tahoma", Tahoma, TahomaReplacements }, - { "terminal", Courier, 0 }, - { "times", Times, 0 }, - { "timesnewroman", Times, 0 }, - { "verdana", Verdana, VerdanaReplacements }, - { "utopia", Utopia, SerifReplacements }, - { 0, 0, 0 } -}; - - -// ------------------------------End of static data ---------------------------------- - -// make sure DSC comments are not longer than 255 chars per line. -static TQString wrapDSC( const TQString &str ) -{ - TQString dsc = str.simplifyWhiteSpace(); - const uint wrapAt = 254; - TQString wrapped; - if ( dsc.length() < wrapAt ) - wrapped = dsc; - else { - wrapped = dsc.left( wrapAt ); - TQString tmp = dsc.mid( wrapAt ); - while ( tmp.length() > wrapAt-3 ) { - wrapped += "\n%%+" + tmp.left( wrapAt-3 ); - tmp = tmp.mid( wrapAt-3 ); - } - wrapped += "\n%%+" + tmp; - } - return wrapped + "\n"; -} - -static TQString toString( const float num ) -{ - return TQString::number( num, 'f', 3 ); -} - -// ----------------------------- Internal class declarations ----------------------------- - -class TQPSPrinterFontPrivate; - -class TQPSPrinterPrivate { -public: - TQPSPrinterPrivate( TQPrinter *prt, int filedes ); - ~TQPSPrinterPrivate(); - - void matrixSetup( TQPainter * ); - void clippingSetup( TQPainter * ); - void setClippingOff( TQPainter * ); - void orientationSetup(); - void resetDrawingTools( TQPainter * ); - void emitHeader( bool finished ); - void setFont( const TQFont &, int script ); - void drawImage( TQPainter *, float x, float y, float w, float h, const TQImage &img, const TQImage &mask ); - void initPage( TQPainter *paint ); - void flushPage( bool last = FALSE ); - - TQPrinter *printer; - int pageCount; - bool dirtyMatrix; - bool dirtyNewPage; - bool epsf; - TQString fontsUsed; - - // outstream is the stream the build up pages are copied to. It points to buffer - // at the start, and is reset to use the outDevice after emitHeader has been called. - TQTextStream outStream; - - // stores the descriptions of the first pages. outStream operates on this buffer - // until we call emitHeader - TQBuffer *buffer; - int pagesInBuffer; - - // the device the output is in the end streamed to. - TQIODevice * outDevice; - int fd; - - // buffer for the current page. Needed becaus we might have page fonts. - TQBuffer *pageBuffer; - TQTextStream pageStream; - - TQDict headerFontNames; - TQDict pageFontNames; - TQDict fonts; - TQPSPrinterFontPrivate *currentFontFile; - int headerFontNumber; - int pageFontNumber; - TQBuffer * fontBuffer; - TQTextStream fontStream; - bool dirtyClipping; - bool firstClipOnPage; - TQRect boundingBox; - TQImage * savedImage; - TQPen cpen; - TQBrush cbrush; - bool dirtypen; - bool dirtybrush; - TQColor bkColor; - bool dirtyBkColor; - TQt::BGMode bkMode; - bool dirtyBkMode; -#ifndef TQT_NO_TEXTCODEC - TQTextCodec * currentFontCodec; -#endif - TQString currentFont; - TQFontMetrics fm; - int textY; - TQFont currentUsed; - int scriptUsed; - TQFont currentSet; - float scale; - - TQStringList fontpath; -}; - - -class TQPSPrinterFontPrivate { -public: - TQPSPrinterFontPrivate(); - virtual ~TQPSPrinterFontPrivate() {} - virtual TQString postScriptFontName() { return psname; } - virtual TQString defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, - TQPSPrinterPrivate *d ); - virtual void download(TQTextStream& s, bool global); - virtual void drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, - const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint); - virtual unsigned short mapUnicode( unsigned short unicode ); - void downloadMapping( TQTextStream &s, bool global ); - TQString glyphName( unsigned short glyphindex, bool *glyphSet = 0 ); - virtual void restore(); - - virtual unsigned short unicode_for_glyph(int glyphindex) { return glyphindex; } - virtual unsigned short glyph_for_unicode(unsigned short unicode) { return unicode; } - unsigned short insertIntoSubset( unsigned short unicode ); - virtual bool embedded() { return FALSE; } - - bool operator == ( const TQPSPrinterFontPrivate &other ) { - return other.psname == psname; - } - inline void setSymbol() { symbol = TRUE; } - -protected: - TQString psname; - TQStringList replacementList; - - TQMap subset; // unicode subset in the global font - TQMap page_subset; // subset added in this page - int subsetCount; - int pageSubsetCount; - bool global_dict; - bool downloaded; - bool symbol; -}; - -// ------------------- end of class declarations --------------------------- - -// -------------------------------------------------------------- -// beginning of font related methods -// -------------------------------------------------------------- - - -static int getPsFontType( const TQFontEngine *fe ) -{ - int weight = fe->fontDef.weight; - bool italic = fe->fontDef.italic; - - int type = 0; // used to look up in the psname array - // get the right modification, or build something - if ( weight > TQFont::Normal && italic ) - type = 3; - else if ( weight > TQFont::Normal ) - type = 2; - else if ( italic ) - type = 1; - return type; -} - -static int addPsFontNameExtension( const TQFontEngine *fe, TQString &ps, const psfont *psf = 0 ) -{ - int type = getPsFontType( fe ); - - if ( psf ) { - ps = TQString::fromLatin1( psf[type].psname ); - } else { - switch ( type ) { - case 1: - ps.append( TQString::fromLatin1("-Italic") ); - break; - case 2: - ps.append( TQString::fromLatin1("-Bold") ); - break; - case 3: - ps.append( TQString::fromLatin1("-BoldItalic") ); - break; - case 0: - default: - break; - } - } - return type; -} - -static TQString makePSFontName( const TQFontEngine *fe, int *listpos = 0, int *ftype = 0 ) -{ - TQString ps; - int i; - - TQString family = fe->fontDef.family.lower(); - - // try to make a "good" postscript name - ps = family.simplifyWhiteSpace(); - i = 0; - while( (unsigned int)i < ps.length() ) { - if ( i != 0 && ps[i] == '[') { - if ( ps[i-1] == ' ' ) - ps.truncate (i-1); - else - ps.truncate (i); - break; - } - if ( i == 0 || ps[i-1] == ' ' ) { - ps[i] = ps[i].upper(); - if ( i ) - ps.remove( i-1, 1 ); - else - i++; - } else { - i++; - } - } - - if ( ps.isEmpty() ) - ps = "Helvetica"; - - // see if the table has a better name - i = 0; - TQString lowerName = ps.lower(); - while( postscriptFonts[i].input && - postscriptFonts[i].input != lowerName ) - i++; - const psfont *psf = postscriptFonts[i].ps; - - int type = addPsFontNameExtension( fe, ps, psf ); - - if ( listpos ) - *listpos = i; - if ( ftype ) - *ftype = type; - return ps; -} - -static void appendReplacements( TQStringList &list, const psfont * const * replacements, int type, float xscale = 100. ) -{ - // iterate through the replacement fonts - while ( *replacements ) { - const psfont *psf = *replacements; - TQString ps = "[ /" + TQString::fromLatin1( psf[type].psname ) + " " + - toString( xscale / psf[type].xscale ) + " " + - toString( psf[type].slant ) + " ]"; - list.append( ps ); - ++replacements; - } -} - -static TQStringList makePSFontNameList( const TQFontEngine *fe, const TQString &psname = TQString::null, bool useNameForLookup = FALSE ) -{ - int i; - int type; - TQStringList list; - TQString ps = psname; - - if ( !ps.isEmpty() && !useNameForLookup ) { - TQString best = "[ /" + ps + " 1.0 0.0 ]"; - list.append( best ); - } - - ps = makePSFontName( fe, &i, &type ); - - const psfont *psf = postscriptFonts[i].ps; - const psfont * const * replacements = postscriptFonts[i].replacements; - float xscale = 100; - if ( psf ) { - // xscale for the "right" font is always 1. We scale the replacements... - xscale = psf->xscale; - ps = "[ /" + TQString::fromLatin1( psf[type].psname ) + " 1.0 " + - toString( psf[type].slant ) + " ]"; - } else { - ps = "[ /" + ps + " 1.0 0.0 ]"; - // only add default replacement fonts in case this font was unknown. - if ( fe->fontDef.fixedPitch ) { - replacements = FixedReplacements; - } else { - replacements = SansSerifReplacements; - // 100 is courier, but most fonts are not as wide as courier. Using 100 - // here would make letters overlap for some fonts. This value is empirical. - xscale = 83; - } - } - list.append( ps ); - - if ( replacements ) - appendReplacements( list, replacements, type, xscale); - return list; -} - -static void emitPSFontNameList( TQTextStream &s, const TQString &psname, const TQStringList &list ) -{ - s << "/" << psname << "List [\n"; - s << list.join("\n "); - s << "\n] d\n"; -} - -static inline float pointSize( const TQFont &f, float scale ) -{ - float psize; - if ( f.pointSize() != -1 ) - psize = f.pointSize()/scale; - else - psize = f.pixelSize(); - return psize; -} - - -// ========================== FONT CLASSES =============== - - -TQPSPrinterFontPrivate::TQPSPrinterFontPrivate() -{ - global_dict = FALSE; - downloaded = FALSE; - symbol = FALSE; - // map 0 to .notdef - subset.insert( 0, 0 ); - subsetCount = 1; - pageSubsetCount = 0; -} - -unsigned short TQPSPrinterFontPrivate::insertIntoSubset( unsigned short u ) -{ - unsigned short retval = 0; - if ( subset.find(u) == subset.end() ) { - if ( !downloaded ) { // we need to add to the page subset - subset.insert( u, subsetCount ); // mark it as used - //printf("GLOBAL SUBSET ADDED %04x = %04x\n",u, subsetCount); - retval = subsetCount; - subsetCount++; - } else if ( page_subset.find(u) == page_subset.end() ) { - page_subset.insert( u, pageSubsetCount ); // mark it as used - //printf("PAGE SUBSET ADDED %04x = %04x\n",u, pageSubsetCount); - retval = pageSubsetCount + (subsetCount/256 + 1) * 256; - pageSubsetCount++; - } - } else { - tqWarning("TQPSPrinterFont::internal error"); - } - return retval; -} - -void TQPSPrinterFontPrivate::restore() -{ - page_subset.clear(); - pageSubsetCount = 0; - //tqDebug("restore for font %s\n",psname.latin1()); -} - -static inline const char *toHex( uchar u ) -{ - static char hexVal[3]; - int i = 1; - while ( i >= 0 ) { - ushort hex = (u & 0x000f); - if ( hex < 0x0a ) - hexVal[i] = '0'+hex; - else - hexVal[i] = 'A'+(hex-0x0a); - u = u >> 4; - i--; - } - hexVal[2] = '\0'; - return hexVal; -} - -static inline const char *toHex( ushort u ) -{ - static char hexVal[5]; - int i = 3; - while ( i >= 0 ) { - ushort hex = (u & 0x000f); - if ( hex < 0x0a ) - hexVal[i] = '0'+hex; - else - hexVal[i] = 'A'+(hex-0x0a); - u = u >> 4; - i--; - } - hexVal[4] = '\0'; - return hexVal; -} - -static inline const char * toInt( int i ) -{ - static char intVal[20]; - intVal[19] = 0; - int pos = 19; - if ( i == 0 ) { - intVal[--pos] = '0'; - } else { - bool neg = FALSE; - if ( i < 0 ) { - neg = TRUE; - i = -i; - } - while ( i ) { - int dec = i%10; - intVal[--pos] = '0'+dec; - i /= 10; - } - if ( neg ) - intVal[--pos] = '-'; - } - return intVal+pos; -} - -void TQPSPrinterFontPrivate::drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, - const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint) -{ - int len = engine->length( item ); - TQScriptItem &si = engine->items[item]; - - int x = p.x() + si.x; - int y = p.y() + si.y; - if ( y != d->textY || d->textY == 0 ) - stream << y << " Y"; - d->textY = y; - - stream << "<"; - if ( si.analysis.bidiLevel % 2 ) { - for ( int i = len-1; i >=0; i-- ) - stream << toHex( mapUnicode(text.unicode()[i].unicode()) ); - } else { - for ( int i = 0; i < len; i++ ) - stream << toHex( mapUnicode(text.unicode()[i].unicode()) ); - } - stream << ">"; - - stream << si.width << " " << x; - - if ( paint->font().underline() ) - stream << ' ' << y + d->fm.underlinePos() + d->fm.lineWidth() - << " " << d->fm.lineWidth() << " Tl"; - if ( paint->font().strikeOut() ) - stream << ' ' << y + d->fm.strikeOutPos() - << " " << d->fm.lineWidth() << " Tl"; - stream << " AT\n"; - -} - - -TQString TQPSPrinterFontPrivate::defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, - TQPSPrinterPrivate *d ) -{ - TQString fontName; - fontName.sprintf( "/%s-Uni", ps.latin1()); - - if ( d->buffer ) { - ++d->headerFontNumber; - d->fontStream << "/F" << d->headerFontNumber << " " - << pointSize( f, d->scale ) << fontName << " DF\n"; - fontName.sprintf( "F%d", d->headerFontNumber ); - d->headerFontNames.insert( key, new TQString( fontName ) ); - } else { - ++d->pageFontNumber; - stream << "/F" << d->pageFontNumber << " " - << pointSize( f, d->scale ) << fontName << " DF\n"; - fontName.sprintf( "F%d", d->pageFontNumber ); - d->pageFontNames.insert( key, new TQString( fontName ) ); - } - return fontName; -} - -unsigned short TQPSPrinterFontPrivate::mapUnicode( unsigned short unicode ) -{ - TQMap::iterator res; - res = subset.find( unicode ); - unsigned short offset = 0; - bool found = FALSE; - if ( res != subset.end() ) { - found = TRUE; - } else { - if ( downloaded ) { - res = page_subset.find( unicode ); - offset = (subsetCount/256 + 1) * 256; - if ( res != page_subset.end() ) - found = TRUE; - } - } - if ( !found ) { - return insertIntoSubset( unicode ); - } - //tqDebug("mapping unicode %x to %x", unicode, offset+*res); - return offset + *res; -} - -// This map is used for symbol fonts to get the correct glyph names for the latin range -static const unsigned short symbol_map[0x100] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220b, - 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - - 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393, - 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f, - 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9, - 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f, - 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3, - 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf, - 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9, - 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f, - - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, - 0x20ac, 0x03d2, 0x2023, 0x2264, 0x2044, 0x221e, 0x0192, 0x2263, - 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193, - 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022, - 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5, - - 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229, - 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209, - 0x2220, 0x2207, 0xf6da, 0xf6d9, 0xf6db, 0x220f, 0x221a, 0x22c5, - 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3, - 0x25ca, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec, - 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4, - 0x0000, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7, - 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x0000, -}; - -TQString TQPSPrinterFontPrivate::glyphName( unsigned short glyphindex, bool *glyphSet ) -{ - TQString glyphname; - int l = 0; - unsigned short unicode = unicode_for_glyph( glyphindex ); - if (symbol && unicode < 0x100) { - // map from latin1 to symbol - unicode = symbol_map[unicode]; - } - if ( !unicode && glyphindex ) { - glyphname = "gl"; - glyphname += toHex( glyphindex ); - } else { - while( unicodetoglyph[l].u < unicode ) - l++; - if ( unicodetoglyph[l].u == unicode ) { - glyphname = unicodetoglyph[l].g; - if ( glyphSet ) { - int other = 0; - switch ( unicode ) { - // some glyph names are duplicate in postscript. Make sure we give the - // duplicate a different name to avoid infinite recursion - case 0x0394: - other = 0x2206; - break; - case 0x03a9: - other = 0x2126; - break; - case 0x0162: - other = 0x021a; - break; - case 0x2215: - other = 0x2044; - break; - case 0x00ad: - other = 0x002d; - break; - case 0x02c9: - other = 0x00af; - break; - case 0x03bc: - other = 0x00b5; - break; - case 0x2219: - other = 0x00b7; - break; - case 0x00a0: - other = 0x0020; - break; - case 0x0163: - other = 0x021b; - break; - default: - break; - } - if ( other ) { - int oglyph = glyph_for_unicode( other ); - if( oglyph && oglyph != glyphindex && glyphSet[oglyph] ) { - glyphname = "uni"; - glyphname += toHex( unicode ); - } - } - } - } else { - glyphname = "uni"; - glyphname += toHex( unicode ); - } - } - return glyphname; -} - -void TQPSPrinterFontPrivate::download(TQTextStream &s, bool global) -{ - //printf("defining mapping for printer font %s\n",psname.latin1()); - downloadMapping( s, global ); -} - -void TQPSPrinterFontPrivate::downloadMapping( TQTextStream &s, bool global ) -{ - uchar rangeOffset = 0; - uchar numRanges = (uchar)(subsetCount/256 + 1); - uchar range; - TQMap *subsetDict = ⊂ - if ( !global ) { - rangeOffset = numRanges; - numRanges = pageSubsetCount/256 + 1; - subsetDict = &page_subset; - } - // build up inverse table - unsigned short *inverse = new unsigned short[numRanges * 256]; - memset( inverse, 0, numRanges * 256 * sizeof( unsigned short ) ); - - TQMap::iterator it; - for ( it = subsetDict->begin(); it != subsetDict->end(); ++it) { - const unsigned short &mapped = *it; - inverse[mapped] = it.key(); - } - - TQString vector; - TQString glyphname; - - for (range=0; range < numRanges; range++) { - //printf("outputing range %04x\n",range*256); - vector = "%% Font Page "; - vector += toHex((uchar)(range + rangeOffset)); - vector += "\n/"; - vector += psname; - vector += "-ENC-"; - vector += toHex((uchar)(range + rangeOffset)); - vector += " [\n"; - - TQString line; - for(int k=0; k<256; k++ ) { - int c = range*256 + k; - unsigned short glyph = inverse[c]; - glyphname = glyphName( glyph ); - if ( line.length() + glyphname.length() > 76 ) { - vector += line; - vector += "\n"; - line = ""; - } - line += "/" + glyphname; - } - vector += line; - vector += "] def\n"; - s << vector; - } - - delete [] inverse; - - // DEFINE BASE FONTS - - for (range=0; range < numRanges; range++) { - s << "/"; - s << psname; - s << "-Uni-"; - s << toHex((uchar)(range + rangeOffset)); - s << " "; - s << psname; - s << "-ENC-"; - s << toHex((uchar)(range + rangeOffset)); - if ( embedded() && embedFonts ) { - s << " /"; - s << psname; - s << " MFEmb\n"; - } else { - s << " " << psname << "List"; - s << " MF\n"; - } - } - - // === write header === - // int VMMin; - // int VMMax; - - s << wrapDSC( "%%BeginFont: " + psname ) - << "%!PS-AdobeFont-1.0 Composite Font\n" - << wrapDSC( "%%FontName: " + psname + "-Uni" ) - << "%%Creator: Composite font created by TQt\n"; - - /* Start the dictionary which will eventually */ - /* become the font. */ - s << "25 dict begin\n"; // need to verify. Sivan - - s << "/FontName /"; - s << psname; - s << "-Uni"; - s << " def\n"; - s << "/PaintType 0 def\n"; - - // This is concatenated with the base fonts, so it should perform - // no transformation. Sivan - s << "/FontMatrix[1 0 0 1 0 0]def\n"; - - s << "/FontType "; - s << 0; - s << " def\n"; - - // now come composite font structures - // FMapTypes: - // 2: 8/8, 8 bits select the font, 8 the glyph - - s << "/FMapType 2 def\n"; - - // The encoding in a composite font is used for indirection. - // Every char is split into a font-number and a character-selector. - // PostScript prints glyph number character-selector from the font - // FDepVector[ Encoding[ font-number ] ]. - - s << "/Encoding ["; - for (range=0; range < rangeOffset + numRanges; range++) { - if (range % 16 == 0) - s << "\n"; - else - s << " "; - s << range; - } - s << "]def\n"; - - // Descendent fonts - - s << "/FDepVector [\n"; - for (range=0; range < rangeOffset + numRanges; range++) { - s << "/"; - s << psname; - s << "-Uni-"; - s << toHex( range ); - s << " findfont\n"; - } - s << "]def\n"; - - // === trailer === - - s << "FontName currentdict end definefont pop\n"; - s << "%%EndFont\n"; -} - - -// ================== TTF ==================== - -typedef TQ_UINT8 BYTE; -typedef TQ_UINT16 USHORT; -typedef TQ_UINT16 uFWord; -typedef TQ_INT16 SHORT; -typedef TQ_INT16 FWord; -typedef TQ_UINT32 ULONG; -typedef TQ_INT32 FIXED; - -typedef struct { - TQ_INT16 whole; - TQ_UINT16 fraction; -} Fixed; // 16.16 bit fixed-point number - -static float f2dot14( ushort s ) -{ - float f = ((float)( s & 0x3fff ))/ 16384.; - f += (s & 0x8000) ? ( (s & 0x4000) ? -1 : -2 ) : ( (s & 0x4000) ? 1 : 0 ); - return f; -} - -typedef struct { - int* epts_ctr; /* array of contour endpoints */ - int num_pts, num_ctr; /* number of points, number of coutours */ - FWord* xcoor, *ycoor; /* arrays of x and y coordinates */ - BYTE* tt_flags; /* array of TrueType flags */ - double* area_ctr; - char* check_ctr; - int* ctrset; /* in contour index followed by out contour index */ -} charproc_data; - - -class TQPSPrinterFontTTF - : public TQPSPrinterFontPrivate { -public: - TQPSPrinterFontTTF(const TQFontEngine *f, TQByteArray& data); - virtual void download(TQTextStream& s, bool global); - virtual void drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, - const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint); - // virtual ~TQPSPrinterFontTTF(); - - virtual bool embedded() { return TRUE; } -private: - TQByteArray data; - TQMemArray uni2glyph; // to speed up lookups - TQMemArray glyph2uni; // to speed up lookups - bool defective; // if we can't process this file - - BYTE* getTable(const char *); - void uni2glyphSetup(); - unsigned short unicode_for_glyph(int glyphindex); - unsigned short glyph_for_unicode(unsigned short unicode); - int topost(FWord x) { return (int)( ((int)(x) * 1000 + HUPM) / unitsPerEm ); } - -#ifdef Q_PRINTER_USE_TYPE42 - void sfnts_pputBYTE(BYTE n,TQTextStream& s, - int& string_len, int& line_len, bool& in_string); - void sfnts_pputUSHORT(USHORT n,TQTextStream& s, - int& string_len, int& line_len, bool& in_string); - void sfnts_pputULONG(ULONG n,TQTextStream& s, - int& string_len, int& line_len, bool& in_string); - void sfnts_end_string(TQTextStream& s, - int& string_len, int& line_len, bool& in_string); - void sfnts_new_table(ULONG length,TQTextStream& s, - int& string_len, int& line_len, bool& in_string); - void sfnts_glyf_table(ULONG oldoffset, - ULONG correct_total_length, - TQTextStream& s, - int& string_len, int& line_len, bool& in_string); - void download_sfnts(TQTextStream& s); -#endif - - void subsetGlyph(int charindex,bool* glyphset); - - void charproc(int charindex, TQTextStream& s, bool *glyphSet); - BYTE* charprocFindGlyphData(int charindex); - void charprocComposite(BYTE *glyph, TQTextStream& s, bool *glyphSet); - void charprocLoad(BYTE *glyph, charproc_data* cd); - - int target_type; /* 42 or 3 */ - - int numTables; /* number of tables present */ - TQString PostName; /* Font's PostScript name */ - TQString FullName; /* Font's full name */ - TQString FamilyName; /* Font's family name */ - TQString Style; /* Font's style string */ - TQString Copyright; /* Font's copyright string */ - TQString Version; /* Font's version string */ - TQString Trademark; /* Font's trademark string */ - int llx,lly,urx,ury; /* bounding box */ - - Fixed TTVersion; /* Truetype version number from offset table */ - Fixed MfrRevision; /* Revision number of this font */ - - BYTE *offset_table; /* Offset table in memory */ - BYTE *post_table; /* 'post' table in memory */ - - BYTE *loca_table; /* 'loca' table in memory */ - BYTE *glyf_table; /* 'glyf' table in memory */ - BYTE *hmtx_table; /* 'hmtx' table in memory */ - - USHORT numberOfHMetrics; - int unitsPerEm; /* unitsPerEm converted to int */ - int HUPM; /* half of above */ - - int numGlyphs; /* from 'post' table */ - - int indexToLocFormat; /* short or long offsets */ - -}; - - -static ULONG getULONG(BYTE *p) -{ - int x; - ULONG val=0; - - for(x=0; x<4; x++) { - val *= 0x100; - val += p[x]; - } - - return val; -} - -static USHORT getUSHORT(BYTE *p) -{ - int x; - USHORT val=0; - - for(x=0; x<2; x++) { - val *= 0x100; - val += p[x]; - } - - return val; -} - -static Fixed getFixed(BYTE *s) -{ - Fixed val={0,0}; - - val.whole = ((s[0] * 256) + s[1]); - val.fraction = ((s[2] * 256) + s[3]); - - return val; -} - -static FWord getFWord(BYTE* s) { return (FWord) getUSHORT(s); } -static uFWord getuFWord(BYTE* s) { return (uFWord) getUSHORT(s); } -static SHORT getSHORT(BYTE* s) { return (SHORT) getUSHORT(s); } - -#if 0 -static const char * const Apple_CharStrings[]={ - ".notdef",".null","nonmarkingreturn","space","exclam","quotedbl","numbersign", - "dollar","percent","ampersand","quotesingle","parenleft","parenright", - "asterisk","plus", "comma","hyphen","period","slash","zero","one","two", - "three","four","five","six","seven","eight","nine","colon","semicolon", - "less","equal","greater","question","at","A","B","C","D","E","F","G","H","I", - "J","K", "L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", - "bracketleft","backslash","bracketright","asciicircum","underscore","grave", - "a","b","c","d","e","f","g","h","i","j","k", "l","m","n","o","p","q","r","s", - "t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde", - "Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis", - "aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla", - "eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex", - "idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde", - "uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent", - "sterling","section","bullet","paragraph","germandbls","registered", - "copyright","trademark","acute","dieresis","notequal","AE","Oslash", - "infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff", - "summation","product","pi","integral","ordfeminine","ordmasculine","Omega", - "ae","oslash","questiondown","exclamdown","logicalnot","radical","florin", - "approxequal","Delta","guillemotleft","guillemotright","ellipsis", - "nobreakspace","Agrave","Atilde","Otilde","OE","oe","endash","emdash", - "quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge", - "ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright", - "fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase", - "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave", - "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple", - "Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde", - "macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron", - "Lslash","lslash","Scaron","scaron","Zcaron","zcaron","brokenbar","Eth","eth", - "Yacute","yacute","Thorn","thorn","minus","multiply","onesuperior", - "twosuperior","threesuperior","onehalf","onequarter","threequarters","franc", - "Gbreve","gbreve","Idot","Scedilla","scedilla","Cacute","cacute","Ccaron", - "ccaron","dmacron","markingspace","capslock","shift","propeller","enter", - "markingtabrtol","markingtabltor","control","markingdeleteltor", - "markingdeletertol","option","escape","parbreakltor","parbreakrtol", - "newpage","checkmark","linebreakltor","linebreakrtol","markingnobreakspace", - "diamond","appleoutline"}; -#endif - -// #define DEBUG_TRUETYPE - -TQPSPrinterFontTTF::TQPSPrinterFontTTF(const TQFontEngine *f, TQByteArray& d) -{ - data = d; - defective = FALSE; - - BYTE *ptr; - - target_type = 3; // will work on any printer - //target_type = 42; // works with gs, faster, better quality - -#ifdef Q_PRINTER_USE_TYPE42 - char* environment_preference = getenv("QT_TTFTOPS"); - if (environment_preference) { - if (TQString(environment_preference) == "42") - target_type = 42; - else if (TQString(environment_preference) == "3") - target_type = 3; - else - tqWarning("The value of QT_TTFTOPS must be 42 or 3"); - } -#endif - offset_table = (unsigned char*) data.data(); /* first 12 bytes */ - - /* Determine how many directory entries there are. */ - numTables = getUSHORT( offset_table + 4 ); - - /* Extract information from the "Offset" table. */ - TTVersion = getFixed( offset_table ); - - /* Load the "head" table and extract information from it. */ - ptr = getTable("head"); - if ( !ptr ) { - defective = TRUE; - return; - } - MfrRevision = getFixed( ptr + 4 ); /* font revision number */ - unitsPerEm = getUSHORT( ptr + 18 ); - HUPM = unitsPerEm / 2; -#ifdef DEBUG_TRUETYPE - printf("unitsPerEm=%d",(int)unitsPerEm); -#endif - llx = topost( getFWord( ptr + 36 ) ); /* bounding box info */ - lly = topost( getFWord( ptr + 38 ) ); - urx = topost( getFWord( ptr + 40 ) ); - ury = topost( getFWord( ptr + 42 ) ); - indexToLocFormat = getSHORT( ptr + 50 ); /* size of 'loca' data */ - if(indexToLocFormat != 0 && indexToLocFormat != 1) { - tqWarning("TrueType font is unusable because indexToLocFormat != 0"); - defective = TRUE; - return; - } - if( getSHORT(ptr+52) != 0 ) { - tqWarning("TrueType font is unusable because glyphDataFormat != 0"); - defective = TRUE; - return; - } - - // === Load information from the "name" table === - - /* Set default values to avoid future references to */ - /* undefined pointers. */ - - psname = FullName = FamilyName = Version = Style = "unknown"; - Copyright = "No copyright notice"; - Trademark = "No trademark notice"; - - BYTE* table_ptr = getTable("name"); /* pointer to table */ - if ( !table_ptr ) { - defective = TRUE; - tqDebug("couldn't find name table" ); - return; - } - int numrecords = getUSHORT( table_ptr + 2 ); /* number of names */ - char* strings = (char *)table_ptr + getUSHORT( table_ptr + 4 ); /* start of string storage */ - - BYTE* ptr2 = table_ptr + 6; - for(int x=0; x < numrecords; x++,ptr2+=12) { - int platform = getUSHORT(ptr2); - //int encoding = getUSHORT(ptr2+2); - //int language = getUSHORT(ptr2+4); - int nameid = getUSHORT(ptr2+6); - int length = getUSHORT(ptr2+8); - int offset = getUSHORT(ptr2+10); - - if( platform == 1 && nameid == 0 ) - Copyright.setLatin1(strings+offset,length); - - if( platform == 1 && nameid == 1 ) - FamilyName.setLatin1(strings+offset,length); - - if( platform == 1 && nameid == 2 ) - Style.setLatin1(strings+offset,length); - - if( platform == 1 && nameid == 4 ) - FullName.setLatin1(strings+offset,length); - - if( platform == 1 && nameid == 5 ) - Version.setLatin1(strings+offset,length); - - if( platform == 1 && nameid == 6 ) - psname.setLatin1(strings+offset,length); - - if( platform == 1 && nameid == 7 ) - Trademark.setLatin1(strings+offset,length); - - } - psname.replace(' ', '-'); - psname.replace("/", ""); - if (psname.isEmpty()) - psname = makePSFontName(f); - - //read_cmap(font); - - /* We need to have the PostScript table around. */ - - post_table = getTable("post"); -#if 0 - if ( post_table ) { - Fixed post_format = getFixed( post_table ); - - if( post_format.whole != 2 || post_format.fraction != 0 ) { - tqWarning("TrueType font does not have a format 2.0 'post' table"); - tqWarning("post format is %d.%d",post_format.whole,post_format.fraction); - // Sivan Feb 2001: no longer defective. - // defective = TRUE; - } - } -#endif - BYTE *maxp = getTable("maxp"); - if ( !maxp ) { - defective = TRUE; - tqDebug("no maxp table in font"); - return; - } - numGlyphs = getUSHORT( maxp + 4 ); -// tqDebug("number of glyphs is %d", numGlyphs); - replacementList = makePSFontNameList( f, psname ); - uni2glyphSetup(); -} - - -void TQPSPrinterFontTTF::drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, - const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint) -{ - // we draw glyphs here to get correct shaping of arabic and indic - TQScriptItem &si = engine->items[item]; - engine->shape( item ); - int len = si.num_glyphs; - - int x = p.x() + si.x; - int y = p.y() + si.y; - if ( y != d->textY || d->textY == 0 ) - stream << y << " Y"; - d->textY = y; - - TQCString xyarray; - int xo = 0; - int yo = 0; - - glyph_t *glyphs = engine->glyphs( &si ); - advance_t *advances = engine->advances( &si ); - qoffset_t *offsets = engine->offsets( &si ); -#ifdef TQ_WS_X11 - int type = si.fontEngine->type(); - bool glyphIndices = (type == TQFontEngine::Xft); - // This helps us get arabic for XLFD fonts working. In that case we have a Unicode - // cmap (== 0), and the glyphs array contains the shaped string. - bool useGlyphAsUnicode = (type == TQFontEngine::XLFD && si.fontEngine->cmap() == 0); -#endif - stream << "<"; - if ( si.analysis.bidiLevel % 2 ) { - for ( int i = len-1; i >=0; i-- ) { - // map unicode is not really the correct name, as we map glyphs, but we also download glyphs, so this works - unsigned short glyph; - if (glyphIndices) - glyph = glyphs[i]; - else - glyph = glyph_for_unicode(useGlyphAsUnicode ? glyphs[i] : text.unicode()[i].unicode()); - stream << toHex(mapUnicode(glyph)); - if ( i != len-1 ) { - xyarray += toInt( xo + offsets[i].x + advances[i+1] ); - xyarray += " "; - xyarray += toInt( yo + offsets[i].y ); - xyarray += " "; - xo = -offsets[i].x; - yo = -offsets[i].y; - } - } - } else { - for ( int i = 0; i < len; i++ ) { - // map unicode is not really the correct name, as we map glyphs, but we also download glyphs, so this works - unsigned short glyph; - if (glyphIndices) - glyph = glyphs[i]; - else - glyph = glyph_for_unicode(useGlyphAsUnicode ? glyphs[i] : text.unicode()[i].unicode()); - stream << toHex(mapUnicode(glyph)); - if ( i ) { - xyarray += toInt( xo + offsets[i].x + advances[i-1] ); - xyarray += " "; - xyarray += toInt( yo + offsets[i].y ); - xyarray += " "; - xo = -offsets[i].x; - yo = -offsets[i].y; - } - } - } - stream << ">"; - - stream << "[" << xyarray << "0 0]"; - stream << si.width << " " << x; - - if ( paint->font().underline() ) - stream << ' ' << y + d->fm.underlinePos() + d->fm.lineWidth() - << " " << d->fm.lineWidth() << " Tl"; - if ( paint->font().strikeOut() ) - stream << ' ' << y + d->fm.strikeOutPos() - << " " << d->fm.lineWidth() << " Tl"; - stream << " XYT\n"; - -} - - -void TQPSPrinterFontTTF::download(TQTextStream& s,bool global) -{ - emitPSFontNameList( s, psname, replacementList); - if ( !embedFonts ) { - downloadMapping(s, global); - return; - } - - //tqDebug("downloading ttf font %s", psname.latin1() ); - //tqDebug("target type=%d", target_type); - global_dict = global; - TQMap *subsetDict = ⊂ - if ( !global ) - subsetDict = &page_subset; - - downloaded = TRUE; - - if (defective) { - s << "% Font "; - s << FullName; - s << " cannot be downloaded\n"; - return; - } - - // === write header === - int VMMin; - int VMMax; - - s << wrapDSC( "%%BeginFont: " + FullName ); - if( target_type == 42 ) { - s << "%!PS-TrueTypeFont-" - << TTVersion.whole - << "." - << TTVersion.fraction - << "-" - << MfrRevision.whole - << "." - << MfrRevision.fraction - << "\n"; - } else { - /* If it is not a Type 42 font, we will use a different format. */ - s << "%!PS-Adobe-3.0 Resource-Font\n"; - } /* See RBIIp 641 */ - - if( Copyright != (char*)NULL ) { - s << wrapDSC( "%%Copyright: " + Copyright ); - } - - if( target_type == 42 ) - s << "%%Creator: Converted from TrueType to type 42 by TQt\n"; - else - s << "%%Creator: Converted from TrueType by TQt\n"; - - /* If VM usage information is available, print it. */ - if( target_type == 42 && post_table) - { - VMMin = (int)getULONG( post_table + 16 ); - VMMax = (int)getULONG( post_table + 20 ); - if( VMMin > 0 && VMMax > 0 ) - s << "%%VMUsage: " << VMMin << " " << VMMax << "\n"; - } - - /* Start the dictionary which will eventually */ - /* become the font. */ - if( target_type != 3 ) { - s << "15 dict begin\n"; - } else { - s << "25 dict begin\n"; - - /* Type 3 fonts will need some subroutines here. */ - s << "/_d{bind def}bind def\n"; - s << "/_m{moveto}_d\n"; - s << "/_l{lineto}_d\n"; - s << "/_cl{closepath eofill}_d\n"; - s << "/_c{curveto}_d\n"; - s << "/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d\n"; - s << "/_e{exec}_d\n"; - } - - s << "/FontName /"; - s << psname; - s << " def\n"; - s << "/PaintType 0 def\n"; - - if(target_type == 42) - s << "/FontMatrix[1 0 0 1 0 0]def\n"; - else - s << "/FontMatrix[.001 0 0 .001 0 0]def\n"; - - s << "/FontBBox["; - s<< llx; - s << " "; - s<< lly; - s << " "; - s<< urx; - s << " "; - s<< ury; - s << "]def\n"; - - s << "/FontType "; - s<< target_type; - s << " def\n"; - - // === write encoding === - - s << "/Encoding StandardEncoding def\n"; - - // === write fontinfo dict === - - /* We create a sub dictionary named "FontInfo" where we */ - /* store information which though it is not used by the */ - /* interpreter, is useful to some programs which will */ - /* be printing with the font. */ - s << "/FontInfo 10 dict dup begin\n"; - - /* These names come from the TrueType font's "name" table. */ - s << "/FamilyName ("; - s << FamilyName; - s << ") def\n"; - - s << "/FullName ("; - s << FullName; - s << ") def\n"; - - s << "/Notice ("; - s << Copyright; - s << " "; - s << Trademark; - s << ") def\n"; - - /* This information is not quite correct. */ - s << "/Weight ("; - s << Style; - s << ") def\n"; - - /* Some fonts have this as "version". */ - s << "/Version ("; - s << Version; - s << ") def\n"; - - /* Some information from the "post" table. */ - if ( post_table ) { - Fixed ItalicAngle = getFixed( post_table + 4 ); - s << "/ItalicAngle "; - s << ItalicAngle.whole; - s << "."; - s << ItalicAngle.fraction; - s << " def\n"; - - s << "/isFixedPitch "; - s << (getULONG( post_table + 12 ) ? "true" : "false" ); - s << " def\n"; - - s << "/UnderlinePosition "; - s << (int)getFWord( post_table + 8 ); - s << " def\n"; - - s << "/UnderlineThickness "; - s << (int)getFWord( post_table + 10 ); - s << " def\n"; - } - s << "end readonly def\n"; - -#ifdef Q_PRINTER_USE_TYPE42 - /* If we are generating a type 42 font, */ - /* emmit the sfnts array. */ - if( target_type == 42 ) - download_sfnts(s); -#endif - /* If we are generating a Type 3 font, we will need to */ - /* have the 'loca' and 'glyf' tables arround while */ - /* we are generating the CharStrings. */ - if(target_type == 3) - { - BYTE *ptr; /* We need only one value */ - ptr = getTable("hhea"); - numberOfHMetrics = getUSHORT(ptr + 34); - - loca_table = getTable("loca"); - glyf_table = getTable("glyf"); - hmtx_table = getTable("hmtx"); - } - - // === CharStrings array === - - // subsetting. We turn a char subset into a glyph subset - // and we mark as used the base glyphs of used composite glyphs. - - bool glyphset[65536]; - for(int c=0; c < 65536; c++) - glyphset[c] = FALSE; - glyphset[0] = TRUE; // always output .notdef - - TQMap::iterator it; - for( it = subsetDict->begin(); it != subsetDict->end(); ++it ) { - subsetGlyph( it.key(), glyphset ); - } - int nGlyphs = numGlyphs; - if ( target_type == 3 ) { - nGlyphs = 0;; - for(int c=0; c < 65536; c++) - if ( glyphset[c] ) nGlyphs++; - } - - s << "/CharStrings "; - s << nGlyphs; - s << " dict dup begin\n"; - - // Emmit one key-value pair for each glyph. - for(int x=0; x < 65536; x++) { - if(target_type == 42) { - s << "/"; - s << glyphName( x ); - s << " "; - s << x; - s << " def\n"; - } else { /* type 3 */ - if (!glyphset[x]) continue; - - //tqDebug("emitting charproc for glyph %d, name=%s", x, glyphName(x).latin1() ); - s << "/"; - s << glyphName( x, glyphset ); - s << "{"; - charproc(x,s, glyphset); - s << "}_d\n"; /* "} bind def" */ - } - } - - s << "end readonly def\n"; - - // === trailer === - - /* If we are generating a type 3 font, we need to provide */ - /* a BuildGlyph and BuildChar proceedures. */ - if( target_type == 3 ) { - s << "\n"; - - s << "/BuildGlyph\n"; - s << " {exch begin\n"; /* start font dictionary */ - s << " CharStrings exch\n"; - s << " 2 copy known not{pop /.notdef}if\n"; - s << " true 3 1 roll get exec\n"; - s << " end}_d\n"; - - s << "\n"; - - /* This proceedure is for compatiblity with */ - /* level 1 interpreters. */ - s << "/BuildChar {\n"; - s << " 1 index /Encoding get exch get\n"; - s << " 1 index /BuildGlyph get exec\n"; - s << "}_d\n"; - - s << "\n"; - - } - - /* If we are generating a type 42 font, we need to check to see */ - /* if this PostScript interpreter understands type 42 fonts. If */ - /* it doesn't, we will hope that the Apple TrueType rasterizer */ - /* has been loaded and we will adjust the font accordingly. */ - /* I found out how to do this by examining a TrueType font */ - /* generated by a Macintosh. That is where the TrueType interpreter */ - /* setup instructions and part of BuildGlyph came from. */ - else if( target_type == 42 ) { - s << "\n"; - - /* If we have no "resourcestatus" command, or FontType 42 */ - /* is unknown, leave "true" on the stack. */ - s << "systemdict/resourcestatus known\n"; - s << " {42 /FontType resourcestatus\n"; - s << " {pop pop false}{true}ifelse}\n"; - s << " {true}ifelse\n"; - - /* If true, execute code to produce an error message if */ - /* we can't find Apple's TrueDict in VM. */ - s << "{/TrueDict where{pop}{(%%[ Error: no TrueType rasterizer ]%%)= flush}ifelse\n"; - - /* Since we are expected to use Apple's TrueDict TrueType */ - /* reasterizer, change the font type to 3. */ - s << "/FontType 3 def\n"; - - /* Define a string to hold the state of the Apple */ - /* TrueType interpreter. */ - s << " /TrueState 271 string def\n"; - - /* It looks like we get information about the resolution */ - /* of the printer and store it in the TrueState string. */ - s << " TrueDict begin sfnts save\n"; - s << " 72 0 matrix defaultmatrix dtransform dup\n"; - s << " mul exch dup mul add sqrt cvi 0 72 matrix\n"; - s << " defaultmatrix dtransform dup mul exch dup\n"; - s << " mul add sqrt cvi 3 -1 roll restore\n"; - s << " TrueState initer end\n"; - - /* This BuildGlyph procedure will look the name up in the */ - /* CharStrings array, and then check to see if what it gets */ - /* is a procedure. If it is, it executes it, otherwise, it */ - /* lets the TrueType rasterizer loose on it. */ - - /* When this proceedure is executed the stack contains */ - /* the font dictionary and the character name. We */ - /* exchange arguments and move the dictionary to the */ - /* dictionary stack. */ - s << " /BuildGlyph{exch begin\n"; - /* stack: charname */ - - /* Put two copies of CharStrings on the stack and consume */ - /* one testing to see if the charname is defined in it, */ - /* leave the answer on the stack. */ - s << " CharStrings dup 2 index known\n"; - /* stack: charname CharStrings bool */ - - /* Exchange the CharStrings dictionary and the charname, */ - /* but if the answer was false, replace the character name */ - /* with ".notdef". */ - s << " {exch}{exch pop /.notdef}ifelse\n"; - /* stack: CharStrings charname */ - - /* Get the value from the CharStrings dictionary and see */ - /* if it is executable. */ - s << " get dup xcheck\n"; - /* stack: CharStrings_entry */ - - /* If is a proceedure. Execute according to RBIIp 277-278. */ - s << " {currentdict systemdict begin begin exec end end}\n"; - - /* Is a TrueType character index, let the rasterizer at it. */ - s << " {TrueDict begin /bander load cvlit exch TrueState render end}\n"; - - s << " ifelse\n"; - - /* Pop the font's dictionary off the stack. */ - s << " end}bind def\n"; - - /* This is the level 1 compatibility BuildChar procedure. */ - /* See RBIIp 281. */ - s << " /BuildChar{\n"; - s << " 1 index /Encoding get exch get\n"; - s << " 1 index /BuildGlyph get exec\n"; - s << " }bind def\n"; - - /* Here we close the condition which is true */ - /* if the printer has no built-in TrueType */ - /* rasterizer. */ - s << "}if\n"; - s << "\n"; - } /* end of if Type 42 not understood. */ - - s << "FontName currentdict end definefont pop\n"; - - downloadMapping(s, global); - s << "%%EndFont\n"; -} - -BYTE* TQPSPrinterFontTTF::getTable(const char* name) -{ - BYTE *ptr; - int x; - - /* We must search the table directory. */ - ptr = offset_table + 12; - x=0; - while (x != numTables) { - if( strncmp((const char *)ptr,name,4) == 0 ) { - ULONG offset; - //ULONG length; - BYTE *table; - - offset = getULONG( ptr + 8 ); - //length = getULONG( ptr + 12 ); - - table = offset_table + offset; - return table; - } - - x++; - ptr += 16; - } - - return 0; -} - -void TQPSPrinterFontTTF::uni2glyphSetup() -{ - uni2glyph.resize(65536); - int i; - for (i=0; i<65536; i++) uni2glyph[i] = 0x0000; - glyph2uni.resize(65536); - for (i=0; i<65536; i++) glyph2uni[i] = 0x0000; - - unsigned char* cmap = getTable("cmap"); - int pos = 0; - - //USHORT version = getUSHORT(cmap + pos); - pos += 2; - USHORT nmaps = getUSHORT(cmap + pos); pos += 2; - - //fprintf(stderr,"cmap version %d (should be 0), %d maps\n",version,nmaps); - - ULONG offset = 0; - int map = -1; - bool symbol = TRUE; - for (i=0; i 70) { - s << "\n"; - line_len=0; - } -} - -// Write a USHORT as a hexadecimal value as part of the sfnts array. - -void TQPSPrinterFontTTF::sfnts_pputUSHORT(USHORT n,TQTextStream& s, - int& string_len, int& line_len, bool& in_string) -{ - sfnts_pputBYTE(n / 256,s, string_len, line_len, in_string); - sfnts_pputBYTE(n % 256,s, string_len, line_len, in_string); -} - - -// Write a ULONG as part of the sfnts array. - -void TQPSPrinterFontTTF::sfnts_pputULONG(ULONG n,TQTextStream& s, - int& string_len, int& line_len, bool& in_string) -{ - int x1 = n % 256; n /= 256; - int x2 = n % 256; n /= 256; - int x3 = n % 256; n /= 256; - - sfnts_pputBYTE(n,s , string_len, line_len, in_string); - sfnts_pputBYTE(x3,s, string_len, line_len, in_string); - sfnts_pputBYTE(x2,s, string_len, line_len, in_string); - sfnts_pputBYTE(x1,s, string_len, line_len, in_string); -} - -/* -** This is called whenever it is -** necessary to end a string in the sfnts array. -** -** (The array must be broken into strings which are -** no longer than 64K characters.) -*/ -void TQPSPrinterFontTTF::sfnts_end_string(TQTextStream& s, - int& string_len, int& line_len, bool& in_string) -{ - if(in_string) { - string_len=0; /* fool sfnts_pputBYTE() */ - - // s << "\n% dummy byte:\n"; - - // extra byte for pre-2013 compatibility - sfnts_pputBYTE(0, s, string_len, line_len, in_string); - - s << ">"; - line_len++; - } - - in_string=FALSE; -} - -/* -** This is called at the start of each new table. -** The argement is the length in bytes of the table -** which will follow. If the new table will not fit -** in the current string, a new one is started. -*/ -void TQPSPrinterFontTTF::sfnts_new_table(ULONG length,TQTextStream& s, - int& string_len, int& line_len, bool& in_string) -{ - if( (string_len + length) > 65528 ) - sfnts_end_string(s, string_len, line_len, in_string); -} - -/* -** We may have to break up the 'glyf' table. That is the reason -** why we provide this special routine to copy it into the sfnts -** array. -*/ -void TQPSPrinterFontTTF::sfnts_glyf_table(ULONG oldoffset, - ULONG correct_total_length, - TQTextStream& s, - int& string_len, int& line_len, bool& in_string) - -{ - int x; - ULONG off; - ULONG length; - int c; - ULONG total=0; /* running total of bytes written to table */ - - loca_table = getTable("loca"); - - int font_off = oldoffset; - - /* Copy the glyphs one by one */ - for(x=0; x < numGlyphs; x++) { - /* Read the glyph offset from the index-to-location table. */ - if(indexToLocFormat == 0) { - off = getUSHORT( loca_table + (x * 2) ); - off *= 2; - length = getUSHORT( loca_table + ((x+1) * 2) ); - length *= 2; - length -= off; - } else { - off = getULONG( loca_table + (x * 4) ); - length = getULONG( loca_table + ((x+1) * 4) ); - length -= off; - } - - // fprintf(stderr,"glyph length=%d",(int)length); - - /* Start new string if necessary. */ - sfnts_new_table( (int)length, s, string_len, line_len, in_string ); - - /* - ** Make sure the glyph is padded out to a - ** two byte boundary. - */ - if( length % 2 ) { - tqWarning("TrueType font contains a 'glyf' table without 2 byte padding"); - defective = TRUE; - return; - } - - /* Copy the bytes of the glyph. */ - while( length-- ) { - c = offset_table[ font_off ]; - font_off++; - - sfnts_pputBYTE(c, s, string_len, line_len, in_string); - total++; /* add to running total */ - } - } - - /* Pad out to full length from table directory */ - while( total < correct_total_length ) { - sfnts_pputBYTE(0, s, string_len, line_len, in_string); - total++; - } - - /* Look for unexplainable descrepancies between sizes */ - if( total != correct_total_length ) { - tqWarning("TQPSPrinterFontTTF::sfnts_glyf_table: total != correct_total_length"); - defective = TRUE; - return; - } -} - -/* -** Here is the routine which ties it all together. -** -** Create the array called "sfnts" which -** holds the actual TrueType data. -*/ - -void TQPSPrinterFontTTF::download_sfnts(TQTextStream& s) -{ - // tables worth including in a type 42 font - char *table_names[]= { - "cvt ", - "fpgm", - "glyf", - "head", - "hhea", - "hmtx", - "loca", - "maxp", - "prep" - }; - - struct { /* The location of each of */ - ULONG oldoffset; /* the above tables. */ - ULONG newoffset; - ULONG length; - ULONG checksum; - } tables[9]; - - int c; /* Input character. */ - int diff; - int count; /* How many `important' tables did we find? */ - - BYTE* ptr = offset_table + 12; // original table directory - ULONG nextoffset=0; - count=0; - - /* - ** Find the tables we want and store there vital - ** statistics in tables[]. - */ - for(int x=0; x < 9; x++ ) { - do { - diff = strncmp( (char*)ptr, table_names[x], 4 ); - - if( diff > 0 ) { /* If we are past it. */ - tables[x].length = 0; - diff = 0; - } - else if( diff < 0 ) { /* If we haven't hit it yet. */ - ptr += 16; - } - else if( diff == 0 ) { /* Here it is! */ - tables[x].newoffset = nextoffset; - tables[x].checksum = getULONG( ptr + 4 ); - tables[x].oldoffset = getULONG( ptr + 8 ); - tables[x].length = getULONG( ptr + 12 ); - nextoffset += ( ((tables[x].length + 3) / 4) * 4 ); - count++; - ptr += 16; - } - } while(diff != 0); - } /* end of for loop which passes over the table directory */ - - /* Begin the sfnts array. */ - - s << "/sfnts[<"; - - bool in_string=TRUE; - int string_len=0; - int line_len=8; - - /* Generate the offset table header */ - /* Start by copying the TrueType version number. */ - ptr = offset_table; - for(int x=0; x < 4; x++) - sfnts_pputBYTE( *(ptr++) , s, string_len, line_len, in_string ); - - /* Now, generate those silly numTables numbers. */ - sfnts_pputUSHORT(count,s, string_len, line_len, in_string); /* number of tables */ - if( count == 9 ) { - sfnts_pputUSHORT(7,s, string_len, line_len, in_string); /* searchRange */ - sfnts_pputUSHORT(3,s, string_len, line_len, in_string); /* entrySelector */ - sfnts_pputUSHORT(81,s, string_len, line_len, in_string); /* rangeShift */ - } - else { - tqWarning("Fewer than 9 tables selected"); - } - - /* Now, emmit the table directory. */ - for(int x=0; x < 9; x++) { - if( tables[x].length == 0 ) /* Skip missing tables */ - continue; - - /* Name */ - sfnts_pputBYTE( table_names[x][0], s, string_len, line_len, in_string); - sfnts_pputBYTE( table_names[x][1], s, string_len, line_len, in_string); - sfnts_pputBYTE( table_names[x][2], s, string_len, line_len, in_string); - sfnts_pputBYTE( table_names[x][3], s, string_len, line_len, in_string); - - /* Checksum */ - sfnts_pputULONG( tables[x].checksum, s, string_len, line_len, in_string ); - - /* Offset */ - sfnts_pputULONG( tables[x].newoffset + 12 + (count * 16), s, - string_len, line_len, in_string ); - - /* Length */ - sfnts_pputULONG( tables[x].length, s, - string_len, line_len, in_string ); - } - - /* Now, send the tables */ - for(int x=0; x < 9; x++) { - if( tables[x].length == 0 ) /* skip tables that aren't there */ - continue; - - /* 'glyf' table gets special treatment */ - if( strcmp(table_names[x],"glyf")==0 ) { - sfnts_glyf_table(tables[x].oldoffset,tables[x].length, s, - string_len, line_len, in_string); - } else { // other tables should not exceed 64K (not always true; Sivan) - if( tables[x].length > 65535 ) { - tqWarning("TrueType font has a table which is too long"); - defective = TRUE; - return; - } - - /* Start new string if necessary. */ - sfnts_new_table(tables[x].length, s, - string_len, line_len, in_string); - - int font_off = tables[x].oldoffset; - /* Copy the bytes of the table. */ - for( int y=0; y < (int)tables[x].length; y++ ) { - c = offset_table[ font_off ]; - font_off++; - - sfnts_pputBYTE(c, s, string_len, line_len, in_string); - } - } - - /* Padd it out to a four byte boundary. */ - int y=tables[x].length; - while( (y % 4) != 0 ) { - sfnts_pputBYTE(0, s, string_len, line_len, in_string); - y++; - } - - } /* End of loop for all tables */ - - /* Close the array. */ - sfnts_end_string(s, string_len, line_len, in_string); - s << "]def\n"; -} -#endif - -// ****************** Type 3 CharProcs ******* - -/* -** This routine is used to break the character -** procedure up into a number of smaller -** procedures. This is necessary so as not to -** overflow the stack on certain level 1 interpreters. -** -** Prepare to push another item onto the stack, -** starting a new proceedure if necessary. -** -** Not all the stack depth calculations in this routine -** are perfectly accurate, but they do the job. -*/ -static int stack_depth = 0; -static void stack(int num_pts, int newnew, TQTextStream& s) -{ - if( num_pts > 25 ) { /* Only do something of we will */ - /* have a log of points. */ - if(stack_depth == 0) { - s << "{"; - stack_depth=1; - } - - stack_depth += newnew; /* Account for what we propose to add */ - - if(stack_depth > 100) { - s << "}_e{"; - stack_depth = 3 + newnew; /* A rough estimate */ - } - } -} - -static void stack_end(TQTextStream& s) /* called at end */ -{ - if(stack_depth) { - s << "}_e"; - stack_depth=0; - } -} - -// postscript drawing commands - -static void PSMoveto(FWord x, FWord y, TQTextStream& ts) -{ - ts << x; - ts << " "; - ts << y; - ts << " _m\n"; -} - -static void PSLineto(FWord x, FWord y, TQTextStream& ts) -{ - ts << x; - ts << " "; - ts << y; - ts << " _l\n"; -} - -/* Emmit a PostScript "curveto" command. */ -static void PSCurveto(FWord* xcoor, FWord* ycoor, - FWord x, FWord y, int s, int t, TQTextStream& ts) -{ - int N, i; - double sx[3], sy[3], cx[4], cy[4]; - - N = t-s+2; - for(i=0; inum_ctr; j++) - if (cd->check_ctr[j]==0 && cd->area_ctr[j] < 0) { - cd->check_ctr[j]=1; - return j; - } - - return NOMOREOUTCTR; -} /* end of nextoutctr() */ - -static int nextinctr(int co, int /*ci*/, charproc_data* cd) -{ - int j; - - for(j=0; jnum_ctr; j++) - if (cd->ctrset[2*j+1]==co) - if (cd->check_ctr[ cd->ctrset[2*j] ]==0) { - cd->check_ctr[ cd->ctrset[2*j] ]=1; - return cd->ctrset[2*j]; - } - - return NOMOREINCTR; -} - -static double intest( int co, int ci, charproc_data *cd ) -{ - int i, j, start, end; - double r1, r2; - FWord xi[3], yi[3]; - - j = start = ( co == 0 ) ? 0 : ( cd->epts_ctr[co - 1] + 1 ); - end = cd->epts_ctr[co]; - i = ( ci == 0 ) ? 0 : ( cd->epts_ctr[ci - 1] + 1 ); - xi[0] = cd->xcoor[i]; - yi[0] = cd->ycoor[i]; - r1 = sqr( cd->xcoor[start] - xi[0] ) + sqr( cd->ycoor[start] - yi[0] ); - - for ( i = start; i <= end; i++ ) { - r2 = sqr( cd->xcoor[i] - xi[0] ) + sqr( cd->ycoor[i] - yi[0] ); - if ( r2 < r1 ) { - r1 = r2; - j = i; - } - } - if ( j == start ) { - xi[1] = cd->xcoor[end]; - yi[1] = cd->ycoor[end]; - } else { - xi[1] = cd->xcoor[j - 1]; - yi[1] = cd->ycoor[j - 1]; - } - if ( j == end ) { - xi[2] = cd->xcoor[start]; - yi[2] = cd->ycoor[start]; - } else { - xi[2] = cd->xcoor[j + 1]; - yi[2] = cd->ycoor[j + 1]; - } - return area( xi, yi, 3 ); -} - -/* -** find the nearest out contour to a specified in contour. -*/ -static int nearout(int ci, charproc_data* cd) -{ - int k = 0; /* !!! is this right? */ - int co; - double a, a1=0; - - for (co=0; co < cd->num_ctr; co++) { - if(cd->area_ctr[co] < 0) { - a=intest(co,ci, cd); - if (a<0 && a1==0) { - k=co; - a1=a; - } - if(a<0 && a1!=0 && a>a1) { - k=co; - a1=a; - } - } - } - - return k; -} /* end of nearout() */ - - -/* -** We call this routine to emmit the PostScript code -** for the character we have loaded with load_char(). -*/ -static void PSConvert(TQTextStream& s, charproc_data* cd) -{ - int i,j,k,fst,start_offpt; - int end_offpt=0; - - cd->area_ctr = new double[cd->num_ctr]; - memset(cd->area_ctr, 0, (cd->num_ctr*sizeof(double))); - - cd->check_ctr = new char[cd->num_ctr]; - memset(cd->check_ctr, 0, (cd->num_ctr*sizeof(char))); - - cd->ctrset = new int[2*(cd->num_ctr)]; - memset(cd->ctrset, 0, (cd->num_ctr*2*sizeof(int))); - - cd->check_ctr[0]=1; - cd->area_ctr[0]=area(cd->xcoor, cd->ycoor, cd->epts_ctr[0]+1); - - for (i=1; inum_ctr; i++) - cd->area_ctr[i]=area(cd->xcoor+cd->epts_ctr[i-1]+1, - cd->ycoor+cd->epts_ctr[i-1]+1, - cd->epts_ctr[i]-cd->epts_ctr[i-1]); - - for (i=0; inum_ctr; i++) { - if (cd->area_ctr[i]>0) { - cd->ctrset[2*i]=i; - cd->ctrset[2*i+1]=nearout(i,cd); - } else { - cd->ctrset[2*i]=-1; - cd->ctrset[2*i+1]=-1; - } - } - - /* Step thru the coutours. */ - /* I believe that a contour is a detatched */ - /* set of curves and lines. */ - i=j=k=0; - while (i < cd->num_ctr ) { - fst = j = (k==0) ? 0 : (cd->epts_ctr[k-1]+1); - - /* Move to the first point on the contour. */ - stack(cd->num_pts,3,s); - PSMoveto(cd->xcoor[j],cd->ycoor[j],s); - start_offpt = 0; /* No off curve points yet. */ - - /* Step thru the remaining points of this contour. */ - for(j++; j <= cd->epts_ctr[k]; j++) { - if (!(cd->tt_flags[j]&1)) { /* Off curve */ - if (!start_offpt) - { start_offpt = end_offpt = j; } - else - end_offpt++; - } else { /* On Curve */ - if (start_offpt) { - stack(cd->num_pts,7,s); - PSCurveto(cd->xcoor,cd->ycoor, - cd->xcoor[j],cd->ycoor[j], - start_offpt,end_offpt,s); - start_offpt = 0; - } else { - stack(cd->num_pts,3,s); - PSLineto(cd->xcoor[j], cd->ycoor[j],s); - } - } - } - - /* Do the final curve or line */ - /* of this coutour. */ - if (start_offpt) { - stack(cd->num_pts,7,s); - PSCurveto(cd->xcoor,cd->ycoor, - cd->xcoor[fst],cd->ycoor[fst], - start_offpt,end_offpt,s); - } else { - stack(cd->num_pts,3,s); - PSLineto(cd->xcoor[fst],cd->ycoor[fst],s); - } - - k=nextinctr(i,k,cd); - - if (k==NOMOREINCTR) - i=k=nextoutctr(i,cd); - - if (i==NOMOREOUTCTR) - break; - } - - /* Now, we can fill the whole thing. */ - stack(cd->num_pts,1,s); - s << "_cl"; /* "closepath eofill" */ - - /* Free our work arrays. */ - delete [] cd->area_ctr; - delete [] cd->check_ctr; - delete [] cd->ctrset; -} - - -/* -** Load the simple glyph data pointed to by glyph. -** The pointer "glyph" should point 10 bytes into -** the glyph data. -*/ -void TQPSPrinterFontTTF::charprocLoad(BYTE *glyph, charproc_data* cd) -{ - int x; - BYTE c, ct; - - /* Read the contour endpoints list. */ - cd->epts_ctr = new int[cd->num_ctr]; - //cd->epts_ctr = (int *)myalloc(cd->num_ctr,sizeof(int)); - for (x = 0; x < cd->num_ctr; x++) { - cd->epts_ctr[x] = getUSHORT(glyph); - glyph += 2; - } - - /* From the endpoint of the last contour, we can */ - /* determine the number of points. */ - cd->num_pts = cd->epts_ctr[cd->num_ctr-1]+1; -#ifdef DEBUG_TRUETYPE - fprintf(stderr,"num_pts=%d\n",cd->num_pts); -#endif - - /* Skip the instructions. */ - x = getUSHORT(glyph); - glyph += 2; - glyph += x; - - /* Allocate space to hold the data. */ - //cd->tt_flags = (BYTE *)myalloc(num_pts,sizeof(BYTE)); - //cd->xcoor = (FWord *)myalloc(num_pts,sizeof(FWord)); - //cd->ycoor = (FWord *)myalloc(num_pts,sizeof(FWord)); - cd->tt_flags = new BYTE[cd->num_pts]; - cd->xcoor = new FWord[cd->num_pts]; - cd->ycoor = new FWord[cd->num_pts]; - - /* Read the flags array, uncompressing it as we go. */ - /* There is danger of overflow here. */ - for (x = 0; x < cd->num_pts; ) { - cd->tt_flags[x++] = c = *(glyph++); - - if (c&8) { /* If next byte is repeat count, */ - ct = *(glyph++); - - if( (x + ct) > cd->num_pts ) { - tqWarning("Fatal Error in TT flags"); - return; - } - - while (ct--) - cd->tt_flags[x++] = c; - } - } - - /* Read the x coordinates */ - for (x = 0; x < cd->num_pts; x++) { - if (cd->tt_flags[x] & 2) { /* one byte value with */ - /* external sign */ - c = *(glyph++); - cd->xcoor[x] = (cd->tt_flags[x] & 0x10) ? c : (-1 * (int)c); - } else if(cd->tt_flags[x] & 0x10) { /* repeat last */ - cd->xcoor[x] = 0; - } else { /* two byte signed value */ - cd->xcoor[x] = getFWord(glyph); - glyph+=2; - } - } - - /* Read the y coordinates */ - for(x = 0; x < cd->num_pts; x++) { - if (cd->tt_flags[x] & 4) { /* one byte value with */ - /* external sign */ - c = *(glyph++); - cd->ycoor[x] = (cd->tt_flags[x] & 0x20) ? c : (-1 * (int)c); - } else if (cd->tt_flags[x] & 0x20) { /* repeat last value */ - cd->ycoor[x] = 0; - } else { /* two byte signed value */ - cd->ycoor[x] = getUSHORT(glyph); - glyph+=2; - } - } - - /* Convert delta values to absolute values. */ - for(x = 1; x < cd->num_pts; x++) { - cd->xcoor[x] += cd->xcoor[x-1]; - cd->ycoor[x] += cd->ycoor[x-1]; - } - - for(x=0; x < cd->num_pts; x++) { - cd->xcoor[x] = topost(cd->xcoor[x]); - cd->ycoor[x] = topost(cd->ycoor[x]); - } -} - -#define ARG_1_AND_2_ARE_WORDS 1 -#define ARGS_ARE_XY_VALUES 2 -#define ROUND_XY_TO_GRID 4 -#define WE_HAVE_A_SCALE 8 -/* RESERVED 16 */ -#define MORE_COMPONENTS 32 -#define WE_HAVE_AN_X_AND_Y_SCALE 64 -#define WE_HAVE_A_TWO_BY_TWO 128 -#define WE_HAVE_INSTRUCTIONS 256 -#define USE_MY_METRICS 512 - -void TQPSPrinterFontTTF::subsetGlyph(int charindex,bool* glyphset) -{ - USHORT flags; - USHORT glyphIndex; - charproc_data cd; - - glyphset[charindex] = TRUE; - //printf("subsetting %s ==> ",glyphName(charindex).latin1()); - - /* Get a pointer to the data. */ - BYTE* glyph = charprocFindGlyphData( charindex ); - - /* If the character is blank, it has no bounding box, */ - /* otherwise read the bounding box. */ - if( glyph == (BYTE*)NULL ) { - cd.num_ctr=0; - } else { - cd.num_ctr = getSHORT(glyph); - /* Advance the pointer past bounding box. */ - glyph += 10; - } - - if( cd.num_ctr < 0 ) { // composite - /* Once around this loop for each component. */ - do { - flags = getUSHORT(glyph); /* read the flags word */ - glyph += 2; - glyphIndex = getUSHORT(glyph); /* read the glyphindex word */ - glyph += 2; - - glyphset[ glyphIndex ] = TRUE; - subsetGlyph( glyphIndex, glyphset ); - //printf("subset contains: %d %s ",glyphIndex, glyphName(glyphIndex).latin1()); - - if(flags & ARG_1_AND_2_ARE_WORDS) { - glyph += 2; - glyph += 2; - } else { - glyph += 1; - glyph += 1; - } - - if(flags & WE_HAVE_A_SCALE) { - glyph += 2; - } else if(flags & WE_HAVE_AN_X_AND_Y_SCALE) { - glyph += 2; - glyph += 2; - } else if(flags & WE_HAVE_A_TWO_BY_TWO) { - glyph += 2; - glyph += 2; - glyph += 2; - glyph += 2; - } else { - } - } while(flags & MORE_COMPONENTS); - } - //printf("\n"); -} - - -/* -** Emmit PostScript code for a composite character. -*/ -void TQPSPrinterFontTTF::charprocComposite(BYTE *glyph, TQTextStream& s, bool *glyphSet) -{ - USHORT flags; - USHORT glyphIndex; - int arg1; - int arg2; - float xscale = 1; - float yscale = 1; -#ifdef DEBUG_TRUETYPE - float scale01 = 0; - float scale10 = 0; -#endif - - /* Once around this loop for each component. */ - do { - flags = getUSHORT(glyph); /* read the flags word */ - glyph += 2; - - glyphIndex = getUSHORT(glyph); /* read the glyphindex word */ - glyph += 2; - - if(flags & ARG_1_AND_2_ARE_WORDS) { - /* The tt spec. seems to say these are signed. */ - arg1 = getSHORT(glyph); - glyph += 2; - arg2 = getSHORT(glyph); - glyph += 2; - } else { /* The tt spec. does not clearly indicate */ - /* whether these values are signed or not. */ - arg1 = (char)*(glyph++); - arg2 = (char)*(glyph++); - } - - if(flags & WE_HAVE_A_SCALE) { - xscale = yscale = f2dot14( getUSHORT(glyph) ); - glyph += 2; - } else if(flags & WE_HAVE_AN_X_AND_Y_SCALE) { - xscale = f2dot14( getUSHORT(glyph) ); - glyph += 2; - yscale = f2dot14( getUSHORT(glyph) ); - glyph += 2; - } else if(flags & WE_HAVE_A_TWO_BY_TWO) { - xscale = f2dot14( getUSHORT(glyph) ); - glyph += 2; -#ifdef DEBUG_TRUETYPE - scale01 = f2dot14( getUSHORT(glyph) ); -#endif - glyph += 2; -#ifdef DEBUG_TRUETYPE - scale10 = f2dot14( getUSHORT(glyph) ); -#endif - glyph += 2; - yscale = f2dot14( getUSHORT(glyph) ); - glyph += 2; - } - - /* Debugging */ -#ifdef DEBUG_TRUETYPE - s << "% flags=" << flags << ", arg1=" << arg1 << ", arg2=" << arg2 << ", xscale=" << xscale << ", yscale=" << yscale << - ", scale01=" << scale01 << ", scale10=" << scale10 << endl; -#endif - - - if ( (flags & ARGS_ARE_XY_VALUES) != ARGS_ARE_XY_VALUES ) { - s << "% unimplemented shift, arg1=" << arg1; - s << ", arg2=" << arg2 << "\n"; - arg1 = arg2 = 0; - } - - /* If we have an (X,Y) shif and it is non-zero, */ - /* translate the coordinate system. */ - if ( flags & (WE_HAVE_A_TWO_BY_TWO|WE_HAVE_AN_X_AND_Y_SCALE) ) { -#if 0 - // code similar to this would be needed for two_by_two - s << "gsave [ " << xscale << " " << scale01 << " " << scale10 << " " - << yscale << " " << topost(arg1) << " " << topost(arg2) << "] SM\n"; -#endif - if ( flags & WE_HAVE_A_TWO_BY_TWO ) - s << "% Two by two transformation, unimplemented\n"; - s << "gsave " << topost(arg1); - s << " " << topost(arg2); - s << " translate\n"; - s << xscale << " " << yscale << " scale\n"; - } else if ( flags & ARGS_ARE_XY_VALUES && ( arg1 != 0 || arg2 != 0 ) ) { - s << "gsave " << topost(arg1); - s << " " << topost(arg2); - s << " translate\n"; - } - - /* Invoke the CharStrings procedure to print the component. */ - s << "false CharStrings /"; - s << glyphName( glyphIndex, glyphSet ); - s << " get exec\n"; - - // printf("false CharStrings /%s get exec\n", - //ttfont_CharStrings_getname(font,glyphIndex)); - - /* If we translated the coordinate system, */ - /* put it back the way it was. */ - if( (flags & ARGS_ARE_XY_VALUES && (arg1 != 0 || arg2 != 0) ) || - ( flags & (WE_HAVE_A_TWO_BY_TWO|WE_HAVE_AN_X_AND_Y_SCALE) ) ) { - s << "grestore "; - } - } while (flags & MORE_COMPONENTS); -} - -/* -** Return a pointer to a specific glyph's data. -*/ -BYTE* TQPSPrinterFontTTF::charprocFindGlyphData(int charindex) -{ - ULONG off; - ULONG length; - - /* Read the glyph offset from the index to location table. */ - if(indexToLocFormat == 0) { - off = getUSHORT( loca_table + (charindex * 2) ); - off *= 2; - length = getUSHORT( loca_table + ((charindex+1) * 2) ); - length *= 2; - length -= off; - } else { - off = getULONG( loca_table + (charindex * 4) ); - length = getULONG( loca_table + ((charindex+1) * 4) ); - length -= off; - } - - if(length > 0) - return glyf_table + off; - else - return (BYTE*)NULL; -} - -void TQPSPrinterFontTTF::charproc(int charindex, TQTextStream& s, bool *glyphSet ) -{ - int llx,lly,urx,ury; - int advance_width; - charproc_data cd; - -#ifdef DEBUG_TRUETYPE - s << "% tt_type3_charproc for "; - s << charindex; - s << "\n"; -#endif - - /* Get a pointer to the data. */ - BYTE* glyph = charprocFindGlyphData( charindex ); - - /* If the character is blank, it has no bounding box, */ - /* otherwise read the bounding box. */ - if( glyph == (BYTE*)NULL ) { - llx=lly=urx=ury=0; /* A blank char has an all zero BoundingBox */ - cd.num_ctr=0; /* Set this for later if()s */ - } else { - /* Read the number of contours. */ - cd.num_ctr = getSHORT(glyph); - - /* Read PostScript bounding box. */ - llx = getFWord(glyph + 2); - lly = getFWord(glyph + 4); - urx = getFWord(glyph + 6); - ury = getFWord(glyph + 8); - - /* Advance the pointer. */ - glyph += 10; - } - - /* If it is a simple character, load its data. */ - if (cd.num_ctr > 0) - charprocLoad(glyph, &cd); - else - cd.num_pts=0; - - /* Consult the horizontal metrics table to determine */ - /* the character width. */ - if( charindex < numberOfHMetrics ) - advance_width = getuFWord( hmtx_table + (charindex * 4) ); - else - advance_width = getuFWord( hmtx_table + ((numberOfHMetrics-1) * 4) ); - - /* Execute setcachedevice in order to inform the font machinery */ - /* of the character bounding box and advance width. */ - stack(cd.num_pts,7,s); - s << topost(advance_width); - s << " 0 "; - s << topost(llx); - s << " "; - s << topost(lly); - s << " "; - s << topost(urx); - s << " "; - s << topost(ury); - s << " _sc\n"; - - /* If it is a simple glyph, convert it, */ - /* otherwise, close the stack business. */ - if( cd.num_ctr > 0 ) { // simple - PSConvert(s,&cd); - delete [] cd.tt_flags; - delete [] cd.xcoor; - delete [] cd.ycoor; - delete [] cd.epts_ctr; - } else if( cd.num_ctr < 0 ) { // composite - charprocComposite(glyph,s, glyphSet); - } - - stack_end(s); -} /* end of tt_type3_charproc() */ - - -// ================== PFA ==================== - -class TQPSPrinterFontPFA - : public TQPSPrinterFontPrivate { -public: - TQPSPrinterFontPFA(const TQFontEngine *f, TQByteArray& data); - virtual void download(TQTextStream& s, bool global); - virtual bool embedded() { return TRUE; } -private: - TQByteArray data; -}; - -TQPSPrinterFontPFA::TQPSPrinterFontPFA(const TQFontEngine *f, TQByteArray& d) -{ - data = d; - - int pos = 0; - char* p = data.data(); - TQString fontname; - - if (p[ pos ] != '%' || p[ pos+1 ] != '!') { // PFA marker - tqWarning("invalid pfa file"); - return; - } - - char* fontnameptr = strstr(p+pos,"/FontName"); - if (fontnameptr == NULL) - return; - - fontnameptr += strlen("/FontName") + 1; - while (*fontnameptr == ' ' || *fontnameptr == '/') fontnameptr++; - int l=0; - while (fontnameptr[l] != ' ') l++; - - psname = TQString::fromLatin1(fontnameptr,l); - replacementList = makePSFontNameList( f, psname ); -} - -void TQPSPrinterFontPFA::download(TQTextStream& s, bool global) -{ - emitPSFontNameList( s, psname, replacementList); - - if ( !embedFonts ) { - downloadMapping(s, global); - return; - } - - //tqDebug("downloading pfa font %s", psname.latin1() ); - char* p = data.data(); - - s << "% Font resource\n"; - for (int i=0; i < (int)data.size(); i++) s << p[i]; - s << "% End of font resource\n"; - downloadMapping( s, global ); -} - -// ================== PFB ==================== - -class TQPSPrinterFontPFB - : public TQPSPrinterFontPrivate { -public: - TQPSPrinterFontPFB(const TQFontEngine *f, TQByteArray& data); - virtual void download(TQTextStream& s, bool global); - virtual bool embedded() { return TRUE; } -private: - TQByteArray data; -}; - -TQPSPrinterFontPFB::TQPSPrinterFontPFB(const TQFontEngine *f, TQByteArray& d) -{ - data = d; - - int pos = 0; - int len; - // int typ; - unsigned char* p = (unsigned char*) data.data(); - TQString fontname; - - if (p[ pos ] != 0x80) { // PFB marker - tqWarning("pfb file does not start with 0x80"); - return; - } - pos++; - // typ = p[ pos ]; // 1=ascii 2=binary 3=done - pos++; - len = p[ pos ]; pos++; - len |= (p[ pos ] << 8) ; pos++; - len |= (p[ pos ] << 16); pos++; - len |= (p[ pos ] << 24); pos++; - - //printf("font block type %d len %d\n",typ,len); - - char* fontnameptr = strstr((char*)p+pos,"/FontName"); - if (fontnameptr == NULL) - return; - - fontnameptr += strlen("/FontName") + 1; - while (*fontnameptr == ' ' || *fontnameptr == '/') fontnameptr++; - int l=0; - while (fontnameptr[l] != ' ') l++; - - psname = TQString::fromLatin1(fontnameptr,l); - replacementList = makePSFontNameList( f, psname ); -} - -void TQPSPrinterFontPFB::download(TQTextStream& s, bool global) -{ - emitPSFontNameList( s, psname, replacementList); - - if ( !embedFonts ) { - downloadMapping(s, global); - return; - } - - //tqDebug("downloading pfb font %s", psname.latin1() ); - unsigned char* p = (unsigned char*) data.data(); - int pos; - int len; - int typ; - - int hexcol = 0; - int line_length = 64; - - s << "% Font resource\n"; - - pos = 0; - typ = -1; - while (typ != 3) { // not end of file - if (p[ pos ] != 0x80) // PFB marker - return; // pfb file does not start with 0x80 - pos++; - typ = p[ pos ]; // 1=ascii 2=binary 3=done - pos++; - - if (typ == 3) break; - - len = p[ pos ]; pos++; - len |= (p[ pos ] << 8) ; pos++; - len |= (p[ pos ] << 16); pos++; - len |= (p[ pos ] << 24); pos++; - - //tqDebug("font block type %d len %d",typ,len); - - int end = pos + len; - if (typ==1) { - while (pos < end) { - if (hexcol > 0) { - s << "\n"; - hexcol = 0; - } - //tqWarning(TQString::fromLatin1((char*)(p+pos),1)); - if (p[pos] == '\r' || p[pos] == '\n') { - s << "\n"; - while (pos < end && (p[pos] == '\r' || p[pos] == '\n')) - pos++; - } else { - s << TQString::fromLatin1((char*)(p+pos),1); - pos++; - } - } - } - if (typ==2) { - static const char *hexchar = "0123456789abcdef"; - while (pos < end) { - /* trim hexadecimal lines to line_length columns */ - if (hexcol >= line_length) { - s << "\n"; - hexcol = 0; - } - s << TQString::fromLatin1(hexchar+((p[pos] >> 4) & 0xf),1) - << TQString::fromLatin1(hexchar+((p[pos] ) & 0xf),1); - pos++; - hexcol += 2; - } - } - } - s << "% End of font resource\n"; - downloadMapping( s, global ); -} - -// ================== AFontFileNotFound ============ - - - -class TQPSPrinterFontNotFound - : public TQPSPrinterFontPrivate { -public: - TQPSPrinterFontNotFound(const TQFontEngine* f); - virtual void download(TQTextStream& s, bool global); -private: - TQByteArray data; -}; - -TQPSPrinterFontNotFound::TQPSPrinterFontNotFound(const TQFontEngine* f) -{ - psname = makePSFontName( f ); - replacementList = makePSFontNameList( f ); -} - -void TQPSPrinterFontNotFound::download(TQTextStream& s, bool) -{ - //tqDebug("downloading not found font %s", psname.latin1() ); - emitPSFontNameList( s, psname, replacementList ); - s << "% No embeddable font for "; - s << psname; - s << " found\n"; - TQPSPrinterFontPrivate::download(s, TRUE); -} - -#ifndef TQT_NO_TEXTCODEC -// =================== A font file for asian ============ - -class TQPSPrinterFontAsian - : public TQPSPrinterFontPrivate { -public: - TQPSPrinterFontAsian() - : TQPSPrinterFontPrivate(), codec( 0 ) {} - void download(TQTextStream& s, bool global); - TQString defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, - TQPSPrinterPrivate *d ); - void drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, - const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint ); - - TQString makePSFontName( const TQFontEngine *f, int type ) const; - virtual TQString extension() const = 0; - - TQTextCodec *codec; -}; - -TQString TQPSPrinterFontAsian::makePSFontName( const TQFontEngine *f, int type ) const -{ - TQString ps; - int i; - - TQString family = f->fontDef.family.lower(); - - // try to make a "good" postscript name - ps = family.simplifyWhiteSpace(); - i = 0; - while( (unsigned int)i < ps.length() ) { - if ( i != 0 && ps[i] == '[') { - if ( ps[i-1] == ' ' ) - ps.truncate (i-1); - else - ps.truncate (i); - break; - } - if ( i == 0 || ps[i-1] == ' ' ) { - ps[i] = ps[i].upper(); - if ( i ) - ps.remove( i-1, 1 ); - else - i++; - } else { - i++; - } - } - - switch ( type ) { - case 1: - ps.append( TQString::fromLatin1("-Italic") ); - break; - case 2: - ps.append( TQString::fromLatin1("-Bold") ); - break; - case 3: - ps.append( TQString::fromLatin1("-BoldItalic") ); - break; - case 0: - default: - break; - } - - ps += extension(); - - return ps; -} - - -TQString TQPSPrinterFontAsian::defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, - const TQString &key, TQPSPrinterPrivate *d) -{ - TQString fontName; - TQString fontName2; - - TQString *tmp = d->headerFontNames.find( ps ); - - if ( d->buffer ) { - if ( tmp ) { - fontName = *tmp; - } else { - fontName.sprintf( "F%d", ++d->headerFontNumber ); - d->fontStream << "/" << fontName << " false " << ps << "List MF\n"; - d->headerFontNames.insert( ps, new TQString( fontName ) ); - } - fontName2.sprintf( "F%d", ++d->headerFontNumber ); - d->fontStream << "/" << fontName2 << " " - << pointSize( f, d->scale ) << "/" << fontName << " DF\n"; - d->headerFontNames.insert( key, new TQString( fontName2 ) ); - } else { - if ( tmp ) { - fontName = *tmp; - } else { - fontName.sprintf( "F%d", ++d->pageFontNumber ); - stream << "/" << fontName << " false " << ps << "List MF\n"; - d->pageFontNames.insert( ps, new TQString( fontName ) ); - } - fontName2.sprintf( "F%d", ++d->pageFontNumber ); - stream << "/" << fontName2 << " " - << pointSize( f, d->scale ) << "/" << fontName << " DF\n"; - d->pageFontNames.insert( key, new TQString( fontName2 ) ); - } - return fontName2; -} - - -void TQPSPrinterFontAsian::download(TQTextStream& s, bool) -{ - //tqDebug("downloading asian font %s", psname.latin1() ); - s << "% Asian postscript font requested. Using " - << psname << endl; - emitPSFontNameList( s, psname, replacementList ); -} - -void TQPSPrinterFontAsian::drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, - const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint) -{ - int len = engine->length( item ); - TQScriptItem &si = engine->items[item]; - - int x = p.x() + si.x; - int y = p.y() + si.y; - if ( y != d->textY || d->textY == 0 ) - stream << y << " Y"; - d->textY = y; - - TQString mdf; - if ( paint->font().underline() ) - mdf += " " + TQString().setNum( y + d->fm.underlinePos() + d->fm.lineWidth() ) + - " " + toString( d->fm.lineWidth() ) + " Tl"; - if ( paint->font().strikeOut() ) - mdf += " " + TQString().setNum( y + d->fm.strikeOutPos() ) + - " " + toString( d->fm.lineWidth() ) + " Tl"; - TQCString mb; - TQCString out; - TQString dummy( TQChar(0x20) ); - - if ( si.analysis.bidiLevel % 2 ) { - for ( int i = len-1; i >= 0; i-- ) { - TQChar ch = text.unicode()[i]; - if ( !ch.row() ) { - ; // ignore, we should never get here anyway - } else { - if ( codec ) { - dummy[0] = ch; - mb = codec->fromUnicode( dummy ); - } else - mb = " "; - - for ( unsigned int j = 0; j < mb.length (); j++ ) { - if ( mb.at(j) == '(' || mb.at(j) == ')' || mb.at(j) == '\\' ) - out += "\\"; - out += mb.at(j); - } - } - } - } else { - for ( int i = 0; i < len; i++ ) { - TQChar ch = text.unicode()[i]; - if ( !ch.row() ) { - ; // ignore, we should never get here anyway - } else { - if ( codec ) { - dummy[0] = ch; - mb = codec->fromUnicode( dummy ); - } else - mb = " "; - - for ( unsigned int j = 0; j < mb.length (); j++ ) { - if ( mb.at(j) == '(' || mb.at(j) == ')' || mb.at(j) == '\\' ) - out += "\\"; - out += mb.at(j); - } - } - } - } - stream << "(" << out << ")" << si.width << " " << x << mdf << " AT\n"; -} - -// ----------- Japanese -------------- - -static const psfont Japanese1 [] = { - { "Ryumin-Light-H", 0, 100. }, - { "Ryumin-Light-H", 0.2, 100. }, - { "GothicBBB-Medium-H", 0, 100. }, - { "GothicBBB-Medium-H", 0.2, 100. } -}; - -static const psfont Japanese1a [] = { - { "GothicBBB-Medium-H", 0, 100. }, - { "GothicBBB-Medium-H", 0.2, 100. }, - { "Ryumin-Light-H", 0, 100. }, - { "Ryumin-Light-H", 0.2, 100. } -}; - -static const psfont Japanese2 [] = { - { "GothicBBB-Medium-H", 0, 100. }, - { "GothicBBB-Medium-H", 0.2, 100. }, - { "GothicBBB-Medium-H", 0, 100. }, - { "GothicBBB-Medium-H", 0.2, 100. } -}; - -static const psfont Japanese2a [] = { - { "Ryumin-Light-H", 0, 100. }, - { "Ryumin-Light-H", 0.2, 100. }, - { "Ryumin-Light-H", 0, 100. }, - { "Ryumin-Light-H", 0.2, 100. } -}; - - -// Wadalab fonts - -static const psfont WadaMin [] = { - { "WadaMin-Regular-H", 0, 100. }, - { "WadaMin-Regular-H", 0.2, 100. }, - { "WadaMin-Bold-H", 0, 100. }, - { "WadaMin-Bold-H", 0.2, 100. } -}; - -static const psfont WadaGo [] = { - { "WadaMaruGo-Regular-H", 0, 100. }, - { "WadaMaruGo-Regular-H", 0.2, 100. }, - { "WadaGo-Bold-H", 0, 100. }, - { "WadaGo-Bold-H", 0.2, 100. } -}; - -// Adobe Wadalab - -static const psfont WadaGoAdobe [] = { - { "WadaMaruGo-RegularH-Hojo-H", 0, 100. }, - { "WadaMaruGo-RegularH-Hojo-H", 0.2, 100. }, - { "WadaMaruGo-RegularH-Hojo-H", 0, 100. }, - { "WadaMaruGo-RegularH-Hojo-H", 0.2, 100. }, -}; -static const psfont WadaMinAdobe [] = { - { "WadaMin-RegularH-Hojo-H", 0, 100. }, - { "WadaMin-RegularH-Hojo-H", 0.2, 100. }, - { "WadaMin-RegularH-Hojo-H", 0, 100. }, - { "WadaMin-RegularH-Hojo-H", 0.2, 100. }, -}; - - -static const psfont * const Japanese1Replacements[] = { - Japanese1, Japanese1a, WadaMin, WadaGo, WadaMinAdobe, WadaGoAdobe, 0 -}; -static const psfont * const Japanese2Replacements[] = { - Japanese2, Japanese2a, WadaMin, WadaGo, WadaMinAdobe, WadaGoAdobe, 0 -}; - -class TQPSPrinterFontJapanese - : public TQPSPrinterFontAsian { -public: - TQPSPrinterFontJapanese(const TQFontEngine* f); - virtual TQString extension() const; -}; - -TQPSPrinterFontJapanese::TQPSPrinterFontJapanese(const TQFontEngine* f) -{ - codec = TQTextCodec::codecForMib( 63 ); // jisx0208.1983-0 - - int type = getPsFontType( f ); - psname = makePSFontName( f, type ); - TQString best = "[ /" + psname + " 1.0 0.0 ]"; - replacementList.append( best ); - - const psfont *const *replacements = ( psname.contains( "Helvetica" ) ? Japanese2Replacements : Japanese1Replacements ); - appendReplacements( replacementList, replacements, type ); -} - -TQString TQPSPrinterFontJapanese::extension() const -{ - return "-H"; -} - -// ----------- Korean -------------- - -// sans serif -static const psfont SMGothic [] = { - { "SMGothic-Medium-KSC-EUC-H", 0, 100. }, - { "SMGothic-Medium-KSC-EUC-H", 0.2, 100. }, - { "SMGothic-DemiBold-KSC-EUC-H", 0, 100. }, - { "SMGothic-DemiBold-KSC-EUC-H", 0.2, 100. } -}; - -// serif -#if 0 // ### this is never used? -static const psfont SMMyungjo [] = { - { "SMMyungjo-Light-KSC-EUC-H", 0, 100. }, - { "SMMyungjo-Light-KSC-EUC-H", 0.2, 100. }, - { "SMMyungjo-Bold-KSC-EUC-H", 0, 100. }, - { "SMMyungjo-Bold-KSC-EUC-H", 0.2, 100. } -}; -#endif - -static const psfont MKai [] = { - { "MingMT-Light-KSC-EUC-H", 0, 100. }, - { "MingMT-Light-KSC-EUC-H", 0.2, 100. }, - { "MKai-Medium-KSC-EUC-H", 0, 100. }, - { "MKai-Medium-KSC-EUC-H", 0.2, 100. }, -}; - - -static const psfont Munhwa [] = { - { "Munhwa-Regular-KSC-EUC-H", 0, 100. }, - { "Munhwa-Regular-KSC-EUC-H", 0.2, 100. }, - { "Munhwa-Bold-KSC-EUC-H", 0, 100. }, - { "Munhwa-Bold-KSC-EUC-H", 0.2, 100. } -}; - -static const psfont MunhwaGothic [] = { - { "MunhwaGothic-Regular-KSC-EUC-H", 0, 100. }, - { "MunhwaGothic-Regular-KSC-EUC-H", 0.2, 100. }, - { "MunhwaGothic-Bold-KSC-EUC-H", 0, 100. }, - { "MunhwaGothic-Bold-KSC-EUC-H", 0.2, 100. } -}; - -static const psfont MunhwaGungSeo [] = { - { "MunhwaGungSeo-Light-KSC-EUC-H", 0, 100. }, - { "MunhwaGungSeo-Light-KSC-EUC-H", 0.2, 100. }, - { "MunhwaGungSeo-Bold-KSC-EUC-H", 0, 100. }, - { "MunhwaGungSeo-Bold-KSC-EUC-H", 0.2, 100. } -}; - -static const psfont MunhwaGungSeoHeulim [] = { - { "MunhwaGungSeoHeulim-Light-KSC-EUC-H", 0, 100. }, - { "MunhwaGungSeoHeulim-Light-KSC-EUC-H", 0.2, 100. }, - { "MunhwaGungSeoHeulim-Bold-KSC-EUC-H", 0, 100. }, - { "MunhwaGungSeoHeulim-Bold-KSC-EUC-H", 0.2, 100. } -}; - -static const psfont MunhwaHoonMin [] = { - { "MunhwaHoonMin-Regular-KSC-EUC-H", 0, 100. }, - { "MunhwaHoonMin-Regular-KSC-EUC-H", 0.2, 100. }, - { "MunhwaHoonMin-Regular-KSC-EUC-H", 0, 100. }, - { "MunhwaHoonMin-Regular-KSC-EUC-H", 0.2, 100. } -}; - -static const psfont BaekmukGulim [] = { - { "Baekmuk-Gulim-KSC-EUC-H", 0, 100. }, - { "Baekmuk-Gulim-KSC-EUC-H", 0.2, 100. }, - { "Baekmuk-Gulim-KSC-EUC-H", 0, 100. }, - { "Baekmuk-Gulim-KSC-EUC-H", 0.2, 100. } -}; - -static const psfont * const KoreanReplacements[] = { - BaekmukGulim, SMGothic, Munhwa, MunhwaGothic, MKai, MunhwaGungSeo, - MunhwaGungSeoHeulim, MunhwaHoonMin, Helvetica, 0 -}; - -class TQPSPrinterFontKorean - : public TQPSPrinterFontAsian { -public: - TQPSPrinterFontKorean(const TQFontEngine* f); - TQString extension() const; -}; - -TQPSPrinterFontKorean::TQPSPrinterFontKorean(const TQFontEngine* f) -{ - codec = TQTextCodec::codecForMib( 38 ); // eucKR - int type = getPsFontType( f ); - psname = makePSFontName( f, type ); - TQString best = "[ /" + psname + " 1.0 0.0 ]"; - replacementList.append( best ); - appendReplacements( replacementList, KoreanReplacements, type ); -} - -TQString TQPSPrinterFontKorean::extension() const -{ - return "-KSC-EUC-H"; -} -// ----------- traditional chinese ------------ - -// Arphic Public License Big5 TrueType fonts (on Debian and CLE and others) -static const psfont ShanHeiSun [] = { - { "ShanHeiSun-Light-ETen-B5-H", 0, 100. }, - { "ShanHeiSun-Light-ETen-B5-H", 0.2, 100. }, - { "ShanHeiSun-Light-ETen-B5-H", 0, 100. }, - { "ShanHeiSun-Light-ETen-B5-H", 0.2, 100. }, -}; -static const psfont ZenKai [] = { - { "ZenKai-Medium-ETen-B5-H", 0, 100. }, - { "ZenKai-Medium-Italic-ETen-B5-H", 0.2, 100. }, - { "ZenKai-Medium-Bold-ETen-B5-H", 0, 100. }, - { "ZenKai-Medium-BoldItalic-ETen-B5-H", 0.2, 100. }, -}; - -// Fonts on Turbolinux -static const psfont SongB5 [] = { - { "B5-MSung-Light-ETen-B5-H", 0, 100. }, - { "B5-MSung-Italic-ETen-B5-H", 0, 100. }, - { "B5-MSung-Bold-ETen-B5-H", 0, 100. }, - { "B5-MSung-BoldItalic-ETen-B5-H", 0, 100. }, -}; -static const psfont KaiB5 [] = { - { "B5-MKai-Medium-ETen-B5-H", 0, 100. }, - { "B5-MKai-Italic-ETen-B5-H", 0, 100. }, - { "B5-MKai-Bold-ETen-B5-H", 0, 100. }, - { "B5-MKai-BoldItalic-ETen-B5-H", 0, 100. }, -}; -static const psfont HeiB5 [] = { - { "B5-MHei-Medium-ETen-B5-H", 0, 100. }, - { "B5-MHei-Italic-ETen-B5-H", 0, 100. }, - { "B5-MHei-Bold-ETen-B5-H", 0, 100. }, - { "B5-MHei-BoldItalic-ETen-B5-H", 0, 100. }, -}; -static const psfont FangSongB5 [] = { - { "B5-CFangSong-Light-ETen-B5-H", 0, 100. }, - { "B5-CFangSong-Italic-ETen-B5-H", 0, 100. }, - { "B5-CFangSong-Bold-ETen-B5-H", 0, 100. }, - { "B5-CFangSong-BoldItalic-ETen-B5-H", 0, 100. }, -}; - -// Arphic fonts on Thiz Linux -static const psfont LinGothic [] = { - { "LinGothic-Light-ETen-B5-H", 0, 100. }, - { "LinGothic-Light-Italic-ETen-B5-H", 0.2, 100. }, - { "LinGothic-Light-Bold-ETen-B5-H", 0, 100. }, - { "LinGothic-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, -}; -static const psfont YenRound [] = { - { "YenRound-Light-ETen-B5-H", 0, 100. }, - { "YenRound-Light-Italic-ETen-B5-H", 0.2, 100. }, - { "YenRound-Light-Bold-ETen-B5-H", 0, 100. }, - { "YenRound-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, -}; - -// Dr. Wang Hann-Tzong's GPL'ed Big5 TrueType fonts -#if 0 // ### this is never used? -static const psfont HtWFangSong [] = { - { "HtW-FSong-Light-ETen-B5-H", 0, 100. }, - { "HtW-FSong-Light-Italic-ETen-B5-H", 0.2, 100. }, - { "HtW-FSong-Light-Bold-ETen-B5-H", 0, 100. }, - { "HtW-FSong-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, -}; -#endif - -static const psfont MingB5 [] = { - { "Ming-Light-ETen-B5-H", 0, 100. }, - { "Ming-Light-Italic-ETen-B5-H", 0.2, 100. }, - { "Ming-Light-Bold-ETen-B5-H", 0, 100. }, - { "Ming-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, -}; - -// Microsoft's Ming/Sung font? -static const psfont MSung [] = { - { "MSung-Light-ETenms-B5-H", 0, 100. }, - { "MSung-Light-ETenms-B5-H", 0.2, 100. }, - { "MSung-Light-ETenms-B5-H", 0, 100. }, - { "MSung-Light-ETenms-B5-H", 0.2, 100. }, -}; -// "Standard Sung/Ming" font by Taiwan Ministry of Education -static const psfont MOESung [] = { - { "MOESung-Regular-B5-H", 0, 100. }, - { "MOESung-Regular-B5-H", 0.2, 100. }, - { "MOESung-Regular-B5-H", 0, 100. }, - { "MOESung-Regular-B5-H", 0.2, 100. }, -}; - -static const psfont MOEKai [] = { - { "MOEKai-Regular-B5-H", 0, 100. }, - { "MOEKai-Regular-B5-H", 0.2, 100. }, - { "MOEKai-Regular-B5-H", 0, 100. }, - { "MOEKai-Regular-B5-H", 0.2, 100. }, -}; - -static const psfont * const TraditionalReplacements[] = { - MOESung, SongB5, ShanHeiSun, MingB5, MSung, FangSongB5, KaiB5, ZenKai, HeiB5, - LinGothic, YenRound, MOEKai, Helvetica, 0 - }; - -#if 0 // ### these are never used? -static const psfont * const SongB5Replacements[] = { - SongB5, ShanHeiSun, MingB5, MSung, MOESung, Helvetica, 0 - }; - -static const psfont * const FangSongB5Replacements[] = { - FangSongB5, HtWFangSong, Courier, 0 - }; -static const psfont * const KaiB5Replacements[] = { - KaiB5, ZenKai, Times, 0 - }; -static const psfont * const HeiB5Replacements[] = { - HeiB5, LinGothic, YenRound, LucidaSans, 0 - }; -static const psfont * const YuanB5Replacements[] = { - YenRound, LinGothic, HeiB5, LucidaSans, 0 - }; -#endif - - -class TQPSPrinterFontTraditionalChinese - : public TQPSPrinterFontAsian { -public: - TQPSPrinterFontTraditionalChinese(const TQFontEngine* f); - TQString extension() const; -}; - -TQPSPrinterFontTraditionalChinese::TQPSPrinterFontTraditionalChinese(const TQFontEngine* f) -{ - codec = TQTextCodec::codecForMib( 2026 ); // Big5-0 - int type = getPsFontType( f ); - psname = makePSFontName( f, type ); - TQString best = "[ /" + psname + " 1.0 0.0 ]"; - replacementList.append( best ); - appendReplacements( replacementList, TraditionalReplacements, type ); -} - -TQString TQPSPrinterFontTraditionalChinese::extension() const -{ - return "-ETen-B5-H"; -} - -// ----------- simplified chinese ------------ - -#if 0 -// GB18030 fonts on XteamLinux (?) -static const psfont SimplifiedGBK2K [] = { - { "MSung-Light-GBK2K-H", 0, 100. }, - { "MSung-Light-GBK2K-H", 0.2, 100. }, - { "MKai-Medium-GBK2K-H", 0, 100. }, - { "MKai-Medium-GBK2K-H", 0.2, 100. }, -}; -#endif - -// GB18030 fonts on Turbolinux -static const psfont SongGBK2K [] = { - { "MSung-Light-GBK2K-H", 0, 100. }, - { "MSung-Italic-GBK2K-H", 0, 100. }, - { "MSung-Bold-GBK2K-H", 0, 100. }, - { "MSung-BoldItalic-GBK2K-H", 0, 100. }, -}; -static const psfont KaiGBK2K [] = { - { "MKai-Medium-GBK2K-H", 0, 100. }, - { "MKai-Italic-GBK2K-H", 0, 100. }, - { "MKai-Bold-GBK2K-H", 0, 100. }, - { "MKai-BoldItalic-GBK2K-H", 0, 100. }, -}; -static const psfont HeiGBK2K [] = { - { "MHei-Medium-GBK2K-H", 0, 100. }, - { "MHei-Italic-GBK2K-H", 0, 100. }, - { "MHei-Bold-GBK2K-H", 0, 100. }, - { "MHei-BoldItalic-GBK2K-H", 0, 100. }, -}; -static const psfont FangSongGBK2K [] = { - { "CFangSong-Light-GBK2K-H", 0, 100. }, - { "CFangSong-Italic-GBK2K-H", 0, 100. }, - { "CFangSong-Bold-GBK2K-H", 0, 100. }, - { "CFangSong-BoldItalic-GBK2K-H", 0, 100. }, -}; - -static const psfont Simplified [] = { - { "MSung-Light-GBK-EUC-H", 0, 100. }, - { "MSung-Light-GBK-EUC-H", 0.2, 100. }, - { "MKai-Medium-GBK-EUC-H", 0, 100. }, - { "MKai-Medium-GBK-EUC-H", 0.2, 100. }, -}; - -static const psfont MSungGBK [] = { - { "MSung-Light-GBK-EUC-H", 0, 100. }, - { "MSung-Light-GBK-EUC-H", 0.2, 100. }, - { "MSung-Light-GBK-EUC-H", 0, 100. }, - { "MSung-Light-GBK-EUC-H", 0.2, 100. }, -}; - -static const psfont FangSong [] = { - { "CFangSong-Light-GBK-EUC-H", 0, 100. }, - { "CFangSong-Light-GBK-EUC-H", 0.2, 100. }, - { "CFangSong-Light-GBK-EUC-H", 0, 100. }, - { "CFangSong-Light-GBK-EUC-H", 0.2, 100. }, -}; - -// Arphic Public License GB2312 TrueType fonts (on Debian and CLE and others) -static const psfont BousungEG [] = { - { "BousungEG-Light-GB-GB-EUC-H", 0, 100. }, - { "BousungEG-Light-GB-GB-EUC-H", 0.2, 100. }, - { "BousungEG-Light-GB-Bold-GB-EUC-H", 0, 100. }, - { "BousungEG-Light-GB-Bold-GB-EUC-H", 0.2, 100. }, -}; -static const psfont GBZenKai [] = { - { "GBZenKai-Medium-GB-GB-EUC-H", 0, 100. }, - { "GBZenKai-Medium-GB-GB-EUC-H", 0.2, 100. }, - { "GBZenKai-Medium-GB-Bold-GB-EUC-H", 0, 100. }, - { "GBZenKai-Medium-GB-Bold-GB-EUC-H", 0.2, 100. }, -}; - -static const psfont * const SimplifiedReplacements[] = { - SongGBK2K, FangSongGBK2K, KaiGBK2K, HeiGBK2K, - Simplified, MSungGBK, FangSong, BousungEG, GBZenKai, Helvetica, 0 - }; -#if 0 -static const psfont * const SongGBK2KReplacements[] = { - SongGBK2K, MSungGBK, BousungEG, Helvetica, 0 - }; -#endif -static const psfont * const FangSongGBK2KReplacements[] = { - FangSongGBK2K, FangSong, Courier, 0 - }; -static const psfont * const KaiGBK2KReplacements[] = { - KaiGBK2K, GBZenKai, Times, 0 - }; -static const psfont * const HeiGBK2KReplacements[] = { - HeiGBK2K, LucidaSans, 0 - }; - -class TQPSPrinterFontSimplifiedChinese - : public TQPSPrinterFontAsian { -public: - TQPSPrinterFontSimplifiedChinese(const TQFontEngine* f); - TQString extension() const; -}; - -TQPSPrinterFontSimplifiedChinese::TQPSPrinterFontSimplifiedChinese(const TQFontEngine* f) -{ - codec = TQTextCodec::codecForMib( 114 ); // GB18030 - int type = getPsFontType( f ); - TQString family = f->fontDef.family.lower(); - if( family.contains("kai",FALSE) ) { - psname = KaiGBK2K[type].psname; - appendReplacements( replacementList, KaiGBK2KReplacements, type ); - } else if( family.contains("fangsong",FALSE) ) { - psname = FangSongGBK2K[type].psname; - appendReplacements( replacementList, FangSongGBK2KReplacements, type ); - } else if( family.contains("hei",FALSE) ) { - psname = HeiGBK2K[type].psname; - appendReplacements( replacementList, HeiGBK2KReplacements, type ); - } else { - psname = SongGBK2K[type].psname; - appendReplacements( replacementList, SimplifiedReplacements, type ); - } - //tqDebug("simplified chinese: fontname is %s, psname=%s", f.family().latin1(), psname.latin1() ); -} - -TQString TQPSPrinterFontSimplifiedChinese::extension() const -{ - return "-GBK2K-H"; -} - -#endif - - -// ================== TQPSPrinterFont ==================== - -class TQPSPrinterFont { -public: - TQPSPrinterFont(const TQFont& f, int script, TQPSPrinterPrivate *priv); - ~TQPSPrinterFont(); - TQString postScriptFontName() { return p->postScriptFontName(); } - TQString defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, - TQPSPrinterPrivate *d ) - { return p->defineFont( stream, ps, f, key, d ); } - void download(TQTextStream& s, bool global) { p->download(s, global); } - TQPSPrinterFontPrivate *handle() { return p; } - TQString xfontname; -private: - TQByteArray data; - TQPSPrinterFontPrivate* p; -}; - -TQPSPrinterFont::~TQPSPrinterFont() -{ - // the dict in TQFontPrivate does deletion for us. - // delete p; -} - - -TQPSPrinterFont::TQPSPrinterFont(const TQFont &f, int script, TQPSPrinterPrivate *priv) - : p(0) -{ - TQString fontfilename; - TQString fontname; - - enum { NONE, PFB, PFA, TTF } type = NONE; - - TQFontEngine *engine = f.d->engineForScript( (TQFont::Script) script ); - xfontname = makePSFontName( engine ); - -#if defined( TQ_WS_X11 ) - bool xlfd = FALSE; - //tqDebug("engine = %p name=%s, script=%d", engine, engine ? engine->name() : "(null)", script); - -#ifndef TQT_NO_XFTFREETYPE - if ( tqt_has_xft && engine && engine->type() == TQFontEngine::Xft ) { - XftPattern *pattern = static_cast( engine )->pattern(); - char *filename = 0; - XftPatternGetString (pattern, XFT_FILE, 0, &filename); - //tqDebug("filename for font is '%s'", filename); - if ( filename ) { - fontfilename = TQString::fromLocal8Bit( filename ); - xfontname = fontfilename; - } - } else -#endif - { - TQString rawName; - if ( engine && engine != (TQFontEngine *)-1 ) - rawName = engine->name(); - int index = rawName.find('-'); - if (index == 0) { - // this is an XLFD font name - for (int i=0; i < 6; i++) { - index = rawName.find('-',index+1); - } - xfontname = rawName.mid(0,index); - if ( xfontname.endsWith( "*" ) ) - xfontname.truncate( xfontname.length() - 1 ); - xlfd = TRUE; - } - } -#endif // TQ_WS_X11 -#ifndef TQT_NO_TEXTCODEC - // map some scripts to something more useful - if ( script == TQFont::Han ) { - TQTextCodec *lc = TQTextCodec::codecForLocale(); - switch( lc->mibEnum() ) { - case 36: // KS C 5601 - case 38: // EUC KR - script = TQFont::Hangul; - break; - - case 57: // gb2312.1980-0 - case 113: // GBK - case -113: // gbk-0 - case 114: // GB18030 - case -114: // gb18030-0 - case 2025: // GB2312 - case 2026: // Big5 - case -2026: // Big5-HKSCS - case 2101: // big5-0, big5.eten-0 - case -2101: // big5hkscs-0, hkscs-1 - break; - - case 16: // JIS7 - case 17: // SJIS - case 18: // EUC JP - case 63: // JIS X 0208 - default: - script = TQFont::Hiragana; - break; - } - } else if ( script == TQFont::Katakana ) - script = TQFont::Hiragana; - else if ( script == TQFont::Bopomofo ) - script = TQFont::Han; -#endif - - TQString searchname = xfontname; -#if defined(TQ_WS_X11) - // we need an extension here due to the fact that we use different - // fonts for different scripts - if ( xlfd && script >= TQFont::Han && script <= TQFont::Bopomofo ) - xfontname += "/" + toString( script ); -#endif - - //tqDebug("looking for font %s in dict", xfontname.latin1() ); - p = priv->fonts.find(xfontname); - if ( p ) - return; - -#if defined(TQ_WS_X11) - if ( xlfd ) { - - for (TQStringList::Iterator it=priv->fontpath.begin(); it!=priv->fontpath.end() && fontfilename.isEmpty(); ++it) { - if ((*it).left(1) != "/") continue; // not a path name, a font server - TQString fontmapname; - int num = 0; - // search font.dir and font.scale for the right file - while ( num < 2 ) { - if ( num == 0 ) - fontmapname = (*it) + "/fonts.scale"; - else - fontmapname = (*it) + "/fonts.dir"; - //tqWarning(fontmapname); - TQFile fontmap(fontmapname); - if (fontmap.open(IO_ReadOnly)) { - while (!fontmap.atEnd()) { - TQString mapping; - fontmap.readLine(mapping,512); - // fold to lower (since X folds to lowercase) - //tqWarning(xfontname); - //tqWarning(mapping); - if (mapping.lower().contains(searchname.lower())) { - int index = mapping.find(' ',0); - TQString ffn = mapping.mid(0,index); - // remove the most common bitmap formats - if( !ffn.contains( ".pcf" ) && !ffn.contains( ".bdf" ) && - !ffn.contains( ".spd" ) && !ffn.contains( ".phont" ) ) { - fontfilename = (*it) + TQString("/") + ffn; - if ( TQFile::exists(fontfilename) ) { - //tqDebug("found font file %s", fontfilename.latin1()); - break; - } else // unset fontfilename - fontfilename = TQString(); - } - } - } - fontmap.close(); - } - num++; - } - } - } -#endif - - //tqDebug("font=%s, fontname=%s, file=%s, p=%p", f.family().latin1(), xfontname.latin1(), fontfilename.latin1(), p); - - // memory mapping would be better here - if (fontfilename.length() > 0) { // maybe there is no file name - TQFile fontfile(fontfilename); - if ( fontfile.exists() ) { - //printf("font name %s size = %d\n",fontfilename.latin1(),fontfile.size()); - data = TQByteArray( fontfile.size() ); - - fontfile.open(IO_Raw | IO_ReadOnly); - fontfile.readBlock(data.data(), fontfile.size()); - fontfile.close(); - } - } - - if (!data.isNull() && data.size() > 0) { - unsigned char* d = (unsigned char *)data.data(); - if (d[0] == 0x80 && d[1] == 0x01 && d[6] == '%' && d[7] == '!') - type = PFB; - else if (d[0] == '%' && d[1] == '!' && d[2] == 'P' && d[3] == 'S') - type = PFA; - else if (d[0]==0x00 && d[1]==0x01 && d[2]==0x00 && d[3]==0x00) - type = TTF; - else - type = NONE; - } else - type = NONE; - - //tqDebug("font is of type %d", type ); - switch (type) { - case TTF : - p = new TQPSPrinterFontTTF(engine, data); - break; - case PFB: - p = new TQPSPrinterFontPFB(engine, data); - break; - case PFA: - p = new TQPSPrinterFontPFA(engine, data); - break; - case NONE: - default: - -#ifndef TQT_NO_TEXTCODEC - - if ( script == TQFont::Hiragana ) - p = new TQPSPrinterFontJapanese( engine ); - else if ( script == TQFont::Hangul ) - p = new TQPSPrinterFontKorean( engine ); - else if ( script == TQFont::Han ) { - TQTextCodec *lc = TQTextCodec::codecForLocale(); - switch( lc->mibEnum() ) { - case 2025: // GB2312 - case 57: // gb2312.1980-0 - case 113: // GBK - case -113: // gbk-0 - case 114: // GB18030 - case -114: // gb18030-0 - p = new TQPSPrinterFontSimplifiedChinese( engine ); - break; - case 2026: // Big5 - case -2026: // big5-0, big5.eten-0 - case 2101: // Big5-HKSCS - case -2101: // big5hkscs-0, hkscs-1 - p = new TQPSPrinterFontTraditionalChinese( engine ); - break; - default: - p = new TQPSPrinterFontJapanese( engine ); - } - } else -#endif - //tqDebug("didnt find font for %s", xfontname.latin1()); - p = new TQPSPrinterFontNotFound( engine ); - break; - } - - if (p->postScriptFontName() == "Symbol") - p->setSymbol(); - - // this is needed to make sure we don't get the same postscriptname twice - TQDictIterator it( priv->fonts ); - for( it.toFirst(); it.current(); ++it ) { - if ( *(*it) == *p ) { -// tqWarning("Post script driver: font already in dict"); - delete p; - p = *it; - return; - } - } - - //tqDebug("inserting font %s in dict psname=%s", xfontname.latin1(), p->postScriptFontName().latin1() ); - priv->fonts.insert( xfontname, p ); -} - -// ================= END OF PS FONT METHODS ============ - - -TQPSPrinterPrivate::TQPSPrinterPrivate( TQPrinter *prt, int filedes ) - : buffer( 0 ), outDevice( 0 ), fd( filedes ), pageBuffer( 0 ), fonts(27, FALSE), fontBuffer(0), savedImage( 0 ), - dirtypen( FALSE ), dirtybrush( FALSE ), dirtyBkColor( FALSE ), bkMode( TQt::TransparentMode ), dirtyBkMode( FALSE ), -#ifndef TQT_NO_TEXTCODEC - currentFontCodec( 0 ), -#endif - fm( TQFont() ), textY( 0 ) -{ - printer = prt; - headerFontNames.setAutoDelete( TRUE ); - pageFontNames.setAutoDelete( TRUE ); - fonts.setAutoDelete( TRUE ); - currentFontFile = 0; - scale = 1.; - scriptUsed = -1; - -#ifdef TQ_WS_X11 - // append tqsettings fontpath - TQSettings settings; - embedFonts = settings.readBoolEntry( "/qt/embedFonts", TRUE ); - - int npaths; - char** font_path; - font_path = XGetFontPath( tqt_xdisplay(), &npaths); - bool xfsconfig_read = FALSE; - for (int i=0; i read its config - bool finished = FALSE; - TQFile f("/etc/X11/fs/config"); - if ( !f.exists() ) - f.setName("/usr/X11R6/lib/X11/fs/config"); - if ( !f.exists() ) - f.setName("/usr/X11/lib/X11/fs/config"); - if ( f.exists() ) { - f.open(IO_ReadOnly); - while(f.status()==IO_Ok && !finished) { - TQString fs; - f.readLine(fs, 1024); - fs=fs.stripWhiteSpace(); - if (fs.left(9)=="catalogue" && fs.contains('=')) { - fs=fs.mid(fs.find('=')+1).stripWhiteSpace(); - bool end = FALSE; - while( f.status()==IO_Ok && !end ) { - if ( fs[int(fs.length())-1] == ',' ) - fs = fs.left(fs.length()-1); - else - end = TRUE; - if (fs[0] != '#' && !fs.contains(":unscaled")) - fontpath += fs; - f.readLine(fs, 1024); - fs=fs.stripWhiteSpace(); - } - finished = TRUE; - } - } - f.close(); - } - xfsconfig_read = TRUE; - } else if(!strstr(font_path[i], ":unscaled")) { - // Fonts paths marked :unscaled are always bitmapped fonts - // -> we can as well ignore them now and save time - fontpath += font_path[i]; - } - } - XFreeFontPath(font_path); - - // append tqsettings fontpath - TQStringList fp = settings.readListEntry( "/qt/fontPath", ':' ); - if ( !fp.isEmpty() ) - fontpath += fp; -#else - embedFonts = FALSE; -#endif -} - -TQPSPrinterPrivate::~TQPSPrinterPrivate() -{ - delete pageBuffer; -} - -void TQPSPrinterPrivate::setFont( const TQFont & fnt, int script ) -{ - TQFont f = fnt; - if ( f.rawMode() ) { - TQFont fnt( TQString::fromLatin1("Helvetica"), 12 ); - setFont( fnt, TQFont::Unicode ); - return; - } - if ( f.pointSize() == 0 ) { -#if defined(CHECK_RANGE) - tqWarning( "TQPrinter: Cannot set a font with zero point size." ); -#endif - f.setPointSize(TQApplication::font().pointSize()); - if ( f.pointSize() == 0 ) - f.setPointSize( 11 ); - } - - TQPSPrinterFont ff( f, script, this ); - TQString ps = ff.postScriptFontName(); - - TQString s = ps; - s.append( ' ' ); - s.prepend( ' ' ); - - TQString key = ff.xfontname; - - if ( f.pointSize() != -1 ) - key += " " + toString( f.pointSize() ); - else - key += " px" + toString( f.pixelSize() ); - TQString * tmp; - if ( !buffer ) - tmp = pageFontNames.find( key ); - else - tmp = headerFontNames.find( key ); - - TQString fontName; - if ( tmp ) - fontName = *tmp; - - if ( fontName.isEmpty() ) { - fontName = ff.defineFont( pageStream, ps, f, key, this ); - } - pageStream << fontName << " F\n"; - - ps.append( ' ' ); - ps.prepend( ' ' ); - if ( !fontsUsed.contains( ps ) ) - fontsUsed += ps; - -#ifndef TQT_NO_TEXTCODEC - TQTextCodec * codec = 0; -// ### -// #ifndef TQT_NO_TEXTCODEC -// i = 0; -// do { -// if ( unicodevalues[i].cs == f.charSet() ) -// codec = TQTextCodec::codecForMib( unicodevalues[i++].mib ); -// } while( codec == 0 && unicodevalues[i++].cs != unicodevalues_LAST ); -// #endif - currentFontCodec = codec; -#endif - currentFont = fontName; - currentFontFile = ff.handle(); - scriptUsed = script; -} - - -static void ps_r7( TQTextStream& stream, const char * s, int l ) -{ - int i = 0; - uchar line[79]; - int col = 0; - - while( i < l ) { - line[col++] = s[i++]; - if ( col >= 76 ) { - line[col++] = '\n'; - line[col++] = '\0'; - stream << (const char *)line; - col = 0; - } - } - if ( col > 0 ) { - while( (col&3) != 0 ) - line[col++] = '%'; // use a comment as padding - line[col++] = '\n'; - line[col++] = '\0'; - stream << (const char *)line; - } -} - - -static const int quoteSize = 3; // 1-8 pixels -static const int maxQuoteLength = 4+16+32+64+128+256; // magic extended quote -static const int quoteReach = 10; // ... 1-1024 pixels back -static const int tableSize = 1024; // 2 ** quoteReach; -static const int numAttempts = 128; - -static const int hashSize = 71; - -static const int None = INT_MAX; - -/* puts the lowest numBits of data into the out array starting at postion (byte/bit). - Adjusts byte and bit to point ot the next position. - - Need to make sure the out array is long enough before calling the method. -*/ -static void emitBits( char *out, int & byte, int & bit, - int numBits, uint data ) -{ - int b = 0; - uint d = data; - while( b < numBits ) { - if ( bit == 0 ) - out[byte] = 0; - if ( d & 1 ) - out[byte] = (uchar)out[byte] | ( 1 << bit ); - d = d >> 1; - b++; - bit++; - if ( bit > 6 ) { - bit = 0; - byte++; - } - } -} - -//#define DEBUG_COMPRESS -#ifdef DEBUG_COMPRESS -#include -#endif - -static TQByteArray compress( const TQImage & image, bool gray ) { -#ifdef DEBUG_COMPRESS - TQTime t; - t.start(); - int sizeUncompressed[11]; - for( int i = 0; i < 11; i++ ) - sizeUncompressed[i] = 0; - int sizeCompressed[11]; - for( int i = 0; i < 11; i++ ) - sizeCompressed[i] = 0; -#endif - - int width = image.width(); - int height = image.height(); - int depth = image.depth(); - int size = width*height; - - int pastPixel[tableSize]; - int mostRecentPixel[hashSize]; - if ( depth == 1 ) - size = (width+7)/8*height; - else if ( !gray ) - size = size*3; - - unsigned char *pixel = new unsigned char[size+1]; - int i = 0; - if ( depth == 1 ) { - TQImage::Endian bitOrder = image.bitOrder(); - memset( pixel, 0xff, size ); - for( int y=0; y < height; y++ ) { - uchar * s = image.scanLine( y ); - for( int x=0; x < width; x++ ) { - // need to copy bit for bit... - bool b = ( bitOrder == TQImage::LittleEndian ) ? - (*(s + (x >> 3)) >> (x & 7)) & 1 : - (*(s + (x >> 3)) << (x & 7)) & 0x80 ; - if ( b ) - pixel[i >> 3] ^= (0x80 >> ( i & 7 )); - i++; - } - // we need to align to 8 bit here - i = (i+7) & 0xffffff8; - } - } else if ( depth == 8 ) { - for( int y=0; y < height; y++ ) { - uchar * s = image.scanLine( y ); - for( int x=0; x < width; x++ ) { - TQRgb rgb = image.color( s[x] ); - if ( gray ) { - pixel[i] = (unsigned char) tqGray( rgb ); - i++; - } else { - pixel[i] = (unsigned char) tqRed( rgb ); - pixel[i+1] = (unsigned char) tqGreen( rgb ); - pixel[i+2] = (unsigned char) tqBlue( rgb ); - i += 3; - } - } - } - } else { - bool alpha = image.hasAlphaBuffer(); - for( int y=0; y < height; y++ ) { - TQRgb * s = (TQRgb*)(image.scanLine( y )); - for( int x=0; x < width; x++ ) { - TQRgb rgb = (*s++); - if ( alpha && tqAlpha( rgb ) < 0x40 ) // 25% alpha, convert to white - - rgb = tqRgb( 0xff, 0xff, 0xff ); - if ( gray ) { - pixel[i] = (unsigned char) tqGray( rgb ); - i++; - } else { - pixel[i] = (unsigned char) tqRed( rgb ); - pixel[i+1] = (unsigned char) tqGreen( rgb ); - pixel[i+2] = (unsigned char) tqBlue( rgb ); - i += 3; - } - } - } - } - - pixel[size] = 0; - - /* this compression function emits blocks of data, where each - block is an unquoted series of pixels, or a quote from earlier - pixels. if the six-letter string "banana" were a six-pixel - image, it might be unquoted "ban" followed by a 3-pixel quote - from -2. note that the final "a" is then copied from the - second "a", which is copied from the first "a" in the same copy - operation. - - the scanning for quotable blocks uses a cobol-like loop and a - hash table: we know how many pixels we need to quote, hash the - first and last pixel we need, and then go backwards in time - looking for some spot where those pixels of those two colours - occur at the right distance from each other. - - when we find a spot, we'll try a string-compare of all the - intervening pixels. we only do a maximum of 128 both-ends - compares or 64 full-string compares. it's more important to be - fast than get the ultimate in compression. - - The format of the compressed stream is as follows: - // 2 bits step size for search and backreference ( 1 or 3 ) - 1 bit compressed or uncompressed block follows - - uncompressed block: - 3 bits size of block in bytes - size*8 bits data - - compressed block: - 3 bits compression header - 0-2 size of block is 1-3 bytes - 3-7 size of block is bigger, 4-8 additional bits specifying size follow - 0/4-8 additional size fields - 10 location of backreference - */ - - for( i=0; i < hashSize; i++ ) - mostRecentPixel[i] = None; - int index = 0; - int emittedUntil = 0; - char *out = (char *)malloc( 256 * sizeof( char ) ); - int outLen = 256; - int outOffset = 0; - int outBit = 0; - - /* we process pixels serially, emitting as necessary/possible. */ - while( index <= size ) { - int bestCandidate = None; - int bestLength = 0; - i = index % tableSize; - int h = pixel[index] % hashSize; - int start, end; - start = end = pastPixel[i] = mostRecentPixel[h]; - mostRecentPixel[h] = index; - /* if our first candidate quote is unusable, or we don't need - to quote because we've already emitted something for this - pixel, just skip. */ - if ( start < index - tableSize || index >= size || - emittedUntil > index) - start = end = None; - int attempts = 0; - /* scan for suitable quote candidates: not too far back, and - if we've found one that's as big as it can get, don't look - for more */ - while( start != None && end != None && - bestLength < maxQuoteLength && - start >= index - tableSize && - end >= index - tableSize + bestLength ) { - /* scan backwards, looking for something good enough to - try a (slow) string comparison. we maintain indexes to - the start and the end of the quote candidate here */ - while( start != None && end != None && - ( pixel[start] != pixel[index] || - pixel[end] != pixel[index+bestLength] ) ) { - if ( attempts++ > numAttempts ) { - start = None; - } else if ( pixel[end] % hashSize == - pixel[index+bestLength] % hashSize ) { - /* we move the area along the end index' chain */ - end = pastPixel[end%tableSize]; - start = end - bestLength; - } else if ( pixel[start] % hashSize == - pixel[index] % hashSize ) { - /* ... or along the start index' chain */ - start = pastPixel[start%tableSize]; - end = start + bestLength; - } else { -#if 0 - /* this should never happen: both the start and - the end pointers ran off their tracks. */ - tqDebug( "oops! %06x %06x %06x %06x %5d %5d %5d %d", - pixel[start], pixel[end], - pixel[index], pixel[index+bestLength], - start, end, index, bestLength ); -#endif - /* but if it should happen, no problem. we'll just - say we found nothing, and the compression will - be a bit worse. */ - start = None; - } - /* if we've moved either index too far to use the - quote candidate, let's just give up here. there's - also a guard against "start" insanity. */ - if ( start < index - tableSize || start < 0 || start >= index ) - start = None; - if ( end < index - tableSize + bestLength || end < bestLength ) - end = None; - } - /* ok, now start and end point to an area of suitable - length whose first and last points match, or one/both - is/are set to None. */ - if ( start != None && end != None ) { - /* slow string compare... */ - int length = 0; - while( length < maxQuoteLength && - index+length < size && - pixel[start+length] == pixel[index+length] ) - length++; - /* if we've found something that overlaps the index - point, maybe we can move the quote point back? if - we're copying 10 pixels from 8 pixels back (an - overlap of 2), that'll be faster than copying from - 4 pixels back (an overlap of 6). */ - if ( start + length > index && length > 0 ) { - int d = index-start; - int equal = TRUE; - while( equal && start + length > index && - start > d && start-d >= index-tableSize ) { - int i = 0; - while( equal && i < d ) { - if( pixel[start+i] != pixel[start+i-d] ) - equal = FALSE; - i++; - } - if ( equal ) - start -= d; - } - } - /* if what we have is longer than the best previous - candidate, we'll use this one. */ - if ( length > bestLength ) { - attempts = 0; - bestCandidate = start; - bestLength = length; - if ( length < maxQuoteLength && index + length < size ) - end = mostRecentPixel[pixel[index+length]%hashSize]; - } else { - /* and if it ins't, we'll try some more. but we'll - count each string compare extra, since they're - so expensive. */ - attempts += 2; - if ( attempts > numAttempts ) { - start = None; - } else if ( pastPixel[start%tableSize] + bestLength < - pastPixel[end%tableSize] ) { - start = pastPixel[start%tableSize]; - end = start + bestLength; - } else { - end = pastPixel[end%tableSize]; - start = end - bestLength; - } - } - /* again, if we can't make use of the current quote - candidate, we don't try any more */ - if ( start < index - tableSize || start < 0 || start > size+1 ) - start = None; - if ( end < index - tableSize + bestLength || end < 0 || end > size+1 ) - end = None; - } - } - /* backreferences to 1 byte of data are actually more costly than - emitting the data directly, 2 bytes don't save much. */ - if ( bestCandidate != None && bestLength < 3 ) - bestCandidate = None; - /* at this point, bestCandidate is a candidate of bestLength - length, or else it's None. if we have such a candidate, or - we're at the end, we have to emit all unquoted data. */ - if ( index == size || bestCandidate != None ) { - /* we need a double loop, because there's a maximum length - on the "unquoted data" section. */ - while( emittedUntil < index ) { -#ifdef DEBUG_COMPRESS - int x = 0; - int bl = emittedUntil - index; - while ( (bl /= 2) ) - x++; - if ( x > 10 ) x = 10; - sizeUncompressed[x]++; -#endif - int l = TQMIN( 8, index - emittedUntil ); - if ( outOffset + l + 2 >= outLen ) { - outLen *= 2; - out = (char *) realloc( out, outLen ); - } - emitBits( out, outOffset, outBit, - 1, 0 ); - emitBits( out, outOffset, outBit, - quoteSize, l-1 ); - while( l-- ) { - emitBits( out, outOffset, outBit, - 8, pixel[emittedUntil] ); - emittedUntil++; - } - } - } - /* if we have some quoted data to output, do it. */ - if ( bestCandidate != None ) { -#ifdef DEBUG_COMPRESS - int x = 0; - int bl = bestLength; - while ( (bl /= 2) ) - x++; - if ( x > 10 ) x = 10; - sizeCompressed[x]++; -#endif - if ( outOffset + 4 >= outLen ) { - outLen *= 2; - out = (char *) realloc( out, outLen ); - } - emitBits( out, outOffset, outBit, - 1, 1 ); - int l = bestLength - 3; - const struct off_len { - int off; - int bits; - } ol_table [] = { - /* Warning: if you change the table here, change /uc in the PS code! */ - { 3, 0/*dummy*/ }, - { 16, 4 }, - { 32, 5 }, - { 64, 6 }, - { 128, 7 }, - { /*256*/ 0xfffffff, 8 }, - }; - - if ( l < ol_table[0].off ) { - emitBits( out, outOffset, outBit, - quoteSize, l ); - } else { - const off_len *ol = ol_table; - l -= ol->off; - ol++; - while ( l >= ol->off ) { - l -= ol->off; - ol++; - } - emitBits( out, outOffset, outBit, - quoteSize, ol->bits-1 ); - emitBits( out, outOffset, outBit, - ol->bits, l ); - } - emitBits( out, outOffset, outBit, - quoteReach, index - bestCandidate - 1 ); - emittedUntil += bestLength; - } - index++; - } - /* we've output all the data; time to clean up and finish off the - last characters. */ - if ( outBit ) - outOffset++; - i = 0; - /* we have to make sure the data is encoded in a stylish way :) */ - while( i < outOffset ) { - uchar c = out[i]; - c += 42; - if ( c > 'Z' && ( c != 't' || i == 0 || out[i-1] != 'Q' ) ) - c += 84; - out[i] = c; - i++; - } - TQByteArray outarr; - outarr.duplicate( out, outOffset ); - free( out ); - delete [] pixel; - -#ifdef DEBUG_COMPRESS - tqDebug( "------------- image compression statistics ----------------" ); - tqDebug(" compression time %d", t.elapsed() ); - tqDebug( "Size dist of uncompressed blocks:" ); - tqDebug( "\t%d\t%d\t%d\t%d\t%d\t%d\n", sizeUncompressed[0], sizeUncompressed[1], - sizeUncompressed[2], sizeUncompressed[3], sizeUncompressed[4], sizeUncompressed[5]); - tqDebug( "\t%d\t%d\t%d\t%d\t%d\n", sizeUncompressed[6], sizeUncompressed[7], - sizeUncompressed[8], sizeUncompressed[9], sizeUncompressed[10] ); - tqDebug( "Size dist of compressed blocks:" ); - tqDebug( "\t%d\t%d\t%d\t%d\t%d\t%d\n", sizeCompressed[0], sizeCompressed[1], - sizeCompressed[2], sizeCompressed[3], sizeCompressed[4], sizeCompressed[5]); - tqDebug( "\t%d\t%d\t%d\t%d\t%d\n", sizeCompressed[6], sizeCompressed[7], - sizeCompressed[8], sizeCompressed[9], sizeCompressed[10] ); - tqDebug( "===> total compression ratio %d/%d = %f", outOffset, size, (float)outOffset/(float)size ); - tqDebug( "-----------------------------------------------------------" ); -#endif - - return outarr; -} - -#undef XCOORD -#undef YCOORD -#undef WIDTH -#undef HEIGHT -#undef POINT -#undef RECT -#undef INT_ARG - -#define XCOORD(x) (float)(x) -#define YCOORD(y) (float)(y) -#define WIDTH(w) (float)(w) -#define HEIGHT(h) (float)(h) - -#define POINT(index) XCOORD(p[index].point->x()) << ' ' << \ - YCOORD(p[index].point->y()) << ' ' -#define RECT(index) XCOORD(p[index].rect->normalize().x()) << ' ' << \ - YCOORD(p[index].rect->normalize().y()) << ' ' << \ - WIDTH (p[index].rect->normalize().width()) << ' ' << \ - HEIGHT(p[index].rect->normalize().height()) << ' ' -#define INT_ARG(index) p[index].ival << ' ' - -static char returnbuffer[13]; -static const char * color( const TQColor &c, TQPrinter * printer ) -{ - if ( c == TQt::black ) - qstrcpy( returnbuffer, "B " ); - else if ( c == TQt::white ) - qstrcpy( returnbuffer, "W " ); - else if ( c.red() == c.green() && c.red() == c.blue() ) - sprintf( returnbuffer, "%d d2 ", c.red() ); - else if ( printer->colorMode() == TQPrinter::GrayScale ) - sprintf( returnbuffer, "%d d2 ", - tqGray( c.red(), c.green(),c.blue() ) ); - else - sprintf( returnbuffer, "%d %d %d ", - c.red(), c.green(), c.blue() ); - return returnbuffer; -} - - -static const char * psCap( TQt::PenCapStyle p ) -{ - if ( p == TQt::SquareCap ) - return "2 "; - else if ( p == TQt::RoundCap ) - return "1 "; - return "0 "; -} - - -static const char * psJoin( TQt::PenJoinStyle p ) { - if ( p == TQt::BevelJoin ) - return "2 "; - else if ( p == TQt::RoundJoin ) - return "1 "; - return "0 "; -} - - - -void TQPSPrinterPrivate::drawImage( TQPainter *paint, float x, float y, float w, float h, - const TQImage &img, const TQImage &mask ) -{ - if ( !w || !h || img.isNull() ) return; - - int width = img.width(); - int height = img.height(); - float scaleX = (float)width/w; - float scaleY = (float)height/h; - - bool gray = (printer->colorMode() == TQPrinter::GrayScale) || - img.allGray(); - int splitSize = 21830 * (gray ? 3 : 1 ); - if ( width * height > splitSize ) { // 65535/3, tolerance for broken printers - int images, subheight; - images = ( width * height + splitSize - 1 ) / splitSize; - subheight = ( height + images-1 ) / images; - while ( subheight * width > splitSize ) { - images++; - subheight = ( height + images-1 ) / images; - } - int suby = 0; - while( suby < height ) { - drawImage(paint, x, y + suby/scaleY, w, TQMIN( subheight, height-suby )/scaleY, - img.copy( 0, suby, width, TQMIN( subheight, height-suby ) ), - mask.isNull() ? mask : mask.copy( 0, suby, width, TQMIN( subheight, height-suby ) )); - suby += subheight; - } - } else { - TQByteArray out; - int size = 0; - const char *bits; - - if ( !mask.isNull() ) { - out = ::compress( mask, TRUE ); - size = (width+7)/8*height; - pageStream << "/mask " << size << " string uc\n"; - ps_r7( pageStream, out, out.size() ); - pageStream << "d\n"; - } - if ( img.depth() == 1 ) { - size = (width+7)/8*height; - bits = "1 "; - } else if ( gray ) { - size = width*height; - bits = "8 "; - } else { - size = width*height*3; - bits = "24 "; - } - - out = ::compress( img, gray ); - pageStream << "/sl " << size << " string uc\n"; - ps_r7( pageStream, out, out.size() ); - pageStream << "d\n" - << width << ' ' << height << "[" << scaleX << " 0 0 " << scaleY << " 0 0]sl " - << bits << (!mask.isNull() ? "mask " : "false ") - << x << ' ' << y << " di\n"; - } -} - - -void TQPSPrinterPrivate::matrixSetup( TQPainter *paint ) -{ -#ifndef TQT_NO_TRANSFORMATIONS - TQWMatrix tmp; - if ( paint->hasViewXForm() ) { - TQRect viewport = paint->viewport(); - TQRect window = paint->window(); - tmp.translate( viewport.x(), viewport.y() ); - tmp.scale( 1.0 * viewport.width() / window.width(), - 1.0 * viewport.height() / window.height() ); - tmp.translate( -window.x(), -window.y() ); - } - if ( paint->hasWorldXForm() ) { - tmp = paint->worldMatrix() * tmp; - } - pageStream << "[" - << tmp.m11() << ' ' << tmp.m12() << ' ' - << tmp.m21() << ' ' << tmp.m22() << ' ' - << tmp.dx() << ' ' << tmp.dy() - << "]ST\n"; -#else - TQPoint p(0,0); - p = paint->xForm(p); - pageStream << "[" - << 0 << ' ' << 0 << ' ' - << 0 << ' ' << 0 << ' ' - << p.x() << ' ' << p.y() - << "]ST\n"; -#endif - dirtyMatrix = FALSE; -} - -void TQPSPrinterPrivate::orientationSetup() -{ - if ( printer->orientation() == TQPrinter::Landscape ) - pageStream << "TQLS\n"; -} - - -void TQPSPrinterPrivate::emitHeader( bool finished ) -{ - TQString title = printer->docName(); - TQString creator = printer->creator(); - if ( !creator ) // default creator - creator = TQString::fromLatin1("TQt " TQT_VERSION_STR); - outDevice = new TQFile(); - (void)((TQFile *)outDevice)->open( IO_WriteOnly, fd ); - outStream.setDevice( outDevice ); - outStream << "%!PS-Adobe-1.0"; - TQPaintDeviceMetrics m( printer ); - scale = 72. / ((float) m.logicalDpiY()); - uint mtop, mleft, mbottom, mright; - printer->margins( &mtop, &mleft, &mbottom, &mright ); - int width = m.width(); - int height = m.height(); - bool fullPage = printer->fullPage(); - if ( finished && pageCount == 1 && printer->numCopies() == 1 && - ( ( printer->fullPage() && qt_gen_epsf ) || - ( printer->outputToFile() && printer->outputFileName().endsWith( ".eps" ) ) ) - ) { - if ( !boundingBox.isValid() ) - boundingBox.setRect( 0, 0, width, height ); - if ( printer->orientation() == TQPrinter::Landscape ) { - if ( !fullPage ) - boundingBox.moveBy( -mleft, -mtop ); - outStream << " EPSF-3.0\n%%BoundingBox: " - << (int)(m.height() - boundingBox.bottom())*scale << " " // llx - << (int)(m.width() - boundingBox.right())*scale - 1 << " " // lly - << (int)(m.height() - boundingBox.top())*scale + 1 << " " // urx - << (int)(m.width() - boundingBox.left())*scale; // ury - } else { - if ( !fullPage ) - boundingBox.moveBy( mleft, -mtop ); - outStream << " EPSF-3.0\n%%BoundingBox: " - << (int)(boundingBox.left())*scale << " " - << (int)(m.height() - boundingBox.bottom())*scale - 1 << " " - << (int)(boundingBox.right())*scale + 1 << " " - << (int)(m.height() - boundingBox.top())*scale; - } - } else { - int w = width + (fullPage ? 0 : mleft + mright); - int h = height + (fullPage ? 0 : mtop + mbottom); - w = (int)(w*scale); - h = (int)(h*scale); - // set a bounding box according to the DSC - if ( printer->orientation() == TQPrinter::Landscape ) - outStream << "\n%%BoundingBox: 0 0 " << h << " " << w; - else - outStream << "\n%%BoundingBox: 0 0 " << w << " " << h; - } - outStream << "\n" << wrapDSC( "%%Creator: " + creator ); - if ( !!title ) - outStream << wrapDSC( "%%Title: " + title ); - outStream << "%%CreationDate: " << TQDateTime::currentDateTime().toString(); - outStream << "\n%%Orientation: "; - if ( printer->orientation() == TQPrinter::Landscape ) - outStream << "Landscape"; - else - outStream << "Portrait"; - if ( finished ) - outStream << "\n%%Pages: " << pageCount << "\n" - << wrapDSC( "%%DocumentFonts: " + fontsUsed ); - else - outStream << "%%Pages: (atend)" - << "\n%%DocumentFonts: (atend)"; - outStream << "\n%%EndComments\n"; - - outStream << "%%BeginProlog\n"; - const char * const prologLicense = "% Prolog copyright 1994-2006 Trolltech. " - "You may copy this prolog in any way\n" - "% that is directly related to this " - "document. For other use of this prolog,\n" - "% see your licensing agreement for TQt.\n"; - outStream << prologLicense << ps_header << "\n"; - - // we have to do this here, as scaling can affect this. - TQString lineStyles = "/LArr[" // Pen styles: - " [] []" // solid line - " [ w s ] [ s w ]" // dash line - " [ s s ] [ s s ]" // dot line - " [ m s s s ] [ s m s s ]" // dash dot line - " [ m s s s s ] [ s m s s s s ]" // dash dot dot line - " ] d\n"; - lineStyles.replace( TQRegExp( "w" ), toString( 10./scale ) ); - lineStyles.replace( TQRegExp( "m" ), toString( 5./scale ) ); - lineStyles.replace( TQRegExp( "s" ), toString( 3./scale ) ); - - outStream << lineStyles; - - outStream << "/pageinit {\n"; - if ( !printer->fullPage() ) { - if ( printer->orientation() == TQPrinter::Portrait ) - outStream << mleft*scale << " " - << mbottom*scale << " translate\n"; - else - outStream << mtop*scale << " " - << mleft*scale << " translate\n"; - } - if ( printer->orientation() == TQPrinter::Portrait ) { - outStream << "% " << m.widthMM() << "*" << m.heightMM() - << "mm (portrait)\n0 " << height*scale - << " translate " << scale << " -" << scale << " scale/defM matrix CM d } d\n"; - } else { - outStream << "% " << m.heightMM() << "*" << m.widthMM() - << " mm (landscape)\n 90 rotate " << scale << " -" << scale << " scale/defM matrix CM d } d\n"; - } - outStream << "%%EndProlog\n"; - - - outStream << "%%BeginSetup\n"; - if ( printer->numCopies() > 1 ) { - outStream << "/#copies " << printer->numCopies() << " def\n"; - outStream << "/NumCopies " << printer->numCopies() << " SPD\n"; - outStream << "/Collate " << (printer->collateCopies() ? "true" : "false") << " SPD\n"; - } - if ( fontBuffer->buffer().size() ) { - if ( pageCount == 1 || finished ) - outStream << "% Fonts and encodings used\n"; - else - outStream << "% Fonts and encodings used on pages 1-" - << pageCount << "\n"; - TQDictIterator it(fonts); - while (it.current()) { - it.current()->download(outStream,TRUE); // true means its global - ++it; - } - outStream.writeRawBytes( fontBuffer->buffer().data(), - fontBuffer->buffer().size() ); - } - outStream << "%%EndSetup\n"; - - outStream.writeRawBytes( buffer->buffer().data(), - buffer->buffer().size() ); - - delete buffer; - buffer = 0; - fontStream.unsetDevice(); - delete fontBuffer; - fontBuffer = 0; -} - - -/* Called whenever a restore has been done. Currently done at the top of a - new page and whenever clipping is turned off. */ -void TQPSPrinterPrivate::resetDrawingTools( TQPainter *paint ) -{ - TQPen defaultPen; // default drawing tools - TQBrush defaultBrush; - - TQColor c = paint->backgroundColor(); - if ( c != TQt::white ) - pageStream << color( c, printer ) << "BC\n"; - - if ( paint->backgroundMode() != TQt::TransparentMode ) - pageStream << "/OMo true d\n"; - - //currentUsed = currentSet; - //setFont( currentSet ); - currentFontFile = 0; - - TQBrush b = paint->brush(); - if ( b != defaultBrush ) { - if ( b == TQt::CustomPattern ) { -#if defined(CHECK_RANGE) - tqWarning( "TQPrinter: Pixmap brush not supported" ); -#endif - } else { - cbrush = b; - } - } - - dirtypen = TRUE; - dirtybrush = TRUE; - - if ( paint->hasViewXForm() || paint->hasWorldXForm() ) - matrixSetup( paint ); -} - - -static void putRect( TQTextStream &stream, const TQRect &r ) -{ - stream << r.x() << " " - << r.y() << " " - << r.width() << " " - << r.height() << " "; -} - - -void TQPSPrinterPrivate::setClippingOff( TQPainter *paint ) -{ - pageStream << "CLO\n"; // clipping off, includes a restore - resetDrawingTools( paint ); // so drawing tools must be reset -} - - -void TQPSPrinterPrivate::clippingSetup( TQPainter *paint ) -{ - if ( paint->hasClipping() ) { - if ( !firstClipOnPage ) - setClippingOff( paint ); - const TQRegion rgn = paint->clipRegion(); - TQMemArray rects = rgn.rects(); - int i; - pageStream<< "CLSTART\n"; // start clipping - for( i = 0 ; i < (int)rects.size() ; i++ ) { - putRect( pageStream, rects[i] ); - pageStream << "ACR\n"; // add clip rect - if ( pageCount == 1 ) - boundingBox = boundingBox.unite( rects[i] ); - } - pageStream << "CLEND\n"; // end clipping - firstClipOnPage = FALSE; - } else { - if ( !firstClipOnPage ) // no need to turn off if first on page - setClippingOff( paint ); - // if we're painting without clipping, the bounding box must - // be everything. NOTE: this assumes that this function is - // only ever called when something is to be painted. - TQPaintDeviceMetrics m( printer ); - if ( !boundingBox.isValid() ) - boundingBox.setRect( 0, 0, m.width(), m.height() ); - } - dirtyClipping = FALSE; -} - -void TQPSPrinterPrivate::initPage(TQPainter *paint) -{ - - // a restore undefines all the fonts that have been defined - // inside the scope (normally within pages) and all the glyphs that - // have been added in the scope. - - TQDictIterator it(fonts); - while (it.current()) { - it.current()->restore(); - ++it; - } - if ( !buffer ) { - pageFontNames.clear(); - } - - pageStream.unsetDevice(); - if ( pageBuffer ) - delete pageBuffer; - pageBuffer = new TQBuffer(); - pageBuffer->open( IO_WriteOnly ); - pageStream.setEncoding( TQTextStream::Latin1 ); - pageStream.setDevice( pageBuffer ); - delete savedImage; - savedImage = 0; - textY = 0; - dirtyClipping = TRUE; - firstClipOnPage = TRUE; - - - resetDrawingTools( paint ); - dirtyNewPage = FALSE; - pageFontNumber = headerFontNumber; -} - -void TQPSPrinterPrivate::flushPage( bool last ) -{ - if ( last && !pageBuffer ) - return; - bool pageFonts = ( buffer == 0 ); - if ( buffer && -// ( last || pagesInBuffer++ > -1 || -// ( pagesInBuffer > 4 && buffer->size() > 262144 ) ) ) - (last || buffer->size() > 50000000) - ) { -// tqDebug("emiting header at page %d", pageCount ); - emitHeader( last ); - } - outStream << "%%Page: " - << pageCount << ' ' << pageCount << endl - << "%%BeginPageSetup\n" - << "QI\n"; - if (!dirtyNewPage) { - if ( pageFonts ) { - //tqDebug("page fonts for page %d", pageCount); - // we have already downloaded the header. Maybe we have page fonts here - TQDictIterator it(fonts); - while (it.current()) { - it.current()->download( outStream, FALSE ); // FALSE means its for the page only - ++it; - } - } - outStream << "%%EndPageSetup\n"; - if ( pageBuffer ) - outStream.writeRawBytes( pageBuffer->buffer().data(), - pageBuffer->buffer().size() ); - } - outStream << "\nQP\n"; - pageCount++; -} - -// ================ PSPrinter class ======================== - -TQPSPrinter::TQPSPrinter( TQPrinter *prt, int fd ) - : TQPaintDevice( TQInternal::Printer | TQInternal::ExternalDevice ) -{ - d = new TQPSPrinterPrivate( prt, fd ); -} - - -TQPSPrinter::~TQPSPrinter() -{ - if ( d->fd >= 0 ) -#if defined(_OS_WIN32_) - ::_close( d->fd ); -#else - ::close( d->fd ); -#endif - delete d; -} - - - -static void ignoreSigPipe(bool b) -{ - static struct sigaction *users_sigpipe_handler = 0; - - if (b) { - if (users_sigpipe_handler != 0) - return; // already ignoring sigpipe - - users_sigpipe_handler = new struct sigaction; - struct sigaction tmp_sigpipe_handler; - tmp_sigpipe_handler.sa_handler = SIG_IGN; - sigemptyset(&tmp_sigpipe_handler.sa_mask); - tmp_sigpipe_handler.sa_flags = 0; - - if (sigaction(SIGPIPE, &tmp_sigpipe_handler, users_sigpipe_handler) == -1) { - delete users_sigpipe_handler; - users_sigpipe_handler = 0; - } - } - else { - if (users_sigpipe_handler == 0) - return; // not ignoring sigpipe - - if (sigaction(SIGPIPE, users_sigpipe_handler, 0) == -1) - tqWarning("TQPSPrinter: could not restore SIGPIPE handler"); - - delete users_sigpipe_handler; - users_sigpipe_handler = 0; - } -} - -bool TQPSPrinter::cmd( int c , TQPainter *paint, TQPDevCmdParam *p ) -{ - if ( c == PdcBegin ) { // start painting - d->pagesInBuffer = 0; - d->buffer = new TQBuffer(); - d->buffer->open( IO_WriteOnly ); - d->outStream.setEncoding( TQTextStream::Latin1 ); - d->outStream.setDevice( d->buffer ); - d->fontBuffer = new TQBuffer(); - d->fontBuffer->open( IO_WriteOnly ); - d->fontStream.setEncoding( TQTextStream::Latin1 ); - d->fontStream.setDevice( d->fontBuffer ); - d->headerFontNumber = 0; - d->pageCount = 1; // initialize state - d->dirtyMatrix = TRUE; - d->dirtyClipping = TRUE; - d->dirtyNewPage = TRUE; - d->firstClipOnPage = TRUE; - d->boundingBox = TQRect( 0, 0, -1, -1 ); - d->fontsUsed = TQString::fromLatin1(""); - - TQPaintDeviceMetrics m( d->printer ); - d->scale = 72. / ((float) m.logicalDpiY()); - - return TRUE; - } - - if ( c == PdcEnd ) { // painting done - bool pageCountAtEnd = (d->buffer != 0); - - // we're writing to lp/lpr through a pipe, we don't want to crash with SIGPIPE - // if lp/lpr dies - ignoreSigPipe(TRUE); - d->flushPage( TRUE ); - d->outStream << "%%Trailer\n"; - if ( pageCountAtEnd ) - d->outStream << "%%Pages: " << d->pageCount - 1 << "\n" << - wrapDSC( "%%DocumentFonts: " + d->fontsUsed ); - d->outStream << "%%EOF\n"; - ignoreSigPipe(FALSE); - - d->outStream.unsetDevice(); - if ( d->outDevice ) - d->outDevice->close(); - if ( d->fd >= 0 ) - ::close( d->fd ); - d->fd = -1; - delete d->outDevice; - d->outDevice = 0; - } - - if ( c >= PdcDrawFirst && c <= PdcDrawLast ) { - if ( !paint ) - return FALSE; // sanity - if ( d->dirtyNewPage ) - d->initPage( paint ); - if ( d->dirtyMatrix ) - d->matrixSetup( paint ); - if ( d->dirtyClipping ) // Must be after matrixSetup and initPage - d->clippingSetup( paint ); - if ( d->dirtypen ) { - // we special-case for narrow solid lines with the default - // cap and join styles - if ( d->cpen.style() == TQt::SolidLine && d->cpen.width() == 0 && - d->cpen.capStyle() == TQt::FlatCap && - d->cpen.joinStyle() == TQt::MiterJoin ) - d->pageStream << color( d->cpen.color(), d->printer ) << "P1\n"; - else - d->pageStream << (int)d->cpen.style() << ' ' << d->cpen.width() - << ' ' << color( d->cpen.color(), d->printer ) - << psCap( d->cpen.capStyle() ) - << psJoin( d->cpen.joinStyle() ) << "PE\n"; - d->dirtypen = FALSE; - } - if ( d->dirtybrush ) { - // we special-case for nobrush and solid white, since - // those are the two most common brushes - if ( d->cbrush.style() == TQt::NoBrush ) - d->pageStream << "NB\n"; - else if ( d->cbrush.style() == TQt::SolidPattern && - d->cbrush.color() == TQt::white ) - d->pageStream << "WB\n"; - else - d->pageStream << (int)d->cbrush.style() << ' ' - << color( d->cbrush.color(), d->printer ) << "BR\n"; - d->dirtybrush = FALSE; - } - if ( d->dirtyBkColor ) { - d->pageStream << color( d->bkColor, d->printer ) << "BC\n"; - d->dirtyBkColor = FALSE; - } - if ( d->dirtyBkMode ) { - if ( d->bkMode == TQt::TransparentMode ) - d->pageStream << "/OMo false d\n"; - else - d->pageStream << "/OMo true d\n"; - d->dirtyBkMode = FALSE; - } - } - - switch( c ) { - case PdcDrawPoint: - d->pageStream << POINT(0) << "P\n"; - break; - case PdcMoveTo: - d->pageStream << POINT(0) << "M\n"; - break; - case PdcLineTo: - d->pageStream << POINT(0) << "L\n"; - break; - case PdcDrawLine: - if ( p[0].point->y() == p[1].point->y() ) - d->pageStream << POINT(1) << p[0].point->x() << " HL\n"; - else if ( p[0].point->x() == p[1].point->x() ) - d->pageStream << POINT(1) << p[0].point->y() << " VL\n"; - else - d->pageStream << POINT(1) << POINT(0) << "DL\n"; - break; - case PdcDrawRect: - d->pageStream << RECT(0) << "R\n"; - break; - case PdcDrawRoundRect: - d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "RR\n"; - break; - case PdcDrawEllipse: - d->pageStream << RECT(0) << "E\n"; - break; - case PdcDrawArc: - d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "A\n"; - break; - case PdcDrawPie: - d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "PIE\n"; - break; - case PdcDrawChord: - d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "CH\n"; - break; - case PdcDrawLineSegments: - if ( p[0].ptarr->size() > 0 ) { - TQPointArray a = *p[0].ptarr; - TQPoint pt; - d->pageStream << "NP\n"; - for ( int i=0; i<(int)a.size(); i+=2 ) { - pt = a.point( i ); - d->pageStream << XCOORD(pt.x()) << ' ' - << YCOORD(pt.y()) << " MT\n"; - pt = a.point( i+1 ); - d->pageStream << XCOORD(pt.x()) << ' ' - << YCOORD(pt.y()) << " LT\n"; - } - d->pageStream << "QS\n"; - } - break; - case PdcDrawPolyline: - if ( p[0].ptarr->size() > 1 ) { - TQPointArray a = *p[0].ptarr; - TQPoint pt = a.point( 0 ); - d->pageStream << "NP\n" - << XCOORD(pt.x()) << ' ' << YCOORD(pt.y()) << " MT\n"; - for ( int i=1; i<(int)a.size(); i++ ) { - pt = a.point( i ); - d->pageStream << XCOORD(pt.x()) << ' ' - << YCOORD(pt.y()) << " LT\n"; - } - d->pageStream << "QS\n"; - } - break; - case PdcDrawPolygon: - if ( p[0].ptarr->size() > 2 ) { - TQPointArray a = *p[0].ptarr; - if ( p[1].ival ) - d->pageStream << "/WFi true d\n"; - TQPoint pt = a.point(0); - d->pageStream << "NP\n"; - d->pageStream << XCOORD(pt.x()) << ' ' - << YCOORD(pt.y()) << " MT\n"; - for( int i=1; i<(int)a.size(); i++) { - pt = a.point( i ); - d->pageStream << XCOORD(pt.x()) << ' ' - << YCOORD(pt.y()) << " LT\n"; - } - d->pageStream << "CP BF QS\n"; - if ( p[1].ival ) - d->pageStream << "/WFi false d\n"; - } - break; - case PdcDrawCubicBezier: - if ( p[0].ptarr->size() == 4 ) { - d->pageStream << "NP\n"; - TQPointArray a = *p[0].ptarr; - d->pageStream << XCOORD(a[0].x()) << ' ' - << YCOORD(a[0].y()) << " MT "; - for ( int i=1; i<4; i++ ) { - d->pageStream << XCOORD(a[i].x()) << ' ' - << YCOORD(a[i].y()) << ' '; - } - d->pageStream << "BZ\n"; - } - break; - case PdcDrawText2: - // we use drawTextItem instead - return TRUE; - case PdcDrawText2Formatted: - return TRUE; - case PdcDrawTextItem: { - const TQTextItem *ti = p[1].textItem; - TQScriptItem &si = ti->engine->items[ti->item]; - int len = ti->engine->length( ti->item ); - if ( si.isSpace || si.isObject ) - return FALSE; - - if ( d->currentSet != d->currentUsed || d->scriptUsed != si.analysis.script || !d->currentFontFile ) { - d->currentUsed = d->currentSet; - d->setFont( d->currentSet, si.analysis.script ); - } - if( d->currentFontFile ) // better not crash in case somethig goes wrong. - d->currentFontFile->drawText( d->pageStream, *p[0].point, ti->engine, ti->item, - ti->engine->string.mid( si.position, len ), d, paint); - return FALSE; - } - case PdcDrawPixmap: { - if ( p[1].pixmap->isNull() ) - break; - TQRect r = *p[0].rect; - TQImage img; - img = *(p[1].pixmap); - TQImage mask; - if ( p[1].pixmap->mask() ) - mask = *(p[1].pixmap->mask()); - d->drawImage(paint, r.x(), r.y(), r.width(), r.height(), img, mask); - break; - } - case PdcDrawImage: { - if ( p[1].image->isNull() ) - break; - TQRect r = *(p[0].rect); - TQImage img = *(p[1].image); - TQImage mask; -#ifndef TQT_NO_IMAGE_DITHER_TO_1 - if ( img.hasAlphaBuffer() ) - mask = img.createAlphaMask(); -#endif - d->drawImage(paint, r.x(), r.y(), r.width(), r.height(), img, mask); - break; - } - case PdcSetBkColor: - { - if ( d->bkColor != *(p[0].color) ) { - d->bkColor = *(p[0].color); - d->dirtyBkColor = TRUE; - } - break; - } - case PdcSetBkMode: - { - if ( d->bkMode != p[0].ival ) { - d->bkMode = (TQt::BGMode) p[0].ival; - d->dirtyBkMode = TRUE; - } - break; - } - case PdcSetROP: -#if defined(CHECK_RANGE) - if ( p[0].ival != TQt::CopyROP ) - tqWarning( "TQPrinter: Raster operation setting not supported" ); -#endif - break; - case PdcSetBrushOrigin: - break; - case PdcSetFont: - d->currentSet = *(p[0].font); - d->fm = paint->fontMetrics(); - // turn these off - they confuse the 'avoid font change' logic - d->currentSet.setUnderline( FALSE ); - d->currentSet.setStrikeOut( FALSE ); - break; - case PdcSetPen: - if ( d->cpen != *(p[0].pen) ) { - d->dirtypen = TRUE; - d->cpen = *(p[0].pen); - } - break; - case PdcSetBrush: - if ( p[0].brush->style() == TQt::CustomPattern ) { -#if defined(CHECK_RANGE) - tqWarning( "TQPrinter: Pixmap brush not supported" ); -#endif - return FALSE; - } - if ( d->cbrush != *(p[0].brush) ) { - d->dirtybrush = TRUE; - d->cbrush = *(p[0].brush); - } - break; - case PdcSetTabStops: - case PdcSetTabArray: - return FALSE; - case PdcSetUnit: - break; - case PdcSetVXform: - case PdcSetWindow: - case PdcSetViewport: - case PdcSetWXform: - case PdcSetWMatrix: - case PdcRestoreWMatrix: - d->dirtyMatrix = TRUE; - break; - case PdcSetClip: - d->dirtyClipping = TRUE; - break; - case PdcSetClipRegion: - d->dirtyClipping = TRUE; - break; - case NewPage: - // we're writing to lp/lpr through a pipe, we don't want to crash with SIGPIPE - // if lp/lpr dies - ignoreSigPipe(TRUE); - d->flushPage(); - ignoreSigPipe(FALSE); - - d->dirtyNewPage = TRUE; - break; - case AbortPrinting: - break; - default: - break; - } - return TRUE; -} - -#endif // TQT_NO_PRINTER diff --git a/src/kernel/qpsprinter.ps b/src/kernel/qpsprinter.ps deleted file mode 100644 index 12a4c4077..000000000 --- a/src/kernel/qpsprinter.ps +++ /dev/null @@ -1,805 +0,0 @@ -% the postscript header we use for our qpsprinter in uncompressed and commented form. -% use the makepsheader perl script to generate a compressed version of this header -% you can then paste into qpsprinter.cpp -% -% some compression of the code is done by the makepsheader script, so we don't need to -% write too criptically here. - -/d /def load def -/D {bind d} bind d -/d2 {dup dup} D -/B {0 d2} D -/W {255 d2} D -/ED {exch d} D -/D0 {0 ED} D -/LT {lineto} D -/MT {moveto} D -/S {stroke} D -/F {setfont} D -/SW {setlinewidth} D -/CP {closepath} D -/RL {rlineto} D -/NP {newpath} D -/CM {currentmatrix} D -/SM {setmatrix} D -/TR {translate} D -/SD {setdash} D -/SC {aload pop setrgbcolor} D -/CR {currentfile read pop} D -/i {index} D -/bs {bitshift} D -/scs {setcolorspace} D -/DB {dict dup begin} D -/DE {end d} D -/ie {ifelse} D -/sp {astore pop} D - -% ENDUNCOMPRESSED: Warning: leave this line in. -% Everything before this line will be left untouched by the compression - - - -/BSt 0 d % brush style -/LWi 1 d % line width -/PSt 1 d % pen style -/Cx 0 d % current x position -/Cy 0 d % current y position -/WFi false d % winding fill -/OMo false d % opaque mode (not transparent) - -/BCol [ 1 1 1 ] d % brush color -/PCol [ 0 0 0 ] d % pen color -/BkCol [ 1 1 1 ] d % background color -/BDArr [ % Brush dense patterns - 0.94 - 0.88 - 0.63 - 0.50 - 0.37 - 0.12 - 0.06 -] d -/defM matrix d - -/nS 0 d % number of saved painter states - -% LArr for the Pen styles is defined in emitHeader because of scaling - -% GPS: GetPenStyle -% Returns the line pattern (from pen style PSt). -% -% bool GPS pattern -% true : returns draw pattern -% false: returns fill pattern -/GPS { - PSt 1 ge PSt 5 le and % valid pen pattern? - { - { LArr PSt 1 sub 2 mul get } % draw pattern - { LArr PSt 2 mul 1 sub get } ifelse % opaque pattern - } - { [] } ifelse % out of range => solid line -} D - -% QS: QtStroke -% draw and fill current path -% -% - QS - -/QS { % stroke command - PSt 0 ne % != NO_PEN - { - gsave - LWi SW % set line width - true GPS 0 setdash S % draw line pattern - OMo PSt 1 ne and % opaque mode and not solid line? - { - BkCol SC - false GPS dup 0 get setdash S % fill in opaque pattern - } if - grestore - } if -} D - - - - -%% The following operations are used to read compressed data from the file -%% Until now this is only used for image compression - -% read 28 bits and leave them on tos -% -% - r28 num -/r28 { - % skip past whitespace and read one character - { currentfile read pop - dup 32 gt { exit } if - pop - } loop - % read three more - 3 { - currentfile read pop - } repeat - % make an accumulator - 0 - % for each character, shift the accumulator and add in the character - 4 { - 7 bitshift exch - dup 128 gt { 84 sub } if 42 sub 127 and - add - } repeat -} D - -/rA 0 d % accumulator -/rL 0 d % bits left - -% takes number of bits, leaves number -% -% num rB num -/rB { - rL 0 eq { - % if we have nothing, let's get something - /rA r28 d - /rL 28 d - } if - dup rL gt { - % if we don't have enough, take what we have and get more - rA exch rL sub rL exch - /rA 0 d /rL 0 d - rB exch bitshift add - } { - % else take some of what we have - dup rA 16#fffffff 3 -1 roll bitshift not and exch - % ... and update rL and rA - dup rL exch sub /rL ED - neg rA exch bitshift /rA ED - } ifelse -} D - -% uncompresses image data from currentfile until the string on the -% stack is full; leaves the string there. -% assumes that nothing could conceivably go wrong, ie. the compressed data has -% to be in the correct format and the length of the string has to be exactly right -% to hold the compressed data -% -% string uc string -% -%%% Warning: if you change the method here, change the table in qpsprinter.cpp:compress()! -/uc { - /rL 0 d - 0 - { % string pos - dup 2 index length ge { exit } if - 1 rB - 1 eq { % compressed - 3 rB % string pos bits - dup 3 ge { - 1 add dup rB % string pos bits extra - 1 index 5 ge { - 1 index 6 ge { - 1 index 7 ge { - 1 index 8 ge { - 128 add - } if - 64 add - } if - 32 add - } if - 16 add - } if - 3 add - exch pop - } if - 3 add - % string pos length - exch 10 rB 1 add - % string length pos dist - { - dup 3 index lt { - dup - } { - 2 index - } ifelse % string length pos dist length-this-time - 4 index 3 index 3 index sub 2 index getinterval - 5 index 4 index 3 -1 roll putinterval - dup 4 -1 roll add 3 1 roll - 4 -1 roll exch sub - dup 0 eq { exit } if - 3 1 roll - } loop % string pos dist length - pop pop - } { % uncompressed - 3 rB 1 add - { - 2 copy 8 rB put 1 add - } repeat - } ifelse - } loop - pop -} D - -%% image drawing routines - -/sl D0 % ### is this needed ? - -% defines for QCI -/QCIgray D0 /QCIcolor D0 /QCIindex D0 - -% this method prints color images if colorimage is available, otherwise -% converts the string to a grayscale image and uses the reular postscript image -% operator for printing. -% Arguments are the same as for the image operator: -% -% width height bits/sample matrix datasrc QCI - -/QCI { - /colorimage where { - pop - false 3 colorimage - }{ % the hard way, based on PD code by John Walker - exec /QCIcolor ED - /QCIgray QCIcolor length 3 idiv string d - 0 1 QCIcolor length 3 idiv 1 sub - { /QCIindex ED - /x QCIindex 3 mul d - QCIgray QCIindex - QCIcolor x get 0.30 mul - QCIcolor x 1 add get 0.59 mul - QCIcolor x 2 add get 0.11 mul - add add cvi - put - } for - QCIgray image - } ifelse -} D - -% general image drawing routine, used from the postscript driver -% -% Draws images with and without mask with 1, 8 and 24(rgb) bits depth. -% -% width height matrix image 1|8|24 mask|false x y di -% -% width and height specify the width/height of the image, -% matrix a transformation matrix, image a procedure holding the image data -% (same for mask) and x/y an additional translation. -% -% ### should move the translation into the matrix!!! -/di -{ - gsave - translate - 1 index 1 eq { % bitmap - false eq { % no mask, draw solid background - pop - true 3 1 roll % width height false matrix image - 4 index - 4 index - false - 4 index - 4 index - imagemask - BkCol SC - imagemask - } { - pop - false 3 1 roll % width height false matrix image - imagemask - } ifelse - } { - dup false ne { - % have a mask, see if we can use it - /languagelevel where { - pop - languagelevel 3 ge - } { false } ifelse - } { - false - } ifelse - - { - % languagelevel3, we can use image mask and dicts - - % store the image mask - /ma exch d - % select colorspace according to 8|24 bit depth and set the decode array /dc - 8 eq { - /dc [0 1] d - /DeviceGray - } { - /dc [0 1 0 1 0 1] d - /DeviceRGB - } ifelse - setcolorspace - % the image data - /im exch d - % transformation matrix - /mt exch d - % width and height - /h exch def - /w exch def - % the image dict - /id - 7 dict dup begin - /ImageType 1 d - /Width w d - /Height h d - /ImageMatrix mt d - /DataSource im d - /BitsPerComponent 8 d - /Decode dc d - end d - % the mask dictionary - /md - 7 dict dup begin - /ImageType 1 d - /Width w d - /Height h d - /ImageMatrix mt d - /DataSource ma d - /BitsPerComponent 1 d - /Decode [0 1] d - end d - % and the combined image dict - 4 dict dup begin - /ImageType 3 d - /DataDict id d - /MaskDict md d - /InterleaveType 3 d - end - image - } { - pop % no mask or can't use it, get rid of it - 8 % width height image 8|24 8 matrix - 4 1 roll - 8 eq { % grayscale - image - } { %color - QCI - } ifelse - } ifelse - } ifelse - grestore -} d - - - - -/BF { % brush fill - gsave - BSt 1 eq % solid brush? - { - BCol SC - WFi { fill } { eofill } ifelse - } if - BSt 2 ge BSt 8 le and % dense pattern? - { - BDArr BSt 2 sub get /sc ED - % the following line scales the brush color according to the pattern. the higher the pattern the lighter the color. - BCol - { - 1. exch sub sc mul 1. exch sub - } forall - 3 array astore - SC - WFi { fill } { eofill } ifelse - } if - BSt 9 ge BSt 14 le and % brush pattern? - { - WFi { clip } { eoclip } ifelse - defM SM - pathbbox % left upper right lower - 3 index 3 index translate - 4 2 roll % right lower left upper - 3 2 roll % right left upper lower - exch % left right lower upper - sub /h ED - sub /w ED - OMo { - NP - 0 0 MT - 0 h RL - w 0 RL - 0 h neg RL - CP - BkCol SC - fill - } if - BCol SC - 0.3 SW - NP - BSt 9 eq BSt 11 eq or % horiz or cross pattern - { 0 4 h - { dup 0 exch MT w exch LT } for - } if - BSt 10 eq BSt 11 eq or % vert or cross pattern - { 0 4 w - { dup 0 MT h LT } for - } if - BSt 12 eq BSt 14 eq or % F-diag or diag cross - { w h gt - { 0 6 w h add - { dup 0 MT h sub h LT } for - } { 0 6 w h add - { dup 0 exch MT w sub w exch LT } for - } ifelse - } if - BSt 13 eq BSt 14 eq or % B-diag or diag cross - { w h gt - { 0 6 w h add - { dup h MT h sub 0 LT } for - } { 0 6 w h add - { dup w exch MT w sub 0 exch LT } for - } ifelse - } if - S - } if - BSt 24 eq % CustomPattern - - { - } if - grestore -} D - -% for arc -/mat matrix d -/ang1 D0 /ang2 D0 -/w D0 /h D0 -/x D0 /y D0 - -/ARC { % Generic ARC function [ X Y W H ang1 ang2 ] - /ang2 ED /ang1 ED /h ED /w ED /y ED /x ED - mat CM pop - x w 2 div add y h 2 div add TR - 1 h w div neg scale - ang2 0 ge - {0 0 w 2 div ang1 ang1 ang2 add arc } - {0 0 w 2 div ang1 ang1 ang2 add arcn} ifelse - mat SM -} D - -/C D0 - -/P { % PdcDrawPoint [x y] - NP - MT - 0.5 0.5 rmoveto - 0 -1 RL - -1 0 RL - 0 1 RL - CP - fill -} D - -/M { % PdcMoveTo [x y] - /Cy ED /Cx ED -} D - -/L { % PdcLineTo [x y] - NP - Cx Cy MT - /Cy ED /Cx ED - Cx Cy LT - QS -} D - -/DL { % PdcDrawLine [x1 y1 x0 y0] - NP - MT - LT - QS -} D - -/HL { % PdcDrawLine [x1 y x0] - 1 index DL -} D - -/VL { % PdcDrawLine [x y1 y0] - 2 index exch DL -} D - -/R { % PdcDrawRect [x y w h] - /h ED /w ED /y ED /x ED - NP - x y MT - 0 h RL - w 0 RL - 0 h neg RL - CP - BF - QS -} D - -/ACR { % add clip rect - /h ED /w ED /y ED /x ED - x y MT - 0 h RL - w 0 RL - 0 h neg RL - CP -} D - -/xr D0 /yr D0 -/rx D0 /ry D0 /rx2 D0 /ry2 D0 - -/RR { % PdcDrawRoundRect [x y w h xr yr] - /yr ED /xr ED /h ED /w ED /y ED /x ED - xr 0 le yr 0 le or - {x y w h R} % Do rect if one of rounding values is less than 0. - {xr 100 ge yr 100 ge or - {x y w h E} % Do ellipse if both rounding values are larger than 100 - { - /rx xr w mul 200 div d - /ry yr h mul 200 div d - /rx2 rx 2 mul d - /ry2 ry 2 mul d - NP - x rx add y MT - x y rx2 ry2 180 -90 - x y h add ry2 sub rx2 ry2 270 -90 - x w add rx2 sub y h add ry2 sub rx2 ry2 0 -90 - x w add rx2 sub y rx2 ry2 90 -90 - ARC ARC ARC ARC - CP - BF - QS - } ifelse - } ifelse -} D - -/E { % PdcDrawEllipse [x y w h] - /h ED /w ED /y ED /x ED - mat CM pop - x w 2 div add y h 2 div add translate - 1 h w div scale - NP - 0 0 w 2 div 0 360 arc - mat SM - BF - QS -} D - -/A { % PdcDrawArc [x y w h ang1 ang2] - 16 div exch 16 div exch - NP - ARC - QS -} D - -/PIE { % PdcDrawPie [x y w h ang1 ang2] - /ang2 ED /ang1 ED /h ED /w ED /y ED /x ED - NP - x w 2 div add y h 2 div add MT - x y w h ang1 16 div ang2 16 div ARC - CP - BF - QS -} D - -/CH { % PdcDrawChord [x y w h ang1 ang2] - 16 div exch 16 div exch - NP - ARC - CP - BF - QS -} D - -/BZ { % PdcDrawCubicBezier [4 points] - curveto - QS -} D - -/CRGB { % Compute RGB [R G B] => R/255 G/255 B/255 - 255 div 3 1 roll - 255 div 3 1 roll - 255 div 3 1 roll -} D - - -/BC { % PdcSetBkColor [R G B] - CRGB - BkCol astore pop -} D - -/BR { % PdcSetBrush [style R G B] - CRGB - BCol astore pop - /BSt ED -} D - -/WB { % set white solid brush - 1 W BR -} D - -/NB { % set nobrush - 0 B BR -} D - -/PE { % PdcSetPen [style width R G B Cap Join] - setlinejoin setlinecap - CRGB - PCol astore pop - /LWi ED - /PSt ED - LWi 0 eq { 0.25 /LWi ED } if % ### 3.0 remove this line - PCol SC -} D - -/P1 { % PdcSetPen [R G B] - 1 0 5 2 roll 0 0 PE -} D - -/ST { % SET TRANSFORM [matrix] - defM setmatrix - concat -} D - -%% Font handling - -% the next three commands are for defining fonts. The first one -% tries to find the most suitable printer font out of a fontlist. -% if encoding is false the default one will be used. -/MF { % newname encoding fontlist - % this function tries to find a suitable postscript font. - % We try quite hard not to get courier for a - % proportional font. The following takes an array of fonts. - % The algorithm will take the first font that - % gives a match (defined as not resulting in a courier font). - % each entry in the table is an array of the form [ /Fontname x-stretch slant ] - % x-strtch can be used to stretch/squeeze the font in x direction. - % This gives better results when eg substituting helvetica for arial - % slant is an optional slant. 0 is non slanted, 0.2 is a typical value for a syntetic oblique. - % encoding can be either an encoding vector of false if the default font encoding is requested. - true exch true exch % push a dummy on the stack, - { % so the loop over the array will leave a font in any case when exiting. - exch pop exch pop % (dummy | oldfont) (dummy | fontdict) fontarray - dup 0 get dup findfont % get the fontname from the array and load it - dup /FontName get % see if the font exists - 3 -1 roll eq { % see if fontname and the one provided are equal - exit - } if - } forall - exch % font fontarray - - % newname encoding font fontarray defines a postscript font - dup - 1 get /fxscale exch def % define scale, sland and encoding - 2 get /fslant exch def - exch /fencoding exch def - [ fxscale 0 fslant 1 0 0 ] makefont % transform font accordingly - fencoding false eq { % check if we have an encoding and use it if available - } { - dup maxlength dict begin % copy font - { - 1 index /FID ne % don't copy FID, as it's not allowed in PS Level 1 - {def}{pop pop}ifelse - } forall - /Encoding fencoding def % replace encoding - currentdict - end - } ifelse - definefont pop -} D - -% an embedded font. This is used for the base fonts of the composite font used later on. -/MFEmb { % newname encoding fontname - findfont dup length dict - begin - { - 1 index /FID ne - {d}{pop pop}ifelse - } forall - /Encoding ED currentdict - end - definefont pop -} D - -% DF: define font -% used to get a scaled version of an already loaded font -% -% newname pointsize fontmame DF - -/DF { - findfont - % get the fontsize on top of the stack and define font matrix - /fs 3 -1 roll d [ fs 0 0 fs -1 mul 0 0 ] - makefont - d -} D - -/ty 0 d -/Y { - /ty ED -} D - -/Tl { % draw underline/strikeout line: () w x y lw ->Tl-> () w x - gsave - setlinewidth - NP 1 index exch MT - 1 index 0 rlineto stroke - grestore -} D - -/XYT { % [string [x/y displacement array] width x] - ty MT % pops x - - /xyshow where { % interpreter has xyshow - pop pop - xyshow - } { % use ashow - exch pop % string cwidth - 1 index % string cwidth string - dup length 2 div exch % string cwidth length string !have to divide by 2 since we use unicode! - stringwidth pop % string cwidth length pwidth - 3 -1 roll % string length pwidth cwidth - exch sub exch div % string extraperchar - exch 0 exch % extraperchar 0 string - ashow - } ifelse -} D - -/AT { - ty MT % pops x - 1 index % string cwidth string - dup length 2 div exch % string cwidth length string !have to divide by 2 since we use unicode! - stringwidth pop % string cwidth length pwidth - 3 -1 roll % string length pwidth cwidth - exch sub exch div % string extraperchar - exch 0 exch % extraperchar 0 string - ashow -} D - -%% start of page -/QI { - /C save d - pageinit - /Cx 0 d % reset current x position - /Cy 0 d % reset current y position - /OMo false d -} D - -%% end of page -/QP { % show page - C restore - showpage -} D - -% merges one key value pair into the page device dict -% -% key value SPD - -/SPD { - /setpagedevice where { - 1 dict dup begin 3 1 roll def end - setpagedevice - } { pop pop } ifelse -} D - -/SV { % Save painter state - BSt LWi PSt Cx Cy WFi OMo BCol PCol BkCol - /nS nS 1 add d - gsave -} D - -/RS { % Restore painter state - nS 0 gt - { grestore - /BkCol ED /PCol ED /BCol ED /OMo ED /WFi ED - /Cy ED /Cx ED /PSt ED /LWi ED /BSt ED - /nS nS 1 sub d - } if -} D - -/CLSTART { % clipping start - /clipTmp matrix CM d % save current matrix - defM SM % Page default matrix - NP -} D - -/CLEND { % clipping end - clip - NP - clipTmp SM % restore the current matrix -} D - -/CLO { % clipping off - grestore % restore top of page state - gsave % save it back again - defM SM % set coordsys (defensive progr.) -} D - diff --git a/src/kernel/qpsprinter_p.h b/src/kernel/qpsprinter_p.h deleted file mode 100644 index 46d93b4b2..000000000 --- a/src/kernel/qpsprinter_p.h +++ /dev/null @@ -1,92 +0,0 @@ -/********************************************************************** -** -** Definition of internal TQPSPrinter class. -** TQPSPrinter implements PostScript (tm) output via TQPrinter. -** -** Created : 940927 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQPSPRINTER_P_H -#define TQPSPRINTER_P_H - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of qpsprinter.cpp and tqprinter_x11.cpp. -// This header file may change from version to version without notice, -// or even be removed. -// -// We mean it. -// -// - - -#ifndef QT_H -#include "tqprinter.h" -#include "tqtextstream.h" -#endif // QT_H - -#ifndef TQT_NO_PRINTER - -class TQPSPrinterPrivate; - -class TQ_EXPORT TQPSPrinter : public TQPaintDevice -{ -private: - // TQPrinter uses these - TQPSPrinter( TQPrinter *, int ); - ~TQPSPrinter(); - - bool cmd ( int, TQPainter *, TQPDevCmdParam * ); - - enum { NewPage = 100, AbortPrinting }; - - friend class TQPrinter; -private: - // not used by TQPrinter - TQPSPrinterPrivate *d; - - // Disabled copy constructor and operator= - TQPSPrinter( const TQPSPrinter & ); - TQPSPrinter &operator=( const TQPSPrinter & ); -}; - -#endif // TQT_NO_PRINTER - -#endif // TQPSPRINTER_P_H diff --git a/src/kernel/qrichtext.cpp b/src/kernel/qrichtext.cpp deleted file mode 100644 index 247e181d9..000000000 --- a/src/kernel/qrichtext.cpp +++ /dev/null @@ -1,8258 +0,0 @@ -/**************************************************************************** -** -** Implementation of the internal TQt classes dealing with rich text -** -** Created : 990101 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qrichtext_p.h" - -#ifndef TQT_NO_RICHTEXT - - -#include "tqstringlist.h" -#include "tqfont.h" -#include "tqtextstream.h" -#include "tqfile.h" -#include "ntqapplication.h" -#include "tqmap.h" -#include "tqfileinfo.h" -#include "tqstylesheet.h" -#include "tqmime.h" -#include "tqimage.h" -#include "tqdragobject.h" -#include "tqpaintdevicemetrics.h" -#include "tqpainter.h" -#include "tqdrawutil.h" -#include "tqcursor.h" -#include "tqptrstack.h" -#include "tqptrdict.h" -#include "tqstyle.h" -#include "tqcleanuphandler.h" -#include "tqtextengine_p.h" -#include - -#include - -static TQTextCursor* richTextExportStart = 0; -static TQTextCursor* richTextExportEnd = 0; - -class TQTextFormatCollection; - -const int border_tolerance = 2; - -#ifdef TQ_WS_WIN -#include "qt_windows.h" -#endif - -#define TQChar_linesep TQChar(0x2028U) - -static inline bool is_printer( TQPainter *p ) -{ - if ( !p || !p->device() ) - return FALSE; - return p->device()->devType() == TQInternal::Printer; -} - -static inline int scale( int value, TQPainter *painter ) -{ - if ( is_printer( painter ) ) { - TQPaintDeviceMetrics metrics( painter->device() ); -#if defined(TQ_WS_X11) - value = value * metrics.logicalDpiY() / - TQPaintDevice::x11AppDpiY( painter->device()->x11Screen() ); -#elif defined (TQ_WS_WIN) - HDC hdc = GetDC( 0 ); - int gdc = GetDeviceCaps( hdc, LOGPIXELSY ); - if ( gdc ) - value = value * metrics.logicalDpiY() / gdc; - ReleaseDC( 0, hdc ); -#elif defined (TQ_WS_MAC) - value = value * metrics.logicalDpiY() / 75; // ##### FIXME -#endif - } - return value; -} - - -inline bool isBreakable( TQTextString *string, int pos ) -{ - if (string->at(pos).nobreak) - return FALSE; - return (pos < string->length()-1 && string->at(pos+1).softBreak); -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -void TQTextCommandHistory::addCommand( TQTextCommand *cmd ) -{ - if ( current < (int)history.count() - 1 ) { - TQPtrList commands; - commands.setAutoDelete( FALSE ); - - for( int i = 0; i <= current; ++i ) { - commands.insert( i, history.at( 0 ) ); - history.take( 0 ); - } - - commands.append( cmd ); - history.clear(); - history = commands; - history.setAutoDelete( TRUE ); - } else { - history.append( cmd ); - } - - if ( (int)history.count() > steps ) - history.removeFirst(); - else - ++current; -} - -TQTextCursor *TQTextCommandHistory::undo( TQTextCursor *c ) -{ - if ( current > -1 ) { - TQTextCursor *c2 = history.at( current )->unexecute( c ); - --current; - return c2; - } - return 0; -} - -TQTextCursor *TQTextCommandHistory::redo( TQTextCursor *c ) -{ - if ( current > -1 ) { - if ( current < (int)history.count() - 1 ) { - ++current; - return history.at( current )->execute( c ); - } - } else { - if ( history.count() > 0 ) { - ++current; - return history.at( current )->execute( c ); - } - } - return 0; -} - -bool TQTextCommandHistory::isUndoAvailable() -{ - return current > -1; -} - -bool TQTextCommandHistory::isRedoAvailable() -{ - return ( current > -1 && current < (int)history.count() - 1 ) || ( current == -1 && history.count() > 0 ); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextDeleteCommand::TQTextDeleteCommand( TQTextDocument *d, int i, int idx, const TQMemArray &str, - const TQByteArray& oldStyleInfo ) - : TQTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo ) -{ - for ( int j = 0; j < (int)text.size(); ++j ) { - if ( text[ j ].format() ) - text[ j ].format()->addRef(); - } -} - -TQTextDeleteCommand::TQTextDeleteCommand( TQTextParagraph *p, int idx, const TQMemArray &str ) - : TQTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) -{ - for ( int i = 0; i < (int)text.size(); ++i ) { - if ( text[ i ].format() ) - text[ i ].format()->addRef(); - } -} - -TQTextDeleteCommand::~TQTextDeleteCommand() -{ - for ( int i = 0; i < (int)text.size(); ++i ) { - if ( text[ i ].format() ) - text[ i ].format()->removeRef(); - } - text.resize( 0 ); -} - -TQTextCursor *TQTextDeleteCommand::execute( TQTextCursor *c ) -{ - TQTextParagraph *s = doc ? doc->paragAt( id ) : parag; - if ( !s ) { - tqWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() ); - return 0; - } - - cursor.setParagraph( s ); - cursor.setIndex( index ); - int len = text.size(); - if ( c ) - *c = cursor; - if ( doc ) { - doc->setSelectionStart( TQTextDocument::Temp, cursor ); - for ( int i = 0; i < len; ++i ) - cursor.gotoNextLetter(); - doc->setSelectionEnd( TQTextDocument::Temp, cursor ); - doc->removeSelectedText( TQTextDocument::Temp, &cursor ); - if ( c ) - *c = cursor; - } else { - s->remove( index, len ); - } - - return c; -} - -TQTextCursor *TQTextDeleteCommand::unexecute( TQTextCursor *c ) -{ - TQTextParagraph *s = doc ? doc->paragAt( id ) : parag; - if ( !s ) { - tqWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() ); - return 0; - } - - cursor.setParagraph( s ); - cursor.setIndex( index ); - TQString str = TQTextString::toString( text ); - cursor.insert( str, TRUE, &text ); - if ( c ) - *c = cursor; - cursor.setParagraph( s ); - cursor.setIndex( index ); - -#ifndef TQT_NO_DATASTREAM - if ( !styleInformation.isEmpty() ) { - TQDataStream styleStream( styleInformation, IO_ReadOnly ); - int num; - styleStream >> num; - TQTextParagraph *p = s; - while ( num-- && p ) { - p->readStyleInformation( styleStream ); - p = p->next(); - } - } -#endif - s = cursor.paragraph(); - while ( s ) { - s->format(); - s->setChanged( TRUE ); - if ( s == c->paragraph() ) - break; - s = s->next(); - } - - return &cursor; -} - -TQTextFormatCommand::TQTextFormatCommand( TQTextDocument *d, int sid, int sidx, int eid, int eidx, - const TQMemArray &old, TQTextFormat *f, int fl ) - : TQTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl ) -{ - format = d->formatCollection()->format( f ); - for ( int j = 0; j < (int)oldFormats.size(); ++j ) { - if ( oldFormats[ j ].format() ) - oldFormats[ j ].format()->addRef(); - } -} - -TQTextFormatCommand::~TQTextFormatCommand() -{ - format->removeRef(); - for ( int j = 0; j < (int)oldFormats.size(); ++j ) { - if ( oldFormats[ j ].format() ) - oldFormats[ j ].format()->removeRef(); - } -} - -TQTextCursor *TQTextFormatCommand::execute( TQTextCursor *c ) -{ - TQTextParagraph *sp = doc->paragAt( startId ); - TQTextParagraph *ep = doc->paragAt( endId ); - if ( !sp || !ep ) - return c; - - TQTextCursor start( doc ); - start.setParagraph( sp ); - start.setIndex( startIndex ); - TQTextCursor end( doc ); - end.setParagraph( ep ); - end.setIndex( endIndex ); - - doc->setSelectionStart( TQTextDocument::Temp, start ); - doc->setSelectionEnd( TQTextDocument::Temp, end ); - doc->setFormat( TQTextDocument::Temp, format, flags ); - doc->removeSelection( TQTextDocument::Temp ); - if ( endIndex == ep->length() ) - end.gotoLeft(); - *c = end; - return c; -} - -TQTextCursor *TQTextFormatCommand::unexecute( TQTextCursor *c ) -{ - TQTextParagraph *sp = doc->paragAt( startId ); - TQTextParagraph *ep = doc->paragAt( endId ); - if ( !sp || !ep ) - return 0; - - int idx = startIndex; - int fIndex = 0; - while ( fIndex < int(oldFormats.size()) ) { - if ( oldFormats.at( fIndex ).c == '\n' ) { - if ( idx > 0 ) { - if ( idx < sp->length() && fIndex > 0 ) - sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() ); - if ( sp == ep ) - break; - sp = sp->next(); - idx = 0; - } - fIndex++; - } - if ( oldFormats.at( fIndex ).format() ) - sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() ); - idx++; - fIndex++; - if ( fIndex >= (int)oldFormats.size() ) - break; - if ( idx >= sp->length() ) { - if ( sp == ep ) - break; - sp = sp->next(); - idx = 0; - } - } - - TQTextCursor end( doc ); - end.setParagraph( ep ); - end.setIndex( endIndex ); - if ( endIndex == ep->length() ) - end.gotoLeft(); - *c = end; - return c; -} - -TQTextStyleCommand::TQTextStyleCommand( TQTextDocument *d, int fParag, int lParag, const TQByteArray& beforeChange ) - : TQTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange ) -{ - after = readStyleInformation( d, fParag, lParag ); -} - - -TQByteArray TQTextStyleCommand::readStyleInformation( TQTextDocument* doc, int fParag, int lParag ) -{ - TQByteArray style; -#ifndef TQT_NO_DATASTREAM - TQTextParagraph *p = doc->paragAt( fParag ); - if ( !p ) - return style; - TQDataStream styleStream( style, IO_WriteOnly ); - int num = lParag - fParag + 1; - styleStream << num; - while ( num -- && p ) { - p->writeStyleInformation( styleStream ); - p = p->next(); - } -#endif - return style; -} - -void TQTextStyleCommand::writeStyleInformation( TQTextDocument* doc, int fParag, const TQByteArray& style ) -{ -#ifndef TQT_NO_DATASTREAM - TQTextParagraph *p = doc->paragAt( fParag ); - if ( !p ) - return; - TQDataStream styleStream( style, IO_ReadOnly ); - int num; - styleStream >> num; - while ( num-- && p ) { - p->readStyleInformation( styleStream ); - p = p->next(); - } -#endif -} - -TQTextCursor *TQTextStyleCommand::execute( TQTextCursor *c ) -{ - writeStyleInformation( doc, firstParag, after ); - return c; -} - -TQTextCursor *TQTextStyleCommand::unexecute( TQTextCursor *c ) -{ - writeStyleInformation( doc, firstParag, before ); - return c; -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextCursor::TQTextCursor( TQTextDocument *d ) - : idx( 0 ), tmpX( -1 ), ox( 0 ), oy( 0 ), - valid( TRUE ) -{ - para = d ? d->firstParagraph() : 0; -} - -TQTextCursor::TQTextCursor( const TQTextCursor &c ) -{ - ox = c.ox; - oy = c.oy; - idx = c.idx; - para = c.para; - tmpX = c.tmpX; - indices = c.indices; - paras = c.paras; - xOffsets = c.xOffsets; - yOffsets = c.yOffsets; - valid = c.valid; -} - -TQTextCursor &TQTextCursor::operator=( const TQTextCursor &c ) -{ - ox = c.ox; - oy = c.oy; - idx = c.idx; - para = c.para; - tmpX = c.tmpX; - indices = c.indices; - paras = c.paras; - xOffsets = c.xOffsets; - yOffsets = c.yOffsets; - valid = c.valid; - - return *this; -} - -bool TQTextCursor::operator==( const TQTextCursor &c ) const -{ - return para == c.para && idx == c.idx; -} - -int TQTextCursor::totalOffsetX() const -{ - int xoff = ox; - for ( TQValueStack::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit ) - xoff += *xit; - return xoff; -} - -int TQTextCursor::totalOffsetY() const -{ - int yoff = oy; - for ( TQValueStack::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit ) - yoff += *yit; - return yoff; -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -void TQTextCursor::gotoIntoNested( const TQPoint &globalPos ) -{ - if ( !para ) - return; - Q_ASSERT( para->at( idx )->isCustom() ); - push(); - ox = 0; - int bl, y; - para->lineHeightOfChar( idx, &bl, &y ); - oy = y + para->rect().y(); - ox = para->at( idx )->x; - TQTextDocument* doc = document(); - para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, globalPos-TQPoint(ox,oy) ); -} -#endif - -void TQTextCursor::invalidateNested() -{ - if ( nestedDepth() ) { - TQValueStack::Iterator it = paras.begin(); - TQValueStack::Iterator it2 = indices.begin(); - for ( ; it != paras.end(); ++it, ++it2 ) { - if ( *it == para ) - continue; - (*it)->invalidate( 0 ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( (*it)->at( *it2 )->isCustom() ) - (*it)->at( *it2 )->customItem()->invalidate(); -#endif - } - } -} - -void TQTextCursor::insert( const TQString &str, bool checkNewLine, TQMemArray *formatting ) -{ - tmpX = -1; - bool justInsert = TRUE; - TQString s( str ); -#if defined(TQ_WS_WIN) - if ( checkNewLine ) { - int i = 0; - while ( ( i = s.find( '\r', i ) ) != -1 ) - s.remove( i ,1 ); - } -#endif - if ( checkNewLine ) - justInsert = s.find( '\n' ) == -1; - if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index - para->insert( idx, s.unicode(), s.length() ); - if ( formatting ) { - for ( int i = 0; i < (int)s.length(); ++i ) { - if ( formatting->at( i ).format() ) { - formatting->at( i ).format()->addRef(); - para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); - } - } - } - idx += s.length(); - } else { // we split at new lines - int start = -1; - int end; - int y = para->rect().y() + para->rect().height(); - int lastIndex = 0; - do { - end = s.find( '\n', start + 1 ); // find line break - if ( end == -1 ) // didn't find one, so end of line is end of string - end = s.length(); - int len = (start == -1 ? end : end - start - 1); - if ( len > 0 ) // insert the line - para->insert( idx, s.unicode() + start + 1, len ); - else - para->invalidate( 0 ); - if ( formatting ) { // set formats to the chars of the line - for ( int i = 0; i < len; ++i ) { - if ( formatting->at( i + lastIndex ).format() ) { - formatting->at( i + lastIndex ).format()->addRef(); - para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); - } - } - lastIndex += len; - } - start = end; // next start is at the end of this line - idx += len; // increase the index of the cursor to the end of the inserted text - if ( s[end] == '\n' ) { // if at the end was a line break, break the line - splitAndInsertEmptyParagraph( FALSE, TRUE ); - para->setEndState( -1 ); - para->prev()->format( -1, FALSE ); - lastIndex++; - } - - } while ( end < (int)s.length() ); - - para->format( -1, FALSE ); - int dy = para->rect().y() + para->rect().height() - y; - TQTextParagraph *p = para; - p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); - p = p->next(); - while ( p ) { - p->setParagId( p->prev()->paragId() + 1 ); - p->move( dy ); - p->invalidate( 0 ); - p->setEndState( -1 ); - p = p->next(); - } - } - - int h = para->rect().height(); - para->format( -1, TRUE ); - if ( h != para->rect().height() ) - invalidateNested(); - else if ( para->document() && para->document()->parent() ) - para->document()->nextDoubleBuffered = TRUE; - - fixCursorPosition(); -} - -void TQTextCursor::gotoLeft() -{ - if ( para->string()->isRightToLeft() ) - gotoNextLetter(); - else - gotoPreviousLetter(); -} - -void TQTextCursor::gotoPreviousLetter() -{ - tmpX = -1; - - if ( idx > 0 ) { - idx = para->string()->previousCursorPosition( idx ); -#ifndef TQT_NO_TEXTCUSTOMITEM - const TQTextStringChar *tsc = para->at( idx ); - if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) - processNesting( EnterEnd ); -#endif - } else if ( para->prev() ) { - para = para->prev(); - while ( !para->isVisible() && para->prev() ) - para = para->prev(); - idx = para->length() - 1; - } else if ( nestedDepth() ) { - pop(); - processNesting( Prev ); - if ( idx == -1 ) { - pop(); - if ( idx > 0 ) { - idx = para->string()->previousCursorPosition( idx ); -#ifndef TQT_NO_TEXTCUSTOMITEM - const TQTextStringChar *tsc = para->at( idx ); - if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) - processNesting( EnterEnd ); -#endif - } else if ( para->prev() ) { - para = para->prev(); - idx = para->length() - 1; - } - } - } -} - -void TQTextCursor::push() -{ - indices.push( idx ); - paras.push( para ); - xOffsets.push( ox ); - yOffsets.push( oy ); -} - -void TQTextCursor::pop() -{ - if ( indices.isEmpty() ) - return; - idx = indices.pop(); - para = paras.pop(); - ox = xOffsets.pop(); - oy = yOffsets.pop(); -} - -void TQTextCursor::restoreState() -{ - while ( !indices.isEmpty() ) - pop(); -} - -bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link, bool loosePlacing, bool matchBetweenCharacters ) -{ - TQPoint pos( p ); - TQRect r; - TQTextParagraph *str = s; - if ( pos.y() < s->rect().y() ) { - pos.setY( s->rect().y() ); -#ifdef TQ_WS_MACX - pos.setX( s->rect().x() ); -#endif - } - while ( s ) { - r = s->rect(); - r.setWidth( document() ? document()->width() : TQWIDGETSIZE_MAX ); - if ( s->isVisible() ) - str = s; - if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() ) - break; - if ( loosePlacing == TRUE && !s->next() ) { -#ifdef TQ_WS_MACX - pos.setX( s->rect().x() + s->rect().width() ); -#endif - break; - } - s = s->next(); - } - - if ( !s || !str ) - return FALSE; - - s = str; - - setParagraph( s ); - int y = s->rect().y(); - int lines = s->lines(); - TQTextStringChar *chr = 0; - int index = 0; - int i = 0; - int cy = 0; - int ch = 0; - for ( ; i < lines; ++i ) { - chr = s->lineStartOfLine( i, &index ); - cy = s->lineY( i ); - ch = s->lineHeight( i ); - if ( !chr ) - return FALSE; - if ( pos.y() <= y + cy + ch ) - break; - } - int nextLine; - if ( i < lines - 1 ) - s->lineStartOfLine( i+1, &nextLine ); - else - nextLine = s->length(); - i = index; - int x = s->rect().x(); - if ( pos.x() < x ) - pos.setX( x + 1 ); - int cw; - int curpos = -1; - int dist = 10000000; - bool inCustom = FALSE; - while ( i < nextLine ) { - chr = s->at(i); - int cpos = x + chr->x; - cw = s->string()->width( i ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( chr->isCustom() && chr->customItem()->isNested() ) { - if ( pos.x() >= cpos && pos.x() <= cpos + cw && - pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) { - inCustom = TRUE; - curpos = i; - break; - } - } else -#endif - { - if( chr->rightToLeft ) - cpos += cw; - int d = cpos - pos.x(); - bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft; - if ( ( matchBetweenCharacters == TRUE && (TQABS( d ) < dist || (dist == d && dm == TRUE )) && para->string()->validCursorPosition( i ) ) || - ( matchBetweenCharacters == FALSE && ( d == 0 || dm == TRUE ) ) ) { - dist = TQABS( d ); - if ( !link || ( pos.x() >= x + chr->x && ( loosePlacing == TRUE || pos.x() < cpos ) ) ) - curpos = i; - } - } - i++; - } - if ( curpos == -1 ) { - if ( loosePlacing == TRUE ) - curpos = s->length()-1; - else - return FALSE; - } - setIndex( curpos ); - -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) { - TQTextDocument *oldDoc = para->document(); - gotoIntoNested( pos ); - if ( oldDoc == para->document() ) - return TRUE; - TQPoint p( pos.x() - offsetX(), pos.y() - offsetY() ); - if ( !place( p, document()->firstParagraph(), link ) ) - pop(); - } -#endif - return TRUE; -} - -bool TQTextCursor::processNesting( Operation op ) -{ - if ( !para->document() ) - return FALSE; - TQTextDocument* doc = para->document(); - push(); - ox = para->at( idx )->x; - int bl, y; - para->lineHeightOfChar( idx, &bl, &y ); - oy = y + para->rect().y(); - bool ok = FALSE; - -#ifndef TQT_NO_TEXTCUSTOMITEM - switch ( op ) { - case EnterBegin: - ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy ); - break; - case EnterEnd: - ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE ); - break; - case Next: - ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy ); - break; - case Prev: - ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy ); - break; - case Down: - ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy ); - break; - case Up: - ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy ); - break; - } - if ( !ok ) -#endif - pop(); - return ok; -} - -void TQTextCursor::gotoRight() -{ - if ( para->string()->isRightToLeft() ) - gotoPreviousLetter(); - else - gotoNextLetter(); -} - -void TQTextCursor::gotoNextLetter() -{ - tmpX = -1; - -#ifndef TQT_NO_TEXTCUSTOMITEM - const TQTextStringChar *tsc = para->at( idx ); - if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { - if ( processNesting( EnterBegin ) ) - return; - } -#endif - - if ( idx < para->length() - 1 ) { - idx = para->string()->nextCursorPosition( idx ); - } else if ( para->next() ) { - para = para->next(); - while ( !para->isVisible() && para->next() ) - para = para->next(); - idx = 0; - } else if ( nestedDepth() ) { - pop(); - processNesting( Next ); - if ( idx == -1 ) { - pop(); - if ( idx < para->length() - 1 ) { - idx = para->string()->nextCursorPosition( idx ); - } else if ( para->next() ) { - para = para->next(); - idx = 0; - } - } - } -} - -void TQTextCursor::gotoUp() -{ - int indexOfLineStart; - int line; - TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); - if ( !c ) - return; - - if (tmpX < 0) - tmpX = x(); - - if ( indexOfLineStart == 0 ) { - if ( !para->prev() ) { - if ( !nestedDepth() ) - return; - pop(); - processNesting( Up ); - if ( idx == -1 ) { - pop(); - if ( !para->prev() ) - return; - idx = tmpX = 0; - } else { - tmpX = -1; - return; - } - } - TQTextParagraph *p = para->prev(); - while ( p && !p->isVisible() ) - p = p->prev(); - if ( p ) - para = p; - int lastLine = para->lines() - 1; - if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) ) - return; - idx = indexOfLineStart; - while (idx < para->length()-1 && para->at(idx)->x < tmpX) - ++idx; - if (idx > indexOfLineStart && - para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) - --idx; - } else { - --line; - int oldIndexOfLineStart = indexOfLineStart; - if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) - return; - idx = indexOfLineStart; - while (idx < oldIndexOfLineStart-1 && para->at(idx)->x < tmpX) - ++idx; - if (idx > indexOfLineStart && - para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) - --idx; - } - fixCursorPosition(); -} - -void TQTextCursor::gotoDown() -{ - int indexOfLineStart; - int line; - TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); - if ( !c ) - return; - - if (tmpX < 0) - tmpX = x(); - if ( line == para->lines() - 1 ) { - if ( !para->next() ) { - if ( !nestedDepth() ) - return; - pop(); - processNesting( Down ); - if ( idx == -1 ) { - pop(); - if ( !para->next() ) - return; - idx = tmpX = 0; - } else { - tmpX = -1; - return; - } - } - TQTextParagraph *s = para->next(); - while ( s && !s->isVisible() ) - s = s->next(); - if ( s ) - para = s; - if ( !para->lineStartOfLine( 0, &indexOfLineStart ) ) - return; - int end; - if ( para->lines() == 1 ) - end = para->length(); - else - para->lineStartOfLine( 1, &end ); - - idx = indexOfLineStart; - while (idx < end-1 && para->at(idx)->x < tmpX) - ++idx; - if (idx > indexOfLineStart && - para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) - --idx; - } else { - ++line; - int end; - if ( line == para->lines() - 1 ) - end = para->length(); - else - para->lineStartOfLine( line + 1, &end ); - if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) - return; - idx = indexOfLineStart; - while (idx < end-1 && para->at(idx)->x < tmpX) - ++idx; - if (idx > indexOfLineStart && - para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) - --idx; - } - fixCursorPosition(); -} - -void TQTextCursor::gotoLineEnd() -{ - tmpX = -1; - int indexOfLineStart; - int line; - TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); - if ( !c ) - return; - - if ( line == para->lines() - 1 ) { - idx = para->length() - 1; - } else { - c = para->lineStartOfLine( ++line, &indexOfLineStart ); - indexOfLineStart--; - idx = indexOfLineStart; - } -} - -void TQTextCursor::gotoLineStart() -{ - tmpX = -1; - int indexOfLineStart; - int line; - TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); - if ( !c ) - return; - - idx = indexOfLineStart; -} - -void TQTextCursor::gotoHome() -{ - if ( topParagraph()->document() ) - gotoPosition( topParagraph()->document()->firstParagraph() ); - else - gotoLineStart(); -} - -void TQTextCursor::gotoEnd() -{ - if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() ) - gotoPosition( topParagraph()->document()->lastParagraph(), - topParagraph()->document()->lastParagraph()->length() - 1); - else - gotoLineEnd(); -} - -void TQTextCursor::gotoPageUp( int visibleHeight ) -{ - int targetY = globalY() - visibleHeight; - TQTextParagraph* old; int index; - do { - old = para; index = idx; - gotoUp(); - } while ( (old != para || index != idx) && globalY() > targetY ); -} - -void TQTextCursor::gotoPageDown( int visibleHeight ) -{ - int targetY = globalY() + visibleHeight; - TQTextParagraph* old; int index; - do { - old = para; index = idx; - gotoDown(); - } while ( (old != para || index != idx) && globalY() < targetY ); -} - -void TQTextCursor::gotoWordRight() -{ - if ( para->string()->isRightToLeft() ) - gotoPreviousWord(); - else - gotoNextWord(); -} - -void TQTextCursor::gotoWordLeft() -{ - if ( para->string()->isRightToLeft() ) - gotoNextWord(); - else - gotoPreviousWord(); -} - -static bool is_seperator( const TQChar &c, bool onlySpace ) -{ - if ( onlySpace ) - return c.isSpace(); - return c.isSpace() || - c == '\t' || - c == '.' || - c == ',' || - c == ':' || - c == ';' || - c == '-' || - c == '<' || - c == '>' || - c == '[' || - c == ']' || - c == '(' || - c == ')' || - c == '{' || - c == '}'; -} - -void TQTextCursor::gotoPreviousWord( bool onlySpace ) -{ - gotoPreviousLetter(); - tmpX = -1; - TQTextString *s = para->string(); - bool allowSame = FALSE; - if ( idx == ((int)s->length()-1) ) - return; - for ( int i = idx; i >= 0; --i ) { - if ( is_seperator( s->at( i ).c, onlySpace ) ) { - if ( !allowSame ) - continue; - idx = i + 1; - return; - } - if ( !allowSame && !is_seperator( s->at( i ).c, onlySpace ) ) - allowSame = TRUE; - } - idx = 0; -} - -void TQTextCursor::gotoNextWord( bool onlySpace ) -{ - tmpX = -1; - TQTextString *s = para->string(); - bool allowSame = FALSE; - for ( int i = idx; i < (int)s->length(); ++i ) { - if ( !is_seperator( s->at( i ).c, onlySpace ) ) { - if ( !allowSame ) - continue; - idx = i; - return; - } - if ( !allowSame && is_seperator( s->at( i ).c, onlySpace ) ) - allowSame = TRUE; - - } - - if ( idx < ((int)s->length()-1) ) { - gotoLineEnd(); - } else if ( para->next() ) { - TQTextParagraph *p = para->next(); - while ( p && !p->isVisible() ) - p = p->next(); - if ( s ) { - para = p; - idx = 0; - } - } else { - gotoLineEnd(); - } -} - -bool TQTextCursor::atParagStart() -{ - return idx == 0; -} - -bool TQTextCursor::atParagEnd() -{ - return idx == para->length() - 1; -} - -void TQTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds ) -{ - if ( !para->document() ) - return; - tmpX = -1; - TQTextFormat *f = 0; - if ( para->document()->useFormatCollection() ) { - f = para->at( idx )->format(); - if ( idx == para->length() - 1 && idx > 0 ) - f = para->at( idx - 1 )->format(); - if ( f->isMisspelled() ) { - f->removeRef(); - f = para->document()->formatCollection()->format( f->font(), f->color() ); - } - } - - if ( atParagEnd() ) { - TQTextParagraph *n = para->next(); - TQTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); - if ( f ) - s->setFormat( 0, 1, f, TRUE ); - s->copyParagData( para ); - if ( ind ) { - int oi, ni; - s->indent( &oi, &ni ); - para = s; - idx = ni; - } else { - para = s; - idx = 0; - } - } else if ( atParagStart() ) { - TQTextParagraph *p = para->prev(); - TQTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds ); - if ( f ) - s->setFormat( 0, 1, f, TRUE ); - s->copyParagData( para ); - if ( ind ) { - s->indent(); - s->format(); - indent(); - para->format(); - } - } else { - TQString str = para->string()->toString().mid( idx, 0xFFFFFF ); - TQTextParagraph *n = para->next(); - TQTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); - s->copyParagData( para ); - s->remove( 0, 1 ); - s->append( str, TRUE ); - for ( uint i = 0; i < str.length(); ++i ) { - TQTextStringChar* tsc = para->at( idx + i ); - s->setFormat( i, 1, tsc->format(), TRUE ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( tsc->isCustom() ) { - TQTextCustomItem * item = tsc->customItem(); - s->at( i )->setCustomItem( item ); - tsc->loseCustomItem(); - } -#endif - if ( tsc->isAnchor() ) - s->at( i )->setAnchor( tsc->anchorName(), - tsc->anchorHref() ); - } - para->truncate( idx ); - if ( ind ) { - int oi, ni; - s->indent( &oi, &ni ); - para = s; - idx = ni; - } else { - para = s; - idx = 0; - } - } - - invalidateNested(); -} - -bool TQTextCursor::remove() -{ - tmpX = -1; - if ( !atParagEnd() ) { - int next = para->string()->nextCursorPosition( idx ); - para->remove( idx, next-idx ); - int h = para->rect().height(); - para->format( -1, TRUE ); - if ( h != para->rect().height() ) - invalidateNested(); - else if ( para->document() && para->document()->parent() ) - para->document()->nextDoubleBuffered = TRUE; - return FALSE; - } else if ( para->next() ) { - para->join( para->next() ); - invalidateNested(); - return TRUE; - } - return FALSE; -} - -/* needed to implement backspace the correct way */ -bool TQTextCursor::removePreviousChar() -{ - tmpX = -1; - if ( !atParagStart() ) { - para->remove( idx-1, 1 ); - int h = para->rect().height(); - idx--; - // shouldn't be needed, just to make sure. - fixCursorPosition(); - para->format( -1, TRUE ); - if ( h != para->rect().height() ) - invalidateNested(); - else if ( para->document() && para->document()->parent() ) - para->document()->nextDoubleBuffered = TRUE; - return FALSE; - } else if ( para->prev() ) { - para = para->prev(); - para->join( para->next() ); - invalidateNested(); - return TRUE; - } - return FALSE; -} - -void TQTextCursor::indent() -{ - int oi = 0, ni = 0; - para->indent( &oi, &ni ); - if ( oi == ni ) - return; - - if ( idx >= oi ) - idx += ni - oi; - else - idx = ni; -} - -void TQTextCursor::fixCursorPosition() -{ - // searches for the closest valid cursor position - if ( para->string()->validCursorPosition( idx ) ) - return; - - int lineIdx; - TQTextStringChar *start = para->lineStartOfChar( idx, &lineIdx, 0 ); - int x = para->string()->at( idx ).x; - int diff = TQABS(start->x - x); - int best = lineIdx; - - TQTextStringChar *c = start; - ++c; - - TQTextStringChar *end = ¶->string()->at( para->length()-1 ); - while ( c <= end && !c->lineStart ) { - int xp = c->x; - if ( c->rightToLeft ) - xp += para->string()->width( lineIdx + (c-start) ); - int ndiff = TQABS(xp - x); - if ( ndiff < diff && para->string()->validCursorPosition(lineIdx + (c-start)) ) { - diff = ndiff; - best = lineIdx + (c-start); - } - ++c; - } - idx = best; -} - - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextDocument::TQTextDocument( TQTextDocument *p ) - : par( p ), parentPar( 0 ) -#ifndef TQT_NO_TEXTCUSTOMITEM - , tc( 0 ) -#endif - , tArray( 0 ), tStopWidth( 0 ) -{ - fCollection = par ? par->fCollection : new TQTextFormatCollection; - init(); -} - -void TQTextDocument::init() -{ - oTextValid = TRUE; - mightHaveCustomItems = FALSE; - if ( par ) - par->insertChild( this ); - pProcessor = 0; - useFC = TRUE; - pFormatter = 0; - indenter = 0; - fParag = 0; - txtFormat = TQt::AutoText; - preferRichText = FALSE; - pages = FALSE; - focusIndicator.parag = 0; - minw = 0; - wused = 0; - minwParag = curParag = 0; - align = AlignAuto; - nSelections = 1; - - setStyleSheet( TQStyleSheet::defaultSheet() ); -#ifndef TQT_NO_MIME - factory_ = TQMimeSourceFactory::defaultFactory(); -#endif - contxt = TQString::null; - - underlLinks = par ? par->underlLinks : TRUE; - backBrush = 0; - buf_pixmap = 0; - nextDoubleBuffered = FALSE; - - if ( par ) - withoutDoubleBuffer = par->withoutDoubleBuffer; - else - withoutDoubleBuffer = FALSE; - - lParag = fParag = createParagraph( this, 0, 0 ); - - cx = 0; - cy = 2; - if ( par ) - cx = cy = 0; - cw = 600; - vw = 0; - flow_ = new TQTextFlow; - flow_->setWidth( cw ); - - leftmargin = rightmargin = 4; - scaleFontsFactor = 1; - - - selectionColors[ Standard ] = TQApplication::palette().color( TQPalette::Active, TQColorGroup::Highlight ); - selectionText[ Standard ] = TRUE; - selectionText[ IMSelectionText ] = TRUE; - selectionText[ IMCompositionText ] = FALSE; - commandHistory = new TQTextCommandHistory( 100 ); - tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; -} - -TQTextDocument::~TQTextDocument() -{ - delete commandHistory; - if ( par ) - par->removeChild( this ); - clear(); - delete flow_; - if ( !par ) { - delete pFormatter; - delete fCollection; - } - delete pProcessor; - delete buf_pixmap; - delete indenter; - delete backBrush; - delete [] tArray; -} - -void TQTextDocument::clear( bool createEmptyParag ) -{ - while ( fParag ) { - TQTextParagraph *p = fParag->next(); - delete fParag; - fParag = p; - } - if ( flow_ ) - flow_->clear(); - fParag = lParag = 0; - if ( createEmptyParag ) - fParag = lParag = createParagraph( this ); - focusIndicator.parag = 0; - selections.clear(); - oText = TQString::null; - oTextValid = FALSE; -} - -int TQTextDocument::widthUsed() const -{ - return wused + 2*border_tolerance; -} - -int TQTextDocument::height() const -{ - int h = 0; - if ( lParag ) - h = lParag->rect().top() + lParag->rect().height() + 1; - int fh = flow_->boundingRect().bottom(); - return TQMAX( h, fh ); -} - - - -TQTextParagraph *TQTextDocument::createParagraph( TQTextDocument *d, TQTextParagraph *pr, TQTextParagraph *nx, bool updateIds ) -{ - return new TQTextParagraph( d, pr, nx, updateIds ); -} - -bool TQTextDocument::setMinimumWidth( int needed, int used, TQTextParagraph *p ) -{ - if ( needed == -1 ) { - minw = 0; - wused = 0; - p = 0; - } - if ( p == minwParag ) { - if (minw > needed) { - TQTextParagraph *tp = fParag; - while (tp) { - if (tp != p && tp->minwidth > needed) { - needed = tp->minwidth; - minwParag = tp; - } - tp = tp->n; - } - } - minw = needed; - emit minimumWidthChanged( minw ); - } else if ( needed > minw ) { - minw = needed; - minwParag = p; - emit minimumWidthChanged( minw ); - } - wused = TQMAX( wused, used ); - wused = TQMAX( wused, minw ); - cw = TQMAX( minw, cw ); - return TRUE; -} - -void TQTextDocument::setPlainText( const TQString &text ) -{ - preferRichText = FALSE; - clear(); - oTextValid = TRUE; - oText = text; - - int lastNl = 0; - int nl = text.find( '\n' ); - if ( nl == -1 ) { - lParag = createParagraph( this, lParag, 0 ); - if ( !fParag ) - fParag = lParag; - TQString s = text; - if ( !s.isEmpty() ) { - if ( s[ (int)s.length() - 1 ] == '\r' ) - s.remove( s.length() - 1, 1 ); - lParag->append( s ); - } - } else { - for (;;) { - lParag = createParagraph( this, lParag, 0 ); - if ( !fParag ) - fParag = lParag; - int l = nl - lastNl; - if ( l > 0 ) { - if (text.unicode()[nl-1] == '\r') - l--; - TQConstString cs(text.unicode()+lastNl, l); - lParag->append( cs.string() ); - } - if ( nl == (int)text.length() ) - break; - lastNl = nl + 1; - nl = text.find( '\n', nl + 1 ); - if ( nl == -1 ) - nl = text.length(); - } - } - if ( !lParag ) - lParag = fParag = createParagraph( this, 0, 0 ); -} - -struct TQ_EXPORT TQTextDocumentTag { - TQTextDocumentTag(){} - TQTextDocumentTag( const TQString&n, const TQStyleSheetItem* s, const TQTextFormat& f ) - :name(n),style(s), format(f), alignment(TQt::AlignAuto), direction(TQChar::DirON),liststyle(TQStyleSheetItem::ListDisc) { - wsm = TQStyleSheetItem::WhiteSpaceNormal; - } - TQString name; - const TQStyleSheetItem* style; - TQString anchorHref; - TQStyleSheetItem::WhiteSpaceMode wsm; - TQTextFormat format; - int alignment : 16; - int direction : 5; - TQStyleSheetItem::ListStyle liststyle; - - TQTextDocumentTag( const TQTextDocumentTag& t ) { - name = t.name; - style = t.style; - anchorHref = t.anchorHref; - wsm = t.wsm; - format = t.format; - alignment = t.alignment; - direction = t.direction; - liststyle = t.liststyle; - } - TQTextDocumentTag& operator=(const TQTextDocumentTag& t) { - name = t.name; - style = t.style; - anchorHref = t.anchorHref; - wsm = t.wsm; - format = t.format; - alignment = t.alignment; - direction = t.direction; - liststyle = t.liststyle; - return *this; - } - - TQ_DUMMY_COMPARISON_OPERATOR(TQTextDocumentTag) -}; - - -#define NEWPAR do{ if ( !hasNewPar) { \ - if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == TQChar_linesep ) \ - curpar->remove( curpar->length()-2, 1 ); \ - curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \ - hasNewPar = TRUE; \ - curpar->rtext = TRUE; \ - curpar->align = curtag.alignment; \ - curpar->lstyle = curtag.liststyle; \ - curpar->litem = ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ); \ - curpar->str->setDirection( (TQChar::Direction)curtag.direction ); \ - space = TRUE; \ - tabExpansionColumn = 0; \ - delete vec; vec = new TQPtrVector( (uint)tags.count() + 1); \ - int i = 0; \ - for ( TQValueStack::Iterator it = tags.begin(); it != tags.end(); ++it ) \ - vec->insert( i++, (*it).style ); \ - vec->insert( i, curtag.style ); \ - }while(FALSE); - - -void TQTextDocument::setRichText( const TQString &text, const TQString &context, const TQTextFormat *initialFormat ) -{ - preferRichText = TRUE; - if ( !context.isEmpty() ) - setContext( context ); - clear(); - fParag = lParag = createParagraph( this ); - oTextValid = TRUE; - oText = text; - setRichTextInternal( text, 0, initialFormat ); - fParag->rtext = TRUE; -} - -void TQTextDocument::setRichTextInternal( const TQString &text, TQTextCursor* cursor, const TQTextFormat *initialFormat ) -{ - TQTextParagraph* curpar = lParag; - int pos = 0; - TQValueStack tags; - if ( !initialFormat ) - initialFormat = formatCollection()->defaultFormat(); - TQTextDocumentTag initag( "", sheet_->item(""), *initialFormat ); - if ( bodyText.isValid() ) - initag.format.setColor( bodyText ); - TQTextDocumentTag curtag = initag; - bool space = TRUE; - bool canMergeLi = FALSE; - - bool textEditMode = FALSE; - int tabExpansionColumn = 0; - - const TQChar* doc = text.unicode(); - int length = text.length(); - bool hasNewPar = curpar->length() <= 1; - TQString anchorName; - - // style sheet handling for margin and line spacing calculation below - TQTextParagraph* stylesPar = curpar; - TQPtrVector* vec = 0; - TQPtrList< TQPtrVector > styles; - styles.setAutoDelete( TRUE ); - - if ( cursor ) { - cursor->splitAndInsertEmptyParagraph(); - TQTextCursor tmp = *cursor; - tmp.gotoPreviousLetter(); - stylesPar = curpar = tmp.paragraph(); - hasNewPar = TRUE; - textEditMode = TRUE; - } else { - NEWPAR; - } - - // set rtext spacing to FALSE for the initial paragraph. - curpar->rtext = FALSE; - - TQString wellKnownTags = "br hr wsp table qt body meta title"; - - while ( pos < length ) { - if ( hasPrefix(doc, length, pos, '<' ) ){ - if ( !hasPrefix( doc, length, pos+1, TQChar('/') ) ) { - // open tag - TQMap attr; - bool emptyTag = FALSE; - TQString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); - if ( tagname.isEmpty() ) - continue; // nothing we could do with this, probably parse error - - const TQStyleSheetItem* nstyle = sheet_->item(tagname); - - if ( nstyle ) { - // we might have to close some 'forgotten' tags - while ( !nstyle->allowedInContext( curtag.style ) ) { - TQString msg; - msg.sprintf( "TQText Warning: Document not valid ( '%s' not allowed in '%s' #%d)", - tagname.ascii(), curtag.style->name().ascii(), pos); - sheet_->error( msg ); - if ( tags.isEmpty() ) - break; - curtag = tags.pop(); - } - - /* special handling for p and li for HTML - compatibility. We do not want to embed blocks in - p, and we do not want new blocks inside non-empty - lis. Plus we want to merge empty lis sometimes. */ - if( nstyle->displayMode() == TQStyleSheetItem::DisplayListItem ) { - canMergeLi = TRUE; - } else if ( nstyle->displayMode() == TQStyleSheetItem::DisplayBlock ) { - while ( curtag.style->name() == "p" ) { - if ( tags.isEmpty() ) - break; - curtag = tags.pop(); - } - - if ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ) { - // we are in a li and a new block comes along - if ( nstyle->name() == "ul" || nstyle->name() == "ol" ) - hasNewPar = FALSE; // we want an empty li (like most browsers) - if ( !hasNewPar ) { - /* do not add new blocks inside - non-empty lis */ - while ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ) { - if ( tags.isEmpty() ) - break; - curtag = tags.pop(); - } - } else if ( canMergeLi ) { - /* we have an empty li and a block - comes along, merge them */ - nstyle = curtag.style; - } - canMergeLi = FALSE; - } - } - } - -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextCustomItem* custom = 0; -#else - bool custom = FALSE; -#endif - - // some well-known tags, some have a nstyle, some not - if ( wellKnownTags.find( tagname ) != -1 ) { - if ( tagname == "br" ) { - emptyTag = space = TRUE; - int index = TQMAX( curpar->length(),1) - 1; - TQTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); - curpar->append( TQChar_linesep ); - curpar->setFormat( index, 1, &format ); - hasNewPar = false; - } else if ( tagname == "hr" ) { - emptyTag = space = TRUE; -#ifndef TQT_NO_TEXTCUSTOMITEM - custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); -#endif - } else if ( tagname == "table" ) { - emptyTag = space = TRUE; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); - curpar->setAlignment( curtag.alignment ); - custom = parseTable( attr, format, doc, length, pos, curpar ); -#endif - } else if ( tagname == "qt" || tagname == "body" ) { - if ( attr.contains( "bgcolor" ) ) { - TQBrush *b = new TQBrush( TQColor( attr["bgcolor"] ) ); - setPaper( b ); - } - if ( attr.contains( "background" ) ) { -#ifndef TQT_NO_MIME - TQImage img; - TQString bg = attr["background"]; - const TQMimeSource* m = factory_->data( bg, contxt ); - if ( !m ) { - tqWarning("TQRichText: no mimesource for %s", bg.latin1() ); - } else { - if ( !TQImageDrag::decode( m, img ) ) { - tqWarning("TQTextImage: cannot decode %s", bg.latin1() ); - } - } - if ( !img.isNull() ) { - TQBrush *b = new TQBrush( TQColor(), TQPixmap( img ) ); - setPaper( b ); - } -#endif - } - if ( attr.contains( "text" ) ) { - TQColor c( attr["text"] ); - initag.format.setColor( c ); - curtag.format.setColor( c ); - bodyText = c; - } - if ( attr.contains( "link" ) ) - linkColor = TQColor( attr["link"] ); - if ( attr.contains( "title" ) ) - attribs.replace( "title", attr["title"] ); - - if ( textEditMode ) { - if ( attr.contains("style" ) ) { - TQString a = attr["style"]; - for ( int s = 0; s < a.contains(';')+1; s++ ) { - TQString style = a.section( ';', s, s ); - if ( style.startsWith("font-size:" ) && style.endsWith("pt") ) { - scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) / - style.mid( 10, style.length() - 12 ).toInt(); - } - } - } - nstyle = 0; // ignore body in textEditMode - } - // end qt- and body-tag handling - } else if ( tagname == "meta" ) { - if ( attr["name"] == "qrichtext" && attr["content"] == "1" ) - textEditMode = TRUE; - } else if ( tagname == "title" ) { - TQString title; - while ( pos < length ) { - if ( hasPrefix( doc, length, pos, TQChar('<') ) && hasPrefix( doc, length, pos+1, TQChar('/') ) && - parseCloseTag( doc, length, pos ) == "title" ) - break; - title += doc[ pos ]; - ++pos; - } - attribs.replace( "title", title ); - } - } // end of well-known tag handling - -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( !custom ) // try generic custom item - custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); -#endif - if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it - continue; - - if ( custom ) { -#ifndef TQT_NO_TEXTCUSTOMITEM - int index = TQMAX( curpar->length(),1) - 1; - TQTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); - curpar->append( TQChar('*') ); - TQTextFormat* f = formatCollection()->format( &format ); - curpar->setFormat( index, 1, f ); - curpar->at( index )->setCustomItem( custom ); - if ( !curtag.anchorHref.isEmpty() ) - curpar->at(index)->setAnchor( TQString::null, curtag.anchorHref ); - if ( !anchorName.isEmpty() ) { - curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); - anchorName = TQString::null; - } - registerCustomItem( custom, curpar ); - hasNewPar = FALSE; -#endif - } else if ( !emptyTag ) { - /* if we do nesting, push curtag on the stack, - otherwise reinint curag. */ - if ( curtag.style->name() != tagname || nstyle->selfNesting() ) { - tags.push( curtag ); - } else { - if ( !tags.isEmpty() ) - curtag = tags.top(); - else - curtag = initag; - } - - curtag.name = tagname; - curtag.style = nstyle; - curtag.name = tagname; - curtag.style = nstyle; - if ( nstyle->whiteSpaceMode() != TQStyleSheetItem::WhiteSpaceModeUndefined ) - curtag.wsm = nstyle->whiteSpaceMode(); - - /* netscape compatibility: eat a newline and only a newline if a pre block starts */ - if ( curtag.wsm == TQStyleSheetItem::WhiteSpacePre && - nstyle->displayMode() == TQStyleSheetItem::DisplayBlock ) - eat( doc, length, pos, '\n' ); - - /* ignore whitespace for inline elements if there - was already one*/ - if ( !textEditMode && - (curtag.wsm == TQStyleSheetItem::WhiteSpaceNormal - || curtag.wsm == TQStyleSheetItem::WhiteSpaceNoWrap) - && ( space || nstyle->displayMode() != TQStyleSheetItem::DisplayInline ) ) - eatSpace( doc, length, pos ); - - curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); - if ( nstyle->isAnchor() ) { - if ( !anchorName.isEmpty() ) - anchorName += "#" + attr["name"]; - else - anchorName = attr["name"]; - curtag.anchorHref = attr["href"]; - } - - if ( nstyle->alignment() != TQStyleSheetItem::Undefined ) - curtag.alignment = nstyle->alignment(); - - if ( nstyle->listStyle() != TQStyleSheetItem::ListStyleUndefined ) - curtag.liststyle = nstyle->listStyle(); - - if ( nstyle->displayMode() == TQStyleSheetItem::DisplayBlock - || nstyle->displayMode() == TQStyleSheetItem::DisplayListItem ) { - - if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") { - TQString type = attr["type"]; - if ( !type.isEmpty() ) { - if ( type == "1" ) { - curtag.liststyle = TQStyleSheetItem::ListDecimal; - } else if ( type == "a" ) { - curtag.liststyle = TQStyleSheetItem::ListLowerAlpha; - } else if ( type == "A" ) { - curtag.liststyle = TQStyleSheetItem::ListUpperAlpha; - } else { - type = type.lower(); - if ( type == "square" ) - curtag.liststyle = TQStyleSheetItem::ListSquare; - else if ( type == "disc" ) - curtag.liststyle = TQStyleSheetItem::ListDisc; - else if ( type == "circle" ) - curtag.liststyle = TQStyleSheetItem::ListCircle; - } - } - } - - - /* Internally we treat ordered and bullet - lists the same for margin calculations. In - order to have fast pointer compares in the - xMargin() functions we restrict ourselves to -
    . Once we calculate the margins in the - parser rathern than later, the unelegance of - this approach goes awy - */ - if ( nstyle->name() == "ul" ) - curtag.style = sheet_->item( "ol" ); - - if ( attr.contains( "align" ) ) { - TQString align = attr["align"].lower(); - if ( align == "center" ) - curtag.alignment = TQt::AlignCenter; - else if ( align == "right" ) - curtag.alignment = TQt::AlignRight; - else if ( align == "justify" ) - curtag.alignment = TQt::AlignJustify; - } - if ( attr.contains( "dir" ) ) { - TQString dir = attr["dir"]; - if ( dir == "rtl" ) - curtag.direction = TQChar::DirR; - else if ( dir == "ltr" ) - curtag.direction = TQChar::DirL; - } - - NEWPAR; - - if ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ) { - if ( attr.contains( "value " ) ) - curpar->setListValue( attr["value"].toInt() ); - } - - if ( attr.contains( "style" ) ) { - TQString a = attr["style"]; - bool ok = TRUE; - for ( int s = 0; ok && s < a.contains(';')+1; s++ ) { - TQString style = a.section( ';', s, s ); - if ( style.startsWith("margin-top:" ) && style.endsWith("px") ) - curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); - else if ( style.startsWith("margin-bottom:" ) && style.endsWith("px") ) - curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); - else if ( style.startsWith("margin-left:" ) && style.endsWith("px") ) - curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); - else if ( style.startsWith("margin-right:" ) && style.endsWith("px") ) - curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); - else if ( style.startsWith("text-indent:" ) && style.endsWith("px") ) - curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); - } - if ( !ok ) // be pressmistic - curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; - } - } - } - } else { - TQString tagname = parseCloseTag( doc, length, pos ); - if ( tagname.isEmpty() ) - continue; // nothing we could do with this, probably parse error - if ( !sheet_->item( tagname ) ) // ignore unknown tags - continue; - if ( tagname == "li" ) - continue; - - // we close a block item. Since the text may continue, we need to have a new paragraph - bool needNewPar = curtag.style->displayMode() == TQStyleSheetItem::DisplayBlock - || curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem; - - - // html slopiness: handle unbalanched tag closing - while ( curtag.name != tagname ) { - TQString msg; - msg.sprintf( "TQText Warning: Document not valid ( '%s' not closed before '%s' #%d)", - curtag.name.ascii(), tagname.ascii(), pos); - sheet_->error( msg ); - if ( tags.isEmpty() ) - break; - curtag = tags.pop(); - } - - - // close the tag - if ( !tags.isEmpty() ) - curtag = tags.pop(); - else - curtag = initag; - - if ( needNewPar ) { - if ( textEditMode && (tagname == "p" || tagname == "div" ) ) // preserve empty paragraphs - hasNewPar = FALSE; - NEWPAR; - } - } - } else { - // normal contents - TQString s; - TQChar c; - while ( pos < length && !hasPrefix(doc, length, pos, TQChar('<') ) ){ - if ( textEditMode ) { - // text edit mode: we handle all white space but ignore newlines - c = parseChar( doc, length, pos, TQStyleSheetItem::WhiteSpacePre ); - if ( c == TQChar_linesep ) - break; - } else { - int l = pos; - c = parseChar( doc, length, pos, curtag.wsm ); - - // in white space pre mode: treat any space as non breakable - // and expand tabs to eight character wide columns. - if ( curtag.wsm == TQStyleSheetItem::WhiteSpacePre ) { - if ( c == '\t' ) { - c = ' '; - while( (++tabExpansionColumn)%8 ) - s += c; - } - if ( c == TQChar_linesep ) - tabExpansionColumn = 0; - else - tabExpansionColumn++; - - } - if ( c == ' ' || c == TQChar_linesep ) { - /* avoid overlong paragraphs by forcing a new - paragraph after 4096 characters. This case can - occur when loading undiscovered plain text - documents in rich text mode. Instead of hanging - forever, we do the trick. - */ - if ( curtag.wsm == TQStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do { - if ( doc[l] == '\n' ) { - hasNewPar = FALSE; // for a new paragraph ... - NEWPAR; - hasNewPar = FALSE; // ... and make it non-reusable - c = '\n'; // make sure we break below - break; - } - } while ( ++l < pos ); - } - } - - if ( c == '\n' ) - break; // break on newlines, pre delievers a TQChar_linesep - - bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; - - if ( curtag.wsm == TQStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) - continue; - if ( c == '\r' ) - continue; - space = c_isSpace; - s += c; - } - if ( !s.isEmpty() && curtag.style->displayMode() != TQStyleSheetItem::DisplayNone ) { - hasNewPar = FALSE; - int index = TQMAX( curpar->length(),1) - 1; - curpar->append( s ); - if (curtag.wsm != TQStyleSheetItem::WhiteSpaceNormal) { - TQTextString *str = curpar->string(); - for (uint i = index; i < index + s.length(); ++i) - str->at(i).nobreak = TRUE; - } - - TQTextFormat* f = formatCollection()->format( &curtag.format ); - curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already - f->ref += s.length() -1; // that what friends are for... - if ( !curtag.anchorHref.isEmpty() ) { - for ( int i = 0; i < int(s.length()); i++ ) - curpar->at(index + i)->setAnchor( TQString::null, curtag.anchorHref ); - } - if ( !anchorName.isEmpty() ) { - for ( int i = 0; i < int(s.length()); i++ ) - curpar->at(index + i)->setAnchor( anchorName, curpar->at(index + i)->anchorHref() ); - anchorName = TQString::null; - } - } - } - } - - if ( hasNewPar && curpar != fParag && !cursor && stylesPar != curpar ) { - // cleanup unused last paragraphs - curpar = curpar->p; - delete curpar->n; - } - - if ( !anchorName.isEmpty() ) { - curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); - anchorName = TQString::null; - } - - - setRichTextMarginsInternal( styles, stylesPar ); - - if ( cursor ) { - cursor->gotoPreviousLetter(); - cursor->remove(); - } - delete vec; -} - -void TQTextDocument::setRichTextMarginsInternal( TQPtrList< TQPtrVector >& styles, TQTextParagraph* stylesPar ) -{ - // margin and line spacing calculation - TQPtrVector* prevStyle = 0; - TQPtrVector* curStyle = styles.first(); - TQPtrVector* nextStyle = styles.next(); - while ( stylesPar ) { - if ( !curStyle ) { - stylesPar = stylesPar->next(); - prevStyle = curStyle; - curStyle = nextStyle; - nextStyle = styles.next(); - continue; - } - - int i, mar; - TQStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0; - if ( mainStyle && mainStyle->displayMode() == TQStyleSheetItem::DisplayListItem ) - stylesPar->setListItem( TRUE ); - int numLists = 0; - for ( i = 0; i < (int)curStyle->size(); ++i ) { - if ( (*curStyle)[ i ]->displayMode() == TQStyleSheetItem::DisplayBlock - && (*curStyle)[ i ]->listStyle() != TQStyleSheetItem::ListStyleUndefined ) - numLists++; - } - stylesPar->ldepth = numLists; - if ( stylesPar->next() && nextStyle ) { - // also set the depth of the next paragraph, required for the margin calculation - numLists = 0; - for ( i = 0; i < (int)nextStyle->size(); ++i ) { - if ( (*nextStyle)[ i ]->displayMode() == TQStyleSheetItem::DisplayBlock - && (*nextStyle)[ i ]->listStyle() != TQStyleSheetItem::ListStyleUndefined ) - numLists++; - } - stylesPar->next()->ldepth = numLists; - } - - // do the top margin - TQStyleSheetItem* item = mainStyle; - int m; - if (stylesPar->utm > 0 ) { - m = stylesPar->utm-1; - stylesPar->utm = 0; - } else { - m = TQMAX(0, item->margin( TQStyleSheetItem::MarginTop ) ); - if ( stylesPar->ldepth ) { - if ( item->displayMode() == TQStyleSheetItem::DisplayListItem ) - m /= stylesPar->ldepth * stylesPar->ldepth; - else - m = 0; - } - } - for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { - item = (*curStyle)[ i ]; - if ( prevStyle && i < (int) prevStyle->size() && - ( item->displayMode() == TQStyleSheetItem::DisplayBlock && - (*prevStyle)[ i ] == item ) ) - break; - // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags - if ( item->listStyle() != TQStyleSheetItem::ListStyleUndefined && - ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) - continue; - mar = TQMAX( 0, item->margin( TQStyleSheetItem::MarginTop ) ); - m = TQMAX( m, mar ); - } - stylesPar->utm = m - stylesPar->topMargin(); - - // do the bottom margin - item = mainStyle; - if (stylesPar->ubm > 0 ) { - m = stylesPar->ubm-1; - stylesPar->ubm = 0; - } else { - m = TQMAX(0, item->margin( TQStyleSheetItem::MarginBottom ) ); - if ( stylesPar->ldepth ) { - if ( item->displayMode() == TQStyleSheetItem::DisplayListItem ) - m /= stylesPar->ldepth * stylesPar->ldepth; - else - m = 0; - } - } - for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { - item = (*curStyle)[ i ]; - if ( nextStyle && i < (int) nextStyle->size() && - ( item->displayMode() == TQStyleSheetItem::DisplayBlock && - (*nextStyle)[ i ] == item ) ) - break; - // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags - if ( item->listStyle() != TQStyleSheetItem::ListStyleUndefined && - ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) - continue; - mar = TQMAX(0, item->margin( TQStyleSheetItem::MarginBottom ) ); - m = TQMAX( m, mar ); - } - stylesPar->ubm = m - stylesPar->bottomMargin(); - - // do the left margin, simplyfied - item = mainStyle; - if (stylesPar->ulm > 0 ) { - m = stylesPar->ulm-1; - stylesPar->ulm = 0; - } else { - m = TQMAX( 0, item->margin( TQStyleSheetItem::MarginLeft ) ); - } - for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { - item = (*curStyle)[ i ]; - m += TQMAX( 0, item->margin( TQStyleSheetItem::MarginLeft ) ); - } - stylesPar->ulm = m - stylesPar->leftMargin(); - - // do the right margin, simplyfied - item = mainStyle; - if (stylesPar->urm > 0 ) { - m = stylesPar->urm-1; - stylesPar->urm = 0; - } else { - m = TQMAX( 0, item->margin( TQStyleSheetItem::MarginRight ) ); - } - for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { - item = (*curStyle)[ i ]; - m += TQMAX( 0, item->margin( TQStyleSheetItem::MarginRight ) ); - } - stylesPar->urm = m - stylesPar->rightMargin(); - - // do the first line margin, which really should be called text-indent - item = mainStyle; - if (stylesPar->uflm > 0 ) { - m = stylesPar->uflm-1; - stylesPar->uflm = 0; - } else { - m = TQMAX( 0, item->margin( TQStyleSheetItem::MarginFirstLine ) ); - } - for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { - item = (*curStyle)[ i ]; - mar = TQMAX( 0, item->margin( TQStyleSheetItem::MarginFirstLine ) ); - m = TQMAX( m, mar ); - } - stylesPar->uflm =m - stylesPar->firstLineMargin(); - - // do the bogus line "spacing", which really is just an extra margin - item = mainStyle; - for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) { - item = (*curStyle)[ i ]; - if ( item->lineSpacing() != TQStyleSheetItem::Undefined ) { - stylesPar->ulinespacing = item->lineSpacing(); - if ( formatCollection() && - stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() ) - stylesPar->ulinespacing += formatCollection()->defaultFormat()->height(); - break; - } - } - - stylesPar = stylesPar->next(); - prevStyle = curStyle; - curStyle = nextStyle; - nextStyle = styles.next(); - } -} - -void TQTextDocument::setText( const TQString &text, const TQString &context ) -{ - focusIndicator.parag = 0; - selections.clear(); - if ( ( txtFormat == TQt::AutoText && TQStyleSheet::mightBeRichText( text ) ) || - txtFormat == TQt::RichText ) - setRichText( text, context ); - else - setPlainText( text ); -} - -TQString TQTextDocument::plainText() const -{ - TQString buffer; - TQString s; - TQTextParagraph *p = fParag; - while ( p ) { - if ( !p->mightHaveCustomItems ) { - const TQTextString *ts = p->string(); // workaround VC++ and Borland - s = ts->toString(); // with FALSE we don't fix spaces (nbsp) - } else { - for ( int i = 0; i < p->length() - 1; ++i ) { -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( p->at( i )->isCustom() ) { - if ( p->at( i )->customItem()->isNested() ) { - s += "\n"; - TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); - TQPtrList cells = t->tableCells(); - for ( TQTextTableCell *c = cells.first(); c; c = cells.next() ) - s += c->richText()->plainText() + "\n"; - s += "\n"; - } - } else -#endif - { - s += p->at( i )->c; - } - } - } - s.remove( s.length() - 1, 1 ); - if ( p->next() ) - s += "\n"; - buffer += s; - p = p->next(); - } - return buffer; -} - -static TQString align_to_string( int a ) -{ - if ( a & TQt::AlignRight ) - return " align=\"right\""; - if ( a & TQt::AlignHCenter ) - return " align=\"center\""; - if ( a & TQt::AlignJustify ) - return " align=\"justify\""; - return TQString::null; -} - -static TQString direction_to_string( int d ) -{ - if ( d != TQChar::DirON ) - return ( d == TQChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" ); - return TQString::null; -} - -static TQString list_value_to_string( int v ) -{ - if ( v != -1 ) - return " listvalue=\"" + TQString::number( v ) + "\""; - return TQString::null; -} - -static TQString list_style_to_string( int v ) -{ - switch( v ) { - case TQStyleSheetItem::ListDecimal: return "\"1\""; - case TQStyleSheetItem::ListLowerAlpha: return "\"a\""; - case TQStyleSheetItem::ListUpperAlpha: return "\"A\""; - case TQStyleSheetItem::ListDisc: return "\"disc\""; - case TQStyleSheetItem::ListSquare: return "\"square\""; - case TQStyleSheetItem::ListCircle: return "\"circle\""; - default: - return TQString::null; - } -} - -static inline bool list_is_ordered( int v ) -{ - return v == TQStyleSheetItem::ListDecimal || - v == TQStyleSheetItem::ListLowerAlpha || - v == TQStyleSheetItem::ListUpperAlpha; -} - - -static TQString margin_to_string( TQStyleSheetItem* style, int t, int b, int l, int r, int fl ) -{ - TQString s; - if ( l > 0 ) - s += TQString(!!s?";":"") + "margin-left:" + TQString::number(l+TQMAX(0,style->margin(TQStyleSheetItem::MarginLeft))) + "px"; - if ( r > 0 ) - s += TQString(!!s?";":"") + "margin-right:" + TQString::number(r+TQMAX(0,style->margin(TQStyleSheetItem::MarginRight))) + "px"; - if ( t > 0 ) - s += TQString(!!s?";":"") + "margin-top:" + TQString::number(t+TQMAX(0,style->margin(TQStyleSheetItem::MarginTop))) + "px"; - if ( b > 0 ) - s += TQString(!!s?";":"") + "margin-bottom:" + TQString::number(b+TQMAX(0,style->margin(TQStyleSheetItem::MarginBottom))) + "px"; - if ( fl > 0 ) - s += TQString(!!s?";":"") + "text-indent:" + TQString::number(fl+TQMAX(0,style->margin(TQStyleSheetItem::MarginFirstLine))) + "px"; - if ( !!s ) - return " style=\"" + s + "\""; - return TQString::null; -} - -TQString TQTextDocument::richText() const -{ - TQString s = ""; - if ( !par ) { - s += "defaultFormat()->font().pointSize() ); - s += "pt;font-family:"; - s += formatCollection()->defaultFormat()->font().family(); - s +="\">"; - } - TQTextParagraph* p = fParag; - - TQStyleSheetItem* item_p = styleSheet()->item("p"); - TQStyleSheetItem* item_div = styleSheet()->item("div"); - TQStyleSheetItem* item_ul = styleSheet()->item("ul"); - TQStyleSheetItem* item_ol = styleSheet()->item("ol"); - TQStyleSheetItem* item_li = styleSheet()->item("li"); - if ( !item_p || !item_div || !item_ul || !item_ol || !item_li ) { - tqWarning( "TQTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, div, ul, ol, or li)" ); - return TQString::null; - } - int pastListDepth = 0; - int listDepth = 0; -#if 0 - int futureListDepth = 0; -#endif - TQMemArray listStyles(10); - - while ( p ) { - listDepth = p->listDepth(); - if ( listDepth < pastListDepth ) { - for ( int i = pastListDepth; i > listDepth; i-- ) - s += list_is_ordered( listStyles[i] ) ? "
" : ""; - s += '\n'; - } else if ( listDepth > pastListDepth ) { - s += '\n'; - listStyles.resize( TQMAX( (int)listStyles.size(), listDepth+1 ) ); - TQString list_type; - listStyles[listDepth] = p->listStyle(); - if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() ) - list_type = " type=" + list_style_to_string( p->listStyle() ); - for ( int i = pastListDepth; i < listDepth; i++ ) { - s += list_is_ordered( p->listStyle() ) ? ""; - } - } else { - s += '\n'; - } - - TQString ps = p->richText(); - -#if 0 - // for the bottom margin we need to know whether we are at the end of a list - futureListDepth = 0; - if ( listDepth > 0 && p->next() ) - futureListDepth = p->next()->listDepth(); -#endif - - if ( richTextExportStart && richTextExportStart->paragraph() ==p && - richTextExportStart->index() == 0 ) - s += ""; - - if ( p->isListItem() ) { - s += "listStyle() != listStyles[listDepth] ) - s += " type=" + list_style_to_string( p->listStyle() ); - s +=align_to_string( p->alignment() ); - s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); - s += list_value_to_string( p->listValue() ); - s += direction_to_string( p->direction() ); - s +=">"; - s += ps; - s += ""; - } else if ( p->listDepth() ) { - s += "alignment() ); - s += margin_to_string( item_div, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); - s +=direction_to_string( p->direction() ); - s += ">"; - s += ps; - s += ""; - } else { - // normal paragraph item - s += "alignment() ); - s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); - s +=direction_to_string( p->direction() ); - s += ">"; - s += ps; - s += "

"; - } - pastListDepth = listDepth; - p = p->next(); - } - while ( listDepth > 0 ) { - s += list_is_ordered( listStyles[listDepth] ) ? "" : ""; - listDepth--; - } - - if ( !par ) - s += "\n\n"; - - return s; -} - -TQString TQTextDocument::text() const -{ - if ( ( txtFormat == TQt::AutoText && preferRichText ) || txtFormat == TQt::RichText ) - return richText(); - return plainText(); -} - -TQString TQTextDocument::text( int parag ) const -{ - TQTextParagraph *p = paragAt( parag ); - if ( !p ) - return TQString::null; - - if ( ( txtFormat == TQt::AutoText && preferRichText ) || txtFormat == TQt::RichText ) - return p->richText(); - else - return p->string()->toString(); -} - -void TQTextDocument::invalidate() -{ - TQTextParagraph *s = fParag; - while ( s ) { - s->invalidate( 0 ); - s = s->next(); - } -} - -void TQTextDocument::selectionStart( int id, int ¶gId, int &index ) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return; - TQTextDocumentSelection &sel = *it; - paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); - index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); -} - -TQTextCursor TQTextDocument::selectionStartCursor( int id) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return TQTextCursor( this ); - TQTextDocumentSelection &sel = *it; - if ( sel.swapped ) - return sel.endCursor; - return sel.startCursor; -} - -TQTextCursor TQTextDocument::selectionEndCursor( int id) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return TQTextCursor( this ); - TQTextDocumentSelection &sel = *it; - if ( !sel.swapped ) - return sel.endCursor; - return sel.startCursor; -} - -void TQTextDocument::selectionEnd( int id, int ¶gId, int &index ) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return; - TQTextDocumentSelection &sel = *it; - paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); - index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); -} - -void TQTextDocument::addSelection( int id ) -{ - nSelections = TQMAX( nSelections, id + 1 ); -} - -static void setSelectionEndHelper( int id, TQTextDocumentSelection &sel, TQTextCursor &start, TQTextCursor &end ) -{ - TQTextCursor c1 = start; - TQTextCursor c2 = end; - if ( sel.swapped ) { - c1 = end; - c2 = start; - } - - c1.paragraph()->removeSelection( id ); - c2.paragraph()->removeSelection( id ); - if ( c1.paragraph() != c2.paragraph() ) { - c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 ); - c2.paragraph()->setSelection( id, 0, c2.index() ); - } else { - c1.paragraph()->setSelection( id, TQMIN( c1.index(), c2.index() ), TQMAX( c1.index(), c2.index() ) ); - } - - sel.startCursor = start; - sel.endCursor = end; - if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) - sel.swapped = sel.startCursor.index() > sel.endCursor.index(); -} - -bool TQTextDocument::setSelectionEnd( int id, const TQTextCursor &cursor ) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return FALSE; - TQTextDocumentSelection &sel = *it; - - TQTextCursor start = sel.startCursor; - TQTextCursor end = cursor; - - if ( start == end ) { - removeSelection( id ); - setSelectionStart( id, cursor ); - return TRUE; - } - - if ( sel.endCursor.paragraph() == end.paragraph() ) { - setSelectionEndHelper( id, sel, start, end ); - return TRUE; - } - - bool inSelection = FALSE; - TQTextCursor c( this ); - TQTextCursor tmp = sel.startCursor; - if ( sel.swapped ) - tmp = sel.endCursor; - tmp.restoreState(); - TQTextCursor tmp2 = cursor; - tmp2.restoreState(); - c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() ); - bool hadStart = FALSE; - bool hadEnd = FALSE; - bool hadStartParag = FALSE; - bool hadEndParag = FALSE; - bool hadOldStart = FALSE; - bool hadOldEnd = FALSE; - bool leftSelection = FALSE; - sel.swapped = FALSE; - for ( ;; ) { - if ( c == start ) - hadStart = TRUE; - if ( c == end ) - hadEnd = TRUE; - if ( c.paragraph() == start.paragraph() ) - hadStartParag = TRUE; - if ( c.paragraph() == end.paragraph() ) - hadEndParag = TRUE; - if ( c == sel.startCursor ) - hadOldStart = TRUE; - if ( c == sel.endCursor ) - hadOldEnd = TRUE; - - if ( !sel.swapped && - ( ( hadEnd && !hadStart ) || - ( hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) ) ) - sel.swapped = TRUE; - - if ( ( c == end && hadStartParag ) || - ( c == start && hadEndParag ) ) { - TQTextCursor tmp = c; - tmp.restoreState(); - if ( tmp.paragraph() != c.paragraph() ) { - int sstart = tmp.paragraph()->selectionStart( id ); - tmp.paragraph()->removeSelection( id ); - tmp.paragraph()->setSelection( id, sstart, tmp.index() ); - } - } - - if ( inSelection && - ( ( c == end && hadStart ) || ( c == start && hadEnd ) ) ) - leftSelection = TRUE; - else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) ) - inSelection = TRUE; - - bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd(); - c.paragraph()->removeSelection( id ); - if ( inSelection ) { - if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) { - c.paragraph()->setSelection( id, TQMIN( start.index(), end.index() ), TQMAX( start.index(), end.index() ) ); - } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) { - c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 ); - } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) { - c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 ); - } else if ( c.paragraph() == end.paragraph() && hadEndParag ) { - c.paragraph()->setSelection( id, 0, end.index() ); - } else if ( c.paragraph() == start.paragraph() && hadStartParag ) { - c.paragraph()->setSelection( id, 0, start.index() ); - } else { - c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 ); - } - } - - if ( leftSelection ) - inSelection = FALSE; - - if ( noSelectionAnymore ) - break; - // *ugle*hack optimization - TQTextParagraph *p = c.paragraph(); - if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) { - c.gotoNextLetter(); - if ( p == lastParagraph() && c.atParagEnd() ) - break; - } else { - if ( p->document()->parent() ) - do { - c.gotoNextLetter(); - } while ( c.paragraph() == p ); - else - c.setParagraph( p->next() ); - } - } - - if ( !sel.swapped ) - sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 ); - - sel.startCursor = start; - sel.endCursor = end; - if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) - sel.swapped = sel.startCursor.index() > sel.endCursor.index(); - - setSelectionEndHelper( id, sel, start, end ); - - return TRUE; -} - -void TQTextDocument::selectAll( int id ) -{ - removeSelection( id ); - - TQTextDocumentSelection sel; - sel.swapped = FALSE; - TQTextCursor c( this ); - - c.setParagraph( fParag ); - c.setIndex( 0 ); - sel.startCursor = c; - - c.setParagraph( lParag ); - c.setIndex( lParag->length() - 1 ); - sel.endCursor = c; - - selections.insert( id, sel ); - - TQTextParagraph *p = fParag; - while ( p ) { - p->setSelection( id, 0, p->length() - 1 ); - p = p->next(); - } - - for ( TQTextDocument *d = childList.first(); d; d = childList.next() ) - d->selectAll( id ); -} - -bool TQTextDocument::removeSelection( int id ) -{ - if ( !selections.contains( id ) ) - return FALSE; - - TQTextDocumentSelection &sel = selections[ id ]; - - TQTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor; - TQTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor; - TQTextParagraph* p = 0; - while ( start != end ) { - if ( p != start.paragraph() ) { - p = start.paragraph(); - p->removeSelection( id ); - //### avoid endless loop by all means necessary, did somebody mention refactoring? - if ( !parent() && p == lParag ) - break; - } - start.gotoNextLetter(); - } - p = start.paragraph(); - p->removeSelection( id ); - selections.remove( id ); - return TRUE; -} - -TQString TQTextDocument::selectedText( int id, bool asRichText ) const -{ - TQMap::ConstIterator it = selections.find( id ); - if ( it == selections.end() ) - return TQString::null; - - TQTextDocumentSelection sel = *it; - - - TQTextCursor c1 = sel.startCursor; - TQTextCursor c2 = sel.endCursor; - if ( sel.swapped ) { - c2 = sel.startCursor; - c1 = sel.endCursor; - } - - /* 3.0.3 improvement: Make it possible to get a reasonable - selection inside a table. This approach is very conservative: - make sure that both cursors have the same depth level and point - to paragraphs within the same text document. - - Meaning if you select text in two table cells, you will get the - entire table. This is still far better than the 3.0.2, where - you always got the entire table. - - ### Fix this properly when refactoring - */ - while ( c2.nestedDepth() > c1.nestedDepth() ) - c2.oneUp(); - while ( c1.nestedDepth() > c2.nestedDepth() ) - c1.oneUp(); - while ( c1.nestedDepth() && c2.nestedDepth() && - c1.paragraph()->document() != c2.paragraph()->document() ) { - c1.oneUp(); - c2.oneUp(); - } - // do not trust sel_swapped with tables. Fix this properly when refactoring as well - if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() || - (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) { - TQTextCursor tmp = c1; - c2 = c1; - c1 = tmp; - } - - // end selection 3.0.3 improvement - - if ( asRichText && !parent() ) { - richTextExportStart = &c1; - richTextExportEnd = &c2; - - TQString sel = richText(); - int from = sel.find( "" ); - if ( from >= 0 ) { - from += 20; - // find the previous span and move it into the start fragment before we clip it - TQString prevspan; - int pspan = sel.findRev( " sel.findRev( "', pspan ); - prevspan = sel.mid( pspan, spanend - pspan + 1 ); - } - int to = sel.findRev( "" ); - if ( from <= to ) - sel = "" + prevspan + sel.mid( from, to - from ); - } - richTextExportStart = richTextExportEnd = 0; - return sel; - } - - TQString s; - if ( c1.paragraph() == c2.paragraph() ) { - TQTextParagraph *p = c1.paragraph(); - int end = c2.index(); - if ( p->at( TQMAX( 0, end - 1 ) )->isCustom() ) - ++end; - if ( !p->mightHaveCustomItems ) { - s += p->string()->toString().mid( c1.index(), end - c1.index() ); - } else { - for ( int i = c1.index(); i < end; ++i ) { -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( p->at( i )->isCustom() ) { - if ( p->at( i )->customItem()->isNested() ) { - s += "\n"; - TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); - TQPtrList cells = t->tableCells(); - for ( TQTextTableCell *c = cells.first(); c; c = cells.next() ) - s += c->richText()->plainText() + "\n"; - s += "\n"; - } - } else -#endif - { - s += p->at( i )->c; - } - } - } - } else { - TQTextParagraph *p = c1.paragraph(); - int start = c1.index(); - while ( p ) { - int end = p == c2.paragraph() ? c2.index() : p->length() - 1; - if ( p == c2.paragraph() && p->at( TQMAX( 0, end - 1 ) )->isCustom() ) - ++end; - if ( !p->mightHaveCustomItems ) { - s += p->string()->toString().mid( start, end - start ); - if ( p != c2.paragraph() ) - s += "\n"; - } else { - for ( int i = start; i < end; ++i ) { -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( p->at( i )->isCustom() ) { - if ( p->at( i )->customItem()->isNested() ) { - s += "\n"; - TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); - TQPtrList cells = t->tableCells(); - for ( TQTextTableCell *c = cells.first(); c; c = cells.next() ) - s += c->richText()->plainText() + "\n"; - s += "\n"; - } - } else -#endif - { - s += p->at( i )->c; - } - } - } - start = 0; - if ( p == c2.paragraph() ) - break; - p = p->next(); - } - } - // ### workaround for plain text export until we get proper - // mime types: turn unicode line seperators into the more - // widely understood \n. Makes copy and pasting code snipplets - // from within Assistent possible - TQChar* uc = (TQChar*) s.unicode(); - for ( uint ii = 0; ii < s.length(); ii++ ) { - if ( uc[(int)ii] == TQChar_linesep ) - uc[(int)ii] = TQChar('\n'); - else if ( uc[(int)ii] == TQChar::nbsp ) - uc[(int)ii] = TQChar(' '); - } - return s; -} - -void TQTextDocument::setFormat( int id, TQTextFormat *f, int flags ) -{ - TQMap::ConstIterator it = selections.find( id ); - if ( it == selections.end() ) - return; - - TQTextDocumentSelection sel = *it; - - TQTextCursor c1 = sel.startCursor; - TQTextCursor c2 = sel.endCursor; - if ( sel.swapped ) { - c2 = sel.startCursor; - c1 = sel.endCursor; - } - - c2.restoreState(); - c1.restoreState(); - - if ( c1.paragraph() == c2.paragraph() ) { - c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); - return; - } - - c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags ); - TQTextParagraph *p = c1.paragraph()->next(); - while ( p && p != c2.paragraph() ) { - p->setFormat( 0, p->length(), f, TRUE, flags ); - p = p->next(); - } - c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags ); -} - -void TQTextDocument::removeSelectedText( int id, TQTextCursor *cursor ) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return; - - TQTextDocumentSelection sel = *it; - TQTextCursor c1 = sel.startCursor; - TQTextCursor c2 = sel.endCursor; - if ( sel.swapped ) { - c2 = sel.startCursor; - c1 = sel.endCursor; - } - - // ### no support for editing tables yet - if ( c1.nestedDepth() || c2.nestedDepth() ) - return; - - c2.restoreState(); - c1.restoreState(); - - *cursor = c1; - removeSelection( id ); - - if ( c1.paragraph() == c2.paragraph() ) { - c1.paragraph()->remove( c1.index(), c2.index() - c1.index() ); - return; - } - - if ( c1.paragraph() == fParag && c1.index() == 0 && - c2.paragraph() == lParag && c2.index() == lParag->length() - 1 ) - cursor->setValid( FALSE ); - - bool didGoLeft = FALSE; - if ( c1.index() == 0 && c1.paragraph() != fParag ) { - cursor->gotoPreviousLetter(); - didGoLeft = cursor->isValid(); - } - - c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() ); - TQTextParagraph *p = c1.paragraph()->next(); - int dy = 0; - TQTextParagraph *tmp; - while ( p && p != c2.paragraph() ) { - tmp = p->next(); - dy -= p->rect().height(); - delete p; - p = tmp; - } - c2.paragraph()->remove( 0, c2.index() ); - while ( p ) { - p->move( dy ); - p->invalidate( 0 ); - p->setEndState( -1 ); - p = p->next(); - } - - - c1.paragraph()->join( c2.paragraph() ); - - if ( didGoLeft ) - cursor->gotoNextLetter(); -} - -void TQTextDocument::indentSelection( int id ) -{ - TQMap::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return; - - TQTextDocumentSelection sel = *it; - TQTextParagraph *startParag = sel.startCursor.paragraph(); - TQTextParagraph *endParag = sel.endCursor.paragraph(); - if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { - endParag = sel.startCursor.paragraph(); - startParag = sel.endCursor.paragraph(); - } - - TQTextParagraph *p = startParag; - while ( p && p != endParag ) { - p->indent(); - p = p->next(); - } -} - -void TQTextDocument::addCommand( TQTextCommand *cmd ) -{ - commandHistory->addCommand( cmd ); -} - -TQTextCursor *TQTextDocument::undo( TQTextCursor *c ) -{ - return commandHistory->undo( c ); -} - -TQTextCursor *TQTextDocument::redo( TQTextCursor *c ) -{ - return commandHistory->redo( c ); -} - -bool TQTextDocument::find( TQTextCursor& cursor, const TQString &expr, bool cs, bool wo, bool forward ) -{ - removeSelection( Standard ); - TQTextParagraph *p = 0; - if ( expr.isEmpty() ) - return FALSE; - for (;;) { - if ( p != cursor.paragraph() ) { - p = cursor.paragraph(); - TQString s = cursor.paragraph()->string()->toString(); - int start = cursor.index(); - for ( ;; ) { - int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs ); - int end = res + expr.length(); - if ( res == -1 || ( !forward && start <= res ) ) - break; - if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && - ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) { - removeSelection( Standard ); - cursor.setIndex( forward ? end : res ); - setSelectionStart( Standard, cursor ); - cursor.setIndex( forward ? res : end ); - setSelectionEnd( Standard, cursor ); - if ( !forward ) - cursor.setIndex( res ); - return TRUE; - } - start = res + (forward ? 1 : -1); - } - } - if ( forward ) { - if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd() ) - break; - cursor.gotoNextLetter(); - } else { - if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() ) - break; - cursor.gotoPreviousLetter(); - } - } - return FALSE; -} - -void TQTextDocument::setTextFormat( TQt::TextFormat f ) -{ - txtFormat = f; - if ( fParag == lParag && fParag->length() <= 1 ) - fParag->rtext = ( f == TQt::RichText ); -} - -TQt::TextFormat TQTextDocument::textFormat() const -{ - return txtFormat; -} - -bool TQTextDocument::inSelection( int selId, const TQPoint &pos ) const -{ - TQMap::ConstIterator it = selections.find( selId ); - if ( it == selections.end() ) - return FALSE; - - TQTextDocumentSelection sel = *it; - TQTextParagraph *startParag = sel.startCursor.paragraph(); - TQTextParagraph *endParag = sel.endCursor.paragraph(); - if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() && - sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) ) - return FALSE; - if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { - endParag = sel.startCursor.paragraph(); - startParag = sel.endCursor.paragraph(); - } - - TQTextParagraph *p = startParag; - while ( p ) { - if ( p->rect().contains( pos ) ) { - bool inSel = FALSE; - int selStart = p->selectionStart( selId ); - int selEnd = p->selectionEnd( selId ); - int y = 0; - int h = 0; - for ( int i = 0; i < p->length(); ++i ) { - if ( i == selStart ) - inSel = TRUE; - if ( i == selEnd ) - break; - if ( p->at( i )->lineStart ) { - y = (*p->lineStarts.find( i ))->y; - h = (*p->lineStarts.find( i ))->h; - } - if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) { - if ( inSel && pos.x() >= p->at( i )->x && - pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) ) - return TRUE; - } - } - } - if ( pos.y() < p->rect().y() ) - break; - if ( p == endParag ) - break; - p = p->next(); - } - - return FALSE; -} - -void TQTextDocument::doLayout( TQPainter *p, int w ) -{ - minw = wused = 0; - if ( !is_printer( p ) ) - p = 0; - withoutDoubleBuffer = ( p != 0 ); - TQPainter * oldPainter = TQTextFormat::painter(); - TQTextFormat::setPainter( p ); - tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; - flow_->setWidth( w ); - cw = w; - vw = w; - TQTextParagraph *parag = fParag; - while ( parag ) { - parag->invalidate( 0 ); - if ( p ) - parag->adjustToPainter( p ); - parag->format(); - parag = parag->next(); - } - TQTextFormat::setPainter( oldPainter ); -} - -TQPixmap *TQTextDocument::bufferPixmap( const TQSize &s ) -{ - if ( !buf_pixmap ) - buf_pixmap = new TQPixmap( s.expandedTo( TQSize(1,1) ) ); - else if ( buf_pixmap->size() != s ) - buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) ); - return buf_pixmap; -} - -void TQTextDocument::draw( TQPainter *p, const TQRect &rect, const TQColorGroup &cg, const TQBrush *paper ) -{ - if ( !firstParagraph() ) - return; - - if ( paper ) { - p->setBrushOrigin( -int( p->translationX() ), - -int( p->translationY() ) ); - - p->fillRect( rect, *paper ); - } - - TQPainter * oldPainter = TQTextFormat::painter(); - TQTextFormat::setPainter( p ); - - if ( formatCollection()->defaultFormat()->color() != cg.text() ) - setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); - - TQTextParagraph *parag = firstParagraph(); - while ( parag ) { - if ( !parag->isValid() ) - parag->format(); - int y = parag->rect().y(); - TQRect pr( parag->rect() ); - pr.setX( 0 ); - pr.setWidth( TQWIDGETSIZE_MAX ); - if ( !rect.isNull() && !rect.intersects( pr ) ) { - parag = parag->next(); - continue; - } - p->translate( 0, y ); - if ( rect.isValid() ) - parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() ); - else - parag->paint( *p, cg, 0, FALSE ); - p->translate( 0, -y ); - parag = parag->next(); - if ( !flow()->isEmpty() ) - flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE ); - } - TQTextFormat::setPainter(oldPainter); -} - -void TQTextDocument::drawParagraph( TQPainter *p, TQTextParagraph *parag, int cx, int cy, int cw, int ch, - TQPixmap *&doubleBuffer, const TQColorGroup &cg, - bool drawCursor, TQTextCursor *cursor, bool resetChanged ) -{ - TQPainter *painter = 0; - if ( resetChanged ) - parag->setChanged( FALSE ); - TQRect ir( parag->rect() ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if (!parag->tableCell()) -#endif - ir.setWidth(width()); - - bool uDoubleBuffer = useDoubleBuffer( parag, p ); - - if ( uDoubleBuffer ) { - painter = new TQPainter; - if ( cx >= 0 && cy >= 0 ) - ir = ir.intersect( TQRect( cx, cy, cw, ch ) ); - if ( !doubleBuffer || - ir.width() > doubleBuffer->width() || - ir.height() > doubleBuffer->height() ) { - doubleBuffer = bufferPixmap( ir.size() ); - painter->begin( doubleBuffer ); - } else { - painter->begin( doubleBuffer ); - } - } else { - painter = p; - painter->translate( ir.x(), ir.y() ); - } - - painter->setBrushOrigin( -ir.x(), -ir.y() ); - - if ( uDoubleBuffer || is_printer( painter ) ) - painter->fillRect( TQRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) ); - else if ( cursor && cursor->paragraph() == parag ) - painter->fillRect( TQRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ), - parag->backgroundBrush( cg ) ); - - painter->translate( -( ir.x() - parag->rect().x() ), - -( ir.y() - parag->rect().y() ) ); - parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch ); - - if ( uDoubleBuffer ) { - delete painter; - painter = 0; - p->drawPixmap( ir.topLeft(), *doubleBuffer, TQRect( TQPoint( 0, 0 ), ir.size() ) ); - } else { - painter->translate( -ir.x(), -ir.y() ); - } - - parag->document()->nextDoubleBuffered = FALSE; -} - -TQTextParagraph *TQTextDocument::draw( TQPainter *p, int cx, int cy, int cw, int ch, const TQColorGroup &cg, - bool onlyChanged, bool drawCursor, TQTextCursor *cursor, bool resetChanged ) -{ - if ( withoutDoubleBuffer || ( par && par->withoutDoubleBuffer ) ) { - withoutDoubleBuffer = TRUE; - TQRect r; - draw( p, r, cg ); - return 0; - } - withoutDoubleBuffer = FALSE; - - if ( !firstParagraph() ) - return 0; - - TQPainter * oldPainter = TQTextFormat::painter(); - TQTextFormat::setPainter( p ); - if ( formatCollection()->defaultFormat()->color() != cg.text() ) - setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); - - if ( cx < 0 && cy < 0 ) { - cx = 0; - cy = 0; - cw = width(); - ch = height(); - } - - TQTextParagraph *lastFormatted = 0; - TQTextParagraph *parag = firstParagraph(); - - TQPixmap *doubleBuffer = 0; - - while ( parag ) { - lastFormatted = parag; - if ( !parag->isValid() ) - parag->format(); - - TQRect pr = parag->rect(); - pr.setWidth( parag->document()->width() ); - if ( pr.y() > cy + ch ) - goto floating; - TQRect clipr( cx, cy, cw, ch ); - if ( !pr.intersects( clipr ) || ( onlyChanged && !parag->hasChanged() ) ) { - pr.setWidth( parag->document()->width() ); - parag = parag->next(); - continue; - } - - drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); - parag = parag->next(); - } - - parag = lastParagraph(); - - floating: - if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) { - if ( !parag->document()->parent() ) { - TQRect fillRect = TQRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), - parag->document()->height() - ( parag->rect().y() + parag->rect().height() ) ); - if ( TQRect( cx, cy, cw, ch ).intersects( fillRect ) ) - p->fillRect( fillRect, cg.brush( TQColorGroup::Base ) ); - } - if ( !flow()->isEmpty() ) { - TQRect cr( cx, cy, cw, ch ); - flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE ); - } - } - - if ( buf_pixmap && buf_pixmap->height() > 300 ) { - delete buf_pixmap; - buf_pixmap = 0; - } - - TQTextFormat::setPainter(oldPainter); - return lastFormatted; -} - -/* - #### this function only sets the default font size in the format collection - */ -void TQTextDocument::setDefaultFormat( const TQFont &font, const TQColor &color ) -{ - bool reformat = font != fCollection->defaultFormat()->font(); - for ( TQTextDocument *d = childList.first(); d; d = childList.next() ) - d->setDefaultFormat( font, color ); - fCollection->updateDefaultFormat( font, color, sheet_ ); - - if ( !reformat ) - return; - tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; - - // invalidate paragraphs and custom items - TQTextParagraph *p = fParag; - while ( p ) { - p->invalidate( 0 ); -#ifndef TQT_NO_TEXTCUSTOMITEM - for ( int i = 0; i < p->length() - 1; ++i ) - if ( p->at( i )->isCustom() ) - p->at( i )->customItem()->invalidate(); -#endif - p = p->next(); - } -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -void TQTextDocument::registerCustomItem( TQTextCustomItem *i, TQTextParagraph *p ) -{ - if ( i && i->placement() != TQTextCustomItem::PlaceInline ) { - flow_->registerFloatingItem( i ); - p->registerFloatingItem( i ); - } - if (i) i->setParagraph( p ); - p->mightHaveCustomItems = mightHaveCustomItems = TRUE; -} - -void TQTextDocument::unregisterCustomItem( TQTextCustomItem *i, TQTextParagraph *p ) -{ - p->unregisterFloatingItem( i ); - i->setParagraph( 0 ); - flow_->unregisterFloatingItem( i ); -} -#endif - -bool TQTextDocument::hasFocusParagraph() const -{ - return !!focusIndicator.parag; -} - -TQString TQTextDocument::focusHref() const -{ - return focusIndicator.href; -} - -TQString TQTextDocument::focusName() const -{ - return focusIndicator.name; -} - -bool TQTextDocument::focusNextPrevChild( bool next ) -{ - if ( !focusIndicator.parag ) { - if ( next ) { - focusIndicator.parag = fParag; - focusIndicator.start = 0; - focusIndicator.len = 0; - } else { - focusIndicator.parag = lParag; - focusIndicator.start = lParag->length(); - focusIndicator.len = 0; - } - } else { - focusIndicator.parag->setChanged( TRUE ); - } - focusIndicator.href = TQString::null; - focusIndicator.name = TQString::null; - - if ( next ) { - TQTextParagraph *p = focusIndicator.parag; - int index = focusIndicator.start + focusIndicator.len; - while ( p ) { - for ( int i = index; i < p->length(); ++i ) { - if ( p->at( i )->isAnchor() ) { - p->setChanged( TRUE ); - focusIndicator.parag = p; - focusIndicator.start = i; - focusIndicator.len = 0; - focusIndicator.href = p->at( i )->anchorHref(); - focusIndicator.name = p->at( i )->anchorName(); - while ( i < p->length() ) { - if ( !p->at( i )->isAnchor() ) - return TRUE; - focusIndicator.len++; - i++; - } -#ifndef TQT_NO_TEXTCUSTOMITEM - } else if ( p->at( i )->isCustom() ) { - if ( p->at( i )->customItem()->isNested() ) { - TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); - TQPtrList cells = t->tableCells(); - // first try to continue - TQTextTableCell *c; - bool resetCells = TRUE; - for ( c = cells.first(); c; c = cells.next() ) { - if ( c->richText()->hasFocusParagraph() ) { - if ( c->richText()->focusNextPrevChild( next ) ) { - p->setChanged( TRUE ); - focusIndicator.parag = p; - focusIndicator.start = i; - focusIndicator.len = 0; - focusIndicator.href = c->richText()->focusHref(); - focusIndicator.name = c->richText()->focusName(); - return TRUE; - } else { - resetCells = FALSE; - c = cells.next(); - break; - } - } - } - // now really try - if ( resetCells ) - c = cells.first(); - for ( ; c; c = cells.next() ) { - if ( c->richText()->focusNextPrevChild( next ) ) { - p->setChanged( TRUE ); - focusIndicator.parag = p; - focusIndicator.start = i; - focusIndicator.len = 0; - focusIndicator.href = c->richText()->focusHref(); - focusIndicator.name = c->richText()->focusName(); - return TRUE; - } - } - } -#endif - } - } - index = 0; - p = p->next(); - } - } else { - TQTextParagraph *p = focusIndicator.parag; - int index = focusIndicator.start - 1; - if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 ) - index++; - while ( p ) { - for ( int i = index; i >= 0; --i ) { - if ( p->at( i )->isAnchor() ) { - p->setChanged( TRUE ); - focusIndicator.parag = p; - focusIndicator.start = i; - focusIndicator.len = 0; - focusIndicator.href = p->at( i )->anchorHref(); - focusIndicator.name = p->at( i )->anchorName(); - while ( i >= -1 ) { - if ( i < 0 || !p->at( i )->isAnchor() ) { - focusIndicator.start++; - return TRUE; - } - if ( i < 0 ) - break; - focusIndicator.len++; - focusIndicator.start--; - i--; - } -#ifndef TQT_NO_TEXTCUSTOMITEM - } else if ( p->at( i )->isCustom() ) { - if ( p->at( i )->customItem()->isNested() ) { - TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); - TQPtrList cells = t->tableCells(); - // first try to continue - TQTextTableCell *c; - bool resetCells = TRUE; - for ( c = cells.last(); c; c = cells.prev() ) { - if ( c->richText()->hasFocusParagraph() ) { - if ( c->richText()->focusNextPrevChild( next ) ) { - p->setChanged( TRUE ); - focusIndicator.parag = p; - focusIndicator.start = i; - focusIndicator.len = 0; - focusIndicator.href = c->richText()->focusHref(); - focusIndicator.name = c->richText()->focusName(); - return TRUE; - } else { - resetCells = FALSE; - c = cells.prev(); - break; - } - } - if ( cells.at() == 0 ) - break; - } - // now really try - if ( resetCells ) - c = cells.last(); - for ( ; c; c = cells.prev() ) { - if ( c->richText()->focusNextPrevChild( next ) ) { - p->setChanged( TRUE ); - focusIndicator.parag = p; - focusIndicator.start = i; - focusIndicator.len = 0; - focusIndicator.href = c->richText()->focusHref(); - focusIndicator.name = c->richText()->focusName(); - return TRUE; - } - if ( cells.at() == 0 ) - break; - } - } -#endif - } - } - p = p->prev(); - if ( p ) - index = p->length() - 1; - } - } - - focusIndicator.parag = 0; - - return FALSE; -} - -int TQTextDocument::length() const -{ - int l = -1; - TQTextParagraph *p = fParag; - while ( p ) { - l += p->length(); - p = p->next(); - } - return TQMAX(0,l); -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -int TQTextFormat::width( const TQChar &c ) const -{ - if ( c.unicode() == 0xad ) // soft hyphen - return 0; - if ( !pntr || !pntr->isActive() ) { - if ( c == '\t' ) - return fm.width( ' ' ); - if ( ha == AlignNormal ) { - int w; - if ( c.row() ) - w = fm.width( c ); - else - w = widths[ c.unicode() ]; - if ( w == 0 && !c.row() ) { - w = fm.width( c ); - ( (TQTextFormat*)this )->widths[ c.unicode() ] = w; - } - return w; - } else { - TQFont f( fn ); - if ( usePixelSizes ) - f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); - else - f.setPointSize( ( f.pointSize() * 2 ) / 3 ); - TQFontMetrics fm_( f ); - return fm_.width( c ); - } - } - - TQFont f( fn ); - if ( ha != AlignNormal ) { - if ( usePixelSizes ) - f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); - else - f.setPointSize( ( f.pointSize() * 2 ) / 3 ); - } - applyFont( f ); - - return pntr_fm->width( c ); -} - -int TQTextFormat::width( const TQString &str, int pos ) const -{ - int w = 0; - if ( str.unicode()[ pos ].unicode() == 0xad ) - return w; - if ( !pntr || !pntr->isActive() ) { - if ( ha == AlignNormal ) { - w = fm.charWidth( str, pos ); - } else { - TQFont f( fn ); - if ( usePixelSizes ) - f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); - else - f.setPointSize( ( f.pointSize() * 2 ) / 3 ); - TQFontMetrics fm_( f ); - w = fm_.charWidth( str, pos ); - } - } else { - TQFont f( fn ); - if ( ha != AlignNormal ) { - if ( usePixelSizes ) - f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); - else - f.setPointSize( ( f.pointSize() * 2 ) / 3 ); - } - applyFont( f ); - w = pntr_fm->charWidth( str, pos ); - } - return w; -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextString::TQTextString() -{ - bidiDirty = TRUE; - bidi = FALSE; - rightToLeft = FALSE; - dir = TQChar::DirON; -} - -TQTextString::TQTextString( const TQTextString &s ) -{ - bidiDirty = TRUE; - bidi = s.bidi; - rightToLeft = s.rightToLeft; - dir = s.dir; - data = s.data; - data.detach(); - for ( int i = 0; i < (int)data.size(); ++i ) { - TQTextFormat *f = data[i].format(); - if ( f ) - f->addRef(); - } -} - -void TQTextString::insert( int index, const TQString &s, TQTextFormat *f ) -{ - insert( index, s.unicode(), s.length(), f ); -} - -void TQTextString::insert( int index, const TQChar *unicode, int len, TQTextFormat *f ) -{ - int os = data.size(); - data.resize( data.size() + len, TQGArray::SpeedOptim ); - if ( index < os ) { - memmove( data.data() + index + len, data.data() + index, - sizeof( TQTextStringChar ) * ( os - index ) ); - } - TQTextStringChar *ch = data.data() + index; - for ( int i = 0; i < len; ++i ) { - ch->x = 0; - ch->lineStart = 0; - ch->d.format = 0; - ch->nobreak = FALSE; - ch->type = TQTextStringChar::Regular; - ch->d.format = f; - ch->rightToLeft = 0; - ch->c = unicode[i]; - ++ch; - } - bidiDirty = TRUE; -} - -TQTextString::~TQTextString() -{ - clear(); -} - -void TQTextString::insert( int index, TQTextStringChar *c, bool doAddRefFormat ) -{ - int os = data.size(); - data.resize( data.size() + 1, TQGArray::SpeedOptim ); - if ( index < os ) { - memmove( data.data() + index + 1, data.data() + index, - sizeof( TQTextStringChar ) * ( os - index ) ); - } - TQTextStringChar &ch = data[ (int)index ]; - ch.c = c->c; - ch.x = 0; - ch.lineStart = 0; - ch.rightToLeft = 0; - ch.d.format = 0; - ch.type = TQTextStringChar::Regular; - ch.nobreak = FALSE; - if ( doAddRefFormat && c->format() ) - c->format()->addRef(); - ch.setFormat( c->format() ); - bidiDirty = TRUE; -} - -int TQTextString::appendParagraphs( TQTextParagraph *start, TQTextParagraph *end ) -{ - int paragCount = 0; - int newLength = data.size(); - TQTextParagraph *p = start; - for (; p != end; p = p->next()) { - newLength += p->length(); - ++paragCount; - } - - const int oldLength = data.size(); - data.resize(newLength, TQGArray::SpeedOptim); - - TQTextStringChar *d = &data[oldLength]; - for (p = start; p != end; p = p->next()) { - const TQTextStringChar * const src = p->at(0); - int i = 0; - for (; i < p->length() - 1; ++i) { - d[i].c = src[i].c; - d[i].x = 0; - d[i].lineStart = 0; - d[i].rightToLeft = 0; - d[i].type = TQTextStringChar::Regular; - d[i].nobreak = FALSE; - d[i].d.format = src[i].format(); - if (d[i].d.format) - d[i].d.format->addRef(); - } - d[i].x = 0; - d[i].lineStart = 0; - d[i].nobreak = FALSE; - d[i].type = TQTextStringChar::Regular; - d[i].d.format = 0; - d[i].rightToLeft = 0; - d[i].c = '\n'; - d += p->length(); - } - - bidiDirty = TRUE; - return paragCount; -} - -void TQTextString::truncate( int index ) -{ - index = TQMAX( index, 0 ); - index = TQMIN( index, (int)data.size() - 1 ); - if ( index < (int)data.size() ) { - for ( int i = index + 1; i < (int)data.size(); ++i ) { - TQTextStringChar &ch = data[ i ]; -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( !(ch.type == TQTextStringChar::Regular) ) { - delete ch.customItem(); - if ( ch.d.custom->format ) - ch.d.custom->format->removeRef(); - delete ch.d.custom; - ch.d.custom = 0; - } else -#endif - if ( ch.format() ) { - ch.format()->removeRef(); - } - } - } - data.truncate( index ); - bidiDirty = TRUE; -} - -void TQTextString::remove( int index, int len ) -{ - for ( int i = index; i < (int)data.size() && i - index < len; ++i ) { - TQTextStringChar &ch = data[ i ]; -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( !(ch.type == TQTextStringChar::Regular) ) { - delete ch.customItem(); - if ( ch.d.custom->format ) - ch.d.custom->format->removeRef(); - delete ch.d.custom; - ch.d.custom = 0; - } else -#endif - if ( ch.format() ) { - ch.format()->removeRef(); - } - } - memmove( data.data() + index, data.data() + index + len, - sizeof( TQTextStringChar ) * ( data.size() - index - len ) ); - data.resize( data.size() - len, TQGArray::SpeedOptim ); - bidiDirty = TRUE; -} - -void TQTextString::clear() -{ - for ( int i = 0; i < (int)data.count(); ++i ) { - TQTextStringChar &ch = data[ i ]; -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( !(ch.type == TQTextStringChar::Regular) ) { - if ( ch.customItem() && ch.customItem()->placement() == TQTextCustomItem::PlaceInline ) - delete ch.customItem(); - if ( ch.d.custom->format ) - ch.d.custom->format->removeRef(); - delete ch.d.custom; - ch.d.custom = 0; - } else -#endif - if ( ch.format() ) { - ch.format()->removeRef(); - } - } - data.resize( 0 ); - bidiDirty = TRUE; -} - -void TQTextString::setFormat( int index, TQTextFormat *f, bool useCollection ) -{ - TQTextStringChar &ch = data[ index ]; - if ( useCollection && ch.format() ) - ch.format()->removeRef(); - ch.setFormat( f ); -} - -void TQTextString::checkBidi() const -{ - TQTextString *that = (TQTextString *)this; - that->bidiDirty = FALSE; - int length = data.size(); - if ( !length ) { - that->bidi = FALSE; - that->rightToLeft = dir == TQChar::DirR; - return; - } - const TQTextStringChar *start = data.data(); - const TQTextStringChar *end = start + length; - - ((TQTextString *)this)->stringCache = toString(data); - - - // determines the properties we need for layouting - TQTextEngine textEngine( toString(), 0 ); - textEngine.direction = (TQChar::Direction) dir; - textEngine.itemize(TQTextEngine::SingleLine); - const TQCharAttributes *ca = textEngine.attributes() + length-1; - TQTextStringChar *ch = (TQTextStringChar *)end - 1; - TQScriptItem *item = &textEngine.items[textEngine.items.size()-1]; - unsigned char bidiLevel = item->analysis.bidiLevel; - if ( bidiLevel ) - that->bidi = TRUE; - int pos = length-1; - while ( ch >= start ) { - if ( item->position > pos ) { - --item; - Q_ASSERT( item >= &textEngine.items[0] ); - Q_ASSERT( item < &textEngine.items[textEngine.items.size()] ); - bidiLevel = item->analysis.bidiLevel; - if ( bidiLevel ) - that->bidi = TRUE; - } - ch->softBreak = ca->softBreak; - ch->whiteSpace = ca->whiteSpace; - ch->charStop = ca->charStop; - ch->wordStop = ca->wordStop; - ch->bidiLevel = bidiLevel; - ch->rightToLeft = (bidiLevel%2); - --ch; - --ca; - --pos; - } - - if ( dir == TQChar::DirR ) { - that->bidi = TRUE; - that->rightToLeft = TRUE; - } else if ( dir == TQChar::DirL ) { - that->rightToLeft = FALSE; - } else { - that->rightToLeft = (textEngine.direction == TQChar::DirR); - } -} - -void TQTextDocument::setStyleSheet( TQStyleSheet *s ) -{ - if ( !s ) - return; - sheet_ = s; - list_tm = list_bm = par_tm = par_bm = 12; - list_lm = 40; - li_tm = li_bm = 0; - TQStyleSheetItem* item = s->item( "ol" ); - if ( item ) { - list_tm = TQMAX(0,item->margin( TQStyleSheetItem::MarginTop )); - list_bm = TQMAX(0,item->margin( TQStyleSheetItem::MarginBottom )); - list_lm = TQMAX(0,item->margin( TQStyleSheetItem::MarginLeft )); - } - if ( (item = s->item( "li" ) ) ) { - li_tm = TQMAX(0,item->margin( TQStyleSheetItem::MarginTop )); - li_bm = TQMAX(0,item->margin( TQStyleSheetItem::MarginBottom )); - } - if ( (item = s->item( "p" ) ) ) { - par_tm = TQMAX(0,item->margin( TQStyleSheetItem::MarginTop )); - par_bm = TQMAX(0,item->margin( TQStyleSheetItem::MarginBottom )); - } -} - -void TQTextDocument::setUnderlineLinks( bool b ) { - underlLinks = b; - for ( TQTextDocument *d = childList.first(); d; d = childList.next() ) - d->setUnderlineLinks( b ); -} - -void TQTextStringChar::setFormat( TQTextFormat *f ) -{ - if ( type == Regular ) { - d.format = f; - } else { -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( !d.custom ) { - d.custom = new CustomData; - d.custom->custom = 0; - } - d.custom->format = f; -#endif - } -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -void TQTextStringChar::setCustomItem( TQTextCustomItem *i ) -{ - if ( type == Regular ) { - TQTextFormat *f = format(); - d.custom = new CustomData; - d.custom->format = f; - } else { - delete d.custom->custom; - } - d.custom->custom = i; - type = (type == Anchor ? CustomAnchor : Custom); -} - -void TQTextStringChar::loseCustomItem() -{ - if ( type == Custom ) { - TQTextFormat *f = d.custom->format; - d.custom->custom = 0; - delete d.custom; - type = Regular; - d.format = f; - } else if ( type == CustomAnchor ) { - d.custom->custom = 0; - type = Anchor; - } -} - -#endif - -TQString TQTextStringChar::anchorName() const -{ - if ( type == Regular ) - return TQString::null; - else - return d.custom->anchorName; -} - -TQString TQTextStringChar::anchorHref() const -{ - if ( type == Regular ) - return TQString::null; - else - return d.custom->anchorHref; -} - -void TQTextStringChar::setAnchor( const TQString& name, const TQString& href ) -{ - if ( type == Regular ) { - TQTextFormat *f = format(); - d.custom = new CustomData; -#ifndef TQT_NO_TEXTCUSTOMITEM - d.custom->custom = 0; -#endif - d.custom->format = f; - type = Anchor; - } else if ( type == Custom ) { - type = CustomAnchor; - } - d.custom->anchorName = name; - d.custom->anchorHref = href; -} - - -int TQTextString::width( int idx ) const -{ - int w = 0; - TQTextStringChar *c = &at( idx ); - if ( !c->charStop || c->c.unicode() == 0xad || c->c.unicode() == 0x2028 ) - return 0; -#ifndef TQT_NO_TEXTCUSTOMITEM - if( c->isCustom() ) { - if( c->customItem()->placement() == TQTextCustomItem::PlaceInline ) - w = c->customItem()->width; - } else -#endif - { - int r = c->c.row(); - if(r < 0x06 -#ifndef TQ_WS_WIN - // Uniscribe's handling of Asian makes the condition below fail. - || (r > 0x1f && !(r > 0xd7 && r < 0xe0)) -#endif - ) { - w = c->format()->width( c->c ); - } else { - w = c->format()->width(toString(), idx); - } - } - return w; -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextParagraph::TQTextParagraph( TQTextDocument *d, TQTextParagraph *pr, TQTextParagraph *nx, bool updateIds ) - : p( pr ), n( nx ), docOrPseudo( d ), - changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE), - lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE), - mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE), - align( 0 ), lstyle( TQStyleSheetItem::ListDisc ), invalid( 0 ), mSelections( 0 ), -#ifndef TQT_NO_TEXTCUSTOMITEM - mFloatingItems( 0 ), -#endif - utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ), - tabStopWidth(0), minwidth(0), tArray(0), eData( 0 ), ldepth( 0 ) -{ - lstyle = TQStyleSheetItem::ListDisc; - if ( !hasdoc ) - docOrPseudo = new TQTextParagraphPseudoDocument; - bgcol = 0; - list_val = -1; - paintdevice = 0; - TQTextFormat* defFormat = formatCollection()->defaultFormat(); - if ( !hasdoc ) { - tabStopWidth = defFormat->width( 'x' ) * 8; - pseudoDocument()->commandHistory = new TQTextCommandHistory( 100 ); - } - - if ( p ) - p->n = this; - if ( n ) - n->p = this; - - if ( !p && hasdoc ) - document()->setFirstParagraph( this ); - if ( !n && hasdoc ) - document()->setLastParagraph( this ); - - state = -1; - - if ( p ) - id = p->id + 1; - else - id = 0; - if ( n && updateIds ) { - TQTextParagraph *s = n; - while ( s ) { - s->id = s->p->id + 1; - s->invalidateStyleCache(); - s = s->n; - } - } - - str = new TQTextString(); - TQChar ch(' '); - str->insert( 0, &ch, 1, formatCollection()->defaultFormat() ); -} - -TQTextParagraph::~TQTextParagraph() -{ - delete str; - if ( hasdoc ) { - TQTextDocument *doc = document(); - if ( this == doc->minwParag ) { - doc->minwParag = 0; - doc->minw = 0; - } - if ( this == doc->curParag ) - doc->curParag = 0; - } else { - delete pseudoDocument(); - } - delete [] tArray; - delete eData; - TQMap::Iterator it = lineStarts.begin(); - for ( ; it != lineStarts.end(); ++it ) - delete *it; - if ( mSelections ) - delete mSelections; -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( mFloatingItems ) - delete mFloatingItems; -#endif - if ( p ) - p->setNext( n ); - if ( n ) - n->setPrev( p ); - delete bgcol; -} - -void TQTextParagraph::setNext( TQTextParagraph *s ) -{ - n = s; - if ( !n && hasdoc ) - document()->setLastParagraph( this ); -} - -void TQTextParagraph::setPrev( TQTextParagraph *s ) -{ - p = s; - if ( !p && hasdoc ) - document()->setFirstParagraph( this ); -} - -void TQTextParagraph::invalidate( int chr ) -{ - if ( invalid < 0 ) - invalid = chr; - else - invalid = TQMIN( invalid, chr ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( mFloatingItems ) { - for ( TQTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) - i->ypos = -1; - } -#endif - invalidateStyleCache(); -} - -void TQTextParagraph::invalidateStyleCache() -{ - if ( list_val < 0 ) - list_val = -1; -} - - -void TQTextParagraph::insert( int index, const TQString &s ) -{ - insert( index, s.unicode(), s.length() ); -} - -void TQTextParagraph::insert( int index, const TQChar *unicode, int len ) -{ - if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() ) - str->insert( index, unicode, len, - document()->preProcessor()->format( TQTextPreProcessor::Standard ) ); - else - str->insert( index, unicode, len, formatCollection()->defaultFormat() ); - invalidate( index ); - needPreProcess = TRUE; -} - -void TQTextParagraph::truncate( int index ) -{ - str->truncate( index ); - insert( length(), " " ); - needPreProcess = TRUE; -} - -void TQTextParagraph::remove( int index, int len ) -{ - if ( index + len - str->length() > 0 ) - return; -#ifndef TQT_NO_TEXTCUSTOMITEM - for ( int i = index; i < index + len; ++i ) { - TQTextStringChar *c = at( i ); - if ( hasdoc && c->isCustom() ) { - document()->unregisterCustomItem( c->customItem(), this ); - } - } -#endif - str->remove( index, len ); - invalidate( 0 ); - needPreProcess = TRUE; -} - -void TQTextParagraph::join( TQTextParagraph *s ) -{ - int oh = r.height() + s->r.height(); - n = s->n; - if ( n ) - n->p = this; - else if ( hasdoc ) - document()->setLastParagraph( this ); - - int start = str->length(); - if ( length() > 0 && at( length() - 1 )->c == ' ' ) { - remove( length() - 1, 1 ); - --start; - } - append( s->str->toString(), TRUE ); - - for ( int i = 0; i < s->length(); ++i ) { - if ( !hasdoc || document()->useFormatCollection() ) { - s->str->at( i ).format()->addRef(); - str->setFormat( i + start, s->str->at( i ).format(), TRUE ); - } -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( s->str->at( i ).isCustom() ) { - TQTextCustomItem * item = s->str->at( i ).customItem(); - str->at( i + start ).setCustomItem( item ); - s->str->at( i ).loseCustomItem(); - if ( hasdoc ) { - document()->unregisterCustomItem( item, s ); - document()->registerCustomItem( item, this ); - } - } - if ( s->str->at( i ).isAnchor() ) { - str->at( i + start ).setAnchor( s->str->at( i ).anchorName(), - s->str->at( i ).anchorHref() ); - } -#endif - } - - if ( !extraData() && s->extraData() ) { - setExtraData( s->extraData() ); - s->setExtraData( 0 ); - } else if ( extraData() && s->extraData() ) { - extraData()->join( s->extraData() ); - } - delete s; - invalidate( 0 ); - r.setHeight( oh ); - needPreProcess = TRUE; - if ( n ) { - TQTextParagraph *s = n; - s->invalidate( 0 ); - while ( s ) { - s->id = s->p->id + 1; - s->state = -1; - s->needPreProcess = TRUE; - s->changed = TRUE; - s->invalidateStyleCache(); - s = s->n; - } - } - format(); - state = -1; -} - -void TQTextParagraph::move( int &dy ) -{ - if ( dy == 0 ) - return; - changed = TRUE; - r.moveBy( 0, dy ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( mFloatingItems ) { - for ( TQTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) - i->ypos += dy; - } -#endif - if ( p ) - p->lastInFrame = TRUE; - - // do page breaks if required - if ( hasdoc && document()->isPageBreakEnabled() ) { - int shift; - if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) { - if ( p ) - p->setChanged( TRUE ); - dy += shift; - } - } -} - -void TQTextParagraph::format( int start, bool doMove ) -{ - if ( !str || str->length() == 0 || !formatter() ) - return; - - if ( hasdoc && - document()->preProcessor() && - ( needPreProcess || state == -1 ) ) - document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid ); - needPreProcess = FALSE; - - if ( invalid == -1 ) - return; - - r.moveTopLeft( TQPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) ); - if ( p ) - p->lastInFrame = FALSE; - - movedDown = FALSE; - bool formattedAgain = FALSE; - - formatAgain: - - r.setWidth( documentWidth() ); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( hasdoc && mFloatingItems ) { - for ( TQTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) { - i->ypos = r.y(); - if ( i->placement() == TQTextCustomItem::PlaceRight ) { - i->xpos = r.x() + r.width() - i->width; - } - } - } -#endif - TQMap oldLineStarts = lineStarts; - lineStarts.clear(); - int y = formatter()->format( document(), this, start, oldLineStarts ); - - - r.setWidth( TQMAX( r.width(), formatter()->minimumWidth() ) ); - - - TQMap::Iterator it = oldLineStarts.begin(); - - for ( ; it != oldLineStarts.end(); ++it ) - delete *it; - - if ( !hasdoc ) { // qt_format_text bounding rect handling - it = lineStarts.begin(); - int usedw = 0; - for ( ; it != lineStarts.end(); ++it ) - usedw = TQMAX( usedw, (*it)->w ); - if ( r.width() <= 0 ) { - // if the user specifies an invalid rect, this means that the - // bounding box should grow to the width that the text actually - // needs - r.setWidth( usedw ); - } else { - r.setWidth( TQMIN( usedw, r.width() ) ); - } - } - - if ( y != r.height() ) - r.setHeight( y ); - - if ( !visible ) { - r.setHeight( 0 ); - } else { - int minw = minwidth = formatter()->minimumWidth(); - int wused = formatter()->widthUsed(); - wused = TQMAX( minw, wused ); - if ( hasdoc ) { - document()->setMinimumWidth( minw, wused, this ); - } else { - pseudoDocument()->minw = TQMAX( pseudoDocument()->minw, minw ); - pseudoDocument()->wused = TQMAX( pseudoDocument()->wused, wused ); - } - } - - // do page breaks if required - if ( hasdoc && document()->isPageBreakEnabled() ) { - int shift = document()->formatter()->formatVertically( document(), this ); - if ( shift && !formattedAgain ) { - formattedAgain = TRUE; - goto formatAgain; - } - } - - if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) { - int dy = ( r.y() + r.height() ) - n->r.y(); - TQTextParagraph *s = n; - bool makeInvalid = p && p->lastInFrame; - while ( s && dy ) { - if ( !s->isFullWidth() ) - makeInvalid = TRUE; - if ( makeInvalid ) - s->invalidate( 0 ); - s->move( dy ); - if ( s->lastInFrame ) - makeInvalid = TRUE; - s = s->n; - } - } - - firstFormat = FALSE; - changed = TRUE; - invalid = -1; - //##### string()->setTextChanged( FALSE ); -} - -int TQTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const -{ - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - TQMap::ConstIterator it = lineStarts.end(); - --it; - for ( ;; ) { - if ( i >= it.key() ) { - if ( bl ) - *bl = ( *it )->baseLine; - if ( y ) - *y = ( *it )->y; - return ( *it )->h; - } - if ( it == lineStarts.begin() ) - break; - --it; - } - - tqWarning( "TQTextParagraph::lineHeightOfChar: couldn't find lh for %d", i ); - return 15; -} - -TQTextStringChar *TQTextParagraph::lineStartOfChar( int i, int *index, int *line ) const -{ - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - int l = (int)lineStarts.count() - 1; - TQMap::ConstIterator it = lineStarts.end(); - --it; - for ( ;; ) { - if ( i >= it.key() ) { - if ( index ) - *index = it.key(); - if ( line ) - *line = l; - return &str->at( it.key() ); - } - if ( it == lineStarts.begin() ) - break; - --it; - --l; - } - - tqWarning( "TQTextParagraph::lineStartOfChar: couldn't find %d", i ); - return 0; -} - -int TQTextParagraph::lines() const -{ - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - return (int)lineStarts.count(); -} - -TQTextStringChar *TQTextParagraph::lineStartOfLine( int line, int *index ) const -{ - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - if ( line >= 0 && line < (int)lineStarts.count() ) { - TQMap::ConstIterator it = lineStarts.begin(); - while ( line-- > 0 ) - ++it; - int i = it.key(); - if ( index ) - *index = i; - return &str->at( i ); - } - - tqWarning( "TQTextParagraph::lineStartOfLine: couldn't find %d", line ); - return 0; -} - -int TQTextParagraph::leftGap() const -{ - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - if ( str->length() == 0) - return 0; - - int line = 0; - int x = str->length() ? str->at(0).x : 0; /* set x to x of first char */ - if ( str->isBidi() ) { - for ( int i = 1; i < str->length()-1; ++i ) - x = TQMIN(x, str->at(i).x); - return x; - } - - TQMap::ConstIterator it = lineStarts.begin(); - while (line < (int)lineStarts.count()) { - int i = it.key(); /* char index */ - x = TQMIN(x, str->at(i).x); - ++it; - ++line; - } - return x; -} - -void TQTextParagraph::setFormat( int index, int len, TQTextFormat *f, bool useCollection, int flags ) -{ - if ( !f ) - return; - if ( index < 0 ) - index = 0; - if ( index > str->length() - 1 ) - index = str->length() - 1; - if ( index + len >= str->length() ) - len = str->length() - index; - - TQTextFormatCollection *fc = 0; - if ( useCollection ) - fc = formatCollection(); - TQTextFormat *of; - for ( int i = 0; i < len; ++i ) { - of = str->at( i + index ).format(); - if ( !changed && ( !of || f->key() != of->key() ) ) - changed = TRUE; - if ( invalid == -1 && - ( f->font().family() != of->font().family() || - f->font().pointSize() != of->font().pointSize() || - f->font().weight() != of->font().weight() || - f->font().italic() != of->font().italic() || - f->vAlign() != of->vAlign() ) ) { - invalidate( 0 ); - } - if ( flags == -1 || flags == TQTextFormat::Format || !fc ) { - if ( fc ) - f = fc->format( f ); - str->setFormat( i + index, f, useCollection ); - } else { - TQTextFormat *fm = fc->format( of, f, flags ); - str->setFormat( i + index, fm, useCollection ); - } - } -} - -void TQTextParagraph::indent( int *oldIndent, int *newIndent ) -{ - if ( !hasdoc || !document()->indent() || isListItem() ) { - if ( oldIndent ) - *oldIndent = 0; - if ( newIndent ) - *newIndent = 0; - if ( oldIndent && newIndent ) - *newIndent = *oldIndent; - return; - } - document()->indent()->indent( document(), this, oldIndent, newIndent ); -} - -void TQTextParagraph::paint( TQPainter &painter, const TQColorGroup &cg, TQTextCursor *cursor, bool drawSelections, - int clipx, int clipy, int clipw, int cliph ) -{ - if ( !visible ) - return; - int i, y, h, baseLine, xstart, xend = 0; - i = y =h = baseLine = 0; - TQRect cursorRect; - drawSelections &= ( mSelections != 0 ); - // macintosh full-width selection style - bool fullWidthStyle = TQApplication::style().styleHint(TQStyle::SH_RichText_FullWidthSelection); - int fullSelectionWidth = 0; - if ( drawSelections && fullWidthStyle ) - fullSelectionWidth = (hasdoc ? document()->width() : r.width()); - - TQString qstr = str->toString(); - // detach string - qstr.setLength(qstr.length()); - // ### workaround so that \n are not drawn, actually this should - // be fixed in TQFont somewhere (under Windows you get ugly boxes - // otherwise) - TQChar* uc = (TQChar*) qstr.unicode(); - for ( uint ii = 0; ii < qstr.length(); ii++ ) - if ( uc[(int)ii]== '\n' || uc[(int)ii] == '\t' ) - uc[(int)ii] = 0x20; - - int line = -1; - int paintStart = 0; - TQTextStringChar *chr = 0; - TQTextStringChar *nextchr = at( 0 ); - for ( i = 0; i < length(); i++ ) { - chr = nextchr; - if ( i < length()-1 ) - nextchr = at( i+1 ); - - // we flush at end of document - bool flush = (i == length()-1); - bool ignoreSoftHyphen = FALSE; - if ( !flush ) { - // we flush at end of line - flush |= nextchr->lineStart; - // we flush on format changes - flush |= ( nextchr->format() != chr->format() ); - // we flush on link changes - flush |= ( nextchr->isLink() != chr->isLink() ); - // we flush on start of run - flush |= ( nextchr->bidiLevel != chr->bidiLevel ); - // we flush on bidi changes - flush |= ( nextchr->rightToLeft != chr->rightToLeft ); - // we flush before and after tabs - flush |= ( chr->c == '\t' || nextchr->c == '\t' ); - // we flush on soft hypens - if (chr->c.unicode() == 0xad) { - flush = TRUE; - if (!nextchr->lineStart) - ignoreSoftHyphen = TRUE; - } - // we flush on custom items - flush |= chr->isCustom(); - // we flush before custom items - flush |= nextchr->isCustom(); - // when painting justified, we flush on spaces - if ((alignment() & TQt::AlignJustify) == TQt::AlignJustify ) - flush |= chr->whiteSpace; - } - - // init a new line - if ( chr->lineStart ) { - ++line; - paintStart = i; - lineInfo( line, y, h, baseLine ); - if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave - break; - } - - // if this is the first line and we are a list item, draw the the bullet label - if ( line == 0 && isListItem() ) { - int x = chr->x; - if (str->isBidi()) { - if (str->isRightToLeft()) { - x = chr->x + str->width(0); - for (int k = 1; k < length(); ++k) { - if (str->at(k).lineStart) - break; - x = TQMAX(x, str->at(k).x + str->width(k)); - } - } else { - x = chr->x; - for (int k = 1; k < length(); ++k) { - if (str->at(k).lineStart) - break; - x = TQMIN(x, str->at(k).x); - } - } - } - drawLabel( &painter, x, y, 0, 0, baseLine, cg ); - } - } - - // check for cursor mark - if ( cursor && this == cursor->paragraph() && i == cursor->index() ) { - TQTextStringChar *c = i == 0 ? chr : chr - 1; - cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(), - 1, c->format()->height() ); - } - - if ( flush ) { // something changed, draw what we have so far - if ( chr->rightToLeft ) { - xstart = chr->x; - xend = at( paintStart )->x + str->width( paintStart ); - } else { - xstart = at( paintStart )->x; - xend = chr->x; - if ( i < length() - 1 ) { - if ( !str->at( i + 1 ).lineStart && - str->at( i + 1 ).rightToLeft == chr->rightToLeft ) - xend = str->at( i + 1 ).x; - else - xend += str->width( i ); - } - } - - if ( (clipx == -1 || clipw <= 0 || (xend >= clipx && xstart <= clipx + clipw)) && - ( clipy == -1 || clipy < y+r.y()+h ) ) { - if ( !chr->isCustom() ) - drawString( painter, qstr, paintStart, i - paintStart + (ignoreSoftHyphen ? 0 : 1), xstart, y, - baseLine, xend-xstart, h, drawSelections, fullSelectionWidth, - chr, cg, chr->rightToLeft ); -#ifndef TQT_NO_TEXTCUSTOMITEM - else if ( chr->customItem()->placement() == TQTextCustomItem::PlaceInline ) { - bool inSelection = FALSE; - if (drawSelections) { - TQMap::ConstIterator it = mSelections->find( TQTextDocument::Standard ); - inSelection = (it != mSelections->end() && (*it).start <= i && (*it).end > i); - } - chr->customItem()->draw( &painter, chr->x, y, - clipx == -1 ? clipx : (clipx - r.x()), - clipy == -1 ? clipy : (clipy - r.y()), - clipw, cliph, cg, inSelection ); - } -#endif - } - paintStart = i+1; - } - - } - - // time to draw the cursor - const int cursor_extent = 4; - if ( !cursorRect.isNull() && cursor && - ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) { - painter.fillRect( cursorRect, cg.color( TQColorGroup::Text ) ); - painter.save(); - if ( string()->isBidi() ) { - if ( at( cursor->index() )->rightToLeft ) { - painter.setPen( TQt::black ); - painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); - painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); - } else { - painter.setPen( TQt::black ); - painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); - painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); - } - } - painter.restore(); - } -} - -//#define BIDI_DEBUG - -void TQTextParagraph::setColorForSelection( TQColor &color, TQPainter &painter, - const TQColorGroup& cg, int selection ) -{ - if (selection < 0) - return; - color = ( hasdoc && selection != TQTextDocument::Standard ) ? - document()->selectionColor( selection ) : - cg.color( TQColorGroup::Highlight ); - if ( selection == TQTextDocument::IMCompositionText ) { -#ifndef TQ_WS_MACX - int h1, s1, v1, h2, s2, v2; - cg.color( TQColorGroup::Base ).hsv( &h1, &s1, &v1 ); - cg.color( TQColorGroup::Background ).hsv( &h2, &s2, &v2 ); - color.setHsv( h1, s1, ( v1 + v2 ) / 2 ); -#else - color = TQt::lightGray; -#endif - painter.setPen( cg.color( TQColorGroup::Text ) ); - } else if ( selection == TQTextDocument::IMSelectionText ) { - color = cg.color( TQColorGroup::Dark ); - painter.setPen( cg.color( TQColorGroup::BrightText ) ); - } else if ( !hasdoc || document()->invertSelectionText( selection ) ) { - painter.setPen( cg.color( TQColorGroup::HighlightedText ) ); - } -} - -void TQTextParagraph::drawString( TQPainter &painter, const TQString &str, int start, int len, int xstart, - int y, int baseLine, int w, int h, bool drawSelections, int fullSelectionWidth, - TQTextStringChar *formatChar, const TQColorGroup& cg, - bool rightToLeft ) -{ - bool plainText = hasdoc ? document()->textFormat() == TQt::PlainText : FALSE; - TQTextFormat* format = formatChar->format(); - - if ( !plainText || ( hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() ) ) - painter.setPen( TQPen( format->color() ) ); - else - painter.setPen( cg.text() ); - painter.setFont( format->font() ); - - if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) { - if ( format->useLinkColor() ) - painter.setPen(document()->linkColor.isValid() ? document()->linkColor : cg.link()); - if ( document()->underlineLinks() ) { - TQFont fn = format->font(); - fn.setUnderline( TRUE ); - painter.setFont( fn ); - } - } - - TQPainter::TextDirection dir = rightToLeft ? TQPainter::RTL : TQPainter::LTR; - - int real_length = len; - if (len && dir != TQPainter::RTL && start + len == length() ) // don't draw the last character (trailing space) - len--; - if (len && str.unicode()[start+len-1] == TQChar_linesep) - len--; - - - TQTextFormat::VerticalAlignment vAlign = format->vAlign(); - if ( vAlign != TQTextFormat::AlignNormal ) { - // sub or superscript - TQFont f( painter.font() ); - if ( format->fontSizesInPixels() ) - f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); - else - f.setPointSize( ( f.pointSize() * 2 ) / 3 ); - painter.setFont( f ); - int h = painter.fontMetrics().height(); - baseLine += (vAlign == TQTextFormat::AlignSubScript) ? h/6 : -h/2; - } - - bool allSelected = FALSE; - if (drawSelections) { - TQMap::ConstIterator it = mSelections->find( TQTextDocument::Standard ); - allSelected = (it != mSelections->end() && (*it).start <= start && (*it).end >= start+len); - } - if (!allSelected) - painter.drawText(xstart, y + baseLine, str, start, len, dir); - -#ifdef BIDI_DEBUG - painter.save(); - painter.setPen ( TQt::red ); - painter.drawLine( xstart, y, xstart, y + baseLine ); - painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 ); - int w = 0; - int i = 0; - while( i < len ) - w += painter.fontMetrics().charWidth( str, start + i++ ); - painter.setPen ( TQt::blue ); - painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine ); - painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 ); - painter.restore(); -#endif - - // check if we are in a selection and draw it - if (drawSelections) { - TQMap::ConstIterator it = mSelections->end(); - while ( it != mSelections->begin() ) { - --it; - int selStart = (*it).start; - int selEnd = (*it).end; - int tmpw = w; - - selStart = TQMAX(selStart, start); - int real_selEnd = TQMIN(selEnd, start+real_length); - selEnd = TQMIN(selEnd, start+len); - bool extendRight = FALSE; - bool extendLeft = FALSE; - bool selWrap = (real_selEnd == length()-1 && n && n->hasSelection(it.key())); - if (selWrap || this->str->at(real_selEnd).lineStart) { - extendRight = (fullSelectionWidth != 0); - if (!extendRight && !rightToLeft) - tmpw += painter.fontMetrics().width(' '); - } - if (fullSelectionWidth && (selStart == 0 || this->str->at(selStart).lineStart)) { - extendLeft = TRUE; - } - if (this->str->isRightToLeft() != rightToLeft) - extendLeft = extendRight = FALSE; - - if (this->str->isRightToLeft()) { - bool tmp = extendLeft; - extendLeft = extendRight; - extendRight = tmp; - } - - if (selStart < real_selEnd || - (selWrap && fullSelectionWidth && extendRight && - // don't draw the standard selection on a printer= - (it.key() != TQTextDocument::Standard || !is_printer( &painter)))) { - int selection = it.key(); - TQColor color; - setColorForSelection( color, painter, cg, selection ); - if (selStart != start || selEnd != start + len || selWrap) { - // have to clip - painter.save(); - int cs, ce; - if (rightToLeft) { - cs = (selEnd != start + len) ? - this->str->at(this->str->previousCursorPosition(selEnd)).x : xstart; - ce = (selStart != start) ? - this->str->at(this->str->previousCursorPosition(selStart)).x : xstart+tmpw; - } else { - cs = (selStart != start) ? this->str->at(selStart).x : xstart; - ce = (selEnd != start + len) ? this->str->at(selEnd).x : xstart+tmpw; - } - TQRect r(cs, y, ce-cs, h); - if (extendLeft) - r.setLeft(0); - if (extendRight) - r.setRight(fullSelectionWidth); - TQRegion reg(r); - if ( painter.hasClipping() ) - reg &= painter.clipRegion(TQPainter::CoordPainter); - painter.setClipRegion(reg, TQPainter::CoordPainter); - } - int xleft = xstart; - if ( extendLeft ) { - tmpw += xstart; - xleft = 0; - } - if ( extendRight ) - tmpw = fullSelectionWidth - xleft; - painter.fillRect( xleft, y, tmpw, h, color ); - painter.drawText( xstart, y + baseLine, str, start, len, dir ); - // draw preedit's underline - if (selection == TQTextDocument::IMCompositionText) - painter.drawLine(xstart, y + baseLine + 1, xstart + w, y + baseLine + 1); - if (selStart != start || selEnd != start + len || selWrap) - painter.restore(); - } - } - } - - if ( format->isMisspelled() ) { - painter.save(); - painter.setPen( TQPen( TQt::red, 1, TQt::DotLine ) ); - painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 ); - painter.restore(); - } - - if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() && - document()->focusIndicator.parag == this && - ( ( document()->focusIndicator.start >= start && - document()->focusIndicator.start + document()->focusIndicator.len <= start + len ) || - ( document()->focusIndicator.start <= start && - document()->focusIndicator.start + document()->focusIndicator.len >= start + len ) ) ) - painter.drawWinFocusRect( TQRect( xstart, y, w, h ) ); -} - -void TQTextParagraph::drawLabel( TQPainter* p, int x, int y, int w, int h, int base, const TQColorGroup& cg ) -{ - TQRect r ( x, y, w, h ); - TQStyleSheetItem::ListStyle s = listStyle(); - - p->save(); - TQTextFormat *format = at( 0 )->format(); - if ( format ) { - p->setPen( format->color() ); - p->setFont( format->font() ); - } - TQFontMetrics fm( p->fontMetrics() ); - int size = fm.lineSpacing() / 3; - - bool rtl = str->isRightToLeft(); - - switch ( s ) { - case TQStyleSheetItem::ListDecimal: - case TQStyleSheetItem::ListLowerAlpha: - case TQStyleSheetItem::ListUpperAlpha: - { - if ( list_val == -1 ) { // uninitialised list value, calcluate the right one - int depth = listDepth(); - list_val--; - // ### evil, square and expensive. This needs to be done when formatting, not when painting - TQTextParagraph* s = prev(); - int depth_s; - while ( s && (depth_s = s->listDepth()) >= depth ) { - if ( depth_s == depth && s->isListItem() ) - list_val--; - s = s->prev(); - } - } - - int n = list_val; - if ( n < -1 ) - n = -n - 1; - TQString l; - switch ( s ) { - case TQStyleSheetItem::ListLowerAlpha: - if ( n < 27 ) { - l = TQChar( ('a' + (char) (n-1))); - break; - } - case TQStyleSheetItem::ListUpperAlpha: - if ( n < 27 ) { - l = TQChar( ('A' + (char) (n-1))); - break; - } - break; - default: //TQStyleSheetItem::ListDecimal: - l.setNum( n ); - break; - } - if (rtl) - l.prepend(" ."); - else - l += TQString::fromLatin1(". "); - int x = ( rtl ? r.left() : r.right() - fm.width(l)); - p->drawText( x, r.top() + base, l ); - } - break; - case TQStyleSheetItem::ListSquare: - { - int x = rtl ? r.left() + size : r.right() - size*2; - TQRect er( x, r.top() + fm.height() / 2 - size / 2, size, size ); - p->fillRect( er , cg.brush( TQColorGroup::Text ) ); - } - break; - case TQStyleSheetItem::ListCircle: - { - int x = rtl ? r.left() + size : r.right() - size*2; - TQRect er( x, r.top() + fm.height() / 2 - size / 2, size, size); - p->drawEllipse( er ); - } - break; - case TQStyleSheetItem::ListDisc: - default: - { - p->setBrush( cg.brush( TQColorGroup::Text )); - int x = rtl ? r.left() + size : r.right() - size*2; - TQRect er( x, r.top() + fm.height() / 2 - size / 2, size, size); - p->drawEllipse( er ); - p->setBrush( TQt::NoBrush ); - } - break; - } - - p->restore(); -} - -#ifndef TQT_NO_DATASTREAM -void TQTextParagraph::readStyleInformation( TQDataStream& stream ) -{ - int int_align, int_lstyle; - uchar uchar_litem, uchar_rtext, uchar_dir; - stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm - >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir; - align = int_align; lstyle = (TQStyleSheetItem::ListStyle) int_lstyle; - litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (TQChar::Direction)uchar_dir ); - TQTextParagraph* s = prev() ? prev() : this; - while ( s ) { - s->invalidate( 0 ); - s = s->next(); - } -} - -void TQTextParagraph::writeStyleInformation( TQDataStream& stream ) const -{ - stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction(); -} -#endif - - -void TQTextParagraph::setListItem( bool li ) -{ - if ( (bool)litem == li ) - return; - litem = li; - changed = TRUE; - TQTextParagraph* s = prev() ? prev() : this; - while ( s ) { - s->invalidate( 0 ); - s = s->next(); - } -} - -void TQTextParagraph::setListDepth( int depth ) { - if ( !hasdoc || depth == ldepth ) - return; - ldepth = depth; - TQTextParagraph* s = prev() ? prev() : this; - while ( s ) { - s->invalidate( 0 ); - s = s->next(); - } -} - -int *TQTextParagraph::tabArray() const -{ - int *ta = tArray; - if ( !ta && hasdoc ) - ta = document()->tabArray(); - return ta; -} - -int TQTextParagraph::nextTab( int, int x ) -{ - int *ta = tArray; - if ( hasdoc ) { - if ( !ta ) - ta = document()->tabArray(); - tabStopWidth = document()->tabStopWidth(); - } - if ( ta ) { - int i = 0; - while ( ta[ i ] ) { - if ( ta[ i ] >= x ) - return tArray[ i ]; - ++i; - } - return tArray[ 0 ]; - } else { - int d; - if ( tabStopWidth != 0 ) - d = x / tabStopWidth; - else - return x; - return tabStopWidth * ( d + 1 ); - } -} - -void TQTextParagraph::adjustToPainter( TQPainter *p ) -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - for ( int i = 0; i < length(); ++i ) { - if ( at( i )->isCustom() ) - at( i )->customItem()->adjustToPainter( p ); - } -#endif -} - -TQTextFormatCollection *TQTextParagraph::formatCollection() const -{ - if ( hasdoc ) - return document()->formatCollection(); - TQTextFormatCollection* fc = &pseudoDocument()->collection; - if ( paintdevice != fc->paintDevice() ) - fc->setPaintDevice( paintdevice ); - return fc; -} - -TQString TQTextParagraph::richText() const -{ - TQString s; - TQTextStringChar *formatChar = 0; - TQString spaces; - bool doStart = richTextExportStart && richTextExportStart->paragraph() == this; - bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this; - int i; - TQString lastAnchorName; - for ( i = 0; i < length()-1; ++i ) { - if ( doStart && i && richTextExportStart->index() == i ) - s += ""; - if ( doEnd && richTextExportEnd->index() == i ) - s += ""; - TQTextStringChar *c = &str->at( i ); - if ( c->isAnchor() && !c->anchorName().isEmpty() && c->anchorName() != lastAnchorName ) { - lastAnchorName = c->anchorName(); - if ( c->anchorName().contains( '#' ) ) { - TQStringList l = TQStringList::split( '#', c->anchorName() ); - for ( TQStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) - s += ""; - } else { - s += "anchorName() + "\">"; - } - } - if ( !formatChar ) { - s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), - 0, TQString::null, c->anchorHref() ); - formatChar = c; - } else if ( ( formatChar->format()->key() != c->format()->key() ) || - (c->anchorHref() != formatChar->anchorHref() ) ) { - s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), - formatChar->format() , formatChar->anchorHref(), c->anchorHref() ); - formatChar = c; - } - if ( c->c == '<' ) - s += "<"; - else if ( c->c == '>' ) - s += ">"; - else if ( c->c =='&' ) - s += "&"; - else if ( c->c =='\"' ) - s += """; -#ifndef TQT_NO_TEXTCUSTOMITEM - else if ( c->isCustom() ) - s += c->customItem()->richText(); -#endif - else if ( c->c == '\n' || c->c == TQChar_linesep ) - s += "
"; // space on purpose for compatibility with Netscape, Lynx & Co. - else - s += c->c; - } - if ( doEnd && richTextExportEnd->index() == i ) - s += ""; - if ( formatChar ) - s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() ); - return s; -} - -void TQTextParagraph::addCommand( TQTextCommand *cmd ) -{ - if ( !hasdoc ) - pseudoDocument()->commandHistory->addCommand( cmd ); - else - document()->commands()->addCommand( cmd ); -} - -TQTextCursor *TQTextParagraph::undo( TQTextCursor *c ) -{ - if ( !hasdoc ) - return pseudoDocument()->commandHistory->undo( c ); - return document()->commands()->undo( c ); -} - -TQTextCursor *TQTextParagraph::redo( TQTextCursor *c ) -{ - if ( !hasdoc ) - return pseudoDocument()->commandHistory->redo( c ); - return document()->commands()->redo( c ); -} - -int TQTextParagraph::topMargin() const -{ - int m = 0; - if ( rtext ) { - m = isListItem() ? (document()->li_tm/TQMAX(1,listDepth()*listDepth())) : - ( listDepth() ? 0 : document()->par_tm ); - if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) ) - m = TQMAX( m, document()->list_tm ); - } - m += utm; - return scale( m, TQTextFormat::painter() ); -} - -int TQTextParagraph::bottomMargin() const -{ - int m = 0; - if ( rtext ) { - m = isListItem() ? (document()->li_bm/TQMAX(1,listDepth()*listDepth())) : - ( listDepth() ? 0 : document()->par_bm ); - if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) ) - m = TQMAX( m, document()->list_bm ); - } - m += ubm; - return scale( m, TQTextFormat::painter() ); -} - -int TQTextParagraph::leftMargin() const -{ - int m = ulm; - if ( listDepth() && !string()->isRightToLeft() ) - m += listDepth() * document()->list_lm; - return scale( m, TQTextFormat::painter() ); -} - -int TQTextParagraph::firstLineMargin() const -{ - int m = uflm; - return scale( m, TQTextFormat::painter() ); -} - -int TQTextParagraph::rightMargin() const -{ - int m = urm; - if ( listDepth() && string()->isRightToLeft() ) - m += listDepth() * document()->list_lm; - return scale( m, TQTextFormat::painter() ); -} - -int TQTextParagraph::lineSpacing() const -{ - int l = ulinespacing; - l = scale( l, TQTextFormat::painter() ); - return l; -} - -void TQTextParagraph::copyParagData( TQTextParagraph *parag ) -{ - rtext = parag->rtext; - lstyle = parag->lstyle; - ldepth = parag->ldepth; - litem = parag->litem; - align = parag->align; - utm = parag->utm; - ubm = parag->ubm; - urm = parag->urm; - ulm = parag->ulm; - uflm = parag->uflm; - ulinespacing = parag->ulinespacing; - TQColor *c = parag->backgroundColor(); - if ( c ) - setBackgroundColor( *c ); - str->setDirection( parag->str->direction() ); -} - -void TQTextParagraph::show() -{ - if ( visible || !hasdoc ) - return; - visible = TRUE; -} - -void TQTextParagraph::hide() -{ - if ( !visible || !hasdoc ) - return; - visible = FALSE; -} - -void TQTextParagraph::setDirection( TQChar::Direction d ) -{ - if ( str && str->direction() != d ) { - str->setDirection( d ); - invalidate( 0 ); - } -} - -TQChar::Direction TQTextParagraph::direction() const -{ - return (str ? str->direction() : TQChar::DirON ); -} - -void TQTextParagraph::setChanged( bool b, bool recursive ) -{ - changed = b; - if ( recursive ) { - if ( document() && document()->parentParagraph() ) - document()->parentParagraph()->setChanged( b, recursive ); - } -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - -TQTextPreProcessor::TQTextPreProcessor() -{ -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextFormatter::TQTextFormatter() - : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE ) -{ -} - -TQTextLineStart *TQTextFormatter::formatLine( TQTextParagraph *parag, TQTextString *string, TQTextLineStart *line, - TQTextStringChar *startChar, TQTextStringChar *lastChar, int align, int space ) -{ - if ( lastChar < startChar ) - return new TQTextLineStart; -#ifndef TQT_NO_COMPLEXTEXT - if( string->isBidi() ) - return bidiReorderLine( parag, string, line, startChar, lastChar, align, space ); -#endif - int start = (startChar - &string->at(0)); - int last = (lastChar - &string->at(0) ); - - // ignore white space at the end of the line. - TQTextStringChar *ch = lastChar; - while ( ch > startChar && ch->whiteSpace ) { - space += ch->format()->width( ' ' ); - --ch; - } - - if (space < 0) - space = 0; - - // do alignment Auto == Left in this case - if ( align & TQt::AlignHCenter || align & TQt::AlignRight ) { - if ( align & TQt::AlignHCenter ) - space /= 2; - for ( int j = start; j <= last; ++j ) - string->at( j ).x += space; - } else if ( align & TQt::AlignJustify ) { - int numSpaces = 0; - // End at "last-1", the last space ends up with a width of 0 - for ( int j = last-1; j >= start; --j ) { - // Start at last tab, if any. - TQTextStringChar &ch = string->at( j ); - if ( ch.c == '\t' ) { - start = j+1; - break; - } - if(ch.whiteSpace) - numSpaces++; - } - int toAdd = 0; - for ( int k = start + 1; k <= last; ++k ) { - TQTextStringChar &ch = string->at( k ); - if( numSpaces && ch.whiteSpace ) { - int s = space / numSpaces; - toAdd += s; - space -= s; - numSpaces--; - } - string->at( k ).x += toAdd; - } - } - - if ( last >= 0 && last < string->length() ) - line->w = string->at( last ).x + string->width( last ); - else - line->w = 0; - - return new TQTextLineStart; -} - -#ifndef TQT_NO_COMPLEXTEXT - -#ifdef BIDI_DEBUG -#include -#endif - -// collects one line of the paragraph and transforms it to visual order -TQTextLineStart *TQTextFormatter::bidiReorderLine( TQTextParagraph * /*parag*/, TQTextString *text, TQTextLineStart *line, - TQTextStringChar *startChar, TQTextStringChar *lastChar, int align, int space ) -{ - // ignore white space at the end of the line. - int endSpaces = 0; - while ( lastChar > startChar && lastChar->whiteSpace ) { - space += lastChar->format()->width( ' ' ); - --lastChar; - ++endSpaces; - } - - int start = (startChar - &text->at(0)); - int last = (lastChar - &text->at(0) ); - - int length = lastChar - startChar + 1; - - - int x = startChar->x; - - unsigned char _levels[256]; - int _visual[256]; - - unsigned char *levels = _levels; - int *visual = _visual; - - if ( length > 255 ) { - levels = (unsigned char *)malloc( length*sizeof( unsigned char ) ); - visual = (int *)malloc( length*sizeof( int ) ); - } - - //tqDebug("bidiReorderLine: length=%d (%d-%d)", length, start, last ); - - TQTextStringChar *ch = startChar; - unsigned char *l = levels; - while ( ch <= lastChar ) { - //tqDebug( " level: %d", ch->bidiLevel ); - *(l++) = (ch++)->bidiLevel; - } - - TQTextEngine::bidiReorder( length, levels, visual ); - - // now construct the reordered string out of the runs... - - int numSpaces = 0; - // set the correct alignment. This is a bit messy.... - if( align == TQt::AlignAuto ) { - // align according to directionality of the paragraph... - if ( text->isRightToLeft() ) - align = TQt::AlignRight; - } - - // This is not really correct, but as we can't make the scrollbar move to the left of the origin, - // this ensures all text can be scrolled to and read. - if (space < 0) - space = 0; - - if ( align & TQt::AlignHCenter ) - x += space/2; - else if ( align & TQt::AlignRight ) - x += space; - else if ( align & TQt::AlignJustify ) { - // End at "last-1", the last space ends up with a width of 0 - for ( int j = last-1; j >= start; --j ) { - // Start at last tab, if any. - TQTextStringChar &ch = text->at( j ); - if ( ch.c == '\t' ) { - start = j+1; - break; - } - if(ch.whiteSpace) - numSpaces++; - } - } - - int toAdd = 0; - int xorig = x; - TQTextStringChar *lc = startChar + visual[0]; - for ( int i = 0; i < length; i++ ) { - TQTextStringChar *ch = startChar + visual[i]; - if (numSpaces && ch->whiteSpace) { - int s = space / numSpaces; - toAdd += s; - space -= s; - numSpaces--; - } - - if (lc->format() != ch->format() && !ch->c.isSpace() - && lc->format()->font().italic() && !ch->format()->font().italic()) { - int rb = lc->format()->fontMetrics().rightBearing(lc->c); - if (rb < 0) - x -= rb; - } - - ch->x = x + toAdd; - ch->rightToLeft = ch->bidiLevel % 2; - //tqDebug("visual: %d (%x) placed at %d rightToLeft=%d", visual[i], ch->c.unicode(), x +toAdd, ch->rightToLeft ); - int ww = 0; - if ( ch->c.unicode() >= 32 || ch->c == '\t' || ch->c == '\n' || ch->isCustom() ) { - ww = text->width( start+visual[i] ); - } else { - ww = ch->format()->width( ' ' ); - } - x += ww; - lc = ch; - } - x += toAdd; - - while ( endSpaces-- ) { - ++lastChar; - int sw = lastChar->format()->width( ' ' ); - if ( text->isRightToLeft() ) { - xorig -= sw; - lastChar->x = xorig; - ch->rightToLeft = TRUE; - } else { - lastChar->x = x; - x += sw; - ch->rightToLeft = FALSE; - } - } - - line->w = x; - - if ( length > 255 ) { - free( levels ); - free( visual ); - } - - return new TQTextLineStart; -} -#endif - - -void TQTextFormatter::insertLineStart( TQTextParagraph *parag, int index, TQTextLineStart *ls ) -{ - TQMap::Iterator it; - if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) { - parag->lineStartList().insert( index, ls ); - } else { - delete *it; - parag->lineStartList().remove( it ); - parag->lineStartList().insert( index, ls ); - } -} - - -/* Standard pagebreak algorithm using TQTextFlow::adjustFlow. Returns - the shift of the paragraphs bottom line. - */ -int TQTextFormatter::formatVertically( TQTextDocument* doc, TQTextParagraph* parag ) -{ - int oldHeight = parag->rect().height(); - TQMap& lineStarts = parag->lineStartList(); - TQMap::Iterator it = lineStarts.begin(); - int h = parag->prev() ? TQMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0; - for ( ; it != lineStarts.end() ; ++it ) { - TQTextLineStart * ls = it.data(); - ls->y = h; - TQTextStringChar *c = ¶g->string()->at(it.key()); -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( c && c->customItem() && c->customItem()->ownLine() ) { - int h = c->customItem()->height; - c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() ); - int delta = c->customItem()->height - h; - ls->h += delta; - if ( delta ) - parag->setMovedDown( TRUE ); - } else -#endif - { - - int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h ); - ls->y += shift; - if ( shift ) - parag->setMovedDown( TRUE ); - } - h = ls->y + ls->h; - } - int m = parag->bottomMargin(); - if ( !parag->next() ) - m = 0; - else - m = TQMAX(m, parag->next()->topMargin() ) / 2; - h += m; - parag->setHeight( h ); - return h - oldHeight; -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextFormatterBreakInWords::TQTextFormatterBreakInWords() -{ -} - -#define SPACE(s) s - -int TQTextFormatterBreakInWords::format( TQTextDocument *doc,TQTextParagraph *parag, - int start, const TQMap & ) -{ - // make sure bidi information is correct. - (void )parag->string()->isBidi(); - - TQTextStringChar *c = 0; - TQTextStringChar *firstChar = 0; - int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; - int x = left + ( doc ? parag->firstLineMargin() : 0 ); - int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); - int y = parag->prev() ? TQMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; - int h = y; - int len = parag->length(); - if ( doc ) - x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 ); - int rm = parag->rightMargin(); - int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - bool fullWidth = TRUE; - int minw = 0; - int wused = 0; - bool wrapEnabled = isWrapEnabled( parag ); - - start = 0; //######### what is the point with start?! (Matthias) - if ( start == 0 ) - c = ¶g->string()->at( 0 ); - - int i = start; - TQTextLineStart *lineStart = new TQTextLineStart( y, y, 0 ); - insertLineStart( parag, 0, lineStart ); - - TQPainter *painter = TQTextFormat::painter(); - - int col = 0; - int ww = 0; - TQChar lastChr; - for ( ; i < len; ++i, ++col ) { - if ( c ) - lastChr = c->c; - c = ¶g->string()->at( i ); - // ### the lines below should not be needed - if ( painter ) - c->format()->setPainter( painter ); - if ( i > 0 ) { - c->lineStart = 0; - } else { - c->lineStart = 1; - firstChar = c; - } - if ( c->c.unicode() >= 32 || c->isCustom() ) { - ww = parag->string()->width( i ); - } else if ( c->c == '\t' ) { - int nx = parag->nextTab( i, x - left ) + left; - if ( nx < x ) - ww = w - x; - else - ww = nx - x; - } else { - ww = c->format()->width( ' ' ); - } - -#ifndef TQT_NO_TEXTCUSTOMITEM - if ( c->isCustom() && c->customItem()->ownLine() ) { - x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; - w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - c->customItem()->resize( w - x ); - w = dw; - y += h; - h = c->height(); - lineStart = new TQTextLineStart( y, h, h ); - insertLineStart( parag, i, lineStart ); - c->lineStart = 1; - firstChar = c; - x = 0xffffff; - continue; - } -#endif - - if ( wrapEnabled && - ( ( wrapAtColumn() == -1 && x + ww > w ) || - ( wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) ) { - x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; - w = dw; - y += h; - h = c->height(); - lineStart = formatLine( parag, parag->string(), lineStart, firstChar, c-1 ); - lineStart->y = y; - insertLineStart( parag, i, lineStart ); - lineStart->baseLine = c->ascent(); - lineStart->h = c->height(); - c->lineStart = 1; - firstChar = c; - col = 0; - if ( wrapAtColumn() != -1 ) - minw = TQMAX( minw, w ); - } else if ( lineStart ) { - lineStart->baseLine = TQMAX( lineStart->baseLine, c->ascent() ); - h = TQMAX( h, c->height() ); - lineStart->h = h; - } - - c->x = x; - x += ww; - wused = TQMAX( wused, x ); - } - - int m = parag->bottomMargin(); - if ( !parag->next() ) - m = 0; - else - m = TQMAX(m, parag->next()->topMargin() ) / 2; - parag->setFullWidth( fullWidth ); - y += h + m; - if ( doc ) - minw += doc->rightMargin(); - if ( !wrapEnabled ) - minw = TQMAX(minw, wused); - - thisminw = minw; - thiswused = wused; - return y; -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextFormatterBreakWords::TQTextFormatterBreakWords() -{ -} - -#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \ - int yflow = lineStart->y + parag->rect().y();\ - int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \ - lineStart->y += shift;\ - y += shift;\ - }}while(FALSE) - -int TQTextFormatterBreakWords::format( TQTextDocument *doc, TQTextParagraph *parag, - int start, const TQMap & ) -{ - // make sure bidi information is correct. - (void )parag->string()->isBidi(); - - TQTextStringChar *c = 0; - TQTextStringChar *firstChar = 0; - TQTextString *string = parag->string(); - int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; - int x = left + ( doc ? parag->firstLineMargin() : 0 ); - int y = parag->prev() ? TQMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; - int h = y; - int len = parag->length(); - if ( doc ) - x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 ); - int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 ); - - int curLeft = x; - int rm = parag->rightMargin(); - int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0; - int w = dw - rdiff; - bool fullWidth = TRUE; - int marg = left + rdiff; - int minw = 0; - int wused = 0; - int tminw = marg; - int linespacing = doc ? parag->lineSpacing() : 0; - bool wrapEnabled = isWrapEnabled( parag ); - - start = 0; - - int i = start; - TQTextLineStart *lineStart = new TQTextLineStart( y, y, 0 ); - insertLineStart( parag, 0, lineStart ); - int lastBreak = -1; - int tmpBaseLine = 0, tmph = 0; - bool lastWasNonInlineCustom = FALSE; - - int align = parag->alignment(); - if ( align == TQt::AlignAuto && doc && doc->alignment() != TQt::AlignAuto ) - align = doc->alignment(); - - align &= TQt::AlignHorizontal_Mask; - - // ### hack. The last char in the paragraph is always invisible, - // ### and somehow sometimes has a wrong format. It changes - // ### between // layouting and printing. This corrects some - // ### layouting errors in BiDi mode due to this. - if ( len > 1 ) { - c = ¶g->string()->at(len - 1); - if (!c->isAnchor()) { - if (c->format()) - c->format()->removeRef(); - c->setFormat( string->at( len - 2 ).format() ); - if (c->format()) - c->format()->addRef(); - } - } - - c = ¶g->string()->at( 0 ); - - TQPainter *painter = TQTextFormat::painter(); - int col = 0; - int ww = 0; - TQChar lastChr = c->c; - TQTextFormat *lastFormat = c->format(); - for ( ; i < len; ++i, ++col ) { - if ( i ) { - c = ¶g->string()->at(i-1); - lastChr = c->c; - lastFormat = c->format(); - } - bool lastWasOwnLineCustomItem = lastBreak == -2; - bool hadBreakableChar = lastBreak != -1; - bool lastWasHardBreak = lastChr == TQChar_linesep; - - // ### next line should not be needed - if ( painter ) - c->format()->setPainter( painter ); - c = &string->at( i ); - - if (lastFormat != c->format() && !c->c.isSpace() - && lastFormat->font().italic() && !c->format()->font().italic()) { - int rb = lastFormat->fontMetrics().rightBearing(lastChr); - if (rb < 0) - x -= rb; - } - - if ( ( i > 0 && (x > curLeft || ww == 0) ) || lastWasNonInlineCustom ) { - c->lineStart = 0; - } else { - c->lineStart = 1; - firstChar = c; - } - - // ignore non spacing marks for column count. - if (col != 0 && ::category(c->c) == TQChar::Mark_NonSpacing) - --col; - -#ifndef TQT_NO_TEXTCUSTOMITEM - lastWasNonInlineCustom = ( c->isCustom() && c->customItem()->placement() != TQTextCustomItem::PlaceInline ); -#endif - - if ( c->c.unicode() >= 32 || c->isCustom() ) { - ww = string->width( i ); - } else if ( c->c == '\t' ) { - if ( align == TQt::AlignRight || align == TQt::AlignCenter ) { - // we can not (yet) do tabs - ww = c->format()->width(' ' ); - } else { - int tabx = lastWasHardBreak ? (left + ( doc ? parag->firstLineMargin() : 0 )) : x; - int nx = parag->nextTab( i, tabx - left ) + left; - if ( nx < tabx ) // strrrange... - ww = 0; - else - ww = nx - tabx; - } - } else { - ww = c->format()->width( ' ' ); - } - -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextCustomItem* ci = c->customItem(); - if ( c->isCustom() && ci->ownLine() ) { - TQTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x - ww) ); - x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; - w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - ci->resize(w - x); - if ( ci->width < w - x ) { - if ( align & TQt::AlignHCenter ) - x = ( w - ci->width ) / 2; - else if ( align & TQt::AlignRight ) { - x = w - ci->width; - } - } - c->x = x; - curLeft = x; - if ( i == 0 || !isBreakable(string, i-1) || - string->at( i - 1 ).lineStart == 0 ) { - y += TQMAX( h, TQMAX( tmph, linespacing ) ); - tmph = c->height(); - h = tmph; - lineStart = lineStart2; - lineStart->y = y; - insertLineStart( parag, i, lineStart ); - c->lineStart = 1; - firstChar = c; - } else { - tmph = c->height(); - h = tmph; - delete lineStart2; - } - lineStart->h = h; - lineStart->baseLine = h; - tmpBaseLine = lineStart->baseLine; - lastBreak = -2; - x = w; - minw = TQMAX( minw, tminw ); - - int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 ); - if ( tw < TQWIDGETSIZE_MAX ) - tminw = tw; - else - tminw = marg; - wused = TQMAX( wused, ci->width ); - continue; - } else if ( c->isCustom() && ci->placement() != TQTextCustomItem::PlaceInline ) { - int tw = ci->minimumWidth(); - if ( tw < TQWIDGETSIZE_MAX ) - minw = TQMAX( minw, tw ); - } -#endif - // we break if - // 1. the last character was a hard break (TQChar_linesep) or - // 2. the last charater was a own-line custom item (eg. table or ruler) or - // 3. wrapping was enabled, it was not a space and following - // condition is true: We either had a breakable character - // previously or we ar allowed to break in words and - either - // we break at w pixels and the current char would exceed that - // or - we break at a column and the current character would - // exceed that. - if ( lastWasHardBreak || lastWasOwnLineCustomItem || - ( wrapEnabled && - ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) && - ( (wrapAtColumn() == -1 && x + ww > w) || - (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) ) - ) - ) { - if ( wrapAtColumn() != -1 ) - minw = TQMAX( minw, x + ww ); - // if a break was forced (no breakable char, hard break or own line custom item), break immediately.... - if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) { - if ( lineStart ) { - lineStart->baseLine = TQMAX( lineStart->baseLine, tmpBaseLine ); - h = TQMAX( h, tmph ); - lineStart->h = h; - DO_FLOW( lineStart ); - } - lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); - x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; - w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - if ( !doc && c->c == '\t' ) { // qt_format_text tab handling - int nx = parag->nextTab( i, x - left ) + left; - if ( nx < x ) - ww = w - x; - else - ww = nx - x; - } - curLeft = x; - y += TQMAX( h, linespacing ); - tmph = c->height(); - h = 0; - lineStart->y = y; - insertLineStart( parag, i, lineStart ); - lineStart->baseLine = c->ascent(); - lineStart->h = c->height(); - c->lineStart = 1; - firstChar = c; - tmpBaseLine = lineStart->baseLine; - lastBreak = -1; - col = 0; - if ( allowBreakInWords() || lastWasHardBreak ) { - minw = TQMAX(minw, tminw); - tminw = marg + ww; - } - } else { // ... otherwise if we had a breakable char, break there - DO_FLOW( lineStart ); - c->x = x; - i = lastBreak; - lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i+1 ).x) ); - x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; - w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - if ( !doc && c->c == '\t' ) { // qt_format_text tab handling - int nx = parag->nextTab( i, x - left ) + left; - if ( nx < x ) - ww = w - x; - else - ww = nx - x; - } - curLeft = x; - y += TQMAX( h, linespacing ); - tmph = c->height(); - h = tmph; - lineStart->y = y; - insertLineStart( parag, i + 1, lineStart ); - lineStart->baseLine = c->ascent(); - lineStart->h = c->height(); - c->lineStart = 1; - firstChar = c; - tmpBaseLine = lineStart->baseLine; - lastBreak = -1; - col = 0; - minw = TQMAX(minw, tminw); - tminw = marg; - continue; - } - } else if (lineStart && isBreakable(string, i)) { - if ( len <= 2 || i < len - 1 ) { - tmpBaseLine = TQMAX( tmpBaseLine, c->ascent() ); - tmph = TQMAX( tmph, c->height() ); - } - minw = TQMAX( minw, tminw ); - - tminw = marg + ww; - lineStart->baseLine = TQMAX( lineStart->baseLine, tmpBaseLine ); - h = TQMAX( h, tmph ); - lineStart->h = h; - if ( i < len - 2 || c->c != ' ' ) - lastBreak = i; - } else { - tminw += ww; - int cascent = c->ascent(); - int cheight = c->height(); - int belowBaseLine = TQMAX( tmph - tmpBaseLine, cheight-cascent ); - tmpBaseLine = TQMAX( tmpBaseLine, cascent ); - tmph = tmpBaseLine + belowBaseLine; - } - - c->x = x; - x += ww; - wused = TQMAX( wused, x ); - } - - if ( lineStart ) { - lineStart->baseLine = TQMAX( lineStart->baseLine, tmpBaseLine ); - h = TQMAX( h, tmph ); - lineStart->h = h; - // last line in a paragraph is not justified - if ( align == TQt::AlignJustify ) - align = TQt::AlignAuto; - DO_FLOW( lineStart ); - lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) ); - delete lineStart; - } - - minw = TQMAX( minw, tminw ); - if ( doc ) - minw += doc->rightMargin(); - - int m = parag->bottomMargin(); - if ( !parag->next() ) - m = 0; - else - m = TQMAX(m, parag->next()->topMargin() ) / 2; - parag->setFullWidth( fullWidth ); - y += TQMAX( h, linespacing ) + m; - - wused += rm; - if ( !wrapEnabled || wrapAtColumn() != -1 ) - minw = TQMAX(minw, wused); - - // This is the case where we are breaking wherever we darn well please - // in cases like that, the minw should not be the length of the entire - // word, because we necessarily want to show the word on the whole line. - // example: word wrap in iconview - if ( allowBreakInWords() && minw > wused ) - minw = wused; - - thisminw = minw; - thiswused = wused; - return y; -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextIndent::TQTextIndent() -{ -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -TQTextFormatCollection::TQTextFormatCollection() - : cKey( 307 ), paintdevice( 0 ) -{ - defFormat = new TQTextFormat( TQApplication::font(), - TQApplication::palette().color( TQPalette::Active, TQColorGroup::Text ) ); - lastFormat = cres = 0; - cflags = -1; - cKey.setAutoDelete( TRUE ); - cachedFormat = 0; -} - -TQTextFormatCollection::~TQTextFormatCollection() -{ - delete defFormat; -} - -void TQTextFormatCollection::setPaintDevice( TQPaintDevice *pd ) -{ - paintdevice = pd; - -#if defined(TQ_WS_X11) - int scr = ( paintdevice ) ? paintdevice->x11Screen() : TQPaintDevice::x11AppScreen(); - - defFormat->fn.x11SetScreen( scr ); - defFormat->update(); - - TQDictIterator it( cKey ); - TQTextFormat *format; - while ( ( format = it.current() ) != 0 ) { - ++it; - format->fn.x11SetScreen( scr ); - format->update(); - } -#endif // TQ_WS_X11 -} - -TQTextFormat *TQTextFormatCollection::format( TQTextFormat *f ) -{ - if ( f->parent() == this || f == defFormat ) { - lastFormat = f; - lastFormat->addRef(); - return lastFormat; - } - - if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) { - lastFormat->addRef(); - return lastFormat; - } - - TQTextFormat *fm = cKey.find( f->key() ); - if ( fm ) { - lastFormat = fm; - lastFormat->addRef(); - return lastFormat; - } - - if ( f->key() == defFormat->key() ) - return defFormat; - - lastFormat = createFormat( *f ); - lastFormat->collection = this; - cKey.insert( lastFormat->key(), lastFormat ); - return lastFormat; -} - -TQTextFormat *TQTextFormatCollection::format( TQTextFormat *of, TQTextFormat *nf, int flags ) -{ - if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) { - cres->addRef(); - return cres; - } - - cres = createFormat( *of ); - kof = of->key(); - knf = nf->key(); - cflags = flags; - if ( flags & TQTextFormat::Bold ) - cres->fn.setBold( nf->fn.bold() ); - if ( flags & TQTextFormat::Italic ) - cres->fn.setItalic( nf->fn.italic() ); - if ( flags & TQTextFormat::Underline ) - cres->fn.setUnderline( nf->fn.underline() ); - if ( flags & TQTextFormat::StrikeOut ) - cres->fn.setStrikeOut( nf->fn.strikeOut() ); - if ( flags & TQTextFormat::Family ) - cres->fn.setFamily( nf->fn.family() ); - if ( flags & TQTextFormat::Size ) { - if ( of->usePixelSizes ) - cres->fn.setPixelSize( nf->fn.pixelSize() ); - else - cres->fn.setPointSize( nf->fn.pointSize() ); - } - if ( flags & TQTextFormat::Color ) - cres->col = nf->col; - if ( flags & TQTextFormat::Misspelled ) - cres->missp = nf->missp; - if ( flags & TQTextFormat::VAlign ) - cres->ha = nf->ha; - cres->update(); - - TQTextFormat *fm = cKey.find( cres->key() ); - if ( !fm ) { - cres->collection = this; - cKey.insert( cres->key(), cres ); - } else { - delete cres; - cres = fm; - cres->addRef(); - } - - return cres; -} - -TQTextFormat *TQTextFormatCollection::format( const TQFont &f, const TQColor &c ) -{ - if ( cachedFormat && cfont == f && ccol == c ) { - cachedFormat->addRef(); - return cachedFormat; - } - - TQString key = TQTextFormat::getKey( f, c, FALSE, TQTextFormat::AlignNormal ); - cachedFormat = cKey.find( key ); - cfont = f; - ccol = c; - - if ( cachedFormat ) { - cachedFormat->addRef(); - return cachedFormat; - } - - if ( key == defFormat->key() ) - return defFormat; - - cachedFormat = createFormat( f, c ); - cachedFormat->collection = this; - cKey.insert( cachedFormat->key(), cachedFormat ); - if ( cachedFormat->key() != key ) - tqWarning("ASSERT: keys for format not identical: '%s '%s'", cachedFormat->key().latin1(), key.latin1() ); - return cachedFormat; -} - -void TQTextFormatCollection::remove( TQTextFormat *f ) -{ - if ( lastFormat == f ) - lastFormat = 0; - if ( cres == f ) - cres = 0; - if ( cachedFormat == f ) - cachedFormat = 0; - if (cKey.find(f->key()) == f) - cKey.remove( f->key() ); -} - -#define UPDATE( up, lo, rest ) \ - if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \ - fm->fn.set##up##rest( font.lo##rest() ) - -void TQTextFormatCollection::updateDefaultFormat( const TQFont &font, const TQColor &color, TQStyleSheet *sheet ) -{ - TQDictIterator it( cKey ); - TQTextFormat *fm; - bool usePixels = font.pointSize() == -1; - bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() : - font.pointSize() != defFormat->fn.pointSize(); - int base = usePixels ? font.pixelSize() : font.pointSize(); - while ( ( fm = it.current() ) ) { - ++it; - UPDATE( F, f, amily ); - UPDATE( W, w, eight ); - UPDATE( B, b, old ); - UPDATE( I, i, talic ); - UPDATE( U, u, nderline ); - if ( changeSize ) { - fm->stdSize = base; - fm->usePixelSizes = usePixels; - if ( usePixels ) - fm->fn.setPixelSize( fm->stdSize ); - else - fm->fn.setPointSize( fm->stdSize ); - sheet->scaleFont( fm->fn, fm->logicalFontSize ); - } - if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col ) - fm->col = color; - fm->update(); - } - - defFormat->fn = font; - defFormat->col = color; - defFormat->update(); - defFormat->stdSize = base; - defFormat->usePixelSizes = usePixels; - - updateKeys(); -} - -// the keys in cKey have changed, rebuild the hashtable -void TQTextFormatCollection::updateKeys() -{ - if ( cKey.isEmpty() ) - return; - cKey.setAutoDelete( FALSE ); - TQTextFormat** formats = new TQTextFormat*[ cKey.count() + 1 ]; - TQTextFormat **f = formats; - TQDictIterator it( cKey ); - while ( ( *f = it.current() ) ) { - ++it; - ++f; - } - cKey.clear(); - for ( f = formats; *f; f++ ) - cKey.insert( (*f)->key(), *f ); - cKey.setAutoDelete( TRUE ); - delete [] formats; -} - - - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -void TQTextFormat::setBold( bool b ) -{ - if ( b == fn.bold() ) - return; - fn.setBold( b ); - update(); -} - -void TQTextFormat::setMisspelled( bool b ) -{ - if ( b == (bool)missp ) - return; - missp = b; - update(); -} - -void TQTextFormat::setVAlign( VerticalAlignment a ) -{ - if ( a == ha ) - return; - ha = a; - update(); -} - -void TQTextFormat::setItalic( bool b ) -{ - if ( b == fn.italic() ) - return; - fn.setItalic( b ); - update(); -} - -void TQTextFormat::setUnderline( bool b ) -{ - if ( b == fn.underline() ) - return; - fn.setUnderline( b ); - update(); -} - -void TQTextFormat::setStrikeOut( bool b ) -{ - if ( b == fn.strikeOut() ) - return; - fn.setStrikeOut( b ); - update(); -} - -void TQTextFormat::setFamily( const TQString &f ) -{ - if ( f == fn.family() ) - return; - fn.setFamily( f ); - update(); -} - -void TQTextFormat::setPointSize( int s ) -{ - if ( s == fn.pointSize() ) - return; - fn.setPointSize( s ); - usePixelSizes = FALSE; - update(); -} - -void TQTextFormat::setFont( const TQFont &f ) -{ - if ( f == fn && !k.isEmpty() ) - return; - fn = f; - update(); -} - -void TQTextFormat::setColor( const TQColor &c ) -{ - if ( c == col ) - return; - col = c; - update(); -} - -TQString TQTextFormat::makeFormatChangeTags( TQTextFormat* defaultFormat, TQTextFormat *f, - const TQString& oldAnchorHref, const TQString& anchorHref ) const -{ - TQString tag; - if ( f ) - tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref ); - - if ( !anchorHref.isEmpty() ) - tag += ""; - - if ( font() != defaultFormat->font() - || vAlign() != defaultFormat->vAlign() - || color().rgb() != defaultFormat->color().rgb() ) { - TQString s; - if ( font().family() != defaultFormat->font().family() ) - s += TQString(!!s?";":"") + "font-family:" + fn.family(); - if ( font().italic() && font().italic() != defaultFormat->font().italic() ) - s += TQString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal"); - if ( font().pointSize() != defaultFormat->font().pointSize() ) - s += TQString(!!s?";":"") + "font-size:" + TQString::number( fn.pointSize() ) + "pt"; - if ( font().weight() != defaultFormat->font().weight() ) - s += TQString(!!s?";":"") + "font-weight:" + TQString::number( fn.weight() * 8 ); - TQString textDecoration; - bool none = FALSE; - if ( font().underline() != defaultFormat->font().underline() ) { - if (font().underline()) - textDecoration = "underline"; - else - none = TRUE; - } - if ( font().overline() != defaultFormat->font().overline() ) { - if (font().overline()) - textDecoration += " overline"; - else - none = TRUE; - } - if ( font().strikeOut() != defaultFormat->font().strikeOut() ) { - if (font().strikeOut()) - textDecoration += " line-through"; - else - none = TRUE; - } - if (none && textDecoration.isEmpty()) - textDecoration = "none"; - if (!textDecoration.isEmpty()) - s += TQString(!!s?";":"") + "text-decoration:" + textDecoration; - if ( vAlign() != defaultFormat->vAlign() ) { - s += TQString(!!s?";":"") + "vertical-align:"; - if ( vAlign() == TQTextFormat::AlignSuperScript ) - s += "super"; - else if ( vAlign() == TQTextFormat::AlignSubScript ) - s += "sub"; - else - s += "normal"; - } - if ( color().rgb() != defaultFormat->color().rgb() ) - s += TQString(!!s?";":"") + "color:" + col.name(); - if ( !s.isEmpty() ) - tag += ""; - } - - return tag; -} - -TQString TQTextFormat::makeFormatEndTags( TQTextFormat* defaultFormat, const TQString& anchorHref ) const -{ - TQString tag; - if ( font().family() != defaultFormat->font().family() - || font().pointSize() != defaultFormat->font().pointSize() - || font().weight() != defaultFormat->font().weight() - || font().italic() != defaultFormat->font().italic() - || font().underline() != defaultFormat->font().underline() - || font().strikeOut() != defaultFormat->font().strikeOut() - || vAlign() != defaultFormat->vAlign() - || color().rgb() != defaultFormat->color().rgb() ) - tag += ""; - if ( !anchorHref.isEmpty() ) - tag += ""; - return tag; -} - -TQTextFormat TQTextFormat::makeTextFormat( const TQStyleSheetItem *style, const TQMap& attr, double scaleFontsFactor ) const -{ - TQTextFormat format(*this); - if (!style ) - return format; - - if ( !style->isAnchor() && style->color().isValid() ) { - // the style is not an anchor and defines a color. - // It might be used inside an anchor and it should - // override the link color. - format.linkColor = FALSE; - } - switch ( style->verticalAlignment() ) { - case TQStyleSheetItem::VAlignBaseline: - format.setVAlign( TQTextFormat::AlignNormal ); - break; - case TQStyleSheetItem::VAlignSuper: - format.setVAlign( TQTextFormat::AlignSuperScript ); - break; - case TQStyleSheetItem::VAlignSub: - format.setVAlign( TQTextFormat::AlignSubScript ); - break; - } - - if ( style->fontWeight() != TQStyleSheetItem::Undefined ) - format.fn.setWeight( style->fontWeight() ); - if ( style->fontSize() != TQStyleSheetItem::Undefined ) { - format.fn.setPointSize( style->fontSize() ); - } else if ( style->logicalFontSize() != TQStyleSheetItem::Undefined ) { - format.logicalFontSize = style->logicalFontSize(); - if ( format.usePixelSizes ) - format.fn.setPixelSize( format.stdSize ); - else - format.fn.setPointSize( format.stdSize ); - style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); - } else if ( style->logicalFontSizeStep() ) { - format.logicalFontSize += style->logicalFontSizeStep(); - if ( format.usePixelSizes ) - format.fn.setPixelSize( format.stdSize ); - else - format.fn.setPointSize( format.stdSize ); - style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); - } - if ( !style->fontFamily().isEmpty() ) - format.fn.setFamily( style->fontFamily() ); - if ( style->color().isValid() ) - format.col = style->color(); - if ( style->definesFontItalic() ) - format.fn.setItalic( style->fontItalic() ); - if ( style->definesFontUnderline() ) - format.fn.setUnderline( style->fontUnderline() ); - if ( style->definesFontStrikeOut() ) - format.fn.setStrikeOut( style->fontStrikeOut() ); - - - if ( style->name() == "font") { - if ( attr.contains("color") ) { - TQString s = attr["color"]; - if ( !s.isEmpty() ) { - format.col.setNamedColor( s ); - format.linkColor = FALSE; - } - } - if ( attr.contains("face") ) { - TQString a = attr["face"]; - TQString family = a.section( ',', 0, 0 ); - if ( !!family ) - format.fn.setFamily( family ); - } - if ( attr.contains("size") ) { - TQString a = attr["size"]; - int n = a.toInt(); - if ( a[0] == '+' || a[0] == '-' ) - n += 3; - format.logicalFontSize = n; - if ( format.usePixelSizes ) - format.fn.setPixelSize( format.stdSize ); - else - format.fn.setPointSize( format.stdSize ); - style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); - } - } - if ( attr.contains("style" ) ) { - TQString a = attr["style"]; - for ( int s = 0; s < a.contains(';')+1; s++ ) { - TQString style = a.section( ';', s, s ); - if ( style.startsWith("font-size:" ) && style.endsWith("pt") ) { - format.logicalFontSize = 0; - int size = int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toDouble() ); - format.setPointSize( size ); - } else if ( style.startsWith("font-style:" ) ) { - TQString s = style.mid( 11 ).stripWhiteSpace(); - if ( s == "normal" ) - format.fn.setItalic( FALSE ); - else if ( s == "italic" || s == "oblique" ) - format.fn.setItalic( TRUE ); - } else if ( style.startsWith("font-weight:" ) ) { - TQString s = style.mid( 12 ); - bool ok = TRUE; - int n = s.toInt( &ok ); - if ( ok ) - format.fn.setWeight( n/8 ); - } else if ( style.startsWith("font-family:" ) ) { - TQString family = style.mid(12).section(',',0,0); - family.replace( '\"', ' ' ); - family.replace( '\'', ' ' ); - family = family.stripWhiteSpace(); - format.fn.setFamily( family ); - } else if ( style.startsWith("text-decoration:" ) ) { - TQString s = style.mid( 16 ); - format.fn.setOverline( s.find("overline") != -1 ); - format.fn.setStrikeOut( s.find("line-through") != -1 ); - format.fn.setUnderline( s.find("underline") != -1 ); - } else if ( style.startsWith("vertical-align:" ) ) { - TQString s = style.mid( 15 ).stripWhiteSpace(); - if ( s == "sub" ) - format.setVAlign( TQTextFormat::AlignSubScript ); - else if ( s == "super" ) - format.setVAlign( TQTextFormat::AlignSuperScript ); - else - format.setVAlign( TQTextFormat::AlignNormal ); - } else if ( style.startsWith("color:" ) ) { - format.col.setNamedColor( style.mid(6) ); - format.linkColor = FALSE; - } - } - } - - format.update(); - return format; -} - -#ifndef TQT_NO_TEXTCUSTOMITEM - -struct TQPixmapInt -{ - TQPixmapInt() : ref( 0 ) {} - TQPixmap pm; - int ref; - TQ_DUMMY_COMPARISON_OPERATOR(TQPixmapInt) -}; - -static TQMap *pixmap_map = 0; - -TQTextImage::TQTextImage( TQTextDocument *p, const TQMap &attr, const TQString& context, - TQMimeSourceFactory &factory ) - : TQTextCustomItem( p ) -{ - width = height = 0; - if ( attr.contains("width") ) - width = attr["width"].toInt(); - if ( attr.contains("height") ) - height = attr["height"].toInt(); - - reg = 0; - TQString imageName = attr["src"]; - - if (!imageName) - imageName = attr["source"]; - - if ( !imageName.isEmpty() ) { - imgId = TQString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory ); - if ( !pixmap_map ) - pixmap_map = new TQMap; - if ( pixmap_map->contains( imgId ) ) { - TQPixmapInt& pmi = pixmap_map->operator[](imgId); - pm = pmi.pm; - pmi.ref++; - width = pm.width(); - height = pm.height(); - } else { - TQImage img; - const TQMimeSource* m = - factory.data( imageName, context ); - if ( !m ) { - tqWarning("TQTextImage: no mimesource for %s", imageName.latin1() ); - } - else { - if ( !TQImageDrag::decode( m, img ) ) { - tqWarning("TQTextImage: cannot decode %s", imageName.latin1() ); - } - } - - if ( !img.isNull() ) { - if ( width == 0 ) { - width = img.width(); - if ( height != 0 ) { - width = img.width() * height / img.height(); - } - } - if ( height == 0 ) { - height = img.height(); - if ( width != img.width() ) { - height = img.height() * width / img.width(); - } - } - if ( img.width() != width || img.height() != height ){ -#ifndef TQT_NO_IMAGE_SMOOTHSCALE - img = img.smoothScale(width, height); -#endif - width = img.width(); - height = img.height(); - } - pm.convertFromImage( img ); - } - if ( !pm.isNull() ) { - TQPixmapInt& pmi = pixmap_map->operator[](imgId); - pmi.pm = pm; - pmi.ref++; - } - } - if ( pm.mask() ) { - TQRegion mask( *pm.mask() ); - TQRegion all( 0, 0, pm.width(), pm.height() ); - reg = new TQRegion( all.subtract( mask ) ); - } - } - - if ( pm.isNull() && (width*height)==0 ) - width = height = 50; - - place = PlaceInline; - if ( attr["align"] == "left" ) - place = PlaceLeft; - else if ( attr["align"] == "right" ) - place = PlaceRight; - - tmpwidth = width; - tmpheight = height; - - attributes = attr; -} - -TQTextImage::~TQTextImage() -{ - if ( pixmap_map && pixmap_map->contains( imgId ) ) { - TQPixmapInt& pmi = pixmap_map->operator[](imgId); - pmi.ref--; - if ( !pmi.ref ) { - pixmap_map->remove( imgId ); - if ( pixmap_map->isEmpty() ) { - delete pixmap_map; - pixmap_map = 0; - } - } - } - delete reg; -} - -TQString TQTextImage::richText() const -{ - TQString s; - s += "::ConstIterator it = attributes.begin(); - for ( ; it != attributes.end(); ++it ) { - s += it.key() + "="; - if ( (*it).find( ' ' ) != -1 ) - s += "\"" + *it + "\"" + " "; - else - s += *it + " "; - } - s += ">"; - return s; -} - -void TQTextImage::adjustToPainter( TQPainter* p ) -{ - width = scale( tmpwidth, p ); - height = scale( tmpheight, p ); -} - -#if !defined(TQ_WS_X11) -#include -#include -static TQPixmap *qrt_selection = 0; -static TQSingleCleanupHandler qrt_cleanup_pixmap; -static void qrt_createSelectionPixmap( const TQColorGroup &cg ) -{ - qrt_selection = new TQPixmap( 2, 2 ); - qrt_cleanup_pixmap.set( &qrt_selection ); - qrt_selection->fill( TQt::color0 ); - TQBitmap m( 2, 2 ); - m.fill( TQt::color1 ); - TQPainter p( &m ); - p.setPen( TQt::color0 ); - for ( int j = 0; j < 2; ++j ) { - p.drawPoint( j % 2, j ); - } - p.end(); - qrt_selection->setMask( m ); - qrt_selection->fill( cg.highlight() ); -} -#endif - -void TQTextImage::draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) -{ - if ( placement() != PlaceInline ) { - x = xpos; - y = ypos; - } - - if ( pm.isNull() ) { - p->fillRect( x , y, width, height, cg.dark() ); - return; - } - - if ( is_printer( p ) ) { - p->drawPixmap( TQRect( x, y, width, height ), pm ); - return; - } - - if ( placement() != PlaceInline && !TQRect( xpos, ypos, width, height ).intersects( TQRect( cx, cy, cw, ch ) ) ) - return; - - if ( placement() == PlaceInline ) - p->drawPixmap( x , y, pm ); - else - p->drawPixmap( cx , cy, pm, cx - x, cy - y, cw, ch ); - - if ( selected && placement() == PlaceInline && is_printer( p ) ) { -#if defined(TQ_WS_X11) - p->fillRect( TQRect( TQPoint( x, y ), pm.size() ), TQBrush( cg.highlight(), TQBrush::Dense4Pattern) ); -#else // in WIN32 Dense4Pattern doesn't work correctly (transparency problem), so work around it - if ( !qrt_selection ) - qrt_createSelectionPixmap( cg ); - p->drawTiledPixmap( x, y, pm.width(), pm.height(), *qrt_selection ); -#endif - } -} - -void TQTextHorizontalLine::adjustToPainter( TQPainter* p ) -{ - height = scale( tmpheight, p ); -} - - -TQTextHorizontalLine::TQTextHorizontalLine( TQTextDocument *p, const TQMap &attr, - const TQString &, - TQMimeSourceFactory & ) - : TQTextCustomItem( p ) -{ - height = tmpheight = 8; - if ( attr.find( "color" ) != attr.end() ) - color = TQColor( *attr.find( "color" ) ); - shade = attr.find( "noshade" ) == attr.end(); -} - -TQTextHorizontalLine::~TQTextHorizontalLine() -{ -} - -TQString TQTextHorizontalLine::richText() const -{ - return "
"; -} - -void TQTextHorizontalLine::draw( TQPainter* p, int x, int y, int , int , int , int , const TQColorGroup& cg, bool selected ) -{ - TQRect r( x, y, width, height); - if ( is_printer( p ) || !shade ) { - TQPen oldPen = p->pen(); - if ( !color.isValid() ) - p->setPen( TQPen( cg.text(), is_printer( p ) ? height/8 : TQMAX( 2, height/4 ) ) ); - else - p->setPen( TQPen( color, is_printer( p ) ? height/8 : TQMAX( 2, height/4 ) ) ); - p->drawLine( r.left()-1, y + height / 2, r.right() + 1, y + height / 2 ); - p->setPen( oldPen ); - } else { - TQColorGroup g( cg ); - if ( color.isValid() ) - g.setColor( TQColorGroup::Dark, color ); - if ( selected ) - p->fillRect( r, g.highlight() ); - qDrawShadeLine( p, r.left() - 1, y + height / 2, r.right() + 1, y + height / 2, g, TRUE, height / 8 ); - } -} -#endif //TQT_NO_TEXTCUSTOMITEM - -/*****************************************************************/ -// Small set of utility functions to make the parser a bit simpler -// - -bool TQTextDocument::hasPrefix(const TQChar* doc, int length, int pos, TQChar c) -{ - if ( pos + 1 > length ) - return FALSE; - return doc[ pos ].lower() == c.lower(); -} - -bool TQTextDocument::hasPrefix( const TQChar* doc, int length, int pos, const TQString& s ) -{ - if ( pos + (int) s.length() > length ) - return FALSE; - for ( int i = 0; i < (int)s.length(); i++ ) { - if ( doc[ pos + i ].lower() != s[ i ].lower() ) - return FALSE; - } - return TRUE; -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -static bool qt_is_cell_in_use( TQPtrList& cells, int row, int col ) -{ - for ( TQTextTableCell* c = cells.first(); c; c = cells.next() ) { - if ( row >= c->row() && row < c->row() + c->rowspan() - && col >= c->column() && col < c->column() + c->colspan() ) - return TRUE; - } - return FALSE; -} - -TQTextCustomItem* TQTextDocument::parseTable( const TQMap &attr, const TQTextFormat &fmt, - const TQChar* doc, int length, int& pos, TQTextParagraph *curpar ) -{ - - TQTextTable* table = new TQTextTable( this, attr ); - int row = -1; - int col = -1; - - TQString rowbgcolor; - TQString rowalign; - TQString tablebgcolor = attr["bgcolor"]; - - TQPtrList multicells; - - TQString tagname; - (void) eatSpace(doc, length, pos); - while ( pos < length) { - if (hasPrefix(doc, length, pos, TQChar('<')) ){ - if (hasPrefix(doc, length, pos+1, TQChar('/'))) { - tagname = parseCloseTag( doc, length, pos ); - if ( tagname == "table" ) { - return table; - } - } else { - TQMap attr2; - bool emptyTag = FALSE; - tagname = parseOpenTag( doc, length, pos, attr2, emptyTag ); - if ( tagname == "tr" ) { - rowbgcolor = attr2["bgcolor"]; - rowalign = attr2["align"]; - row++; - col = -1; - } - else if ( tagname == "td" || tagname == "th" ) { - col++; - while ( qt_is_cell_in_use( multicells, row, col ) ) { - col++; - } - - if ( row >= 0 && col >= 0 ) { - const TQStyleSheetItem* s = sheet_->item(tagname); - if ( !attr2.contains("bgcolor") ) { - if (!rowbgcolor.isEmpty() ) - attr2["bgcolor"] = rowbgcolor; - else if (!tablebgcolor.isEmpty() ) - attr2["bgcolor"] = tablebgcolor; - } - if ( !attr2.contains("align") ) { - if (!rowalign.isEmpty() ) - attr2["align"] = rowalign; - } - - // extract the cell contents - int end = pos; - while ( end < length - && !hasPrefix( doc, length, end, "richText()->parentPar = curpar; - if ( cell->colspan() > 1 || cell->rowspan() > 1 ) - multicells.append( cell ); - col += cell->colspan()-1; - pos = end; - } - } - } - - } else { - ++pos; - } - } - return table; -} -#endif // TQT_NO_TEXTCUSTOMITEM - -bool TQTextDocument::eatSpace(const TQChar* doc, int length, int& pos, bool includeNbsp ) -{ - int old_pos = pos; - while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != TQChar::nbsp ) ) ) - pos++; - return old_pos < pos; -} - -bool TQTextDocument::eat(const TQChar* doc, int length, int& pos, TQChar c) -{ - bool ok = pos < length && doc[pos] == c; - if ( ok ) - pos++; - return ok; -} -/*****************************************************************/ - -struct Entity { - const char * name; - TQ_UINT16 code; -}; - -static const Entity entitylist [] = { - { "AElig", 0x00c6 }, - { "Aacute", 0x00c1 }, - { "Acirc", 0x00c2 }, - { "Agrave", 0x00c0 }, - { "Alpha", 0x0391 }, - { "AMP", 38 }, - { "Aring", 0x00c5 }, - { "Atilde", 0x00c3 }, - { "Auml", 0x00c4 }, - { "Beta", 0x0392 }, - { "Ccedil", 0x00c7 }, - { "Chi", 0x03a7 }, - { "Dagger", 0x2021 }, - { "Delta", 0x0394 }, - { "ETH", 0x00d0 }, - { "Eacute", 0x00c9 }, - { "Ecirc", 0x00ca }, - { "Egrave", 0x00c8 }, - { "Epsilon", 0x0395 }, - { "Eta", 0x0397 }, - { "Euml", 0x00cb }, - { "Gamma", 0x0393 }, - { "GT", 62 }, - { "Iacute", 0x00cd }, - { "Icirc", 0x00ce }, - { "Igrave", 0x00cc }, - { "Iota", 0x0399 }, - { "Iuml", 0x00cf }, - { "Kappa", 0x039a }, - { "Lambda", 0x039b }, - { "LT", 60 }, - { "Mu", 0x039c }, - { "Ntilde", 0x00d1 }, - { "Nu", 0x039d }, - { "OElig", 0x0152 }, - { "Oacute", 0x00d3 }, - { "Ocirc", 0x00d4 }, - { "Ograve", 0x00d2 }, - { "Omega", 0x03a9 }, - { "Omicron", 0x039f }, - { "Oslash", 0x00d8 }, - { "Otilde", 0x00d5 }, - { "Ouml", 0x00d6 }, - { "Phi", 0x03a6 }, - { "Pi", 0x03a0 }, - { "Prime", 0x2033 }, - { "Psi", 0x03a8 }, - { "TQUOT", 34 }, - { "Rho", 0x03a1 }, - { "Scaron", 0x0160 }, - { "Sigma", 0x03a3 }, - { "THORN", 0x00de }, - { "Tau", 0x03a4 }, - { "Theta", 0x0398 }, - { "Uacute", 0x00da }, - { "Ucirc", 0x00db }, - { "Ugrave", 0x00d9 }, - { "Upsilon", 0x03a5 }, - { "Uuml", 0x00dc }, - { "Xi", 0x039e }, - { "Yacute", 0x00dd }, - { "Yuml", 0x0178 }, - { "Zeta", 0x0396 }, - { "aacute", 0x00e1 }, - { "acirc", 0x00e2 }, - { "acute", 0x00b4 }, - { "aelig", 0x00e6 }, - { "agrave", 0x00e0 }, - { "alefsym", 0x2135 }, - { "alpha", 0x03b1 }, - { "amp", 38 }, - { "and", 0x22a5 }, - { "ang", 0x2220 }, - { "apos", 0x0027 }, - { "aring", 0x00e5 }, - { "asymp", 0x2248 }, - { "atilde", 0x00e3 }, - { "auml", 0x00e4 }, - { "bdquo", 0x201e }, - { "beta", 0x03b2 }, - { "brvbar", 0x00a6 }, - { "bull", 0x2022 }, - { "cap", 0x2229 }, - { "ccedil", 0x00e7 }, - { "cedil", 0x00b8 }, - { "cent", 0x00a2 }, - { "chi", 0x03c7 }, - { "circ", 0x02c6 }, - { "clubs", 0x2663 }, - { "cong", 0x2245 }, - { "copy", 0x00a9 }, - { "crarr", 0x21b5 }, - { "cup", 0x222a }, - { "curren", 0x00a4 }, - { "dArr", 0x21d3 }, - { "dagger", 0x2020 }, - { "darr", 0x2193 }, - { "deg", 0x00b0 }, - { "delta", 0x03b4 }, - { "diams", 0x2666 }, - { "divide", 0x00f7 }, - { "eacute", 0x00e9 }, - { "ecirc", 0x00ea }, - { "egrave", 0x00e8 }, - { "empty", 0x2205 }, - { "emsp", 0x2003 }, - { "ensp", 0x2002 }, - { "epsilon", 0x03b5 }, - { "equiv", 0x2261 }, - { "eta", 0x03b7 }, - { "eth", 0x00f0 }, - { "euml", 0x00eb }, - { "euro", 0x20ac }, - { "exist", 0x2203 }, - { "fnof", 0x0192 }, - { "forall", 0x2200 }, - { "frac12", 0x00bd }, - { "frac14", 0x00bc }, - { "frac34", 0x00be }, - { "frasl", 0x2044 }, - { "gamma", 0x03b3 }, - { "ge", 0x2265 }, - { "gt", 62 }, - { "hArr", 0x21d4 }, - { "harr", 0x2194 }, - { "hearts", 0x2665 }, - { "hellip", 0x2026 }, - { "iacute", 0x00ed }, - { "icirc", 0x00ee }, - { "iexcl", 0x00a1 }, - { "igrave", 0x00ec }, - { "image", 0x2111 }, - { "infin", 0x221e }, - { "int", 0x222b }, - { "iota", 0x03b9 }, - { "iquest", 0x00bf }, - { "isin", 0x2208 }, - { "iuml", 0x00ef }, - { "kappa", 0x03ba }, - { "lArr", 0x21d0 }, - { "lambda", 0x03bb }, - { "lang", 0x2329 }, - { "laquo", 0x00ab }, - { "larr", 0x2190 }, - { "lceil", 0x2308 }, - { "ldquo", 0x201c }, - { "le", 0x2264 }, - { "lfloor", 0x230a }, - { "lowast", 0x2217 }, - { "loz", 0x25ca }, - { "lrm", 0x200e }, - { "lsaquo", 0x2039 }, - { "lsquo", 0x2018 }, - { "lt", 60 }, - { "macr", 0x00af }, - { "mdash", 0x2014 }, - { "micro", 0x00b5 }, - { "middot", 0x00b7 }, - { "minus", 0x2212 }, - { "mu", 0x03bc }, - { "nabla", 0x2207 }, - { "nbsp", 0x00a0 }, - { "ndash", 0x2013 }, - { "ne", 0x2260 }, - { "ni", 0x220b }, - { "not", 0x00ac }, - { "notin", 0x2209 }, - { "nsub", 0x2284 }, - { "ntilde", 0x00f1 }, - { "nu", 0x03bd }, - { "oacute", 0x00f3 }, - { "ocirc", 0x00f4 }, - { "oelig", 0x0153 }, - { "ograve", 0x00f2 }, - { "oline", 0x203e }, - { "omega", 0x03c9 }, - { "omicron", 0x03bf }, - { "oplus", 0x2295 }, - { "or", 0x22a6 }, - { "ordf", 0x00aa }, - { "ordm", 0x00ba }, - { "oslash", 0x00f8 }, - { "otilde", 0x00f5 }, - { "otimes", 0x2297 }, - { "ouml", 0x00f6 }, - { "para", 0x00b6 }, - { "part", 0x2202 }, - { "percnt", 0x0025 }, - { "permil", 0x2030 }, - { "perp", 0x22a5 }, - { "phi", 0x03c6 }, - { "pi", 0x03c0 }, - { "piv", 0x03d6 }, - { "plusmn", 0x00b1 }, - { "pound", 0x00a3 }, - { "prime", 0x2032 }, - { "prod", 0x220f }, - { "prop", 0x221d }, - { "psi", 0x03c8 }, - { "quot", 34 }, - { "rArr", 0x21d2 }, - { "radic", 0x221a }, - { "rang", 0x232a }, - { "raquo", 0x00bb }, - { "rarr", 0x2192 }, - { "rceil", 0x2309 }, - { "rdquo", 0x201d }, - { "real", 0x211c }, - { "reg", 0x00ae }, - { "rfloor", 0x230b }, - { "rho", 0x03c1 }, - { "rlm", 0x200f }, - { "rsaquo", 0x203a }, - { "rsquo", 0x2019 }, - { "sbquo", 0x201a }, - { "scaron", 0x0161 }, - { "sdot", 0x22c5 }, - { "sect", 0x00a7 }, - { "shy", 0x00ad }, - { "sigma", 0x03c3 }, - { "sigmaf", 0x03c2 }, - { "sim", 0x223c }, - { "spades", 0x2660 }, - { "sub", 0x2282 }, - { "sube", 0x2286 }, - { "sum", 0x2211 }, - { "sup1", 0x00b9 }, - { "sup2", 0x00b2 }, - { "sup3", 0x00b3 }, - { "sup", 0x2283 }, - { "supe", 0x2287 }, - { "szlig", 0x00df }, - { "tau", 0x03c4 }, - { "there4", 0x2234 }, - { "theta", 0x03b8 }, - { "thetasym", 0x03d1 }, - { "thinsp", 0x2009 }, - { "thorn", 0x00fe }, - { "tilde", 0x02dc }, - { "times", 0x00d7 }, - { "trade", 0x2122 }, - { "uArr", 0x21d1 }, - { "uacute", 0x00fa }, - { "uarr", 0x2191 }, - { "ucirc", 0x00fb }, - { "ugrave", 0x00f9 }, - { "uml", 0x00a8 }, - { "upsih", 0x03d2 }, - { "upsilon", 0x03c5 }, - { "uuml", 0x00fc }, - { "weierp", 0x2118 }, - { "xi", 0x03be }, - { "yacute", 0x00fd }, - { "yen", 0x00a5 }, - { "yuml", 0x00ff }, - { "zeta", 0x03b6 }, - { "zwj", 0x200d }, - { "zwnj", 0x200c }, - { "", 0x0000 } -}; - - - - - -static TQMap *html_map = 0; -static void tqt_cleanup_html_map() -{ - delete html_map; - html_map = 0; -} - -static TQMap *htmlMap() -{ - if ( !html_map ) { - html_map = new TQMap; - tqAddPostRoutine( tqt_cleanup_html_map ); - - const Entity *ent = entitylist; - while( ent->code ) { - html_map->insert( ent->name, TQChar(ent->code) ); - ent++; - } - } - return html_map; -} - -TQChar TQTextDocument::parseHTMLSpecialChar(const TQChar* doc, int length, int& pos) -{ - TQString s; - pos++; - int recoverpos = pos; - while ( pos < length && doc[pos] != ';' && !doc[pos].isSpace() && pos < recoverpos + 8 ) { - s += doc[pos]; - pos++; - } - if (doc[pos] != ';' && !doc[pos].isSpace() ) { - pos = recoverpos; - return '&'; - } - pos++; - - if ( s.length() > 1 && s[0] == '#') { - int off = 1; - int base = 10; - if (s[1] == 'x') { - off = 2; - base = 16; - } - bool ok; - int num = s.mid(off).toInt(&ok, base); - if ( num == 151 ) // ### hack for designer manual - return '-'; - if (ok) - return num; - } else { - TQMap::Iterator it = htmlMap()->find(s); - if ( it != htmlMap()->end() ) { - return *it; - } - } - - pos = recoverpos; - return '&'; -} - -TQString TQTextDocument::parseWord(const TQChar* doc, int length, int& pos, bool lower) -{ - TQString s; - - if (doc[pos] == '"') { - pos++; - while ( pos < length && doc[pos] != '"' ) { - if ( doc[pos] == '&' ) { - s += parseHTMLSpecialChar( doc, length, pos ); - } else { - s += doc[pos]; - pos++; - } - } - eat(doc, length, pos, '"'); - } else if (doc[pos] == '\'') { - pos++; - while ( pos < length && doc[pos] != '\'' ) { - s += doc[pos]; - pos++; - } - eat(doc, length, pos, '\''); - } else { - static TQString term = TQString::fromLatin1("/>"); - while ( pos < length - && doc[pos] != '>' - && !hasPrefix(doc, length, pos, term) - && doc[pos] != '<' - && doc[pos] != '=' - && !doc[pos].isSpace() ) - { - if ( doc[pos] == '&' ) { - s += parseHTMLSpecialChar( doc, length, pos ); - } else { - s += doc[pos]; - pos++; - } - } - if (lower) - s = s.lower(); - } - return s; -} - -TQChar TQTextDocument::parseChar(const TQChar* doc, int length, int& pos, TQStyleSheetItem::WhiteSpaceMode wsm ) -{ - if ( pos >= length ) - return TQChar::null; - - TQChar c = doc[pos++]; - - if (c == '<' ) - return TQChar::null; - - if ( c.isSpace() && c != TQChar::nbsp ) { - if ( wsm == TQStyleSheetItem::WhiteSpacePre ) { - if ( c == '\n' ) - return TQChar_linesep; - else - return c; - } else { // non-pre mode: collapse whitespace except nbsp - while ( pos< length && - doc[pos].isSpace() && doc[pos] != TQChar::nbsp ) - pos++; - return ' '; - } - } - else if ( c == '&' ) - return parseHTMLSpecialChar( doc, length, --pos ); - else - return c; -} - -TQString TQTextDocument::parseOpenTag(const TQChar* doc, int length, int& pos, - TQMap &attr, bool& emptyTag) -{ - emptyTag = FALSE; - pos++; - if ( hasPrefix(doc, length, pos, '!') ) { - if ( hasPrefix( doc, length, pos+1, "--")) { - pos += 3; - // eat comments - TQString pref = TQString::fromLatin1("-->"); - while ( !hasPrefix(doc, length, pos, pref ) && pos < length ) - pos++; - if ( hasPrefix(doc, length, pos, pref ) ) { - pos += 3; - eatSpace(doc, length, pos, TRUE); - } - emptyTag = TRUE; - return TQString::null; - } - else { - // eat strange internal tags - while ( !hasPrefix(doc, length, pos, '>') && pos < length ) - pos++; - if ( hasPrefix(doc, length, pos, '>') ) { - pos++; - eatSpace(doc, length, pos, TRUE); - } - return TQString::null; - } - } - - TQString tag = parseWord(doc, length, pos ); - eatSpace(doc, length, pos, TRUE); - static TQString term = TQString::fromLatin1("/>"); - static TQString s_TRUE = TQString::fromLatin1("TRUE"); - - while (doc[pos] != '>' && ! (emptyTag = hasPrefix(doc, length, pos, term) )) { - TQString key = parseWord(doc, length, pos ); - eatSpace(doc, length, pos, TRUE); - if ( key.isEmpty()) { - // error recovery - while ( pos < length && doc[pos] != '>' ) - pos++; - break; - } - TQString value; - if (hasPrefix(doc, length, pos, '=') ){ - pos++; - eatSpace(doc, length, pos); - value = parseWord(doc, length, pos, FALSE); - } - else - value = s_TRUE; - attr.insert(key.lower(), value ); - eatSpace(doc, length, pos, TRUE); - } - - if (emptyTag) { - eat(doc, length, pos, '/'); - eat(doc, length, pos, '>'); - } - else - eat(doc, length, pos, '>'); - - return tag; -} - -TQString TQTextDocument::parseCloseTag( const TQChar* doc, int length, int& pos ) -{ - pos++; - pos++; - TQString tag = parseWord(doc, length, pos ); - eatSpace(doc, length, pos, TRUE); - eat(doc, length, pos, '>'); - return tag; -} - -TQTextFlow::TQTextFlow() -{ - w = pagesize = 0; -} - -TQTextFlow::~TQTextFlow() -{ - clear(); -} - -void TQTextFlow::clear() -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - leftItems.setAutoDelete( TRUE ); - rightItems.setAutoDelete( TRUE ); - leftItems.clear(); - rightItems.clear(); - leftItems.setAutoDelete( FALSE ); - rightItems.setAutoDelete( FALSE ); -#endif -} - -void TQTextFlow::setWidth( int width ) -{ - w = width; -} - -int TQTextFlow::adjustLMargin( int yp, int, int margin, int space ) -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - for ( TQTextCustomItem* item = leftItems.first(); item; item = leftItems.next() ) { - if ( item->ypos == -1 ) - continue; - if ( yp >= item->ypos && yp < item->ypos + item->height ) - margin = TQMAX( margin, item->xpos + item->width + space ); - } -#endif - return margin; -} - -int TQTextFlow::adjustRMargin( int yp, int, int margin, int space ) -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - for ( TQTextCustomItem* item = rightItems.first(); item; item = rightItems.next() ) { - if ( item->ypos == -1 ) - continue; - if ( yp >= item->ypos && yp < item->ypos + item->height ) - margin = TQMAX( margin, w - item->xpos - space ); - } -#endif - return margin; -} - - -int TQTextFlow::adjustFlow( int y, int /*w*/, int h ) -{ - if ( pagesize > 0 ) { // check pages - int yinpage = y % pagesize; - if ( yinpage <= border_tolerance ) - return border_tolerance - yinpage; - else - if ( yinpage + h > pagesize - border_tolerance ) - return ( pagesize - yinpage ) + border_tolerance; - } - return 0; -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -void TQTextFlow::unregisterFloatingItem( TQTextCustomItem* item ) -{ - leftItems.removeRef( item ); - rightItems.removeRef( item ); -} - -void TQTextFlow::registerFloatingItem( TQTextCustomItem* item ) -{ - if ( item->placement() == TQTextCustomItem::PlaceRight ) { - if ( !rightItems.contains( item ) ) - rightItems.append( item ); - } else if ( item->placement() == TQTextCustomItem::PlaceLeft && - !leftItems.contains( item ) ) { - leftItems.append( item ); - } -} -#endif // TQT_NO_TEXTCUSTOMITEM - -TQRect TQTextFlow::boundingRect() const -{ - TQRect br; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQPtrListIterator l( leftItems ); - while( l.current() ) { - br = br.unite( l.current()->geometry() ); - ++l; - } - TQPtrListIterator r( rightItems ); - while( r.current() ) { - br = br.unite( r.current()->geometry() ); - ++r; - } -#endif - return br; -} - - -void TQTextFlow::drawFloatingItems( TQPainter* p, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextCustomItem *item; - for ( item = leftItems.first(); item; item = leftItems.next() ) { - if ( item->xpos == -1 || item->ypos == -1 ) - continue; - item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); - } - - for ( item = rightItems.first(); item; item = rightItems.next() ) { - if ( item->xpos == -1 || item->ypos == -1 ) - continue; - item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); - } -#endif -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#ifndef TQT_NO_TEXTCUSTOMITEM -void TQTextCustomItem::pageBreak( int /*y*/ , TQTextFlow* /*flow*/ ) -{ -} -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM -TQTextTable::TQTextTable( TQTextDocument *p, const TQMap & attr ) - : TQTextCustomItem( p ) -{ - cells.setAutoDelete( FALSE ); - cellspacing = 2; - if ( attr.contains("cellspacing") ) - cellspacing = attr["cellspacing"].toInt(); - cellpadding = 1; - if ( attr.contains("cellpadding") ) - cellpadding = attr["cellpadding"].toInt(); - border = innerborder = 0; - if ( attr.contains("border" ) ) { - TQString s( attr["border"] ); - if ( s == "TRUE" ) - border = 1; - else - border = attr["border"].toInt(); - } - us_b = border; - - innerborder = us_ib = border ? 1 : 0; - - if ( border ) - cellspacing += 2; - - us_ib = innerborder; - us_cs = cellspacing; - us_cp = cellpadding; - outerborder = cellspacing + border; - us_ob = outerborder; - layout = new TQGridLayout( 1, 1, cellspacing ); - - fixwidth = 0; - stretch = 0; - if ( attr.contains("width") ) { - bool b; - TQString s( attr["width"] ); - int w = s.toInt( &b ); - if ( b ) { - fixwidth = w; - } else { - s = s.stripWhiteSpace(); - if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) - stretch = s.left( s.length()-1).toInt(); - } - } - us_fixwidth = fixwidth; - - place = PlaceInline; - if ( attr["align"] == "left" ) - place = PlaceLeft; - else if ( attr["align"] == "right" ) - place = PlaceRight; - cachewidth = 0; - attributes = attr; - pageBreakFor = -1; -} - -TQTextTable::~TQTextTable() -{ - delete layout; -} - -TQString TQTextTable::richText() const -{ - TQString s; - s = "::ConstIterator it = attributes.begin(); - for ( ; it != attributes.end(); ++it ) - s += it.key() + "=" + *it + " "; - s += ">\n"; - - int lastRow = -1; - bool needEnd = FALSE; - TQPtrListIterator it2( cells ); - while ( it2.current() ) { - TQTextTableCell *cell = it2.current(); - ++it2; - if ( lastRow != cell->row() ) { - if ( lastRow != -1 ) - s += "\n"; - s += ""; - lastRow = cell->row(); - needEnd = TRUE; - } - s += "attributes.begin(); - for ( ; it != cell->attributes.end(); ++it ) - s += " " + it.key() + "=" + *it; - s += ">"; - s += cell->richText()->richText(); - s += ""; - } - if ( needEnd ) - s += "\n"; - s += "
\n"; - return s; -} - -void TQTextTable::setParagraph(TQTextParagraph *p) -{ - for ( TQTextTableCell* cell = cells.first(); cell; cell = cells.next() ) - cell->richText()->parentPar = p; - TQTextCustomItem::setParagraph(p); -} - -void TQTextTable::adjustToPainter( TQPainter* p ) -{ - cellspacing = scale( us_cs, p ); - cellpadding = scale( us_cp, p ); - border = scale( us_b , p ); - innerborder = scale( us_ib, p ); - outerborder = scale( us_ob ,p ); - fixwidth = scale( us_fixwidth, p); - width = 0; - cachewidth = 0; - for ( TQTextTableCell* cell = cells.first(); cell; cell = cells.next() ) - cell->adjustToPainter( p ); -} - -void TQTextTable::adjustCells( int y , int shift ) -{ - TQPtrListIterator it( cells ); - TQTextTableCell* cell; - bool enlarge = FALSE; - while ( ( cell = it.current() ) ) { - ++it; - TQRect r = cell->geometry(); - if ( y <= r.top() ) { - r.moveBy(0, shift ); - cell->setGeometry( r ); - enlarge = TRUE; - } else if ( y <= r.bottom() ) { - r.rBottom() += shift; - cell->setGeometry( r ); - enlarge = TRUE; - } - } - if ( enlarge ) - height += shift; -} - -void TQTextTable::pageBreak( int yt, TQTextFlow* flow ) -{ - if ( flow->pageSize() <= 0 ) - return; - if ( layout && pageBreakFor > 0 && pageBreakFor != yt ) { - layout->invalidate(); - int h = layout->heightForWidth( width-2*outerborder ); - layout->setGeometry( TQRect(0, 0, width-2*outerborder, h) ); - height = layout->geometry().height()+2*outerborder; - } - pageBreakFor = yt; - TQPtrListIterator it( cells ); - TQTextTableCell* cell; - while ( ( cell = it.current() ) ) { - ++it; - int y = yt + outerborder + cell->geometry().y(); - int shift = flow->adjustFlow( y - cellspacing, width, cell->richText()->height() + 2*cellspacing ); - adjustCells( y - outerborder - yt, shift ); - } -} - - -void TQTextTable::draw(TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) -{ - if ( placement() != PlaceInline ) { - x = xpos; - y = ypos; - } - - for (TQTextTableCell* cell = cells.first(); cell; cell = cells.next() ) { - if ( ( cx < 0 && cy < 0 ) || - TQRect( cx, cy, cw, ch ).intersects( TQRect( x + outerborder + cell->geometry().x(), - y + outerborder + cell->geometry().y(), - cell->geometry().width(), cell->geometry().height() ) ) ) { - cell->draw( p, x+outerborder, y+outerborder, cx, cy, cw, ch, cg, selected ); - if ( border ) { - TQRect r( x+outerborder+cell->geometry().x() - innerborder, - y+outerborder+cell->geometry().y() - innerborder, - cell->geometry().width() + 2 * innerborder, - cell->geometry().height() + 2 * innerborder ); - if ( is_printer( p ) ) { - TQPen oldPen = p->pen(); - TQRect r2 = r; - r2.addCoords( innerborder/2, innerborder/2, -innerborder/2, -innerborder/2 ); - p->setPen( TQPen( cg.text(), innerborder ) ); - p->drawRect( r2 ); - p->setPen( oldPen ); - } else { - int s = TQMAX( cellspacing-2*innerborder, 0); - if ( s ) { - p->fillRect( r.left()-s, r.top(), s+1, r.height(), cg.button() ); - p->fillRect( r.right(), r.top(), s+1, r.height(), cg.button() ); - p->fillRect( r.left()-s, r.top()-s, r.width()+2*s, s, cg.button() ); - p->fillRect( r.left()-s, r.bottom(), r.width()+2*s, s, cg.button() ); - } - qDrawShadePanel( p, r, cg, TRUE, innerborder ); - } - } - } - } - if ( border ) { - TQRect r ( x, y, width, height ); - if ( is_printer( p ) ) { - TQRect r2 = r; - r2.addCoords( border/2, border/2, -border/2, -border/2 ); - TQPen oldPen = p->pen(); - p->setPen( TQPen( cg.text(), border ) ); - p->drawRect( r2 ); - p->setPen( oldPen ); - } else { - int s = border+TQMAX( cellspacing-2*innerborder, 0); - if ( s ) { - p->fillRect( r.left(), r.top(), s, r.height(), cg.button() ); - p->fillRect( r.right()-s, r.top(), s, r.height(), cg.button() ); - p->fillRect( r.left(), r.top(), r.width(), s, cg.button() ); - p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() ); - } - qDrawShadePanel( p, r, cg, FALSE, border ); - } - } - -} - -int TQTextTable::minimumWidth() const -{ - return fixwidth ? fixwidth : ((layout ? layout->minimumSize().width() : 0) + 2 * outerborder); -} - -void TQTextTable::resize( int nwidth ) -{ - if ( fixwidth && cachewidth != 0 ) - return; - if ( nwidth == cachewidth ) - return; - - - cachewidth = nwidth; - int w = nwidth; - - format( w ); - - if ( stretch ) - nwidth = nwidth * stretch / 100; - - width = nwidth; - layout->invalidate(); - int shw = layout->sizeHint().width() + 2*outerborder; - int mw = layout->minimumSize().width() + 2*outerborder; - if ( stretch ) - width = TQMAX( mw, nwidth ); - else - width = TQMAX( mw, TQMIN( nwidth, shw ) ); - - if ( fixwidth ) - width = fixwidth; - - layout->invalidate(); - mw = layout->minimumSize().width() + 2*outerborder; - width = TQMAX( width, mw ); - - int h = layout->heightForWidth( width-2*outerborder ); - layout->setGeometry( TQRect(0, 0, width-2*outerborder, h) ); - height = layout->geometry().height()+2*outerborder; -} - -void TQTextTable::format( int w ) -{ - for ( int i = 0; i < (int)cells.count(); ++i ) { - TQTextTableCell *cell = cells.at( i ); - TQRect r = cell->geometry(); - r.setWidth( w - 2*outerborder ); - cell->setGeometry( r ); - } -} - -void TQTextTable::addCell( TQTextTableCell* cell ) -{ - cells.append( cell ); - layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1, - cell->column(), cell->column() + cell->colspan()-1 ); -} - -bool TQTextTable::enter( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd ) -{ - currCell.remove( c ); - if ( !atEnd ) - return next( c, doc, parag, idx, ox, oy ); - currCell.insert( c, cells.count() ); - return prev( c, doc, parag, idx, ox, oy ); -} - -bool TQTextTable::enterAt( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, const TQPoint &pos ) -{ - currCell.remove( c ); - int lastCell = -1; - int lastY = -1; - int i; - for ( i = 0; i < (int)cells.count(); ++i ) { - TQTextTableCell *cell = cells.at( i ); - if ( !cell ) - continue; - TQRect r( cell->geometry().x(), - cell->geometry().y(), - cell->geometry().width() + 2 * innerborder + 2 * outerborder, - cell->geometry().height() + 2 * innerborder + 2 * outerborder ); - - if ( r.left() <= pos.x() && r.right() >= pos.x() ) { - if ( cell->geometry().y() > lastY ) { - lastCell = i; - lastY = cell->geometry().y(); - } - if ( r.top() <= pos.y() && r.bottom() >= pos.y() ) { - currCell.insert( c, i ); - break; - } - } - } - if ( i == (int) cells.count() ) - return FALSE; // no cell found - - if ( currCell.find( c ) == currCell.end() ) { - if ( lastY != -1 ) - currCell.insert( c, lastCell ); - else - return FALSE; - } - - TQTextTableCell *cell = cells.at( *currCell.find( c ) ); - if ( !cell ) - return FALSE; - doc = cell->richText(); - parag = doc->firstParagraph(); - idx = 0; - ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); - oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; - return TRUE; -} - -bool TQTextTable::next( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) -{ - int cc = -1; - if ( currCell.find( c ) != currCell.end() ) - cc = *currCell.find( c ); - if ( cc > (int)cells.count() - 1 || cc < 0 ) - cc = -1; - currCell.remove( c ); - currCell.insert( c, ++cc ); - if ( cc >= (int)cells.count() ) { - currCell.insert( c, 0 ); - TQTextCustomItem::next( c, doc, parag, idx, ox, oy ); - TQTextTableCell *cell = cells.first(); - if ( !cell ) - return FALSE; - doc = cell->richText(); - idx = -1; - return TRUE; - } - - if ( currCell.find( c ) == currCell.end() ) - return FALSE; - TQTextTableCell *cell = cells.at( *currCell.find( c ) ); - if ( !cell ) - return FALSE; - doc = cell->richText(); - parag = doc->firstParagraph(); - idx = 0; - ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); - oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; - return TRUE; -} - -bool TQTextTable::prev( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) -{ - int cc = -1; - if ( currCell.find( c ) != currCell.end() ) - cc = *currCell.find( c ); - if ( cc > (int)cells.count() - 1 || cc < 0 ) - cc = cells.count(); - currCell.remove( c ); - currCell.insert( c, --cc ); - if ( cc < 0 ) { - currCell.insert( c, 0 ); - TQTextCustomItem::prev( c, doc, parag, idx, ox, oy ); - TQTextTableCell *cell = cells.first(); - if ( !cell ) - return FALSE; - doc = cell->richText(); - idx = -1; - return TRUE; - } - - if ( currCell.find( c ) == currCell.end() ) - return FALSE; - TQTextTableCell *cell = cells.at( *currCell.find( c ) ); - if ( !cell ) - return FALSE; - doc = cell->richText(); - parag = doc->lastParagraph(); - idx = parag->length() - 1; - ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); - oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; - return TRUE; -} - -bool TQTextTable::down( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) -{ - if ( currCell.find( c ) == currCell.end() ) - return FALSE; - TQTextTableCell *cell = cells.at( *currCell.find( c ) ); - if ( cell->row_ == layout->numRows() - 1 ) { - currCell.insert( c, 0 ); - TQTextCustomItem::down( c, doc, parag, idx, ox, oy ); - TQTextTableCell *cell = cells.first(); - if ( !cell ) - return FALSE; - doc = cell->richText(); - idx = -1; - return TRUE; - } - - int oldRow = cell->row_; - int oldCol = cell->col_; - if ( currCell.find( c ) == currCell.end() ) - return FALSE; - int cc = *currCell.find( c ); - for ( int i = cc; i < (int)cells.count(); ++i ) { - cell = cells.at( i ); - if ( cell->row_ > oldRow && cell->col_ == oldCol ) { - currCell.insert( c, i ); - break; - } - } - doc = cell->richText(); - if ( !cell ) - return FALSE; - parag = doc->firstParagraph(); - idx = 0; - ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); - oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; - return TRUE; -} - -bool TQTextTable::up( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) -{ - if ( currCell.find( c ) == currCell.end() ) - return FALSE; - TQTextTableCell *cell = cells.at( *currCell.find( c ) ); - if ( cell->row_ == 0 ) { - currCell.insert( c, 0 ); - TQTextCustomItem::up( c, doc, parag, idx, ox, oy ); - TQTextTableCell *cell = cells.first(); - if ( !cell ) - return FALSE; - doc = cell->richText(); - idx = -1; - return TRUE; - } - - int oldRow = cell->row_; - int oldCol = cell->col_; - if ( currCell.find( c ) == currCell.end() ) - return FALSE; - int cc = *currCell.find( c ); - for ( int i = cc; i >= 0; --i ) { - cell = cells.at( i ); - if ( cell->row_ < oldRow && cell->col_ == oldCol ) { - currCell.insert( c, i ); - break; - } - } - doc = cell->richText(); - if ( !cell ) - return FALSE; - parag = doc->lastParagraph(); - idx = parag->length() - 1; - ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); - oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; - return TRUE; -} - -TQTextTableCell::TQTextTableCell( TQTextTable* table, - int row, int column, - const TQMap &attr, - const TQStyleSheetItem* /*style*/, // ### use them - const TQTextFormat& fmt, const TQString& context, - TQMimeSourceFactory &factory, TQStyleSheet *sheet, - const TQString& doc) -{ - cached_width = -1; - cached_sizehint = -1; - - maxw = TQWIDGETSIZE_MAX; - minw = 0; - - parent = table; - row_ = row; - col_ = column; - stretch_ = 0; - richtext = new TQTextDocument( table->parent ); - richtext->formatCollection()->setPaintDevice( table->parent->formatCollection()->paintDevice() ); - richtext->bodyText = fmt.color(); - richtext->setTableCell( this ); - TQString a = *attr.find( "align" ); - if ( !a.isEmpty() ) { - a = a.lower(); - if ( a == "left" ) - richtext->setAlignment( TQt::AlignLeft ); - else if ( a == "center" ) - richtext->setAlignment( TQt::AlignHCenter ); - else if ( a == "right" ) - richtext->setAlignment( TQt::AlignRight ); - } - align = 0; - TQString va = *attr.find( "valign" ); - if ( !va.isEmpty() ) { - va = va.lower(); - if ( va == "top" ) - align |= TQt::AlignTop; - else if ( va == "center" || va == "middle" ) - align |= TQt::AlignVCenter; - else if ( va == "bottom" ) - align |= TQt::AlignBottom; - } - richtext->setFormatter( table->parent->formatter() ); - richtext->setUseFormatCollection( table->parent->useFormatCollection() ); - richtext->setMimeSourceFactory( &factory ); - richtext->setStyleSheet( sheet ); - richtext->setRichText( doc, context, &fmt ); - rowspan_ = 1; - colspan_ = 1; - if ( attr.contains("colspan") ) - colspan_ = attr["colspan"].toInt(); - if ( attr.contains("rowspan") ) - rowspan_ = attr["rowspan"].toInt(); - - background = 0; - if ( attr.contains("bgcolor") ) { - background = new TQBrush(TQColor( attr["bgcolor"] )); - } - - - hasFixedWidth = FALSE; - if ( attr.contains("width") ) { - bool b; - TQString s( attr["width"] ); - int w = s.toInt( &b ); - if ( b ) { - maxw = w; - minw = maxw; - hasFixedWidth = TRUE; - } else { - s = s.stripWhiteSpace(); - if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) - stretch_ = s.left( s.length()-1).toInt(); - } - } - - attributes = attr; - - parent->addCell( this ); -} - -TQTextTableCell::~TQTextTableCell() -{ - delete background; - background = 0; - delete richtext; - richtext = 0; -} - -TQSize TQTextTableCell::sizeHint() const -{ - int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); - int used = richtext->widthUsed() + extra; - - if (stretch_ ) { - int w = parent->width * stretch_ / 100 - 2*parent->cellspacing - 2*parent->cellpadding; - return TQSize( TQMIN( w, maxw ), 0 ).expandedTo( minimumSize() ); - } - - return TQSize( used, 0 ).expandedTo( minimumSize() ); -} - -TQSize TQTextTableCell::minimumSize() const -{ - int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); - return TQSize( TQMAX( richtext->minimumWidth() + extra, minw), 0 ); -} - -TQSize TQTextTableCell::maximumSize() const -{ - return TQSize( maxw, TQWIDGETSIZE_MAX ); -} - -TQSizePolicy::ExpandData TQTextTableCell::expanding() const -{ - return TQSizePolicy::BothDirections; -} - -bool TQTextTableCell::isEmpty() const -{ - return FALSE; -} -void TQTextTableCell::setGeometry( const TQRect& r ) -{ - int extra = 2 * ( parent->innerborder + parent->cellpadding ); - if ( r.width() != cached_width ) - richtext->doLayout( TQTextFormat::painter(), r.width() - extra ); - cached_width = r.width(); - geom = r; -} - -TQRect TQTextTableCell::geometry() const -{ - return geom; -} - -bool TQTextTableCell::hasHeightForWidth() const -{ - return TRUE; -} - -int TQTextTableCell::heightForWidth( int w ) const -{ - int extra = 2 * ( parent->innerborder + parent->cellpadding ); - w = TQMAX( minw, w ); - - if ( cached_width != w ) { - TQTextTableCell* that = (TQTextTableCell*) this; - that->richtext->doLayout( TQTextFormat::painter(), w - extra ); - that->cached_width = w; - } - return richtext->height() + extra; -} - -void TQTextTableCell::adjustToPainter( TQPainter* p ) -{ - TQTextParagraph *parag = richtext->firstParagraph(); - while ( parag ) { - parag->adjustToPainter( p ); - parag = parag->next(); - } -} - -int TQTextTableCell::horizontalAlignmentOffset() const -{ - return parent->cellpadding; -} - -int TQTextTableCell::verticalAlignmentOffset() const -{ - if ( (align & TQt::AlignVCenter ) == TQt::AlignVCenter ) - return ( geom.height() - richtext->height() ) / 2; - else if ( ( align & TQt::AlignBottom ) == TQt::AlignBottom ) - return geom.height() - parent->cellpadding - richtext->height() ; - return parent->cellpadding; -} - -void TQTextTableCell::draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool ) -{ - if ( cached_width != geom.width() ) { - int extra = 2 * ( parent->innerborder + parent->cellpadding ); - richtext->doLayout( p, geom.width() - extra ); - cached_width = geom.width(); - } - TQColorGroup g( cg ); - if ( background ) - g.setBrush( TQColorGroup::Base, *background ); - else if ( richtext->paper() ) - g.setBrush( TQColorGroup::Base, *richtext->paper() ); - - p->save(); - p->translate( x + geom.x(), y + geom.y() ); - if ( background ) - p->fillRect( 0, 0, geom.width(), geom.height(), *background ); - else if ( richtext->paper() ) - p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() ); - - p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() ); - - TQRegion r; - if ( cx >= 0 && cy >= 0 ) - richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ), - cy - ( y + geom.y() + verticalAlignmentOffset() ), - cw, ch, g, FALSE, FALSE, 0 ); - else - richtext->draw( p, -1, -1, -1, -1, g, FALSE, FALSE, 0 ); - - p->restore(); -} -#endif - -#endif //TQT_NO_RICHTEXT diff --git a/src/kernel/qrichtext_p.cpp b/src/kernel/qrichtext_p.cpp deleted file mode 100644 index 022eb13de..000000000 --- a/src/kernel/qrichtext_p.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/**************************************************************************** -** -** Implementation of the internal TQt classes dealing with rich text -** -** Created : 990101 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qrichtext_p.h" - -#ifndef TQT_NO_RICHTEXT - -TQTextCommand::~TQTextCommand() {} -TQTextCommand::Commands TQTextCommand::type() const { return Invalid; } - - -#ifndef TQT_NO_TEXTCUSTOMITEM -TQTextCustomItem::~TQTextCustomItem() {} -void TQTextCustomItem::adjustToPainter( TQPainter* p){ if ( p ) width = 0; } -TQTextCustomItem::Placement TQTextCustomItem::placement() const { return PlaceInline; } - -bool TQTextCustomItem::ownLine() const { return FALSE; } -void TQTextCustomItem::resize( int nwidth ){ width = nwidth; } -void TQTextCustomItem::invalidate() {} - -bool TQTextCustomItem::isNested() const { return FALSE; } -int TQTextCustomItem::minimumWidth() const { return 0; } - -TQString TQTextCustomItem::richText() const { return TQString::null; } - -bool TQTextCustomItem::enter( TQTextCursor *, TQTextDocument*&, TQTextParagraph *&, int &, int &, int &, bool ) -{ - return TRUE; -} -bool TQTextCustomItem::enterAt( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int &, const TQPoint & ) -{ - return TRUE; -} -bool TQTextCustomItem::next( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) -{ - return TRUE; -} -bool TQTextCustomItem::prev( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) -{ - return TRUE; -} -bool TQTextCustomItem::down( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) -{ - return TRUE; -} -bool TQTextCustomItem::up( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) -{ - return TRUE; -} -#endif // TQT_NO_TEXTCUSTOMITEM - -void TQTextFlow::setPageSize( int ps ) { pagesize = ps; } -#ifndef TQT_NO_TEXTCUSTOMITEM -bool TQTextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); } -#else -bool TQTextFlow::isEmpty() { return TRUE; } -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM -void TQTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; } - -void TQTextTable::invalidate() { cachewidth = -1; } -#endif - -TQTextParagraphData::~TQTextParagraphData() {} -void TQTextParagraphData::join( TQTextParagraphData * ) {} - -TQTextFormatter::~TQTextFormatter() {} -void TQTextFormatter::setWrapEnabled( bool b ) { wrapEnabled = b; } -void TQTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; } - - - -int TQTextCursor::x() const -{ - if ( idx >= para->length() ) - return 0; - TQTextStringChar *c = para->at( idx ); - int curx = c->x; - if ( !c->rightToLeft && - c->c.isSpace() && - idx > 0 && - para->at( idx - 1 )->c != '\t' && - !c->lineStart && - ( para->alignment() & TQt::AlignJustify ) == TQt::AlignJustify ) - curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 ); - if ( c->rightToLeft ) - curx += para->string()->width( idx ); - return curx; -} - -int TQTextCursor::y() const -{ - int dummy, line; - para->lineStartOfChar( idx, &dummy, &line ); - return para->lineY( line ); -} - -int TQTextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); } -int TQTextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); } - -TQTextDocument *TQTextCursor::document() const -{ - return para ? para->document() : 0; -} - -void TQTextCursor::gotoPosition( TQTextParagraph* p, int index ) -{ - if ( para && p != para ) { - while ( !indices.isEmpty() && para->document() != p->document() ) - pop(); - Q_ASSERT( indices.isEmpty() || para->document() == p->document() ); - } - para = p; - if ( index < 0 || index >= para->length() ) { -#if defined(QT_CHECK_RANGE) - tqWarning( "TQTextCursor::gotoParagraph Index: %d out of range", index ); -#endif - if ( index < 0 || para->length() == 0 ) - index = 0; - else - index = para->length() - 1; - } - - tmpX = -1; - idx = index; - fixCursorPosition(); -} - -bool TQTextDocument::hasSelection( int id, bool visible ) const -{ - return ( selections.find( id ) != selections.end() && - ( !visible || - ( (TQTextDocument*)this )->selectionStartCursor( id ) != - ( (TQTextDocument*)this )->selectionEndCursor( id ) ) ); -} - -void TQTextDocument::setSelectionStart( int id, const TQTextCursor &cursor ) -{ - TQTextDocumentSelection sel; - sel.startCursor = cursor; - sel.endCursor = cursor; - sel.swapped = FALSE; - selections[ id ] = sel; -} - -TQTextParagraph *TQTextDocument::paragAt( int i ) const -{ - TQTextParagraph* p = curParag; - if ( !p || p->paragId() > i ) - p = fParag; - while ( p && p->paragId() != i ) - p = p->next(); - ((TQTextDocument*)this)->curParag = p; - return p; -} - - -TQTextFormat::~TQTextFormat() -{ -} - -TQTextFormat::TQTextFormat() - : fm( TQFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( tqApp->font().pointSize() ) -{ - ref = 0; - - usePixelSizes = FALSE; - if ( stdSize == -1 ) { - stdSize = tqApp->font().pixelSize(); - usePixelSizes = TRUE; - } - - missp = FALSE; - ha = AlignNormal; - collection = 0; -} - -TQTextFormat::TQTextFormat( const TQStyleSheetItem *style ) - : fm( TQFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( tqApp->font().pointSize() ) -{ - ref = 0; - - usePixelSizes = FALSE; - if ( stdSize == -1 ) { - stdSize = tqApp->font().pixelSize(); - usePixelSizes = TRUE; - } - - missp = FALSE; - ha = AlignNormal; - collection = 0; - fn = TQFont( style->fontFamily(), - style->fontSize(), - style->fontWeight(), - style->fontItalic() ); - fn.setUnderline( style->fontUnderline() ); - fn.setStrikeOut( style->fontStrikeOut() ); - col = style->color(); - fm = TQFontMetrics( fn ); - leftBearing = fm.minLeftBearing(); - rightBearing = fm.minRightBearing(); - hei = fm.lineSpacing(); - asc = fm.ascent() + (fm.leading()+1)/2; - dsc = fm.descent(); - missp = FALSE; - ha = AlignNormal; - memset( widths, 0, 256 ); - generateKey(); - addRef(); -} - -TQTextFormat::TQTextFormat( const TQFont &f, const TQColor &c, TQTextFormatCollection *parent ) - : fn( f ), col( c ), fm( TQFontMetrics( f ) ), linkColor( TRUE ), - logicalFontSize( 3 ), stdSize( f.pointSize() ) -{ - ref = 0; - usePixelSizes = FALSE; - if ( stdSize == -1 ) { - stdSize = f.pixelSize(); - usePixelSizes = TRUE; - } - collection = parent; - leftBearing = fm.minLeftBearing(); - rightBearing = fm.minRightBearing(); - hei = fm.lineSpacing(); - asc = fm.ascent() + (fm.leading()+1)/2; - dsc = fm.descent(); - missp = FALSE; - ha = AlignNormal; - memset( widths, 0, 256 ); - generateKey(); - addRef(); -} - -TQTextFormat::TQTextFormat( const TQTextFormat &f ) - : fm( f.fm ) -{ - ref = 0; - collection = 0; - fn = f.fn; - col = f.col; - leftBearing = f.leftBearing; - rightBearing = f.rightBearing; - memset( widths, 0, 256 ); - hei = f.hei; - asc = f.asc; - dsc = f.dsc; - stdSize = f.stdSize; - usePixelSizes = f.usePixelSizes; - logicalFontSize = f.logicalFontSize; - missp = f.missp; - ha = f.ha; - k = f.k; - linkColor = f.linkColor; - addRef(); -} - -TQTextFormat& TQTextFormat::operator=( const TQTextFormat &f ) -{ - ref = 0; - collection = f.collection; - fn = f.fn; - col = f.col; - fm = f.fm; - leftBearing = f.leftBearing; - rightBearing = f.rightBearing; - memset( widths, 0, 256 ); - hei = f.hei; - asc = f.asc; - dsc = f.dsc; - stdSize = f.stdSize; - usePixelSizes = f.usePixelSizes; - logicalFontSize = f.logicalFontSize; - missp = f.missp; - ha = f.ha; - k = f.k; - linkColor = f.linkColor; - addRef(); - return *this; -} - -void TQTextFormat::update() -{ - fm = TQFontMetrics( fn ); - leftBearing = fm.minLeftBearing(); - rightBearing = fm.minRightBearing(); - hei = fm.lineSpacing(); - asc = fm.ascent() + (fm.leading()+1)/2; - dsc = fm.descent(); - memset( widths, 0, 256 ); - generateKey(); -} - - -TQPainter* TQTextFormat::pntr = 0; -TQFontMetrics* TQTextFormat::pntr_fm = 0; -int TQTextFormat::pntr_ldg=-1; -int TQTextFormat::pntr_asc=-1; -int TQTextFormat::pntr_hei=-1; -int TQTextFormat::pntr_dsc=-1; - -void TQTextFormat::cleanupPrivateData() { - delete TQTextFormat::pntr_fm; - TQTextFormat::pntr_fm = 0; - TQTextFormat::pntr = 0; - - // Not really necessary, but better to tidy-up everything - TQTextFormat::pntr_fm = 0; - TQTextFormat::pntr_ldg=-1; - TQTextFormat::pntr_asc=-1; - TQTextFormat::pntr_hei=-1; - TQTextFormat::pntr_dsc=-1; -} - -void TQTextFormat::setPainter( TQPainter *p ) -{ - pntr = p; -} - -TQPainter* TQTextFormat::painter() -{ - return pntr; -} - -void TQTextFormat::applyFont( const TQFont &f ) -{ - TQFontMetrics fm( pntr->fontMetrics() ); - - if ( !pntr_fm ) { - tqAddPostRoutine( &TQTextFormat::cleanupPrivateData ); - } - - if ( !pntr_fm - || pntr_fm->painter != pntr - || pntr_fm->d != fm.d - || !pntr->font().isCopyOf( f ) - ) { - pntr->setFont( f ); - delete pntr_fm; - pntr_fm = new TQFontMetrics( pntr->fontMetrics() ); - pntr_ldg = pntr_fm->leading(); - pntr_asc = pntr_fm->ascent()+(pntr_ldg+1)/2; - pntr_hei = pntr_fm->lineSpacing(); - pntr_dsc = -1; - } -} - -int TQTextFormat::minLeftBearing() const -{ - if ( !pntr || !pntr->isActive() ) - return leftBearing; - applyFont( fn ); - return pntr_fm->minLeftBearing(); -} - -int TQTextFormat::minRightBearing() const -{ - if ( !pntr || !pntr->isActive() ) - return rightBearing; - applyFont( fn ); - return pntr_fm->minRightBearing(); -} - -int TQTextFormat::height() const -{ - if ( !pntr || !pntr->isActive() ) - return hei; - applyFont( fn ); - return pntr_hei; -} - -int TQTextFormat::ascent() const -{ - if ( !pntr || !pntr->isActive() ) - return asc; - applyFont( fn ); - return pntr_asc; -} - -int TQTextFormat::descent() const -{ - if ( !pntr || !pntr->isActive() ) - return dsc; - applyFont( fn ); - if ( pntr_dsc < 0 ) - pntr_dsc = pntr_fm->descent(); - return pntr_dsc; -} - -int TQTextFormat::leading() const -{ - if ( !pntr || !pntr->isActive() ) - return fm.leading(); - applyFont( fn ); - return pntr_ldg; -} - -void TQTextFormat::generateKey() -{ - k = getKey( fn, col, isMisspelled(), vAlign() ); -} - -TQString TQTextFormat::getKey( const TQFont &fn, const TQColor &col, bool misspelled, VerticalAlignment a ) -{ - TQString k = fn.key(); - k += '/'; - k += TQString::number( (uint)col.rgb() ); - k += '/'; - k += TQString::number( (int)misspelled ); - k += '/'; - k += TQString::number( (int)a ); - return k; -} - -TQString TQTextString::toString( const TQMemArray &data ) -{ - TQString s; - int l = data.size(); - s.setUnicode( 0, l ); - TQTextStringChar *c = data.data(); - TQChar *uc = (TQChar *)s.unicode(); - while ( l-- ) - *(uc++) = (c++)->c; - - return s; -} - -void TQTextParagraph::setSelection( int id, int start, int end ) -{ - TQMap::ConstIterator it = selections().find( id ); - if ( it != mSelections->end() ) { - if ( start == ( *it ).start && end == ( *it ).end ) - return; - } - - TQTextParagraphSelection sel; - sel.start = start; - sel.end = end; - (*mSelections)[ id ] = sel; - setChanged( TRUE, TRUE ); -} - -void TQTextParagraph::removeSelection( int id ) -{ - if ( !hasSelection( id ) ) - return; - if ( mSelections ) - mSelections->remove( id ); - setChanged( TRUE, TRUE ); -} - -int TQTextParagraph::selectionStart( int id ) const -{ - if ( !mSelections ) - return -1; - TQMap::ConstIterator it = mSelections->find( id ); - if ( it == mSelections->end() ) - return -1; - return ( *it ).start; -} - -int TQTextParagraph::selectionEnd( int id ) const -{ - if ( !mSelections ) - return -1; - TQMap::ConstIterator it = mSelections->find( id ); - if ( it == mSelections->end() ) - return -1; - return ( *it ).end; -} - -bool TQTextParagraph::hasSelection( int id ) const -{ - return mSelections ? mSelections->contains( id ) : FALSE; -} - -bool TQTextParagraph::fullSelected( int id ) const -{ - if ( !mSelections ) - return FALSE; - TQMap::ConstIterator it = mSelections->find( id ); - if ( it == mSelections->end() ) - return FALSE; - return ( *it ).start == 0 && ( *it ).end == str->length() - 1; -} - -int TQTextParagraph::lineY( int l ) const -{ - if ( l > (int)lineStarts.count() - 1 ) { - tqWarning( "TQTextParagraph::lineY: line %d out of range!", l ); - return 0; - } - - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - TQMap::ConstIterator it = lineStarts.begin(); - while ( l-- > 0 ) - ++it; - return ( *it )->y; -} - -int TQTextParagraph::lineBaseLine( int l ) const -{ - if ( l > (int)lineStarts.count() - 1 ) { - tqWarning( "TQTextParagraph::lineBaseLine: line %d out of range!", l ); - return 10; - } - - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - TQMap::ConstIterator it = lineStarts.begin(); - while ( l-- > 0 ) - ++it; - return ( *it )->baseLine; -} - -int TQTextParagraph::lineHeight( int l ) const -{ - if ( l > (int)lineStarts.count() - 1 ) { - tqWarning( "TQTextParagraph::lineHeight: line %d out of range!", l ); - return 15; - } - - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - TQMap::ConstIterator it = lineStarts.begin(); - while ( l-- > 0 ) - ++it; - return ( *it )->h; -} - -void TQTextParagraph::lineInfo( int l, int &y, int &h, int &bl ) const -{ - if ( l > (int)lineStarts.count() - 1 ) { - tqWarning( "TQTextParagraph::lineInfo: line %d out of range!", l ); - tqDebug( "%d %d", (int)lineStarts.count() - 1, l ); - y = 0; - h = 15; - bl = 10; - return; - } - - if ( !isValid() ) - ( (TQTextParagraph*)this )->format(); - - TQMap::ConstIterator it = lineStarts.begin(); - while ( l-- > 0 ) - ++it; - y = ( *it )->y; - h = ( *it )->h; - bl = ( *it )->baseLine; -} - - -void TQTextParagraph::setAlignment( int a ) -{ - if ( a == (int)align ) - return; - align = a; - invalidate( 0 ); -} - -TQTextFormatter *TQTextParagraph::formatter() const -{ - if ( hasdoc ) - return document()->formatter(); - if ( pseudoDocument()->pFormatter ) - return pseudoDocument()->pFormatter; - return ( ( (TQTextParagraph*)this )->pseudoDocument()->pFormatter = new TQTextFormatterBreakWords ); -} - -void TQTextParagraph::setTabArray( int *a ) -{ - delete [] tArray; - tArray = a; -} - -void TQTextParagraph::setTabStops( int tw ) -{ - if ( hasdoc ) - document()->setTabStops( tw ); - else - tabStopWidth = tw; -} - -TQMap &TQTextParagraph::selections() const -{ - if ( !mSelections ) - ((TQTextParagraph *)this)->mSelections = new TQMap; - return *mSelections; -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -TQPtrList &TQTextParagraph::floatingItems() const -{ - if ( !mFloatingItems ) - ((TQTextParagraph *)this)->mFloatingItems = new TQPtrList; - return *mFloatingItems; -} -#endif - -TQTextStringChar::~TQTextStringChar() -{ - if ( format() ) - format()->removeRef(); - if ( type ) // not Regular - delete d.custom; -} - -TQTextParagraphPseudoDocument::TQTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0),collection(){} -TQTextParagraphPseudoDocument::~TQTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; } - - -#endif //TQT_NO_RICHTEXT diff --git a/src/kernel/qrichtext_p.h b/src/kernel/qrichtext_p.h deleted file mode 100644 index 1032c74eb..000000000 --- a/src/kernel/qrichtext_p.h +++ /dev/null @@ -1,2142 +0,0 @@ -/**************************************************************************** -** -** Definition of internal rich text classes -** -** Created : 990124 -** -** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQRICHTEXT_P_H -#define TQRICHTEXT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of a number of TQt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqstring.h" -#include "tqptrlist.h" -#include "tqrect.h" -#include "tqfontmetrics.h" -#include "tqintdict.h" -#include "tqmap.h" -#include "tqstringlist.h" -#include "tqfont.h" -#include "tqcolor.h" -#include "tqsize.h" -#include "tqvaluelist.h" -#include "tqvaluestack.h" -#include "tqobject.h" -#include "tqdict.h" -#include "tqpixmap.h" -#include "tqstylesheet.h" -#include "tqptrvector.h" -#include "tqpainter.h" -#include "tqlayout.h" -#include "tqobject.h" -#include "ntqapplication.h" -#endif // QT_H - -#ifndef TQT_NO_RICHTEXT - -class TQTextDocument; -class TQTextString; -class TQTextPreProcessor; -class TQTextFormat; -class TQTextCursor; -class TQTextParagraph; -class TQTextFormatter; -class TQTextIndent; -class TQTextFormatCollection; -class TQStyleSheetItem; -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQTextCustomItem; -#endif -class TQTextFlow; -struct TQBidiContext; - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextStringChar -{ - friend class TQTextString; - -public: - // this is never called, initialize variables in TQTextString::insert()!!! - TQTextStringChar() : nobreak(FALSE), lineStart( 0 ), type( Regular ) {d.format=0;} - ~TQTextStringChar(); - - struct CustomData - { - TQTextFormat *format; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextCustomItem *custom; -#endif - TQString anchorName; - TQString anchorHref; - }; - enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 }; - - TQChar c; - // this is the same struct as in tqtextengine_p.h. Don't change! - uchar softBreak :1; // Potential linebreak point - uchar whiteSpace :1; // A unicode whitespace character, except NBSP, ZWNBSP - uchar charStop :1; // Valid cursor position (for left/right arrow) - uchar wordStop :1; // Valid cursor position (for ctrl + left/right arrow) - uchar nobreak :1; - - uchar lineStart : 1; - uchar /*Type*/ type : 2; - uchar bidiLevel :7; - uchar rightToLeft : 1; - - int x; - union { - TQTextFormat* format; - CustomData* custom; - } d; - - - int height() const; - int ascent() const; - int descent() const; - bool isCustom() const { return (type & Custom) != 0; } - TQTextFormat *format() const; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextCustomItem *customItem() const; -#endif - void setFormat( TQTextFormat *f ); -#ifndef TQT_NO_TEXTCUSTOMITEM - void setCustomItem( TQTextCustomItem *i ); -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM - void loseCustomItem(); -#endif - - - bool isAnchor() const { return ( type & Anchor) != 0; } - bool isLink() const { return isAnchor() && !!d.custom->anchorHref; } - TQString anchorName() const; - TQString anchorHref() const; - void setAnchor( const TQString& name, const TQString& href ); - -private: - TQTextStringChar &operator=( const TQTextStringChar & ) { - //abort(); - return *this; - } - TQTextStringChar( const TQTextStringChar & ) { - } - friend class TQTextParagraph; -}; - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMemArray; -// MOC_SKIP_END -#endif - -class TQ_EXPORT TQTextString -{ -public: - - TQTextString(); - TQTextString( const TQTextString &s ); - virtual ~TQTextString(); - - static TQString toString( const TQMemArray &data ); - TQString toString() const; - - inline TQTextStringChar &at( int i ) const { return data[ i ]; } - inline int length() const { return data.size(); } - - int width( int idx ) const; - - void insert( int index, const TQString &s, TQTextFormat *f ); - void insert( int index, const TQChar *unicode, int len, TQTextFormat *f ); - void insert( int index, TQTextStringChar *c, bool doAddRefFormat = FALSE ); - void truncate( int index ); - void remove( int index, int len ); - void clear(); - - void setFormat( int index, TQTextFormat *f, bool useCollection ); - - void setBidi( bool b ) { bidi = b; } - bool isBidi() const; - bool isRightToLeft() const; - TQChar::Direction direction() const; - void setDirection( TQChar::Direction d ) { dir = d; bidiDirty = TRUE; } - - TQMemArray rawData() const { return data.copy(); } - - void operator=( const TQString &s ) { clear(); insert( 0, s, 0 ); } - void operator+=( const TQString &s ) { insert( length(), s, 0 ); } - void prepend( const TQString &s ) { insert( 0, s, 0 ); } - int appendParagraphs( TQTextParagraph *start, TQTextParagraph *end ); - - // return next and previous valid cursor positions. - bool validCursorPosition( int idx ); - int nextCursorPosition( int idx ); - int previousCursorPosition( int idx ); - -private: - void checkBidi() const; - - TQMemArray data; - TQString stringCache; - uint bidiDirty : 1; - uint bidi : 1; // true when the paragraph has right to left characters - uint rightToLeft : 1; - uint dir : 5; -}; - -inline bool TQTextString::isBidi() const -{ - if ( bidiDirty ) - checkBidi(); - return bidi; -} - -inline bool TQTextString::isRightToLeft() const -{ - if ( bidiDirty ) - checkBidi(); - return rightToLeft; -} - -inline TQString TQTextString::toString() const -{ - if(bidiDirty) - checkBidi(); - return stringCache; -} - -inline TQChar::Direction TQTextString::direction() const -{ - return (TQChar::Direction) dir; -} - -inline int TQTextString::nextCursorPosition( int next ) -{ - if ( bidiDirty ) - checkBidi(); - - const TQTextStringChar *c = data.data(); - int len = length(); - - if ( next < len - 1 ) { - next++; - while ( next < len - 1 && !c[next].charStop ) - next++; - } - return next; -} - -inline int TQTextString::previousCursorPosition( int prev ) -{ - if ( bidiDirty ) - checkBidi(); - - const TQTextStringChar *c = data.data(); - - if ( prev ) { - prev--; - while ( prev && !c[prev].charStop ) - prev--; - } - return prev; -} - -inline bool TQTextString::validCursorPosition( int idx ) -{ - if ( bidiDirty ) - checkBidi(); - - return (at( idx ).charStop); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueStack; -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueStack; -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueStack; -// MOC_SKIP_END -#endif - -class TQ_EXPORT TQTextCursor -{ -public: - TQTextCursor( TQTextDocument *d = 0 ); - TQTextCursor( const TQTextCursor &c ); - TQTextCursor &operator=( const TQTextCursor &c ); - virtual ~TQTextCursor() {} - - bool operator==( const TQTextCursor &c ) const; - bool operator!=( const TQTextCursor &c ) const { return !(*this == c); } - - inline TQTextParagraph *paragraph() const { return para; } - - TQTextDocument *document() const; - int index() const; - - void gotoPosition( TQTextParagraph* p, int index = 0); - void setIndex( int index ) { gotoPosition(paragraph(), index ); } - void setParagraph( TQTextParagraph*p ) { gotoPosition(p, 0 ); } - - void gotoLeft(); - void gotoRight(); - void gotoNextLetter(); - void gotoPreviousLetter(); - void gotoUp(); - void gotoDown(); - void gotoLineEnd(); - void gotoLineStart(); - void gotoHome(); - void gotoEnd(); - void gotoPageUp( int visibleHeight ); - void gotoPageDown( int visibleHeight ); - void gotoNextWord( bool onlySpace = FALSE ); - void gotoPreviousWord( bool onlySpace = FALSE ); - void gotoWordLeft(); - void gotoWordRight(); - - void insert( const TQString &s, bool checkNewLine, TQMemArray *formatting = 0 ); - void splitAndInsertEmptyParagraph( bool ind = TRUE, bool updateIds = TRUE ); - bool remove(); - bool removePreviousChar(); - void indent(); - - bool atParagStart(); - bool atParagEnd(); - - int x() const; // x in current paragraph - int y() const; // y in current paragraph - - int globalX() const; - int globalY() const; - - TQTextParagraph *topParagraph() const { return paras.isEmpty() ? para : paras.first(); } - int offsetX() const { return ox; } // inner document offset - int offsetY() const { return oy; } // inner document offset - int totalOffsetX() const; // total document offset - int totalOffsetY() const; // total document offset - - bool place( const TQPoint &pos, TQTextParagraph *s ) { return place( pos, s, FALSE ); } - bool place( const TQPoint &pos, TQTextParagraph *s, bool link ) { return place( pos, s, link, TRUE, TRUE ); } - bool place( const TQPoint &pos, TQTextParagraph *s, bool link, bool loosePlacing, bool matchBetweenCharacters ); - void restoreState(); - - - int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast - void oneUp() { if ( !indices.isEmpty() ) pop(); } - void setValid( bool b ) { valid = b; } - bool isValid() const { return valid; } - - void fixCursorPosition(); -private: - enum Operation { EnterBegin, EnterEnd, Next, Prev, Up, Down }; - - void push(); - void pop(); - bool processNesting( Operation op ); - void invalidateNested(); - void gotoIntoNested( const TQPoint &globalPos ); - - TQTextParagraph *para; - int idx, tmpX; - int ox, oy; - TQValueStack indices; - TQValueStack paras; - TQValueStack xOffsets; - TQValueStack yOffsets; - uint valid : 1; - -}; - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextCommand -{ -public: - enum Commands { Invalid, Insert, Delete, Format, Style }; - - TQTextCommand( TQTextDocument *d ) : doc( d ), cursor( d ) {} - virtual ~TQTextCommand(); - - virtual Commands type() const; - - virtual TQTextCursor *execute( TQTextCursor *c ) = 0; - virtual TQTextCursor *unexecute( TQTextCursor *c ) = 0; - -protected: - TQTextDocument *doc; - TQTextCursor cursor; - -}; - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; -// MOC_SKIP_END -#endif - -class TQ_EXPORT TQTextCommandHistory -{ -public: - TQTextCommandHistory( int s ) : current( -1 ), steps( s ) { history.setAutoDelete( TRUE ); } - virtual ~TQTextCommandHistory(); - - void clear() { history.clear(); current = -1; } - - void addCommand( TQTextCommand *cmd ); - TQTextCursor *undo( TQTextCursor *c ); - TQTextCursor *redo( TQTextCursor *c ); - - bool isUndoAvailable(); - bool isRedoAvailable(); - - void setUndoDepth( int d ) { steps = d; } - int undoDepth() const { return steps; } - - int historySize() const { return history.count(); } - int currentPosition() const { return current; } - -private: - TQPtrList history; - int current, steps; - -}; - -inline TQTextCommandHistory::~TQTextCommandHistory() -{ - clear(); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQ_EXPORT TQTextCustomItem -{ -public: - TQTextCustomItem( TQTextDocument *p ) - : xpos(0), ypos(-1), width(-1), height(0), parent( p ) - {} - virtual ~TQTextCustomItem(); - virtual void draw(TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) = 0; - - virtual void adjustToPainter( TQPainter* ); - - enum Placement { PlaceInline = 0, PlaceLeft, PlaceRight }; - virtual Placement placement() const; - bool placeInline() { return placement() == PlaceInline; } - - virtual bool ownLine() const; - virtual void resize( int nwidth ); - virtual void invalidate(); - virtual int ascent() const { return height; } - - virtual bool isNested() const; - virtual int minimumWidth() const; - - virtual TQString richText() const; - - int xpos; // used for floating items - int ypos; // used for floating items - int width; - int height; - - TQRect geometry() const { return TQRect( xpos, ypos, width, height ); } - - virtual bool enter( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); - virtual bool enterAt( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, const TQPoint & ); - virtual bool next( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - virtual bool prev( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - virtual bool down( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - virtual bool up( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - - virtual void setParagraph( TQTextParagraph *p ) { parag = p; } - TQTextParagraph *paragraph() const { return parag; } - - TQTextDocument *parent; - TQTextParagraph *parag; - - virtual void pageBreak( int y, TQTextFlow* flow ); -}; -#endif - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -//Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -// MOC_SKIP_END -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQ_EXPORT TQTextImage : public TQTextCustomItem -{ -public: - TQTextImage( TQTextDocument *p, const TQMap &attr, const TQString& context, - TQMimeSourceFactory &factory ); - virtual ~TQTextImage(); - - Placement placement() const { return place; } - void adjustToPainter( TQPainter* ); - int minimumWidth() const { return width; } - - TQString richText() const; - - void draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); - -private: - TQRegion* reg; - TQPixmap pm; - Placement place; - int tmpwidth, tmpheight; - TQMap attributes; - TQString imgId; - -}; -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQ_EXPORT TQTextHorizontalLine : public TQTextCustomItem -{ -public: - TQTextHorizontalLine( TQTextDocument *p, const TQMap &attr, const TQString& context, - TQMimeSourceFactory &factory ); - virtual ~TQTextHorizontalLine(); - - void adjustToPainter( TQPainter* ); - void draw(TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); - TQString richText() const; - - bool ownLine() const { return TRUE; } - -private: - int tmpheight; - TQColor color; - bool shade; - -}; -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; -// MOC_SKIP_END -#endif -#endif - -class TQ_EXPORT TQTextFlow -{ - friend class TQTextDocument; -#ifndef TQT_NO_TEXTCUSTOMITEM - friend class TQTextTableCell; -#endif - -public: - TQTextFlow(); - virtual ~TQTextFlow(); - - virtual void setWidth( int width ); - int width() const; - - virtual void setPageSize( int ps ); - int pageSize() const { return pagesize; } - - virtual int adjustLMargin( int yp, int h, int margin, int space ); - virtual int adjustRMargin( int yp, int h, int margin, int space ); - -#ifndef TQT_NO_TEXTCUSTOMITEM - virtual void registerFloatingItem( TQTextCustomItem* item ); - virtual void unregisterFloatingItem( TQTextCustomItem* item ); -#endif - virtual TQRect boundingRect() const; - virtual void drawFloatingItems(TQPainter* p, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); - - virtual int adjustFlow( int y, int w, int h ); // adjusts y according to the defined pagesize. Returns the shift. - - virtual bool isEmpty(); - - void clear(); - -private: - int w; - int pagesize; - -#ifndef TQT_NO_TEXTCUSTOMITEM - TQPtrList leftItems; - TQPtrList rightItems; -#endif -}; - -inline int TQTextFlow::width() const { return w; } - -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQTextTable; - -class TQ_EXPORT TQTextTableCell : public TQLayoutItem -{ - friend class TQTextTable; - -public: - TQTextTableCell( TQTextTable* table, - int row, int column, - const TQMap &attr, - const TQStyleSheetItem* style, - const TQTextFormat& fmt, const TQString& context, - TQMimeSourceFactory &factory, TQStyleSheet *sheet, const TQString& doc ); - virtual ~TQTextTableCell(); - - TQSize sizeHint() const ; - TQSize minimumSize() const ; - TQSize maximumSize() const ; - TQSizePolicy::ExpandData expanding() const; - bool isEmpty() const; - void setGeometry( const TQRect& ) ; - TQRect geometry() const; - - bool hasHeightForWidth() const; - int heightForWidth( int ) const; - - void adjustToPainter( TQPainter* ); - - int row() const { return row_; } - int column() const { return col_; } - int rowspan() const { return rowspan_; } - int colspan() const { return colspan_; } - int stretch() const { return stretch_; } - - TQTextDocument* richText() const { return richtext; } - TQTextTable* table() const { return parent; } - - void draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); - - TQBrush *backGround() const { return background; } - virtual void invalidate(); - - int verticalAlignmentOffset() const; - int horizontalAlignmentOffset() const; - -private: - TQRect geom; - TQTextTable* parent; - TQTextDocument* richtext; - int row_; - int col_; - int rowspan_; - int colspan_; - int stretch_; - int maxw; - int minw; - bool hasFixedWidth; - TQBrush *background; - int cached_width; - int cached_sizehint; - TQMap attributes; - int align; -}; -#endif - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -// MOC_SKIP_END -#endif - -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQ_EXPORT TQTextTable: public TQTextCustomItem -{ - friend class TQTextTableCell; - -public: - TQTextTable( TQTextDocument *p, const TQMap &attr ); - virtual ~TQTextTable(); - - void adjustToPainter( TQPainter *p ); - void pageBreak( int y, TQTextFlow* flow ); - void draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, - const TQColorGroup& cg, bool selected ); - - bool noErase() const { return TRUE; } - bool ownLine() const { return TRUE; } - Placement placement() const { return place; } - bool isNested() const { return TRUE; } - void resize( int nwidth ); - virtual void invalidate(); - - virtual bool enter( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); - virtual bool enterAt( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, const TQPoint &pos ); - virtual bool next( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - virtual bool prev( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - virtual bool down( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - virtual bool up( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); - - TQString richText() const; - - int minimumWidth() const; - - TQPtrList tableCells() const { return cells; } - - bool isStretching() const { return stretch; } - void setParagraph(TQTextParagraph *p); - -private: - void format( int w ); - void addCell( TQTextTableCell* cell ); - -private: - TQGridLayout* layout; - TQPtrList cells; - int cachewidth; - int fixwidth; - int cellpadding; - int cellspacing; - int border; - int outerborder; - int stretch; - int innerborder; - int us_cp, us_ib, us_b, us_ob, us_cs; - int us_fixwidth; - TQMap attributes; - TQMap currCell; - Placement place; - void adjustCells( int y , int shift ); - int pageBreakFor; -}; -#endif -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#ifndef TQT_NO_TEXTCUSTOMITEM -class TQTextTableCell; -class TQTextParagraph; -#endif - -struct TQ_EXPORT TQTextDocumentSelection -{ - TQTextCursor startCursor, endCursor; - bool swapped; - TQ_DUMMY_COMPARISON_OPERATOR(TQTextDocumentSelection) -}; - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -//Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; -// MOC_SKIP_END -#endif - -class TQ_EXPORT TQTextDocument : public TQObject -{ - TQ_OBJECT - -#ifndef TQT_NO_TEXTCUSTOMITEM - friend class TQTextTableCell; -#endif - friend class TQTextCursor; - friend class TQTextEdit; - friend class TQTextParagraph; - friend class TQTextTable; - -public: - enum SelectionIds { - Standard = 0, - IMSelectionText = 31998, - IMCompositionText = 31999, // this must be higher! - Temp = 32000 // This selection must not be drawn, it's used e.g. by undo/redo to - // remove multiple lines with removeSelectedText() - }; - - TQTextDocument( TQTextDocument *p ); - virtual ~TQTextDocument(); - - TQTextDocument *parent() const { return par; } - TQTextParagraph *parentParagraph() const { return parentPar; } - - void setText( const TQString &text, const TQString &context ); - TQMap attributes() const { return attribs; } - void setAttributes( const TQMap &attr ) { attribs = attr; } - - TQString text() const; - TQString text( int parag ) const; - TQString originalText() const; - - int x() const; - int y() const; - int width() const; - int widthUsed() const; - int visibleWidth() const; - int height() const; - void setWidth( int w ); - int minimumWidth() const; - bool setMinimumWidth( int needed, int used = -1, TQTextParagraph *parag = 0 ); - - void setY( int y ); - int leftMargin() const; - void setLeftMargin( int lm ); - int rightMargin() const; - void setRightMargin( int rm ); - - TQTextParagraph *firstParagraph() const; - TQTextParagraph *lastParagraph() const; - void setFirstParagraph( TQTextParagraph *p ); - void setLastParagraph( TQTextParagraph *p ); - - void invalidate(); - - void setPreProcessor( TQTextPreProcessor *sh ); - TQTextPreProcessor *preProcessor() const; - - void setFormatter( TQTextFormatter *f ); - TQTextFormatter *formatter() const; - - void setIndent( TQTextIndent *i ); - TQTextIndent *indent() const; - - TQColor selectionColor( int id ) const; - bool invertSelectionText( int id ) const; - void setSelectionColor( int id, const TQColor &c ); - void setInvertSelectionText( int id, bool b ); - bool hasSelection( int id, bool visible = FALSE ) const; - void setSelectionStart( int id, const TQTextCursor &cursor ); - bool setSelectionEnd( int id, const TQTextCursor &cursor ); - void selectAll( int id ); - bool removeSelection( int id ); - void selectionStart( int id, int ¶gId, int &index ); - TQTextCursor selectionStartCursor( int id ); - TQTextCursor selectionEndCursor( int id ); - void selectionEnd( int id, int ¶gId, int &index ); - void setFormat( int id, TQTextFormat *f, int flags ); - int numSelections() const { return nSelections; } - void addSelection( int id ); - - TQString selectedText( int id, bool asRichText = FALSE ) const; - void removeSelectedText( int id, TQTextCursor *cursor ); - void indentSelection( int id ); - - TQTextParagraph *paragAt( int i ) const; - - void addCommand( TQTextCommand *cmd ); - TQTextCursor *undo( TQTextCursor *c = 0 ); - TQTextCursor *redo( TQTextCursor *c = 0 ); - TQTextCommandHistory *commands() const { return commandHistory; } - - TQTextFormatCollection *formatCollection() const; - - bool find( TQTextCursor &cursor, const TQString &expr, bool cs, bool wo, bool forward); - - void setTextFormat( TQt::TextFormat f ); - TQt::TextFormat textFormat() const; - - bool inSelection( int selId, const TQPoint &pos ) const; - - TQStyleSheet *styleSheet() const { return sheet_; } -#ifndef TQT_NO_MIME - TQMimeSourceFactory *mimeSourceFactory() const { return factory_; } -#endif - TQString context() const { return contxt; } - - void setStyleSheet( TQStyleSheet *s ); - void setDefaultFormat( const TQFont &font, const TQColor &color ); -#ifndef TQT_NO_MIME - void setMimeSourceFactory( TQMimeSourceFactory *f ) { if ( f ) factory_ = f; } -#endif - void setContext( const TQString &c ) { if ( !c.isEmpty() ) contxt = c; } - - void setUnderlineLinks( bool b ); - bool underlineLinks() const { return underlLinks; } - - void setPaper( TQBrush *brush ) { if ( backBrush ) delete backBrush; backBrush = brush; } - TQBrush *paper() const { return backBrush; } - - void doLayout( TQPainter *p, int w ); - void draw( TQPainter *p, const TQRect& rect, const TQColorGroup &cg, const TQBrush *paper = 0 ); - bool useDoubleBuffer( TQTextParagraph *parag, TQPainter *p ); - - void drawParagraph( TQPainter *p, TQTextParagraph *parag, int cx, int cy, int cw, int ch, - TQPixmap *&doubleBuffer, const TQColorGroup &cg, - bool drawCursor, TQTextCursor *cursor, bool resetChanged = TRUE ); - TQTextParagraph *draw( TQPainter *p, int cx, int cy, int cw, int ch, const TQColorGroup &cg, - bool onlyChanged = FALSE, bool drawCursor = FALSE, TQTextCursor *cursor = 0, - bool resetChanged = TRUE ); - -#ifndef TQT_NO_TEXTCUSTOMITEM - void registerCustomItem( TQTextCustomItem *i, TQTextParagraph *p ); - void unregisterCustomItem( TQTextCustomItem *i, TQTextParagraph *p ); -#endif - - void setFlow( TQTextFlow *f ); - void takeFlow(); - TQTextFlow *flow() const { return flow_; } - bool isPageBreakEnabled() const { return pages; } - void setPageBreakEnabled( bool b ) { pages = b; } - - void setUseFormatCollection( bool b ) { useFC = b; } - bool useFormatCollection() const { return useFC; } - -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextTableCell *tableCell() const { return tc; } - void setTableCell( TQTextTableCell *c ) { tc = c; } -#endif - - void setPlainText( const TQString &text ); - void setRichText( const TQString &text, const TQString &context, const TQTextFormat *initialFormat = 0 ); - TQString richText() const; - TQString plainText() const; - - bool focusNextPrevChild( bool next ); - - int alignment() const; - void setAlignment( int a ); - - int *tabArray() const; - int tabStopWidth() const; - void setTabArray( int *a ); - void setTabStops( int tw ); - - void setUndoDepth( int d ) { commandHistory->setUndoDepth( d ); } - int undoDepth() const { return commandHistory->undoDepth(); } - - int length() const; - void clear( bool createEmptyParag = FALSE ); - - virtual TQTextParagraph *createParagraph( TQTextDocument *d, TQTextParagraph *pr = 0, TQTextParagraph *nx = 0, bool updateIds = TRUE ); - void insertChild( TQObject *o ) { TQObject::insertChild( o ); } - void removeChild( TQObject *o ) { TQObject::removeChild( o ); } - void insertChild( TQTextDocument *d ) { childList.append( d ); } - void removeChild( TQTextDocument *d ) { childList.removeRef( d ); } - TQPtrList children() const { return childList; } - - bool hasFocusParagraph() const; - TQString focusHref() const; - TQString focusName() const; - - void invalidateOriginalText() { oTextValid = FALSE; oText = ""; } - -signals: - void minimumWidthChanged( int ); - -private: - void init(); - TQPixmap *bufferPixmap( const TQSize &s ); - // HTML parser - bool hasPrefix(const TQChar* doc, int length, int pos, TQChar c); - bool hasPrefix(const TQChar* doc, int length, int pos, const TQString& s); -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextCustomItem* parseTable( const TQMap &attr, const TQTextFormat &fmt, - const TQChar* doc, int length, int& pos, TQTextParagraph *curpar ); -#endif - bool eatSpace(const TQChar* doc, int length, int& pos, bool includeNbsp = FALSE ); - bool eat(const TQChar* doc, int length, int& pos, TQChar c); - TQString parseOpenTag(const TQChar* doc, int length, int& pos, TQMap &attr, bool& emptyTag); - TQString parseCloseTag( const TQChar* doc, int length, int& pos ); - TQChar parseHTMLSpecialChar(const TQChar* doc, int length, int& pos); - TQString parseWord(const TQChar* doc, int length, int& pos, bool lower = TRUE); - TQChar parseChar(const TQChar* doc, int length, int& pos, TQStyleSheetItem::WhiteSpaceMode wsm ); - void setRichTextInternal( const TQString &text, TQTextCursor* cursor = 0, const TQTextFormat *initialFormat = 0 ); - void setRichTextMarginsInternal( TQPtrList< TQPtrVector >& styles, TQTextParagraph* stylesPar ); - -private: - struct TQ_EXPORT Focus { - TQTextParagraph *parag; - int start, len; - TQString href; - TQString name; - }; - - int cx, cy, cw, vw; - TQTextParagraph *fParag, *lParag; - TQTextPreProcessor *pProcessor; - TQMap selectionColors; - TQMap selections; - TQMap selectionText; - TQTextCommandHistory *commandHistory; - TQTextFormatter *pFormatter; - TQTextIndent *indenter; - TQTextFormatCollection *fCollection; - TQt::TextFormat txtFormat; - uint preferRichText : 1; - uint pages : 1; - uint useFC : 1; - uint withoutDoubleBuffer : 1; - uint underlLinks : 1; - uint nextDoubleBuffered : 1; - uint oTextValid : 1; - uint mightHaveCustomItems : 1; - int align; - int nSelections; - TQTextFlow *flow_; - TQTextDocument *par; - TQTextParagraph *parentPar; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextTableCell *tc; -#endif - TQBrush *backBrush; - TQPixmap *buf_pixmap; - Focus focusIndicator; - int minw; - int wused; - int leftmargin; - int rightmargin; - TQTextParagraph *minwParag, *curParag; - TQStyleSheet* sheet_; -#ifndef TQT_NO_MIME - TQMimeSourceFactory* factory_; -#endif - TQString contxt; - TQMap attribs; - int *tArray; - int tStopWidth; - int uDepth; - TQString oText; - TQPtrList childList; - TQColor linkColor, bodyText; - double scaleFontsFactor; - - short list_tm,list_bm, list_lm, li_tm, li_bm, par_tm, par_bm; -#if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= - TQTextDocument( const TQTextDocument & ); - TQTextDocument &operator=( const TQTextDocument & ); -#endif -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - -class TQ_EXPORT TQTextDeleteCommand : public TQTextCommand -{ -public: - TQTextDeleteCommand( TQTextDocument *d, int i, int idx, const TQMemArray &str, - const TQByteArray& oldStyle ); - TQTextDeleteCommand( TQTextParagraph *p, int idx, const TQMemArray &str ); - virtual ~TQTextDeleteCommand(); - - Commands type() const { return Delete; } - TQTextCursor *execute( TQTextCursor *c ); - TQTextCursor *unexecute( TQTextCursor *c ); - -protected: - int id, index; - TQTextParagraph *parag; - TQMemArray text; - TQByteArray styleInformation; - -}; - -class TQ_EXPORT TQTextInsertCommand : public TQTextDeleteCommand -{ -public: - TQTextInsertCommand( TQTextDocument *d, int i, int idx, const TQMemArray &str, - const TQByteArray& oldStyleInfo ) - : TQTextDeleteCommand( d, i, idx, str, oldStyleInfo ) {} - TQTextInsertCommand( TQTextParagraph *p, int idx, const TQMemArray &str ) - : TQTextDeleteCommand( p, idx, str ) {} - virtual ~TQTextInsertCommand() {} - - Commands type() const { return Insert; } - TQTextCursor *execute( TQTextCursor *c ) { return TQTextDeleteCommand::unexecute( c ); } - TQTextCursor *unexecute( TQTextCursor *c ) { return TQTextDeleteCommand::execute( c ); } - -}; - -class TQ_EXPORT TQTextFormatCommand : public TQTextCommand -{ -public: - TQTextFormatCommand( TQTextDocument *d, int sid, int sidx, int eid, int eidx, const TQMemArray &old, TQTextFormat *f, int fl ); - virtual ~TQTextFormatCommand(); - - Commands type() const { return Format; } - TQTextCursor *execute( TQTextCursor *c ); - TQTextCursor *unexecute( TQTextCursor *c ); - -protected: - int startId, startIndex, endId, endIndex; - TQTextFormat *format; - TQMemArray oldFormats; - int flags; - -}; - -class TQ_EXPORT TQTextStyleCommand : public TQTextCommand -{ -public: - TQTextStyleCommand( TQTextDocument *d, int fParag, int lParag, const TQByteArray& beforeChange ); - virtual ~TQTextStyleCommand() {} - - Commands type() const { return Style; } - TQTextCursor *execute( TQTextCursor *c ); - TQTextCursor *unexecute( TQTextCursor *c ); - - static TQByteArray readStyleInformation( TQTextDocument* d, int fParag, int lParag ); - static void writeStyleInformation( TQTextDocument* d, int fParag, const TQByteArray& style ); - -private: - int firstParag, lastParag; - TQByteArray before; - TQByteArray after; -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -struct TQ_EXPORT TQTextParagraphSelection -{ - TQTextParagraphSelection() : start(0), end(0) { } - int start, end; - TQ_DUMMY_COMPARISON_OPERATOR(TQTextParagraphSelection) -}; - -struct TQ_EXPORT TQTextLineStart -{ - TQTextLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) - { } - TQTextLineStart( int y_, int bl, int h_ ) : y( y_ ), baseLine( bl ), h( h_ ), - w( 0 ) - { } - -public: - int y, baseLine, h; - int w; -}; - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; -// MOC_SKIP_END -#endif - -class TQ_EXPORT TQTextParagraphData -{ -public: - TQTextParagraphData() {} - virtual ~TQTextParagraphData(); - virtual void join( TQTextParagraphData * ); -}; - -class TQTextParagraphPseudoDocument; - -class TQSyntaxHighlighter; - -class TQ_EXPORT TQTextParagraph -{ - friend class TQTextDocument; - friend class TQTextCursor; - friend class TQSyntaxHighlighter; - -public: - TQTextParagraph( TQTextDocument *d, TQTextParagraph *pr = 0, TQTextParagraph *nx = 0, bool updateIds = TRUE ); - ~TQTextParagraph(); - - TQTextString *string() const; - TQTextStringChar *at( int i ) const; // maybe remove later - int leftGap() const; - int length() const; // maybe remove later - - void setListStyle( TQStyleSheetItem::ListStyle ls ) { lstyle = ls; changed = TRUE; } - TQStyleSheetItem::ListStyle listStyle() const { return (TQStyleSheetItem::ListStyle)lstyle; } - void setListItem( bool li ); - bool isListItem() const { return litem; } - void setListValue( int v ) { list_val = v; } - int listValue() const { return list_val > 0 ? list_val : -1; } - - void setListDepth( int depth ); - int listDepth() const { return ldepth; } - -// void setFormat( TQTextFormat *fm ); -// TQTextFormat *paragFormat() const; - - inline TQTextDocument *document() const { - if (hasdoc) return (TQTextDocument*) docOrPseudo; - return 0; - } - TQTextParagraphPseudoDocument *pseudoDocument() const; - - TQRect rect() const; - void setHeight( int h ) { r.setHeight( h ); } - void show(); - void hide(); - bool isVisible() const { return visible; } - - TQTextParagraph *prev() const; - TQTextParagraph *next() const; - void setPrev( TQTextParagraph *s ); - void setNext( TQTextParagraph *s ); - - void insert( int index, const TQString &s ); - void insert( int index, const TQChar *unicode, int len ); - void append( const TQString &s, bool reallyAtEnd = FALSE ); - void truncate( int index ); - void remove( int index, int len ); - void join( TQTextParagraph *s ); - - void invalidate( int chr ); - - void move( int &dy ); - void format( int start = -1, bool doMove = TRUE ); - - bool isValid() const; - bool hasChanged() const; - void setChanged( bool b, bool recursive = FALSE ); - - int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const; - TQTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const; - int lines() const; - TQTextStringChar *lineStartOfLine( int line, int *index = 0 ) const; - int lineY( int l ) const; - int lineBaseLine( int l ) const; - int lineHeight( int l ) const; - void lineInfo( int l, int &y, int &h, int &bl ) const; - - void setSelection( int id, int start, int end ); - void removeSelection( int id ); - int selectionStart( int id ) const; - int selectionEnd( int id ) const; - bool hasSelection( int id ) const; - bool hasAnySelection() const; - bool fullSelected( int id ) const; - - void setEndState( int s ); - int endState() const; - - void setParagId( int i ); - int paragId() const; - - bool firstPreProcess() const; - void setFirstPreProcess( bool b ); - - void indent( int *oldIndent = 0, int *newIndent = 0 ); - - void setExtraData( TQTextParagraphData *data ); - TQTextParagraphData *extraData() const; - - TQMap &lineStartList(); - - void setFormat( int index, int len, TQTextFormat *f, bool useCollection = TRUE, int flags = -1 ); - - void setAlignment( int a ); - int alignment() const; - - void paint( TQPainter &painter, const TQColorGroup &cg, TQTextCursor *cursor = 0, bool drawSelections = FALSE, - int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 ); - - int topMargin() const; - int bottomMargin() const; - int leftMargin() const; - int firstLineMargin() const; - int rightMargin() const; - int lineSpacing() const; - -#ifndef TQT_NO_TEXTCUSTOMITEM - void registerFloatingItem( TQTextCustomItem *i ); - void unregisterFloatingItem( TQTextCustomItem *i ); -#endif - - void setFullWidth( bool b ) { fullWidth = b; } - bool isFullWidth() const { return fullWidth; } - -#ifndef TQT_NO_TEXTCUSTOMITEM - TQTextTableCell *tableCell() const; -#endif - - TQBrush *background() const; - - int documentWidth() const; - int documentVisibleWidth() const; - int documentX() const; - int documentY() const; - TQTextFormatCollection *formatCollection() const; - TQTextFormatter *formatter() const; - - int nextTab( int i, int x ); - int *tabArray() const; - void setTabArray( int *a ); - void setTabStops( int tw ); - - void adjustToPainter( TQPainter *p ); - - void setNewLinesAllowed( bool b ); - bool isNewLinesAllowed() const; - - TQString richText() const; - - void addCommand( TQTextCommand *cmd ); - TQTextCursor *undo( TQTextCursor *c = 0 ); - TQTextCursor *redo( TQTextCursor *c = 0 ); - TQTextCommandHistory *commands() const; - void copyParagData( TQTextParagraph *parag ); - - void setBreakable( bool b ) { breakable = b; } - bool isBreakable() const { return breakable; } - - void setBackgroundColor( const TQColor &c ); - TQColor *backgroundColor() const { return bgcol; } - void clearBackgroundColor(); - - void setMovedDown( bool b ) { movedDown = b; } - bool wasMovedDown() const { return movedDown; } - - void setDirection( TQChar::Direction d ); - TQChar::Direction direction() const; - void setPaintDevice( TQPaintDevice *pd ) { paintdevice = pd; } - - void readStyleInformation( TQDataStream& stream ); - void writeStyleInformation( TQDataStream& stream ) const; - -protected: - void setColorForSelection( TQColor &c, TQPainter &p, const TQColorGroup& cg, int selection ); - void drawLabel( TQPainter* p, int x, int y, int w, int h, int base, const TQColorGroup& cg ); - void drawString( TQPainter &painter, const TQString &str, int start, int len, int xstart, - int y, int baseLine, int w, int h, bool drawSelections, int fullSelectionWidth, - TQTextStringChar *formatChar, const TQColorGroup& cg, - bool rightToLeft ); - -private: - TQMap &selections() const; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQPtrList &floatingItems() const; -#endif - TQBrush backgroundBrush( const TQColorGroup&cg ) { if ( bgcol ) return *bgcol; return cg.brush( TQColorGroup::Base ); } - void invalidateStyleCache(); - - TQMap lineStarts; - TQRect r; - TQTextParagraph *p, *n; - void *docOrPseudo; - uint changed : 1; - uint firstFormat : 1; - uint firstPProcess : 1; - uint needPreProcess : 1; - uint fullWidth : 1; - uint lastInFrame : 1; - uint visible : 1; - uint breakable : 1; - uint movedDown : 1; - uint mightHaveCustomItems : 1; - uint hasdoc : 1; - uint litem : 1; // whether the paragraph is a list item - uint rtext : 1; // whether the paragraph needs rich text margin - int align : 4; - uint /*TQStyleSheetItem::ListStyle*/ lstyle : 4; - int invalid; - int state, id; - TQTextString *str; - TQMap *mSelections; -#ifndef TQT_NO_TEXTCUSTOMITEM - TQPtrList *mFloatingItems; -#endif - short utm, ubm, ulm, urm, uflm, ulinespacing; - short tabStopWidth; - int minwidth; - int *tArray; - TQTextParagraphData *eData; - short list_val; - ushort ldepth; - TQColor *bgcol; - TQPaintDevice *paintdevice; -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextFormatter -{ -public: - TQTextFormatter(); - virtual ~TQTextFormatter(); - - virtual int format( TQTextDocument *doc, TQTextParagraph *parag, int start, const TQMap &oldLineStarts ) = 0; - virtual int formatVertically( TQTextDocument* doc, TQTextParagraph* parag ); - - bool isWrapEnabled( TQTextParagraph *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} - int wrapAtColumn() const { return wrapColumn;} - virtual void setWrapEnabled( bool b ); - virtual void setWrapAtColumn( int c ); - virtual void setAllowBreakInWords( bool b ) { biw = b; } - bool allowBreakInWords() const { return biw; } - - int minimumWidth() const { return thisminw; } - int widthUsed() const { return thiswused; } - -protected: - virtual TQTextLineStart *formatLine( TQTextParagraph *parag, TQTextString *string, TQTextLineStart *line, TQTextStringChar *start, - TQTextStringChar *last, int align = TQt::AlignAuto, int space = 0 ); -#ifndef TQT_NO_COMPLEXTEXT - virtual TQTextLineStart *bidiReorderLine( TQTextParagraph *parag, TQTextString *string, TQTextLineStart *line, TQTextStringChar *start, - TQTextStringChar *last, int align, int space ); -#endif - void insertLineStart( TQTextParagraph *parag, int index, TQTextLineStart *ls ); - - int thisminw; - int thiswused; - -private: - bool wrapEnabled; - int wrapColumn; - bool biw; - -#ifdef HAVE_THAI_BREAKS - static TQCString *thaiCache; - static TQTextString *cachedString; - static ThBreakIterator *thaiIt; -#endif -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextFormatterBreakInWords : public TQTextFormatter -{ -public: - TQTextFormatterBreakInWords(); - virtual ~TQTextFormatterBreakInWords() {} - - int format( TQTextDocument *doc, TQTextParagraph *parag, int start, const TQMap &oldLineStarts ); - -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextFormatterBreakWords : public TQTextFormatter -{ -public: - TQTextFormatterBreakWords(); - virtual ~TQTextFormatterBreakWords() {} - - int format( TQTextDocument *doc, TQTextParagraph *parag, int start, const TQMap &oldLineStarts ); - -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextIndent -{ -public: - TQTextIndent(); - virtual ~TQTextIndent() {} - - virtual void indent( TQTextDocument *doc, TQTextParagraph *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; - -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextPreProcessor -{ -public: - enum Ids { - Standard = 0 - }; - - TQTextPreProcessor(); - virtual ~TQTextPreProcessor() {} - - virtual void process( TQTextDocument *doc, TQTextParagraph *, int, bool = TRUE ) = 0; - virtual TQTextFormat *format( int id ) = 0; - -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -class TQ_EXPORT TQTextFormat -{ - friend class TQTextFormatCollection; - friend class TQTextDocument; - -public: - enum Flags { - NoFlags, - Bold = 1, - Italic = 2, - Underline = 4, - Family = 8, - Size = 16, - Color = 32, - Misspelled = 64, - VAlign = 128, - StrikeOut= 256, - Font = Bold | Italic | Underline | Family | Size | StrikeOut, - Format = Font | Color | Misspelled | VAlign - }; - - enum VerticalAlignment { AlignNormal, AlignSuperScript, AlignSubScript }; - - TQTextFormat(); - virtual ~TQTextFormat(); - - TQTextFormat( const TQStyleSheetItem *s ); - TQTextFormat( const TQFont &f, const TQColor &c, TQTextFormatCollection *parent = 0 ); - TQTextFormat( const TQTextFormat &fm ); - TQTextFormat makeTextFormat( const TQStyleSheetItem *style, const TQMap& attr, double scaleFontsFactor ) const; - TQTextFormat& operator=( const TQTextFormat &fm ); - TQColor color() const; - TQFont font() const; - TQFontMetrics fontMetrics() const { return fm; } - bool isMisspelled() const; - VerticalAlignment vAlign() const; - int minLeftBearing() const; - int minRightBearing() const; - int width( const TQChar &c ) const; - int width( const TQString &str, int pos ) const; - int height() const; - int ascent() const; - int descent() const; - int leading() const; - bool useLinkColor() const; - - void setBold( bool b ); - void setItalic( bool b ); - void setUnderline( bool b ); - void setStrikeOut( bool b ); - void setFamily( const TQString &f ); - void setPointSize( int s ); - void setFont( const TQFont &f ); - void setColor( const TQColor &c ); - void setMisspelled( bool b ); - void setVAlign( VerticalAlignment a ); - - bool operator==( const TQTextFormat &f ) const; - TQTextFormatCollection *parent() const; - const TQString &key() const; - - static TQString getKey( const TQFont &f, const TQColor &c, bool misspelled, VerticalAlignment vAlign ); - - void addRef(); - void removeRef(); - - TQString makeFormatChangeTags( TQTextFormat* defaultFormat, TQTextFormat *f, const TQString& oldAnchorHref, const TQString& anchorHref ) const; - TQString makeFormatEndTags( TQTextFormat* defaultFormat, const TQString& anchorHref ) const; - - static void setPainter( TQPainter *p ); - static TQPainter* painter(); - - bool fontSizesInPixels() { return usePixelSizes; } - -protected: - virtual void generateKey(); - -private: - void update(); - static void applyFont( const TQFont &f ); - static void cleanupPrivateData(); - -private: - TQFont fn; - TQColor col; - TQFontMetrics fm; - uint missp : 1; - uint linkColor : 1; - uint usePixelSizes : 1; - int leftBearing, rightBearing; - VerticalAlignment ha; - uchar widths[ 256 ]; - int hei, asc, dsc; - TQTextFormatCollection *collection; - int ref; - TQString k; - int logicalFontSize; - int stdSize; - static TQPainter *pntr; - static TQFontMetrics *pntr_fm; - static int pntr_asc; - static int pntr_hei; - static int pntr_ldg; - static int pntr_dsc; - -}; - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#if defined(Q_TEMPLATEDLL) -// MOC_SKIP_BEGIN -Q_TEMPLATE_EXTERN template class TQ_EXPORT TQDict; -// MOC_SKIP_END -#endif - -class TQ_EXPORT TQTextFormatCollection -{ - friend class TQTextDocument; - friend class TQTextFormat; - -public: - TQTextFormatCollection(); - virtual ~TQTextFormatCollection(); - - void setDefaultFormat( TQTextFormat *f ); - TQTextFormat *defaultFormat() const; - virtual TQTextFormat *format( TQTextFormat *f ); - virtual TQTextFormat *format( TQTextFormat *of, TQTextFormat *nf, int flags ); - virtual TQTextFormat *format( const TQFont &f, const TQColor &c ); - virtual void remove( TQTextFormat *f ); - virtual TQTextFormat *createFormat( const TQTextFormat &f ) { return new TQTextFormat( f ); } - virtual TQTextFormat *createFormat( const TQFont &f, const TQColor &c ) { return new TQTextFormat( f, c, this ); } - - void updateDefaultFormat( const TQFont &font, const TQColor &c, TQStyleSheet *sheet ); - - TQPaintDevice *paintDevice() const { return paintdevice; } - void setPaintDevice( TQPaintDevice * ); - -private: - void updateKeys(); - -private: - TQTextFormat *defFormat, *lastFormat, *cachedFormat; - TQDict cKey; - TQTextFormat *cres; - TQFont cfont; - TQColor ccol; - TQString kof, knf; - int cflags; - - TQPaintDevice *paintdevice; -}; - -class TQ_EXPORT TQTextParagraphPseudoDocument -{ -public: - TQTextParagraphPseudoDocument(); - ~TQTextParagraphPseudoDocument(); - TQRect docRect; - TQTextFormatter *pFormatter; - TQTextCommandHistory *commandHistory; - int minw; - int wused; - TQTextFormatCollection collection; -}; - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -inline int TQTextParagraph::length() const -{ - return str->length(); -} - -inline TQRect TQTextParagraph::rect() const -{ - return r; -} - -inline int TQTextCursor::index() const -{ - return idx; -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -inline int TQTextDocument::x() const -{ - return cx; -} - -inline int TQTextDocument::y() const -{ - return cy; -} - -inline int TQTextDocument::width() const -{ - return TQMAX( cw, flow_->width() ); -} - -inline int TQTextDocument::visibleWidth() const -{ - return vw; -} - -inline TQTextParagraph *TQTextDocument::firstParagraph() const -{ - return fParag; -} - -inline TQTextParagraph *TQTextDocument::lastParagraph() const -{ - return lParag; -} - -inline void TQTextDocument::setFirstParagraph( TQTextParagraph *p ) -{ - fParag = p; -} - -inline void TQTextDocument::setLastParagraph( TQTextParagraph *p ) -{ - lParag = p; -} - -inline void TQTextDocument::setWidth( int w ) -{ - cw = TQMAX( w, minw ); - flow_->setWidth( cw ); - vw = w; -} - -inline int TQTextDocument::minimumWidth() const -{ - return minw; -} - -inline void TQTextDocument::setY( int y ) -{ - cy = y; -} - -inline int TQTextDocument::leftMargin() const -{ - return leftmargin; -} - -inline void TQTextDocument::setLeftMargin( int lm ) -{ - leftmargin = lm; -} - -inline int TQTextDocument::rightMargin() const -{ - return rightmargin; -} - -inline void TQTextDocument::setRightMargin( int rm ) -{ - rightmargin = rm; -} - -inline TQTextPreProcessor *TQTextDocument::preProcessor() const -{ - return pProcessor; -} - -inline void TQTextDocument::setPreProcessor( TQTextPreProcessor * sh ) -{ - pProcessor = sh; -} - -inline void TQTextDocument::setFormatter( TQTextFormatter *f ) -{ - delete pFormatter; - pFormatter = f; -} - -inline TQTextFormatter *TQTextDocument::formatter() const -{ - return pFormatter; -} - -inline void TQTextDocument::setIndent( TQTextIndent *i ) -{ - indenter = i; -} - -inline TQTextIndent *TQTextDocument::indent() const -{ - return indenter; -} - -inline TQColor TQTextDocument::selectionColor( int id ) const -{ - return selectionColors[ id ]; -} - -inline bool TQTextDocument::invertSelectionText( int id ) const -{ - return selectionText[ id ]; -} - -inline void TQTextDocument::setSelectionColor( int id, const TQColor &c ) -{ - selectionColors[ id ] = c; -} - -inline void TQTextDocument::setInvertSelectionText( int id, bool b ) -{ - selectionText[ id ] = b; -} - -inline TQTextFormatCollection *TQTextDocument::formatCollection() const -{ - return fCollection; -} - -inline int TQTextDocument::alignment() const -{ - return align; -} - -inline void TQTextDocument::setAlignment( int a ) -{ - align = a; -} - -inline int *TQTextDocument::tabArray() const -{ - return tArray; -} - -inline int TQTextDocument::tabStopWidth() const -{ - return tStopWidth; -} - -inline void TQTextDocument::setTabArray( int *a ) -{ - tArray = a; -} - -inline void TQTextDocument::setTabStops( int tw ) -{ - tStopWidth = tw; -} - -inline TQString TQTextDocument::originalText() const -{ - if ( oTextValid ) - return oText; - return text(); -} - -inline void TQTextDocument::setFlow( TQTextFlow *f ) -{ - if ( flow_ ) - delete flow_; - flow_ = f; -} - -inline void TQTextDocument::takeFlow() -{ - flow_ = 0; -} - -inline bool TQTextDocument::useDoubleBuffer( TQTextParagraph *parag, TQPainter *p ) -{ - return ( !parag->document()->parent() || parag->document()->nextDoubleBuffered ) && - ( !p || !p->device() || p->device()->devType() != TQInternal::Printer ); -} - -// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -inline TQColor TQTextFormat::color() const -{ - return col; -} - -inline TQFont TQTextFormat::font() const -{ - return fn; -} - -inline bool TQTextFormat::isMisspelled() const -{ - return missp; -} - -inline TQTextFormat::VerticalAlignment TQTextFormat::vAlign() const -{ - return ha; -} - -inline bool TQTextFormat::operator==( const TQTextFormat &f ) const -{ - return k == f.k; -} - -inline TQTextFormatCollection *TQTextFormat::parent() const -{ - return collection; -} - -inline void TQTextFormat::addRef() -{ - ref++; -} - -inline void TQTextFormat::removeRef() -{ - ref--; - if ( !collection ) - return; - if ( this == collection->defFormat ) - return; - if ( ref == 0 ) - collection->remove( this ); -} - -inline const TQString &TQTextFormat::key() const -{ - return k; -} - -inline bool TQTextFormat::useLinkColor() const -{ - return linkColor; -} - -inline TQTextStringChar *TQTextParagraph::at( int i ) const -{ - return &str->at( i ); -} - -inline bool TQTextParagraph::isValid() const -{ - return invalid == -1; -} - -inline bool TQTextParagraph::hasChanged() const -{ - return changed; -} - -inline void TQTextParagraph::setBackgroundColor( const TQColor & c ) -{ - delete bgcol; - bgcol = new TQColor( c ); - setChanged( TRUE ); -} - -inline void TQTextParagraph::clearBackgroundColor() -{ - delete bgcol; bgcol = 0; setChanged( TRUE ); -} - -inline void TQTextParagraph::append( const TQString &s, bool reallyAtEnd ) -{ - if ( reallyAtEnd ) - insert( str->length(), s ); - else - insert( TQMAX( str->length() - 1, 0 ), s ); -} - -inline TQTextParagraph *TQTextParagraph::prev() const -{ - return p; -} - -inline TQTextParagraph *TQTextParagraph::next() const -{ - return n; -} - -inline bool TQTextParagraph::hasAnySelection() const -{ - return mSelections ? !selections().isEmpty() : FALSE; -} - -inline void TQTextParagraph::setEndState( int s ) -{ - if ( s == state ) - return; - state = s; -} - -inline int TQTextParagraph::endState() const -{ - return state; -} - -inline void TQTextParagraph::setParagId( int i ) -{ - id = i; -} - -inline int TQTextParagraph::paragId() const -{ - if ( id == -1 ) - tqWarning( "invalid parag id!!!!!!!! (%p)", (void*)this ); - return id; -} - -inline bool TQTextParagraph::firstPreProcess() const -{ - return firstPProcess; -} - -inline void TQTextParagraph::setFirstPreProcess( bool b ) -{ - firstPProcess = b; -} - -inline TQMap &TQTextParagraph::lineStartList() -{ - return lineStarts; -} - -inline TQTextString *TQTextParagraph::string() const -{ - return str; -} - -inline TQTextParagraphPseudoDocument *TQTextParagraph::pseudoDocument() const -{ - if ( hasdoc ) - return 0; - return (TQTextParagraphPseudoDocument*) docOrPseudo; -} - - -#ifndef TQT_NO_TEXTCUSTOMITEM -inline TQTextTableCell *TQTextParagraph::tableCell() const -{ - return hasdoc ? document()->tableCell () : 0; -} -#endif - -inline TQTextCommandHistory *TQTextParagraph::commands() const -{ - return hasdoc ? document()->commands() : pseudoDocument()->commandHistory; -} - - -inline int TQTextParagraph::alignment() const -{ - return align; -} - -#ifndef TQT_NO_TEXTCUSTOMITEM -inline void TQTextParagraph::registerFloatingItem( TQTextCustomItem *i ) -{ - floatingItems().append( i ); -} - -inline void TQTextParagraph::unregisterFloatingItem( TQTextCustomItem *i ) -{ - floatingItems().removeRef( i ); -} -#endif - -inline TQBrush *TQTextParagraph::background() const -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - return tableCell() ? tableCell()->backGround() : 0; -#else - return 0; -#endif -} - -inline int TQTextParagraph::documentWidth() const -{ - return hasdoc ? document()->width() : pseudoDocument()->docRect.width(); -} - -inline int TQTextParagraph::documentVisibleWidth() const -{ - return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width(); -} - -inline int TQTextParagraph::documentX() const -{ - return hasdoc ? document()->x() : pseudoDocument()->docRect.x(); -} - -inline int TQTextParagraph::documentY() const -{ - return hasdoc ? document()->y() : pseudoDocument()->docRect.y(); -} - -inline void TQTextParagraph::setExtraData( TQTextParagraphData *data ) -{ - eData = data; -} - -inline TQTextParagraphData *TQTextParagraph::extraData() const -{ - return eData; -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -inline void TQTextFormatCollection::setDefaultFormat( TQTextFormat *f ) -{ - defFormat = f; -} - -inline TQTextFormat *TQTextFormatCollection::defaultFormat() const -{ - return defFormat; -} - -// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -inline TQTextFormat *TQTextStringChar::format() const -{ - return (type == Regular) ? d.format : d.custom->format; -} - - -#ifndef TQT_NO_TEXTCUSTOMITEM -inline TQTextCustomItem *TQTextStringChar::customItem() const -{ - return isCustom() ? d.custom->custom : 0; -} -#endif - -inline int TQTextStringChar::height() const -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - return !isCustom() ? format()->height() : ( customItem()->placement() == TQTextCustomItem::PlaceInline ? customItem()->height : 0 ); -#else - return format()->height(); -#endif -} - -inline int TQTextStringChar::ascent() const -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - return !isCustom() ? format()->ascent() : ( customItem()->placement() == TQTextCustomItem::PlaceInline ? customItem()->ascent() : 0 ); -#else - return format()->ascent(); -#endif -} - -inline int TQTextStringChar::descent() const -{ -#ifndef TQT_NO_TEXTCUSTOMITEM - return !isCustom() ? format()->descent() : 0; -#else - return format()->descent(); -#endif -} - -#endif //TQT_NO_RICHTEXT - -#endif diff --git a/src/kernel/qscriptengine.cpp b/src/kernel/qscriptengine.cpp deleted file mode 100644 index bbf0f30bb..000000000 --- a/src/kernel/qscriptengine.cpp +++ /dev/null @@ -1,1622 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qscriptengine_p.h" - -#include "tqstring.h" -#include "tqrect.h" -#include "tqfont.h" -#include -#include "tqtextengine_p.h" -#include "tqfontengine_p.h" -#include - -#undef None -#undef Pre -#undef Above -#undef Below - -const int Prealloc = 256; -template -class TQVarLengthArray -{ -public: - inline explicit TQVarLengthArray(int size = 0); - inline ~TQVarLengthArray() { - if (ptr != reinterpret_cast(array)) - free(ptr); - } - - inline int size() const { return s; } - inline int count() const { return s; } - inline bool isEmpty() const { return (s == 0); } - inline void resize(int size); - inline void clear() { resize(0); } - - inline int capacity() const { return a; } - inline void reserve(int size); - - inline T &operator[](int idx) { - Q_ASSERT(idx >= 0 && idx < s); - return ptr[idx]; - } - inline const T &operator[](int idx) const { - Q_ASSERT(idx >= 0 && idx < s); - return ptr[idx]; - } - - inline void append(const T &t) { - const int idx = s; - resize(idx + 1); - ptr[idx] = t; - } - - inline T *data() { return ptr; } - inline const T *data() const { return ptr; } - inline const T * constData() const { return ptr; } - -private: - void realloc(int size, int alloc); - - int a; - int s; - T *ptr; - TQ_UINT64 array[((Prealloc * sizeof(T)) / sizeof(TQ_UINT64)) + 1]; -}; - -template -TQ_INLINE_TEMPLATES TQVarLengthArray::TQVarLengthArray(int asize) - : s(asize) { - if (s > Prealloc) { - ptr = reinterpret_cast(malloc(s * sizeof(T))); - a = s; - } else { - ptr = reinterpret_cast(array); - a = Prealloc; - } -} - - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Basic processing -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -static inline void positionCluster(TQShaperItem *item, int gfrom, int glast) -{ - int nmarks = glast - gfrom; - if (nmarks <= 0) { - tqWarning("positionCluster: no marks to position!"); - return; - } - - TQFontEngine *f = item->font; - - glyph_metrics_t baseInfo = f->boundingBox(item->glyphs[gfrom]); - - if (item->script == TQFont::Hebrew) - // we need to attach below the baseline, because of the hebrew iud. - baseInfo.height = TQMAX(baseInfo.height, -baseInfo.y); - - TQRect baseRect(baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height); - -// tqDebug("---> positionCluster: cluster from %d to %d", gfrom, glast); -// tqDebug("baseInfo: %f/%f (%f/%f) off=%f/%f", baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height, baseInfo.xoff, baseInfo.yoff); - - int size = (f->ascent()/10); - int offsetBase = (size - 4) / 4 + TQMIN(size, 4) + 1; -// tqDebug("offset = %f", offsetBase); - - bool rightToLeft = item->flags & TQTextEngine::RightToLeft; - - int i; - unsigned char lastCmb = 0; - TQRect attachmentRect; - - for(i = 1; i <= nmarks; i++) { - glyph_t mark = item->glyphs[gfrom+i]; - TQPoint p; - glyph_metrics_t markInfo = f->boundingBox(mark); - TQRect markRect(markInfo.x, markInfo.y, markInfo.width, markInfo.height); -// tqDebug("markInfo: %f/%f (%f/%f) off=%f/%f", markInfo.x, markInfo.y, markInfo.width, markInfo.height, markInfo.xoff, markInfo.yoff); - - int offset = offsetBase; - unsigned char cmb = item->attributes[gfrom+i].combiningClass; - - // ### maybe the whole position determination should move down to heuristicSetGlyphAttributes. Would save some - // bits in the glyphAttributes structure. - if (cmb < 200) { - // fixed position classes. We approximate by mapping to one of the others. - // currently I added only the ones for arabic, hebrew, lao and thai. - - // for Lao and Thai marks with class 0, see below (heuristicSetGlyphAttributes) - - // add a bit more offset to arabic, a bit hacky - if (cmb >= 27 && cmb <= 36 && offset < 3) - offset +=1; - // below - if ((cmb >= 10 && cmb <= 18) || - cmb == 20 || cmb == 22 || - cmb == 29 || cmb == 32) - cmb = TQChar::Combining_Below; - // above - else if (cmb == 23 || cmb == 27 || cmb == 28 || - cmb == 30 || cmb == 31 || (cmb >= 33 && cmb <= 36)) - cmb = TQChar::Combining_Above; - //below-right - else if (cmb == 9 || cmb == 103 || cmb == 118) - cmb = TQChar::Combining_BelowRight; - // above-right - else if (cmb == 24 || cmb == 107 || cmb == 122) - cmb = TQChar::Combining_AboveRight; - else if (cmb == 25) - cmb = TQChar::Combining_AboveLeft; - // fixed: - // 19 21 - - } - - // combining marks of different class don't interact. Reset the rectangle. - if (cmb != lastCmb) { - //tqDebug("resetting rect"); - attachmentRect = baseRect; - } - - switch(cmb) { - case TQChar::Combining_DoubleBelow: - // ### wrong in rtl context! - case TQChar::Combining_BelowLeft: - p += TQPoint(0, offset); - case TQChar::Combining_BelowLeftAttached: - p += attachmentRect.bottomLeft() - markRect.topLeft(); - break; - case TQChar::Combining_Below: - p += TQPoint(0, offset); - case TQChar::Combining_BelowAttached: - p += attachmentRect.bottomLeft() - markRect.topLeft(); - p += TQPoint((attachmentRect.width() - markRect.width())/2 , 0); - break; - case TQChar::Combining_BelowRight: - p += TQPoint(0, offset); - case TQChar::Combining_BelowRightAttached: - p += attachmentRect.bottomRight() - markRect.topRight(); - break; - case TQChar::Combining_Left: - p += TQPoint(-offset, 0); - case TQChar::Combining_LeftAttached: - break; - case TQChar::Combining_Right: - p += TQPoint(offset, 0); - case TQChar::Combining_RightAttached: - break; - case TQChar::Combining_DoubleAbove: - // ### wrong in RTL context! - case TQChar::Combining_AboveLeft: - p += TQPoint(0, -offset); - case TQChar::Combining_AboveLeftAttached: - p += attachmentRect.topLeft() - markRect.bottomLeft(); - break; - case TQChar::Combining_Above: - p += TQPoint(0, -offset); - case TQChar::Combining_AboveAttached: - p += attachmentRect.topLeft() - markRect.bottomLeft(); - p += TQPoint((attachmentRect.width() - markRect.width())/2 , 0); - break; - case TQChar::Combining_AboveRight: - p += TQPoint(0, -offset); - case TQChar::Combining_AboveRightAttached: - p += attachmentRect.topRight() - markRect.bottomRight(); - break; - - case TQChar::Combining_IotaSubscript: - default: - break; - } -// tqDebug("char=%x combiningClass = %d offset=%d/%d", mark, cmb, p.x(), p.y()); - markRect.moveBy(p.x(), p.y()); - attachmentRect |= markRect; - lastCmb = cmb; - if (rightToLeft) { - item->offsets[gfrom+i].x = p.x(); - item->offsets[gfrom+i].y = p.y(); - } else { - item->offsets[gfrom+i].x = p.x() - baseInfo.xoff; - item->offsets[gfrom+i].y = p.y() - baseInfo.yoff; - } - item->advances[gfrom+i] = 0; - } - item->has_positioning = TRUE; -} - - -void qt_heuristicPosition(TQShaperItem *item) -{ - int cEnd = -1; - int i = item->num_glyphs; - while (i--) { - if (cEnd == -1 && item->attributes[i].mark) { - cEnd = i; - } else if (cEnd != -1 && !item->attributes[i].mark) { - positionCluster(item, i, cEnd); - cEnd = -1; - } - } -} - - - -// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs -// and no reordering. -// also computes logClusters heuristically -static void heuristicSetGlyphAttributes(TQShaperItem *item, const TQChar *uc, int length) -{ - // justification is missing here!!!!! - - if ( item->num_glyphs != length ) - tqWarning("TQScriptEngine::heuristicSetGlyphAttributes: char length and num glyphs disagree" ); - - unsigned short *logClusters = item->log_clusters; - - int i; - for (i = 0; i < length; ++i) - logClusters[i] = i; - - // first char in a run is never (treated as) a mark - int cStart = 0; - item->attributes[0].mark = FALSE; - item->attributes[0].clusterStart = TRUE; - item->attributes[0].combiningClass = 0; - if (qIsZeroWidthChar(uc[0].unicode())) { - item->attributes[0].zeroWidth = TRUE; - item->advances[0] = 0; - item->has_positioning = TRUE; - } else { - item->attributes[0].zeroWidth = FALSE; - } - - int lastCat = ::category(uc[0]); - for (i = 1; i < length; ++i) { - int cat = ::category(uc[i]); - if (qIsZeroWidthChar(uc[i].unicode())) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = TRUE; - item->attributes[i].zeroWidth = TRUE; - item->attributes[i].combiningClass = 0; - cStart = i; - item->advances[i] = 0; - item->has_positioning = TRUE; - } else if (cat != TQChar::Mark_NonSpacing) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = TRUE; - item->attributes[i].combiningClass = 0; - cStart = i; - } else { - int cmb = ::combiningClass(uc[i]); - - if (cmb == 0) { - // Fix 0 combining classes - if ((uc[i].unicode() & 0xff00) == 0x0e00) { - // thai or lao - unsigned char col = uc[i].cell(); - if (col == 0x31 || - col == 0x34 || - col == 0x35 || - col == 0x36 || - col == 0x37 || - col == 0x47 || - col == 0x4c || - col == 0x4d || - col == 0x4e) { - cmb = TQChar::Combining_AboveRight; - } else if (col == 0xb1 || - col == 0xb4 || - col == 0xb5 || - col == 0xb6 || - col == 0xb7 || - col == 0xbb || - col == 0xcc || - col == 0xcd) { - cmb = TQChar::Combining_Above; - } else if (col == 0xbc) { - cmb = TQChar::Combining_Below; - } - } - } - - item->attributes[i].mark = TRUE; - item->attributes[i].clusterStart = FALSE; - item->attributes[i].combiningClass = cmb; - logClusters[i] = cStart; - item->advances[i] = 0; - item->has_positioning = TRUE; - } - - if (lastCat == TQChar::Separator_Space) - item->attributes[i-1].justification = GlyphAttributes::Space; - else if (cat != TQChar::Mark_NonSpacing) - item->attributes[i-1].justification = GlyphAttributes::Character; - else - item->attributes[i-1].justification = GlyphAttributes::NoJustification; - - lastCat = cat; - } -} - -static void heuristicSetGlyphAttributes(TQShaperItem *item) -{ - heuristicSetGlyphAttributes(item, item->string->unicode() + item->from, item->length); -} - - -static bool basic_shape(TQShaperItem *item) -{ - if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - heuristicSetGlyphAttributes(item); - qt_heuristicPosition(item); - return TRUE; -} - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Middle eastern languages -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -// Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly -// ligatures one does not want in modern Hebrew (as lam-alef ligatures). -enum { - CcmpProperty = 0x1 -}; -#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) -static const TQOpenType::Features hebrew_features[] = { - { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, - {0, 0} -}; -#endif -/* Hebrew shaping. In the non opentype case we try to use the - presentation forms specified for Hebrew. Especially for the - ligatures with Dagesh this gives much better results than we could - achieve manually. -*/ -static bool hebrew_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script == TQFont::Hebrew); - -#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) - TQOpenType *openType = item->font->openType(); - - if (openType && openType->supportsScript(item->script)) { - openType->selectScript(item->script, hebrew_features); - - if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - heuristicSetGlyphAttributes(item); - openType->shape(item); - return openType->positionAndAdd(item); - } -#endif - - enum { - Dagesh = 0x5bc, - ShinDot = 0x5c1, - SinDot = 0x5c2, - Patah = 0x5b7, - Qamats = 0x5b8, - Holam = 0x5b9, - Rafe = 0x5bf - }; - unsigned short chars[512]; - TQChar *shapedChars = item->length > 256 ? (TQChar *)::malloc(2*item->length * sizeof(TQChar)) : (TQChar *)chars; - - const TQChar *uc = item->string->unicode() + item->from; - unsigned short *logClusters = item->log_clusters; - - *shapedChars = *uc; - logClusters[0] = 0; - int slen = 1; - int cluster_start = 0; - int i; - for (i = 1; i < item->length; ++i) { - ushort base = shapedChars[slen-1].unicode(); - ushort shaped = 0; - bool invalid = FALSE; - if (uc[i].unicode() == Dagesh) { - if (base >= 0x5d0 - && base <= 0x5ea - && base != 0x5d7 - && base != 0x5dd - && base != 0x5df - && base != 0x5e2 - && base != 0x5e5) { - shaped = base - 0x5d0 + 0xfb30; - } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) { - shaped = base + 2; - } else { - invalid = TRUE; - } - } else if (uc[i].unicode() == ShinDot) { - if (base == 0x05e9) - shaped = 0xfb2a; - else if (base == 0xfb49) - shaped = 0xfb2c; - else - invalid = TRUE; - } else if (uc[i].unicode() == SinDot) { - if (base == 0x05e9) - shaped = 0xfb2b; - else if (base == 0xfb49) - shaped = 0xfb2d; - else - invalid = TRUE; - } else if (uc[i].unicode() == Patah) { - if (base == 0x5d0) - shaped = 0xfb2e; - } else if (uc[i].unicode() == Qamats) { - if (base == 0x5d0) - shaped = 0xfb2f; - } else if (uc[i].unicode() == Holam) { - if (base == 0x5d5) - shaped = 0xfb4b; - } else if (uc[i].unicode() == Rafe) { - if (base == 0x5d1) - shaped = 0xfb4c; - else if (base == 0x5db) - shaped = 0xfb4d; - else if (base == 0x5e4) - shaped = 0xfb4e; - } - - if (invalid) { - shapedChars[slen] = 0x25cc; - item->attributes[slen].clusterStart = TRUE; - item->attributes[slen].mark = FALSE; - item->attributes[slen].combiningClass = 0; - cluster_start = slen; - ++slen; - } - if (shaped) { - if (item->font->canRender((TQChar *)&shaped, 1)) { - shapedChars[slen-1] = TQChar(shaped); - } else - shaped = 0; - } - if (!shaped) { - shapedChars[slen] = uc[i]; - if (::category(uc[i]) != TQChar::Mark_NonSpacing) { - item->attributes[slen].clusterStart = TRUE; - item->attributes[slen].mark = FALSE; - item->attributes[slen].combiningClass = 0; - cluster_start = slen; - } else { - item->attributes[slen].clusterStart = FALSE; - item->attributes[slen].mark = TRUE; - item->attributes[slen].combiningClass = ::combiningClass(uc[i]); - } - ++slen; - } - logClusters[i] = cluster_start; - } - - if (item->font->stringToCMap(shapedChars, slen, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - for (i = 0; i < item->num_glyphs; ++i) { - if (item->attributes[i].mark) - item->advances[i] = 0; - } - qt_heuristicPosition(item); - - if (item->length > 256) - ::free(shapedChars); - return TRUE; -} - -// these groups correspond to the groups defined in the Unicode standard. -// Some of these groups are equal whith regards to both joining and line breaking behaviour, -// and thus have the same enum value -// -// I'm not sure the mapping of syriac to arabic enums is correct with regards to justification, but as -// I couldn't find any better document I'll hope for the best. -enum ArabicGroup { - // NonJoining - ArabicNone, - ArabicSpace, - // Transparent - Transparent, - // Causing - Center, - Kashida, - - // Arabic - // Dual - Beh, - Noon, - Meem = Noon, - Heh = Noon, - KnottedHeh = Noon, - HehGoal = Noon, - SwashKaf = Noon, - Yeh, - Hah, - Seen, - Sad = Seen, - Tah, - Kaf = Tah, - Gaf = Tah, - Lam = Tah, - Ain, - Feh = Ain, - Qaf = Ain, - // Right - Alef, - Waw, - Dal, - TehMarbuta = Dal, - Reh, - HamzaOnHehGoal, - YehWithTail = HamzaOnHehGoal, - YehBarre = HamzaOnHehGoal, - - // Syriac - // Dual - Beth = Beh, - Gamal = Ain, - Heth = Noon, - Teth = Hah, - Yudh = Noon, - Kaph = Noon, - Lamadh = Lam, - Mim = Noon, - Nun = Noon, - Semakh = Noon, - FinalSemakh = Noon, - SyriacE = Ain, - Pe = Ain, - ReversedPe = Hah, - Qaph = Noon, - Shin = Noon, - Fe = Ain, - - // Right - Alaph = Alef, - Dalath = Dal, - He = Dal, - SyriacWaw = Waw, - Zain = Alef, - YudhHe = Waw, - Sadhe = HamzaOnHehGoal, - Taw = Dal, - - // Compiler bug? Otherwise ArabicGroupsEnd would be equal to Dal + 1. - Dummy = HamzaOnHehGoal, - ArabicGroupsEnd -}; - -static const unsigned char arabic_group[0x150] = { - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - ArabicNone, ArabicNone, Alef, Alef, - Waw, Alef, Yeh, Alef, - Beh, TehMarbuta, Beh, Beh, - Hah, Hah, Hah, Dal, - - Dal, Reh, Reh, Seen, - Seen, Sad, Sad, Tah, - Tah, Ain, Ain, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - // 0x640 - Kashida, Feh, Qaf, Kaf, - Lam, Meem, Noon, Heh, - Waw, Yeh, Yeh, Transparent, - Transparent, Transparent, Transparent, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, Beh, Qaf, - - Transparent, Alef, Alef, Alef, - ArabicNone, Alef, Waw, Waw, - Yeh, Beh, Beh, Beh, - Beh, Beh, Beh, Beh, - - // 0x680 - Beh, Hah, Hah, Hah, - Hah, Hah, Hah, Hah, - Dal, Dal, Dal, Dal, - Dal, Dal, Dal, Dal, - - Dal, Reh, Reh, Reh, - Reh, Reh, Reh, Reh, - Reh, Reh, Seen, Seen, - Seen, Sad, Sad, Tah, - - Ain, Feh, Feh, Feh, - Feh, Feh, Feh, Qaf, - Qaf, Gaf, SwashKaf, Gaf, - Kaf, Kaf, Kaf, Gaf, - - Gaf, Gaf, Gaf, Gaf, - Gaf, Lam, Lam, Lam, - Lam, Noon, Noon, Noon, - Noon, Noon, KnottedHeh, Hah, - - // 0x6c0 - TehMarbuta, HehGoal, HamzaOnHehGoal, HamzaOnHehGoal, - Waw, Waw, Waw, Waw, - Waw, Waw, Waw, Waw, - Yeh, YehWithTail, Yeh, Waw, - - Yeh, Yeh, YehBarre, YehBarre, - ArabicNone, TehMarbuta, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, Transparent, - Transparent, ArabicNone, Transparent, Transparent, - Transparent, Transparent, Dal, Reh, - - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, Seen, Sad, - Ain, ArabicNone, ArabicNone, KnottedHeh, - - // 0x700 - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - Alaph, Transparent, Beth, Gamal, - Gamal, Dalath, Dalath, He, - SyriacWaw, Zain, Heth, Teth, - Teth, Yudh, YudhHe, Kaph, - - Lamadh, Mim, Nun, Semakh, - FinalSemakh, SyriacE, Pe, ReversedPe, - Sadhe, Qaph, Dalath, Shin, - Taw, Beth, Gamal, Dalath, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, ArabicNone, - ArabicNone, Zain, Kaph, Fe, -}; - -static inline ArabicGroup arabicGroup(unsigned short uc) -{ - if (uc >= 0x0600 && uc < 0x750) - return (ArabicGroup) arabic_group[uc-0x600]; - else if (uc == 0x200d) - return Center; - else if (::category(uc) == TQChar::Separator_Space) - return ArabicSpace; - else - return ArabicNone; -} - - -/* - Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on - arabic). - - Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent). - transparent joining is not encoded in TQChar::joining(), but applies to all combining marks and format marks. - - Right join-causing: dual + center - Left join-causing: dual + right + center - - Rules are as follows (for a string already in visual order, as we have it here): - - R1 Transparent characters do not affect joining behaviour. - R2 A right joining character, that has a right join-causing char on the right will get form XRight - (R3 A left joining character, that has a left join-causing char on the left will get form XLeft) - Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode - R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on - the right will get form XMedial - R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left - will get form XRight - R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right - will get form XLeft - R7 Otherwise the character will get form XIsolated - - Additionally we have to do the minimal ligature support for lam-alef ligatures: - - L1 Transparent characters do not affect ligature behaviour. - L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft) - L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated) - - The state table below handles rules R1-R7. -*/ - -enum Shape { - XIsolated, - XFinal, - XInitial, - XMedial, - // intermediate state - XCausing -}; - - -enum Joining { - JNone, - JCausing, - JDual, - JRight, - JTransparent -}; - - -static const Joining joining_for_group[ArabicGroupsEnd] = { - // NonJoining - JNone, // ArabicNone - JNone, // ArabicSpace - // Transparent - JTransparent, // Transparent - // Causing - JCausing, // Center - JCausing, // Kashida - // Dual - JDual, // Beh - JDual, // Noon - JDual, // Yeh - JDual, // Hah - JDual, // Seen - JDual, // Tah - JDual, // Ain - // Right - JRight, // Alef - JRight, // Waw - JRight, // Dal - JRight, // Reh - JRight // HamzaOnHehGoal -}; - - -struct JoiningPair { - Shape form1; - Shape form2; -}; - -static const JoiningPair joining_table[5][4] = -// None, Causing, Dual, Right -{ - { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XInitial }, { XIsolated, XIsolated } }, // XIsolated - { { XFinal, XIsolated }, { XFinal, XCausing }, { XFinal, XInitial }, { XFinal, XIsolated } }, // XFinal - { { XIsolated, XIsolated }, { XInitial, XCausing }, { XInitial, XMedial }, { XInitial, XFinal } }, // XInitial - { { XFinal, XIsolated }, { XMedial, XCausing }, { XMedial, XMedial }, { XMedial, XFinal } }, // XMedial - { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XMedial }, { XIsolated, XFinal } }, // XCausing -}; - - -/* -According to http://www.microsoft.com/middleeast/Arabicdev/IE6/KBase.asp - -1. Find the priority of the connecting opportunities in each word -2. Add expansion at the highest priority connection opportunity -3. If more than one connection opportunity have the same highest value, - use the opportunity closest to the end of the word. - -Following is a chart that provides the priority for connection -opportunities and where expansion occurs. The character group names -are those in table 6.6 of the UNICODE 2.0 book. - - -PrioritY Glyph Condition Kashida Location - -Arabic_Kashida User inserted Kashida The user entered a Kashida in a position. After the user - (Shift+j or Shift+[E with hat]) Thus, it is the highest priority to insert an inserted kashida - automatic kashida. - -Arabic_Seen Seen, Sad Connecting to the next character. After the character. - (Initial or medial form). - -Arabic_HaaDal Teh Marbutah, Haa, Dal Connecting to previous character. Before the final form - of these characters. - -Arabic_Alef Alef, Tah, Lam, Connecting to previous character. Before the final form - Kaf and Gaf of these characters. - -Arabic_BaRa Reh, Yeh Connected to medial Beh Before preceding medial Baa - -Arabic_Waw Waw, Ain, Qaf, Feh Connecting to previous character. Before the final form of - these characters. - -Arabic_Normal Other connecting Connecting to previous character. Before the final form - characters of these characters. - - - -This seems to imply that we have at most one kashida point per arabic word. - -*/ - -struct TQArabicProperties { - unsigned char shape; - unsigned char justification; -}; - - -static void getArabicProperties(const unsigned short *chars, int len, TQArabicProperties *properties) -{ -// tqDebug("arabicSyriacOpenTypeShape: properties:"); - int lastPos = 0; - int lastGroup = ArabicNone; - - ArabicGroup group = arabicGroup(chars[0]); - Joining j = joining_for_group[group]; - Shape shape = joining_table[XIsolated][j].form2; - properties[0].justification = GlyphAttributes::NoJustification; - - for (int i = 1; i < len; ++i) { - // #### fix handling for spaces and punktuation - properties[i].justification = GlyphAttributes::NoJustification; - - group = arabicGroup(chars[i]); - j = joining_for_group[group]; - - if (j == JTransparent) { - properties[i].shape = XIsolated; - continue; - } - - properties[lastPos].shape = joining_table[shape][j].form1; - shape = joining_table[shape][j].form2; - - switch(lastGroup) { - case Seen: - if (properties[lastPos].shape == XInitial || properties[lastPos].shape == XMedial) - properties[i-1].justification = GlyphAttributes::Arabic_Seen; - break; - case Hah: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = GlyphAttributes::Arabic_HaaDal; - break; - case Alef: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = GlyphAttributes::Arabic_Alef; - break; - case Ain: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = GlyphAttributes::Arabic_Waw; - break; - case Noon: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = GlyphAttributes::Arabic_Normal; - break; - case ArabicNone: - break; - - default: - Q_ASSERT(FALSE); - } - - lastGroup = ArabicNone; - - switch(group) { - case ArabicNone: - case Transparent: - // ### Center should probably be treated as transparent when it comes to justification. - case Center: - break; - case ArabicSpace: - properties[i].justification = GlyphAttributes::Arabic_Space; - break; - case Kashida: - properties[i].justification = GlyphAttributes::Arabic_Kashida; - break; - case Seen: - lastGroup = Seen; - break; - - case Hah: - case Dal: - lastGroup = Hah; - break; - - case Alef: - case Tah: - lastGroup = Alef; - break; - - case Yeh: - case Reh: - if (properties[lastPos].shape == XMedial && arabicGroup(chars[lastPos]) == Beh) - properties[lastPos-1].justification = GlyphAttributes::Arabic_BaRa; - break; - - case Ain: - case Waw: - lastGroup = Ain; - break; - - case Noon: - case Beh: - case HamzaOnHehGoal: - lastGroup = Noon; - break; - case ArabicGroupsEnd: - Q_ASSERT(FALSE); - } - - lastPos = i; - } - properties[lastPos].shape = joining_table[shape][JNone].form1; - - -// for (int i = 0; i < len; ++i) -// tqDebug("arabic properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification); -} - - - - - - -// The unicode to unicode shaping codec. -// does only presentation forms B at the moment, but that should be enough for -// simple display -static const ushort arabicUnicodeMapping[256][2] = { - // base of shaped forms, and number-1 of them (0 for non shaping, - // 1 for right binding and 3 for dual binding - - // These are just the glyphs available in Unicode, - // some characters are in R class, but have no glyphs in Unicode. - - { 0x0600, 0 }, // 0x0600 - { 0x0601, 0 }, // 0x0601 - { 0x0602, 0 }, // 0x0602 - { 0x0603, 0 }, // 0x0603 - { 0x0604, 0 }, // 0x0604 - { 0x0605, 0 }, // 0x0605 - { 0x0606, 0 }, // 0x0606 - { 0x0607, 0 }, // 0x0607 - { 0x0608, 0 }, // 0x0608 - { 0x0609, 0 }, // 0x0609 - { 0x060A, 0 }, // 0x060A - { 0x060B, 0 }, // 0x060B - { 0x060C, 0 }, // 0x060C - { 0x060D, 0 }, // 0x060D - { 0x060E, 0 }, // 0x060E - { 0x060F, 0 }, // 0x060F - - { 0x0610, 0 }, // 0x0610 - { 0x0611, 0 }, // 0x0611 - { 0x0612, 0 }, // 0x0612 - { 0x0613, 0 }, // 0x0613 - { 0x0614, 0 }, // 0x0614 - { 0x0615, 0 }, // 0x0615 - { 0x0616, 0 }, // 0x0616 - { 0x0617, 0 }, // 0x0617 - { 0x0618, 0 }, // 0x0618 - { 0x0619, 0 }, // 0x0619 - { 0x061A, 0 }, // 0x061A - { 0x061B, 0 }, // 0x061B - { 0x061C, 0 }, // 0x061C - { 0x061D, 0 }, // 0x061D - { 0x061E, 0 }, // 0x061E - { 0x061F, 0 }, // 0x061F - - { 0x0620, 0 }, // 0x0620 - { 0xFE80, 0 }, // 0x0621 HAMZA - { 0xFE81, 1 }, // 0x0622 R ALEF WITH MADDA ABOVE - { 0xFE83, 1 }, // 0x0623 R ALEF WITH HAMZA ABOVE - { 0xFE85, 1 }, // 0x0624 R WAW WITH HAMZA ABOVE - { 0xFE87, 1 }, // 0x0625 R ALEF WITH HAMZA BELOW - { 0xFE89, 3 }, // 0x0626 D YEH WITH HAMZA ABOVE - { 0xFE8D, 1 }, // 0x0627 R ALEF - { 0xFE8F, 3 }, // 0x0628 D BEH - { 0xFE93, 1 }, // 0x0629 R TEH MARBUTA - { 0xFE95, 3 }, // 0x062A D TEH - { 0xFE99, 3 }, // 0x062B D THEH - { 0xFE9D, 3 }, // 0x062C D JEEM - { 0xFEA1, 3 }, // 0x062D D HAH - { 0xFEA5, 3 }, // 0x062E D KHAH - { 0xFEA9, 1 }, // 0x062F R DAL - - { 0xFEAB, 1 }, // 0x0630 R THAL - { 0xFEAD, 1 }, // 0x0631 R REH - { 0xFEAF, 1 }, // 0x0632 R ZAIN - { 0xFEB1, 3 }, // 0x0633 D SEEN - { 0xFEB5, 3 }, // 0x0634 D SHEEN - { 0xFEB9, 3 }, // 0x0635 D SAD - { 0xFEBD, 3 }, // 0x0636 D DAD - { 0xFEC1, 3 }, // 0x0637 D TAH - { 0xFEC5, 3 }, // 0x0638 D ZAH - { 0xFEC9, 3 }, // 0x0639 D AIN - { 0xFECD, 3 }, // 0x063A D GHAIN - { 0x063B, 0 }, // 0x063B - { 0x063C, 0 }, // 0x063C - { 0x063D, 0 }, // 0x063D - { 0x063E, 0 }, // 0x063E - { 0x063F, 0 }, // 0x063F - - { 0x0640, 0 }, // 0x0640 C TATWEEL // ### Join Causing, only one glyph - { 0xFED1, 3 }, // 0x0641 D FEH - { 0xFED5, 3 }, // 0x0642 D TQAF - { 0xFED9, 3 }, // 0x0643 D KAF - { 0xFEDD, 3 }, // 0x0644 D LAM - { 0xFEE1, 3 }, // 0x0645 D MEEM - { 0xFEE5, 3 }, // 0x0646 D NOON - { 0xFEE9, 3 }, // 0x0647 D HEH - { 0xFEED, 1 }, // 0x0648 R WAW - { 0x0649, 3 }, // 0x0649 ALEF MAKSURA // ### Dual, glyphs not consecutive, handle in code. - { 0xFEF1, 3 }, // 0x064A D YEH - { 0x064B, 0 }, // 0x064B - { 0x064C, 0 }, // 0x064C - { 0x064D, 0 }, // 0x064D - { 0x064E, 0 }, // 0x064E - { 0x064F, 0 }, // 0x064F - - { 0x0650, 0 }, // 0x0650 - { 0x0651, 0 }, // 0x0651 - { 0x0652, 0 }, // 0x0652 - { 0x0653, 0 }, // 0x0653 - { 0x0654, 0 }, // 0x0654 - { 0x0655, 0 }, // 0x0655 - { 0x0656, 0 }, // 0x0656 - { 0x0657, 0 }, // 0x0657 - { 0x0658, 0 }, // 0x0658 - { 0x0659, 0 }, // 0x0659 - { 0x065A, 0 }, // 0x065A - { 0x065B, 0 }, // 0x065B - { 0x065C, 0 }, // 0x065C - { 0x065D, 0 }, // 0x065D - { 0x065E, 0 }, // 0x065E - { 0x065F, 0 }, // 0x065F - - { 0x0660, 0 }, // 0x0660 - { 0x0661, 0 }, // 0x0661 - { 0x0662, 0 }, // 0x0662 - { 0x0663, 0 }, // 0x0663 - { 0x0664, 0 }, // 0x0664 - { 0x0665, 0 }, // 0x0665 - { 0x0666, 0 }, // 0x0666 - { 0x0667, 0 }, // 0x0667 - { 0x0668, 0 }, // 0x0668 - { 0x0669, 0 }, // 0x0669 - { 0x066A, 0 }, // 0x066A - { 0x066B, 0 }, // 0x066B - { 0x066C, 0 }, // 0x066C - { 0x066D, 0 }, // 0x066D - { 0x066E, 0 }, // 0x066E - { 0x066F, 0 }, // 0x066F - - { 0x0670, 0 }, // 0x0670 - { 0xFB50, 1 }, // 0x0671 R ALEF WASLA - { 0x0672, 0 }, // 0x0672 - { 0x0673, 0 }, // 0x0673 - { 0x0674, 0 }, // 0x0674 - { 0x0675, 0 }, // 0x0675 - { 0x0676, 0 }, // 0x0676 - { 0x0677, 0 }, // 0x0677 - { 0x0678, 0 }, // 0x0678 - { 0xFB66, 3 }, // 0x0679 D TTEH - { 0xFB5E, 3 }, // 0x067A D TTEHEH - { 0xFB52, 3 }, // 0x067B D BEEH - { 0x067C, 0 }, // 0x067C - { 0x067D, 0 }, // 0x067D - { 0xFB56, 3 }, // 0x067E D PEH - { 0xFB62, 3 }, // 0x067F D TEHEH - - { 0xFB5A, 3 }, // 0x0680 D BEHEH - { 0x0681, 0 }, // 0x0681 - { 0x0682, 0 }, // 0x0682 - { 0xFB76, 3 }, // 0x0683 D NYEH - { 0xFB72, 3 }, // 0x0684 D DYEH - { 0x0685, 0 }, // 0x0685 - { 0xFB7A, 3 }, // 0x0686 D TCHEH - { 0xFB7E, 3 }, // 0x0687 D TCHEHEH - { 0xFB88, 1 }, // 0x0688 R DDAL - { 0x0689, 0 }, // 0x0689 - { 0x068A, 0 }, // 0x068A - { 0x068B, 0 }, // 0x068B - { 0xFB84, 1 }, // 0x068C R DAHAL - { 0xFB82, 1 }, // 0x068D R DDAHAL - { 0xFB86, 1 }, // 0x068E R DUL - { 0x068F, 0 }, // 0x068F - - { 0x0690, 0 }, // 0x0690 - { 0xFB8C, 1 }, // 0x0691 R RREH - { 0x0692, 0 }, // 0x0692 - { 0x0693, 0 }, // 0x0693 - { 0x0694, 0 }, // 0x0694 - { 0x0695, 0 }, // 0x0695 - { 0x0696, 0 }, // 0x0696 - { 0x0697, 0 }, // 0x0697 - { 0xFB8A, 1 }, // 0x0698 R JEH - { 0x0699, 0 }, // 0x0699 - { 0x069A, 0 }, // 0x069A - { 0x069B, 0 }, // 0x069B - { 0x069C, 0 }, // 0x069C - { 0x069D, 0 }, // 0x069D - { 0x069E, 0 }, // 0x069E - { 0x069F, 0 }, // 0x069F - - { 0x06A0, 0 }, // 0x06A0 - { 0x06A1, 0 }, // 0x06A1 - { 0x06A2, 0 }, // 0x06A2 - { 0x06A3, 0 }, // 0x06A3 - { 0xFB6A, 3 }, // 0x06A4 D VEH - { 0x06A5, 0 }, // 0x06A5 - { 0xFB6E, 3 }, // 0x06A6 D PEHEH - { 0x06A7, 0 }, // 0x06A7 - { 0x06A8, 0 }, // 0x06A8 - { 0xFB8E, 3 }, // 0x06A9 D KEHEH - { 0x06AA, 0 }, // 0x06AA - { 0x06AB, 0 }, // 0x06AB - { 0x06AC, 0 }, // 0x06AC - { 0xFBD3, 3 }, // 0x06AD D NG - { 0x06AE, 0 }, // 0x06AE - { 0xFB92, 3 }, // 0x06AF D GAF - - { 0x06B0, 0 }, // 0x06B0 - { 0xFB9A, 3 }, // 0x06B1 D NGOEH - { 0x06B2, 0 }, // 0x06B2 - { 0xFB96, 3 }, // 0x06B3 D GUEH - { 0x06B4, 0 }, // 0x06B4 - { 0x06B5, 0 }, // 0x06B5 - { 0x06B6, 0 }, // 0x06B6 - { 0x06B7, 0 }, // 0x06B7 - { 0x06B8, 0 }, // 0x06B8 - { 0x06B9, 0 }, // 0x06B9 - { 0xFB9E, 1 }, // 0x06BA R NOON GHUNNA - { 0xFBA0, 3 }, // 0x06BB D RNOON - { 0x06BC, 0 }, // 0x06BC - { 0x06BD, 0 }, // 0x06BD - { 0xFBAA, 3 }, // 0x06BE D HEH DOACHASHMEE - { 0x06BF, 0 }, // 0x06BF - - { 0xFBA4, 1 }, // 0x06C0 R HEH WITH YEH ABOVE - { 0xFBA6, 3 }, // 0x06C1 D HEH GOAL - { 0x06C2, 0 }, // 0x06C2 - { 0x06C3, 0 }, // 0x06C3 - { 0x06C4, 0 }, // 0x06C4 - { 0xFBE0, 1 }, // 0x06C5 R KIRGHIZ OE - { 0xFBD9, 1 }, // 0x06C6 R OE - { 0xFBD7, 1 }, // 0x06C7 R U - { 0xFBDB, 1 }, // 0x06C8 R YU - { 0xFBE2, 1 }, // 0x06C9 R KIRGHIZ YU - { 0x06CA, 0 }, // 0x06CA - { 0xFBDE, 1 }, // 0x06CB R VE - { 0xFBFC, 3 }, // 0x06CC D FARSI YEH - { 0x06CD, 0 }, // 0x06CD - { 0x06CE, 0 }, // 0x06CE - { 0x06CF, 0 }, // 0x06CF - - { 0xFBE4, 3 }, // 0x06D0 D E - { 0x06D1, 0 }, // 0x06D1 - { 0xFBAE, 1 }, // 0x06D2 R YEH BARREE - { 0xFBB0, 1 }, // 0x06D3 R YEH BARREE WITH HAMZA ABOVE - { 0x06D4, 0 }, // 0x06D4 - { 0x06D5, 0 }, // 0x06D5 - { 0x06D6, 0 }, // 0x06D6 - { 0x06D7, 0 }, // 0x06D7 - { 0x06D8, 0 }, // 0x06D8 - { 0x06D9, 0 }, // 0x06D9 - { 0x06DA, 0 }, // 0x06DA - { 0x06DB, 0 }, // 0x06DB - { 0x06DC, 0 }, // 0x06DC - { 0x06DD, 0 }, // 0x06DD - { 0x06DE, 0 }, // 0x06DE - { 0x06DF, 0 }, // 0x06DF - - { 0x06E0, 0 }, // 0x06E0 - { 0x06E1, 0 }, // 0x06E1 - { 0x06E2, 0 }, // 0x06E2 - { 0x06E3, 0 }, // 0x06E3 - { 0x06E4, 0 }, // 0x06E4 - { 0x06E5, 0 }, // 0x06E5 - { 0x06E6, 0 }, // 0x06E6 - { 0x06E7, 0 }, // 0x06E7 - { 0x06E8, 0 }, // 0x06E8 - { 0x06E9, 0 }, // 0x06E9 - { 0x06EA, 0 }, // 0x06EA - { 0x06EB, 0 }, // 0x06EB - { 0x06EC, 0 }, // 0x06EC - { 0x06ED, 0 }, // 0x06ED - { 0x06EE, 0 }, // 0x06EE - { 0x06EF, 0 }, // 0x06EF - - { 0x06F0, 0 }, // 0x06F0 - { 0x06F1, 0 }, // 0x06F1 - { 0x06F2, 0 }, // 0x06F2 - { 0x06F3, 0 }, // 0x06F3 - { 0x06F4, 0 }, // 0x06F4 - { 0x06F5, 0 }, // 0x06F5 - { 0x06F6, 0 }, // 0x06F6 - { 0x06F7, 0 }, // 0x06F7 - { 0x06F8, 0 }, // 0x06F8 - { 0x06F9, 0 }, // 0x06F9 - { 0x06FA, 0 }, // 0x06FA - { 0x06FB, 0 }, // 0x06FB - { 0x06FC, 0 }, // 0x06FC - { 0x06FD, 0 }, // 0x06FD - { 0x06FE, 0 }, // 0x06FE - { 0x06FF, 0 } // 0x06FF -}; - -// the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, this table does -static const ushort alefMaksura[4] = {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}; - -// this is a bit tricky. Alef always binds to the right, so the second parameter descibing the shape -// of the lam can be either initial of medial. So initial maps to the isolated form of the ligature, -// medial to the final form -static const ushort arabicUnicodeLamAlefMapping[6][4] = { - { 0xfffd, 0xfffd, 0xfef5, 0xfef6 }, // 0x622 R Alef with Madda above - { 0xfffd, 0xfffd, 0xfef7, 0xfef8 }, // 0x623 R Alef with Hamza above - { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x624 // Just to fill the table ;-) - { 0xfffd, 0xfffd, 0xfef9, 0xfefa }, // 0x625 R Alef with Hamza below - { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x626 // Just to fill the table ;-) - { 0xfffd, 0xfffd, 0xfefb, 0xfefc } // 0x627 R Alef -}; - -static inline int getShape(uchar cell, int shape) -{ - // the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, handle this here - uint ch = (cell != 0x49) - ? (shape ? arabicUnicodeMapping[cell][0] + shape : 0x600+cell) - : alefMaksura[shape] ; - return ch; -} - - -/* - Two small helper functions for arabic shaping. -*/ -static inline const TQChar prevChar(const TQString *str, int pos) -{ - //tqDebug("leftChar: pos=%d", pos); - pos--; - const TQChar *ch = str->unicode() + pos; - while(pos > -1) { - if(::category(*ch) != TQChar::Mark_NonSpacing) - return *ch; - pos--; - ch--; - } - return TQChar::replacement; -} - -static inline const TQChar nextChar(const TQString *str, int pos) -{ - pos++; - int len = str->length(); - const TQChar *ch = str->unicode() + pos; - while(pos < len) { - //tqDebug("rightChar: %d isLetter=%d, joining=%d", pos, ch.isLetter(), ch.joining()); - if(::category(*ch) != TQChar::Mark_NonSpacing) - return *ch; - // assume it's a transparent char, this might not be 100% correct - pos++; - ch++; - } - return TQChar::replacement; -} - - -static void shapedString(const TQString *uc, int from, int len, TQChar *shapeBuffer, int *shapedLength, - bool reverse, GlyphAttributes *attributes, unsigned short *logClusters) -{ - Q_ASSERT((int)uc->length() >= from + len); - - if(len == 0) { - *shapedLength = 0; - return; - } - - TQVarLengthArray props(len + 2); - TQArabicProperties *properties = props.data(); - int f = from; - int l = len; - if (from > 0) { - --f; - ++l; - ++properties; - } - if (f + l < (int)uc->length()) { - ++l; - } - getArabicProperties((const unsigned short *)(uc->unicode()+f), l, props.data()); - - const TQChar *ch = uc->unicode() + from; - TQChar *data = shapeBuffer; - int clusterStart = 0; - - for (int i = 0; i < len; i++) { - uchar r = ch->row(); - int gpos = data - shapeBuffer; - - if (r != 0x06) { - if (r == 0x20) { - uchar c = ch->cell(); - if (c == 0x0c || c == 0x0d) - // remove ZWJ and ZWNJ - goto skip; - } - if (reverse) - *data = mirroredChar(*ch); - else - *data = *ch; - } else { - uchar c = ch->cell(); - int pos = i + from; - int shape = properties[i].shape; -// tqDebug("mapping U+%x to shape %d glyph=0x%x", ch->unicode(), shape, getShape(c, shape)); - // take care of lam-alef ligatures (lam right of alef) - ushort map; - switch (c) { - case 0x44: { // lam - const TQChar pch = nextChar(uc, pos); - if (pch.row() == 0x06) { - switch (pch.cell()) { - case 0x22: - case 0x23: - case 0x25: - case 0x27: -// tqDebug(" lam of lam-alef ligature"); - map = arabicUnicodeLamAlefMapping[pch.cell() - 0x22][shape]; - goto next; - default: - break; - } - } - break; - } - case 0x22: // alef with madda - case 0x23: // alef with hamza above - case 0x25: // alef with hamza below - case 0x27: // alef - if (prevChar(uc, pos).unicode() == 0x0644) { - // have a lam alef ligature - //tqDebug(" alef of lam-alef ligature"); - goto skip; - } - default: - break; - } - map = getShape(c, shape); - next: - *data = map; - } - // ##### Fixme - //attributes[gpos].zeroWidth = zeroWidth; - if (::category(*ch) == TQChar::Mark_NonSpacing) { - attributes[gpos].mark = TRUE; -// tqDebug("glyph %d (char %d) is mark!", gpos, i); - } else { - attributes[gpos].mark = FALSE; - clusterStart = data - shapeBuffer; - } - attributes[gpos].clusterStart = !attributes[gpos].mark; - attributes[gpos].combiningClass = combiningClass(*ch); - attributes[gpos].justification = properties[i].justification; -// tqDebug("data[%d] = %x (from %x)", gpos, (uint)data->unicode(), ch->unicode()); - data++; - skip: - ch++; - logClusters[i] = clusterStart; - } - *shapedLength = data - shapeBuffer; -} - -#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) - -enum { - InitProperty = 0x2, - IsolProperty = 0x4, - FinaProperty = 0x8, - MediProperty = 0x10, - RligProperty = 0x20, - CaltProperty = 0x40, - LigaProperty = 0x80, - DligProperty = 0x100, - CswhProperty = 0x200, - MsetProperty = 0x400 -}; - -static const TQOpenType::Features arabic_features[] = { - { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, - { FT_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty }, - { FT_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty }, - { FT_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty }, - { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, - { FT_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty }, - { FT_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty }, - { FT_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty }, - { FT_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty }, - { FT_MAKE_TAG('c', 's', 'w', 'h'), CswhProperty }, - // mset is used in old Win95 fonts that don't have a 'mark' positioning table. - { FT_MAKE_TAG('m', 's', 'e', 't'), MsetProperty }, - {0, 0} -}; - -static const TQOpenType::Features syriac_features[] = { - { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, - { FT_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty }, - { FT_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty }, - { FT_MAKE_TAG('f', 'i', 'n', '2'), FinaProperty }, - { FT_MAKE_TAG('f', 'i', 'n', '3'), FinaProperty }, - { FT_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty }, - { FT_MAKE_TAG('m', 'e', 'd', '2'), MediProperty }, - { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, - { FT_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty }, - { FT_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty }, - { FT_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty }, - { FT_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty }, - {0, 0} -}; - -static bool arabicSyriacOpenTypeShape(TQOpenType *openType, TQShaperItem *item, bool *ot_ok) -{ - *ot_ok = true; - - openType->selectScript(item->script, item->script == TQFont::Arabic ? arabic_features : syriac_features); - int nglyphs = item->num_glyphs; - if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - heuristicSetGlyphAttributes(item); - - unsigned short *logClusters = item->log_clusters; - const unsigned short *uc = (const unsigned short *)item->string->unicode() + item->from; - - TQVarLengthArray props(item->length+2); - TQArabicProperties *properties = props.data(); - int f = 0; - int l = item->length; - if (item->from > 0) { - --f; - ++l; - ++properties; - } - if (f + l < (int)item->string->length()) { - ++l; - } - getArabicProperties((const unsigned short *)(uc+f), l, props.data()); - - TQVarLengthArray apply(item->num_glyphs); - - - // Hack to remove ZWJ and ZWNJ from rendered output. - int j = 0; - for (int i = 0; i < item->num_glyphs; i++) { - if (uc[i] == 0x200c || uc[i] == 0x200d) - continue; - item->glyphs[j] = item->glyphs[i]; - item->attributes[j] = item->attributes[i]; - item->advances[j] = item->advances[i]; - item->offsets[j] = item->offsets[i]; - properties[j] = properties[i]; - item->attributes[j].justification = properties[i].justification; - logClusters[i] = logClusters[j]; - ++j; - } - item->num_glyphs = j; - - for (int i = 0; i < item->num_glyphs; i++) { - apply[i] = 0; - - if (properties[i].shape == XIsolated) - apply[i] |= MediProperty|FinaProperty|InitProperty; - else if (properties[i].shape == XMedial) - apply[i] |= IsolProperty|FinaProperty|InitProperty; - else if (properties[i].shape == XFinal) - apply[i] |= IsolProperty|MediProperty|InitProperty; - else if (properties[i].shape == XInitial) - apply[i] |= IsolProperty|MediProperty|FinaProperty; - } - - if (!openType->shape(item, apply.data())) { - *ot_ok = false; - return false; - } - item->num_glyphs = nglyphs; - return openType->positionAndAdd(item); -} - -#endif - -// #### stil missing: identify invalid character combinations -static bool arabic_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script == TQFont::Arabic); - -#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) - TQOpenType *openType = item->font->openType(); - - if (openType && openType->supportsScript(TQFont::Arabic)) { - bool ot_ok; - if (arabicSyriacOpenTypeShape(openType, item, &ot_ok)) - return true; - if (ot_ok) - return false; - // fall through to the non OT code - } -#endif - - TQVarLengthArray shapedChars(item->length); - - int slen; - shapedString(item->string, item->from, item->length, (TQChar *)shapedChars.data(), &slen, - item->flags & TQTextEngine::RightToLeft, - item->attributes, item->log_clusters); - - if (item->font->stringToCMap((TQChar *)shapedChars.data(), slen, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - for (int i = 0; i < slen; ++i) - if (item->attributes[i].mark) - item->advances[i] = 0; - qt_heuristicPosition(item); - return TRUE; -} - -#if defined(TQ_WS_X11) -# include "qscriptengine_x11.cpp" -#elif defined(TQ_WS_WIN) -# include "qscriptengine_win.cpp" -#elif defined(TQ_WS_MAC) -# include "qscriptengine_mac.cpp" -#endif diff --git a/src/kernel/qscriptengine_p.h b/src/kernel/qscriptengine_p.h deleted file mode 100644 index 77dd87b96..000000000 --- a/src/kernel/qscriptengine_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the $MODULE$ of the TQt Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -****************************************************************************/ - -#ifndef TQSCRIPTENGINE_P_H -#define TQSCRIPTENGINE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "tqtextengine_p.h" - -class TQString; -struct TQCharAttributes; - -struct TQShaperItem { - int script; - const TQString *string; - int from; - int length; - TQFontEngine *font; - glyph_t *glyphs; - advance_t *advances; - qoffset_t *offsets; - GlyphAttributes *attributes; - int num_glyphs; // in: available glyphs out: glyphs used/needed - unsigned short *log_clusters; - int flags; - bool has_positioning; -}; - -// return true if ok. -typedef bool (*ShapeFunction)(TQShaperItem *item); -typedef void (*AttributeFunction)(int script, const TQString &, int, int, TQCharAttributes *); - -struct q_scriptEngine { - ShapeFunction shape; - AttributeFunction charAttributes; -}; - -extern const q_scriptEngine scriptEngines[]; - -#endif // TQSCRIPTENGINE_P_H diff --git a/src/kernel/qscriptengine_x11.cpp b/src/kernel/qscriptengine_x11.cpp deleted file mode 100644 index 5d22fdf49..000000000 --- a/src/kernel/qscriptengine_x11.cpp +++ /dev/null @@ -1,3744 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -// ------------------------------------------------------------------------------------------------------------------ -// -// Continuation of middle eastern languages -// -// ------------------------------------------------------------------------------------------------------------------ - -// #### stil missing: identify invalid character combinations -static bool syriac_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script == TQFont::Syriac); - -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - if (openType && openType->supportsScript(TQFont::Syriac)) { - bool ot_ok; - if (arabicSyriacOpenTypeShape(openType, item, &ot_ok)) - return true; - if (ot_ok) - return false; - // fall through to the non OT code - } -#endif - return basic_shape(item); -} - - -static bool thaana_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script == TQFont::Thaana); - -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - - if (openType && openType->supportsScript(item->script)) { - openType->selectScript(TQFont::Thaana); - if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - heuristicSetGlyphAttributes(item); - openType->shape(item); - return openType->positionAndAdd(item); - } -#endif - return basic_shape(item); -} - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Indic languages -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -enum Form { - Invalid = 0x0, - Unknown = Invalid, - Consonant, - Nukta, - Halant, - Matra, - VowelMark, - StressMark, - IndependentVowel, - LengthMark, - Control, - Other -}; - -static const unsigned char indicForms[0xe00-0x900] = { - // Devangari - Invalid, VowelMark, VowelMark, VowelMark, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Nukta, Other, Matra, Matra, - - Matra, Matra, Matra, Matra, - Matra, Matra, Matra, Matra, - Matra, Matra, Matra, Matra, - Matra, Halant, Unknown, Unknown, - - Other, StressMark, StressMark, StressMark, - StressMark, Unknown, Unknown, Unknown, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - IndependentVowel, IndependentVowel, VowelMark, VowelMark, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Consonant, - Consonant, Consonant /* ??? */, Consonant, Consonant, - - // Bengali - Invalid, VowelMark, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, Invalid, Invalid, IndependentVowel, - - IndependentVowel, Invalid, Invalid, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Invalid, Consonant, Invalid, - Invalid, Invalid, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Nukta, Other, Matra, Matra, - - Matra, Matra, Matra, Matra, - Matra, Invalid, Invalid, Matra, - Matra, Invalid, Invalid, Matra, - Matra, Halant, Consonant, Unknown, - - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, VowelMark, - Invalid, Invalid, Invalid, Invalid, - Consonant, Consonant, Invalid, Consonant, - - IndependentVowel, IndependentVowel, VowelMark, VowelMark, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Consonant, Consonant, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Gurmukhi - Invalid, VowelMark, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, Invalid, - Invalid, Invalid, Invalid, IndependentVowel, - - IndependentVowel, Invalid, Invalid, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Invalid, Consonant, Consonant, - Invalid, Consonant, Consonant, Invalid, - Consonant, Consonant, Unknown, Unknown, - Nukta, Other, Matra, Matra, - - Matra, Matra, Matra, Invalid, - Invalid, Invalid, Invalid, Matra, - Matra, Invalid, Invalid, Matra, - Matra, Halant, Unknown, Unknown, - - Invalid, Invalid, Invalid, Invalid, - Invalid, Unknown, Unknown, Unknown, - Invalid, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Invalid, - - Other, Other, Invalid, Invalid, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - StressMark, StressMark, Consonant, Consonant, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Gujarati - Invalid, VowelMark, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, Invalid, IndependentVowel, - - IndependentVowel, IndependentVowel, Invalid, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Invalid, Consonant, Consonant, - Invalid, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Nukta, Other, Matra, Matra, - - Matra, Matra, Matra, Matra, - Matra, Matra, Invalid, Matra, - Matra, Matra, Invalid, Matra, - Matra, Halant, Unknown, Unknown, - - Other, Unknown, Unknown, Unknown, - Unknown, Unknown, Unknown, Unknown, - Unknown, Unknown, Unknown, Unknown, - Unknown, Unknown, Unknown, Unknown, - - IndependentVowel, IndependentVowel, VowelMark, VowelMark, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Oriya - Invalid, VowelMark, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, Invalid, Invalid, IndependentVowel, - - IndependentVowel, Invalid, Invalid, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Invalid, Consonant, Consonant, - Invalid, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Nukta, Other, Matra, Matra, - - Matra, Matra, Matra, Matra, - Invalid, Invalid, Invalid, Matra, - Matra, Invalid, Invalid, Matra, - Matra, Halant, Unknown, Unknown, - - Other, Invalid, Invalid, Invalid, - Invalid, Unknown, LengthMark, LengthMark, - Invalid, Invalid, Invalid, Invalid, - Consonant, Consonant, Invalid, Consonant, - - IndependentVowel, IndependentVowel, Invalid, Invalid, - Invalid, Invalid, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Consonant, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - //Tamil - Invalid, Invalid, VowelMark, Other, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, Invalid, - Invalid, Invalid, IndependentVowel, IndependentVowel, - - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - IndependentVowel, Consonant, Invalid, Invalid, - Invalid, Consonant, Consonant, Invalid, - Consonant, Invalid, Consonant, Consonant, - - Invalid, Invalid, Invalid, Consonant, - Consonant, Invalid, Invalid, Invalid, - Consonant, Consonant, Consonant, Invalid, - Invalid, Invalid, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Invalid, Invalid, Matra, Matra, - - Matra, Matra, Matra, Invalid, - Invalid, Invalid, Matra, Matra, - Matra, Invalid, Matra, Matra, - Matra, Halant, Invalid, Invalid, - - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, LengthMark, - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, Invalid, - - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Telugu - Invalid, VowelMark, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Invalid, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Invalid, Invalid, Matra, Matra, - - Matra, Matra, Matra, Matra, - Matra, Invalid, Matra, Matra, - Matra, Invalid, Matra, Matra, - Matra, Halant, Invalid, Invalid, - - Invalid, Invalid, Invalid, Invalid, - Invalid, LengthMark, Matra, Invalid, - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, Invalid, - - IndependentVowel, IndependentVowel, Invalid, Invalid, - Invalid, Invalid, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Kannada - Invalid, Invalid, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Invalid, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Nukta, Other, Matra, Matra, - - Matra, Matra, Matra, Matra, - Matra, Invalid, Matra, Matra, - Matra, Invalid, Matra, Matra, - Matra, Halant, Invalid, Invalid, - - Invalid, Invalid, Invalid, Invalid, - Invalid, LengthMark, LengthMark, Invalid, - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Consonant, Invalid, - - IndependentVowel, IndependentVowel, VowelMark, VowelMark, - Invalid, Invalid, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Malayalam - Invalid, Invalid, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - - IndependentVowel, Invalid, IndependentVowel, IndependentVowel, - IndependentVowel, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Unknown, Unknown, - Invalid, Invalid, Matra, Matra, - - Matra, Matra, Matra, Matra, - Invalid, Invalid, Matra, Matra, - Matra, Invalid, Matra, Matra, - Matra, Halant, Invalid, Invalid, - - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, LengthMark, - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, Invalid, - - IndependentVowel, IndependentVowel, Invalid, Invalid, - Invalid, Invalid, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, - - // Sinhala - Invalid, Invalid, VowelMark, VowelMark, - Invalid, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - - IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, - IndependentVowel, IndependentVowel, IndependentVowel, Invalid, - Invalid, Invalid, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - - Consonant, Consonant, Invalid, Consonant, - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Consonant, - Invalid, Consonant, Invalid, Invalid, - - Consonant, Consonant, Consonant, Consonant, - Consonant, Consonant, Consonant, Invalid, - Invalid, Invalid, Halant, Invalid, - Invalid, Invalid, Invalid, Matra, - - Matra, Matra, Matra, Matra, - Matra, Invalid, Matra, Invalid, - Matra, Matra, Matra, Matra, - Matra, Matra, Matra, Matra, - - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, Invalid, - Invalid, Invalid, Invalid, Invalid, - - Invalid, Invalid, Matra, Matra, - Other, Other, Other, Other, - Other, Other, Other, Other, - Other, Other, Other, Other, -}; - -enum Position { - None, - Pre, - Above, - Below, - Post, - Split, - Base, - Reph, - Vattu, - Inherit -}; - -static const unsigned char indicPosition[0xe00-0x900] = { - // Devanagari - None, Above, Above, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - Below, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, Post, Pre, - - Post, Below, Below, Below, - Below, Above, Above, Above, - Above, Post, Post, Post, - Post, None, None, None, - - None, Above, Below, Above, - Above, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, Below, Below, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Bengali - None, Above, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - Below, None, None, Post, - - Below, None, None, None, - None, None, None, None, - None, None, None, None, - Below, None, Post, Pre, - - Post, Below, Below, Below, - Below, None, None, Pre, - Pre, None, None, Split, - Split, Below, None, None, - - None, None, None, None, - None, None, None, Post, - None, None, None, None, - None, None, None, None, - - None, None, Below, Below, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Gurmukhi - None, Above, Above, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, Post, - - Below, None, None, None, - None, Below, None, None, - None, Below, None, None, - Below, None, Post, Pre, - - Post, Below, Below, None, - None, None, None, Above, - Above, None, None, Above, - Above, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - Above, Above, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Gujarati - None, Above, Above, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - Below, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, Post, Pre, - - Post, Below, Below, Below, - Below, Above, None, Above, - Above, Post, None, Post, - Post, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, Below, Below, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Oriya - None, Above, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - Below, None, None, None, - Below, None, None, None, - Below, Below, Below, Post, - - Below, None, Below, Below, - None, None, None, None, - None, None, None, None, - None, None, Post, Above, - - Post, Below, Below, Below, - None, None, None, Pre, - Split, None, None, Split, - Split, None, None, None, - - None, None, None, None, - None, None, Above, Post, - None, None, None, None, - None, None, None, Post, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, Below, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Tamil - None, None, Above, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, Post, Post, - - Above, Below, Below, None, - None, None, Pre, Pre, - Pre, None, Split, Split, - Split, Halant, None, None, - - None, None, None, None, - None, None, None, Post, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Telugu - None, Post, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, Below, Below, Below, - Below, Below, Below, Below, - Below, Below, Below, Below, - - Below, Below, Below, Below, - Below, Below, Below, Below, - Below, None, Below, Below, - Below, Below, Below, Below, - - Below, None, Below, Below, - None, Below, Below, Below, - Below, Below, None, None, - None, None, Post, Above, - - Above, Post, Post, Post, - Post, None, Above, Above, - Split, None, Post, Above, - Above, Halant, None, None, - - None, None, None, None, - None, Above, Below, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Kannada - None, None, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, Below, Below, Below, - Below, Below, Below, Below, - Below, Below, Below, Below, - - Below, Below, Below, Below, - Below, Below, Below, Below, - Below, Below, Below, Below, - Below, Below, Below, Below, - - Below, None, Below, Below, - None, Below, Below, Below, - Below, Below, None, None, - None, None, Post, Above, - - Split, Post, Post, Post, - Post, None, Above, Split, - Split, None, Split, Split, - Above, Halant, None, None, - - None, None, None, None, - None, Post, Post, None, - None, None, None, None, - None, None, Below, None, - - None, None, Below, Below, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Malayalam - None, None, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, Post, - - Post, None, Below, None, - None, Post, None, None, - None, None, None, None, - None, None, Post, Post, - - Post, Post, Post, Post, - None, None, Pre, Pre, - Pre, None, Split, Split, - Split, Halant, None, None, - - None, None, None, None, - None, None, None, Post, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - // Sinhala - None, None, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, Post, - - Post, Post, Above, Above, - Below, None, Below, None, - Post, Pre, Split, Pre, - Split, Split, Split, Post, - - None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, - - None, None, Post, Post, - None, None, None, None, - None, None, None, None, - None, None, None, None -}; - -static inline Form form(unsigned short uc) { - if (uc < 0x900 || uc > 0xdff) { - if (uc == 0x25cc) - return Consonant; - if (uc == 0x200c || uc == 0x200d) - return Control; - return Other; - } - return (Form)indicForms[uc-0x900]; -} - -static inline Position indic_position(unsigned short uc) { - if (uc < 0x900 || uc > 0xdff) - return None; - return (Position) indicPosition[uc-0x900]; -} - - -enum IndicScriptProperties { - HasReph = 0x01, - HasSplit = 0x02 -}; - -const uchar scriptProperties[10] = { - // Devanagari, - HasReph, - // Bengali, - HasReph|HasSplit, - // Gurmukhi, - 0, - // Gujarati, - HasReph, - // Oriya, - HasReph|HasSplit, - // Tamil, - HasSplit, - // Telugu, - HasSplit, - // Kannada, - HasSplit|HasReph, - // Malayalam, - HasSplit, - // Sinhala, - HasSplit -}; - -struct IndicOrdering { - Form form; - Position position; -}; - -static const IndicOrdering devanagari_order [] = { - { Consonant, Below }, - { Matra, Below }, - { VowelMark, Below }, - { StressMark, Below }, - { Matra, Above }, - { Matra, Post }, - { Consonant, Reph }, - { VowelMark, Above }, - { StressMark, Above }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering bengali_order [] = { - { Consonant, Below }, - { Matra, Below }, - { Matra, Above }, - { Consonant, Reph }, - { VowelMark, Above }, - { Consonant, Post }, - { Matra, Post }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering gurmukhi_order [] = { - { Consonant, Below }, - { Matra, Below }, - { Matra, Above }, - { Consonant, Post }, - { Matra, Post }, - { VowelMark, Above }, - { (Form)0, None } -}; - -static const IndicOrdering tamil_order [] = { - { Matra, Above }, - { Matra, Post }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering telugu_order [] = { - { Matra, Above }, - { Matra, Below }, - { Matra, Post }, - { Consonant, Below }, - { Consonant, Post }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering kannada_order [] = { - { Matra, Above }, - { Matra, Post }, - { Consonant, Below }, - { Consonant, Post }, - { LengthMark, Post }, - { Consonant, Reph }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering malayalam_order [] = { - { Consonant, Below }, - { Matra, Below }, - { Consonant, Reph }, - { Consonant, Post }, - { Matra, Post }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering sinhala_order [] = { - { Matra, Below }, - { Matra, Above }, - { Matra, Post }, - { VowelMark, Post }, - { (Form)0, None } -}; - -static const IndicOrdering * const indic_order[] = { - devanagari_order, // Devanagari - bengali_order, // Bengali - gurmukhi_order, // Gurmukhi - devanagari_order, // Gujarati - bengali_order, // Oriya - tamil_order, // Tamil - telugu_order, // Telugu - kannada_order, // Kannada - malayalam_order, // Malayalam - sinhala_order // Sinhala -}; - - - -// vowel matras that have to be split into two parts. -static const unsigned short split_matras[] = { - // matra, split1, split2 - - // bengalis - 0x9cb, 0x9c7, 0x9be, - 0x9cc, 0x9c7, 0x9d7, - // oriya - 0xb48, 0xb47, 0xb56, - 0xb4b, 0xb47, 0xb3e, - 0xb4c, 0xb47, 0xb57, - // tamil - 0xbca, 0xbc6, 0xbbe, - 0xbcb, 0xbc7, 0xbbe, - 0xbcc, 0xbc6, 0xbd7, - // telugu - 0xc48, 0xc46, 0xc56, - // kannada - 0xcc0, 0xcbf, 0xcd5, - 0xcc7, 0xcc6, 0xcd5, - 0xcc8, 0xcc6, 0xcd6, - 0xcca, 0xcc6, 0xcc2, - 0xccb, 0xcca, 0xcd5, - // malayalam - 0xd4a, 0xd46, 0xd3e, - 0xd4b, 0xd47, 0xd3e, - 0xd4c, 0xd46, 0xd57, - // sinhala - 0xdda, 0xdd9, 0xdca, - 0xddc, 0xdd9, 0xdcf, - 0xddd, 0xddc, 0xdca, - 0xdde, 0xdd9, 0xddf, - 0xffff -}; - -static inline void splitMatra(unsigned short *reordered, int matra, int &len, int &base) -{ - unsigned short matra_uc = reordered[matra]; - //tqDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]); - - const unsigned short *split = split_matras; - while (split[0] < matra_uc) - split += 3; - - assert(*split == matra_uc); - ++split; - - if (indic_position(*split) == Pre) { - reordered[matra] = split[1]; - memmove(reordered + 1, reordered, len*sizeof(unsigned short)); - reordered[0] = split[0]; - base++; - } else { - memmove(reordered + matra + 1, reordered + matra, (len-matra)*sizeof(unsigned short)); - reordered[matra] = split[0]; - reordered[matra+1] = split[1]; - } - len++; -} - -enum IndicProperties { - // these two are already defined -// CcmpProperty = 0x1, -// InitProperty = 0x2, - NuktaProperty = 0x4, - AkhantProperty = 0x8, - RephProperty = 0x10, - PreFormProperty = 0x20, - BelowFormProperty = 0x40, - AboveFormProperty = 0x80, - HalfFormProperty = 0x100, - PostFormProperty = 0x200, - VattuProperty = 0x400, - PreSubstProperty = 0x800, - BelowSubstProperty = 0x1000, - AboveSubstProperty = 0x2000, - PostSubstProperty = 0x4000, - HalantProperty = 0x8000, - CligProperty = 0x10000 -}; - -#ifndef TQT_NO_XFTFREETYPE -static const TQOpenType::Features indic_features[] = { - { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, - { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, - { FT_MAKE_TAG('n', 'u', 'k', 't'), NuktaProperty }, - { FT_MAKE_TAG('a', 'k', 'h', 'n'), AkhantProperty }, - { FT_MAKE_TAG('r', 'p', 'h', 'f'), RephProperty }, - { FT_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty }, - { FT_MAKE_TAG('h', 'a', 'l', 'f'), HalfFormProperty }, - { FT_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty }, - { FT_MAKE_TAG('v', 'a', 't', 'u'), VattuProperty }, - { FT_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty }, - { FT_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty }, - { FT_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty }, - { FT_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty }, - { FT_MAKE_TAG('h', 'a', 'l', 'n'), HalantProperty }, - { 0, 0 } -}; -#endif - -// #define INDIC_DEBUG -#ifdef INDIC_DEBUG -#define IDEBUG tqDebug -#else -#define IDEBUG if(0) tqDebug -#endif - -#ifdef INDIC_DEBUG -static TQString propertiesToString(int properties) -{ - TQString res; - properties = ~properties; - if (properties & CcmpProperty) - res += "Ccmp "; - if (properties & InitProperty) - res += "Init "; - if (properties & NuktaProperty) - res += "Nukta "; - if (properties & AkhantProperty) - res += "Akhant "; - if (properties & RephProperty) - res += "Reph "; - if (properties & PreFormProperty) - res += "PreForm "; - if (properties & BelowFormProperty) - res += "BelowForm "; - if (properties & AboveFormProperty) - res += "AboveForm "; - if (properties & HalfFormProperty) - res += "HalfForm "; - if (properties & PostFormProperty) - res += "PostForm "; - if (properties & VattuProperty) - res += "Vattu "; - if (properties & PreSubstProperty) - res += "PreSubst "; - if (properties & BelowSubstProperty) - res += "BelowSubst "; - if (properties & AboveSubstProperty) - res += "AboveSubst "; - if (properties & PostSubstProperty) - res += "PostSubst "; - if (properties & HalantProperty) - res += "Halant "; - if (properties & CligProperty) - res += "Clig "; - return res; -} -#endif - -static bool indic_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool invalid) -{ - Q_UNUSED(openType) - int script = item->script; - Q_ASSERT(script >= TQFont::Devanagari && script <= TQFont::Sinhala); - const unsigned short script_base = 0x0900 + 0x80*(script-TQFont::Devanagari); - const unsigned short ra = script_base + 0x30; - const unsigned short halant = script_base + 0x4d; - const unsigned short nukta = script_base + 0x3c; - - int len = item->length; - IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->from, item->length, invalid); - - if (item->num_glyphs < len+4) { - item->num_glyphs = len+4; - return FALSE; - } - - TQVarLengthArray reordered(len+4); - TQVarLengthArray position(len+4); - - unsigned char properties = scriptProperties[script-TQFont::Devanagari]; - - if (invalid) { - *reordered.data() = 0x25cc; - memcpy(reordered.data()+1, item->string->unicode() + item->from, len*sizeof(TQChar)); - len++; - } else { - memcpy(reordered.data(), item->string->unicode() + item->from, len*sizeof(TQChar)); - } - if (reordered[len-1] == 0x200c) // zero width non joiner - len--; - - int i; - int base = 0; - int reph = -1; - -#ifdef INDIC_DEBUG - IDEBUG("original:"); - for (i = 0; i < len; i++) { - IDEBUG(" %d: %4x", i, reordered[i]); - } -#endif - - if (len != 1) { - unsigned short *uc = reordered.data(); - bool beginsWithRa = FALSE; - - // Rule 1: find base consonant - // - // The shaping engine finds the base consonant of the - // syllable, using the following algorithm: starting from the - // end of the syllable, move backwards until a consonant is - // found that does not have a below-base or post-base form - // (post-base forms have to follow below-base forms), or - // arrive at the first consonant. The consonant stopped at - // will be the base. - // - // * If the syllable starts with Ra + H (in a script that has - // 'Reph'), Ra is excluded from candidates for base - // consonants. - // - // * In Kannada and Telugu, the base consonant cannot be - // farther than 3 consonants from the end of the syllable. - // #### replace the HasReph property by testing if the feature exists in the font! - if (form(*uc) == Consonant || (script == TQFont::Bengali && form(*uc) == IndependentVowel)) { - beginsWithRa = (properties & HasReph) && ((len > 2) && *uc == ra && *(uc+1) == halant); - - if (beginsWithRa && form(*(uc+2)) == Control) - beginsWithRa = FALSE; - - base = (beginsWithRa ? 2 : 0); - IDEBUG(" length = %d, beginsWithRa = %d, base=%d", len, beginsWithRa, base); - - int lastConsonant = 0; - int matra = -1; - // we remember: - // * the last consonant since we need it for rule 2 - // * the matras position for rule 3 and 4 - - // figure out possible base glyphs - memset(position.data(), 0, len); - if (script == TQFont::Devanagari || script == TQFont::Gujarati) { - bool vattu = FALSE; - for (i = base; i < len; ++i) { - position[i] = form(uc[i]); - if (position[i] == Consonant) { - lastConsonant = i; - vattu = (!vattu && uc[i] == ra); - if (vattu) { - IDEBUG("excluding vattu glyph at %d from base candidates", i); - position[i] = Vattu; - } - } else if (position[i] == Matra) { - matra = i; - } - } - } else { - for (i = base; i < len; ++i) { - position[i] = form(uc[i]); - if (position[i] == Consonant) - lastConsonant = i; - else if (matra < 0 && position[i] == Matra) - matra = i; - } - } - int skipped = 0; - Position pos = Post; - for (i = len-1; i > base; i--) { - if (position[i] != Consonant && (position[i] != Control || script == TQFont::Kannada)) - continue; - - Position charPosition = indic_position(uc[i]); - if (pos == Post && charPosition == Post) { - pos = Post; - } else if ((pos == Post || pos == Below) && charPosition == Below) { - if (script == TQFont::Devanagari || script == TQFont::Gujarati) - base = i; - pos = Below; - } else { - base = i; - break; - } - if (skipped == 2 && (script == TQFont::Kannada || script == TQFont::Telugu)) { - base = i; - break; - } - ++skipped; - } - - IDEBUG(" base consonant at %d skipped=%d, lastConsonant=%d", base, skipped, lastConsonant); - - // Rule 2: - // - // If the base consonant is not the last one, Uniscribe - // moves the halant from the base consonant to the last - // one. - if (lastConsonant > base) { - int halantPos = 0; - if (uc[base+1] == halant) - halantPos = base + 1; - else if (uc[base+1] == nukta && uc[base+2] == halant) - halantPos = base + 2; - if (halantPos > 0) { - IDEBUG(" moving halant from %d to %d!", base+1, lastConsonant); - for (i = halantPos; i < lastConsonant; i++) - uc[i] = uc[i+1]; - uc[lastConsonant] = halant; - } - } - - // Rule 3: - // - // If the syllable starts with Ra + H, Uniscribe moves - // this combination so that it follows either: - - // * the post-base 'matra' (if any) or the base consonant - // (in scripts that show similarity to Devanagari, i.e., - // Devanagari, Gujarati, Bengali) - // * the base consonant (other scripts) - // * the end of the syllable (Kannada) - - Position matra_position = None; - if (matra > 0) - matra_position = indic_position(uc[matra]); - IDEBUG(" matra at %d with form %d, base=%d", matra, matra_position, base); - - if (beginsWithRa && base != 0) { - int toPos = base+1; - if (toPos < len && uc[toPos] == nukta) - toPos++; - if (toPos < len && uc[toPos] == halant) - toPos++; - if (toPos < len && uc[toPos] == 0x200d) - toPos++; - if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant) - toPos += 2; - if (script == TQFont::Devanagari || script == TQFont::Gujarati || script == TQFont::Bengali) { - if (matra_position == Post || matra_position == Split) { - toPos = matra+1; - matra -= 2; - } - } else if (script == TQFont::Kannada) { - toPos = len; - matra -= 2; - } - - IDEBUG("moving leading ra+halant to position %d", toPos); - for (i = 2; i < toPos; i++) - uc[i-2] = uc[i]; - uc[toPos-2] = ra; - uc[toPos-1] = halant; - base -= 2; - if (properties & HasReph) - reph = toPos-2; - } - - // Rule 4: - - // Uniscribe splits two- or three-part matras into their - // parts. This splitting is a character-to-character - // operation). - // - // Uniscribe describes some moving operations for these - // matras here. For shaping however all pre matras need - // to be at the begining of the syllable, so we just move - // them there now. - if (matra_position == Split) { - splitMatra(uc, matra, len, base); - // Handle three-part matras (0xccb in Kannada) - matra_position = indic_position(uc[matra]); - if (matra_position == Split) - splitMatra(uc, matra, len, base); - } else if (matra_position == Pre) { - unsigned short m = uc[matra]; - while (matra--) - uc[matra+1] = uc[matra]; - uc[0] = m; - base++; - } - } - - // Rule 5: - // - // Uniscribe classifies consonants and 'matra' parts as - // pre-base, above-base (Reph), below-base or post-base. This - // classification exists on the character code level and is - // language-dependent, not font-dependent. - for (i = 0; i < base; ++i) - position[i] = Pre; - position[base] = Base; - for (i = base+1; i < len; ++i) { - position[i] = indic_position(uc[i]); - // #### replace by adjusting table - if (uc[i] == nukta || uc[i] == halant) - position[i] = Inherit; - } - if (reph > 0) { - // recalculate reph, it might have changed. - for (i = base+1; i < len; ++i) - if (uc[i] == ra) - reph = i; - position[reph] = Reph; - position[reph+1] = Inherit; - } - - // all reordering happens now to the chars after the base - int fixed = base+1; - if (fixed < len && uc[fixed] == nukta) - fixed++; - if (fixed < len && uc[fixed] == halant) - fixed++; - if (fixed < len && uc[fixed] == 0x200d) - fixed++; - -#ifdef INDIC_DEBUG - for (i = fixed; i < len; ++i) - IDEBUG("position[%d] = %d, form=%d", i, position[i], form(uc[i])); -#endif - // we continuosly position the matras and vowel marks and increase the fixed - // until we reached the end. - const IndicOrdering *finalOrder = indic_order[script-TQFont::Devanagari]; - - IDEBUG(" reordering pass:"); - //IDEBUG(" base=%d fixed=%d", base, fixed); - int toMove = 0; - while (finalOrder[toMove].form && fixed < len-1) { - //IDEBUG(" fixed = %d, moving form %d with pos %d", fixed, finalOrder[toMove].form, finalOrder[toMove].position); - for (i = fixed; i < len; i++) { - if (form(uc[i]) == finalOrder[toMove].form && - position[i] == finalOrder[toMove].position) { - // need to move this glyph - int to = fixed; - if (i < len-1 && position[i+1] == Inherit) { - IDEBUG(" moving two chars from %d to %d", i, to); - unsigned short ch = uc[i]; - unsigned short ch2 = uc[i+1]; - unsigned char pos = position[i]; - for (int j = i+1; j > to+1; j--) { - uc[j] = uc[j-2]; - position[j] = position[j-2]; - } - uc[to] = ch; - uc[to+1] = ch2; - position[to] = pos; - position[to+1] = pos; - fixed += 2; - } else { - IDEBUG(" moving one char from %d to %d", i, to); - unsigned short ch = uc[i]; - unsigned char pos = position[i]; - for (int j = i; j > to; j--) { - uc[j] = uc[j-1]; - position[j] = position[j-1]; - } - uc[to] = ch; - position[to] = pos; - fixed++; - } - } - } - toMove++; - } - - } - - if (reph > 0) { - // recalculate reph, it might have changed. - for (i = base+1; i < len; ++i) - if (reordered[i] == ra) - reph = i; - } - - if (item->font->stringToCMap((const TQChar *)reordered.data(), len, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - - IDEBUG(" base=%d, reph=%d", base, reph); - IDEBUG("reordered:"); - for (i = 0; i < len; i++) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = FALSE; - item->attributes[i].justification = 0; - item->attributes[i].zeroWidth = FALSE; - IDEBUG(" %d: %4x", i, reordered[i]); - } - - // now we have the syllable in the right order, and can start running it through open type. - - bool control = FALSE; - for (i = 0; i < len; ++i) - control |= (form(reordered[i]) == Control); - -#ifndef TQT_NO_XFTFREETYPE - if (openType) { - - // we need to keep track of where the base glyph is for some - // scripts and use the cluster feature for this. This - // also means we have to correct the logCluster output from - // the open type engine manually afterwards. for indic this - // is rather simple, as all chars just point to the first - // glyph in the syllable. - TQVarLengthArray clusters(len); - TQVarLengthArray properties(len); - - for (i = 0; i < len; ++i) - clusters[i] = i; - - // features we should always apply - for (i = 0; i < len; ++i) - properties[i] = ~(CcmpProperty - | NuktaProperty - | VattuProperty - | PreSubstProperty - | BelowSubstProperty - | AboveSubstProperty - | HalantProperty - | PositioningProperties); - - // Ccmp always applies - // Init - if (item->from == 0 - || !(item->string->unicode()[item->from-1].isLetter() || item->string->unicode()[item->from-1].isMark())) - properties[0] &= ~InitProperty; - - // Nukta always applies - // Akhant - for (i = 0; i <= base; ++i) - properties[i] &= ~AkhantProperty; - // Reph - if (reph >= 0) { - properties[reph] &= ~RephProperty; - properties[reph+1] &= ~RephProperty; - } - // BelowForm - for (i = base+1; i < len; ++i) - properties[i] &= ~BelowFormProperty; - - if (script == TQFont::Devanagari || script == TQFont::Gujarati) { - // vattu glyphs need this aswell - bool vattu = FALSE; - for (i = base-2; i > 1; --i) { - if (form(reordered[i]) == Consonant) { - vattu = (!vattu && reordered[i] == ra); - if (vattu) { - IDEBUG("forming vattu ligature at %d", i); - properties[i] &= ~BelowFormProperty; - properties[i+1] &= ~BelowFormProperty; - } - } - } - } - // HalfFormProperty - for (i = 0; i < base; ++i) - properties[i] &= ~HalfFormProperty; - if (control) { - for (i = 2; i < len; ++i) { - if (reordered[i] == 0x200d /* ZWJ */) { - properties[i-1] &= ~HalfFormProperty; - properties[i-2] &= ~HalfFormProperty; - } else if (reordered[i] == 0x200c /* ZWNJ */) { - properties[i-1] &= ~HalfFormProperty; - properties[i-2] &= ~HalfFormProperty; - } - } - } - // PostFormProperty - for (i = base+1; i < len; ++i) - properties[i] &= ~PostFormProperty; - // vattu always applies - // pres always applies - // blws always applies - // abvs always applies - - // psts - // ### this looks slightly different from before, but I believe it's correct - if (reordered[len-1] != halant || base != len-2) - properties[base] &= ~PostSubstProperty; - for (i = base+1; i < len; ++i) - properties[i] &= ~PostSubstProperty; - - // halant always applies - -#ifdef INDIC_DEBUG - { - IDEBUG("OT properties:"); - for (int i = 0; i < len; ++i) - tqDebug(" i: %s", ::propertiesToString(properties[i]).toLatin1().data()); - } -#endif - - // initialize - item->log_clusters = clusters.data(); - openType->shape(item, properties.data()); - - int newLen = openType->len(); - OTL_GlyphItem otl_glyphs = openType->glyphs(); - - // move the left matra back to it's correct position in malayalam and tamil - if ((script == TQFont::Malayalam || script == TQFont::Tamil) && (form(reordered[0]) == Matra)) { -// tqDebug("reordering matra, len=%d", newLen); - // need to find the base in the shaped string and move the matra there - int basePos = 0; - while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base) - basePos++; - --basePos; - if (basePos < newLen && basePos > 1) { -// tqDebug("moving prebase matra to position %d in syllable newlen=%d", basePos, newLen); - OTL_GlyphItemRec m = otl_glyphs[0]; - --basePos; - for (i = 0; i < basePos; ++i) - otl_glyphs[i] = otl_glyphs[i+1]; - otl_glyphs[basePos] = m; - } - } - - if (!openType->positionAndAdd(item, FALSE)) - return FALSE; - - if (control) { - IDEBUG("found a control char in the syllable"); - int i = 0, j = 0; - while (i < item->num_glyphs) { - if (form(reordered[otl_glyphs[i].cluster]) == Control) { - ++i; - if (i >= item->num_glyphs) - break; - } - item->glyphs[j] = item->glyphs[i]; - ++i; - ++j; - } - item->num_glyphs = j; - } - - } -#endif - - item->attributes[0].clusterStart = TRUE; - IDEBUG("<<<<<<"); - return TRUE; -} - - -/* syllables are of the form: - - (Consonant Nukta? Halant)* Consonant Matra? VowelMark? StressMark? - (Consonant Nukta? Halant)* Consonant Halant - IndependentVowel VowelMark? StressMark? - - We return syllable boundaries on invalid combinations aswell -*/ -static int indic_nextSyllableBoundary(int script, const TQString &s, int start, int end, bool *invalid) -{ - *invalid = FALSE; - IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end); - const TQChar *uc = s.unicode()+start; - - int pos = 0; - Form state = form(uc[pos].unicode()); - IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos].unicode()); - pos++; - - if (state != Consonant && state != IndependentVowel) { - if (state != Other) - *invalid = TRUE; - goto finish; - } - - while (pos < end - start) { - Form newState = form(uc[pos].unicode()); - IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos].unicode()); - switch(newState) { - case Control: - newState = state; - if (state == Halant && uc[pos].unicode() == 0x200d /* ZWJ */) - break; - // the control character should be the last char in the item - ++pos; - goto finish; - case Consonant: - if (state == Halant && (script != TQFont::Sinhala || uc[pos-1].unicode() == 0x200d /* ZWJ */)) - break; - goto finish; - case Halant: - if (state == Nukta || state == Consonant) - break; - // Bengali has a special exception allowing the combination Vowel_A/E + Halant + Ya - if (script == TQFont::Bengali && pos == 1 && - (uc[0].unicode() == 0x0985 || uc[0].unicode() == 0x098f)) - break; - goto finish; - case Nukta: - if (state == Consonant) - break; - goto finish; - case StressMark: - if (state == VowelMark) - break; - // fall through - case VowelMark: - if (state == Matra || state == IndependentVowel) - break; - // fall through - case Matra: - if (state == Consonant || state == Nukta) - break; - // ### not sure if this is correct. If it is, does it apply only to Bengali or should - // it work for all Indic languages? - // the combination Independent_A + Vowel Sign AA is allowed. - if (script == TQFont::Bengali && uc[pos].unicode() == 0x9be && uc[pos-1].unicode() == 0x985) - break; - if (script == TQFont::Tamil && state == Matra) { - if (uc[pos-1].unicode() == 0x0bc6 && - (uc[pos].unicode() == 0xbbe || uc[pos].unicode() == 0xbd7)) - break; - if (uc[pos-1].unicode() == 0x0bc7 && uc[pos].unicode() == 0xbbe) - break; - } - goto finish; - - case LengthMark: - case IndependentVowel: - case Invalid: - case Other: - goto finish; - } - state = newState; - pos++; - } - finish: - return pos+start; -} - -static bool indic_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script >= TQFont::Devanagari && item->script <= TQFont::Sinhala); - -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - if (openType) - openType->selectScript(item->script, indic_features); -#else - TQOpenType *openType = 0; -#endif - unsigned short *logClusters = item->log_clusters; - - TQShaperItem syllable = *item; - int first_glyph = 0; - - int sstart = item->from; - int end = sstart + item->length; - IDEBUG("indic_shape: from %d length %d", item->from, item->length); - while (sstart < end) { - bool invalid; - int send = indic_nextSyllableBoundary(item->script, *item->string, sstart, end, &invalid); - IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, - invalid ? "TRUE" : "FALSE"); - syllable.from = sstart; - syllable.length = send-sstart; - syllable.glyphs = item->glyphs + first_glyph; - syllable.offsets = item->offsets + first_glyph; - syllable.advances = item->advances + first_glyph; - syllable.attributes = item->attributes + first_glyph; - syllable.num_glyphs = item->num_glyphs - first_glyph; - if (!indic_shape_syllable(openType, &syllable, invalid)) { - IDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); - item->num_glyphs += syllable.num_glyphs; - return FALSE; - } - item->has_positioning |= syllable.has_positioning; - - // fix logcluster array - IDEBUG("syllable:"); - int i; - for (i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) - IDEBUG(" %d -> glyph %x", i, item->glyphs[i]); - IDEBUG(" logclusters:"); - for (i = sstart; i < send; ++i) { - IDEBUG(" %d -> glyph %d", i, first_glyph); - logClusters[i-item->from] = first_glyph; - } - sstart = send; - first_glyph += syllable.num_glyphs; - } - item->num_glyphs = first_glyph; - return TRUE; -} - - -static void indic_attributes(int script, const TQString &text, int from, int len, TQCharAttributes *attributes) -{ - int end = from + len; - const TQChar *uc = text.unicode() + from; - attributes += from; - int i = 0; - while (i < len) { - bool invalid; - int boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from; - attributes[i].charStop = TRUE; - - if (boundary > len-1) boundary = len; - i++; - while (i < boundary) { - attributes[i].charStop = FALSE; - ++uc; - ++i; - } - assert(i == boundary); - } - - -} - - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Thai and Lao -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -#include -#include - - -static void thaiWordBreaks(const TQChar *string, const int len, TQCharAttributes *attributes) -{ -#ifndef TQT_NO_TEXTCODEC - typedef int (*th_brk_def)(const char*, int[], int); - static TQTextCodec *thaiCodec = TQTextCodec::codecForMib(2259); - static th_brk_def th_brk = 0; - -#ifndef TQT_NO_LIBRARY - /* load libthai dynamically */ - if (!th_brk && thaiCodec) { - th_brk = (th_brk_def)TQLibrary::resolve("thai", "th_brk"); - if (!th_brk) - thaiCodec = 0; - } -#endif - - if (!th_brk) - return; - - TQCString cstr = thaiCodec->fromUnicode(TQConstString(string, len).string()); - - int brp[128]; - int *break_positions = brp; - int numbreaks = th_brk(cstr.data(), break_positions, 128); - if (numbreaks > 128) { - break_positions = new int[numbreaks]; - numbreaks = th_brk(cstr.data(),break_positions, numbreaks); - } - - attributes[0].softBreak = TRUE; - int i; - for (i = 1; i < len; ++i) - attributes[i].softBreak = FALSE; - - for (i = 0; i < numbreaks; ++i) - attributes[break_positions[i]].softBreak = TRUE; - - if (break_positions != brp) - delete [] break_positions; -#endif -} - - -static void thai_attributes( int script, const TQString &text, int from, int len, TQCharAttributes *attributes ) -{ - Q_UNUSED(script); - Q_ASSERT(script == TQFont::Thai); - thaiWordBreaks(text.unicode() + from, len, attributes); -} - - - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Tibetan -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -// tibetan syllables are of the form: -// head position consonant -// first sub-joined consonant -// ....intermediate sub-joined consonants (if any) -// last sub-joined consonant -// sub-joined vowel (a-chung U+0F71) -// standard or compound vowel sign (or 'virama' for devanagari transliteration) - -enum TibetanForm { - TibetanOther, - TibetanHeadConsonant, - TibetanSubjoinedConsonant, - TibetanSubjoinedVowel, - TibetanVowel -}; - -// this table starts at U+0f40 -static const unsigned char tibetanForm[0x80] = { - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, - TibetanOther, TibetanOther, TibetanOther, TibetanOther, - - TibetanOther, TibetanVowel, TibetanVowel, TibetanVowel, - TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, - TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, - TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, - - TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, - TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, - TibetanOther, TibetanOther, TibetanOther, TibetanOther, - TibetanOther, TibetanOther, TibetanOther, TibetanOther, - - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, - TibetanSubjoinedConsonant, TibetanOther, TibetanOther, TibetanOther -}; - - -static inline TibetanForm tibetan_form(const TQChar &c) -{ - return (TibetanForm)tibetanForm[c.unicode() - 0x0f40]; -} - -#ifndef TQT_NO_XFTFREETYPE -static const TQOpenType::Features tibetan_features[] = { - { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, - { FT_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty }, - { FT_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty }, - {0, 0} -}; -#endif - -static bool tibetan_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool invalid) -{ - Q_UNUSED(openType) - int len = item->length; - - if (item->num_glyphs < item->length + 4) { - item->num_glyphs = item->length + 4; - return FALSE; - } - - int i; - TQVarLengthArray reordered(len+4); - - const TQChar *str = item->string->unicode() + item->from; - if (invalid) { - *reordered.data() = 0x25cc; - memcpy(reordered.data()+1, str, len*sizeof(TQChar)); - len++; - str = (TQChar *)reordered.data(); - } - - if (item->font->stringToCMap(str, len, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - for (i = 0; i < item->length; i++) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = FALSE; - item->attributes[i].justification = 0; - item->attributes[i].zeroWidth = FALSE; - IDEBUG(" %d: %4x", i, str[i].unicode()); - } - - // now we have the syllable in the right order, and can start running it through open type. - -#ifndef TQT_NO_XFTFREETYPE - if (openType && openType->supportsScript(TQFont::Tibetan)) { - openType->selectScript(TQFont::Tibetan, tibetan_features); - - openType->shape(item); - if (!openType->positionAndAdd(item, FALSE)) - return FALSE; - } -#endif - - item->attributes[0].clusterStart = TRUE; - return TRUE; -} - - -static int tibetan_nextSyllableBoundary(const TQString &s, int start, int end, bool *invalid) -{ - const TQChar *uc = s.unicode() + start; - - int pos = 0; - TibetanForm state = tibetan_form(*uc); - -// tqDebug("state[%d]=%d (uc=%4x)", pos, state, uc[pos].unicode()); - pos++; - - if (state != TibetanHeadConsonant) { - if (state != TibetanOther) - *invalid = TRUE; - goto finish; - } - - while (pos < end - start) { - TibetanForm newState = tibetan_form(uc[pos]); - switch(newState) { - case TibetanSubjoinedConsonant: - case TibetanSubjoinedVowel: - if (state != TibetanHeadConsonant && - state != TibetanSubjoinedConsonant) - goto finish; - state = newState; - break; - case TibetanVowel: - if (state != TibetanHeadConsonant && - state != TibetanSubjoinedConsonant && - state != TibetanSubjoinedVowel) - goto finish; - break; - case TibetanOther: - case TibetanHeadConsonant: - goto finish; - } - pos++; - } - -finish: - *invalid = FALSE; - return start+pos; -} - -static bool tibetan_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script == TQFont::Tibetan); - -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - if (openType && !openType->supportsScript(item->script)) - openType = 0; -#else - TQOpenType *openType = 0; -#endif - unsigned short *logClusters = item->log_clusters; - - TQShaperItem syllable = *item; - int first_glyph = 0; - - int sstart = item->from; - int end = sstart + item->length; - while (sstart < end) { - bool invalid; - int send = tibetan_nextSyllableBoundary(*(item->string), sstart, end, &invalid); - IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, - invalid ? "TRUE" : "FALSE"); - syllable.from = sstart; - syllable.length = send-sstart; - syllable.glyphs = item->glyphs + first_glyph; - syllable.offsets = item->offsets + first_glyph; - syllable.advances = item->advances + first_glyph; - syllable.attributes = item->attributes + first_glyph; - syllable.num_glyphs = item->num_glyphs - first_glyph; - if (!tibetan_shape_syllable(openType, &syllable, invalid)) { - item->num_glyphs += syllable.num_glyphs; - return FALSE; - } - item->has_positioning |= syllable.has_positioning; - - // fix logcluster array - for (int i = sstart; i < send; ++i) - logClusters[i-item->from] = first_glyph; - sstart = send; - first_glyph += syllable.num_glyphs; - } - item->num_glyphs = first_glyph; - return TRUE; -} - -static void tibetan_attributes(int script, const TQString &text, int from, int len, TQCharAttributes *attributes) -{ - Q_UNUSED(script); - - int end = from + len; - const TQChar *uc = text.unicode() + from; - attributes += from; - int i = 0; - while (i < len) { - bool invalid; - int boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from; - - attributes[i].charStop = TRUE; - - if (boundary > len-1) boundary = len; - i++; - while (i < boundary) { - attributes[i].charStop = FALSE; - ++uc; - ++i; - } - assert(i == boundary); - } -} - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Khmer -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - - -// Vocabulary -// Base -> A consonant or an independent vowel in its full (not subscript) form. It is the -// center of the syllable, it can be surrounded by coeng (subscript) consonants, vowels, -// split vowels, signs... but there is only one base in a syllable, it has to be coded as -// the first character of the syllable. -// split vowel --> vowel that has two parts placed separately (e.g. Before and after the consonant). -// Khmer language has five of them. Khmer split vowels either have one part before the -// base and one after the base or they have a part before the base and a part above the base. -// The first part of all Khmer split vowels is the same character, identical to -// the glyph of Khmer dependent vowel SRA EI -// coeng --> modifier used in Khmer to construct coeng (subscript) consonants -// Differently than indian languages, the coeng modifies the consonant that follows it, -// not the one preceding it Each consonant has two forms, the base form and the subscript form -// the base form is the normal one (using the consonants code-point), the subscript form is -// displayed when the combination coeng + consonant is encountered. -// Consonant of type 1 -> A consonant which has subscript for that only occupies space under a base consonant -// Consonant of type 2.-> Its subscript form occupies space under and before the base (only one, RO) -// Consonant of Type 3 -> Its subscript form occupies space under and after the base (KHO, CHHO, THHO, BA, YO, SA) -// Consonant shifter -> Khmer has to series of consonants. The same dependent vowel has different sounds -// if it is attached to a consonant of the first series or a consonant of the second series -// Most consonants have an equivalent in the other series, but some of theme exist only in -// one series (for example SA). If we want to use the consonant SA with a vowel sound that -// can only be done with a vowel sound that corresponds to a vowel accompanying a consonant -// of the other series, then we need to use a consonant shifter: TRIISAP or MUSIKATOAN -// x17C9 y x17CA. TRIISAP changes a first series consonant to second series sound and -// MUSIKATOAN a second series consonant to have a first series vowel sound. -// Consonant shifter are both normally supercript marks, but, when they are followed by a -// superscript, they change shape and take the form of subscript dependent vowel SRA U. -// If they are in the same syllable as a coeng consonant, Unicode 3.0 says that they -// should be typed before the coeng. Unicode 4.0 breaks the standard and says that it should -// be placed after the coeng consonant. -// Dependent vowel -> In khmer dependent vowels can be placed above, below, before or after the base -// Each vowel has its own position. Only one vowel per syllable is allowed. -// Signs -> Khmer has above signs and post signs. Only one above sign and/or one post sign are -// Allowed in a syllable. -// -// -// order is important here! This order must be the same that is found in each horizontal -// line in the statetable for Khmer (see khmerStateTable) . -// -enum KhmerCharClassValues { - CC_RESERVED = 0, - CC_CONSONANT = 1, // Consonant of type 1 or independent vowel - CC_CONSONANT2 = 2, // Consonant of type 2 - CC_CONSONANT3 = 3, // Consonant of type 3 - CC_ZERO_WIDTH_NJ_MARK = 4, // Zero Width non joiner character (0x200C) - CC_CONSONANT_SHIFTER = 5, - CC_ROBAT = 6, // Khmer special diacritic accent -treated differently in state table - CC_COENG = 7, // Subscript consonant combining character - CC_DEPENDENT_VOWEL = 8, - CC_SIGN_ABOVE = 9, - CC_SIGN_AFTER = 10, - CC_ZERO_WIDTH_J_MARK = 11, // Zero width joiner character - CC_COUNT = 12 // This is the number of character classes -}; - - -enum KhmerCharClassFlags { - CF_CLASS_MASK = 0x0000FFFF, - - CF_CONSONANT = 0x01000000, // flag to speed up comparing - CF_SPLIT_VOWEL = 0x02000000, // flag for a split vowel -> the first part is added in front of the syllable - CF_DOTTED_CIRCLE = 0x04000000, // add a dotted circle if a character with this flag is the first in a syllable - CF_COENG = 0x08000000, // flag to speed up comparing - CF_SHIFTER = 0x10000000, // flag to speed up comparing - CF_ABOVE_VOWEL = 0x20000000, // flag to speed up comparing - - // position flags - CF_POS_BEFORE = 0x00080000, - CF_POS_BELOW = 0x00040000, - CF_POS_ABOVE = 0x00020000, - CF_POS_AFTER = 0x00010000, - CF_POS_MASK = 0x000f0000 -}; - - -// Characters that get refered to by name -enum KhmerChar { - C_SIGN_ZWNJ = 0x200C, - C_SIGN_ZWJ = 0x200D, - C_DOTTED_CIRCLE = 0x25CC, - C_RO = 0x179A, - C_VOWEL_AA = 0x17B6, - C_SIGN_NIKAHIT = 0x17C6, - C_VOWEL_E = 0x17C1, - C_COENG = 0x17D2 -}; - - -// simple classes, they are used in the statetable (in this file) to control the length of a syllable -// they are also used to know where a character should be placed (location in reference to the base character) -// and also to know if a character, when independently displayed, should be displayed with a dotted-circle to -// indicate error in syllable construction -// -enum { - _xx = CC_RESERVED, - _sa = CC_SIGN_ABOVE | CF_DOTTED_CIRCLE | CF_POS_ABOVE, - _sp = CC_SIGN_AFTER | CF_DOTTED_CIRCLE| CF_POS_AFTER, - _c1 = CC_CONSONANT | CF_CONSONANT, - _c2 = CC_CONSONANT2 | CF_CONSONANT, - _c3 = CC_CONSONANT3 | CF_CONSONANT, - _rb = CC_ROBAT | CF_POS_ABOVE | CF_DOTTED_CIRCLE, - _cs = CC_CONSONANT_SHIFTER | CF_DOTTED_CIRCLE | CF_SHIFTER, - _dl = CC_DEPENDENT_VOWEL | CF_POS_BEFORE | CF_DOTTED_CIRCLE, - _db = CC_DEPENDENT_VOWEL | CF_POS_BELOW | CF_DOTTED_CIRCLE, - _da = CC_DEPENDENT_VOWEL | CF_POS_ABOVE | CF_DOTTED_CIRCLE | CF_ABOVE_VOWEL, - _dr = CC_DEPENDENT_VOWEL | CF_POS_AFTER | CF_DOTTED_CIRCLE, - _co = CC_COENG | CF_COENG | CF_DOTTED_CIRCLE, - - // split vowel - _va = _da | CF_SPLIT_VOWEL, - _vr = _dr | CF_SPLIT_VOWEL -}; - - -// Character class: a character class value -// ORed with character class flags. -// -typedef unsigned long KhmerCharClass; - - -// Character class tables -// _xx character does not combine into syllable, such as numbers, puntuation marks, non-Khmer signs... -// _sa Sign placed above the base -// _sp Sign placed after the base -// _c1 Consonant of type 1 or independent vowel (independent vowels behave as type 1 consonants) -// _c2 Consonant of type 2 (only RO) -// _c3 Consonant of type 3 -// _rb Khmer sign robat u17CC. combining mark for subscript consonants -// _cd Consonant-shifter -// _dl Dependent vowel placed before the base (left of the base) -// _db Dependent vowel placed below the base -// _da Dependent vowel placed above the base -// _dr Dependent vowel placed behind the base (right of the base) -// _co Khmer combining mark COENG u17D2, combines with the consonant or independent vowel following -// it to create a subscript consonant or independent vowel -// _va Khmer split vowel in wich the first part is before the base and the second one above the base -// _vr Khmer split vowel in wich the first part is before the base and the second one behind (right of) the base -// -static const KhmerCharClass khmerCharClasses[] = { - _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, // 1780 - 178F - _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c2, _c1, _c1, _c1, _c3, _c3, // 1790 - 179F - _c1, _c3, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, // 17A0 - 17AF - _c1, _c1, _c1, _c1, _dr, _dr, _dr, _da, _da, _da, _da, _db, _db, _db, _va, _vr, // 17B0 - 17BF - _vr, _dl, _dl, _dl, _vr, _vr, _sa, _sp, _sp, _cs, _cs, _sa, _rb, _sa, _sa, _sa, // 17C0 - 17CF - _sa, _sa, _co, _sa, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _sa, _xx, _xx // 17D0 - 17DF -}; - -// this enum must reflect the range of khmerCharClasses -enum KhmerCharClassesRange { - KhmerFirstChar = 0x1780, - KhmerLastChar = 0x17df -}; - -// Below we define how a character in the input string is either in the khmerCharClasses table -// (in which case we get its type back), a ZWJ or ZWNJ (two characters that may appear -// within the syllable, but are not in the table) we also get their type back, or an unknown object -// in which case we get _xx (CC_RESERVED) back -// -static inline KhmerCharClass getKhmerCharClass(const TQChar &uc) -{ - if (uc.unicode() == C_SIGN_ZWJ) { - return CC_ZERO_WIDTH_J_MARK; - } - - if (uc.unicode() == C_SIGN_ZWNJ) { - return CC_ZERO_WIDTH_NJ_MARK; - } - - if (uc.unicode() < KhmerFirstChar || uc.unicode() > KhmerLastChar) { - return CC_RESERVED; - } - - return khmerCharClasses[uc.unicode() - KhmerFirstChar]; -} - - -// The stateTable is used to calculate the end (the length) of a well -// formed Khmer Syllable. -// -// Each horizontal line is ordered exactly the same way as the values in KhmerClassTable -// CharClassValues. This coincidence of values allows the follow up of the table. -// -// Each line corresponds to a state, which does not necessarily need to be a type -// of component... for example, state 2 is a base, with is always a first character -// in the syllable, but the state could be produced a consonant of any type when -// it is the first character that is analysed (in ground state). -// -// Differentiating 3 types of consonants is necessary in order to -// forbid the use of certain combinations, such as having a second -// coeng after a coeng RO, -// The inexistent possibility of having a type 3 after another type 3 is permitted, -// eliminating it would very much complicate the table, and it does not create typing -// problems, as the case above. -// -// The table is quite complex, in order to limit the number of coeng consonants -// to 2 (by means of the table). -// -// There a peculiarity, as far as Unicode is concerned: -// - The consonant-shifter is considered in two possible different -// locations, the one considered in Unicode 3.0 and the one considered in -// Unicode 4.0. (there is a backwards compatibility problem in this standard). -// -// -// xx independent character, such as a number, punctuation sign or non-khmer char -// -// c1 Khmer consonant of type 1 or an independent vowel -// that is, a letter in which the subscript for is only under the -// base, not taking any space to the right or to the left -// -// c2 Khmer consonant of type 2, the coeng form takes space under -// and to the left of the base (only RO is of this type) -// -// c3 Khmer consonant of type 3. Its subscript form takes space under -// and to the right of the base. -// -// cs Khmer consonant shifter -// -// rb Khmer robat -// -// co coeng character (u17D2) -// -// dv dependent vowel (including split vowels, they are treated in the same way). -// even if dv is not defined above, the component that is really tested for is -// KhmerClassTable::CC_DEPENDENT_VOWEL, which is common to all dependent vowels -// -// zwj Zero Width joiner -// -// zwnj Zero width non joiner -// -// sa above sign -// -// sp post sign -// -// there are lines with equal content but for an easier understanding -// (and maybe change in the future) we did not join them -// -static const signed char khmerStateTable[][CC_COUNT] = -{ - // xx c1 c2 c3 zwnj cs rb co dv sa sp zwj - { 1, 2, 2, 2, 1, 1, 1, 6, 1, 1, 1, 2}, // 0 - ground state - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 - exit state (or sign to the right of the syllable) - {-1, -1, -1, -1, 3, 4, 5, 6, 16, 17, 1, -1}, // 2 - Base consonant - {-1, -1, -1, -1, -1, 4, -1, -1, 16, -1, -1, -1}, // 3 - First ZWNJ before a register shifter It can only be followed by a shifter or a vowel - {-1, -1, -1, -1, 15, -1, -1, 6, 16, 17, 1, 14}, // 4 - First register shifter - {-1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 1, -1}, // 5 - Robat - {-1, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 - First Coeng - {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, // 7 - First consonant of type 1 after coeng - {-1, -1, -1, -1, 12, 13, -1, -1, 16, 17, 1, 14}, // 8 - First consonant of type 2 after coeng - {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, // 9 - First consonant or type 3 after ceong - {-1, 11, 11, 11, -1, -1, -1, -1, -1, -1, -1, -1}, // 10 - Second Coeng (no register shifter before) - {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, // 11 - Second coeng consonant (or ind. vowel) no register shifter before - {-1, -1, -1, -1, -1, 13, -1, -1, 16, -1, -1, -1}, // 12 - Second ZWNJ before a register shifter - {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, // 13 - Second register shifter - {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, // 14 - ZWJ before vowel - {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, // 15 - ZWNJ before vowel - {-1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 1, 18}, // 16 - dependent vowel - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 18}, // 17 - sign above - {-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1}, // 18 - ZWJ after vowel - {-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, // 19 - Third coeng - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, // 20 - dependent vowel after a Robat -}; - - -// #define KHMER_DEBUG -#ifdef KHMER_DEBUG -#define KHDEBUG tqDebug -#else -#define KHDEBUG if(0) tqDebug -#endif - -// Given an input string of characters and a location in which to start looking -// calculate, using the state table, which one is the last character of the syllable -// that starts in the starting position. -// -static inline int khmer_nextSyllableBoundary(const TQString &s, int start, int end, bool *invalid) -{ - *invalid = FALSE; - const TQChar *uc = s.unicode() + start; - int state = 0; - int pos = start; - - while (pos < end) { - KhmerCharClass charClass = getKhmerCharClass(*uc); - if (pos == start) { - *invalid = (charClass > 0) && ! (charClass & CF_CONSONANT); - } - state = khmerStateTable[state][charClass & CF_CLASS_MASK]; - - KHDEBUG("state[%d]=%d class=%8lx (uc=%4x)", pos - start, state, - charClass, uc->unicode() ); - - if (state < 0) { - break; - } - ++uc; - ++pos; - } - return pos; -} - - -#ifndef TQT_NO_XFTFREETYPE -static const TQOpenType::Features khmer_features[] = { - { FT_MAKE_TAG( 'p', 'r', 'e', 'f' ), PreFormProperty }, - { FT_MAKE_TAG( 'b', 'l', 'w', 'f' ), BelowFormProperty }, - { FT_MAKE_TAG( 'a', 'b', 'v', 'f' ), AboveFormProperty }, - { FT_MAKE_TAG( 'p', 's', 't', 'f' ), PostFormProperty }, - { FT_MAKE_TAG( 'p', 'r', 'e', 's' ), PreSubstProperty }, - { FT_MAKE_TAG( 'b', 'l', 'w', 's' ), BelowSubstProperty }, - { FT_MAKE_TAG( 'a', 'b', 'v', 's' ), AboveSubstProperty }, - { FT_MAKE_TAG( 'p', 's', 't', 's' ), PostSubstProperty }, - { FT_MAKE_TAG( 'c', 'l', 'i', 'g' ), CligProperty }, - { 0, 0 } -}; -#endif - - -static bool khmer_shape_syllable(TQOpenType *openType, TQShaperItem *item) -{ -#ifndef TQT_NO_XFTFREETYPE - if (openType) - openType->selectScript(TQFont::Khmer, khmer_features); -#endif - // according to the specs this is the max length one can get - // ### the real value should be smaller - assert(item->length < 13); - - KHDEBUG("syllable from %d len %d, str='%s'", item->from, item->length, - item->string->mid(item->from, item->length).utf8().data()); - - int len = 0; - int syllableEnd = item->from + item->length; - unsigned short reordered[16]; - unsigned char properties[16]; - enum { - AboveForm = 0x01, - PreForm = 0x02, - PostForm = 0x04, - BelowForm = 0x08 - }; - memset(properties, 0, 16*sizeof(unsigned char)); - -#ifdef KHMER_DEBUG - tqDebug("original:"); - for (int i = from; i < syllableEnd; i++) { - tqDebug(" %d: %4x", i, string[i].unicode()); - } -#endif - - // write a pre vowel or the pre part of a split vowel first - // and look out for coeng + ro. RO is the only vowel of type 2, and - // therefore the only one that requires saving space before the base. - // - int coengRo = -1; // There is no Coeng Ro, if found this value will change - int i; - for (i = item->from; i < syllableEnd; i += 1) { - KhmerCharClass charClass = getKhmerCharClass(item->string->at(i)); - - // if a split vowel, write the pre part. In Khmer the pre part - // is the same for all split vowels, same glyph as pre vowel C_VOWEL_E - if (charClass & CF_SPLIT_VOWEL) { - reordered[len] = C_VOWEL_E; - properties[len] = PreForm; - ++len; - break; // there can be only one vowel - } - // if a vowel with pos before write it out - if (charClass & CF_POS_BEFORE) { - reordered[len] = item->string->at(i).unicode(); - properties[len] = PreForm; - ++len; - break; // there can be only one vowel - } - // look for coeng + ro and remember position - // works because coeng + ro is always in front of a vowel (if there is a vowel) - // and because CC_CONSONANT2 is enough to identify it, as it is the only consonant - // with this flag - if ( (charClass & CF_COENG) && (i + 1 < syllableEnd) && - ( (getKhmerCharClass(item->string->at(i+1)) & CF_CLASS_MASK) == CC_CONSONANT2) ) { - coengRo = i; - } - } - - // write coeng + ro if found - if (coengRo > -1) { - reordered[len] = C_COENG; - properties[len] = PreForm; - ++len; - reordered[len] = C_RO; - properties[len] = PreForm; - ++len; - } - - // shall we add a dotted circle? - // If in the position in which the base should be (first char in the string) there is - // a character that has the Dotted circle flag (a character that cannot be a base) - // then write a dotted circle - if (getKhmerCharClass(item->string->at(item->from)) & CF_DOTTED_CIRCLE) { - reordered[len] = C_DOTTED_CIRCLE; - ++len; - } - - // copy what is left to the output, skipping before vowels and - // coeng Ro if they are present - for (i = item->from; i < syllableEnd; i += 1) { - TQChar uc = item->string->at(i); - KhmerCharClass charClass = getKhmerCharClass(uc); - - // skip a before vowel, it was already processed - if (charClass & CF_POS_BEFORE) { - continue; - } - - // skip coeng + ro, it was already processed - if (i == coengRo) { - i += 1; - continue; - } - - switch (charClass & CF_POS_MASK) - { - case CF_POS_ABOVE : - reordered[len] = uc.unicode(); - properties[len] = AboveForm; - ++len; - break; - - case CF_POS_AFTER : - reordered[len] = uc.unicode(); - properties[len] = PostForm; - ++len; - break; - - case CF_POS_BELOW : - reordered[len] = uc.unicode(); - properties[len] = BelowForm; - ++len; - break; - - default: - // assign the correct flags to a coeng consonant - // Consonants of type 3 are taged as Post forms and those type 1 as below forms - if ( (charClass & CF_COENG) && i + 1 < syllableEnd ) { - unsigned char property = (getKhmerCharClass(item->string->at(i+1)) & CF_CLASS_MASK) == CC_CONSONANT3 ? - PostForm : BelowForm; - reordered[len] = uc.unicode(); - properties[len] = property; - ++len; - i += 1; - reordered[len] = item->string->at(i).unicode(); - properties[len] = property; - ++len; - break; - } - - // if a shifter is followed by an above vowel change the shifter to below form, - // an above vowel can have two possible positions i + 1 or i + 3 - // (position i+1 corresponds to unicode 3, position i+3 to Unicode 4) - // and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two - // different positions, right after the shifter or after a vowel (Unicode 4) - if ( (charClass & CF_SHIFTER) && (i + 1 < syllableEnd) ) { - if (getKhmerCharClass(item->string->at(i+1)) & CF_ABOVE_VOWEL ) { - reordered[len] = uc.unicode(); - properties[len] = BelowForm; - ++len; - break; - } - if (i + 2 < syllableEnd && - (item->string->at(i+1).unicode() == C_VOWEL_AA) && - (item->string->at(i+2).unicode() == C_SIGN_NIKAHIT) ) - { - reordered[len] = uc.unicode(); - properties[len] = BelowForm; - ++len; - break; - } - if (i + 3 < syllableEnd && (getKhmerCharClass(item->string->at(i+3)) & CF_ABOVE_VOWEL) ) { - reordered[len] = uc.unicode(); - properties[len] = BelowForm; - ++len; - break; - } - if (i + 4 < syllableEnd && - (item->string->at(i+3).unicode() == C_VOWEL_AA) && - (item->string->at(i+4).unicode() == C_SIGN_NIKAHIT) ) - { - reordered[len] = uc.unicode(); - properties[len] = BelowForm; - ++len; - break; - } - } - - // default - any other characters - reordered[len] = uc.unicode(); - ++len; - break; - } // switch - } // for - - if (item->font->stringToCMap((const TQChar *)reordered, len, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - KHDEBUG("after shaping: len=%d", len); - for (i = 0; i < len; i++) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = FALSE; - item->attributes[i].justification = 0; - item->attributes[i].zeroWidth = FALSE; - KHDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]); - } - - // now we have the syllable in the right order, and can start running it through open type. - -#ifndef TQT_NO_XFTFREETYPE - if (openType) { - uint where[16]; - - for (int i = 0; i < len; ++i) { - where[i] = ~(PreSubstProperty - | BelowSubstProperty - | AboveSubstProperty - | PostSubstProperty - | CligProperty - | PositioningProperties); - if (properties[i] == PreForm) - where[i] &= ~PreFormProperty; - else if (properties[i] == BelowForm) - where[i] &= ~BelowFormProperty; - else if (properties[i] == AboveForm) - where[i] &= ~AboveFormProperty; - else if (properties[i] == PostForm) - where[i] &= ~PostFormProperty; - } - - openType->shape(item, where); - if (!openType->positionAndAdd(item, FALSE)) - return FALSE; - } else -#endif - { - KHDEBUG("Not using openType"); - Q_UNUSED(openType); - } - - item->attributes[0].clusterStart = TRUE; - return TRUE; -} - -static bool khmer_shape(TQShaperItem *item) -{ - assert(item->script == TQFont::Khmer); - -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - if (openType && !openType->supportsScript(item->script)) - openType = 0; -#else - TQOpenType *openType = 0; -#endif - unsigned short *logClusters = item->log_clusters; - - TQShaperItem syllable = *item; - int first_glyph = 0; - - int sstart = item->from; - int end = sstart + item->length; - KHDEBUG("khmer_shape: from %d length %d", item->from, item->length); - while (sstart < end) { - bool invalid; - int send = khmer_nextSyllableBoundary(*item->string, sstart, end, &invalid); - KHDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, - invalid ? "TRUE" : "FALSE"); - syllable.from = sstart; - syllable.length = send-sstart; - syllable.glyphs = item->glyphs + first_glyph; - syllable.offsets = item->offsets + first_glyph; - syllable.advances = item->advances + first_glyph; - syllable.attributes = item->attributes + first_glyph; - syllable.num_glyphs = item->num_glyphs - first_glyph; - if (!khmer_shape_syllable(openType, &syllable)) { - KHDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); - item->num_glyphs += syllable.num_glyphs; - return FALSE; - } - item->has_positioning |= syllable.has_positioning; - - // fix logcluster array - KHDEBUG("syllable:"); - int i; - for (i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) - KHDEBUG(" %d -> glyph %x", i, item->glyphs[i]); - KHDEBUG(" logclusters:"); - for (i = sstart; i < send; ++i) { - KHDEBUG(" %d -> glyph %d", i, first_glyph); - logClusters[i-item->from] = first_glyph; - } - sstart = send; - first_glyph += syllable.num_glyphs; - } - item->num_glyphs = first_glyph; - return TRUE; -} - -static void khmer_attributes( int script, const TQString &text, int from, int len, TQCharAttributes *attributes ) -{ - Q_UNUSED(script); - - int end = from + len; - const TQChar *uc = text.unicode() + from; - attributes += from; - int i = 0; - while ( i < len ) { - bool invalid; - int boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from; - - attributes[i].charStop = TRUE; - - if ( boundary > len-1 ) boundary = len; - i++; - while ( i < boundary ) { - attributes[i].charStop = FALSE; - ++uc; - ++i; - } - assert( i == boundary ); - } -} - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Myanmar -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -enum MymrCharClassValues -{ - Mymr_CC_RESERVED = 0, - Mymr_CC_CONSONANT = 1, /* Consonant of type 1, that has subscript form */ - Mymr_CC_CONSONANT2 = 2, /* Consonant of type 2, that has no subscript form */ - Mymr_CC_NGA = 3, /* Consonant NGA */ - Mymr_CC_YA = 4, /* Consonant YA */ - Mymr_CC_RA = 5, /* Consonant RA */ - Mymr_CC_WA = 6, /* Consonant WA */ - Mymr_CC_HA = 7, /* Consonant HA */ - Mymr_CC_IND_VOWEL = 8, /* Independent vowel */ - Mymr_CC_ZERO_WIDTH_NJ_MARK = 9, /* Zero Width non joiner character (0x200C) */ - Mymr_CC_VIRAMA = 10, /* Subscript consonant combining character */ - Mymr_CC_PRE_VOWEL = 11, /* Dependent vowel, prebase (Vowel e) */ - Mymr_CC_BELOW_VOWEL = 12, /* Dependent vowel, prebase (Vowel u, uu) */ - Mymr_CC_ABOVE_VOWEL = 13, /* Dependent vowel, prebase (Vowel i, ii, ai) */ - Mymr_CC_POST_VOWEL = 14, /* Dependent vowel, prebase (Vowel aa) */ - Mymr_CC_SIGN_ABOVE = 15, - Mymr_CC_SIGN_BELOW = 16, - Mymr_CC_SIGN_AFTER = 17, - Mymr_CC_ZERO_WIDTH_J_MARK = 18, /* Zero width joiner character */ - Mymr_CC_COUNT = 19 /* This is the number of character classes */ -}; - -enum MymrCharClassFlags -{ - Mymr_CF_CLASS_MASK = 0x0000FFFF, - - Mymr_CF_CONSONANT = 0x01000000, /* flag to speed up comparing */ - Mymr_CF_MEDIAL = 0x02000000, /* flag to speed up comparing */ - Mymr_CF_IND_VOWEL = 0x04000000, /* flag to speed up comparing */ - Mymr_CF_DEP_VOWEL = 0x08000000, /* flag to speed up comparing */ - Mymr_CF_DOTTED_CIRCLE = 0x10000000, /* add a dotted circle if a character with this flag is the first in a syllable */ - Mymr_CF_VIRAMA = 0x20000000, /* flag to speed up comparing */ - - /* position flags */ - Mymr_CF_POS_BEFORE = 0x00080000, - Mymr_CF_POS_BELOW = 0x00040000, - Mymr_CF_POS_ABOVE = 0x00020000, - Mymr_CF_POS_AFTER = 0x00010000, - Mymr_CF_POS_MASK = 0x000f0000, - - Mymr_CF_AFTER_KINZI = 0x00100000 -}; - -/* Characters that get refrered to by name */ -enum MymrChar -{ - Mymr_C_SIGN_ZWNJ = 0x200C, - Mymr_C_SIGN_ZWJ = 0x200D, - Mymr_C_DOTTED_CIRCLE = 0x25CC, - Mymr_C_RA = 0x101B, - Mymr_C_YA = 0x101A, - Mymr_C_NGA = 0x1004, - Mymr_C_VOWEL_E = 0x1031, - Mymr_C_VIRAMA = 0x1039 -}; - -enum -{ - Mymr_xx = Mymr_CC_RESERVED, - Mymr_c1 = Mymr_CC_CONSONANT | Mymr_CF_CONSONANT | Mymr_CF_POS_BELOW, - Mymr_c2 = Mymr_CC_CONSONANT2 | Mymr_CF_CONSONANT, - Mymr_ng = Mymr_CC_NGA | Mymr_CF_CONSONANT | Mymr_CF_POS_ABOVE, - Mymr_ya = Mymr_CC_YA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_AFTER | Mymr_CF_AFTER_KINZI, - Mymr_ra = Mymr_CC_RA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BEFORE, - Mymr_wa = Mymr_CC_WA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW, - Mymr_ha = Mymr_CC_HA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW, - Mymr_id = Mymr_CC_IND_VOWEL | Mymr_CF_IND_VOWEL, - Mymr_vi = Mymr_CC_VIRAMA | Mymr_CF_VIRAMA | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE, - Mymr_dl = Mymr_CC_PRE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BEFORE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, - Mymr_db = Mymr_CC_BELOW_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, - Mymr_da = Mymr_CC_ABOVE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, - Mymr_dr = Mymr_CC_POST_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, - Mymr_sa = Mymr_CC_SIGN_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_ABOVE | Mymr_CF_AFTER_KINZI, - Mymr_sb = Mymr_CC_SIGN_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_BELOW | Mymr_CF_AFTER_KINZI, - Mymr_sp = Mymr_CC_SIGN_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI -}; - - -typedef int MymrCharClass; - - -static const MymrCharClass mymrCharClasses[] = -{ - Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_ng, Mymr_c1, Mymr_c1, Mymr_c1, - Mymr_c1, Mymr_c1, Mymr_c2, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, /* 1000 - 100F */ - Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, - Mymr_c1, Mymr_c1, Mymr_ya, Mymr_ra, Mymr_c1, Mymr_wa, Mymr_c1, Mymr_ha, /* 1010 - 101F */ - Mymr_c2, Mymr_c2, Mymr_xx, Mymr_id, Mymr_id, Mymr_id, Mymr_id, Mymr_id, - Mymr_xx, Mymr_id, Mymr_id, Mymr_xx, Mymr_dr, Mymr_da, Mymr_da, Mymr_db, /* 1020 - 102F */ - Mymr_db, Mymr_dl, Mymr_da, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_sa, Mymr_sb, - Mymr_sp, Mymr_vi, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1030 - 103F */ - Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, - Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1040 - 104F */ - Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, - Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1050 - 105F */ -}; - -static MymrCharClass -getMyanmarCharClass (const TQChar &ch) -{ - if (ch.unicode() == Mymr_C_SIGN_ZWJ) - return Mymr_CC_ZERO_WIDTH_J_MARK; - - if (ch.unicode() == Mymr_C_SIGN_ZWNJ) - return Mymr_CC_ZERO_WIDTH_NJ_MARK; - - if (ch.unicode() < 0x1000 || ch.unicode() > 0x105f) - return Mymr_CC_RESERVED; - - return mymrCharClasses[ch.unicode() - 0x1000]; -} - -static const signed char mymrStateTable[][Mymr_CC_COUNT] = -{ -// xx c1, c2 ng ya ra wa ha id zwnj vi dl db da dr sa sb sp zwj - { 1, 4, 4, 2, 4, 4, 4, 4, 24, 1, 27, 17, 18, 19, 20, 21, 1, 1, 4}, // 0 - ground state - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 - exit state (or sp to the right of the syllable) - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 17, 18, 19, 20, 21, -1, -1, 4}, // 2 - NGA - {-1, 4, 4, 4, 4, 4, 4, 4, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 3 - Virama after NGA - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 17, 18, 19, 20, 21, 1, 1, -1}, // 4 - Base consonant - {-2, 6, -2, -2, 7, 8, 9, 10, -2, 23, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 5 - First virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 17, 18, 19, 20, 21, -1, -1, -1}, // 6 - c1 after virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, // 7 - ya after virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, // 8 - ra after virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, // 9 - wa after virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, // 10 - ha after virama - {-1, -1, -1, -1, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 11 - Virama after NGA+zwj - {-2, -2, -2, -2, -2, -2, 13, 14, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 12 - Second virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 17, 18, 19, 20, 21, -1, -1, -1}, // 13 - wa after virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, // 14 - ha after virama - {-2, -2, -2, -2, -2, -2, -2, 16, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 15 - Third virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, // 16 - ha after virama - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 1, 1, -1}, // 17 - dl, Dependent vowel e - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, 21, 1, 1, -1}, // 18 - db, Dependent vowel u,uu - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1}, // 19 - da, Dependent vowel i,ii,ai - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, 1, 1, -1}, // 20 - dr, Dependent vowel aa - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, // 21 - sa, Sign anusvara - {-1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 22 - atha - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, // 23 - zwnj for atha - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, // 24 - Independent vowel - {-2, -2, -2, -2, 26, 26, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 25 - Virama after subscript consonant - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, 1, -1}, // 26 - ra/ya after subscript consonant + virama - {-1, 6, -1, -1, 7, 8, 9, 10, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 27 - Virama after ground state -// exit state -2 is for invalid order of medials and combination of invalids -// with virama where virama should treat as start of next syllable -}; - - - -// #define MYANMAR_DEBUG -#ifdef MYANMAR_DEBUG -#define MMDEBUG tqDebug -#else -#define MMDEBUG if(0) tqDebug -#endif - -// Given an input string of characters and a location in which to start looking -// calculate, using the state table, which one is the last character of the syllable -// that starts in the starting position. -// -static inline int myanmar_nextSyllableBoundary(const TQString &s, int start, int end, bool *invalid) -{ - *invalid = FALSE; - const TQChar *uc = s.unicode() + start; - int state = 0; - int pos = start; - - while (pos < end) { - MymrCharClass charClass = getMyanmarCharClass(*uc); - state = mymrStateTable[state][charClass & Mymr_CF_CLASS_MASK]; - if (pos == start) - *invalid = charClass & Mymr_CF_DOTTED_CIRCLE; - - MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, uc->unicode() ); - - if (state < 0) { - if (state < -1) - --pos; - break; - } - ++uc; - ++pos; - } - return pos; -} - - -#ifndef TQT_NO_XFTFREETYPE -// ###### might have to change order of above and below forms and substitutions, -// but according to Unicode below comes before above -static const TQOpenType::Features myanmar_features[] = { - { FT_MAKE_TAG( 'p', 'r', 'e', 'f' ), PreFormProperty }, - { FT_MAKE_TAG( 'b', 'l', 'w', 'f' ), BelowFormProperty }, - { FT_MAKE_TAG( 'a', 'b', 'v', 'f' ), AboveFormProperty }, - { FT_MAKE_TAG( 'p', 's', 't', 'f' ), PostFormProperty }, - { FT_MAKE_TAG( 'p', 'r', 'e', 's' ), PreSubstProperty }, - { FT_MAKE_TAG( 'b', 'l', 'w', 's' ), BelowSubstProperty }, - { FT_MAKE_TAG( 'a', 'b', 'v', 's' ), AboveSubstProperty }, - { FT_MAKE_TAG( 'p', 's', 't', 's' ), PostSubstProperty }, - { FT_MAKE_TAG( 'r', 'l', 'i', 'g' ), CligProperty }, // Myanmar1 uses this instead of the other features - { 0, 0 } -}; -#endif - - -// Visual order before shaping should be: -// -// [Vowel Mark E] -// [Virama + Medial Ra] -// [Base] -// [Virama + Consonant] -// [Nga + Virama] (Kinzi) ### should probably come before post forms (medial ya) -// [Vowels] -// [Marks] -// -// This means that we can keep the logical order apart from having to -// move the pre vowel, medial ra and kinzi - -static bool myanmar_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool invalid) -{ -#ifndef TQT_NO_XFTFREETYPE - if (openType) - openType->selectScript(TQFont::Myanmar, myanmar_features); -#endif - // according to the table the max length of a syllable should be around 14 chars - assert(item->length < 32); - - MMDEBUG("\nsyllable from %d len %d, str='%s'", item->from, item->length, - item->string->mid(item->from, item->length).utf8().data()); - - const TQChar *uc = item->string->unicode() + item->from; -#ifdef MYANMAR_DEBUG - tqDebug("original:"); - for (int i = 0; i < item->length; i++) { - tqDebug(" %d: %4x", i, uc[i].unicode()); - } -#endif - int vowel_e = -1; - int kinzi = -1; - int medial_ra = -1; - int base = -1; - int i; - for (i = 0; i < item->length; ++i) { - ushort chr = uc[i].unicode(); - - if (chr == Mymr_C_VOWEL_E) { - vowel_e = i; - continue; - } - if (i == 0 - && chr == Mymr_C_NGA - && i + 2 < item->length - && uc[i+1].unicode() == Mymr_C_VIRAMA) { - int mc = getMyanmarCharClass(uc[i+2]); - //MMDEBUG("maybe kinzi: mc=%x", mc); - if ((mc & Mymr_CF_CONSONANT) == Mymr_CF_CONSONANT) { - kinzi = i; - continue; - } - } - if (base >= 0 - && chr == Mymr_C_VIRAMA - && i + 1 < item->length - && uc[i+1].unicode() == Mymr_C_RA) { - medial_ra = i; - continue; - } - if (base < 0) - base = i; - } - - MMDEBUG("\n base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base, vowel_e, kinzi, medial_ra); - int len = 0; - unsigned short reordered[32]; - unsigned char properties[32]; - enum { - AboveForm = 0x01, - PreForm = 0x02, - PostForm = 0x04, - BelowForm = 0x08 - }; - memset(properties, 0, 32*sizeof(unsigned char)); - - // write vowel_e if found - if (vowel_e >= 0) { - reordered[0] = Mymr_C_VOWEL_E; - len = 1; - } - // write medial_ra - if (medial_ra >= 0) { - reordered[len] = Mymr_C_VIRAMA; - reordered[len+1] = Mymr_C_RA; - properties[len] = PreForm; - properties[len+1] = PreForm; - len += 2; - } - - // shall we add a dotted circle? - // If in the position in which the base should be (first char in the string) there is - // a character that has the Dotted circle flag (a character that cannot be a base) - // then write a dotted circle - if (invalid) { - reordered[len] = C_DOTTED_CIRCLE; - ++len; - } - - bool lastWasVirama = FALSE; - int basePos = -1; - // copy the rest of the syllable to the output, inserting the kinzi - // at the correct place - for (i = 0; i < item->length; ++i) { - if (i == vowel_e) - continue; - if (i == medial_ra || i == kinzi) { - ++i; - continue; - } - - ushort chr = uc[i].unicode(); - MymrCharClass cc = getMyanmarCharClass(uc[i]); - if (kinzi >= 0 && i > base && (cc & Mymr_CF_AFTER_KINZI)) { - reordered[len] = Mymr_C_NGA; - reordered[len+1] = Mymr_C_VIRAMA; - properties[len-1] = AboveForm; - properties[len] = AboveForm; - len += 2; - kinzi = -1; - } - - if (lastWasVirama) { - int prop = 0; - switch(cc & Mymr_CF_POS_MASK) { - case Mymr_CF_POS_BEFORE: - prop = PreForm; - break; - case Mymr_CF_POS_BELOW: - prop = BelowForm; - break; - case Mymr_CF_POS_ABOVE: - prop = AboveForm; - break; - case Mymr_CF_POS_AFTER: - prop = PostForm; - break; - default: - break; - } - properties[len-1] = prop; - properties[len] = prop; - if(basePos >= 0 && basePos == len-2) - properties[len-2] = prop; - } - lastWasVirama = (chr == Mymr_C_VIRAMA); - if(i == base) - basePos = len; - - if ((chr != Mymr_C_SIGN_ZWNJ && chr != Mymr_C_SIGN_ZWJ) || !len) { - reordered[len] = chr; - ++len; - } - } - if (kinzi >= 0) { - reordered[len] = Mymr_C_NGA; - reordered[len+1] = Mymr_C_VIRAMA; - properties[len] = AboveForm; - properties[len+1] = AboveForm; - len += 2; - } - - if (item->font->stringToCMap((const TQChar *)reordered, len, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - - MMDEBUG("after shaping: len=%d", len); - for (i = 0; i < len; i++) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = FALSE; - item->attributes[i].justification = 0; - item->attributes[i].zeroWidth = FALSE; - MMDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]); - } - - // now we have the syllable in the right order, and can start running it through open type. - -#ifndef TQT_NO_XFTFREETYPE - if (openType) { - uint where[32]; - - for (int i = 0; i < len; ++i) { - where[i] = ~(PreSubstProperty - | BelowSubstProperty - | AboveSubstProperty - | PostSubstProperty - | CligProperty - | PositioningProperties); - if (properties[i] == PreForm) - where[i] &= ~PreFormProperty; - else if (properties[i] == BelowForm) - where[i] &= ~BelowFormProperty; - else if (properties[i] == AboveForm) - where[i] &= ~AboveFormProperty; - else if (properties[i] == PostForm) - where[i] &= ~PostFormProperty; - } - - openType->shape(item, where); - if (!openType->positionAndAdd(item, FALSE)) - return FALSE; - } else -#endif - { - MMDEBUG("Not using openType"); - Q_UNUSED(openType); - } - - item->attributes[0].clusterStart = TRUE; - return TRUE; -} - -static bool myanmar_shape(TQShaperItem *item) -{ - assert(item->script == TQFont::Myanmar); - -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - if (openType && !openType->supportsScript(item->script)) - openType = 0; -#else - TQOpenType *openType = 0; -#endif - unsigned short *logClusters = item->log_clusters; - - TQShaperItem syllable = *item; - int first_glyph = 0; - - int sstart = item->from; - int end = sstart + item->length; - MMDEBUG("myanmar_shape: from %d length %d", item->from, item->length); - while (sstart < end) { - bool invalid; - int send = myanmar_nextSyllableBoundary(*item->string, sstart, end, &invalid); - MMDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, - invalid ? "TRUE" : "FALSE"); - syllable.from = sstart; - syllable.length = send-sstart; - syllable.glyphs = item->glyphs + first_glyph; - syllable.offsets = item->offsets + first_glyph; - syllable.advances = item->advances + first_glyph; - syllable.attributes = item->attributes + first_glyph; - syllable.num_glyphs = item->num_glyphs - first_glyph; - if (!myanmar_shape_syllable(openType, &syllable, invalid)) { - MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); - item->num_glyphs += syllable.num_glyphs; - return FALSE; - } - item->has_positioning |= syllable.has_positioning; - - // fix logcluster array - MMDEBUG("syllable:"); - int i; - for (i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) - MMDEBUG(" %d -> glyph %x", i, item->glyphs[i]); - MMDEBUG(" logclusters:"); - for (i = sstart; i < send; ++i) { - MMDEBUG(" %d -> glyph %d", i, first_glyph); - logClusters[i-item->from] = first_glyph; - } - sstart = send; - first_glyph += syllable.num_glyphs; - } - item->num_glyphs = first_glyph; - return TRUE; -} - -static void myanmar_attributes( int script, const TQString &text, int from, int len, TQCharAttributes *attributes ) -{ - Q_UNUSED(script); - - int end = from + len; - const TQChar *uc = text.unicode() + from; - attributes += from; - int i = 0; - while ( i < len ) { - bool invalid; - int boundary = myanmar_nextSyllableBoundary( text, from+i, end, &invalid ) - from; - - attributes[i].charStop = TRUE; - attributes[i].softBreak = TRUE; - - if ( boundary > len-1 ) boundary = len; - i++; - while ( i < boundary ) { - attributes[i].charStop = FALSE; - attributes[i].softBreak = FALSE; - ++uc; - ++i; - } - assert( i == boundary ); - } -} - -// -------------------------------------------------------------------------------------------------------------------------------------------- -// -// Hangul -// -// -------------------------------------------------------------------------------------------------------------------------------------------- - -// Hangul is a syllable based script. Unicode reserves a large range -// for precomposed hangul, where syllables are already precomposed to -// their final glyph shape. In addition, a so called jamo range is -// defined, that can be used to express old Hangul. Modern hangul -// syllables can also be expressed as jamo, and should be composed -// into syllables. The operation is rather simple and mathematical. - -// Every hangul jamo is classified as being either a Leading consonant -// (L), and intermediat Vowel (V) or a trailing consonant (T). Modern -// hangul syllables (the ones in the precomposed area can be of type -// LV or LVT. -// -// Syllable breaks do _not_ occur between: -// -// L L, V or precomposed -// V, LV V, T -// LVT, T T -// -// A standard syllable is of the form L+V+T*. The above rules allow -// nonstandard syllables L*V*T*. To transform them into standard -// syllables fill characers L_f and V_f can be inserted. - -enum { - Hangul_SBase = 0xac00, - Hangul_LBase = 0x1100, - Hangul_VBase = 0x1161, - Hangul_TBase = 0x11a7, - Hangul_SCount = 11172, - Hangul_LCount = 19, - Hangul_VCount = 21, - Hangul_TCount = 28, - Hangul_NCount = 21*28 -}; - -static inline bool hangul_isPrecomposed(unsigned short uc) { - return (uc >= Hangul_SBase && uc < Hangul_SBase + Hangul_SCount); -} - -static inline bool hangul_isLV(unsigned short uc) { - return ((uc - Hangul_SBase) % Hangul_TCount == 0); -} - -enum HangulType { - L, - V, - T, - LV, - LVT, - X -}; - -static inline HangulType hangul_type(unsigned short uc) { - if (uc > Hangul_SBase && uc < Hangul_SBase + Hangul_SCount) - return hangul_isLV(uc) ? LV : LVT; - if (uc < Hangul_LBase || uc > 0x11ff) - return X; - if (uc < Hangul_VBase) - return L; - if (uc < Hangul_TBase) - return V; - return T; -} - -static int hangul_nextSyllableBoundary(const TQString &s, int start, int end) -{ - const TQChar *uc = s.unicode() + start; - - HangulType state = hangul_type(uc->unicode()); - int pos = 1; - - while (pos < end - start) { - HangulType newState = hangul_type(uc[pos].unicode()); - switch(newState) { - case X: - goto finish; - case L: - case V: - case T: - if (state > newState) - goto finish; - state = newState; - break; - case LV: - if (state > L) - goto finish; - state = V; - break; - case LVT: - if (state > L) - goto finish; - state = T; - } - ++pos; - } - - finish: - return start+pos; -} - -#ifndef TQT_NO_XFTFREETYPE -static const TQOpenType::Features hangul_features [] = { - { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, - { FT_MAKE_TAG('l', 'j', 'm', 'o'), CcmpProperty }, - { FT_MAKE_TAG('j', 'j', 'm', 'o'), CcmpProperty }, - { FT_MAKE_TAG('t', 'j', 'm', 'o'), CcmpProperty }, - { 0, 0 } -}; -#endif - -static bool hangul_shape_syllable(TQOpenType *openType, TQShaperItem *item) -{ - Q_UNUSED(openType) - const TQChar *ch = item->string->unicode() + item->from; - - int i; - unsigned short composed = 0; - // see if we can compose the syllable into a modern hangul - if (item->length == 2) { - int LIndex = ch[0].unicode() - Hangul_LBase; - int VIndex = ch[1].unicode() - Hangul_VBase; - if (LIndex >= 0 && LIndex < Hangul_LCount && - VIndex >= 0 && VIndex < Hangul_VCount) - composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + Hangul_SBase; - } else if (item->length == 3) { - int LIndex = ch[0].unicode() - Hangul_LBase; - int VIndex = ch[1].unicode() - Hangul_VBase; - int TIndex = ch[2].unicode() - Hangul_TBase; - if (LIndex >= 0 && LIndex < Hangul_LCount && - VIndex >= 0 && VIndex < Hangul_VCount && - TIndex >= 0 && TIndex < Hangul_TCount) - composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + TIndex + Hangul_SBase; - } - - - int len = item->length; - TQChar c(composed); - - // ### icc says 'chars' is unused - // const TQChar *chars = ch; - - // if we have a modern hangul use the composed form - if (composed) { - // chars = &c; - len = 1; - } - - if (item->font->stringToCMap(ch, len, item->glyphs, item->advances, - &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) - return FALSE; - for (i = 0; i < len; i++) { - item->attributes[i].mark = FALSE; - item->attributes[i].clusterStart = FALSE; - item->attributes[i].justification = 0; - item->attributes[i].zeroWidth = FALSE; - IDEBUG(" %d: %4x", i, ch[i].unicode()); - } - -#ifndef TQT_NO_XFTFREETYPE - if (openType && !composed) { - - TQVarLengthArray logClusters(len); - for (i = 0; i < len; ++i) - logClusters[i] = i; - item->log_clusters = logClusters.data(); - - openType->shape(item); - if (!openType->positionAndAdd(item, FALSE)) - return FALSE; - - } -#endif - - item->attributes[0].clusterStart = TRUE; - return TRUE; -} - -static bool hangul_shape(TQShaperItem *item) -{ - Q_ASSERT(item->script == TQFont::Hangul); - - const TQChar *uc = item->string->unicode() + item->from; - - bool allPrecomposed = TRUE; - for (int i = 0; i < item->length; ++i) { - if (!hangul_isPrecomposed(uc[i].unicode())) { - allPrecomposed = FALSE; - break; - } - } - - if (!allPrecomposed) { -#ifndef TQT_NO_XFTFREETYPE - TQOpenType *openType = item->font->openType(); - if (openType && !openType->supportsScript(item->script)) - openType = 0; - if (openType) - openType->selectScript(TQFont::Hangul, hangul_features); -#else - TQOpenType *openType = 0; -#endif - - unsigned short *logClusters = item->log_clusters; - - TQShaperItem syllable = *item; - int first_glyph = 0; - - int sstart = item->from; - int end = sstart + item->length; - while (sstart < end) { - int send = hangul_nextSyllableBoundary(*(item->string), sstart, end); - - syllable.from = sstart; - syllable.length = send-sstart; - syllable.glyphs = item->glyphs + first_glyph; - syllable.offsets = item->offsets + first_glyph; - syllable.advances = item->advances + first_glyph; - syllable.attributes = item->attributes + first_glyph; - syllable.num_glyphs = item->num_glyphs - first_glyph; - if (!hangul_shape_syllable(openType, &syllable)) { - item->num_glyphs += syllable.num_glyphs; - return FALSE; - } - item->has_positioning |= syllable.has_positioning; - // fix logcluster array - for (int i = sstart; i < send; ++i) - logClusters[i-item->from] = first_glyph; - sstart = send; - first_glyph += syllable.num_glyphs; - } - item->num_glyphs = first_glyph; - return TRUE; - } - - return basic_shape(item); -} - -static void hangul_attributes(int script, const TQString &text, int from, int len, TQCharAttributes *attributes) -{ - Q_UNUSED(script); - - int end = from + len; - const TQChar *uc = text.unicode() + from; - attributes += from; - int i = 0; - while (i < len) { - int boundary = hangul_nextSyllableBoundary(text, from+i, end) - from; - - attributes[i].charStop = TRUE; - - if (boundary > len-1) boundary = len; - i++; - while (i < boundary) { - attributes[i].charStop = FALSE; - ++uc; - ++i; - } - assert(i == boundary); - } -} - -// ----------------------------------------------------------------------------------------------- -// -// The script engine jump table -// -// ----------------------------------------------------------------------------------------------- - -const q_scriptEngine scriptEngines[] = { - // Latin, - { basic_shape, 0 }, - // Greek, - { basic_shape, 0 }, - // Cyrillic, - { basic_shape, 0 }, - // Armenian, - { basic_shape, 0 }, - // Georgian, - { basic_shape, 0 }, - // Runic, - { basic_shape, 0 }, - // Ogham, - { basic_shape, 0 }, - // SpacingModifiers, - { basic_shape, 0 }, - // CombiningMarks, - { basic_shape, 0 }, - - // // Middle Eastern Scripts - // Hebrew, - { hebrew_shape, 0 }, - // Arabic, - { arabic_shape, 0 }, - // Syriac, - { syriac_shape, 0 }, - // Thaana, - { thaana_shape, 0 }, - - // // South and Southeast Asian Scripts - // Devanagari, - { indic_shape, indic_attributes }, - // Bengali, - { indic_shape, indic_attributes }, - // Gurmukhi, - { indic_shape, indic_attributes }, - // Gujarati, - { indic_shape, indic_attributes }, - // Oriya, - { indic_shape, indic_attributes }, - // Tamil, - { indic_shape, indic_attributes }, - // Telugu, - { indic_shape, indic_attributes }, - // Kannada, - { indic_shape, indic_attributes }, - // Malayalam, - { indic_shape, indic_attributes }, - // Sinhala, - { indic_shape, indic_attributes }, - // Thai, - { basic_shape, thai_attributes }, - // Lao, - { basic_shape, thai_attributes }, - // Tibetan, - { tibetan_shape, tibetan_attributes }, - // Myanmar, - { myanmar_shape, myanmar_attributes }, - // Khmer, - { khmer_shape, khmer_attributes }, - - // // East Asian Scripts - // Han, - { basic_shape, 0 }, - // Hiragana, - { basic_shape, 0 }, - // Katakana, - { basic_shape, 0 }, - // Hangul, - { hangul_shape, hangul_attributes }, - // Bopomofo, - { basic_shape, 0 }, - // Yi, - { basic_shape, 0 }, - - // // Additional Scripts - // Ethiopic, - { basic_shape, 0 }, - // Cherokee, - { basic_shape, 0 }, - // CanadianAboriginal, - { basic_shape, 0 }, - // Mongolian, - { basic_shape, 0 }, - - // // Symbols - // CurrencySymbols, - { basic_shape, 0 }, - // LetterlikeSymbols, - { basic_shape, 0 }, - // NumberForms, - { basic_shape, 0 }, - // MathematicalOperators, - { basic_shape, 0 }, - // TechnicalSymbols, - { basic_shape, 0 }, - // GeometricSymbols, - { basic_shape, 0 }, - // MiscellaneousSymbols, - { basic_shape, 0 }, - // EnclosedAndSquare, - { basic_shape, 0 }, - // Braille, - { basic_shape, 0 }, - - // Unicode, - { basic_shape, 0 }, - //Tagalog, - { basic_shape, 0 }, - //Hanunoo, - { basic_shape, 0 }, - //Buhid, - { basic_shape, 0 }, - //Tagbanwa, - { basic_shape, 0 }, - // KatakanaHalfWidth - { basic_shape, 0 }, - // Limbu - { basic_shape, 0 }, - // TaiLe - { basic_shape, 0 } -}; diff --git a/src/kernel/qt_kernel.pri b/src/kernel/qt_kernel.pri index 315b931fd..84a383a5d 100644 --- a/src/kernel/qt_kernel.pri +++ b/src/kernel/qt_kernel.pri @@ -4,7 +4,7 @@ kernel { KERNEL_P = kernel HEADERS += \ $$KERNEL_H/tqaccel.h \ - $$KERNEL_P/qucomextra_p.h \ + $$KERNEL_P/tqucomextra_p.h \ $$KERNEL_H/ntqapplication.h \ $$KERNEL_P/qapplication_p.h \ $$KERNEL_H/tqasyncimageio.h \ @@ -89,11 +89,11 @@ kernel { $$KERNEL_H/tqwindowdefs.h \ $$KERNEL_H/tqwmatrix.h \ $$KERNEL_H/tqvariant.h \ - $$KERNEL_P/qrichtext_p.h \ - $$KERNEL_P/qinternal_p.h \ + $$KERNEL_P/tqrichtext_p.h \ + $$KERNEL_P/tqinternal_p.h \ $$KERNEL_H/tqgplugin.h \ $$KERNEL_H/tqsimplerichtext.h \ - $$KERNEL_CPP/qscriptengine_p.h \ + $$KERNEL_CPP/tqscriptengine_p.h \ $$KERNEL_CPP/tqtextengine_p.h \ $$KERNEL_CPP/tqfontengine_p.h \ $$KERNEL_CPP/tqtextlayout_p.h @@ -182,7 +182,7 @@ kernel { DEFINES += QMAC_ONE_PIXEL_LOCK } else:unix { SOURCES += $$KERNEL_CPP/tqprinter_unix.cpp \ - $$KERNEL_CPP/qpsprinter.cpp + $$KERNEL_CPP/tqpsprinter.cpp glibmainloop { SOURCES += $$KERNEL_CPP/tqeventloop_unix_glib.cpp } else { @@ -194,7 +194,7 @@ kernel { $$KERNEL_CPP/tqthread_unix.cpp SOURCES += $$KERNEL_CPP/tqabstractlayout.cpp \ - $$KERNEL_CPP/qucomextra.cpp \ + $$KERNEL_CPP/tqucomextra.cpp \ $$KERNEL_CPP/tqaccel.cpp \ $$KERNEL_CPP/qapplication.cpp \ $$KERNEL_CPP/tqasyncimageio.cpp \ @@ -257,16 +257,16 @@ kernel { $$KERNEL_CPP/tqwidget.cpp \ $$KERNEL_CPP/tqwmatrix.cpp \ $$KERNEL_CPP/tqvariant.cpp \ - $$KERNEL_CPP/qrichtext.cpp \ - $$KERNEL_CPP/qinternal.cpp \ - $$KERNEL_CPP/qrichtext_p.cpp \ + $$KERNEL_CPP/tqrichtext.cpp \ + $$KERNEL_CPP/tqinternal.cpp \ + $$KERNEL_CPP/tqrichtext_p.cpp \ $$KERNEL_CPP/tqgplugin.cpp \ $$KERNEL_CPP/tqsimplerichtext.cpp \ - $$KERNEL_CPP/qscriptengine.cpp \ + $$KERNEL_CPP/tqscriptengine.cpp \ $$KERNEL_CPP/tqtextlayout.cpp \ $$KERNEL_CPP/tqtextengine.cpp - unix:HEADERS += $$KERNEL_P/qpsprinter_p.h \ + unix:HEADERS += $$KERNEL_P/tqpsprinter_p.h \ $$KERNEL_H/tqfontdatabase.h accessibility { diff --git a/src/kernel/qt_pch.h b/src/kernel/qt_pch.h index 690551eb6..1420944ef 100644 --- a/src/kernel/qt_pch.h +++ b/src/kernel/qt_pch.h @@ -22,7 +22,7 @@ # endif # endif #include // I must be first! -#include // All moc genereated code has this include +#include // All moc genereated code has this include #include #include #include diff --git a/src/kernel/qt_x11.pri b/src/kernel/qt_x11.pri deleted file mode 100644 index c81055eb3..000000000 --- a/src/kernel/qt_x11.pri +++ /dev/null @@ -1,23 +0,0 @@ -unix { - !xinerama:DEFINES += TQT_NO_XINERAMA - !xshape:DEFINES += TQT_NO_SHAPE - !xcursor:DEFINES += TQT_NO_XCURSOR - !xrandr:DEFINES += TQT_NO_XRANDR - !xrender:DEFINES += TQT_NO_XRENDER - !xftfreetype:DEFINES += TQT_NO_XFTFREETYPE - !xkb:DEFINES += TQT_NO_XKB - xft2header:DEFINES+=QT_USE_XFT2_HEADER - - SOURCES += $$KERNEL_CPP/qtaddons_x11.cpp - PRECOMPILED_HEADER = kernel/qt_pch.h - - SOURCES += $$KERNEL_CPP/tqttdeintegration_x11.cpp - HEADERS += $$KERNEL_H/tqttdeintegration_x11_p.h -} - -nas { - DEFINES += QT_NAS_SUPPORT - LIBS += -laudio -lXt -} - -!x11sm:DEFINES += TQT_NO_SM_SUPPORT diff --git a/src/kernel/qt_x11_p.h b/src/kernel/qt_x11_p.h deleted file mode 100644 index 23bdb7eaa..000000000 --- a/src/kernel/qt_x11_p.h +++ /dev/null @@ -1,280 +0,0 @@ -/**************************************************************************** -** -** Includes X11 system header files. -** -** Created : 981123 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef QT_X11_H -#define QT_X11_H - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of q*_x11.cpp. This header file may change from version to version -// without notice, or even be removed. -// -// - - -#ifndef QT_H -#include "tqwindowdefs.h" -#endif // QT_H - -// the following is necessary to work around breakage in many versions -// of XFree86's Xlib.h still in use -// ### which versions? -#if defined(_XLIB_H_) // crude hack, but... -#error "cannot include before this file" -#endif -#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback -#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback -#define XSetIMValues qt_XSetIMValues -#include -#undef XRegisterIMInstantiateCallback -#undef XUnregisterIMInstantiateCallback -#undef XSetIMValues - -#include -#include -#include - - -//#define TQT_NO_SHAPE -#ifdef TQT_NO_SHAPE -#define XShapeCombineRegion(a,b,c,d,e,f,g) -#define XShapeCombineMask(a,b,c,d,e,f,g) -#else -#include -#endif // TQT_NO_SHAPE - - -// the wacom tablet (currently just the IRIX version) -#if defined (QT_TABLET_SUPPORT) -# include -#if defined (Q_OS_IRIX) -# include // wacom driver defines for IRIX (quite handy) -#endif -#endif // QT_TABLET_SUPPORT - - -// #define TQT_NO_XINERAMA -#ifndef TQT_NO_XINERAMA -# if 0 // ### Xsun, but how to detect it? -// Xinerama is only supported in Solaris 7 with patches 107648/108376 and -// Solaris 8 or above which introduce the X11R6.4 Xserver. -// To switch the Xinerama functionality on, you need to add the "+xinerama" -// argument to the Xsun start line. -// At least Solaris 7 and 8 are missing Xinerama system headers and function -// declarations (bug 4284701). -// The Xinerama API is not documented. In theory it could change but it -// probably won't because Sun are using it in at least dtlogin (bug 4221829). -extern "C" Bool XPanoramiXQueryExtension( - Display*, - int*, - int* -); -extern "C" Status XPanoramiXQueryVersion( - Display*, - int*, - int* -); -extern "C" Status XPanoramiXGetState( - Display*, - Drawable, - XPanoramiXInfo* -); -extern "C" Status XPanoramiXGetScreenCount( - Display *, - Drawable, - XPanoramiXInfo* -); -extern "C" Status XPanoramiXGetScreenSize( - Display*, - Drawable, - int, - XPanoramiXInfo* -); -# else // XFree86 -// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3). -extern "C" { -# include -} -# endif -#endif // TQT_NO_XINERAMA - -// #define TQT_NO_XRANDR -#ifndef TQT_NO_XRANDR -# include -#endif // TQT_NO_XRANDR - -// #define TQT_NO_XRENDER -#ifndef TQT_NO_XRENDER -# include -// #define TQT_NO_XFTFREETYPE -# ifndef TQT_NO_XFTFREETYPE -// This hacks around the freetype poeple putting an #error into freetype.h in 2.1.7, making -// it impossible to use an updated freetype with older Xft header files. -# include -# ifdef QT_USE_XFT2_HEADER -# include -# else -# include -# endif // QT_USE_XFT2_HEADER -# if defined(XFT_VERSION) && XFT_VERSION >= 20000 -# define QT_XFT2 -# else -# include -// Xft1 doesn't have these functions, so we implement them in qtaddons_x11.cpp -extern "C" { - TQt::HANDLE XftDrawPicture( XftDraw * ); - void XftDrawSetClipRectangles(XftDraw *, int, int, XRectangle *, int); - void XftDrawSetSubwindowMode(XftDraw *, int); -} -# endif // XFT_VERSION -# endif // TQT_NO_XFTFREETYPE -#else -// make sure TQT_NO_XFTFREETYPE is defined if TQT_NO_XRENDER is defined -# ifndef TQT_NO_XFTFREETYPE -# define TQT_NO_XFTFREETYPE -# endif -#endif // TQT_NO_XRENDER - - -#ifndef TQT_NO_XSYNC -# include -#endif // TQT_NO_XSYNC - - -#ifndef TQT_NO_XKB -# include -#endif // TQT_NO_XKB - - -#if !defined(XlibSpecificationRelease) -# define X11R4 -typedef char *XPointer; -#else -# undef X11R4 -#endif - -// #define TQT_NO_XIM -#if defined(X11R4) -// X11R4 does not have XIM -#define TQT_NO_XIM -#elif defined(Q_OS_OSF) && (XlibSpecificationRelease < 6) -// broken in Xlib up to OSF/1 3.2 -#define TQT_NO_XIM -#elif defined(Q_OS_AIX) -// broken in Xlib up to what version of AIX? -#define TQT_NO_XIM -#elif defined(TQT_NO_DEBUG) && defined(Q_OS_IRIX) -// XmbLookupString broken on IRIX -// XCreateIC broken when compiling -64 on IRIX 6.5.2 -#define TQT_NO_XIM -#elif defined(Q_OS_HPUX) && defined(__LP64__) -// XCreateIC broken when compiling 64-bit ELF on HP-UX 11.0 -#define TQT_NO_XIM -#elif defined(Q_OS_SCO) -// ### suggested by user... -// ### #define TQT_NO_XIM -#endif // TQT_NO_XIM - - -/* - * Solaris patch 108652-47 and higher fixes crases in - * XRegisterIMInstantiateCallback, but the function doesn't seem to - * work. - * - * Instead, we disabled R6 input, and open the input method - * immediately at application start. - */ -#if !defined(TQT_NO_XIM) && (XlibSpecificationRelease >= 6) && \ - !defined(Q_OS_SOLARIS) -#define USE_X11R6_XIM - -//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback -//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2. -//######### Many old X11R6 header files lack XSetIMValues. -//######### Therefore, we have to declare these functions ourselves. - -extern "C" Bool XRegisterIMInstantiateCallback( - Display*, - struct _XrmHashBucketRec*, - char*, - char*, - XIMProc, //XFree86 has XIDProc, which has to be wrong - XPointer -); - -extern "C" Bool XUnregisterIMInstantiateCallback( - Display*, - struct _XrmHashBucketRec*, - char*, - char*, - XIMProc, //XFree86 has XIDProc, which has to be wrong - XPointer -); - -extern "C" char *XSetIMValues( XIM /* im */, ... ); - -#endif - -#ifndef TQT_NO_XIM -// some platforms (eg. Solaris 2.51) don't have these defines in Xlib.h -#ifndef XNResetState -#define XNResetState "resetState" -#endif -#ifndef XIMPreserveState -#define XIMPreserveState (1L<<1) -#endif -#endif - - -#ifndef X11R4 -# include -#endif // X11R4 - - -#ifdef QT_MITSHM -# include -#endif // QT_MITSHM - - -#endif // QT_X11_H diff --git a/src/kernel/qtaddons_x11.cpp b/src/kernel/qtaddons_x11.cpp index ad1ea7e00..089466ec7 100644 --- a/src/kernel/qtaddons_x11.cpp +++ b/src/kernel/qtaddons_x11.cpp @@ -22,7 +22,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #if !defined(TQT_NO_XFTFREETYPE) && !defined(QT_XFT2) diff --git a/src/kernel/qucomextra.cpp b/src/kernel/qucomextra.cpp deleted file mode 100644 index 4e0de283c..000000000 --- a/src/kernel/qucomextra.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Implementation of extra TQUcom classes -** -** Created : 990101 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qucomextra_p.h" -#include - - -#ifndef TQT_NO_VARIANT -// 6dc75d58-a1d9-4417-b591-d45c63a3a4ea -const TQUuid TID_QUType_TQVariant( 0x6dc75d58, 0xa1d9, 0x4417, 0xb5, 0x91, 0xd4, 0x5c, 0x63, 0xa3, 0xa4, 0xea ); -TQUType_TQVariant static_QUType_TQVariant; - -const TQUuid *TQUType_TQVariant::uuid() const { return &TID_QUType_TQVariant; } -const char *TQUType_TQVariant::desc() const { return "TQVariant"; } - -void TQUType_TQVariant::set( TQUObject *o, const TQVariant& v ) -{ - o->payload.ptr = new TQVariant( v ); - o->type = this; -} - -TQVariant &TQUType_TQVariant::get( TQUObject * o ) -{ - return *(TQVariant*)o->payload.ptr; -} - -bool TQUType_TQVariant::canConvertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( o->type, &static_QUType_TQString ) - || isEqual( o->type, &static_QUType_int ) - || isEqual( o->type, &static_QUType_bool ) - || isEqual( o->type, &static_QUType_double ) - || isEqual( o->type, &static_QUType_charstar ) ) - return TRUE; - return t->canConvertTo( o, this ); -} - -bool TQUType_TQVariant::canConvertTo( TQUObject * /*o*/, TQUType * /*t*/ ) -{ - return FALSE; -} - -bool TQUType_TQVariant::convertFrom( TQUObject *o, TQUType *t ) -{ - TQVariant *var = 0; - if ( isEqual( o->type, &static_QUType_TQString ) ) - var = new TQVariant( static_QUType_TQString.get( o ) ); - else if ( isEqual( o->type, &static_QUType_int ) ) - var = new TQVariant( static_QUType_int.get( o ) ); - else if ( isEqual( o->type, &static_QUType_bool ) ) - var = new TQVariant( static_QUType_bool.get( o ) ); - else if ( isEqual( o->type, &static_QUType_double ) ) - var = new TQVariant( static_QUType_double.get( o ) ); - else if ( isEqual( o->type, &static_QUType_charstar ) ) - var = new TQVariant( static_QUType_charstar.get( o ) ); - else - return t->convertTo( o, this ); - - o->type->clear( o ); - o->payload.ptr = var; - o->type = this; - return TRUE; -} - -bool TQUType_TQVariant::convertTo( TQUObject * /*o*/, TQUType * /*t*/ ) -{ - return FALSE; -} - -void TQUType_TQVariant::clear( TQUObject *o ) -{ - delete (TQVariant*)o->payload.ptr; - o->payload.ptr = 0; -} - -int TQUType_TQVariant::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_TQVariant::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - - -#endif - -const TQUuid TID_QUType_varptr( 0x8d48b3a8, 0xbd7f, 0x11d5, 0x8d, 0x74, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3 ); -TQUType_varptr static_QUType_varptr; -const TQUuid *TQUType_varptr::uuid() const { return &TID_QUType_varptr; } -const char *TQUType_varptr::desc() const { return "varptr"; } - -void TQUType_varptr::set( TQUObject *o, const void* v ) -{ - o->payload.ptr = (void*) v; - o->type = this; -} - -bool TQUType_varptr::canConvertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_ptr ) ) - return TRUE; - return t->canConvertTo( o, this ); -} - -bool TQUType_varptr::canConvertTo( TQUObject *, TQUType * t) -{ - return isEqual( t, &static_QUType_ptr ); -} - -bool TQUType_varptr::convertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_ptr ) ) - ; - else - return t->convertTo( o, this ); - - o->type = this; - return TRUE; -} - -bool TQUType_varptr::convertTo( TQUObject *o, TQUType * t) -{ - if ( isEqual( t, &static_QUType_ptr ) ) { - o->type = &static_QUType_ptr; - return TRUE; - } - return FALSE; -} - -int TQUType_varptr::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_varptr::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} diff --git a/src/kernel/qucomextra_p.h b/src/kernel/qucomextra_p.h deleted file mode 100644 index ad4dacb5c..000000000 --- a/src/kernel/qucomextra_p.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Definition of extra TQUcom classes -** -** Created : 990101 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQUCOMEXTRA_P_H -#define TQUCOMEXTRA_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. This header file may -// change from version to version without notice, or even be -// removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include -#endif // QT_H - -#if __GNUC__ - 0 > 3 -#pragma GCC system_header -#endif - -class TQVariant; - -#ifndef TQT_NO_VARIANT -// 6dc75d58-a1d9-4417-b591-d45c63a3a4ea -extern const TQUuid TID_QUType_TQVariant; - -struct TQ_EXPORT TQUType_TQVariant : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, const TQVariant & ); - TQVariant &get( TQUObject * o ); - - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ); - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_TQVariant static_QUType_TQVariant; -#endif //TQT_NO_VARIANT - - -// {0x8d48b3a8, 0xbd7f, 0x11d5, 0x8d, 0x74, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3 } -extern TQ_EXPORT const TQUuid TID_QUType_varptr; -struct TQ_EXPORT TQUType_varptr : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, const void* ); - void* &get( TQUObject * o ) { return o->payload.ptr; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_varptr static_QUType_varptr; - - -#endif // TQUCOMEXTRA_P_H - diff --git a/src/kernel/tqaccessible.cpp b/src/kernel/tqaccessible.cpp index 6cbe717e6..5a43e402b 100644 --- a/src/kernel/tqaccessible.cpp +++ b/src/kernel/tqaccessible.cpp @@ -42,7 +42,7 @@ #include "tqptrdict.h" #include "tqmetaobject.h" -#include +#include #include "ntqapplication.h" #include diff --git a/src/kernel/tqaccessible.h b/src/kernel/tqaccessible.h index ead26b9b0..8cedf1b2c 100644 --- a/src/kernel/tqaccessible.h +++ b/src/kernel/tqaccessible.h @@ -41,7 +41,7 @@ #ifndef QT_H #include "tqobject.h" -#include +#include #include "tqrect.h" #include "tqguardedptr.h" #include "tqmemarray.h" diff --git a/src/kernel/tqclipboard_x11.cpp b/src/kernel/tqclipboard_x11.cpp index e20708f54..16af49f8e 100644 --- a/src/kernel/tqclipboard_x11.cpp +++ b/src/kernel/tqclipboard_x11.cpp @@ -73,7 +73,7 @@ #include "tqtextcodec.h" #include "tqvaluelist.h" #include "tqmap.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include "qapplication_p.h" diff --git a/src/kernel/tqcolor_x11.cpp b/src/kernel/tqcolor_x11.cpp index f5cfc024a..09a8b8880 100644 --- a/src/kernel/tqcolor_x11.cpp +++ b/src/kernel/tqcolor_x11.cpp @@ -44,7 +44,7 @@ #include "tqpaintdevice.h" #include "ntqapplication.h" #include "qapplication_p.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" // NOT REVISED diff --git a/src/kernel/tqcursor_x11.cpp b/src/kernel/tqcursor_x11.cpp index 9facf093c..3724706c2 100644 --- a/src/kernel/tqcursor_x11.cpp +++ b/src/kernel/tqcursor_x11.cpp @@ -44,7 +44,7 @@ #include "ntqapplication.h" #include "tqdatastream.h" #include "tqnamespace.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include #ifndef TQT_NO_XCURSOR diff --git a/src/kernel/tqdesktopwidget_x11.cpp b/src/kernel/tqdesktopwidget_x11.cpp index 5adc611bc..2a9e5bd9e 100644 --- a/src/kernel/tqdesktopwidget_x11.cpp +++ b/src/kernel/tqdesktopwidget_x11.cpp @@ -39,7 +39,7 @@ #include "tqdesktopwidget.h" #include "ntqapplication.h" #include "tqobjectlist.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include // defined in tqwidget_x11.cpp diff --git a/src/kernel/tqeventloop_x11.cpp b/src/kernel/tqeventloop_x11.cpp index b90ce7456..743d48e70 100644 --- a/src/kernel/tqeventloop_x11.cpp +++ b/src/kernel/tqeventloop_x11.cpp @@ -41,7 +41,7 @@ #include "ntqapplication.h" #include "tqbitarray.h" #include "tqcolor_p.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #if defined(TQT_THREAD_SUPPORT) # include "tqmutex.h" diff --git a/src/kernel/tqeventloop_x11_glib.cpp b/src/kernel/tqeventloop_x11_glib.cpp index f16fa1017..28069fe1b 100644 --- a/src/kernel/tqeventloop_x11_glib.cpp +++ b/src/kernel/tqeventloop_x11_glib.cpp @@ -44,7 +44,7 @@ #include "ntqapplication.h" #include "tqbitarray.h" #include "tqcolor_p.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #if defined(TQT_THREAD_SUPPORT) # include "tqmutex.h" diff --git a/src/kernel/tqfont.cpp b/src/kernel/tqfont.cpp index a3e21c655..e058e49d4 100644 --- a/src/kernel/tqfont.cpp +++ b/src/kernel/tqfont.cpp @@ -55,7 +55,7 @@ #include "tqpaintdevicemetrics.h" #endif -#include +#include #include "tqfontdata_p.h" #include "tqfontengine_p.h" #include "tqpainter_p.h" diff --git a/src/kernel/tqfont.h b/src/kernel/tqfont.h index 27f5269e2..435b604df 100644 --- a/src/kernel/tqfont.h +++ b/src/kernel/tqfont.h @@ -193,9 +193,9 @@ public: static void cleanup(); static void cacheStatistics(); - // a copy of this lives in qunicodetables.cpp, as we can't include + // a copy of this lives in tqunicodetables.cpp, as we can't include // tqfont.h it in tools/. Do not modify without changing the script - // enum in qunicodetable_p.h aswell. + // enum in tqunicodetable_p.h aswell. enum Script { // European Alphabetic Scripts Latin, diff --git a/src/kernel/tqfont_x11.cpp b/src/kernel/tqfont_x11.cpp index a54e13dc2..373a82a5f 100644 --- a/src/kernel/tqfont_x11.cpp +++ b/src/kernel/tqfont_x11.cpp @@ -55,12 +55,12 @@ #include "tqtextcodec.h" #include -#include +#include #include "tqfontdata_p.h" #include "tqfontengine_p.h" #include "tqtextengine_p.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include #include diff --git a/src/kernel/tqfontdatabase.cpp b/src/kernel/tqfontdatabase.cpp index 33f10900f..0702bb67f 100644 --- a/src/kernel/tqfontdatabase.cpp +++ b/src/kernel/tqfontdatabase.cpp @@ -45,7 +45,7 @@ #include #include -#include +#include #include "tqfontengine_p.h" #include diff --git a/src/kernel/tqfontdatabase_x11.cpp b/src/kernel/tqfontdatabase_x11.cpp index 49de442cd..23f1f541c 100644 --- a/src/kernel/tqfontdatabase_x11.cpp +++ b/src/kernel/tqfontdatabase_x11.cpp @@ -43,7 +43,7 @@ #include #include -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include #include diff --git a/src/kernel/tqfontengine_p.h b/src/kernel/tqfontengine_p.h index 559972746..dcd306fc0 100644 --- a/src/kernel/tqfontengine_p.h +++ b/src/kernel/tqfontengine_p.h @@ -219,7 +219,7 @@ private: #endif #ifdef TQ_WS_X11 -#include "qt_x11_p.h" +#include "tqt_x11_p.h" struct TransformedFont @@ -406,7 +406,7 @@ class TQTextEngine; #ifndef TQT_NO_XFTFREETYPE -#include "qscriptengine_p.h" +#include "tqscriptengine_p.h" #include "tqtextengine_p.h" #include #include FT_FREETYPE_H diff --git a/src/kernel/tqfontengine_x11.cpp b/src/kernel/tqfontengine_x11.cpp index 8002c42df..1157bbb57 100644 --- a/src/kernel/tqfontengine_x11.cpp +++ b/src/kernel/tqfontengine_x11.cpp @@ -51,12 +51,12 @@ #include "tqpainter.h" #include "tqimage.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include "tqfont.h" #include "tqtextengine_p.h" -#include +#include #include @@ -2234,7 +2234,7 @@ TQFontEngine::Type TQFontEngineXft::type() const #ifndef TQT_NO_XFTFREETYPE -#include "qscriptengine_p.h" +#include "tqscriptengine_p.h" //#define OT_DEBUG diff --git a/src/kernel/tqgplugin.cpp b/src/kernel/tqgplugin.cpp index c0cfd8f47..606e856fb 100644 --- a/src/kernel/tqgplugin.cpp +++ b/src/kernel/tqgplugin.cpp @@ -40,7 +40,7 @@ #ifndef TQT_NO_COMPONENT -#include +#include TQGPlugin::TQGPlugin() : _iface( 0 ) diff --git a/src/kernel/tqgplugin.h b/src/kernel/tqgplugin.h index 88212515b..30e350cd2 100644 --- a/src/kernel/tqgplugin.h +++ b/src/kernel/tqgplugin.h @@ -74,9 +74,9 @@ #define Q_PLUGIN_FLAGS_STRING "01" #endif -// this is duplicated at Q_UCM_VERIFICATION_DATA in qcom_p.h +// this is duplicated at Q_UCM_VERIFICATION_DATA in tqcom_p.h // NOTE: if you change pattern, you MUST change the pattern in -// qcomlibrary.cpp as well. changing the pattern will break all +// tqcomlibrary.cpp as well. changing the pattern will break all // backwards compatibility as well (no old plugins will be loaded). #ifndef Q_PLUGIN_VERIFICATION_DATA # define Q_PLUGIN_VERIFICATION_DATA \ diff --git a/src/kernel/tqimage.cpp b/src/kernel/tqimage.cpp index 0a2995ede..50ed52222 100644 --- a/src/kernel/tqimage.cpp +++ b/src/kernel/tqimage.cpp @@ -50,7 +50,7 @@ #include "tqmngio.h" #include "tqjpegio.h" #include "tqmap.h" -#include +#include #include "tqimageformatinterface_p.h" #include "tqwmatrix.h" #include "ntqapplication.h" diff --git a/src/kernel/tqimageformatinterface_p.h b/src/kernel/tqimageformatinterface_p.h index 8abe49c2d..685b92012 100644 --- a/src/kernel/tqimageformatinterface_p.h +++ b/src/kernel/tqimageformatinterface_p.h @@ -40,7 +40,7 @@ #define TQIMAGEFORMATINTERFACE_P_H #ifndef QT_H -#include +#include #endif // QT_H #if __GNUC__ - 0 > 3 diff --git a/src/kernel/tqinputcontext_p.h b/src/kernel/tqinputcontext_p.h index e7b94e9cc..b2df28c2b 100644 --- a/src/kernel/tqinputcontext_p.h +++ b/src/kernel/tqinputcontext_p.h @@ -63,7 +63,7 @@ class TQString; #ifdef TQ_WS_X11 #include "tqmemarray.h" #include "tqwindowdefs.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #endif #ifdef TQ_WS_WIN diff --git a/src/kernel/tqinputcontext_x11.cpp b/src/kernel/tqinputcontext_x11.cpp index d0f8699b3..7377b264c 100644 --- a/src/kernel/tqinputcontext_x11.cpp +++ b/src/kernel/tqinputcontext_x11.cpp @@ -45,7 +45,7 @@ #include "ntqapplication.h" #include "tqwidget.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" /*! This function may be overridden only if input method is depending diff --git a/src/kernel/tqinternal.cpp b/src/kernel/tqinternal.cpp new file mode 100644 index 000000000..11243d1d2 --- /dev/null +++ b/src/kernel/tqinternal.cpp @@ -0,0 +1,787 @@ +/**************************************************************************** +** +** Implementation of some internal classes +** +** Created : 010427 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "private/tqinternal_p.h" +#include "tqwidget.h" +#include "tqpixmap.h" +#include "tqpainter.h" +#include "tqcleanuphandler.h" + +// Modern systems (year 2011) have very large screens in excess of 1000 pixels wide +// Some may even have screens in excess of 4000 pixels wide(!) +// Prevent drawing artifacts on such screens +#define USE_HUGE_QT_SHARED_DOUBLE_BUFFERS 1 + +static TQPixmap* qdb_shared_pixmap = 0; +static TQPixmap *qdb_force_pixmap = 0; +static TQSharedDoubleBuffer* qdb_owner = 0; + +TQCleanupHandler qdb_pixmap_cleanup; + +#ifdef TQ_WS_MACX +bool TQSharedDoubleBuffer::dblbufr = FALSE; +#else +bool TQSharedDoubleBuffer::dblbufr = TRUE; +#endif + + +/* + hardLimitWidth/Height: if >= 0, the maximum number of pixels that + get double buffered. + + sharedLimitWidth/Height: if >= 0, the maximum number of pixels the + shared double buffer can keep. + + For x with sharedLimitSize < x <= hardLimitSize, temporary buffers + are constructed. + */ +static const int hardLimitWidth = -1; +static const int hardLimitHeight = -1; +#if defined( TQ_WS_MAC9 ) +// Small in Mac9 - 5K on 32bpp +static const int sharedLimitWidth = 64; +static const int sharedLimitHeight = 20; +#else +#ifdef USE_HUGE_QT_SHARED_DOUBLE_BUFFERS +// 24M on 32bpp +static const int sharedLimitWidth = 6400; +static const int sharedLimitHeight = 1000; +#else +// 240K on 32bpp +static const int sharedLimitWidth = 640; +static const int sharedLimitHeight = 100; +#endif +#endif + +// ******************************************************************* +// TQSharedDoubleBufferCleaner declaration and implementation +// ******************************************************************* + +/* \internal + This class is responsible for cleaning up the pixmaps created by the + TQSharedDoubleBuffer class. When TQSharedDoubleBuffer creates a + pixmap larger than the shared limits, this class deletes it after a + specified amount of time. + + When the large pixmap is created/used, you must call start(). If the + large pixmap is ever deleted, you must call stop(). The start() + method always restarts the timer, so if the large pixmap is + constantly in use, the timer will never fire, and the pixmap will + not be constantly created and destroyed. +*/ + +static const int shared_double_buffer_cleanup_timeout = 30000; // 30 seconds + +// declaration + +class TQSharedDoubleBufferCleaner : public TQObject +{ +public: + TQSharedDoubleBufferCleaner( void ); + + void start( void ); + void stop( void ); + + void doCleanup( void ); + + bool event( TQEvent *e ); + +private: + int timer_id; +}; + +// implementation + +/* \internal + Creates a TQSharedDoubleBufferCleaner object. The timer is not + started when creating the object. +*/ +TQSharedDoubleBufferCleaner::TQSharedDoubleBufferCleaner( void ) + : TQObject( 0, "internal shared double buffer cleanup object" ), + timer_id( -1 ) +{ +} + +/* \internal + Starts the cleanup timer. Any previously running timer is stopped. +*/ +void TQSharedDoubleBufferCleaner::start( void ) +{ + stop(); + timer_id = startTimer( shared_double_buffer_cleanup_timeout ); +} + +/* \internal + Stops the cleanup timer, if it is running. +*/ +void TQSharedDoubleBufferCleaner::stop( void ) +{ + if ( timer_id != -1 ) + killTimer( timer_id ); + timer_id = -1; +} + +/* \internal + */ +void TQSharedDoubleBufferCleaner::doCleanup( void ) +{ + qdb_pixmap_cleanup.remove( &qdb_force_pixmap ); + delete qdb_force_pixmap; + qdb_force_pixmap = 0; +} + +/* \internal + Event handler reimplementation. Calls doCleanup() when the timer + fires. +*/ +bool TQSharedDoubleBufferCleaner::event( TQEvent *e ) +{ + if ( e->type() != TQEvent::Timer ) + return FALSE; + + TQTimerEvent *event = (TQTimerEvent *) e; + if ( event->timerId() == timer_id ) { + doCleanup(); + stop(); + } +#ifdef QT_CHECK_STATE + else { + tqWarning( "TQSharedDoubleBufferCleaner::event: invalid timer event received." ); + return FALSE; + } +#endif // QT_CHECK_STATE + + return TRUE; +} + +// static instance +static TQSharedDoubleBufferCleaner *static_cleaner = 0; +TQSingleCleanupHandler cleanup_static_cleaner; + +inline static TQSharedDoubleBufferCleaner *staticCleaner() +{ + if ( ! static_cleaner ) { + static_cleaner = new TQSharedDoubleBufferCleaner(); + cleanup_static_cleaner.set( &static_cleaner ); + } + return static_cleaner; +} + + +// ******************************************************************* +// TQSharedDoubleBuffer implementation +// ******************************************************************* + +/* \internal + \enum DoubleBufferFlags + + \value InitBG initialize the background of the double buffer. + + \value Force disable shared buffer size limits. + + \value Default InitBG and Force are used by default. +*/ + +/* \internal + \enum DoubleBufferState + + \value Active indicates that the buffer may be used. + + \value BufferActive indicates that painting with painter() will be + double buffered. + + \value ExternalPainter indicates that painter() will return a + painter that was not created by TQSharedDoubleBuffer. +*/ + +/* \internal + \class TQSharedDoubleBuffer + + This class provides a single, reusable double buffer. This class + is used internally by TQt widgets that need double buffering, which + prevents each individual widget form creating a double buffering + pixmap. + + Using a single pixmap double buffer and sharing it across all + widgets is nicer on window system resources. +*/ + +/* \internal + Creates a TQSharedDoubleBuffer with flags \f. + + \sa DoubleBufferFlags +*/ +TQSharedDoubleBuffer::TQSharedDoubleBuffer( DBFlags f ) + : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), + p( 0 ), external_p( 0 ), pix( 0 ) +{ +} + +/* \internal + Creates a TQSharedDoubleBuffer with flags \f. The \a widget, \a x, + \a y, \a w and \a h arguments are passed to begin(). + + \sa DoubleBufferFlags begin() +*/ +TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQWidget* widget, + int x, int y, int w, int h, + DBFlags f ) + : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), + p( 0 ), external_p( 0 ), pix( 0 ) +{ + begin( widget, x, y, w, h ); +} + +/* \internal + Creates a TQSharedDoubleBuffer with flags \f. The \a painter, \a x, + \a y, \a w and \a h arguments are passed to begin(). + + \sa DoubleBufferFlags begin() +*/ +TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQPainter* painter, + int x, int y, int w, int h, + DBFlags f) + : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), + p( 0 ), external_p( 0 ), pix( 0 ) +{ + begin( painter, x, y, w, h ); +} + +/* \internal + Creates a TQSharedDoubleBuffer with flags \f. The \a widget and + \a r arguments are passed to begin(). + + \sa DoubleBufferFlags begin() +*/ +TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQWidget *widget, const TQRect &r, DBFlags f ) + : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), + p( 0 ), external_p( 0 ), pix( 0 ) +{ + begin( widget, r ); +} + +/* \internal + Creates a TQSharedDoubleBuffer with flags \f. The \a painter and + \a r arguments are passed to begin(). + + \sa DoubleBufferFlags begin() +*/ +TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQPainter *painter, const TQRect &r, DBFlags f ) + : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ), + p( 0 ), external_p( 0 ), pix( 0 ) +{ + begin( painter, r ); +} + +/* \internal + Destructs the TQSharedDoubleBuffer and calls end() if the buffer is + active. + + \sa isActive() end() +*/ +TQSharedDoubleBuffer::~TQSharedDoubleBuffer() +{ + if ( isActive() ) + end(); +} + +/* \internal + Starts double buffered painting in the area specified by \a x, + \a y, \a w and \a h on \a painter. Painting should be done using the + TQPainter returned by TQSharedDoubleBuffer::painter(). + + The double buffered area will be updated when calling end(). + + \sa painter() isActive() end() +*/ +bool TQSharedDoubleBuffer::begin( TQPainter* painter, int x, int y, int w, int h ) +{ + if ( isActive() ) { +#if defined(QT_CHECK_STATE) + tqWarning( "TQSharedDoubleBuffer::begin: Buffer is already active." + "\n\tYou must end() the buffer before a second begin()" ); +#endif // QT_CHECK_STATE + return FALSE; + } + + external_p = painter; + + if ( painter->device()->devType() == TQInternal::Widget ) + return begin( (TQWidget *) painter->device(), x, y, w, h ); + + state = Active; + + rx = x; + ry = y; + rw = w; + rh = h; + + if ( ( pix = getPixmap() ) ) { +#ifdef TQ_WS_X11 + if ( painter->device()->x11Screen() != pix->x11Screen() ) + pix->x11SetScreen( painter->device()->x11Screen() ); + TQPixmap::x11SetDefaultScreen( pix->x11Screen() ); +#endif // TQ_WS_X11 + + state |= BufferActive; + p = new TQPainter( pix ); + if ( p->isActive() ) { + p->setPen( external_p->pen() ); + p->setBackgroundColor( external_p->backgroundColor() ); + p->setFont( external_p->font() ); + } + } else { + state |= ExternalPainter; + p = external_p; + } + + return TRUE; +} + +/* \internal + + + Starts double buffered painting in the area specified by \a x, + \a y, \a w and \a h on \a widget. Painting should be done using the + TQPainter returned by TQSharedDoubleBuffer::painter(). + + The double buffered area will be updated when calling end(). + + \sa painter() isActive() end() +*/ +bool TQSharedDoubleBuffer::begin( TQWidget* widget, int x, int y, int w, int h ) +{ + if ( isActive() ) { +#if defined(QT_CHECK_STATE) + tqWarning( "TQSharedDoubleBuffer::begin: Buffer is already active." + "\n\tYou must end() the buffer before a second begin()" ); +#endif // QT_CHECK_STATE + return FALSE; + } + + state = Active; + + wid = widget; + rx = x; + ry = y; + rw = w <= 0 ? wid->width() : w; + rh = h <= 0 ? wid->height() : h; + + if ( ( pix = getPixmap() ) ) { +#ifdef TQ_WS_X11 + if ( wid->x11Screen() != pix->x11Screen() ) + pix->x11SetScreen( wid->x11Screen() ); + TQPixmap::x11SetDefaultScreen( pix->x11Screen() ); +#endif // TQ_WS_X11 + + state |= BufferActive; + if ( flags & InitBG ) { + pix->fill( wid, rx, ry ); + } + p = new TQPainter( pix, wid ); + // newly created painters should be translated to the origin + // of the widget, so that paint methods can draw onto the double + // buffered painter in widget coordinates. + p->setBrushOrigin( -rx, -ry ); + p->translate( -rx, -ry ); + } else { + if ( external_p ) { + state |= ExternalPainter; + p = external_p; + } else { + p = new TQPainter( wid ); + } + + if ( flags & InitBG ) { + wid->erase( rx, ry, rw, rh ); + } + } + return TRUE; +} + +/* \internal + Ends double buffered painting. The contents of the shared double + buffer pixmap are drawn onto the destination by calling flush(), + and ownership of the shared double buffer pixmap is released. + + \sa begin() flush() +*/ +bool TQSharedDoubleBuffer::end() +{ + if ( ! isActive() ) { +#if defined(QT_CHECK_STATE) + tqWarning( "TQSharedDoubleBuffer::end: Buffer is not active." + "\n\tYou must call begin() before calling end()." ); +#endif // QT_CHECK_STATE + return FALSE; + } + + if ( ! ( state & ExternalPainter ) ) { + p->end(); + delete p; + } + + flush(); + + if ( pix ) { + releasePixmap(); + } + + wid = 0; + rx = ry = rw = rh = 0; + // do not reset flags! + state = 0; + + p = external_p = 0; + pix = 0; + + return TRUE; +} + +/* \internal + Paints the contents of the shared double buffer pixmap onto the + destination. The destination is determined from the arguments + based to begin(). + + Note: You should not need to call this function, since it is called + from end(). + + \sa begin() end() +*/ +void TQSharedDoubleBuffer::flush() +{ + if ( ! isActive() || ! ( state & BufferActive ) ) + return; + + if ( external_p ) + external_p->drawPixmap( rx, ry, *pix, 0, 0, rw, rh ); + else if ( wid && wid->isVisible() ) + bitBlt( wid, rx, ry, pix, 0, 0, rw, rh ); +} + +/* \internal + Acquire ownership of the shared double buffer pixmap, subject to the + following conditions: + + \list 1 + \i double buffering is enabled globally. + \i the shared double buffer pixmap is not in use. + \i the size specified in begin() is valid, and within limits. + \endlist + + If all of these conditions are met, then this TQSharedDoubleBuffer + object becomes the owner of the shared double buffer pixmap. The + shared double buffer pixmap is resize if necessary, and this + function returns a pointer to the pixmap. Ownership must later be + relinquished by calling releasePixmap(). + + If none of the above conditions are met, this function returns + zero. + + \sa releasePixmap() +*/ +TQPixmap *TQSharedDoubleBuffer::getPixmap() +{ + if ( isDisabled() ) { + // double buffering disabled globally + return 0; + } + + if ( qdb_owner ) { + // shared pixmap already in use + return 0; + } + + if ( rw <= 0 || rh <= 0 || + ( hardLimitWidth > 0 && rw >= hardLimitWidth ) || + ( hardLimitHeight > 0 && rh >= hardLimitHeight ) ) { + // invalid size, or hard limit reached + return 0; + } + + if ( rw >= sharedLimitWidth || rh >= sharedLimitHeight ) { + if ( flags & Force ) { +#ifdef USE_HUGE_QT_SHARED_DOUBLE_BUFFERS + rw = TQMIN(rw, 16000); + rh = TQMIN(rh, 16000); +#else + rw = TQMIN(rw, 8000); + rh = TQMIN(rh, 8000); +#endif + // need to create a big pixmap and start the cleaner + if ( ! qdb_force_pixmap ) { + qdb_force_pixmap = new TQPixmap( rw, rh ); + qdb_pixmap_cleanup.add( &qdb_force_pixmap ); + } else if ( qdb_force_pixmap->width () < rw || + qdb_force_pixmap->height() < rh ) { + qdb_force_pixmap->resize( rw, rh ); + } + qdb_owner = this; + staticCleaner()->start(); + return qdb_force_pixmap; + } + + // size is outside shared limit + return 0; + } + + if ( ! qdb_shared_pixmap ) { + qdb_shared_pixmap = new TQPixmap( rw, rh ); + qdb_pixmap_cleanup.add( &qdb_shared_pixmap ); + } else if ( qdb_shared_pixmap->width() < rw || + qdb_shared_pixmap->height() < rh ) { + qdb_shared_pixmap->resize( rw, rh ); + } + qdb_owner = this; + return qdb_shared_pixmap; +} + +/* \internal + Releases ownership of the shared double buffer pixmap. + + \sa getPixmap() +*/ +void TQSharedDoubleBuffer::releasePixmap() +{ + if ( qdb_owner != this ) { + // sanity check + +#ifdef QT_CHECK_STATE + tqWarning( "TQSharedDoubleBuffer::releasePixmap: internal error." + "\n\t%p does not own shared pixmap, %p does.", + (void*)this, (void*)qdb_owner ); +#endif // QT_CHECK_STATE + + return; + } + + qdb_owner = 0; +} + +/* \internal + \fn bool TQSharedDoubleBuffer::isDisabled() + + Returns TRUE if double buffering is disabled globally, FALSE otherwise. +*/ + +/* \internal + \fn void TQSharedDoubleBuffer::setDisabled( bool off ) + + Disables global double buffering \a off is TRUE, otherwise global + double buffering is enabled. +*/ + +/* \internal + Deletes the shared double buffer pixmap. You should not need to + call this function, since it is called from the TQApplication + destructor. +*/ +void TQSharedDoubleBuffer::cleanup() +{ + qdb_pixmap_cleanup.remove( &qdb_shared_pixmap ); + qdb_pixmap_cleanup.remove( &qdb_force_pixmap ); + delete qdb_shared_pixmap; + delete qdb_force_pixmap; + qdb_shared_pixmap = 0; + qdb_force_pixmap = 0; + qdb_owner = 0; +} + +/* \internal + \fn bool TQSharedDoubleBuffer::begin( TQWidget *widget, const TQRect &r ) + \overload +*/ + +/* \internal + \fn bool TQSharedDoubleBuffer::begin( TQPainter *painter, const TQRect &r ) + \overload +*/ + +/* \internal + \fn TQPainter *TQSharedDoubleBuffer::painter() const + + Returns the active painter on the double buffered area, + or zero if double buffered painting is not active. +*/ + +/* \internal + \fn bool TQSharedDoubleBuffer::isActive() const + + Returns TRUE if double buffered painting is active, FALSE otherwise. +*/ + +/* \internal + \fn bool TQSharedDoubleBuffer::isBuffered() const + + Returns TRUE if painting is double buffered, FALSE otherwise. +*/ + + +// ******************************************************************* +// TQMembuf declaration and implementation +// ******************************************************************* + +/* \internal + This class implements an efficient buffering of data that is often used by + asynchronous IO classes like TQSocket, TQHttp and TQProcess. +*/ + +TQMembuf::TQMembuf() : _size(0), _index(0) +{ + buf = new TQPtrList; + buf->setAutoDelete( TRUE ); +} + +TQMembuf::~TQMembuf() +{ + delete buf; +} + +/*! \internal + This function consumes \a nbytes bytes of data from the + buffer and copies it into \a sink. If \a sink is a 0 pointer + the data goes into the nirvana. +*/ +bool TQMembuf::consumeBytes( TQ_ULONG nbytes, char *sink ) +{ + if ( nbytes <= 0 || nbytes > _size ) + return FALSE; + _size -= nbytes; + for ( ;; ) { + TQByteArray *a = buf->first(); + if ( _index + nbytes >= a->size() ) { + // Here we skip the whole byte array and get the next later + int len = a->size() - _index; + if ( sink ) { + memcpy( sink, a->data()+_index, len ); + sink += len; + } + nbytes -= len; + buf->remove(); + _index = 0; + if ( nbytes == 0 ) + break; + } else { + // Here we skip only a part of the first byte array + if ( sink ) + memcpy( sink, a->data()+_index, nbytes ); + _index += nbytes; + break; + } + } + return TRUE; +} + +/*! \internal + Scans for any occurrence of '\n' in the buffer. If \a store + is not 0 the text up to the first '\n' (or terminating 0) is + written to \a store, and a terminating 0 is appended to \a store + if necessary. Returns TRUE if a '\n' was found; otherwise returns + FALSE. +*/ +bool TQMembuf::scanNewline( TQByteArray *store ) +{ + if ( _size == 0 ) + return FALSE; + int i = 0; // index into 'store' + TQByteArray *a = 0; + char *p; + int n; + for ( ;; ) { + if ( !a ) { + a = buf->first(); + if ( !a || a->size() == 0 ) + return FALSE; + p = a->data() + _index; + n = a->size() - _index; + } else { + a = buf->next(); + if ( !a || a->size() == 0 ) + return FALSE; + p = a->data(); + n = a->size(); + } + if ( store ) { + while ( n-- > 0 ) { + *(store->data()+i) = *p; + if ( ++i == (int)store->size() ) + store->resize( store->size() < 256 + ? 1024 : store->size()*4 ); + switch ( *p ) { + case '\0': + store->resize( i ); + return FALSE; + case '\n': + *(store->data()+i) = '\0'; + store->resize( i ); + return TRUE; + } + p++; + } + } else { + while ( n-- > 0 ) { + switch ( *p++ ) { + case '\0': + return FALSE; + case '\n': + return TRUE; + } + } + } + } +} + +int TQMembuf::ungetch( int ch ) +{ + if ( buf->isEmpty() || _index==0 ) { + // we need a new TQByteArray + TQByteArray *ba = new TQByteArray( 1 ); + buf->insert( 0, ba ); + _size++; + ba->at( 0 ) = ch; + } else { + // we can reuse a place in the buffer + TQByteArray *ba = buf->first(); + _index--; + _size++; + ba->at( _index ) = ch; + } + return ch; +} diff --git a/src/kernel/tqinternal_p.h b/src/kernel/tqinternal_p.h new file mode 100644 index 000000000..d8c29cc67 --- /dev/null +++ b/src/kernel/tqinternal_p.h @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Definition of some shared interal classes +** +** Created : 010427 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQINTERNAL_P_H +#define TQINTERNAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of a number of TQt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// +#ifndef QT_H +#include "tqnamespace.h" +#include "tqrect.h" +#include "tqptrlist.h" +#include "tqcstring.h" +#include "tqiodevice.h" +#endif // QT_H + +class TQWidget; +class TQPainter; +class TQPixmap; + +class TQ_EXPORT TQSharedDoubleBuffer +{ +public: + enum DoubleBufferFlags { + NoFlags = 0x00, + InitBG = 0x01, + Force = 0x02, + Default = InitBG | Force + }; + typedef uint DBFlags; + + TQSharedDoubleBuffer( DBFlags f = Default ); + TQSharedDoubleBuffer( TQWidget* widget, + int x = 0, int y = 0, int w = -1, int h = -1, + DBFlags f = Default ); + TQSharedDoubleBuffer( TQPainter* painter, + int x = 0, int y = 0, int w = -1, int h = -1, + DBFlags f = Default ); + TQSharedDoubleBuffer( TQWidget *widget, const TQRect &r, DBFlags f = Default ); + TQSharedDoubleBuffer( TQPainter *painter, const TQRect &r, DBFlags f = Default ); + ~TQSharedDoubleBuffer(); + + bool begin( TQWidget* widget, int x = 0, int y = 0, int w = -1, int h = -1 ); + bool begin( TQPainter* painter, int x = 0, int y = 0, int w = -1, int h = -1); + bool begin( TQWidget* widget, const TQRect &r ); + bool begin( TQPainter* painter, const TQRect &r ); + bool end(); + + TQPainter* painter() const; + + bool isActive() const; + bool isBuffered() const; + void flush(); + + static bool isDisabled() { return !dblbufr; } + static void setDisabled( bool off ) { dblbufr = !off; } + + static void cleanup(); + +private: + enum DoubleBufferState { + Active = 0x0100, + BufferActive = 0x0200, + ExternalPainter = 0x0400 + }; + typedef uint DBState; + + TQPixmap *getPixmap(); + void releasePixmap(); + + TQWidget *wid; + int rx, ry, rw, rh; + DBFlags flags; + DBState state; + + TQPainter *p, *external_p; + TQPixmap *pix; + + static bool dblbufr; +}; + +inline bool TQSharedDoubleBuffer::begin( TQWidget* widget, const TQRect &r ) +{ return begin( widget, r.x(), r.y(), r.width(), r.height() ); } + +inline bool TQSharedDoubleBuffer::begin( TQPainter *painter, const TQRect &r ) +{ return begin( painter, r.x(), r.y(), r.width(), r.height() ); } + +inline TQPainter* TQSharedDoubleBuffer::painter() const +{ return p; } + +inline bool TQSharedDoubleBuffer::isActive() const +{ return ( state & Active ); } + +inline bool TQSharedDoubleBuffer::isBuffered() const +{ return ( state & BufferActive ); } + + +class TQVirtualDestructor { +public: + virtual ~TQVirtualDestructor() {} +}; + +template +class TQAutoDeleter : public TQVirtualDestructor { +public: + TQAutoDeleter( T* p ) : ptr( p ) {} + ~TQAutoDeleter() { delete ptr; } + T* data() const { return ptr; } +private: + T* ptr; +}; + +template +T* qAutoDeleterData( TQAutoDeleter* ad ) +{ + if ( !ad ) + return 0; + return ad->data(); +} + +template +TQAutoDeleter* qAutoDeleter( T* p ) +{ + return new TQAutoDeleter( p ); +} + +class TQ_EXPORT TQMembuf +{ +public: + TQMembuf(); + ~TQMembuf(); + + void append( TQByteArray *ba ); + void clear(); + + bool consumeBytes( TQ_ULONG nbytes, char *sink ); + TQByteArray readAll(); + bool scanNewline( TQByteArray *store ); + bool canReadLine() const; + + int ungetch( int ch ); + + TQIODevice::Offset size() const; + +private: + + TQPtrList *buf; + TQIODevice::Offset _size; + TQIODevice::Offset _index; +}; + +inline void TQMembuf::append( TQByteArray *ba ) +{ buf->append( ba ); _size += ba->size(); } + +inline void TQMembuf::clear() +{ buf->clear(); _size=0; _index=0; } + +inline TQByteArray TQMembuf::readAll() +{ TQByteArray ba(_size); consumeBytes(_size,ba.data()); return ba; } + +inline bool TQMembuf::canReadLine() const +{ return ((TQMembuf*)this)->scanNewline( 0 ); } + +inline TQIODevice::Offset TQMembuf::size() const +{ return _size; } + +#endif // TQINTERNAL_P_H diff --git a/src/kernel/tqmotifdnd_x11.cpp b/src/kernel/tqmotifdnd_x11.cpp index 8bd2d8b8f..cf5867aeb 100644 --- a/src/kernel/tqmotifdnd_x11.cpp +++ b/src/kernel/tqmotifdnd_x11.cpp @@ -73,7 +73,7 @@ in doc/dnd.doc, where the documentation system can see it. */ #ifndef TQT_NO_DRAGANDDROP #include "tqwidget.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include diff --git a/src/kernel/tqobject.cpp b/src/kernel/tqobject.cpp index 1e376c21e..84361e501 100644 --- a/src/kernel/tqobject.cpp +++ b/src/kernel/tqobject.cpp @@ -45,8 +45,8 @@ #include "tqsignalslotimp.h" #include "tqregexp.h" #include "tqmetaobject.h" -#include -#include "qucomextra_p.h" +#include +#include "tqucomextra_p.h" #include "tqptrvector.h" // TQStyleControlElementData diff --git a/src/kernel/tqpaintdevice_x11.cpp b/src/kernel/tqpaintdevice_x11.cpp index 5a1ce8302..37bdfa83e 100644 --- a/src/kernel/tqpaintdevice_x11.cpp +++ b/src/kernel/tqpaintdevice_x11.cpp @@ -44,7 +44,7 @@ #include "tqwidget.h" #include "tqbitmap.h" #include "ntqapplication.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" /*! diff --git a/src/kernel/tqpainter.cpp b/src/kernel/tqpainter.cpp index b2c0d5fba..b66f16d2b 100644 --- a/src/kernel/tqpainter.cpp +++ b/src/kernel/tqpainter.cpp @@ -48,7 +48,7 @@ #include "tqimage.h" #include "tqpaintdevicemetrics.h" #include "ntqapplication.h" -#include "qrichtext_p.h" +#include "tqrichtext_p.h" #include "tqregexp.h" #include "tqcleanuphandler.h" #include diff --git a/src/kernel/tqpainter_x11.cpp b/src/kernel/tqpainter_x11.cpp index 22d892d17..d419b3411 100644 --- a/src/kernel/tqpainter_x11.cpp +++ b/src/kernel/tqpainter_x11.cpp @@ -48,7 +48,7 @@ #include "tqtextcodec.h" #include "tqpaintdevicemetrics.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include "tqtextlayout_p.h" #include "tqfontdata_p.h" diff --git a/src/kernel/tqpicture.cpp b/src/kernel/tqpicture.cpp index 3ab6a000b..c0fb3d008 100644 --- a/src/kernel/tqpicture.cpp +++ b/src/kernel/tqpicture.cpp @@ -50,7 +50,7 @@ #include "tqpaintdevicemetrics.h" #ifndef TQT_NO_SVG -#include "private/qsvgdevice_p.h" +#include "private/tqsvgdevice_p.h" #endif /*! diff --git a/src/kernel/tqpixmap.cpp b/src/kernel/tqpixmap.cpp index 460dfc64d..4a40d821b 100644 --- a/src/kernel/tqpixmap.cpp +++ b/src/kernel/tqpixmap.cpp @@ -48,7 +48,7 @@ #include "tqbuffer.h" #include "tqobjectlist.h" #include "ntqapplication.h" -#include +#include #include "tqmime.h" #include "tqdragobject.h" #include "tqfile.h" diff --git a/src/kernel/tqpixmap_x11.cpp b/src/kernel/tqpixmap_x11.cpp index b1e6c6894..9f8c6b7d1 100644 --- a/src/kernel/tqpixmap_x11.cpp +++ b/src/kernel/tqpixmap_x11.cpp @@ -72,7 +72,7 @@ #include "tqimage.h" #include "tqwmatrix.h" #include "ntqapplication.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include diff --git a/src/kernel/tqprinter_unix.cpp b/src/kernel/tqprinter_unix.cpp index 06eeabbdd..2899d86df 100644 --- a/src/kernel/tqprinter_unix.cpp +++ b/src/kernel/tqprinter_unix.cpp @@ -52,7 +52,7 @@ static inline int qt_open(const char *pathname, int flags, mode_t mode) #ifndef TQT_NO_PRINTER #include "tqpaintdevicemetrics.h" -#include "qpsprinter_p.h" +#include "tqpsprinter_p.h" #include "tqprintdialog.h" #include "ntqapplication.h" #include "tqprinter_p.h" diff --git a/src/kernel/tqprocess.cpp b/src/kernel/tqprocess.cpp index b3837d7d9..db2318a30 100644 --- a/src/kernel/tqprocess.cpp +++ b/src/kernel/tqprocess.cpp @@ -46,7 +46,7 @@ #ifndef TQT_NO_PROCESS #include "ntqapplication.h" -#include "private/qinternal_p.h" +#include "private/tqinternal_p.h" //#define QT_QPROCESS_DEBUG diff --git a/src/kernel/tqprocess_unix.cpp b/src/kernel/tqprocess_unix.cpp index c3bb2ba70..d85b64d71 100644 --- a/src/kernel/tqprocess_unix.cpp +++ b/src/kernel/tqprocess_unix.cpp @@ -56,7 +56,7 @@ #include "tqtimer.h" #include "tqcleanuphandler.h" #include "tqregexp.h" -#include "private/qinternal_p.h" +#include "private/tqinternal_p.h" #include #include diff --git a/src/kernel/tqpsprinter.cpp b/src/kernel/tqpsprinter.cpp new file mode 100644 index 000000000..80e00ae23 --- /dev/null +++ b/src/kernel/tqpsprinter.cpp @@ -0,0 +1,6574 @@ +/********************************************************************** +** +** Implementation of TQPSPrinter class +** +** Created : 941003 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +// POSIX Large File Support redefines open -> open64 +#if defined(open) +# undef open +#endif + +// POSIX Large File Support redefines truncate -> truncate64 +#if defined(truncate) +# undef truncate +#endif + +#include "tqpsprinter_p.h" + +#ifndef TQT_NO_PRINTER + +#undef Q_PRINTER_USE_TYPE42 + +#include "tqpainter.h" +#include "ntqapplication.h" +#include "tqpaintdevicemetrics.h" +#include "tqimage.h" +#include "tqdatetime.h" +#include "tqstring.h" +#include "tqdict.h" +#include "tqmemarray.h" +#include "tqfile.h" +#include "tqbuffer.h" +#include "tqintdict.h" +#include "tqtextcodec.h" +#include "tqsettings.h" +#include "tqmap.h" +#include "tqfontdatabase.h" +#include "tqregexp.h" +#include "tqbitmap.h" +#include + +#if defined(Q_OS_WIN32) +#include +#ifdef Q_PRINTER_USE_TYPE42 +#include +#endif +#else +#include +#include +#endif + +#ifdef TQ_WS_X11 +#include "tqt_x11_p.h" +#ifdef None +#undef None +#endif +#ifdef GrayScale +#undef GrayScale +#endif +#endif + +#if defined( TQ_WS_X11 ) +#include "tqfontdata_p.h" +#include "tqfontengine_p.h" +#include "tqtextlayout_p.h" +#include "tqtextengine_p.h" +extern bool tqt_has_xft; +#endif + +static bool qt_gen_epsf = FALSE; +static bool embedFonts = TRUE; + +TQ_EXPORT void tqt_generate_epsf( bool b ) +{ + qt_gen_epsf = b; +} + +static const char *const ps_header = +"/d/def load def/D{bind d}bind d/d2{dup dup}D/B{0 d2}D/W{255 d2}D/ED{exch d}D\n" +"/D0{0 ED}D/LT{lineto}D/MT{moveto}D/S{stroke}D/F{setfont}D/SW{setlinewidth}D\n" +"/CP{closepath}D/RL{rlineto}D/NP{newpath}D/CM{currentmatrix}D/SM{setmatrix}D\n" +"/TR{translate}D/SD{setdash}D/SC{aload pop setrgbcolor}D/CR{currentfile read\n" +"pop}D/i{index}D/bs{bitshift}D/scs{setcolorspace}D/DB{dict dup begin}D/DE{end\n" +"d}D/ie{ifelse}D/sp{astore pop}D/BSt 0 d/LWi 1 d/PSt 1 d/Cx 0 d/Cy 0 d/WFi\n" +"false d/OMo false d/BCol[1 1 1]d/PCol[0 0 0]d/BkCol[1 1 1]d/BDArr[0.94 0.88\n" +"0.63 0.50 0.37 0.12 0.06]d/defM matrix d/nS 0 d/GPS{PSt 1 ge PSt 5 le and{{\n" +"LArr PSt 1 sub 2 mul get}{LArr PSt 2 mul 1 sub get}ie}{[]}ie}D/QS{PSt 0 ne{\n" +"gsave LWi SW true GPS 0 SD S OMo PSt 1 ne and{BkCol SC false GPS dup 0 get\n" +"SD S}if grestore}if}D/r28{{CR dup 32 gt{exit}if pop}loop 3{CR}repeat 0 4{7\n" +"bs exch dup 128 gt{84 sub}if 42 sub 127 and add}repeat}D/rA 0 d/rL 0 d/rB{rL\n" +"0 eq{/rA r28 d/rL 28 d}if dup rL gt{rA exch rL sub rL exch/rA 0 d/rL 0 d rB\n" +"exch bs add}{dup rA 16#fffffff 3 -1 roll bs not and exch dup rL exch sub/rL\n" +"ED neg rA exch bs/rA ED}ie}D/uc{/rL 0 d 0{dup 2 i length ge{exit}if 1 rB 1\n" +"eq{3 rB dup 3 ge{1 add dup rB 1 i 5 ge{1 i 6 ge{1 i 7 ge{1 i 8 ge{128 add}if\n" +"64 add}if 32 add}if 16 add}if 3 add exch pop}if 3 add exch 10 rB 1 add{dup 3\n" +"i lt{dup}{2 i}ie 4 i 3 i 3 i sub 2 i getinterval 5 i 4 i 3 -1 roll\n" +"putinterval dup 4 -1 roll add 3 1 roll 4 -1 roll exch sub dup 0 eq{exit}if 3\n" +"1 roll}loop pop pop}{3 rB 1 add{2 copy 8 rB put 1 add}repeat}ie}loop pop}D\n" +"/sl D0/TQCIgray D0/TQCIcolor D0/TQCIindex D0/TQCI{/colorimage where{pop false 3\n" +"colorimage}{exec/TQCIcolor ED/TQCIgray TQCIcolor length 3 idiv string d 0 1\n" +"TQCIcolor length 3 idiv 1 sub{/TQCIindex ED/x TQCIindex 3 mul d TQCIgray\n" +"TQCIindex TQCIcolor x get 0.30 mul TQCIcolor x 1 add get 0.59 mul TQCIcolor x 2\n" +"add get 0.11 mul add add cvi put}for TQCIgray image}ie}D/di{gsave TR 1 i 1 eq\n" +"{false eq{pop true 3 1 roll 4 i 4 i false 4 i 4 i imagemask BkCol SC\n" +"imagemask}{pop false 3 1 roll imagemask}ie}{dup false ne{/languagelevel\n" +"where{pop languagelevel 3 ge}{false}ie}{false}ie{/ma ED 8 eq{/dc[0 1]d\n" +"/DeviceGray}{/dc[0 1 0 1 0 1]d/DeviceRGB}ie scs/im ED/mt ED/h ED/w ED/id 7\n" +"DB/ImageType 1 d/Width w d/Height h d/ImageMatrix mt d/DataSource im d\n" +"/BitsPerComponent 8 d/Decode dc d DE/md 7 DB/ImageType 1 d/Width w d/Height\n" +"h d/ImageMatrix mt d/DataSource ma d/BitsPerComponent 1 d/Decode[0 1]d DE 4\n" +"DB/ImageType 3 d/DataDict id d/MaskDict md d/InterleaveType 3 d end image}{\n" +"pop 8 4 1 roll 8 eq{image}{TQCI}ie}ie}ie grestore}d/BF{gsave BSt 1 eq{BCol SC\n" +"WFi{fill}{eofill}ie}if BSt 2 ge BSt 8 le and{BDArr BSt 2 sub get/sc ED BCol{\n" +"1. exch sub sc mul 1. exch sub}forall 3 array astore SC WFi{fill}{eofill}ie}\n" +"if BSt 9 ge BSt 14 le and{WFi{clip}{eoclip}ie defM SM pathbbox 3 i 3 i TR 4\n" +"2 roll 3 2 roll exch sub/h ED sub/w ED OMo{NP 0 0 MT 0 h RL w 0 RL 0 h neg\n" +"RL CP BkCol SC fill}if BCol SC 0.3 SW NP BSt 9 eq BSt 11 eq or{0 4 h{dup 0\n" +"exch MT w exch LT}for}if BSt 10 eq BSt 11 eq or{0 4 w{dup 0 MT h LT}for}if\n" +"BSt 12 eq BSt 14 eq or{w h gt{0 6 w h add{dup 0 MT h sub h LT}for}{0 6 w h\n" +"add{dup 0 exch MT w sub w exch LT}for}ie}if BSt 13 eq BSt 14 eq or{w h gt{0\n" +"6 w h add{dup h MT h sub 0 LT}for}{0 6 w h add{dup w exch MT w sub 0 exch LT\n" +"}for}ie}if S}if BSt 24 eq{}if grestore}D/mat matrix d/ang1 D0/ang2 D0/w D0/h\n" +"D0/x D0/y D0/ARC{/ang2 ED/ang1 ED/h ED/w ED/y ED/x ED mat CM pop x w 2 div\n" +"add y h 2 div add TR 1 h w div neg scale ang2 0 ge{0 0 w 2 div ang1 ang1\n" +"ang2 add arc}{0 0 w 2 div ang1 ang1 ang2 add arcn}ie mat SM}D/C D0/P{NP MT\n" +"0.5 0.5 rmoveto 0 -1 RL -1 0 RL 0 1 RL CP fill}D/M{/Cy ED/Cx ED}D/L{NP Cx Cy\n" +"MT/Cy ED/Cx ED Cx Cy LT QS}D/DL{NP MT LT QS}D/HL{1 i DL}D/VL{2 i exch DL}D/R\n" +"{/h ED/w ED/y ED/x ED NP x y MT 0 h RL w 0 RL 0 h neg RL CP BF QS}D/ACR{/h\n" +"ED/w ED/y ED/x ED x y MT 0 h RL w 0 RL 0 h neg RL CP}D/xr D0/yr D0/rx D0/ry\n" +"D0/rx2 D0/ry2 D0/RR{/yr ED/xr ED/h ED/w ED/y ED/x ED xr 0 le yr 0 le or{x y\n" +"w h R}{xr 100 ge yr 100 ge or{x y w h E}{/rx xr w mul 200 div d/ry yr h mul\n" +"200 div d/rx2 rx 2 mul d/ry2 ry 2 mul d NP x rx add y MT x y rx2 ry2 180 -90\n" +"x y h add ry2 sub rx2 ry2 270 -90 x w add rx2 sub y h add ry2 sub rx2 ry2 0\n" +"-90 x w add rx2 sub y rx2 ry2 90 -90 ARC ARC ARC ARC CP BF QS}ie}ie}D/E{/h\n" +"ED/w ED/y ED/x ED mat CM pop x w 2 div add y h 2 div add TR 1 h w div scale\n" +"NP 0 0 w 2 div 0 360 arc mat SM BF QS}D/A{16 div exch 16 div exch NP ARC QS}\n" +"D/PIE{/ang2 ED/ang1 ED/h ED/w ED/y ED/x ED NP x w 2 div add y h 2 div add MT\n" +"x y w h ang1 16 div ang2 16 div ARC CP BF QS}D/CH{16 div exch 16 div exch NP\n" +"ARC CP BF QS}D/BZ{curveto QS}D/CRGB{255 div 3 1 roll 255 div 3 1 roll 255\n" +"div 3 1 roll}D/BC{CRGB BkCol sp}D/BR{CRGB BCol sp/BSt ED}D/WB{1 W BR}D/NB{0\n" +"B BR}D/PE{setlinejoin setlinecap CRGB PCol sp/LWi ED/PSt ED LWi 0 eq{0.25\n" +"/LWi ED}if PCol SC}D/P1{1 0 5 2 roll 0 0 PE}D/ST{defM SM concat}D/MF{true\n" +"exch true exch{exch pop exch pop dup 0 get dup findfont dup/FontName get 3\n" +"-1 roll eq{exit}if}forall exch dup 1 get/fxscale ED 2 get/fslant ED exch\n" +"/fencoding ED[fxscale 0 fslant 1 0 0]makefont fencoding false eq{}{dup\n" +"maxlength dict begin{1 i/FID ne{def}{pop pop}ifelse}forall/Encoding\n" +"fencoding d currentdict end}ie definefont pop}D/MFEmb{findfont dup length\n" +"dict begin{1 i/FID ne{d}{pop pop}ifelse}forall/Encoding ED currentdict end\n" +"definefont pop}D/DF{findfont/fs 3 -1 roll d[fs 0 0 fs -1 mul 0 0]makefont d}\n" +"D/ty 0 d/Y{/ty ED}D/Tl{gsave SW NP 1 i exch MT 1 i 0 RL S grestore}D/XYT{ty\n" +"MT/xyshow where{pop pop xyshow}{exch pop 1 i dup length 2 div exch\n" +"stringwidth pop 3 -1 roll exch sub exch div exch 0 exch ashow}ie}D/AT{ty MT\n" +"1 i dup length 2 div exch stringwidth pop 3 -1 roll exch sub exch div exch 0\n" +"exch ashow}D/QI{/C save d pageinit/Cx 0 d/Cy 0 d/OMo false d}D/QP{C restore\n" +"showpage}D/SPD{/setpagedevice where{1 DB 3 1 roll d end setpagedevice}{pop\n" +"pop}ie}D/SV{BSt LWi PSt Cx Cy WFi OMo BCol PCol BkCol/nS nS 1 add d gsave}D\n" +"/RS{nS 0 gt{grestore/BkCol ED/PCol ED/BCol ED/OMo ED/WFi ED/Cy ED/Cx ED/PSt\n" +"ED/LWi ED/BSt ED/nS nS 1 sub d}if}D/CLSTART{/clipTmp matrix CM d defM SM NP}\n" +"D/CLEND{clip NP clipTmp SM}D/CLO{grestore gsave defM SM}D\n"; + +// the next table is derived from a list provided by Adobe on its web +// server: http://partners.adobe.com/asn/developer/typeforum/glyphlist.txt + +// the start of the header comment: +// +// Name: Adobe Glyph List +// Table version: 1.2 +// Date: 22 Oct 1998 +// +// Description: +// +// The Adobe Glyph List (AGL) list relates Unicode values (UVs) to glyph +// names, and should be used only as described in the document "Unicode and +// Glyph Names," at +// http://partners.adobe.com:80/asn/developer/type/unicodegn.html +// +// IMPORTANT NOTE: +// the list contains glyphs in the private use area of unicode. These should get removed when regenerating the glyphlist. +// also 0 shout be mapped to .notdef +static const struct { + TQ_UINT16 u; + const char * g; +} unicodetoglyph[] = { + // grep '^[0-9A-F][0-9A-F][0-9A-F][0-9A-F];' < /tmp/glyphlist.txt | sed -e 's/;/, "/' -e 's-;-" }, // -' -e 's/^/ { 0x/' | sort + { 0x0000, ".notdef" }, + { 0x0020, "space" }, // SPACE + { 0x0021, "exclam" }, // EXCLAMATION MARK + { 0x0022, "quotedbl" }, // QUOTATION MARK + { 0x0023, "numbersign" }, // NUMBER SIGN + { 0x0024, "dollar" }, // DOLLAR SIGN + { 0x0025, "percent" }, // PERCENT SIGN + { 0x0026, "ampersand" }, // AMPERSAND + { 0x0027, "quotesingle" }, // APOSTROPHE + { 0x0028, "parenleft" }, // LEFT PARENTHESIS + { 0x0029, "parenright" }, // RIGHT PARENTHESIS + { 0x002A, "asterisk" }, // ASTERISK + { 0x002B, "plus" }, // PLUS SIGN + { 0x002C, "comma" }, // COMMA + { 0x002D, "hyphen" }, // HYPHEN-MINUS + { 0x002E, "period" }, // FULL STOP + { 0x002F, "slash" }, // SOLIDUS + { 0x0030, "zero" }, // DIGIT ZERO + { 0x0031, "one" }, // DIGIT ONE + { 0x0032, "two" }, // DIGIT TWO + { 0x0033, "three" }, // DIGIT THREE + { 0x0034, "four" }, // DIGIT FOUR + { 0x0035, "five" }, // DIGIT FIVE + { 0x0036, "six" }, // DIGIT SIX + { 0x0037, "seven" }, // DIGIT SEVEN + { 0x0038, "eight" }, // DIGIT EIGHT + { 0x0039, "nine" }, // DIGIT NINE + { 0x003A, "colon" }, // COLON + { 0x003B, "semicolon" }, // SEMICOLON + { 0x003C, "less" }, // LESS-THAN SIGN + { 0x003D, "equal" }, // EQUALS SIGN + { 0x003E, "greater" }, // GREATER-THAN SIGN + { 0x003F, "question" }, // QUESTION MARK + { 0x0040, "at" }, // COMMERCIAL AT + { 0x0041, "A" }, // LATIN CAPITAL LETTER A + { 0x0042, "B" }, // LATIN CAPITAL LETTER B + { 0x0043, "C" }, // LATIN CAPITAL LETTER C + { 0x0044, "D" }, // LATIN CAPITAL LETTER D + { 0x0045, "E" }, // LATIN CAPITAL LETTER E + { 0x0046, "F" }, // LATIN CAPITAL LETTER F + { 0x0047, "G" }, // LATIN CAPITAL LETTER G + { 0x0048, "H" }, // LATIN CAPITAL LETTER H + { 0x0049, "I" }, // LATIN CAPITAL LETTER I + { 0x004A, "J" }, // LATIN CAPITAL LETTER J + { 0x004B, "K" }, // LATIN CAPITAL LETTER K + { 0x004C, "L" }, // LATIN CAPITAL LETTER L + { 0x004D, "M" }, // LATIN CAPITAL LETTER M + { 0x004E, "N" }, // LATIN CAPITAL LETTER N + { 0x004F, "O" }, // LATIN CAPITAL LETTER O + { 0x0050, "P" }, // LATIN CAPITAL LETTER P + { 0x0051, "Q" }, // LATIN CAPITAL LETTER Q + { 0x0052, "R" }, // LATIN CAPITAL LETTER R + { 0x0053, "S" }, // LATIN CAPITAL LETTER S + { 0x0054, "T" }, // LATIN CAPITAL LETTER T + { 0x0055, "U" }, // LATIN CAPITAL LETTER U + { 0x0056, "V" }, // LATIN CAPITAL LETTER V + { 0x0057, "W" }, // LATIN CAPITAL LETTER W + { 0x0058, "X" }, // LATIN CAPITAL LETTER X + { 0x0059, "Y" }, // LATIN CAPITAL LETTER Y + { 0x005A, "Z" }, // LATIN CAPITAL LETTER Z + { 0x005B, "bracketleft" }, // LEFT SQUARE BRACKET + { 0x005C, "backslash" }, // REVERSE SOLIDUS + { 0x005D, "bracketright" }, // RIGHT SQUARE BRACKET + { 0x005E, "asciicircum" }, // CIRCUMFLEX ACCENT + { 0x005F, "underscore" }, // LOW LINE + { 0x0060, "grave" }, // GRAVE ACCENT + { 0x0061, "a" }, // LATIN SMALL LETTER A + { 0x0062, "b" }, // LATIN SMALL LETTER B + { 0x0063, "c" }, // LATIN SMALL LETTER C + { 0x0064, "d" }, // LATIN SMALL LETTER D + { 0x0065, "e" }, // LATIN SMALL LETTER E + { 0x0066, "f" }, // LATIN SMALL LETTER F + { 0x0067, "g" }, // LATIN SMALL LETTER G + { 0x0068, "h" }, // LATIN SMALL LETTER H + { 0x0069, "i" }, // LATIN SMALL LETTER I + { 0x006A, "j" }, // LATIN SMALL LETTER J + { 0x006B, "k" }, // LATIN SMALL LETTER K + { 0x006C, "l" }, // LATIN SMALL LETTER L + { 0x006D, "m" }, // LATIN SMALL LETTER M + { 0x006E, "n" }, // LATIN SMALL LETTER N + { 0x006F, "o" }, // LATIN SMALL LETTER O + { 0x0070, "p" }, // LATIN SMALL LETTER P + { 0x0071, "q" }, // LATIN SMALL LETTER Q + { 0x0072, "r" }, // LATIN SMALL LETTER R + { 0x0073, "s" }, // LATIN SMALL LETTER S + { 0x0074, "t" }, // LATIN SMALL LETTER T + { 0x0075, "u" }, // LATIN SMALL LETTER U + { 0x0076, "v" }, // LATIN SMALL LETTER V + { 0x0077, "w" }, // LATIN SMALL LETTER W + { 0x0078, "x" }, // LATIN SMALL LETTER X + { 0x0079, "y" }, // LATIN SMALL LETTER Y + { 0x007A, "z" }, // LATIN SMALL LETTER Z + { 0x007B, "braceleft" }, // LEFT CURLY BRACKET + { 0x007C, "bar" }, // VERTICAL LINE + { 0x007D, "braceright" }, // RIGHT CURLY BRACKET + { 0x007E, "asciitilde" }, // TILDE + { 0x00A0, "space" }, // NO-BREAK SPACE;Duplicate + { 0x00A1, "exclamdown" }, // INVERTED EXCLAMATION MARK + { 0x00A2, "cent" }, // CENT SIGN + { 0x00A3, "sterling" }, // POUND SIGN + { 0x00A4, "currency" }, // CURRENCY SIGN + { 0x00A5, "yen" }, // YEN SIGN + { 0x00A6, "brokenbar" }, // BROKEN BAR + { 0x00A7, "section" }, // SECTION SIGN + { 0x00A8, "dieresis" }, // DIAERESIS + { 0x00A9, "copyright" }, // COPYRIGHT SIGN + { 0x00AA, "ordfeminine" }, // FEMININE ORDINAL INDICATOR + { 0x00AB, "guillemotleft" }, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + { 0x00AC, "logicalnot" }, // NOT SIGN + { 0x00AD, "hyphen" }, // SOFT HYPHEN;Duplicate + { 0x00AE, "registered" }, // REGISTERED SIGN + { 0x00AF, "macron" }, // MACRON + { 0x00B0, "degree" }, // DEGREE SIGN + { 0x00B1, "plusminus" }, // PLUS-MINUS SIGN + { 0x00B2, "twosuperior" }, // SUPERSCRIPT TWO + { 0x00B3, "threesuperior" }, // SUPERSCRIPT THREE + { 0x00B4, "acute" }, // ACUTE ACCENT + { 0x00B5, "mu" }, // MICRO SIGN + { 0x00B6, "paragraph" }, // PILCROW SIGN + { 0x00B7, "periodcentered" }, // MIDDLE DOT + { 0x00B8, "cedilla" }, // CEDILLA + { 0x00B9, "onesuperior" }, // SUPERSCRIPT ONE + { 0x00BA, "ordmasculine" }, // MASCULINE ORDINAL INDICATOR + { 0x00BB, "guillemotright" }, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + { 0x00BC, "onequarter" }, // VULGAR FRACTION ONE QUARTER + { 0x00BD, "onehalf" }, // VULGAR FRACTION ONE HALF + { 0x00BE, "threequarters" }, // VULGAR FRACTION THREE QUARTERS + { 0x00BF, "questiondown" }, // INVERTED QUESTION MARK + { 0x00C0, "Agrave" }, // LATIN CAPITAL LETTER A WITH GRAVE + { 0x00C1, "Aacute" }, // LATIN CAPITAL LETTER A WITH ACUTE + { 0x00C2, "Acircumflex" }, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX + { 0x00C3, "Atilde" }, // LATIN CAPITAL LETTER A WITH TILDE + { 0x00C4, "Adieresis" }, // LATIN CAPITAL LETTER A WITH DIAERESIS + { 0x00C5, "Aring" }, // LATIN CAPITAL LETTER A WITH RING ABOVE + { 0x00C6, "AE" }, // LATIN CAPITAL LETTER AE + { 0x00C7, "Ccedilla" }, // LATIN CAPITAL LETTER C WITH CEDILLA + { 0x00C8, "Egrave" }, // LATIN CAPITAL LETTER E WITH GRAVE + { 0x00C9, "Eacute" }, // LATIN CAPITAL LETTER E WITH ACUTE + { 0x00CA, "Ecircumflex" }, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX + { 0x00CB, "Edieresis" }, // LATIN CAPITAL LETTER E WITH DIAERESIS + { 0x00CC, "Igrave" }, // LATIN CAPITAL LETTER I WITH GRAVE + { 0x00CD, "Iacute" }, // LATIN CAPITAL LETTER I WITH ACUTE + { 0x00CE, "Icircumflex" }, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX + { 0x00CF, "Idieresis" }, // LATIN CAPITAL LETTER I WITH DIAERESIS + { 0x00D0, "Eth" }, // LATIN CAPITAL LETTER ETH + { 0x00D1, "Ntilde" }, // LATIN CAPITAL LETTER N WITH TILDE + { 0x00D2, "Ograve" }, // LATIN CAPITAL LETTER O WITH GRAVE + { 0x00D3, "Oacute" }, // LATIN CAPITAL LETTER O WITH ACUTE + { 0x00D4, "Ocircumflex" }, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX + { 0x00D5, "Otilde" }, // LATIN CAPITAL LETTER O WITH TILDE + { 0x00D6, "Odieresis" }, // LATIN CAPITAL LETTER O WITH DIAERESIS + { 0x00D7, "multiply" }, // MULTIPLICATION SIGN + { 0x00D8, "Oslash" }, // LATIN CAPITAL LETTER O WITH STROKE + { 0x00D9, "Ugrave" }, // LATIN CAPITAL LETTER U WITH GRAVE + { 0x00DA, "Uacute" }, // LATIN CAPITAL LETTER U WITH ACUTE + { 0x00DB, "Ucircumflex" }, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX + { 0x00DC, "Udieresis" }, // LATIN CAPITAL LETTER U WITH DIAERESIS + { 0x00DD, "Yacute" }, // LATIN CAPITAL LETTER Y WITH ACUTE + { 0x00DE, "Thorn" }, // LATIN CAPITAL LETTER THORN + { 0x00DF, "germandbls" }, // LATIN SMALL LETTER SHARP S + { 0x00E0, "agrave" }, // LATIN SMALL LETTER A WITH GRAVE + { 0x00E1, "aacute" }, // LATIN SMALL LETTER A WITH ACUTE + { 0x00E2, "acircumflex" }, // LATIN SMALL LETTER A WITH CIRCUMFLEX + { 0x00E3, "atilde" }, // LATIN SMALL LETTER A WITH TILDE + { 0x00E4, "adieresis" }, // LATIN SMALL LETTER A WITH DIAERESIS + { 0x00E5, "aring" }, // LATIN SMALL LETTER A WITH RING ABOVE + { 0x00E6, "ae" }, // LATIN SMALL LETTER AE + { 0x00E7, "ccedilla" }, // LATIN SMALL LETTER C WITH CEDILLA + { 0x00E8, "egrave" }, // LATIN SMALL LETTER E WITH GRAVE + { 0x00E9, "eacute" }, // LATIN SMALL LETTER E WITH ACUTE + { 0x00EA, "ecircumflex" }, // LATIN SMALL LETTER E WITH CIRCUMFLEX + { 0x00EB, "edieresis" }, // LATIN SMALL LETTER E WITH DIAERESIS + { 0x00EC, "igrave" }, // LATIN SMALL LETTER I WITH GRAVE + { 0x00ED, "iacute" }, // LATIN SMALL LETTER I WITH ACUTE + { 0x00EE, "icircumflex" }, // LATIN SMALL LETTER I WITH CIRCUMFLEX + { 0x00EF, "idieresis" }, // LATIN SMALL LETTER I WITH DIAERESIS + { 0x00F0, "eth" }, // LATIN SMALL LETTER ETH + { 0x00F1, "ntilde" }, // LATIN SMALL LETTER N WITH TILDE + { 0x00F2, "ograve" }, // LATIN SMALL LETTER O WITH GRAVE + { 0x00F3, "oacute" }, // LATIN SMALL LETTER O WITH ACUTE + { 0x00F4, "ocircumflex" }, // LATIN SMALL LETTER O WITH CIRCUMFLEX + { 0x00F5, "otilde" }, // LATIN SMALL LETTER O WITH TILDE + { 0x00F6, "odieresis" }, // LATIN SMALL LETTER O WITH DIAERESIS + { 0x00F7, "divide" }, // DIVISION SIGN + { 0x00F8, "oslash" }, // LATIN SMALL LETTER O WITH STROKE + { 0x00F9, "ugrave" }, // LATIN SMALL LETTER U WITH GRAVE + { 0x00FA, "uacute" }, // LATIN SMALL LETTER U WITH ACUTE + { 0x00FB, "ucircumflex" }, // LATIN SMALL LETTER U WITH CIRCUMFLEX + { 0x00FC, "udieresis" }, // LATIN SMALL LETTER U WITH DIAERESIS + { 0x00FD, "yacute" }, // LATIN SMALL LETTER Y WITH ACUTE + { 0x00FE, "thorn" }, // LATIN SMALL LETTER THORN + { 0x00FF, "ydieresis" }, // LATIN SMALL LETTER Y WITH DIAERESIS + { 0x0100, "Amacron" }, // LATIN CAPITAL LETTER A WITH MACRON + { 0x0101, "amacron" }, // LATIN SMALL LETTER A WITH MACRON + { 0x0102, "Abreve" }, // LATIN CAPITAL LETTER A WITH BREVE + { 0x0103, "abreve" }, // LATIN SMALL LETTER A WITH BREVE + { 0x0104, "Aogonek" }, // LATIN CAPITAL LETTER A WITH OGONEK + { 0x0105, "aogonek" }, // LATIN SMALL LETTER A WITH OGONEK + { 0x0106, "Cacute" }, // LATIN CAPITAL LETTER C WITH ACUTE + { 0x0107, "cacute" }, // LATIN SMALL LETTER C WITH ACUTE + { 0x0108, "Ccircumflex" }, // LATIN CAPITAL LETTER C WITH CIRCUMFLEX + { 0x0109, "ccircumflex" }, // LATIN SMALL LETTER C WITH CIRCUMFLEX + { 0x010A, "Cdotaccent" }, // LATIN CAPITAL LETTER C WITH DOT ABOVE + { 0x010B, "cdotaccent" }, // LATIN SMALL LETTER C WITH DOT ABOVE + { 0x010C, "Ccaron" }, // LATIN CAPITAL LETTER C WITH CARON + { 0x010D, "ccaron" }, // LATIN SMALL LETTER C WITH CARON + { 0x010E, "Dcaron" }, // LATIN CAPITAL LETTER D WITH CARON + { 0x010F, "dcaron" }, // LATIN SMALL LETTER D WITH CARON + { 0x0110, "Dcroat" }, // LATIN CAPITAL LETTER D WITH STROKE + { 0x0111, "dcroat" }, // LATIN SMALL LETTER D WITH STROKE + { 0x0112, "Emacron" }, // LATIN CAPITAL LETTER E WITH MACRON + { 0x0113, "emacron" }, // LATIN SMALL LETTER E WITH MACRON + { 0x0114, "Ebreve" }, // LATIN CAPITAL LETTER E WITH BREVE + { 0x0115, "ebreve" }, // LATIN SMALL LETTER E WITH BREVE + { 0x0116, "Edotaccent" }, // LATIN CAPITAL LETTER E WITH DOT ABOVE + { 0x0117, "edotaccent" }, // LATIN SMALL LETTER E WITH DOT ABOVE + { 0x0118, "Eogonek" }, // LATIN CAPITAL LETTER E WITH OGONEK + { 0x0119, "eogonek" }, // LATIN SMALL LETTER E WITH OGONEK + { 0x011A, "Ecaron" }, // LATIN CAPITAL LETTER E WITH CARON + { 0x011B, "ecaron" }, // LATIN SMALL LETTER E WITH CARON + { 0x011C, "Gcircumflex" }, // LATIN CAPITAL LETTER G WITH CIRCUMFLEX + { 0x011D, "gcircumflex" }, // LATIN SMALL LETTER G WITH CIRCUMFLEX + { 0x011E, "Gbreve" }, // LATIN CAPITAL LETTER G WITH BREVE + { 0x011F, "gbreve" }, // LATIN SMALL LETTER G WITH BREVE + { 0x0120, "Gdotaccent" }, // LATIN CAPITAL LETTER G WITH DOT ABOVE + { 0x0121, "gdotaccent" }, // LATIN SMALL LETTER G WITH DOT ABOVE + { 0x0122, "Gcommaaccent" }, // LATIN CAPITAL LETTER G WITH CEDILLA + { 0x0123, "gcommaaccent" }, // LATIN SMALL LETTER G WITH CEDILLA + { 0x0124, "Hcircumflex" }, // LATIN CAPITAL LETTER H WITH CIRCUMFLEX + { 0x0125, "hcircumflex" }, // LATIN SMALL LETTER H WITH CIRCUMFLEX + { 0x0126, "Hbar" }, // LATIN CAPITAL LETTER H WITH STROKE + { 0x0127, "hbar" }, // LATIN SMALL LETTER H WITH STROKE + { 0x0128, "Itilde" }, // LATIN CAPITAL LETTER I WITH TILDE + { 0x0129, "itilde" }, // LATIN SMALL LETTER I WITH TILDE + { 0x012A, "Imacron" }, // LATIN CAPITAL LETTER I WITH MACRON + { 0x012B, "imacron" }, // LATIN SMALL LETTER I WITH MACRON + { 0x012C, "Ibreve" }, // LATIN CAPITAL LETTER I WITH BREVE + { 0x012D, "ibreve" }, // LATIN SMALL LETTER I WITH BREVE + { 0x012E, "Iogonek" }, // LATIN CAPITAL LETTER I WITH OGONEK + { 0x012F, "iogonek" }, // LATIN SMALL LETTER I WITH OGONEK + { 0x0130, "Idotaccent" }, // LATIN CAPITAL LETTER I WITH DOT ABOVE + { 0x0131, "dotlessi" }, // LATIN SMALL LETTER DOTLESS I + { 0x0132, "IJ" }, // LATIN CAPITAL LIGATURE IJ + { 0x0133, "ij" }, // LATIN SMALL LIGATURE IJ + { 0x0134, "Jcircumflex" }, // LATIN CAPITAL LETTER J WITH CIRCUMFLEX + { 0x0135, "jcircumflex" }, // LATIN SMALL LETTER J WITH CIRCUMFLEX + { 0x0136, "Kcommaaccent" }, // LATIN CAPITAL LETTER K WITH CEDILLA + { 0x0137, "kcommaaccent" }, // LATIN SMALL LETTER K WITH CEDILLA + { 0x0138, "kgreenlandic" }, // LATIN SMALL LETTER KRA + { 0x0139, "Lacute" }, // LATIN CAPITAL LETTER L WITH ACUTE + { 0x013A, "lacute" }, // LATIN SMALL LETTER L WITH ACUTE + { 0x013B, "Lcommaaccent" }, // LATIN CAPITAL LETTER L WITH CEDILLA + { 0x013C, "lcommaaccent" }, // LATIN SMALL LETTER L WITH CEDILLA + { 0x013D, "Lcaron" }, // LATIN CAPITAL LETTER L WITH CARON + { 0x013E, "lcaron" }, // LATIN SMALL LETTER L WITH CARON + { 0x013F, "Ldot" }, // LATIN CAPITAL LETTER L WITH MIDDLE DOT + { 0x0140, "ldot" }, // LATIN SMALL LETTER L WITH MIDDLE DOT + { 0x0141, "Lslash" }, // LATIN CAPITAL LETTER L WITH STROKE + { 0x0142, "lslash" }, // LATIN SMALL LETTER L WITH STROKE + { 0x0143, "Nacute" }, // LATIN CAPITAL LETTER N WITH ACUTE + { 0x0144, "nacute" }, // LATIN SMALL LETTER N WITH ACUTE + { 0x0145, "Ncommaaccent" }, // LATIN CAPITAL LETTER N WITH CEDILLA + { 0x0146, "ncommaaccent" }, // LATIN SMALL LETTER N WITH CEDILLA + { 0x0147, "Ncaron" }, // LATIN CAPITAL LETTER N WITH CARON + { 0x0148, "ncaron" }, // LATIN SMALL LETTER N WITH CARON + { 0x0149, "napostrophe" }, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + { 0x014A, "Eng" }, // LATIN CAPITAL LETTER ENG + { 0x014B, "eng" }, // LATIN SMALL LETTER ENG + { 0x014C, "Omacron" }, // LATIN CAPITAL LETTER O WITH MACRON + { 0x014D, "omacron" }, // LATIN SMALL LETTER O WITH MACRON + { 0x014E, "Obreve" }, // LATIN CAPITAL LETTER O WITH BREVE + { 0x014F, "obreve" }, // LATIN SMALL LETTER O WITH BREVE + { 0x0150, "Ohungarumlaut" }, // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + { 0x0151, "ohungarumlaut" }, // LATIN SMALL LETTER O WITH DOUBLE ACUTE + { 0x0152, "OE" }, // LATIN CAPITAL LIGATURE OE + { 0x0153, "oe" }, // LATIN SMALL LIGATURE OE + { 0x0154, "Racute" }, // LATIN CAPITAL LETTER R WITH ACUTE + { 0x0155, "racute" }, // LATIN SMALL LETTER R WITH ACUTE + { 0x0156, "Rcommaaccent" }, // LATIN CAPITAL LETTER R WITH CEDILLA + { 0x0157, "rcommaaccent" }, // LATIN SMALL LETTER R WITH CEDILLA + { 0x0158, "Rcaron" }, // LATIN CAPITAL LETTER R WITH CARON + { 0x0159, "rcaron" }, // LATIN SMALL LETTER R WITH CARON + { 0x015A, "Sacute" }, // LATIN CAPITAL LETTER S WITH ACUTE + { 0x015B, "sacute" }, // LATIN SMALL LETTER S WITH ACUTE + { 0x015C, "Scircumflex" }, // LATIN CAPITAL LETTER S WITH CIRCUMFLEX + { 0x015D, "scircumflex" }, // LATIN SMALL LETTER S WITH CIRCUMFLEX + { 0x015E, "Scedilla" }, // LATIN CAPITAL LETTER S WITH CEDILLA + { 0x015F, "scedilla" }, // LATIN SMALL LETTER S WITH CEDILLA + { 0x0160, "Scaron" }, // LATIN CAPITAL LETTER S WITH CARON + { 0x0161, "scaron" }, // LATIN SMALL LETTER S WITH CARON + { 0x0162, "Tcommaaccent" }, // LATIN CAPITAL LETTER T WITH CEDILLA + { 0x0163, "tcommaaccent" }, // LATIN SMALL LETTER T WITH CEDILLA + { 0x0164, "Tcaron" }, // LATIN CAPITAL LETTER T WITH CARON + { 0x0165, "tcaron" }, // LATIN SMALL LETTER T WITH CARON + { 0x0166, "Tbar" }, // LATIN CAPITAL LETTER T WITH STROKE + { 0x0167, "tbar" }, // LATIN SMALL LETTER T WITH STROKE + { 0x0168, "Utilde" }, // LATIN CAPITAL LETTER U WITH TILDE + { 0x0169, "utilde" }, // LATIN SMALL LETTER U WITH TILDE + { 0x016A, "Umacron" }, // LATIN CAPITAL LETTER U WITH MACRON + { 0x016B, "umacron" }, // LATIN SMALL LETTER U WITH MACRON + { 0x016C, "Ubreve" }, // LATIN CAPITAL LETTER U WITH BREVE + { 0x016D, "ubreve" }, // LATIN SMALL LETTER U WITH BREVE + { 0x016E, "Uring" }, // LATIN CAPITAL LETTER U WITH RING ABOVE + { 0x016F, "uring" }, // LATIN SMALL LETTER U WITH RING ABOVE + { 0x0170, "Uhungarumlaut" }, // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + { 0x0171, "uhungarumlaut" }, // LATIN SMALL LETTER U WITH DOUBLE ACUTE + { 0x0172, "Uogonek" }, // LATIN CAPITAL LETTER U WITH OGONEK + { 0x0173, "uogonek" }, // LATIN SMALL LETTER U WITH OGONEK + { 0x0174, "Wcircumflex" }, // LATIN CAPITAL LETTER W WITH CIRCUMFLEX + { 0x0175, "wcircumflex" }, // LATIN SMALL LETTER W WITH CIRCUMFLEX + { 0x0176, "Ycircumflex" }, // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + { 0x0177, "ycircumflex" }, // LATIN SMALL LETTER Y WITH CIRCUMFLEX + { 0x0178, "Ydieresis" }, // LATIN CAPITAL LETTER Y WITH DIAERESIS + { 0x0179, "Zacute" }, // LATIN CAPITAL LETTER Z WITH ACUTE + { 0x017A, "zacute" }, // LATIN SMALL LETTER Z WITH ACUTE + { 0x017B, "Zdotaccent" }, // LATIN CAPITAL LETTER Z WITH DOT ABOVE + { 0x017C, "zdotaccent" }, // LATIN SMALL LETTER Z WITH DOT ABOVE + { 0x017D, "Zcaron" }, // LATIN CAPITAL LETTER Z WITH CARON + { 0x017E, "zcaron" }, // LATIN SMALL LETTER Z WITH CARON + { 0x017F, "longs" }, // LATIN SMALL LETTER LONG S + { 0x0192, "florin" }, // LATIN SMALL LETTER F WITH HOOK + { 0x01A0, "Ohorn" }, // LATIN CAPITAL LETTER O WITH HORN + { 0x01A1, "ohorn" }, // LATIN SMALL LETTER O WITH HORN + { 0x01AF, "Uhorn" }, // LATIN CAPITAL LETTER U WITH HORN + { 0x01B0, "uhorn" }, // LATIN SMALL LETTER U WITH HORN + { 0x01E6, "Gcaron" }, // LATIN CAPITAL LETTER G WITH CARON + { 0x01E7, "gcaron" }, // LATIN SMALL LETTER G WITH CARON + { 0x01FA, "Aringacute" }, // LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE + { 0x01FB, "aringacute" }, // LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE + { 0x01FC, "AEacute" }, // LATIN CAPITAL LETTER AE WITH ACUTE + { 0x01FD, "aeacute" }, // LATIN SMALL LETTER AE WITH ACUTE + { 0x01FE, "Oslashacute" }, // LATIN CAPITAL LETTER O WITH STROKE AND ACUTE + { 0x01FF, "oslashacute" }, // LATIN SMALL LETTER O WITH STROKE AND ACUTE + { 0x0218, "Scommaaccent" }, // LATIN CAPITAL LETTER S WITH COMMA BELOW + { 0x0219, "scommaaccent" }, // LATIN SMALL LETTER S WITH COMMA BELOW + { 0x021A, "Tcommaaccent" }, // LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate + { 0x021B, "tcommaaccent" }, // LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate + { 0x02BC, "afii57929" }, // MODIFIER LETTER APOSTROPHE + { 0x02BD, "afii64937" }, // MODIFIER LETTER REVERSED COMMA + { 0x02C6, "circumflex" }, // MODIFIER LETTER CIRCUMFLEX ACCENT + { 0x02C7, "caron" }, // CARON + { 0x02C9, "macron" }, // MODIFIER LETTER MACRON;Duplicate + { 0x02D8, "breve" }, // BREVE + { 0x02D9, "dotaccent" }, // DOT ABOVE + { 0x02DA, "ring" }, // RING ABOVE + { 0x02DB, "ogonek" }, // OGONEK + { 0x02DC, "tilde" }, // SMALL TILDE + { 0x02DD, "hungarumlaut" }, // DOUBLE ACUTE ACCENT + { 0x0300, "gravecomb" }, // COMBINING GRAVE ACCENT + { 0x0301, "acutecomb" }, // COMBINING ACUTE ACCENT + { 0x0303, "tildecomb" }, // COMBINING TILDE + { 0x0309, "hookabovecomb" }, // COMBINING HOOK ABOVE + { 0x0323, "dotbelowcomb" }, // COMBINING DOT BELOW + { 0x0384, "tonos" }, // GREEK TONOS + { 0x0385, "dieresistonos" }, // GREEK DIALYTIKA TONOS + { 0x0386, "Alphatonos" }, // GREEK CAPITAL LETTER ALPHA WITH TONOS + { 0x0387, "anoteleia" }, // GREEK ANO TELEIA + { 0x0388, "Epsilontonos" }, // GREEK CAPITAL LETTER EPSILON WITH TONOS + { 0x0389, "Etatonos" }, // GREEK CAPITAL LETTER ETA WITH TONOS + { 0x038A, "Iotatonos" }, // GREEK CAPITAL LETTER IOTA WITH TONOS + { 0x038C, "Omicrontonos" }, // GREEK CAPITAL LETTER OMICRON WITH TONOS + { 0x038E, "Upsilontonos" }, // GREEK CAPITAL LETTER UPSILON WITH TONOS + { 0x038F, "Omegatonos" }, // GREEK CAPITAL LETTER OMEGA WITH TONOS + { 0x0390, "iotadieresistonos" }, // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + { 0x0391, "Alpha" }, // GREEK CAPITAL LETTER ALPHA + { 0x0392, "Beta" }, // GREEK CAPITAL LETTER BETA + { 0x0393, "Gamma" }, // GREEK CAPITAL LETTER GAMMA + { 0x0394, "Delta" }, // GREEK CAPITAL LETTER DELTA;Duplicate + { 0x0395, "Epsilon" }, // GREEK CAPITAL LETTER EPSILON + { 0x0396, "Zeta" }, // GREEK CAPITAL LETTER ZETA + { 0x0397, "Eta" }, // GREEK CAPITAL LETTER ETA + { 0x0398, "Theta" }, // GREEK CAPITAL LETTER THETA + { 0x0399, "Iota" }, // GREEK CAPITAL LETTER IOTA + { 0x039A, "Kappa" }, // GREEK CAPITAL LETTER KAPPA + { 0x039B, "Lambda" }, // GREEK CAPITAL LETTER LAMDA + { 0x039C, "Mu" }, // GREEK CAPITAL LETTER MU + { 0x039D, "Nu" }, // GREEK CAPITAL LETTER NU + { 0x039E, "Xi" }, // GREEK CAPITAL LETTER XI + { 0x039F, "Omicron" }, // GREEK CAPITAL LETTER OMICRON + { 0x03A0, "Pi" }, // GREEK CAPITAL LETTER PI + { 0x03A1, "Rho" }, // GREEK CAPITAL LETTER RHO + { 0x03A3, "Sigma" }, // GREEK CAPITAL LETTER SIGMA + { 0x03A4, "Tau" }, // GREEK CAPITAL LETTER TAU + { 0x03A5, "Upsilon" }, // GREEK CAPITAL LETTER UPSILON + { 0x03A6, "Phi" }, // GREEK CAPITAL LETTER PHI + { 0x03A7, "Chi" }, // GREEK CAPITAL LETTER CHI + { 0x03A8, "Psi" }, // GREEK CAPITAL LETTER PSI + { 0x03A9, "Omega" }, // GREEK CAPITAL LETTER OMEGA;Duplicate + { 0x03AA, "Iotadieresis" }, // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + { 0x03AB, "Upsilondieresis" }, // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + { 0x03AC, "alphatonos" }, // GREEK SMALL LETTER ALPHA WITH TONOS + { 0x03AD, "epsilontonos" }, // GREEK SMALL LETTER EPSILON WITH TONOS + { 0x03AE, "etatonos" }, // GREEK SMALL LETTER ETA WITH TONOS + { 0x03AF, "iotatonos" }, // GREEK SMALL LETTER IOTA WITH TONOS + { 0x03B0, "upsilondieresistonos" }, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + { 0x03B1, "alpha" }, // GREEK SMALL LETTER ALPHA + { 0x03B2, "beta" }, // GREEK SMALL LETTER BETA + { 0x03B3, "gamma" }, // GREEK SMALL LETTER GAMMA + { 0x03B4, "delta" }, // GREEK SMALL LETTER DELTA + { 0x03B5, "epsilon" }, // GREEK SMALL LETTER EPSILON + { 0x03B6, "zeta" }, // GREEK SMALL LETTER ZETA + { 0x03B7, "eta" }, // GREEK SMALL LETTER ETA + { 0x03B8, "theta" }, // GREEK SMALL LETTER THETA + { 0x03B9, "iota" }, // GREEK SMALL LETTER IOTA + { 0x03BA, "kappa" }, // GREEK SMALL LETTER KAPPA + { 0x03BB, "lambda" }, // GREEK SMALL LETTER LAMDA + { 0x03BC, "mu" }, // GREEK SMALL LETTER MU;Duplicate + { 0x03BD, "nu" }, // GREEK SMALL LETTER NU + { 0x03BE, "xi" }, // GREEK SMALL LETTER XI + { 0x03BF, "omicron" }, // GREEK SMALL LETTER OMICRON + { 0x03C0, "pi" }, // GREEK SMALL LETTER PI + { 0x03C1, "rho" }, // GREEK SMALL LETTER RHO + { 0x03C2, "sigma1" }, // GREEK SMALL LETTER FINAL SIGMA + { 0x03C3, "sigma" }, // GREEK SMALL LETTER SIGMA + { 0x03C4, "tau" }, // GREEK SMALL LETTER TAU + { 0x03C5, "upsilon" }, // GREEK SMALL LETTER UPSILON + { 0x03C6, "phi" }, // GREEK SMALL LETTER PHI + { 0x03C7, "chi" }, // GREEK SMALL LETTER CHI + { 0x03C8, "psi" }, // GREEK SMALL LETTER PSI + { 0x03C9, "omega" }, // GREEK SMALL LETTER OMEGA + { 0x03CA, "iotadieresis" }, // GREEK SMALL LETTER IOTA WITH DIALYTIKA + { 0x03CB, "upsilondieresis" }, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA + { 0x03CC, "omicrontonos" }, // GREEK SMALL LETTER OMICRON WITH TONOS + { 0x03CD, "upsilontonos" }, // GREEK SMALL LETTER UPSILON WITH TONOS + { 0x03CE, "omegatonos" }, // GREEK SMALL LETTER OMEGA WITH TONOS + { 0x03D1, "theta1" }, // GREEK THETA SYMBOL + { 0x03D2, "Upsilon1" }, // GREEK UPSILON WITH HOOK SYMBOL + { 0x03D5, "phi1" }, // GREEK PHI SYMBOL + { 0x03D6, "omega1" }, // GREEK PI SYMBOL + { 0x0401, "afii10023" }, // CYRILLIC CAPITAL LETTER IO + { 0x0402, "afii10051" }, // CYRILLIC CAPITAL LETTER DJE + { 0x0403, "afii10052" }, // CYRILLIC CAPITAL LETTER GJE + { 0x0404, "afii10053" }, // CYRILLIC CAPITAL LETTER UKRAINIAN IE + { 0x0405, "afii10054" }, // CYRILLIC CAPITAL LETTER DZE + { 0x0406, "afii10055" }, // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + { 0x0407, "afii10056" }, // CYRILLIC CAPITAL LETTER YI + { 0x0408, "afii10057" }, // CYRILLIC CAPITAL LETTER JE + { 0x0409, "afii10058" }, // CYRILLIC CAPITAL LETTER LJE + { 0x040A, "afii10059" }, // CYRILLIC CAPITAL LETTER NJE + { 0x040B, "afii10060" }, // CYRILLIC CAPITAL LETTER TSHE + { 0x040C, "afii10061" }, // CYRILLIC CAPITAL LETTER KJE + { 0x040E, "afii10062" }, // CYRILLIC CAPITAL LETTER SHORT U + { 0x040F, "afii10145" }, // CYRILLIC CAPITAL LETTER DZHE + { 0x0410, "afii10017" }, // CYRILLIC CAPITAL LETTER A + { 0x0411, "afii10018" }, // CYRILLIC CAPITAL LETTER BE + { 0x0412, "afii10019" }, // CYRILLIC CAPITAL LETTER VE + { 0x0413, "afii10020" }, // CYRILLIC CAPITAL LETTER GHE + { 0x0414, "afii10021" }, // CYRILLIC CAPITAL LETTER DE + { 0x0415, "afii10022" }, // CYRILLIC CAPITAL LETTER IE + { 0x0416, "afii10024" }, // CYRILLIC CAPITAL LETTER ZHE + { 0x0417, "afii10025" }, // CYRILLIC CAPITAL LETTER ZE + { 0x0418, "afii10026" }, // CYRILLIC CAPITAL LETTER I + { 0x0419, "afii10027" }, // CYRILLIC CAPITAL LETTER SHORT I + { 0x041A, "afii10028" }, // CYRILLIC CAPITAL LETTER KA + { 0x041B, "afii10029" }, // CYRILLIC CAPITAL LETTER EL + { 0x041C, "afii10030" }, // CYRILLIC CAPITAL LETTER EM + { 0x041D, "afii10031" }, // CYRILLIC CAPITAL LETTER EN + { 0x041E, "afii10032" }, // CYRILLIC CAPITAL LETTER O + { 0x041F, "afii10033" }, // CYRILLIC CAPITAL LETTER PE + { 0x0420, "afii10034" }, // CYRILLIC CAPITAL LETTER ER + { 0x0421, "afii10035" }, // CYRILLIC CAPITAL LETTER ES + { 0x0422, "afii10036" }, // CYRILLIC CAPITAL LETTER TE + { 0x0423, "afii10037" }, // CYRILLIC CAPITAL LETTER U + { 0x0424, "afii10038" }, // CYRILLIC CAPITAL LETTER EF + { 0x0425, "afii10039" }, // CYRILLIC CAPITAL LETTER HA + { 0x0426, "afii10040" }, // CYRILLIC CAPITAL LETTER TSE + { 0x0427, "afii10041" }, // CYRILLIC CAPITAL LETTER CHE + { 0x0428, "afii10042" }, // CYRILLIC CAPITAL LETTER SHA + { 0x0429, "afii10043" }, // CYRILLIC CAPITAL LETTER SHCHA + { 0x042A, "afii10044" }, // CYRILLIC CAPITAL LETTER HARD SIGN + { 0x042B, "afii10045" }, // CYRILLIC CAPITAL LETTER YERU + { 0x042C, "afii10046" }, // CYRILLIC CAPITAL LETTER SOFT SIGN + { 0x042D, "afii10047" }, // CYRILLIC CAPITAL LETTER E + { 0x042E, "afii10048" }, // CYRILLIC CAPITAL LETTER YU + { 0x042F, "afii10049" }, // CYRILLIC CAPITAL LETTER YA + { 0x0430, "afii10065" }, // CYRILLIC SMALL LETTER A + { 0x0431, "afii10066" }, // CYRILLIC SMALL LETTER BE + { 0x0432, "afii10067" }, // CYRILLIC SMALL LETTER VE + { 0x0433, "afii10068" }, // CYRILLIC SMALL LETTER GHE + { 0x0434, "afii10069" }, // CYRILLIC SMALL LETTER DE + { 0x0435, "afii10070" }, // CYRILLIC SMALL LETTER IE + { 0x0436, "afii10072" }, // CYRILLIC SMALL LETTER ZHE + { 0x0437, "afii10073" }, // CYRILLIC SMALL LETTER ZE + { 0x0438, "afii10074" }, // CYRILLIC SMALL LETTER I + { 0x0439, "afii10075" }, // CYRILLIC SMALL LETTER SHORT I + { 0x043A, "afii10076" }, // CYRILLIC SMALL LETTER KA + { 0x043B, "afii10077" }, // CYRILLIC SMALL LETTER EL + { 0x043C, "afii10078" }, // CYRILLIC SMALL LETTER EM + { 0x043D, "afii10079" }, // CYRILLIC SMALL LETTER EN + { 0x043E, "afii10080" }, // CYRILLIC SMALL LETTER O + { 0x043F, "afii10081" }, // CYRILLIC SMALL LETTER PE + { 0x0440, "afii10082" }, // CYRILLIC SMALL LETTER ER + { 0x0441, "afii10083" }, // CYRILLIC SMALL LETTER ES + { 0x0442, "afii10084" }, // CYRILLIC SMALL LETTER TE + { 0x0443, "afii10085" }, // CYRILLIC SMALL LETTER U + { 0x0444, "afii10086" }, // CYRILLIC SMALL LETTER EF + { 0x0445, "afii10087" }, // CYRILLIC SMALL LETTER HA + { 0x0446, "afii10088" }, // CYRILLIC SMALL LETTER TSE + { 0x0447, "afii10089" }, // CYRILLIC SMALL LETTER CHE + { 0x0448, "afii10090" }, // CYRILLIC SMALL LETTER SHA + { 0x0449, "afii10091" }, // CYRILLIC SMALL LETTER SHCHA + { 0x044A, "afii10092" }, // CYRILLIC SMALL LETTER HARD SIGN + { 0x044B, "afii10093" }, // CYRILLIC SMALL LETTER YERU + { 0x044C, "afii10094" }, // CYRILLIC SMALL LETTER SOFT SIGN + { 0x044D, "afii10095" }, // CYRILLIC SMALL LETTER E + { 0x044E, "afii10096" }, // CYRILLIC SMALL LETTER YU + { 0x044F, "afii10097" }, // CYRILLIC SMALL LETTER YA + { 0x0451, "afii10071" }, // CYRILLIC SMALL LETTER IO + { 0x0452, "afii10099" }, // CYRILLIC SMALL LETTER DJE + { 0x0453, "afii10100" }, // CYRILLIC SMALL LETTER GJE + { 0x0454, "afii10101" }, // CYRILLIC SMALL LETTER UKRAINIAN IE + { 0x0455, "afii10102" }, // CYRILLIC SMALL LETTER DZE + { 0x0456, "afii10103" }, // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + { 0x0457, "afii10104" }, // CYRILLIC SMALL LETTER YI + { 0x0458, "afii10105" }, // CYRILLIC SMALL LETTER JE + { 0x0459, "afii10106" }, // CYRILLIC SMALL LETTER LJE + { 0x045A, "afii10107" }, // CYRILLIC SMALL LETTER NJE + { 0x045B, "afii10108" }, // CYRILLIC SMALL LETTER TSHE + { 0x045C, "afii10109" }, // CYRILLIC SMALL LETTER KJE + { 0x045E, "afii10110" }, // CYRILLIC SMALL LETTER SHORT U + { 0x045F, "afii10193" }, // CYRILLIC SMALL LETTER DZHE + { 0x0462, "afii10146" }, // CYRILLIC CAPITAL LETTER YAT + { 0x0463, "afii10194" }, // CYRILLIC SMALL LETTER YAT + { 0x0472, "afii10147" }, // CYRILLIC CAPITAL LETTER FITA + { 0x0473, "afii10195" }, // CYRILLIC SMALL LETTER FITA + { 0x0474, "afii10148" }, // CYRILLIC CAPITAL LETTER IZHITSA + { 0x0475, "afii10196" }, // CYRILLIC SMALL LETTER IZHITSA + { 0x0490, "afii10050" }, // CYRILLIC CAPITAL LETTER GHE WITH UPTURN + { 0x0491, "afii10098" }, // CYRILLIC SMALL LETTER GHE WITH UPTURN + { 0x04D9, "afii10846" }, // CYRILLIC SMALL LETTER SCHWA + { 0x05B0, "afii57799" }, // HEBREW POINT SHEVA + { 0x05B1, "afii57801" }, // HEBREW POINT HATAF SEGOL + { 0x05B2, "afii57800" }, // HEBREW POINT HATAF PATAH + { 0x05B3, "afii57802" }, // HEBREW POINT HATAF TQAMATS + { 0x05B4, "afii57793" }, // HEBREW POINT HIRIQ + { 0x05B5, "afii57794" }, // HEBREW POINT TSERE + { 0x05B6, "afii57795" }, // HEBREW POINT SEGOL + { 0x05B7, "afii57798" }, // HEBREW POINT PATAH + { 0x05B8, "afii57797" }, // HEBREW POINT TQAMATS + { 0x05B9, "afii57806" }, // HEBREW POINT HOLAM + { 0x05BB, "afii57796" }, // HEBREW POINT TQUBUTS + { 0x05BC, "afii57807" }, // HEBREW POINT DAGESH OR MAPIQ + { 0x05BD, "afii57839" }, // HEBREW POINT METEG + { 0x05BE, "afii57645" }, // HEBREW PUNCTUATION MATQAF + { 0x05BF, "afii57841" }, // HEBREW POINT RAFE + { 0x05C0, "afii57842" }, // HEBREW PUNCTUATION PASEQ + { 0x05C1, "afii57804" }, // HEBREW POINT SHIN DOT + { 0x05C2, "afii57803" }, // HEBREW POINT SIN DOT + { 0x05C3, "afii57658" }, // HEBREW PUNCTUATION SOF PASUQ + { 0x05D0, "afii57664" }, // HEBREW LETTER ALEF + { 0x05D1, "afii57665" }, // HEBREW LETTER BET + { 0x05D2, "afii57666" }, // HEBREW LETTER GIMEL + { 0x05D3, "afii57667" }, // HEBREW LETTER DALET + { 0x05D4, "afii57668" }, // HEBREW LETTER HE + { 0x05D5, "afii57669" }, // HEBREW LETTER VAV + { 0x05D6, "afii57670" }, // HEBREW LETTER ZAYIN + { 0x05D7, "afii57671" }, // HEBREW LETTER HET + { 0x05D8, "afii57672" }, // HEBREW LETTER TET + { 0x05D9, "afii57673" }, // HEBREW LETTER YOD + { 0x05DA, "afii57674" }, // HEBREW LETTER FINAL KAF + { 0x05DB, "afii57675" }, // HEBREW LETTER KAF + { 0x05DC, "afii57676" }, // HEBREW LETTER LAMED + { 0x05DD, "afii57677" }, // HEBREW LETTER FINAL MEM + { 0x05DE, "afii57678" }, // HEBREW LETTER MEM + { 0x05DF, "afii57679" }, // HEBREW LETTER FINAL NUN + { 0x05E0, "afii57680" }, // HEBREW LETTER NUN + { 0x05E1, "afii57681" }, // HEBREW LETTER SAMEKH + { 0x05E2, "afii57682" }, // HEBREW LETTER AYIN + { 0x05E3, "afii57683" }, // HEBREW LETTER FINAL PE + { 0x05E4, "afii57684" }, // HEBREW LETTER PE + { 0x05E5, "afii57685" }, // HEBREW LETTER FINAL TSADI + { 0x05E6, "afii57686" }, // HEBREW LETTER TSADI + { 0x05E7, "afii57687" }, // HEBREW LETTER TQOF + { 0x05E8, "afii57688" }, // HEBREW LETTER RESH + { 0x05E9, "afii57689" }, // HEBREW LETTER SHIN + { 0x05EA, "afii57690" }, // HEBREW LETTER TAV + { 0x05F0, "afii57716" }, // HEBREW LIGATURE YIDDISH DOUBLE VAV + { 0x05F1, "afii57717" }, // HEBREW LIGATURE YIDDISH VAV YOD + { 0x05F2, "afii57718" }, // HEBREW LIGATURE YIDDISH DOUBLE YOD + { 0x060C, "afii57388" }, // ARABIC COMMA + { 0x061B, "afii57403" }, // ARABIC SEMICOLON + { 0x061F, "afii57407" }, // ARABIC QUESTION MARK + { 0x0621, "afii57409" }, // ARABIC LETTER HAMZA + { 0x0622, "afii57410" }, // ARABIC LETTER ALEF WITH MADDA ABOVE + { 0x0623, "afii57411" }, // ARABIC LETTER ALEF WITH HAMZA ABOVE + { 0x0624, "afii57412" }, // ARABIC LETTER WAW WITH HAMZA ABOVE + { 0x0625, "afii57413" }, // ARABIC LETTER ALEF WITH HAMZA BELOW + { 0x0626, "afii57414" }, // ARABIC LETTER YEH WITH HAMZA ABOVE + { 0x0627, "afii57415" }, // ARABIC LETTER ALEF + { 0x0628, "afii57416" }, // ARABIC LETTER BEH + { 0x0629, "afii57417" }, // ARABIC LETTER TEH MARBUTA + { 0x062A, "afii57418" }, // ARABIC LETTER TEH + { 0x062B, "afii57419" }, // ARABIC LETTER THEH + { 0x062C, "afii57420" }, // ARABIC LETTER JEEM + { 0x062D, "afii57421" }, // ARABIC LETTER HAH + { 0x062E, "afii57422" }, // ARABIC LETTER KHAH + { 0x062F, "afii57423" }, // ARABIC LETTER DAL + { 0x0630, "afii57424" }, // ARABIC LETTER THAL + { 0x0631, "afii57425" }, // ARABIC LETTER REH + { 0x0632, "afii57426" }, // ARABIC LETTER ZAIN + { 0x0633, "afii57427" }, // ARABIC LETTER SEEN + { 0x0634, "afii57428" }, // ARABIC LETTER SHEEN + { 0x0635, "afii57429" }, // ARABIC LETTER SAD + { 0x0636, "afii57430" }, // ARABIC LETTER DAD + { 0x0637, "afii57431" }, // ARABIC LETTER TAH + { 0x0638, "afii57432" }, // ARABIC LETTER ZAH + { 0x0639, "afii57433" }, // ARABIC LETTER AIN + { 0x063A, "afii57434" }, // ARABIC LETTER GHAIN + { 0x0640, "afii57440" }, // ARABIC TATWEEL + { 0x0641, "afii57441" }, // ARABIC LETTER FEH + { 0x0642, "afii57442" }, // ARABIC LETTER TQAF + { 0x0643, "afii57443" }, // ARABIC LETTER KAF + { 0x0644, "afii57444" }, // ARABIC LETTER LAM + { 0x0645, "afii57445" }, // ARABIC LETTER MEEM + { 0x0646, "afii57446" }, // ARABIC LETTER NOON + { 0x0647, "afii57470" }, // ARABIC LETTER HEH + { 0x0648, "afii57448" }, // ARABIC LETTER WAW + { 0x0649, "afii57449" }, // ARABIC LETTER ALEF MAKSURA + { 0x064A, "afii57450" }, // ARABIC LETTER YEH + { 0x064B, "afii57451" }, // ARABIC FATHATAN + { 0x064C, "afii57452" }, // ARABIC DAMMATAN + { 0x064D, "afii57453" }, // ARABIC KASRATAN + { 0x064E, "afii57454" }, // ARABIC FATHA + { 0x064F, "afii57455" }, // ARABIC DAMMA + { 0x0650, "afii57456" }, // ARABIC KASRA + { 0x0651, "afii57457" }, // ARABIC SHADDA + { 0x0652, "afii57458" }, // ARABIC SUKUN + { 0x0660, "afii57392" }, // ARABIC-INDIC DIGIT ZERO + { 0x0661, "afii57393" }, // ARABIC-INDIC DIGIT ONE + { 0x0662, "afii57394" }, // ARABIC-INDIC DIGIT TWO + { 0x0663, "afii57395" }, // ARABIC-INDIC DIGIT THREE + { 0x0664, "afii57396" }, // ARABIC-INDIC DIGIT FOUR + { 0x0665, "afii57397" }, // ARABIC-INDIC DIGIT FIVE + { 0x0666, "afii57398" }, // ARABIC-INDIC DIGIT SIX + { 0x0667, "afii57399" }, // ARABIC-INDIC DIGIT SEVEN + { 0x0668, "afii57400" }, // ARABIC-INDIC DIGIT EIGHT + { 0x0669, "afii57401" }, // ARABIC-INDIC DIGIT NINE + { 0x066A, "afii57381" }, // ARABIC PERCENT SIGN + { 0x066D, "afii63167" }, // ARABIC FIVE POINTED STAR + { 0x0679, "afii57511" }, // ARABIC LETTER TTEH + { 0x067E, "afii57506" }, // ARABIC LETTER PEH + { 0x0686, "afii57507" }, // ARABIC LETTER TCHEH + { 0x0688, "afii57512" }, // ARABIC LETTER DDAL + { 0x0691, "afii57513" }, // ARABIC LETTER RREH + { 0x0698, "afii57508" }, // ARABIC LETTER JEH + { 0x06A4, "afii57505" }, // ARABIC LETTER VEH + { 0x06AF, "afii57509" }, // ARABIC LETTER GAF + { 0x06BA, "afii57514" }, // ARABIC LETTER NOON GHUNNA + { 0x06D2, "afii57519" }, // ARABIC LETTER YEH BARREE + { 0x06D5, "afii57534" }, // ARABIC LETTER AE + { 0x1E80, "Wgrave" }, // LATIN CAPITAL LETTER W WITH GRAVE + { 0x1E81, "wgrave" }, // LATIN SMALL LETTER W WITH GRAVE + { 0x1E82, "Wacute" }, // LATIN CAPITAL LETTER W WITH ACUTE + { 0x1E83, "wacute" }, // LATIN SMALL LETTER W WITH ACUTE + { 0x1E84, "Wdieresis" }, // LATIN CAPITAL LETTER W WITH DIAERESIS + { 0x1E85, "wdieresis" }, // LATIN SMALL LETTER W WITH DIAERESIS + { 0x1EF2, "Ygrave" }, // LATIN CAPITAL LETTER Y WITH GRAVE + { 0x1EF3, "ygrave" }, // LATIN SMALL LETTER Y WITH GRAVE + { 0x200C, "afii61664" }, // ZERO WIDTH NON-JOINER + { 0x200D, "afii301" }, // ZERO WIDTH JOINER + { 0x200E, "afii299" }, // LEFT-TO-RIGHT MARK + { 0x200F, "afii300" }, // RIGHT-TO-LEFT MARK + { 0x2012, "figuredash" }, // FIGURE DASH + { 0x2013, "endash" }, // EN DASH + { 0x2014, "emdash" }, // EM DASH + { 0x2015, "afii00208" }, // HORIZONTAL BAR + { 0x2017, "underscoredbl" }, // DOUBLE LOW LINE + { 0x2018, "quoteleft" }, // LEFT SINGLE QUOTATION MARK + { 0x2019, "quoteright" }, // RIGHT SINGLE QUOTATION MARK + { 0x201A, "quotesinglbase" }, // SINGLE LOW-9 QUOTATION MARK + { 0x201B, "quotereversed" }, // SINGLE HIGH-REVERSED-9 QUOTATION MARK + { 0x201C, "quotedblleft" }, // LEFT DOUBLE QUOTATION MARK + { 0x201D, "quotedblright" }, // RIGHT DOUBLE QUOTATION MARK + { 0x201E, "quotedblbase" }, // DOUBLE LOW-9 QUOTATION MARK + { 0x2020, "dagger" }, // DAGGER + { 0x2021, "daggerdbl" }, // DOUBLE DAGGER + { 0x2022, "bullet" }, // BULLET + { 0x2024, "onedotenleader" }, // ONE DOT LEADER + { 0x2025, "twodotenleader" }, // TWO DOT LEADER + { 0x2026, "ellipsis" }, // HORIZONTAL ELLIPSIS + { 0x202C, "afii61573" }, // POP DIRECTIONAL FORMATTING + { 0x202D, "afii61574" }, // LEFT-TO-RIGHT OVERRIDE + { 0x202E, "afii61575" }, // RIGHT-TO-LEFT OVERRIDE + { 0x2030, "perthousand" }, // PER MILLE SIGN + { 0x2032, "minute" }, // PRIME + { 0x2033, "second" }, // DOUBLE PRIME + { 0x2039, "guilsinglleft" }, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + { 0x203A, "guilsinglright" }, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + { 0x203C, "exclamdbl" }, // DOUBLE EXCLAMATION MARK + { 0x2044, "fraction" }, // FRACTION SLASH + { 0x2070, "zerosuperior" }, // SUPERSCRIPT ZERO + { 0x2074, "foursuperior" }, // SUPERSCRIPT FOUR + { 0x2075, "fivesuperior" }, // SUPERSCRIPT FIVE + { 0x2076, "sixsuperior" }, // SUPERSCRIPT SIX + { 0x2077, "sevensuperior" }, // SUPERSCRIPT SEVEN + { 0x2078, "eightsuperior" }, // SUPERSCRIPT EIGHT + { 0x2079, "ninesuperior" }, // SUPERSCRIPT NINE + { 0x207D, "parenleftsuperior" }, // SUPERSCRIPT LEFT PARENTHESIS + { 0x207E, "parenrightsuperior" }, // SUPERSCRIPT RIGHT PARENTHESIS + { 0x207F, "nsuperior" }, // SUPERSCRIPT LATIN SMALL LETTER N + { 0x2080, "zeroinferior" }, // SUBSCRIPT ZERO + { 0x2081, "oneinferior" }, // SUBSCRIPT ONE + { 0x2082, "twoinferior" }, // SUBSCRIPT TWO + { 0x2083, "threeinferior" }, // SUBSCRIPT THREE + { 0x2084, "fourinferior" }, // SUBSCRIPT FOUR + { 0x2085, "fiveinferior" }, // SUBSCRIPT FIVE + { 0x2086, "sixinferior" }, // SUBSCRIPT SIX + { 0x2087, "seveninferior" }, // SUBSCRIPT SEVEN + { 0x2088, "eightinferior" }, // SUBSCRIPT EIGHT + { 0x2089, "nineinferior" }, // SUBSCRIPT NINE + { 0x208D, "parenleftinferior" }, // SUBSCRIPT LEFT PARENTHESIS + { 0x208E, "parenrightinferior" }, // SUBSCRIPT RIGHT PARENTHESIS + { 0x20A1, "colonmonetary" }, // COLON SIGN + { 0x20A3, "franc" }, // FRENCH FRANC SIGN + { 0x20A4, "lira" }, // LIRA SIGN + { 0x20A7, "peseta" }, // PESETA SIGN + { 0x20AA, "afii57636" }, // NEW SHETQEL SIGN + { 0x20AB, "dong" }, // DONG SIGN + { 0x20AC, "Euro" }, // EURO SIGN + { 0x2105, "afii61248" }, // CARE OF + { 0x2111, "Ifraktur" }, // BLACK-LETTER CAPITAL I + { 0x2113, "afii61289" }, // SCRIPT SMALL L + { 0x2116, "afii61352" }, // NUMERO SIGN + { 0x2118, "weierstrass" }, // SCRIPT CAPITAL P + { 0x211C, "Rfraktur" }, // BLACK-LETTER CAPITAL R + { 0x211E, "prescription" }, // PRESCRIPTION TAKE + { 0x2122, "trademark" }, // TRADE MARK SIGN + { 0x2126, "Omega" }, // OHM SIGN + { 0x212E, "estimated" }, // ESTIMATED SYMBOL + { 0x2135, "aleph" }, // ALEF SYMBOL + { 0x2153, "onethird" }, // VULGAR FRACTION ONE THIRD + { 0x2154, "twothirds" }, // VULGAR FRACTION TWO THIRDS + { 0x215B, "oneeighth" }, // VULGAR FRACTION ONE EIGHTH + { 0x215C, "threeeighths" }, // VULGAR FRACTION THREE EIGHTHS + { 0x215D, "fiveeighths" }, // VULGAR FRACTION FIVE EIGHTHS + { 0x215E, "seveneighths" }, // VULGAR FRACTION SEVEN EIGHTHS + { 0x2190, "arrowleft" }, // LEFTWARDS ARROW + { 0x2191, "arrowup" }, // UPWARDS ARROW + { 0x2192, "arrowright" }, // RIGHTWARDS ARROW + { 0x2193, "arrowdown" }, // DOWNWARDS ARROW + { 0x2194, "arrowboth" }, // LEFT RIGHT ARROW + { 0x2195, "arrowupdn" }, // UP DOWN ARROW + { 0x21A8, "arrowupdnbse" }, // UP DOWN ARROW WITH BASE + { 0x21B5, "carriagereturn" }, // DOWNWARDS ARROW WITH CORNER LEFTWARDS + { 0x21D0, "arrowdblleft" }, // LEFTWARDS DOUBLE ARROW + { 0x21D1, "arrowdblup" }, // UPWARDS DOUBLE ARROW + { 0x21D2, "arrowdblright" }, // RIGHTWARDS DOUBLE ARROW + { 0x21D3, "arrowdbldown" }, // DOWNWARDS DOUBLE ARROW + { 0x21D4, "arrowdblboth" }, // LEFT RIGHT DOUBLE ARROW + { 0x2200, "universal" }, // FOR ALL + { 0x2202, "partialdiff" }, // PARTIAL DIFFERENTIAL + { 0x2203, "existential" }, // THERE EXISTS + { 0x2205, "emptyset" }, // EMPTY SET + { 0x2206, "Delta" }, // INCREMENT + { 0x2207, "gradient" }, // NABLA + { 0x2208, "element" }, // ELEMENT OF + { 0x2209, "notelement" }, // NOT AN ELEMENT OF + { 0x220B, "suchthat" }, // CONTAINS AS MEMBER + { 0x220F, "product" }, // N-ARY PRODUCT + { 0x2211, "summation" }, // N-ARY SUMMATION + { 0x2212, "minus" }, // MINUS SIGN + { 0x2215, "fraction" }, // DIVISION SLASH;Duplicate + { 0x2217, "asteriskmath" }, // ASTERISK OPERATOR + { 0x2219, "periodcentered" }, // BULLET OPERATOR;Duplicate + { 0x221A, "radical" }, // SQUARE ROOT + { 0x221D, "proportional" }, // PROPORTIONAL TO + { 0x221E, "infinity" }, // INFINITY + { 0x221F, "orthogonal" }, // RIGHT ANGLE + { 0x2220, "angle" }, // ANGLE + { 0x2227, "logicaland" }, // LOGICAL AND + { 0x2228, "logicalor" }, // LOGICAL OR + { 0x2229, "intersection" }, // INTERSECTION + { 0x222A, "union" }, // UNION + { 0x222B, "integral" }, // INTEGRAL + { 0x2234, "therefore" }, // THEREFORE + { 0x223C, "similar" }, // TILDE OPERATOR + { 0x2245, "congruent" }, // APPROXIMATELY EQUAL TO + { 0x2248, "approxequal" }, // ALMOST EQUAL TO + { 0x2260, "notequal" }, // NOT EQUAL TO + { 0x2261, "equivalence" }, // IDENTICAL TO + { 0x2264, "lessequal" }, // LESS-THAN OR EQUAL TO + { 0x2265, "greaterequal" }, // GREATER-THAN OR EQUAL TO + { 0x2282, "propersubset" }, // SUBSET OF + { 0x2283, "propersuperset" }, // SUPERSET OF + { 0x2284, "notsubset" }, // NOT A SUBSET OF + { 0x2286, "reflexsubset" }, // SUBSET OF OR EQUAL TO + { 0x2287, "reflexsuperset" }, // SUPERSET OF OR EQUAL TO + { 0x2295, "circleplus" }, // CIRCLED PLUS + { 0x2297, "circlemultiply" }, // CIRCLED TIMES + { 0x22A5, "perpendicular" }, // UP TACK + { 0x22C5, "dotmath" }, // DOT OPERATOR + { 0x2302, "house" }, // HOUSE + { 0x2310, "revlogicalnot" }, // REVERSED NOT SIGN + { 0x2320, "integraltp" }, // TOP HALF INTEGRAL + { 0x2321, "integralbt" }, // BOTTOM HALF INTEGRAL + { 0x2329, "angleleft" }, // LEFT-POINTING ANGLE BRACKET + { 0x232A, "angleright" }, // RIGHT-POINTING ANGLE BRACKET + { 0x2500, "SF100000" }, // BOX DRAWINGS LIGHT HORIZONTAL + { 0x2502, "SF110000" }, // BOX DRAWINGS LIGHT VERTICAL + { 0x250C, "SF010000" }, // BOX DRAWINGS LIGHT DOWN AND RIGHT + { 0x2510, "SF030000" }, // BOX DRAWINGS LIGHT DOWN AND LEFT + { 0x2514, "SF020000" }, // BOX DRAWINGS LIGHT UP AND RIGHT + { 0x2518, "SF040000" }, // BOX DRAWINGS LIGHT UP AND LEFT + { 0x251C, "SF080000" }, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT + { 0x2524, "SF090000" }, // BOX DRAWINGS LIGHT VERTICAL AND LEFT + { 0x252C, "SF060000" }, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + { 0x2534, "SF070000" }, // BOX DRAWINGS LIGHT UP AND HORIZONTAL + { 0x253C, "SF050000" }, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + { 0x2550, "SF430000" }, // BOX DRAWINGS DOUBLE HORIZONTAL + { 0x2551, "SF240000" }, // BOX DRAWINGS DOUBLE VERTICAL + { 0x2552, "SF510000" }, // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + { 0x2553, "SF520000" }, // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + { 0x2554, "SF390000" }, // BOX DRAWINGS DOUBLE DOWN AND RIGHT + { 0x2555, "SF220000" }, // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + { 0x2556, "SF210000" }, // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + { 0x2557, "SF250000" }, // BOX DRAWINGS DOUBLE DOWN AND LEFT + { 0x2558, "SF500000" }, // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + { 0x2559, "SF490000" }, // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + { 0x255A, "SF380000" }, // BOX DRAWINGS DOUBLE UP AND RIGHT + { 0x255B, "SF280000" }, // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + { 0x255C, "SF270000" }, // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + { 0x255D, "SF260000" }, // BOX DRAWINGS DOUBLE UP AND LEFT + { 0x255E, "SF360000" }, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + { 0x255F, "SF370000" }, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + { 0x2560, "SF420000" }, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + { 0x2561, "SF190000" }, // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + { 0x2562, "SF200000" }, // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + { 0x2563, "SF230000" }, // BOX DRAWINGS DOUBLE VERTICAL AND LEFT + { 0x2564, "SF470000" }, // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + { 0x2565, "SF480000" }, // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + { 0x2566, "SF410000" }, // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + { 0x2567, "SF450000" }, // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + { 0x2568, "SF460000" }, // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + { 0x2569, "SF400000" }, // BOX DRAWINGS DOUBLE UP AND HORIZONTAL + { 0x256A, "SF540000" }, // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + { 0x256B, "SF530000" }, // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + { 0x256C, "SF440000" }, // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + { 0x2580, "upblock" }, // UPPER HALF BLOCK + { 0x2584, "dnblock" }, // LOWER HALF BLOCK + { 0x2588, "block" }, // FULL BLOCK + { 0x258C, "lfblock" }, // LEFT HALF BLOCK + { 0x2590, "rtblock" }, // RIGHT HALF BLOCK + { 0x2591, "ltshade" }, // LIGHT SHADE + { 0x2592, "shade" }, // MEDIUM SHADE + { 0x2593, "dkshade" }, // DARK SHADE + { 0x25A0, "filledbox" }, // BLACK SQUARE + { 0x25A1, "H22073" }, // WHITE SQUARE + { 0x25AA, "H18543" }, // BLACK SMALL SQUARE + { 0x25AB, "H18551" }, // WHITE SMALL SQUARE + { 0x25AC, "filledrect" }, // BLACK RECTANGLE + { 0x25B2, "triagup" }, // BLACK UP-POINTING TRIANGLE + { 0x25BA, "triagrt" }, // BLACK RIGHT-POINTING POINTER + { 0x25BC, "triagdn" }, // BLACK DOWN-POINTING TRIANGLE + { 0x25C4, "triaglf" }, // BLACK LEFT-POINTING POINTER + { 0x25CA, "lozenge" }, // LOZENGE + { 0x25CB, "circle" }, // WHITE CIRCLE + { 0x25CF, "H18533" }, // BLACK CIRCLE + { 0x25D8, "invbullet" }, // INVERSE BULLET + { 0x25D9, "invcircle" }, // INVERSE WHITE CIRCLE + { 0x25E6, "openbullet" }, // WHITE BULLET + { 0x263A, "smileface" }, // WHITE SMILING FACE + { 0x263B, "invsmileface" }, // BLACK SMILING FACE + { 0x263C, "sun" }, // WHITE SUN WITH RAYS + { 0x2640, "female" }, // FEMALE SIGN + { 0x2642, "male" }, // MALE SIGN + { 0x2660, "spade" }, // BLACK SPADE SUIT + { 0x2663, "club" }, // BLACK CLUB SUIT + { 0x2665, "heart" }, // BLACK HEART SUIT + { 0x2666, "diamond" }, // BLACK DIAMOND SUIT + { 0x266A, "musicalnote" }, // EIGHTH NOTE + { 0x266B, "musicalnotedbl" }, // BEAMED EIGHTH NOTES + // The names below are in the PU area of Unicode, but needed to get a correct mapping of the symbol font + { 0xF6D9, "copyrightserif" }, + { 0xF6DA, "registerserif" }, + { 0xF6DB, "trademarkserif" }, + { 0xF8E5, "radicalex" }, + { 0xF8E6, "arrowvertex" }, + { 0xF8E7, "arrowhorizex" }, + { 0xF8E8, "registersans" }, + { 0xF8E9, "copyrightsans" }, + { 0xF8EA, "trademarksans" }, + { 0xF8EB, "parenlefttp" }, + { 0xF8EC, "parenleftex" }, + { 0xF8ED, "parenleftbt" }, + { 0xF8EE, "bracketlefttp" }, + { 0xF8EF, "bracketleftex" }, + { 0xF8F0, "bracketleftbt" }, + { 0xF8F1, "bracelefttp" }, + { 0xF8F2, "braceleftmid" }, + { 0xF8F3, "braceleftbt" }, + { 0xF8F4, "braceex" }, + { 0xF8F5, "integralex" }, + { 0xF8F6, "parenrighttp" }, + { 0xF8F7, "parenrightex" }, + { 0xF8F8, "parenrightbt" }, + { 0xF8F9, "bracketrighttp" }, + { 0xF8FA, "bracketrightex" }, + { 0xF8FB, "bracketrightbt" }, + { 0xF8FC, "bracerighttp" }, + { 0xF8FD, "bracerightmid" }, + { 0xF8FE, "bracerightbt" }, + // End of extensions needed for symbols + { 0xFB00, "ff" }, // LATIN SMALL LIGATURE FF + { 0xFB01, "fi" }, // LATIN SMALL LIGATURE FI + { 0xFB02, "fl" }, // LATIN SMALL LIGATURE FL + { 0xFB03, "ffi" }, // LATIN SMALL LIGATURE FFI + { 0xFB04, "ffl" }, // LATIN SMALL LIGATURE FFL + { 0xFB1F, "afii57705" }, // HEBREW LIGATURE YIDDISH YOD YOD PATAH + { 0xFB2A, "afii57694" }, // HEBREW LETTER SHIN WITH SHIN DOT + { 0xFB2B, "afii57695" }, // HEBREW LETTER SHIN WITH SIN DOT + { 0xFB35, "afii57723" }, // HEBREW LETTER VAV WITH DAGESH + { 0xFB4B, "afii57700" }, // HEBREW LETTER VAV WITH HOLAM + // end of stuff from glyphlist.txt + { 0xFFFF, 0 } +}; + +// --------------------------------------------------------------------- +// postscript font substitution dictionary. We assume every postscript printer has at least +// Helvetica, Times, Courier and Symbol + +struct psfont { + const char *psname; + float slant; + float xscale; +}; + +static const psfont Arial[] = { + {"Arial", 0, 84.04 }, + { "Arial-Italic", 0, 84.04 }, + { "Arial-Bold", 0, 88.65 }, + { "Arial-BoldItalic", 0, 88.65 } +}; + +static const psfont AvantGarde[] = { + { "AvantGarde-Book", 0, 87.43 }, + { "AvantGarde-BookOblique", 0, 88.09 }, + { "AvantGarde-Demi", 0, 88.09 }, + { "AvantGarde-DemiOblique", 0, 87.43 }, +}; + +static const psfont Bookman [] = { + { "Bookman-Light", 0, 93.78 }, + { "Bookman-LightItalic", 0, 91.42 }, + { "Bookman-Demi", 0, 99.86 }, + { "Bookman-DemiItalic", 0, 101.54 } +}; + +static const psfont Charter [] = { + { "CharterBT-Roman", 0, 84.04 }, + { "CharterBT-Italic", 0.0, 81.92 }, + { "CharterBT-Bold", 0, 88.99 }, + { "CharterBT-BoldItalic", 0.0, 88.20 } +}; + +static const psfont Courier [] = { + { "Courier", 0, 100. }, + { "Courier-Oblique", 0, 100. }, + { "Courier-Bold", 0, 100. }, + { "Courier-BoldOblique", 0, 100. } +}; + +static const psfont Garamond [] = { + { "Garamond-Antiqua", 0, 78.13 }, + { "Garamond-Kursiv", 0, 78.13 }, + { "Garamond-Halbfett", 0, 78.13 }, + { "Garamond-KursivHalbfett", 0, 78.13 } +}; + +static const psfont GillSans [] = { // ### some estimated value for xstretch + { "GillSans", 0, 82 }, + { "GillSans-Italic", 0, 82 }, + { "GillSans-Bold", 0, 82 }, + { "GillSans-BoldItalic", 0, 82 } +}; + +static const psfont Helvetica [] = { + { "Helvetica", 0, 84.04 }, + { "Helvetica-Oblique", 0, 84.04 }, + { "Helvetica-Bold", 0, 88.65 }, + { "Helvetica-BoldOblique", 0, 88.65 } +}; + +static const psfont Letter [] = { + { "LetterGothic", 0, 83.32 }, + { "LetterGothic-Italic", 0, 83.32 }, + { "LetterGothic-Bold", 0, 83.32 }, + { "LetterGothic-Bold", 0.2, 83.32 } +}; + +static const psfont LucidaSans [] = { + { "LucidaSans", 0, 94.36 }, + { "LucidaSans-Oblique", 0, 94.36 }, + { "LucidaSans-Demi", 0, 98.10 }, + { "LucidaSans-DemiOblique", 0, 98.08 } +}; + +static const psfont LucidaSansTT [] = { + { "LucidaSans-Typewriter", 0, 100.50 }, + { "LucidaSans-TypewriterOblique", 0, 100.50 }, + { "LucidaSans-TypewriterBold", 0, 100.50 }, + { "LucidaSans-TypewriterBoldOblique", 0, 100.50 } +}; + +static const psfont LucidaBright [] = { + { "LucidaBright", 0, 93.45 }, + { "LucidaBright-Italic", 0, 91.98 }, + { "LucidaBright-Demi", 0, 96.22 }, + { "LucidaBright-DemiItalic", 0, 96.98 } +}; + +static const psfont Palatino [] = { + { "Palatino-Roman", 0, 82.45 }, + { "Palatino-Italic", 0, 76.56 }, + { "Palatino-Bold", 0, 83.49 }, + { "Palatino-BoldItalic", 0, 81.51 } +}; + +static const psfont Symbol [] = { + { "Symbol", 0, 82.56 }, + { "Symbol", 0.2, 82.56 }, + { "Symbol", 0, 82.56 }, + { "Symbol", 0.2, 82.56 } +}; + +static const psfont Tahoma [] = { + { "Tahoma", 0, 83.45 }, + { "Tahoma", 0.2, 83.45 }, + { "Tahoma-Bold", 0, 95.59 }, + { "Tahoma-Bold", 0.2, 95.59 } +}; + +static const psfont Times [] = { + { "Times-Roman", 0, 82.45 }, + { "Times-Italic", 0, 82.45 }, + { "Times-Bold", 0, 82.45 }, + { "Times-BoldItalic", 0, 82.45 } +}; + +static const psfont Verdana [] = { + { "Verdana", 0, 96.06 }, + { "Verdana-Italic", 0, 96.06 }, + { "Verdana-Bold", 0, 107.12 }, + { "Verdana-BoldItalic", 0, 107.10 } +}; + +static const psfont Utopia [] = { // ### + { "Utopia-Regular", 0, 84.70 }, + { "Utopia-Regular", 0.2, 84.70 }, + { "Utopia-Bold", 0, 88.01 }, + { "Utopia-Bold", 0.2, 88.01 } +}; + +static const psfont * const SansSerifReplacements[] = { + Helvetica, 0 + }; +static const psfont * const SerifReplacements[] = { + Times, 0 + }; +static const psfont * const FixedReplacements[] = { + Courier, 0 + }; +static const psfont * const TahomaReplacements[] = { + Verdana, AvantGarde, Helvetica, 0 + }; +static const psfont * const VerdanaReplacements[] = { + Tahoma, AvantGarde, Helvetica, 0 + }; + +static const struct { + const char * input; // spaces are stripped in here, and everything lowercase + const psfont * ps; + const psfont *const * replacements; +} postscriptFonts [] = { + { "arial", Arial, SansSerifReplacements }, + { "arialmt", Arial, SansSerifReplacements }, + { "arialunicodems", Arial, SansSerifReplacements }, + { "avantgarde", AvantGarde, SansSerifReplacements }, + { "bookman", Bookman, SerifReplacements }, + { "charter", Charter, SansSerifReplacements }, + { "bitstreamcharter", Charter, SansSerifReplacements }, + { "bitstreamcyberbit", Times, SerifReplacements }, // ### + { "courier", Courier, 0 }, + { "couriernew", Courier, 0 }, + { "fixed", Courier, 0 }, + { "garamond", Garamond, SerifReplacements }, + { "gillsans", GillSans, SansSerifReplacements }, + { "helvetica", Helvetica, 0 }, + { "letter", Letter, FixedReplacements }, + { "lucida", LucidaSans, SansSerifReplacements }, + { "lucidasans", LucidaSans, SansSerifReplacements }, + { "lucidabright", LucidaBright, SerifReplacements }, + { "lucidasanstypewriter", LucidaSansTT, FixedReplacements }, + { "luciduxsans", LucidaSans, SansSerifReplacements }, + { "luciduxserif", LucidaBright, SerifReplacements }, + { "luciduxmono", LucidaSansTT, FixedReplacements }, + { "palatino", Palatino, SerifReplacements }, + { "symbol", Symbol, 0 }, + { "tahoma", Tahoma, TahomaReplacements }, + { "terminal", Courier, 0 }, + { "times", Times, 0 }, + { "timesnewroman", Times, 0 }, + { "verdana", Verdana, VerdanaReplacements }, + { "utopia", Utopia, SerifReplacements }, + { 0, 0, 0 } +}; + + +// ------------------------------End of static data ---------------------------------- + +// make sure DSC comments are not longer than 255 chars per line. +static TQString wrapDSC( const TQString &str ) +{ + TQString dsc = str.simplifyWhiteSpace(); + const uint wrapAt = 254; + TQString wrapped; + if ( dsc.length() < wrapAt ) + wrapped = dsc; + else { + wrapped = dsc.left( wrapAt ); + TQString tmp = dsc.mid( wrapAt ); + while ( tmp.length() > wrapAt-3 ) { + wrapped += "\n%%+" + tmp.left( wrapAt-3 ); + tmp = tmp.mid( wrapAt-3 ); + } + wrapped += "\n%%+" + tmp; + } + return wrapped + "\n"; +} + +static TQString toString( const float num ) +{ + return TQString::number( num, 'f', 3 ); +} + +// ----------------------------- Internal class declarations ----------------------------- + +class TQPSPrinterFontPrivate; + +class TQPSPrinterPrivate { +public: + TQPSPrinterPrivate( TQPrinter *prt, int filedes ); + ~TQPSPrinterPrivate(); + + void matrixSetup( TQPainter * ); + void clippingSetup( TQPainter * ); + void setClippingOff( TQPainter * ); + void orientationSetup(); + void resetDrawingTools( TQPainter * ); + void emitHeader( bool finished ); + void setFont( const TQFont &, int script ); + void drawImage( TQPainter *, float x, float y, float w, float h, const TQImage &img, const TQImage &mask ); + void initPage( TQPainter *paint ); + void flushPage( bool last = FALSE ); + + TQPrinter *printer; + int pageCount; + bool dirtyMatrix; + bool dirtyNewPage; + bool epsf; + TQString fontsUsed; + + // outstream is the stream the build up pages are copied to. It points to buffer + // at the start, and is reset to use the outDevice after emitHeader has been called. + TQTextStream outStream; + + // stores the descriptions of the first pages. outStream operates on this buffer + // until we call emitHeader + TQBuffer *buffer; + int pagesInBuffer; + + // the device the output is in the end streamed to. + TQIODevice * outDevice; + int fd; + + // buffer for the current page. Needed becaus we might have page fonts. + TQBuffer *pageBuffer; + TQTextStream pageStream; + + TQDict headerFontNames; + TQDict pageFontNames; + TQDict fonts; + TQPSPrinterFontPrivate *currentFontFile; + int headerFontNumber; + int pageFontNumber; + TQBuffer * fontBuffer; + TQTextStream fontStream; + bool dirtyClipping; + bool firstClipOnPage; + TQRect boundingBox; + TQImage * savedImage; + TQPen cpen; + TQBrush cbrush; + bool dirtypen; + bool dirtybrush; + TQColor bkColor; + bool dirtyBkColor; + TQt::BGMode bkMode; + bool dirtyBkMode; +#ifndef TQT_NO_TEXTCODEC + TQTextCodec * currentFontCodec; +#endif + TQString currentFont; + TQFontMetrics fm; + int textY; + TQFont currentUsed; + int scriptUsed; + TQFont currentSet; + float scale; + + TQStringList fontpath; +}; + + +class TQPSPrinterFontPrivate { +public: + TQPSPrinterFontPrivate(); + virtual ~TQPSPrinterFontPrivate() {} + virtual TQString postScriptFontName() { return psname; } + virtual TQString defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, + TQPSPrinterPrivate *d ); + virtual void download(TQTextStream& s, bool global); + virtual void drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, + const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint); + virtual unsigned short mapUnicode( unsigned short unicode ); + void downloadMapping( TQTextStream &s, bool global ); + TQString glyphName( unsigned short glyphindex, bool *glyphSet = 0 ); + virtual void restore(); + + virtual unsigned short unicode_for_glyph(int glyphindex) { return glyphindex; } + virtual unsigned short glyph_for_unicode(unsigned short unicode) { return unicode; } + unsigned short insertIntoSubset( unsigned short unicode ); + virtual bool embedded() { return FALSE; } + + bool operator == ( const TQPSPrinterFontPrivate &other ) { + return other.psname == psname; + } + inline void setSymbol() { symbol = TRUE; } + +protected: + TQString psname; + TQStringList replacementList; + + TQMap subset; // unicode subset in the global font + TQMap page_subset; // subset added in this page + int subsetCount; + int pageSubsetCount; + bool global_dict; + bool downloaded; + bool symbol; +}; + +// ------------------- end of class declarations --------------------------- + +// -------------------------------------------------------------- +// beginning of font related methods +// -------------------------------------------------------------- + + +static int getPsFontType( const TQFontEngine *fe ) +{ + int weight = fe->fontDef.weight; + bool italic = fe->fontDef.italic; + + int type = 0; // used to look up in the psname array + // get the right modification, or build something + if ( weight > TQFont::Normal && italic ) + type = 3; + else if ( weight > TQFont::Normal ) + type = 2; + else if ( italic ) + type = 1; + return type; +} + +static int addPsFontNameExtension( const TQFontEngine *fe, TQString &ps, const psfont *psf = 0 ) +{ + int type = getPsFontType( fe ); + + if ( psf ) { + ps = TQString::fromLatin1( psf[type].psname ); + } else { + switch ( type ) { + case 1: + ps.append( TQString::fromLatin1("-Italic") ); + break; + case 2: + ps.append( TQString::fromLatin1("-Bold") ); + break; + case 3: + ps.append( TQString::fromLatin1("-BoldItalic") ); + break; + case 0: + default: + break; + } + } + return type; +} + +static TQString makePSFontName( const TQFontEngine *fe, int *listpos = 0, int *ftype = 0 ) +{ + TQString ps; + int i; + + TQString family = fe->fontDef.family.lower(); + + // try to make a "good" postscript name + ps = family.simplifyWhiteSpace(); + i = 0; + while( (unsigned int)i < ps.length() ) { + if ( i != 0 && ps[i] == '[') { + if ( ps[i-1] == ' ' ) + ps.truncate (i-1); + else + ps.truncate (i); + break; + } + if ( i == 0 || ps[i-1] == ' ' ) { + ps[i] = ps[i].upper(); + if ( i ) + ps.remove( i-1, 1 ); + else + i++; + } else { + i++; + } + } + + if ( ps.isEmpty() ) + ps = "Helvetica"; + + // see if the table has a better name + i = 0; + TQString lowerName = ps.lower(); + while( postscriptFonts[i].input && + postscriptFonts[i].input != lowerName ) + i++; + const psfont *psf = postscriptFonts[i].ps; + + int type = addPsFontNameExtension( fe, ps, psf ); + + if ( listpos ) + *listpos = i; + if ( ftype ) + *ftype = type; + return ps; +} + +static void appendReplacements( TQStringList &list, const psfont * const * replacements, int type, float xscale = 100. ) +{ + // iterate through the replacement fonts + while ( *replacements ) { + const psfont *psf = *replacements; + TQString ps = "[ /" + TQString::fromLatin1( psf[type].psname ) + " " + + toString( xscale / psf[type].xscale ) + " " + + toString( psf[type].slant ) + " ]"; + list.append( ps ); + ++replacements; + } +} + +static TQStringList makePSFontNameList( const TQFontEngine *fe, const TQString &psname = TQString::null, bool useNameForLookup = FALSE ) +{ + int i; + int type; + TQStringList list; + TQString ps = psname; + + if ( !ps.isEmpty() && !useNameForLookup ) { + TQString best = "[ /" + ps + " 1.0 0.0 ]"; + list.append( best ); + } + + ps = makePSFontName( fe, &i, &type ); + + const psfont *psf = postscriptFonts[i].ps; + const psfont * const * replacements = postscriptFonts[i].replacements; + float xscale = 100; + if ( psf ) { + // xscale for the "right" font is always 1. We scale the replacements... + xscale = psf->xscale; + ps = "[ /" + TQString::fromLatin1( psf[type].psname ) + " 1.0 " + + toString( psf[type].slant ) + " ]"; + } else { + ps = "[ /" + ps + " 1.0 0.0 ]"; + // only add default replacement fonts in case this font was unknown. + if ( fe->fontDef.fixedPitch ) { + replacements = FixedReplacements; + } else { + replacements = SansSerifReplacements; + // 100 is courier, but most fonts are not as wide as courier. Using 100 + // here would make letters overlap for some fonts. This value is empirical. + xscale = 83; + } + } + list.append( ps ); + + if ( replacements ) + appendReplacements( list, replacements, type, xscale); + return list; +} + +static void emitPSFontNameList( TQTextStream &s, const TQString &psname, const TQStringList &list ) +{ + s << "/" << psname << "List [\n"; + s << list.join("\n "); + s << "\n] d\n"; +} + +static inline float pointSize( const TQFont &f, float scale ) +{ + float psize; + if ( f.pointSize() != -1 ) + psize = f.pointSize()/scale; + else + psize = f.pixelSize(); + return psize; +} + + +// ========================== FONT CLASSES =============== + + +TQPSPrinterFontPrivate::TQPSPrinterFontPrivate() +{ + global_dict = FALSE; + downloaded = FALSE; + symbol = FALSE; + // map 0 to .notdef + subset.insert( 0, 0 ); + subsetCount = 1; + pageSubsetCount = 0; +} + +unsigned short TQPSPrinterFontPrivate::insertIntoSubset( unsigned short u ) +{ + unsigned short retval = 0; + if ( subset.find(u) == subset.end() ) { + if ( !downloaded ) { // we need to add to the page subset + subset.insert( u, subsetCount ); // mark it as used + //printf("GLOBAL SUBSET ADDED %04x = %04x\n",u, subsetCount); + retval = subsetCount; + subsetCount++; + } else if ( page_subset.find(u) == page_subset.end() ) { + page_subset.insert( u, pageSubsetCount ); // mark it as used + //printf("PAGE SUBSET ADDED %04x = %04x\n",u, pageSubsetCount); + retval = pageSubsetCount + (subsetCount/256 + 1) * 256; + pageSubsetCount++; + } + } else { + tqWarning("TQPSPrinterFont::internal error"); + } + return retval; +} + +void TQPSPrinterFontPrivate::restore() +{ + page_subset.clear(); + pageSubsetCount = 0; + //tqDebug("restore for font %s\n",psname.latin1()); +} + +static inline const char *toHex( uchar u ) +{ + static char hexVal[3]; + int i = 1; + while ( i >= 0 ) { + ushort hex = (u & 0x000f); + if ( hex < 0x0a ) + hexVal[i] = '0'+hex; + else + hexVal[i] = 'A'+(hex-0x0a); + u = u >> 4; + i--; + } + hexVal[2] = '\0'; + return hexVal; +} + +static inline const char *toHex( ushort u ) +{ + static char hexVal[5]; + int i = 3; + while ( i >= 0 ) { + ushort hex = (u & 0x000f); + if ( hex < 0x0a ) + hexVal[i] = '0'+hex; + else + hexVal[i] = 'A'+(hex-0x0a); + u = u >> 4; + i--; + } + hexVal[4] = '\0'; + return hexVal; +} + +static inline const char * toInt( int i ) +{ + static char intVal[20]; + intVal[19] = 0; + int pos = 19; + if ( i == 0 ) { + intVal[--pos] = '0'; + } else { + bool neg = FALSE; + if ( i < 0 ) { + neg = TRUE; + i = -i; + } + while ( i ) { + int dec = i%10; + intVal[--pos] = '0'+dec; + i /= 10; + } + if ( neg ) + intVal[--pos] = '-'; + } + return intVal+pos; +} + +void TQPSPrinterFontPrivate::drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, + const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint) +{ + int len = engine->length( item ); + TQScriptItem &si = engine->items[item]; + + int x = p.x() + si.x; + int y = p.y() + si.y; + if ( y != d->textY || d->textY == 0 ) + stream << y << " Y"; + d->textY = y; + + stream << "<"; + if ( si.analysis.bidiLevel % 2 ) { + for ( int i = len-1; i >=0; i-- ) + stream << toHex( mapUnicode(text.unicode()[i].unicode()) ); + } else { + for ( int i = 0; i < len; i++ ) + stream << toHex( mapUnicode(text.unicode()[i].unicode()) ); + } + stream << ">"; + + stream << si.width << " " << x; + + if ( paint->font().underline() ) + stream << ' ' << y + d->fm.underlinePos() + d->fm.lineWidth() + << " " << d->fm.lineWidth() << " Tl"; + if ( paint->font().strikeOut() ) + stream << ' ' << y + d->fm.strikeOutPos() + << " " << d->fm.lineWidth() << " Tl"; + stream << " AT\n"; + +} + + +TQString TQPSPrinterFontPrivate::defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, + TQPSPrinterPrivate *d ) +{ + TQString fontName; + fontName.sprintf( "/%s-Uni", ps.latin1()); + + if ( d->buffer ) { + ++d->headerFontNumber; + d->fontStream << "/F" << d->headerFontNumber << " " + << pointSize( f, d->scale ) << fontName << " DF\n"; + fontName.sprintf( "F%d", d->headerFontNumber ); + d->headerFontNames.insert( key, new TQString( fontName ) ); + } else { + ++d->pageFontNumber; + stream << "/F" << d->pageFontNumber << " " + << pointSize( f, d->scale ) << fontName << " DF\n"; + fontName.sprintf( "F%d", d->pageFontNumber ); + d->pageFontNames.insert( key, new TQString( fontName ) ); + } + return fontName; +} + +unsigned short TQPSPrinterFontPrivate::mapUnicode( unsigned short unicode ) +{ + TQMap::iterator res; + res = subset.find( unicode ); + unsigned short offset = 0; + bool found = FALSE; + if ( res != subset.end() ) { + found = TRUE; + } else { + if ( downloaded ) { + res = page_subset.find( unicode ); + offset = (subsetCount/256 + 1) * 256; + if ( res != page_subset.end() ) + found = TRUE; + } + } + if ( !found ) { + return insertIntoSubset( unicode ); + } + //tqDebug("mapping unicode %x to %x", unicode, offset+*res); + return offset + *res; +} + +// This map is used for symbol fonts to get the correct glyph names for the latin range +static const unsigned short symbol_map[0x100] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220b, + 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + + 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393, + 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f, + 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9, + 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f, + 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3, + 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf, + 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9, + 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f, + + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x20ac, 0x03d2, 0x2023, 0x2264, 0x2044, 0x221e, 0x0192, 0x2263, + 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193, + 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022, + 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5, + + 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229, + 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209, + 0x2220, 0x2207, 0xf6da, 0xf6d9, 0xf6db, 0x220f, 0x221a, 0x22c5, + 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3, + 0x25ca, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec, + 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4, + 0x0000, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7, + 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x0000, +}; + +TQString TQPSPrinterFontPrivate::glyphName( unsigned short glyphindex, bool *glyphSet ) +{ + TQString glyphname; + int l = 0; + unsigned short unicode = unicode_for_glyph( glyphindex ); + if (symbol && unicode < 0x100) { + // map from latin1 to symbol + unicode = symbol_map[unicode]; + } + if ( !unicode && glyphindex ) { + glyphname = "gl"; + glyphname += toHex( glyphindex ); + } else { + while( unicodetoglyph[l].u < unicode ) + l++; + if ( unicodetoglyph[l].u == unicode ) { + glyphname = unicodetoglyph[l].g; + if ( glyphSet ) { + int other = 0; + switch ( unicode ) { + // some glyph names are duplicate in postscript. Make sure we give the + // duplicate a different name to avoid infinite recursion + case 0x0394: + other = 0x2206; + break; + case 0x03a9: + other = 0x2126; + break; + case 0x0162: + other = 0x021a; + break; + case 0x2215: + other = 0x2044; + break; + case 0x00ad: + other = 0x002d; + break; + case 0x02c9: + other = 0x00af; + break; + case 0x03bc: + other = 0x00b5; + break; + case 0x2219: + other = 0x00b7; + break; + case 0x00a0: + other = 0x0020; + break; + case 0x0163: + other = 0x021b; + break; + default: + break; + } + if ( other ) { + int oglyph = glyph_for_unicode( other ); + if( oglyph && oglyph != glyphindex && glyphSet[oglyph] ) { + glyphname = "uni"; + glyphname += toHex( unicode ); + } + } + } + } else { + glyphname = "uni"; + glyphname += toHex( unicode ); + } + } + return glyphname; +} + +void TQPSPrinterFontPrivate::download(TQTextStream &s, bool global) +{ + //printf("defining mapping for printer font %s\n",psname.latin1()); + downloadMapping( s, global ); +} + +void TQPSPrinterFontPrivate::downloadMapping( TQTextStream &s, bool global ) +{ + uchar rangeOffset = 0; + uchar numRanges = (uchar)(subsetCount/256 + 1); + uchar range; + TQMap *subsetDict = ⊂ + if ( !global ) { + rangeOffset = numRanges; + numRanges = pageSubsetCount/256 + 1; + subsetDict = &page_subset; + } + // build up inverse table + unsigned short *inverse = new unsigned short[numRanges * 256]; + memset( inverse, 0, numRanges * 256 * sizeof( unsigned short ) ); + + TQMap::iterator it; + for ( it = subsetDict->begin(); it != subsetDict->end(); ++it) { + const unsigned short &mapped = *it; + inverse[mapped] = it.key(); + } + + TQString vector; + TQString glyphname; + + for (range=0; range < numRanges; range++) { + //printf("outputing range %04x\n",range*256); + vector = "%% Font Page "; + vector += toHex((uchar)(range + rangeOffset)); + vector += "\n/"; + vector += psname; + vector += "-ENC-"; + vector += toHex((uchar)(range + rangeOffset)); + vector += " [\n"; + + TQString line; + for(int k=0; k<256; k++ ) { + int c = range*256 + k; + unsigned short glyph = inverse[c]; + glyphname = glyphName( glyph ); + if ( line.length() + glyphname.length() > 76 ) { + vector += line; + vector += "\n"; + line = ""; + } + line += "/" + glyphname; + } + vector += line; + vector += "] def\n"; + s << vector; + } + + delete [] inverse; + + // DEFINE BASE FONTS + + for (range=0; range < numRanges; range++) { + s << "/"; + s << psname; + s << "-Uni-"; + s << toHex((uchar)(range + rangeOffset)); + s << " "; + s << psname; + s << "-ENC-"; + s << toHex((uchar)(range + rangeOffset)); + if ( embedded() && embedFonts ) { + s << " /"; + s << psname; + s << " MFEmb\n"; + } else { + s << " " << psname << "List"; + s << " MF\n"; + } + } + + // === write header === + // int VMMin; + // int VMMax; + + s << wrapDSC( "%%BeginFont: " + psname ) + << "%!PS-AdobeFont-1.0 Composite Font\n" + << wrapDSC( "%%FontName: " + psname + "-Uni" ) + << "%%Creator: Composite font created by TQt\n"; + + /* Start the dictionary which will eventually */ + /* become the font. */ + s << "25 dict begin\n"; // need to verify. Sivan + + s << "/FontName /"; + s << psname; + s << "-Uni"; + s << " def\n"; + s << "/PaintType 0 def\n"; + + // This is concatenated with the base fonts, so it should perform + // no transformation. Sivan + s << "/FontMatrix[1 0 0 1 0 0]def\n"; + + s << "/FontType "; + s << 0; + s << " def\n"; + + // now come composite font structures + // FMapTypes: + // 2: 8/8, 8 bits select the font, 8 the glyph + + s << "/FMapType 2 def\n"; + + // The encoding in a composite font is used for indirection. + // Every char is split into a font-number and a character-selector. + // PostScript prints glyph number character-selector from the font + // FDepVector[ Encoding[ font-number ] ]. + + s << "/Encoding ["; + for (range=0; range < rangeOffset + numRanges; range++) { + if (range % 16 == 0) + s << "\n"; + else + s << " "; + s << range; + } + s << "]def\n"; + + // Descendent fonts + + s << "/FDepVector [\n"; + for (range=0; range < rangeOffset + numRanges; range++) { + s << "/"; + s << psname; + s << "-Uni-"; + s << toHex( range ); + s << " findfont\n"; + } + s << "]def\n"; + + // === trailer === + + s << "FontName currentdict end definefont pop\n"; + s << "%%EndFont\n"; +} + + +// ================== TTF ==================== + +typedef TQ_UINT8 BYTE; +typedef TQ_UINT16 USHORT; +typedef TQ_UINT16 uFWord; +typedef TQ_INT16 SHORT; +typedef TQ_INT16 FWord; +typedef TQ_UINT32 ULONG; +typedef TQ_INT32 FIXED; + +typedef struct { + TQ_INT16 whole; + TQ_UINT16 fraction; +} Fixed; // 16.16 bit fixed-point number + +static float f2dot14( ushort s ) +{ + float f = ((float)( s & 0x3fff ))/ 16384.; + f += (s & 0x8000) ? ( (s & 0x4000) ? -1 : -2 ) : ( (s & 0x4000) ? 1 : 0 ); + return f; +} + +typedef struct { + int* epts_ctr; /* array of contour endpoints */ + int num_pts, num_ctr; /* number of points, number of coutours */ + FWord* xcoor, *ycoor; /* arrays of x and y coordinates */ + BYTE* tt_flags; /* array of TrueType flags */ + double* area_ctr; + char* check_ctr; + int* ctrset; /* in contour index followed by out contour index */ +} charproc_data; + + +class TQPSPrinterFontTTF + : public TQPSPrinterFontPrivate { +public: + TQPSPrinterFontTTF(const TQFontEngine *f, TQByteArray& data); + virtual void download(TQTextStream& s, bool global); + virtual void drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, + const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint); + // virtual ~TQPSPrinterFontTTF(); + + virtual bool embedded() { return TRUE; } +private: + TQByteArray data; + TQMemArray uni2glyph; // to speed up lookups + TQMemArray glyph2uni; // to speed up lookups + bool defective; // if we can't process this file + + BYTE* getTable(const char *); + void uni2glyphSetup(); + unsigned short unicode_for_glyph(int glyphindex); + unsigned short glyph_for_unicode(unsigned short unicode); + int topost(FWord x) { return (int)( ((int)(x) * 1000 + HUPM) / unitsPerEm ); } + +#ifdef Q_PRINTER_USE_TYPE42 + void sfnts_pputBYTE(BYTE n,TQTextStream& s, + int& string_len, int& line_len, bool& in_string); + void sfnts_pputUSHORT(USHORT n,TQTextStream& s, + int& string_len, int& line_len, bool& in_string); + void sfnts_pputULONG(ULONG n,TQTextStream& s, + int& string_len, int& line_len, bool& in_string); + void sfnts_end_string(TQTextStream& s, + int& string_len, int& line_len, bool& in_string); + void sfnts_new_table(ULONG length,TQTextStream& s, + int& string_len, int& line_len, bool& in_string); + void sfnts_glyf_table(ULONG oldoffset, + ULONG correct_total_length, + TQTextStream& s, + int& string_len, int& line_len, bool& in_string); + void download_sfnts(TQTextStream& s); +#endif + + void subsetGlyph(int charindex,bool* glyphset); + + void charproc(int charindex, TQTextStream& s, bool *glyphSet); + BYTE* charprocFindGlyphData(int charindex); + void charprocComposite(BYTE *glyph, TQTextStream& s, bool *glyphSet); + void charprocLoad(BYTE *glyph, charproc_data* cd); + + int target_type; /* 42 or 3 */ + + int numTables; /* number of tables present */ + TQString PostName; /* Font's PostScript name */ + TQString FullName; /* Font's full name */ + TQString FamilyName; /* Font's family name */ + TQString Style; /* Font's style string */ + TQString Copyright; /* Font's copyright string */ + TQString Version; /* Font's version string */ + TQString Trademark; /* Font's trademark string */ + int llx,lly,urx,ury; /* bounding box */ + + Fixed TTVersion; /* Truetype version number from offset table */ + Fixed MfrRevision; /* Revision number of this font */ + + BYTE *offset_table; /* Offset table in memory */ + BYTE *post_table; /* 'post' table in memory */ + + BYTE *loca_table; /* 'loca' table in memory */ + BYTE *glyf_table; /* 'glyf' table in memory */ + BYTE *hmtx_table; /* 'hmtx' table in memory */ + + USHORT numberOfHMetrics; + int unitsPerEm; /* unitsPerEm converted to int */ + int HUPM; /* half of above */ + + int numGlyphs; /* from 'post' table */ + + int indexToLocFormat; /* short or long offsets */ + +}; + + +static ULONG getULONG(BYTE *p) +{ + int x; + ULONG val=0; + + for(x=0; x<4; x++) { + val *= 0x100; + val += p[x]; + } + + return val; +} + +static USHORT getUSHORT(BYTE *p) +{ + int x; + USHORT val=0; + + for(x=0; x<2; x++) { + val *= 0x100; + val += p[x]; + } + + return val; +} + +static Fixed getFixed(BYTE *s) +{ + Fixed val={0,0}; + + val.whole = ((s[0] * 256) + s[1]); + val.fraction = ((s[2] * 256) + s[3]); + + return val; +} + +static FWord getFWord(BYTE* s) { return (FWord) getUSHORT(s); } +static uFWord getuFWord(BYTE* s) { return (uFWord) getUSHORT(s); } +static SHORT getSHORT(BYTE* s) { return (SHORT) getUSHORT(s); } + +#if 0 +static const char * const Apple_CharStrings[]={ + ".notdef",".null","nonmarkingreturn","space","exclam","quotedbl","numbersign", + "dollar","percent","ampersand","quotesingle","parenleft","parenright", + "asterisk","plus", "comma","hyphen","period","slash","zero","one","two", + "three","four","five","six","seven","eight","nine","colon","semicolon", + "less","equal","greater","question","at","A","B","C","D","E","F","G","H","I", + "J","K", "L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", + "bracketleft","backslash","bracketright","asciicircum","underscore","grave", + "a","b","c","d","e","f","g","h","i","j","k", "l","m","n","o","p","q","r","s", + "t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde", + "Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis", + "aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla", + "eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex", + "idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde", + "uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent", + "sterling","section","bullet","paragraph","germandbls","registered", + "copyright","trademark","acute","dieresis","notequal","AE","Oslash", + "infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff", + "summation","product","pi","integral","ordfeminine","ordmasculine","Omega", + "ae","oslash","questiondown","exclamdown","logicalnot","radical","florin", + "approxequal","Delta","guillemotleft","guillemotright","ellipsis", + "nobreakspace","Agrave","Atilde","Otilde","OE","oe","endash","emdash", + "quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge", + "ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright", + "fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase", + "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave", + "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple", + "Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde", + "macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron", + "Lslash","lslash","Scaron","scaron","Zcaron","zcaron","brokenbar","Eth","eth", + "Yacute","yacute","Thorn","thorn","minus","multiply","onesuperior", + "twosuperior","threesuperior","onehalf","onequarter","threequarters","franc", + "Gbreve","gbreve","Idot","Scedilla","scedilla","Cacute","cacute","Ccaron", + "ccaron","dmacron","markingspace","capslock","shift","propeller","enter", + "markingtabrtol","markingtabltor","control","markingdeleteltor", + "markingdeletertol","option","escape","parbreakltor","parbreakrtol", + "newpage","checkmark","linebreakltor","linebreakrtol","markingnobreakspace", + "diamond","appleoutline"}; +#endif + +// #define DEBUG_TRUETYPE + +TQPSPrinterFontTTF::TQPSPrinterFontTTF(const TQFontEngine *f, TQByteArray& d) +{ + data = d; + defective = FALSE; + + BYTE *ptr; + + target_type = 3; // will work on any printer + //target_type = 42; // works with gs, faster, better quality + +#ifdef Q_PRINTER_USE_TYPE42 + char* environment_preference = getenv("QT_TTFTOPS"); + if (environment_preference) { + if (TQString(environment_preference) == "42") + target_type = 42; + else if (TQString(environment_preference) == "3") + target_type = 3; + else + tqWarning("The value of QT_TTFTOPS must be 42 or 3"); + } +#endif + offset_table = (unsigned char*) data.data(); /* first 12 bytes */ + + /* Determine how many directory entries there are. */ + numTables = getUSHORT( offset_table + 4 ); + + /* Extract information from the "Offset" table. */ + TTVersion = getFixed( offset_table ); + + /* Load the "head" table and extract information from it. */ + ptr = getTable("head"); + if ( !ptr ) { + defective = TRUE; + return; + } + MfrRevision = getFixed( ptr + 4 ); /* font revision number */ + unitsPerEm = getUSHORT( ptr + 18 ); + HUPM = unitsPerEm / 2; +#ifdef DEBUG_TRUETYPE + printf("unitsPerEm=%d",(int)unitsPerEm); +#endif + llx = topost( getFWord( ptr + 36 ) ); /* bounding box info */ + lly = topost( getFWord( ptr + 38 ) ); + urx = topost( getFWord( ptr + 40 ) ); + ury = topost( getFWord( ptr + 42 ) ); + indexToLocFormat = getSHORT( ptr + 50 ); /* size of 'loca' data */ + if(indexToLocFormat != 0 && indexToLocFormat != 1) { + tqWarning("TrueType font is unusable because indexToLocFormat != 0"); + defective = TRUE; + return; + } + if( getSHORT(ptr+52) != 0 ) { + tqWarning("TrueType font is unusable because glyphDataFormat != 0"); + defective = TRUE; + return; + } + + // === Load information from the "name" table === + + /* Set default values to avoid future references to */ + /* undefined pointers. */ + + psname = FullName = FamilyName = Version = Style = "unknown"; + Copyright = "No copyright notice"; + Trademark = "No trademark notice"; + + BYTE* table_ptr = getTable("name"); /* pointer to table */ + if ( !table_ptr ) { + defective = TRUE; + tqDebug("couldn't find name table" ); + return; + } + int numrecords = getUSHORT( table_ptr + 2 ); /* number of names */ + char* strings = (char *)table_ptr + getUSHORT( table_ptr + 4 ); /* start of string storage */ + + BYTE* ptr2 = table_ptr + 6; + for(int x=0; x < numrecords; x++,ptr2+=12) { + int platform = getUSHORT(ptr2); + //int encoding = getUSHORT(ptr2+2); + //int language = getUSHORT(ptr2+4); + int nameid = getUSHORT(ptr2+6); + int length = getUSHORT(ptr2+8); + int offset = getUSHORT(ptr2+10); + + if( platform == 1 && nameid == 0 ) + Copyright.setLatin1(strings+offset,length); + + if( platform == 1 && nameid == 1 ) + FamilyName.setLatin1(strings+offset,length); + + if( platform == 1 && nameid == 2 ) + Style.setLatin1(strings+offset,length); + + if( platform == 1 && nameid == 4 ) + FullName.setLatin1(strings+offset,length); + + if( platform == 1 && nameid == 5 ) + Version.setLatin1(strings+offset,length); + + if( platform == 1 && nameid == 6 ) + psname.setLatin1(strings+offset,length); + + if( platform == 1 && nameid == 7 ) + Trademark.setLatin1(strings+offset,length); + + } + psname.replace(' ', '-'); + psname.replace("/", ""); + if (psname.isEmpty()) + psname = makePSFontName(f); + + //read_cmap(font); + + /* We need to have the PostScript table around. */ + + post_table = getTable("post"); +#if 0 + if ( post_table ) { + Fixed post_format = getFixed( post_table ); + + if( post_format.whole != 2 || post_format.fraction != 0 ) { + tqWarning("TrueType font does not have a format 2.0 'post' table"); + tqWarning("post format is %d.%d",post_format.whole,post_format.fraction); + // Sivan Feb 2001: no longer defective. + // defective = TRUE; + } + } +#endif + BYTE *maxp = getTable("maxp"); + if ( !maxp ) { + defective = TRUE; + tqDebug("no maxp table in font"); + return; + } + numGlyphs = getUSHORT( maxp + 4 ); +// tqDebug("number of glyphs is %d", numGlyphs); + replacementList = makePSFontNameList( f, psname ); + uni2glyphSetup(); +} + + +void TQPSPrinterFontTTF::drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, + const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint) +{ + // we draw glyphs here to get correct shaping of arabic and indic + TQScriptItem &si = engine->items[item]; + engine->shape( item ); + int len = si.num_glyphs; + + int x = p.x() + si.x; + int y = p.y() + si.y; + if ( y != d->textY || d->textY == 0 ) + stream << y << " Y"; + d->textY = y; + + TQCString xyarray; + int xo = 0; + int yo = 0; + + glyph_t *glyphs = engine->glyphs( &si ); + advance_t *advances = engine->advances( &si ); + qoffset_t *offsets = engine->offsets( &si ); +#ifdef TQ_WS_X11 + int type = si.fontEngine->type(); + bool glyphIndices = (type == TQFontEngine::Xft); + // This helps us get arabic for XLFD fonts working. In that case we have a Unicode + // cmap (== 0), and the glyphs array contains the shaped string. + bool useGlyphAsUnicode = (type == TQFontEngine::XLFD && si.fontEngine->cmap() == 0); +#endif + stream << "<"; + if ( si.analysis.bidiLevel % 2 ) { + for ( int i = len-1; i >=0; i-- ) { + // map unicode is not really the correct name, as we map glyphs, but we also download glyphs, so this works + unsigned short glyph; + if (glyphIndices) + glyph = glyphs[i]; + else + glyph = glyph_for_unicode(useGlyphAsUnicode ? glyphs[i] : text.unicode()[i].unicode()); + stream << toHex(mapUnicode(glyph)); + if ( i != len-1 ) { + xyarray += toInt( xo + offsets[i].x + advances[i+1] ); + xyarray += " "; + xyarray += toInt( yo + offsets[i].y ); + xyarray += " "; + xo = -offsets[i].x; + yo = -offsets[i].y; + } + } + } else { + for ( int i = 0; i < len; i++ ) { + // map unicode is not really the correct name, as we map glyphs, but we also download glyphs, so this works + unsigned short glyph; + if (glyphIndices) + glyph = glyphs[i]; + else + glyph = glyph_for_unicode(useGlyphAsUnicode ? glyphs[i] : text.unicode()[i].unicode()); + stream << toHex(mapUnicode(glyph)); + if ( i ) { + xyarray += toInt( xo + offsets[i].x + advances[i-1] ); + xyarray += " "; + xyarray += toInt( yo + offsets[i].y ); + xyarray += " "; + xo = -offsets[i].x; + yo = -offsets[i].y; + } + } + } + stream << ">"; + + stream << "[" << xyarray << "0 0]"; + stream << si.width << " " << x; + + if ( paint->font().underline() ) + stream << ' ' << y + d->fm.underlinePos() + d->fm.lineWidth() + << " " << d->fm.lineWidth() << " Tl"; + if ( paint->font().strikeOut() ) + stream << ' ' << y + d->fm.strikeOutPos() + << " " << d->fm.lineWidth() << " Tl"; + stream << " XYT\n"; + +} + + +void TQPSPrinterFontTTF::download(TQTextStream& s,bool global) +{ + emitPSFontNameList( s, psname, replacementList); + if ( !embedFonts ) { + downloadMapping(s, global); + return; + } + + //tqDebug("downloading ttf font %s", psname.latin1() ); + //tqDebug("target type=%d", target_type); + global_dict = global; + TQMap *subsetDict = ⊂ + if ( !global ) + subsetDict = &page_subset; + + downloaded = TRUE; + + if (defective) { + s << "% Font "; + s << FullName; + s << " cannot be downloaded\n"; + return; + } + + // === write header === + int VMMin; + int VMMax; + + s << wrapDSC( "%%BeginFont: " + FullName ); + if( target_type == 42 ) { + s << "%!PS-TrueTypeFont-" + << TTVersion.whole + << "." + << TTVersion.fraction + << "-" + << MfrRevision.whole + << "." + << MfrRevision.fraction + << "\n"; + } else { + /* If it is not a Type 42 font, we will use a different format. */ + s << "%!PS-Adobe-3.0 Resource-Font\n"; + } /* See RBIIp 641 */ + + if( Copyright != (char*)NULL ) { + s << wrapDSC( "%%Copyright: " + Copyright ); + } + + if( target_type == 42 ) + s << "%%Creator: Converted from TrueType to type 42 by TQt\n"; + else + s << "%%Creator: Converted from TrueType by TQt\n"; + + /* If VM usage information is available, print it. */ + if( target_type == 42 && post_table) + { + VMMin = (int)getULONG( post_table + 16 ); + VMMax = (int)getULONG( post_table + 20 ); + if( VMMin > 0 && VMMax > 0 ) + s << "%%VMUsage: " << VMMin << " " << VMMax << "\n"; + } + + /* Start the dictionary which will eventually */ + /* become the font. */ + if( target_type != 3 ) { + s << "15 dict begin\n"; + } else { + s << "25 dict begin\n"; + + /* Type 3 fonts will need some subroutines here. */ + s << "/_d{bind def}bind def\n"; + s << "/_m{moveto}_d\n"; + s << "/_l{lineto}_d\n"; + s << "/_cl{closepath eofill}_d\n"; + s << "/_c{curveto}_d\n"; + s << "/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d\n"; + s << "/_e{exec}_d\n"; + } + + s << "/FontName /"; + s << psname; + s << " def\n"; + s << "/PaintType 0 def\n"; + + if(target_type == 42) + s << "/FontMatrix[1 0 0 1 0 0]def\n"; + else + s << "/FontMatrix[.001 0 0 .001 0 0]def\n"; + + s << "/FontBBox["; + s<< llx; + s << " "; + s<< lly; + s << " "; + s<< urx; + s << " "; + s<< ury; + s << "]def\n"; + + s << "/FontType "; + s<< target_type; + s << " def\n"; + + // === write encoding === + + s << "/Encoding StandardEncoding def\n"; + + // === write fontinfo dict === + + /* We create a sub dictionary named "FontInfo" where we */ + /* store information which though it is not used by the */ + /* interpreter, is useful to some programs which will */ + /* be printing with the font. */ + s << "/FontInfo 10 dict dup begin\n"; + + /* These names come from the TrueType font's "name" table. */ + s << "/FamilyName ("; + s << FamilyName; + s << ") def\n"; + + s << "/FullName ("; + s << FullName; + s << ") def\n"; + + s << "/Notice ("; + s << Copyright; + s << " "; + s << Trademark; + s << ") def\n"; + + /* This information is not quite correct. */ + s << "/Weight ("; + s << Style; + s << ") def\n"; + + /* Some fonts have this as "version". */ + s << "/Version ("; + s << Version; + s << ") def\n"; + + /* Some information from the "post" table. */ + if ( post_table ) { + Fixed ItalicAngle = getFixed( post_table + 4 ); + s << "/ItalicAngle "; + s << ItalicAngle.whole; + s << "."; + s << ItalicAngle.fraction; + s << " def\n"; + + s << "/isFixedPitch "; + s << (getULONG( post_table + 12 ) ? "true" : "false" ); + s << " def\n"; + + s << "/UnderlinePosition "; + s << (int)getFWord( post_table + 8 ); + s << " def\n"; + + s << "/UnderlineThickness "; + s << (int)getFWord( post_table + 10 ); + s << " def\n"; + } + s << "end readonly def\n"; + +#ifdef Q_PRINTER_USE_TYPE42 + /* If we are generating a type 42 font, */ + /* emmit the sfnts array. */ + if( target_type == 42 ) + download_sfnts(s); +#endif + /* If we are generating a Type 3 font, we will need to */ + /* have the 'loca' and 'glyf' tables arround while */ + /* we are generating the CharStrings. */ + if(target_type == 3) + { + BYTE *ptr; /* We need only one value */ + ptr = getTable("hhea"); + numberOfHMetrics = getUSHORT(ptr + 34); + + loca_table = getTable("loca"); + glyf_table = getTable("glyf"); + hmtx_table = getTable("hmtx"); + } + + // === CharStrings array === + + // subsetting. We turn a char subset into a glyph subset + // and we mark as used the base glyphs of used composite glyphs. + + bool glyphset[65536]; + for(int c=0; c < 65536; c++) + glyphset[c] = FALSE; + glyphset[0] = TRUE; // always output .notdef + + TQMap::iterator it; + for( it = subsetDict->begin(); it != subsetDict->end(); ++it ) { + subsetGlyph( it.key(), glyphset ); + } + int nGlyphs = numGlyphs; + if ( target_type == 3 ) { + nGlyphs = 0;; + for(int c=0; c < 65536; c++) + if ( glyphset[c] ) nGlyphs++; + } + + s << "/CharStrings "; + s << nGlyphs; + s << " dict dup begin\n"; + + // Emmit one key-value pair for each glyph. + for(int x=0; x < 65536; x++) { + if(target_type == 42) { + s << "/"; + s << glyphName( x ); + s << " "; + s << x; + s << " def\n"; + } else { /* type 3 */ + if (!glyphset[x]) continue; + + //tqDebug("emitting charproc for glyph %d, name=%s", x, glyphName(x).latin1() ); + s << "/"; + s << glyphName( x, glyphset ); + s << "{"; + charproc(x,s, glyphset); + s << "}_d\n"; /* "} bind def" */ + } + } + + s << "end readonly def\n"; + + // === trailer === + + /* If we are generating a type 3 font, we need to provide */ + /* a BuildGlyph and BuildChar proceedures. */ + if( target_type == 3 ) { + s << "\n"; + + s << "/BuildGlyph\n"; + s << " {exch begin\n"; /* start font dictionary */ + s << " CharStrings exch\n"; + s << " 2 copy known not{pop /.notdef}if\n"; + s << " true 3 1 roll get exec\n"; + s << " end}_d\n"; + + s << "\n"; + + /* This proceedure is for compatiblity with */ + /* level 1 interpreters. */ + s << "/BuildChar {\n"; + s << " 1 index /Encoding get exch get\n"; + s << " 1 index /BuildGlyph get exec\n"; + s << "}_d\n"; + + s << "\n"; + + } + + /* If we are generating a type 42 font, we need to check to see */ + /* if this PostScript interpreter understands type 42 fonts. If */ + /* it doesn't, we will hope that the Apple TrueType rasterizer */ + /* has been loaded and we will adjust the font accordingly. */ + /* I found out how to do this by examining a TrueType font */ + /* generated by a Macintosh. That is where the TrueType interpreter */ + /* setup instructions and part of BuildGlyph came from. */ + else if( target_type == 42 ) { + s << "\n"; + + /* If we have no "resourcestatus" command, or FontType 42 */ + /* is unknown, leave "true" on the stack. */ + s << "systemdict/resourcestatus known\n"; + s << " {42 /FontType resourcestatus\n"; + s << " {pop pop false}{true}ifelse}\n"; + s << " {true}ifelse\n"; + + /* If true, execute code to produce an error message if */ + /* we can't find Apple's TrueDict in VM. */ + s << "{/TrueDict where{pop}{(%%[ Error: no TrueType rasterizer ]%%)= flush}ifelse\n"; + + /* Since we are expected to use Apple's TrueDict TrueType */ + /* reasterizer, change the font type to 3. */ + s << "/FontType 3 def\n"; + + /* Define a string to hold the state of the Apple */ + /* TrueType interpreter. */ + s << " /TrueState 271 string def\n"; + + /* It looks like we get information about the resolution */ + /* of the printer and store it in the TrueState string. */ + s << " TrueDict begin sfnts save\n"; + s << " 72 0 matrix defaultmatrix dtransform dup\n"; + s << " mul exch dup mul add sqrt cvi 0 72 matrix\n"; + s << " defaultmatrix dtransform dup mul exch dup\n"; + s << " mul add sqrt cvi 3 -1 roll restore\n"; + s << " TrueState initer end\n"; + + /* This BuildGlyph procedure will look the name up in the */ + /* CharStrings array, and then check to see if what it gets */ + /* is a procedure. If it is, it executes it, otherwise, it */ + /* lets the TrueType rasterizer loose on it. */ + + /* When this proceedure is executed the stack contains */ + /* the font dictionary and the character name. We */ + /* exchange arguments and move the dictionary to the */ + /* dictionary stack. */ + s << " /BuildGlyph{exch begin\n"; + /* stack: charname */ + + /* Put two copies of CharStrings on the stack and consume */ + /* one testing to see if the charname is defined in it, */ + /* leave the answer on the stack. */ + s << " CharStrings dup 2 index known\n"; + /* stack: charname CharStrings bool */ + + /* Exchange the CharStrings dictionary and the charname, */ + /* but if the answer was false, replace the character name */ + /* with ".notdef". */ + s << " {exch}{exch pop /.notdef}ifelse\n"; + /* stack: CharStrings charname */ + + /* Get the value from the CharStrings dictionary and see */ + /* if it is executable. */ + s << " get dup xcheck\n"; + /* stack: CharStrings_entry */ + + /* If is a proceedure. Execute according to RBIIp 277-278. */ + s << " {currentdict systemdict begin begin exec end end}\n"; + + /* Is a TrueType character index, let the rasterizer at it. */ + s << " {TrueDict begin /bander load cvlit exch TrueState render end}\n"; + + s << " ifelse\n"; + + /* Pop the font's dictionary off the stack. */ + s << " end}bind def\n"; + + /* This is the level 1 compatibility BuildChar procedure. */ + /* See RBIIp 281. */ + s << " /BuildChar{\n"; + s << " 1 index /Encoding get exch get\n"; + s << " 1 index /BuildGlyph get exec\n"; + s << " }bind def\n"; + + /* Here we close the condition which is true */ + /* if the printer has no built-in TrueType */ + /* rasterizer. */ + s << "}if\n"; + s << "\n"; + } /* end of if Type 42 not understood. */ + + s << "FontName currentdict end definefont pop\n"; + + downloadMapping(s, global); + s << "%%EndFont\n"; +} + +BYTE* TQPSPrinterFontTTF::getTable(const char* name) +{ + BYTE *ptr; + int x; + + /* We must search the table directory. */ + ptr = offset_table + 12; + x=0; + while (x != numTables) { + if( strncmp((const char *)ptr,name,4) == 0 ) { + ULONG offset; + //ULONG length; + BYTE *table; + + offset = getULONG( ptr + 8 ); + //length = getULONG( ptr + 12 ); + + table = offset_table + offset; + return table; + } + + x++; + ptr += 16; + } + + return 0; +} + +void TQPSPrinterFontTTF::uni2glyphSetup() +{ + uni2glyph.resize(65536); + int i; + for (i=0; i<65536; i++) uni2glyph[i] = 0x0000; + glyph2uni.resize(65536); + for (i=0; i<65536; i++) glyph2uni[i] = 0x0000; + + unsigned char* cmap = getTable("cmap"); + int pos = 0; + + //USHORT version = getUSHORT(cmap + pos); + pos += 2; + USHORT nmaps = getUSHORT(cmap + pos); pos += 2; + + //fprintf(stderr,"cmap version %d (should be 0), %d maps\n",version,nmaps); + + ULONG offset = 0; + int map = -1; + bool symbol = TRUE; + for (i=0; i 70) { + s << "\n"; + line_len=0; + } +} + +// Write a USHORT as a hexadecimal value as part of the sfnts array. + +void TQPSPrinterFontTTF::sfnts_pputUSHORT(USHORT n,TQTextStream& s, + int& string_len, int& line_len, bool& in_string) +{ + sfnts_pputBYTE(n / 256,s, string_len, line_len, in_string); + sfnts_pputBYTE(n % 256,s, string_len, line_len, in_string); +} + + +// Write a ULONG as part of the sfnts array. + +void TQPSPrinterFontTTF::sfnts_pputULONG(ULONG n,TQTextStream& s, + int& string_len, int& line_len, bool& in_string) +{ + int x1 = n % 256; n /= 256; + int x2 = n % 256; n /= 256; + int x3 = n % 256; n /= 256; + + sfnts_pputBYTE(n,s , string_len, line_len, in_string); + sfnts_pputBYTE(x3,s, string_len, line_len, in_string); + sfnts_pputBYTE(x2,s, string_len, line_len, in_string); + sfnts_pputBYTE(x1,s, string_len, line_len, in_string); +} + +/* +** This is called whenever it is +** necessary to end a string in the sfnts array. +** +** (The array must be broken into strings which are +** no longer than 64K characters.) +*/ +void TQPSPrinterFontTTF::sfnts_end_string(TQTextStream& s, + int& string_len, int& line_len, bool& in_string) +{ + if(in_string) { + string_len=0; /* fool sfnts_pputBYTE() */ + + // s << "\n% dummy byte:\n"; + + // extra byte for pre-2013 compatibility + sfnts_pputBYTE(0, s, string_len, line_len, in_string); + + s << ">"; + line_len++; + } + + in_string=FALSE; +} + +/* +** This is called at the start of each new table. +** The argement is the length in bytes of the table +** which will follow. If the new table will not fit +** in the current string, a new one is started. +*/ +void TQPSPrinterFontTTF::sfnts_new_table(ULONG length,TQTextStream& s, + int& string_len, int& line_len, bool& in_string) +{ + if( (string_len + length) > 65528 ) + sfnts_end_string(s, string_len, line_len, in_string); +} + +/* +** We may have to break up the 'glyf' table. That is the reason +** why we provide this special routine to copy it into the sfnts +** array. +*/ +void TQPSPrinterFontTTF::sfnts_glyf_table(ULONG oldoffset, + ULONG correct_total_length, + TQTextStream& s, + int& string_len, int& line_len, bool& in_string) + +{ + int x; + ULONG off; + ULONG length; + int c; + ULONG total=0; /* running total of bytes written to table */ + + loca_table = getTable("loca"); + + int font_off = oldoffset; + + /* Copy the glyphs one by one */ + for(x=0; x < numGlyphs; x++) { + /* Read the glyph offset from the index-to-location table. */ + if(indexToLocFormat == 0) { + off = getUSHORT( loca_table + (x * 2) ); + off *= 2; + length = getUSHORT( loca_table + ((x+1) * 2) ); + length *= 2; + length -= off; + } else { + off = getULONG( loca_table + (x * 4) ); + length = getULONG( loca_table + ((x+1) * 4) ); + length -= off; + } + + // fprintf(stderr,"glyph length=%d",(int)length); + + /* Start new string if necessary. */ + sfnts_new_table( (int)length, s, string_len, line_len, in_string ); + + /* + ** Make sure the glyph is padded out to a + ** two byte boundary. + */ + if( length % 2 ) { + tqWarning("TrueType font contains a 'glyf' table without 2 byte padding"); + defective = TRUE; + return; + } + + /* Copy the bytes of the glyph. */ + while( length-- ) { + c = offset_table[ font_off ]; + font_off++; + + sfnts_pputBYTE(c, s, string_len, line_len, in_string); + total++; /* add to running total */ + } + } + + /* Pad out to full length from table directory */ + while( total < correct_total_length ) { + sfnts_pputBYTE(0, s, string_len, line_len, in_string); + total++; + } + + /* Look for unexplainable descrepancies between sizes */ + if( total != correct_total_length ) { + tqWarning("TQPSPrinterFontTTF::sfnts_glyf_table: total != correct_total_length"); + defective = TRUE; + return; + } +} + +/* +** Here is the routine which ties it all together. +** +** Create the array called "sfnts" which +** holds the actual TrueType data. +*/ + +void TQPSPrinterFontTTF::download_sfnts(TQTextStream& s) +{ + // tables worth including in a type 42 font + char *table_names[]= { + "cvt ", + "fpgm", + "glyf", + "head", + "hhea", + "hmtx", + "loca", + "maxp", + "prep" + }; + + struct { /* The location of each of */ + ULONG oldoffset; /* the above tables. */ + ULONG newoffset; + ULONG length; + ULONG checksum; + } tables[9]; + + int c; /* Input character. */ + int diff; + int count; /* How many `important' tables did we find? */ + + BYTE* ptr = offset_table + 12; // original table directory + ULONG nextoffset=0; + count=0; + + /* + ** Find the tables we want and store there vital + ** statistics in tables[]. + */ + for(int x=0; x < 9; x++ ) { + do { + diff = strncmp( (char*)ptr, table_names[x], 4 ); + + if( diff > 0 ) { /* If we are past it. */ + tables[x].length = 0; + diff = 0; + } + else if( diff < 0 ) { /* If we haven't hit it yet. */ + ptr += 16; + } + else if( diff == 0 ) { /* Here it is! */ + tables[x].newoffset = nextoffset; + tables[x].checksum = getULONG( ptr + 4 ); + tables[x].oldoffset = getULONG( ptr + 8 ); + tables[x].length = getULONG( ptr + 12 ); + nextoffset += ( ((tables[x].length + 3) / 4) * 4 ); + count++; + ptr += 16; + } + } while(diff != 0); + } /* end of for loop which passes over the table directory */ + + /* Begin the sfnts array. */ + + s << "/sfnts[<"; + + bool in_string=TRUE; + int string_len=0; + int line_len=8; + + /* Generate the offset table header */ + /* Start by copying the TrueType version number. */ + ptr = offset_table; + for(int x=0; x < 4; x++) + sfnts_pputBYTE( *(ptr++) , s, string_len, line_len, in_string ); + + /* Now, generate those silly numTables numbers. */ + sfnts_pputUSHORT(count,s, string_len, line_len, in_string); /* number of tables */ + if( count == 9 ) { + sfnts_pputUSHORT(7,s, string_len, line_len, in_string); /* searchRange */ + sfnts_pputUSHORT(3,s, string_len, line_len, in_string); /* entrySelector */ + sfnts_pputUSHORT(81,s, string_len, line_len, in_string); /* rangeShift */ + } + else { + tqWarning("Fewer than 9 tables selected"); + } + + /* Now, emmit the table directory. */ + for(int x=0; x < 9; x++) { + if( tables[x].length == 0 ) /* Skip missing tables */ + continue; + + /* Name */ + sfnts_pputBYTE( table_names[x][0], s, string_len, line_len, in_string); + sfnts_pputBYTE( table_names[x][1], s, string_len, line_len, in_string); + sfnts_pputBYTE( table_names[x][2], s, string_len, line_len, in_string); + sfnts_pputBYTE( table_names[x][3], s, string_len, line_len, in_string); + + /* Checksum */ + sfnts_pputULONG( tables[x].checksum, s, string_len, line_len, in_string ); + + /* Offset */ + sfnts_pputULONG( tables[x].newoffset + 12 + (count * 16), s, + string_len, line_len, in_string ); + + /* Length */ + sfnts_pputULONG( tables[x].length, s, + string_len, line_len, in_string ); + } + + /* Now, send the tables */ + for(int x=0; x < 9; x++) { + if( tables[x].length == 0 ) /* skip tables that aren't there */ + continue; + + /* 'glyf' table gets special treatment */ + if( strcmp(table_names[x],"glyf")==0 ) { + sfnts_glyf_table(tables[x].oldoffset,tables[x].length, s, + string_len, line_len, in_string); + } else { // other tables should not exceed 64K (not always true; Sivan) + if( tables[x].length > 65535 ) { + tqWarning("TrueType font has a table which is too long"); + defective = TRUE; + return; + } + + /* Start new string if necessary. */ + sfnts_new_table(tables[x].length, s, + string_len, line_len, in_string); + + int font_off = tables[x].oldoffset; + /* Copy the bytes of the table. */ + for( int y=0; y < (int)tables[x].length; y++ ) { + c = offset_table[ font_off ]; + font_off++; + + sfnts_pputBYTE(c, s, string_len, line_len, in_string); + } + } + + /* Padd it out to a four byte boundary. */ + int y=tables[x].length; + while( (y % 4) != 0 ) { + sfnts_pputBYTE(0, s, string_len, line_len, in_string); + y++; + } + + } /* End of loop for all tables */ + + /* Close the array. */ + sfnts_end_string(s, string_len, line_len, in_string); + s << "]def\n"; +} +#endif + +// ****************** Type 3 CharProcs ******* + +/* +** This routine is used to break the character +** procedure up into a number of smaller +** procedures. This is necessary so as not to +** overflow the stack on certain level 1 interpreters. +** +** Prepare to push another item onto the stack, +** starting a new proceedure if necessary. +** +** Not all the stack depth calculations in this routine +** are perfectly accurate, but they do the job. +*/ +static int stack_depth = 0; +static void stack(int num_pts, int newnew, TQTextStream& s) +{ + if( num_pts > 25 ) { /* Only do something of we will */ + /* have a log of points. */ + if(stack_depth == 0) { + s << "{"; + stack_depth=1; + } + + stack_depth += newnew; /* Account for what we propose to add */ + + if(stack_depth > 100) { + s << "}_e{"; + stack_depth = 3 + newnew; /* A rough estimate */ + } + } +} + +static void stack_end(TQTextStream& s) /* called at end */ +{ + if(stack_depth) { + s << "}_e"; + stack_depth=0; + } +} + +// postscript drawing commands + +static void PSMoveto(FWord x, FWord y, TQTextStream& ts) +{ + ts << x; + ts << " "; + ts << y; + ts << " _m\n"; +} + +static void PSLineto(FWord x, FWord y, TQTextStream& ts) +{ + ts << x; + ts << " "; + ts << y; + ts << " _l\n"; +} + +/* Emmit a PostScript "curveto" command. */ +static void PSCurveto(FWord* xcoor, FWord* ycoor, + FWord x, FWord y, int s, int t, TQTextStream& ts) +{ + int N, i; + double sx[3], sy[3], cx[4], cy[4]; + + N = t-s+2; + for(i=0; inum_ctr; j++) + if (cd->check_ctr[j]==0 && cd->area_ctr[j] < 0) { + cd->check_ctr[j]=1; + return j; + } + + return NOMOREOUTCTR; +} /* end of nextoutctr() */ + +static int nextinctr(int co, int /*ci*/, charproc_data* cd) +{ + int j; + + for(j=0; jnum_ctr; j++) + if (cd->ctrset[2*j+1]==co) + if (cd->check_ctr[ cd->ctrset[2*j] ]==0) { + cd->check_ctr[ cd->ctrset[2*j] ]=1; + return cd->ctrset[2*j]; + } + + return NOMOREINCTR; +} + +static double intest( int co, int ci, charproc_data *cd ) +{ + int i, j, start, end; + double r1, r2; + FWord xi[3], yi[3]; + + j = start = ( co == 0 ) ? 0 : ( cd->epts_ctr[co - 1] + 1 ); + end = cd->epts_ctr[co]; + i = ( ci == 0 ) ? 0 : ( cd->epts_ctr[ci - 1] + 1 ); + xi[0] = cd->xcoor[i]; + yi[0] = cd->ycoor[i]; + r1 = sqr( cd->xcoor[start] - xi[0] ) + sqr( cd->ycoor[start] - yi[0] ); + + for ( i = start; i <= end; i++ ) { + r2 = sqr( cd->xcoor[i] - xi[0] ) + sqr( cd->ycoor[i] - yi[0] ); + if ( r2 < r1 ) { + r1 = r2; + j = i; + } + } + if ( j == start ) { + xi[1] = cd->xcoor[end]; + yi[1] = cd->ycoor[end]; + } else { + xi[1] = cd->xcoor[j - 1]; + yi[1] = cd->ycoor[j - 1]; + } + if ( j == end ) { + xi[2] = cd->xcoor[start]; + yi[2] = cd->ycoor[start]; + } else { + xi[2] = cd->xcoor[j + 1]; + yi[2] = cd->ycoor[j + 1]; + } + return area( xi, yi, 3 ); +} + +/* +** find the nearest out contour to a specified in contour. +*/ +static int nearout(int ci, charproc_data* cd) +{ + int k = 0; /* !!! is this right? */ + int co; + double a, a1=0; + + for (co=0; co < cd->num_ctr; co++) { + if(cd->area_ctr[co] < 0) { + a=intest(co,ci, cd); + if (a<0 && a1==0) { + k=co; + a1=a; + } + if(a<0 && a1!=0 && a>a1) { + k=co; + a1=a; + } + } + } + + return k; +} /* end of nearout() */ + + +/* +** We call this routine to emmit the PostScript code +** for the character we have loaded with load_char(). +*/ +static void PSConvert(TQTextStream& s, charproc_data* cd) +{ + int i,j,k,fst,start_offpt; + int end_offpt=0; + + cd->area_ctr = new double[cd->num_ctr]; + memset(cd->area_ctr, 0, (cd->num_ctr*sizeof(double))); + + cd->check_ctr = new char[cd->num_ctr]; + memset(cd->check_ctr, 0, (cd->num_ctr*sizeof(char))); + + cd->ctrset = new int[2*(cd->num_ctr)]; + memset(cd->ctrset, 0, (cd->num_ctr*2*sizeof(int))); + + cd->check_ctr[0]=1; + cd->area_ctr[0]=area(cd->xcoor, cd->ycoor, cd->epts_ctr[0]+1); + + for (i=1; inum_ctr; i++) + cd->area_ctr[i]=area(cd->xcoor+cd->epts_ctr[i-1]+1, + cd->ycoor+cd->epts_ctr[i-1]+1, + cd->epts_ctr[i]-cd->epts_ctr[i-1]); + + for (i=0; inum_ctr; i++) { + if (cd->area_ctr[i]>0) { + cd->ctrset[2*i]=i; + cd->ctrset[2*i+1]=nearout(i,cd); + } else { + cd->ctrset[2*i]=-1; + cd->ctrset[2*i+1]=-1; + } + } + + /* Step thru the coutours. */ + /* I believe that a contour is a detatched */ + /* set of curves and lines. */ + i=j=k=0; + while (i < cd->num_ctr ) { + fst = j = (k==0) ? 0 : (cd->epts_ctr[k-1]+1); + + /* Move to the first point on the contour. */ + stack(cd->num_pts,3,s); + PSMoveto(cd->xcoor[j],cd->ycoor[j],s); + start_offpt = 0; /* No off curve points yet. */ + + /* Step thru the remaining points of this contour. */ + for(j++; j <= cd->epts_ctr[k]; j++) { + if (!(cd->tt_flags[j]&1)) { /* Off curve */ + if (!start_offpt) + { start_offpt = end_offpt = j; } + else + end_offpt++; + } else { /* On Curve */ + if (start_offpt) { + stack(cd->num_pts,7,s); + PSCurveto(cd->xcoor,cd->ycoor, + cd->xcoor[j],cd->ycoor[j], + start_offpt,end_offpt,s); + start_offpt = 0; + } else { + stack(cd->num_pts,3,s); + PSLineto(cd->xcoor[j], cd->ycoor[j],s); + } + } + } + + /* Do the final curve or line */ + /* of this coutour. */ + if (start_offpt) { + stack(cd->num_pts,7,s); + PSCurveto(cd->xcoor,cd->ycoor, + cd->xcoor[fst],cd->ycoor[fst], + start_offpt,end_offpt,s); + } else { + stack(cd->num_pts,3,s); + PSLineto(cd->xcoor[fst],cd->ycoor[fst],s); + } + + k=nextinctr(i,k,cd); + + if (k==NOMOREINCTR) + i=k=nextoutctr(i,cd); + + if (i==NOMOREOUTCTR) + break; + } + + /* Now, we can fill the whole thing. */ + stack(cd->num_pts,1,s); + s << "_cl"; /* "closepath eofill" */ + + /* Free our work arrays. */ + delete [] cd->area_ctr; + delete [] cd->check_ctr; + delete [] cd->ctrset; +} + + +/* +** Load the simple glyph data pointed to by glyph. +** The pointer "glyph" should point 10 bytes into +** the glyph data. +*/ +void TQPSPrinterFontTTF::charprocLoad(BYTE *glyph, charproc_data* cd) +{ + int x; + BYTE c, ct; + + /* Read the contour endpoints list. */ + cd->epts_ctr = new int[cd->num_ctr]; + //cd->epts_ctr = (int *)myalloc(cd->num_ctr,sizeof(int)); + for (x = 0; x < cd->num_ctr; x++) { + cd->epts_ctr[x] = getUSHORT(glyph); + glyph += 2; + } + + /* From the endpoint of the last contour, we can */ + /* determine the number of points. */ + cd->num_pts = cd->epts_ctr[cd->num_ctr-1]+1; +#ifdef DEBUG_TRUETYPE + fprintf(stderr,"num_pts=%d\n",cd->num_pts); +#endif + + /* Skip the instructions. */ + x = getUSHORT(glyph); + glyph += 2; + glyph += x; + + /* Allocate space to hold the data. */ + //cd->tt_flags = (BYTE *)myalloc(num_pts,sizeof(BYTE)); + //cd->xcoor = (FWord *)myalloc(num_pts,sizeof(FWord)); + //cd->ycoor = (FWord *)myalloc(num_pts,sizeof(FWord)); + cd->tt_flags = new BYTE[cd->num_pts]; + cd->xcoor = new FWord[cd->num_pts]; + cd->ycoor = new FWord[cd->num_pts]; + + /* Read the flags array, uncompressing it as we go. */ + /* There is danger of overflow here. */ + for (x = 0; x < cd->num_pts; ) { + cd->tt_flags[x++] = c = *(glyph++); + + if (c&8) { /* If next byte is repeat count, */ + ct = *(glyph++); + + if( (x + ct) > cd->num_pts ) { + tqWarning("Fatal Error in TT flags"); + return; + } + + while (ct--) + cd->tt_flags[x++] = c; + } + } + + /* Read the x coordinates */ + for (x = 0; x < cd->num_pts; x++) { + if (cd->tt_flags[x] & 2) { /* one byte value with */ + /* external sign */ + c = *(glyph++); + cd->xcoor[x] = (cd->tt_flags[x] & 0x10) ? c : (-1 * (int)c); + } else if(cd->tt_flags[x] & 0x10) { /* repeat last */ + cd->xcoor[x] = 0; + } else { /* two byte signed value */ + cd->xcoor[x] = getFWord(glyph); + glyph+=2; + } + } + + /* Read the y coordinates */ + for(x = 0; x < cd->num_pts; x++) { + if (cd->tt_flags[x] & 4) { /* one byte value with */ + /* external sign */ + c = *(glyph++); + cd->ycoor[x] = (cd->tt_flags[x] & 0x20) ? c : (-1 * (int)c); + } else if (cd->tt_flags[x] & 0x20) { /* repeat last value */ + cd->ycoor[x] = 0; + } else { /* two byte signed value */ + cd->ycoor[x] = getUSHORT(glyph); + glyph+=2; + } + } + + /* Convert delta values to absolute values. */ + for(x = 1; x < cd->num_pts; x++) { + cd->xcoor[x] += cd->xcoor[x-1]; + cd->ycoor[x] += cd->ycoor[x-1]; + } + + for(x=0; x < cd->num_pts; x++) { + cd->xcoor[x] = topost(cd->xcoor[x]); + cd->ycoor[x] = topost(cd->ycoor[x]); + } +} + +#define ARG_1_AND_2_ARE_WORDS 1 +#define ARGS_ARE_XY_VALUES 2 +#define ROUND_XY_TO_GRID 4 +#define WE_HAVE_A_SCALE 8 +/* RESERVED 16 */ +#define MORE_COMPONENTS 32 +#define WE_HAVE_AN_X_AND_Y_SCALE 64 +#define WE_HAVE_A_TWO_BY_TWO 128 +#define WE_HAVE_INSTRUCTIONS 256 +#define USE_MY_METRICS 512 + +void TQPSPrinterFontTTF::subsetGlyph(int charindex,bool* glyphset) +{ + USHORT flags; + USHORT glyphIndex; + charproc_data cd; + + glyphset[charindex] = TRUE; + //printf("subsetting %s ==> ",glyphName(charindex).latin1()); + + /* Get a pointer to the data. */ + BYTE* glyph = charprocFindGlyphData( charindex ); + + /* If the character is blank, it has no bounding box, */ + /* otherwise read the bounding box. */ + if( glyph == (BYTE*)NULL ) { + cd.num_ctr=0; + } else { + cd.num_ctr = getSHORT(glyph); + /* Advance the pointer past bounding box. */ + glyph += 10; + } + + if( cd.num_ctr < 0 ) { // composite + /* Once around this loop for each component. */ + do { + flags = getUSHORT(glyph); /* read the flags word */ + glyph += 2; + glyphIndex = getUSHORT(glyph); /* read the glyphindex word */ + glyph += 2; + + glyphset[ glyphIndex ] = TRUE; + subsetGlyph( glyphIndex, glyphset ); + //printf("subset contains: %d %s ",glyphIndex, glyphName(glyphIndex).latin1()); + + if(flags & ARG_1_AND_2_ARE_WORDS) { + glyph += 2; + glyph += 2; + } else { + glyph += 1; + glyph += 1; + } + + if(flags & WE_HAVE_A_SCALE) { + glyph += 2; + } else if(flags & WE_HAVE_AN_X_AND_Y_SCALE) { + glyph += 2; + glyph += 2; + } else if(flags & WE_HAVE_A_TWO_BY_TWO) { + glyph += 2; + glyph += 2; + glyph += 2; + glyph += 2; + } else { + } + } while(flags & MORE_COMPONENTS); + } + //printf("\n"); +} + + +/* +** Emmit PostScript code for a composite character. +*/ +void TQPSPrinterFontTTF::charprocComposite(BYTE *glyph, TQTextStream& s, bool *glyphSet) +{ + USHORT flags; + USHORT glyphIndex; + int arg1; + int arg2; + float xscale = 1; + float yscale = 1; +#ifdef DEBUG_TRUETYPE + float scale01 = 0; + float scale10 = 0; +#endif + + /* Once around this loop for each component. */ + do { + flags = getUSHORT(glyph); /* read the flags word */ + glyph += 2; + + glyphIndex = getUSHORT(glyph); /* read the glyphindex word */ + glyph += 2; + + if(flags & ARG_1_AND_2_ARE_WORDS) { + /* The tt spec. seems to say these are signed. */ + arg1 = getSHORT(glyph); + glyph += 2; + arg2 = getSHORT(glyph); + glyph += 2; + } else { /* The tt spec. does not clearly indicate */ + /* whether these values are signed or not. */ + arg1 = (char)*(glyph++); + arg2 = (char)*(glyph++); + } + + if(flags & WE_HAVE_A_SCALE) { + xscale = yscale = f2dot14( getUSHORT(glyph) ); + glyph += 2; + } else if(flags & WE_HAVE_AN_X_AND_Y_SCALE) { + xscale = f2dot14( getUSHORT(glyph) ); + glyph += 2; + yscale = f2dot14( getUSHORT(glyph) ); + glyph += 2; + } else if(flags & WE_HAVE_A_TWO_BY_TWO) { + xscale = f2dot14( getUSHORT(glyph) ); + glyph += 2; +#ifdef DEBUG_TRUETYPE + scale01 = f2dot14( getUSHORT(glyph) ); +#endif + glyph += 2; +#ifdef DEBUG_TRUETYPE + scale10 = f2dot14( getUSHORT(glyph) ); +#endif + glyph += 2; + yscale = f2dot14( getUSHORT(glyph) ); + glyph += 2; + } + + /* Debugging */ +#ifdef DEBUG_TRUETYPE + s << "% flags=" << flags << ", arg1=" << arg1 << ", arg2=" << arg2 << ", xscale=" << xscale << ", yscale=" << yscale << + ", scale01=" << scale01 << ", scale10=" << scale10 << endl; +#endif + + + if ( (flags & ARGS_ARE_XY_VALUES) != ARGS_ARE_XY_VALUES ) { + s << "% unimplemented shift, arg1=" << arg1; + s << ", arg2=" << arg2 << "\n"; + arg1 = arg2 = 0; + } + + /* If we have an (X,Y) shif and it is non-zero, */ + /* translate the coordinate system. */ + if ( flags & (WE_HAVE_A_TWO_BY_TWO|WE_HAVE_AN_X_AND_Y_SCALE) ) { +#if 0 + // code similar to this would be needed for two_by_two + s << "gsave [ " << xscale << " " << scale01 << " " << scale10 << " " + << yscale << " " << topost(arg1) << " " << topost(arg2) << "] SM\n"; +#endif + if ( flags & WE_HAVE_A_TWO_BY_TWO ) + s << "% Two by two transformation, unimplemented\n"; + s << "gsave " << topost(arg1); + s << " " << topost(arg2); + s << " translate\n"; + s << xscale << " " << yscale << " scale\n"; + } else if ( flags & ARGS_ARE_XY_VALUES && ( arg1 != 0 || arg2 != 0 ) ) { + s << "gsave " << topost(arg1); + s << " " << topost(arg2); + s << " translate\n"; + } + + /* Invoke the CharStrings procedure to print the component. */ + s << "false CharStrings /"; + s << glyphName( glyphIndex, glyphSet ); + s << " get exec\n"; + + // printf("false CharStrings /%s get exec\n", + //ttfont_CharStrings_getname(font,glyphIndex)); + + /* If we translated the coordinate system, */ + /* put it back the way it was. */ + if( (flags & ARGS_ARE_XY_VALUES && (arg1 != 0 || arg2 != 0) ) || + ( flags & (WE_HAVE_A_TWO_BY_TWO|WE_HAVE_AN_X_AND_Y_SCALE) ) ) { + s << "grestore "; + } + } while (flags & MORE_COMPONENTS); +} + +/* +** Return a pointer to a specific glyph's data. +*/ +BYTE* TQPSPrinterFontTTF::charprocFindGlyphData(int charindex) +{ + ULONG off; + ULONG length; + + /* Read the glyph offset from the index to location table. */ + if(indexToLocFormat == 0) { + off = getUSHORT( loca_table + (charindex * 2) ); + off *= 2; + length = getUSHORT( loca_table + ((charindex+1) * 2) ); + length *= 2; + length -= off; + } else { + off = getULONG( loca_table + (charindex * 4) ); + length = getULONG( loca_table + ((charindex+1) * 4) ); + length -= off; + } + + if(length > 0) + return glyf_table + off; + else + return (BYTE*)NULL; +} + +void TQPSPrinterFontTTF::charproc(int charindex, TQTextStream& s, bool *glyphSet ) +{ + int llx,lly,urx,ury; + int advance_width; + charproc_data cd; + +#ifdef DEBUG_TRUETYPE + s << "% tt_type3_charproc for "; + s << charindex; + s << "\n"; +#endif + + /* Get a pointer to the data. */ + BYTE* glyph = charprocFindGlyphData( charindex ); + + /* If the character is blank, it has no bounding box, */ + /* otherwise read the bounding box. */ + if( glyph == (BYTE*)NULL ) { + llx=lly=urx=ury=0; /* A blank char has an all zero BoundingBox */ + cd.num_ctr=0; /* Set this for later if()s */ + } else { + /* Read the number of contours. */ + cd.num_ctr = getSHORT(glyph); + + /* Read PostScript bounding box. */ + llx = getFWord(glyph + 2); + lly = getFWord(glyph + 4); + urx = getFWord(glyph + 6); + ury = getFWord(glyph + 8); + + /* Advance the pointer. */ + glyph += 10; + } + + /* If it is a simple character, load its data. */ + if (cd.num_ctr > 0) + charprocLoad(glyph, &cd); + else + cd.num_pts=0; + + /* Consult the horizontal metrics table to determine */ + /* the character width. */ + if( charindex < numberOfHMetrics ) + advance_width = getuFWord( hmtx_table + (charindex * 4) ); + else + advance_width = getuFWord( hmtx_table + ((numberOfHMetrics-1) * 4) ); + + /* Execute setcachedevice in order to inform the font machinery */ + /* of the character bounding box and advance width. */ + stack(cd.num_pts,7,s); + s << topost(advance_width); + s << " 0 "; + s << topost(llx); + s << " "; + s << topost(lly); + s << " "; + s << topost(urx); + s << " "; + s << topost(ury); + s << " _sc\n"; + + /* If it is a simple glyph, convert it, */ + /* otherwise, close the stack business. */ + if( cd.num_ctr > 0 ) { // simple + PSConvert(s,&cd); + delete [] cd.tt_flags; + delete [] cd.xcoor; + delete [] cd.ycoor; + delete [] cd.epts_ctr; + } else if( cd.num_ctr < 0 ) { // composite + charprocComposite(glyph,s, glyphSet); + } + + stack_end(s); +} /* end of tt_type3_charproc() */ + + +// ================== PFA ==================== + +class TQPSPrinterFontPFA + : public TQPSPrinterFontPrivate { +public: + TQPSPrinterFontPFA(const TQFontEngine *f, TQByteArray& data); + virtual void download(TQTextStream& s, bool global); + virtual bool embedded() { return TRUE; } +private: + TQByteArray data; +}; + +TQPSPrinterFontPFA::TQPSPrinterFontPFA(const TQFontEngine *f, TQByteArray& d) +{ + data = d; + + int pos = 0; + char* p = data.data(); + TQString fontname; + + if (p[ pos ] != '%' || p[ pos+1 ] != '!') { // PFA marker + tqWarning("invalid pfa file"); + return; + } + + char* fontnameptr = strstr(p+pos,"/FontName"); + if (fontnameptr == NULL) + return; + + fontnameptr += strlen("/FontName") + 1; + while (*fontnameptr == ' ' || *fontnameptr == '/') fontnameptr++; + int l=0; + while (fontnameptr[l] != ' ') l++; + + psname = TQString::fromLatin1(fontnameptr,l); + replacementList = makePSFontNameList( f, psname ); +} + +void TQPSPrinterFontPFA::download(TQTextStream& s, bool global) +{ + emitPSFontNameList( s, psname, replacementList); + + if ( !embedFonts ) { + downloadMapping(s, global); + return; + } + + //tqDebug("downloading pfa font %s", psname.latin1() ); + char* p = data.data(); + + s << "% Font resource\n"; + for (int i=0; i < (int)data.size(); i++) s << p[i]; + s << "% End of font resource\n"; + downloadMapping( s, global ); +} + +// ================== PFB ==================== + +class TQPSPrinterFontPFB + : public TQPSPrinterFontPrivate { +public: + TQPSPrinterFontPFB(const TQFontEngine *f, TQByteArray& data); + virtual void download(TQTextStream& s, bool global); + virtual bool embedded() { return TRUE; } +private: + TQByteArray data; +}; + +TQPSPrinterFontPFB::TQPSPrinterFontPFB(const TQFontEngine *f, TQByteArray& d) +{ + data = d; + + int pos = 0; + int len; + // int typ; + unsigned char* p = (unsigned char*) data.data(); + TQString fontname; + + if (p[ pos ] != 0x80) { // PFB marker + tqWarning("pfb file does not start with 0x80"); + return; + } + pos++; + // typ = p[ pos ]; // 1=ascii 2=binary 3=done + pos++; + len = p[ pos ]; pos++; + len |= (p[ pos ] << 8) ; pos++; + len |= (p[ pos ] << 16); pos++; + len |= (p[ pos ] << 24); pos++; + + //printf("font block type %d len %d\n",typ,len); + + char* fontnameptr = strstr((char*)p+pos,"/FontName"); + if (fontnameptr == NULL) + return; + + fontnameptr += strlen("/FontName") + 1; + while (*fontnameptr == ' ' || *fontnameptr == '/') fontnameptr++; + int l=0; + while (fontnameptr[l] != ' ') l++; + + psname = TQString::fromLatin1(fontnameptr,l); + replacementList = makePSFontNameList( f, psname ); +} + +void TQPSPrinterFontPFB::download(TQTextStream& s, bool global) +{ + emitPSFontNameList( s, psname, replacementList); + + if ( !embedFonts ) { + downloadMapping(s, global); + return; + } + + //tqDebug("downloading pfb font %s", psname.latin1() ); + unsigned char* p = (unsigned char*) data.data(); + int pos; + int len; + int typ; + + int hexcol = 0; + int line_length = 64; + + s << "% Font resource\n"; + + pos = 0; + typ = -1; + while (typ != 3) { // not end of file + if (p[ pos ] != 0x80) // PFB marker + return; // pfb file does not start with 0x80 + pos++; + typ = p[ pos ]; // 1=ascii 2=binary 3=done + pos++; + + if (typ == 3) break; + + len = p[ pos ]; pos++; + len |= (p[ pos ] << 8) ; pos++; + len |= (p[ pos ] << 16); pos++; + len |= (p[ pos ] << 24); pos++; + + //tqDebug("font block type %d len %d",typ,len); + + int end = pos + len; + if (typ==1) { + while (pos < end) { + if (hexcol > 0) { + s << "\n"; + hexcol = 0; + } + //tqWarning(TQString::fromLatin1((char*)(p+pos),1)); + if (p[pos] == '\r' || p[pos] == '\n') { + s << "\n"; + while (pos < end && (p[pos] == '\r' || p[pos] == '\n')) + pos++; + } else { + s << TQString::fromLatin1((char*)(p+pos),1); + pos++; + } + } + } + if (typ==2) { + static const char *hexchar = "0123456789abcdef"; + while (pos < end) { + /* trim hexadecimal lines to line_length columns */ + if (hexcol >= line_length) { + s << "\n"; + hexcol = 0; + } + s << TQString::fromLatin1(hexchar+((p[pos] >> 4) & 0xf),1) + << TQString::fromLatin1(hexchar+((p[pos] ) & 0xf),1); + pos++; + hexcol += 2; + } + } + } + s << "% End of font resource\n"; + downloadMapping( s, global ); +} + +// ================== AFontFileNotFound ============ + + + +class TQPSPrinterFontNotFound + : public TQPSPrinterFontPrivate { +public: + TQPSPrinterFontNotFound(const TQFontEngine* f); + virtual void download(TQTextStream& s, bool global); +private: + TQByteArray data; +}; + +TQPSPrinterFontNotFound::TQPSPrinterFontNotFound(const TQFontEngine* f) +{ + psname = makePSFontName( f ); + replacementList = makePSFontNameList( f ); +} + +void TQPSPrinterFontNotFound::download(TQTextStream& s, bool) +{ + //tqDebug("downloading not found font %s", psname.latin1() ); + emitPSFontNameList( s, psname, replacementList ); + s << "% No embeddable font for "; + s << psname; + s << " found\n"; + TQPSPrinterFontPrivate::download(s, TRUE); +} + +#ifndef TQT_NO_TEXTCODEC +// =================== A font file for asian ============ + +class TQPSPrinterFontAsian + : public TQPSPrinterFontPrivate { +public: + TQPSPrinterFontAsian() + : TQPSPrinterFontPrivate(), codec( 0 ) {} + void download(TQTextStream& s, bool global); + TQString defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, + TQPSPrinterPrivate *d ); + void drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, + const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint ); + + TQString makePSFontName( const TQFontEngine *f, int type ) const; + virtual TQString extension() const = 0; + + TQTextCodec *codec; +}; + +TQString TQPSPrinterFontAsian::makePSFontName( const TQFontEngine *f, int type ) const +{ + TQString ps; + int i; + + TQString family = f->fontDef.family.lower(); + + // try to make a "good" postscript name + ps = family.simplifyWhiteSpace(); + i = 0; + while( (unsigned int)i < ps.length() ) { + if ( i != 0 && ps[i] == '[') { + if ( ps[i-1] == ' ' ) + ps.truncate (i-1); + else + ps.truncate (i); + break; + } + if ( i == 0 || ps[i-1] == ' ' ) { + ps[i] = ps[i].upper(); + if ( i ) + ps.remove( i-1, 1 ); + else + i++; + } else { + i++; + } + } + + switch ( type ) { + case 1: + ps.append( TQString::fromLatin1("-Italic") ); + break; + case 2: + ps.append( TQString::fromLatin1("-Bold") ); + break; + case 3: + ps.append( TQString::fromLatin1("-BoldItalic") ); + break; + case 0: + default: + break; + } + + ps += extension(); + + return ps; +} + + +TQString TQPSPrinterFontAsian::defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, + const TQString &key, TQPSPrinterPrivate *d) +{ + TQString fontName; + TQString fontName2; + + TQString *tmp = d->headerFontNames.find( ps ); + + if ( d->buffer ) { + if ( tmp ) { + fontName = *tmp; + } else { + fontName.sprintf( "F%d", ++d->headerFontNumber ); + d->fontStream << "/" << fontName << " false " << ps << "List MF\n"; + d->headerFontNames.insert( ps, new TQString( fontName ) ); + } + fontName2.sprintf( "F%d", ++d->headerFontNumber ); + d->fontStream << "/" << fontName2 << " " + << pointSize( f, d->scale ) << "/" << fontName << " DF\n"; + d->headerFontNames.insert( key, new TQString( fontName2 ) ); + } else { + if ( tmp ) { + fontName = *tmp; + } else { + fontName.sprintf( "F%d", ++d->pageFontNumber ); + stream << "/" << fontName << " false " << ps << "List MF\n"; + d->pageFontNames.insert( ps, new TQString( fontName ) ); + } + fontName2.sprintf( "F%d", ++d->pageFontNumber ); + stream << "/" << fontName2 << " " + << pointSize( f, d->scale ) << "/" << fontName << " DF\n"; + d->pageFontNames.insert( key, new TQString( fontName2 ) ); + } + return fontName2; +} + + +void TQPSPrinterFontAsian::download(TQTextStream& s, bool) +{ + //tqDebug("downloading asian font %s", psname.latin1() ); + s << "% Asian postscript font requested. Using " + << psname << endl; + emitPSFontNameList( s, psname, replacementList ); +} + +void TQPSPrinterFontAsian::drawText( TQTextStream &stream, const TQPoint &p, TQTextEngine *engine, int item, + const TQString &text, TQPSPrinterPrivate *d, TQPainter *paint) +{ + int len = engine->length( item ); + TQScriptItem &si = engine->items[item]; + + int x = p.x() + si.x; + int y = p.y() + si.y; + if ( y != d->textY || d->textY == 0 ) + stream << y << " Y"; + d->textY = y; + + TQString mdf; + if ( paint->font().underline() ) + mdf += " " + TQString().setNum( y + d->fm.underlinePos() + d->fm.lineWidth() ) + + " " + toString( d->fm.lineWidth() ) + " Tl"; + if ( paint->font().strikeOut() ) + mdf += " " + TQString().setNum( y + d->fm.strikeOutPos() ) + + " " + toString( d->fm.lineWidth() ) + " Tl"; + TQCString mb; + TQCString out; + TQString dummy( TQChar(0x20) ); + + if ( si.analysis.bidiLevel % 2 ) { + for ( int i = len-1; i >= 0; i-- ) { + TQChar ch = text.unicode()[i]; + if ( !ch.row() ) { + ; // ignore, we should never get here anyway + } else { + if ( codec ) { + dummy[0] = ch; + mb = codec->fromUnicode( dummy ); + } else + mb = " "; + + for ( unsigned int j = 0; j < mb.length (); j++ ) { + if ( mb.at(j) == '(' || mb.at(j) == ')' || mb.at(j) == '\\' ) + out += "\\"; + out += mb.at(j); + } + } + } + } else { + for ( int i = 0; i < len; i++ ) { + TQChar ch = text.unicode()[i]; + if ( !ch.row() ) { + ; // ignore, we should never get here anyway + } else { + if ( codec ) { + dummy[0] = ch; + mb = codec->fromUnicode( dummy ); + } else + mb = " "; + + for ( unsigned int j = 0; j < mb.length (); j++ ) { + if ( mb.at(j) == '(' || mb.at(j) == ')' || mb.at(j) == '\\' ) + out += "\\"; + out += mb.at(j); + } + } + } + } + stream << "(" << out << ")" << si.width << " " << x << mdf << " AT\n"; +} + +// ----------- Japanese -------------- + +static const psfont Japanese1 [] = { + { "Ryumin-Light-H", 0, 100. }, + { "Ryumin-Light-H", 0.2, 100. }, + { "GothicBBB-Medium-H", 0, 100. }, + { "GothicBBB-Medium-H", 0.2, 100. } +}; + +static const psfont Japanese1a [] = { + { "GothicBBB-Medium-H", 0, 100. }, + { "GothicBBB-Medium-H", 0.2, 100. }, + { "Ryumin-Light-H", 0, 100. }, + { "Ryumin-Light-H", 0.2, 100. } +}; + +static const psfont Japanese2 [] = { + { "GothicBBB-Medium-H", 0, 100. }, + { "GothicBBB-Medium-H", 0.2, 100. }, + { "GothicBBB-Medium-H", 0, 100. }, + { "GothicBBB-Medium-H", 0.2, 100. } +}; + +static const psfont Japanese2a [] = { + { "Ryumin-Light-H", 0, 100. }, + { "Ryumin-Light-H", 0.2, 100. }, + { "Ryumin-Light-H", 0, 100. }, + { "Ryumin-Light-H", 0.2, 100. } +}; + + +// Wadalab fonts + +static const psfont WadaMin [] = { + { "WadaMin-Regular-H", 0, 100. }, + { "WadaMin-Regular-H", 0.2, 100. }, + { "WadaMin-Bold-H", 0, 100. }, + { "WadaMin-Bold-H", 0.2, 100. } +}; + +static const psfont WadaGo [] = { + { "WadaMaruGo-Regular-H", 0, 100. }, + { "WadaMaruGo-Regular-H", 0.2, 100. }, + { "WadaGo-Bold-H", 0, 100. }, + { "WadaGo-Bold-H", 0.2, 100. } +}; + +// Adobe Wadalab + +static const psfont WadaGoAdobe [] = { + { "WadaMaruGo-RegularH-Hojo-H", 0, 100. }, + { "WadaMaruGo-RegularH-Hojo-H", 0.2, 100. }, + { "WadaMaruGo-RegularH-Hojo-H", 0, 100. }, + { "WadaMaruGo-RegularH-Hojo-H", 0.2, 100. }, +}; +static const psfont WadaMinAdobe [] = { + { "WadaMin-RegularH-Hojo-H", 0, 100. }, + { "WadaMin-RegularH-Hojo-H", 0.2, 100. }, + { "WadaMin-RegularH-Hojo-H", 0, 100. }, + { "WadaMin-RegularH-Hojo-H", 0.2, 100. }, +}; + + +static const psfont * const Japanese1Replacements[] = { + Japanese1, Japanese1a, WadaMin, WadaGo, WadaMinAdobe, WadaGoAdobe, 0 +}; +static const psfont * const Japanese2Replacements[] = { + Japanese2, Japanese2a, WadaMin, WadaGo, WadaMinAdobe, WadaGoAdobe, 0 +}; + +class TQPSPrinterFontJapanese + : public TQPSPrinterFontAsian { +public: + TQPSPrinterFontJapanese(const TQFontEngine* f); + virtual TQString extension() const; +}; + +TQPSPrinterFontJapanese::TQPSPrinterFontJapanese(const TQFontEngine* f) +{ + codec = TQTextCodec::codecForMib( 63 ); // jisx0208.1983-0 + + int type = getPsFontType( f ); + psname = makePSFontName( f, type ); + TQString best = "[ /" + psname + " 1.0 0.0 ]"; + replacementList.append( best ); + + const psfont *const *replacements = ( psname.contains( "Helvetica" ) ? Japanese2Replacements : Japanese1Replacements ); + appendReplacements( replacementList, replacements, type ); +} + +TQString TQPSPrinterFontJapanese::extension() const +{ + return "-H"; +} + +// ----------- Korean -------------- + +// sans serif +static const psfont SMGothic [] = { + { "SMGothic-Medium-KSC-EUC-H", 0, 100. }, + { "SMGothic-Medium-KSC-EUC-H", 0.2, 100. }, + { "SMGothic-DemiBold-KSC-EUC-H", 0, 100. }, + { "SMGothic-DemiBold-KSC-EUC-H", 0.2, 100. } +}; + +// serif +#if 0 // ### this is never used? +static const psfont SMMyungjo [] = { + { "SMMyungjo-Light-KSC-EUC-H", 0, 100. }, + { "SMMyungjo-Light-KSC-EUC-H", 0.2, 100. }, + { "SMMyungjo-Bold-KSC-EUC-H", 0, 100. }, + { "SMMyungjo-Bold-KSC-EUC-H", 0.2, 100. } +}; +#endif + +static const psfont MKai [] = { + { "MingMT-Light-KSC-EUC-H", 0, 100. }, + { "MingMT-Light-KSC-EUC-H", 0.2, 100. }, + { "MKai-Medium-KSC-EUC-H", 0, 100. }, + { "MKai-Medium-KSC-EUC-H", 0.2, 100. }, +}; + + +static const psfont Munhwa [] = { + { "Munhwa-Regular-KSC-EUC-H", 0, 100. }, + { "Munhwa-Regular-KSC-EUC-H", 0.2, 100. }, + { "Munhwa-Bold-KSC-EUC-H", 0, 100. }, + { "Munhwa-Bold-KSC-EUC-H", 0.2, 100. } +}; + +static const psfont MunhwaGothic [] = { + { "MunhwaGothic-Regular-KSC-EUC-H", 0, 100. }, + { "MunhwaGothic-Regular-KSC-EUC-H", 0.2, 100. }, + { "MunhwaGothic-Bold-KSC-EUC-H", 0, 100. }, + { "MunhwaGothic-Bold-KSC-EUC-H", 0.2, 100. } +}; + +static const psfont MunhwaGungSeo [] = { + { "MunhwaGungSeo-Light-KSC-EUC-H", 0, 100. }, + { "MunhwaGungSeo-Light-KSC-EUC-H", 0.2, 100. }, + { "MunhwaGungSeo-Bold-KSC-EUC-H", 0, 100. }, + { "MunhwaGungSeo-Bold-KSC-EUC-H", 0.2, 100. } +}; + +static const psfont MunhwaGungSeoHeulim [] = { + { "MunhwaGungSeoHeulim-Light-KSC-EUC-H", 0, 100. }, + { "MunhwaGungSeoHeulim-Light-KSC-EUC-H", 0.2, 100. }, + { "MunhwaGungSeoHeulim-Bold-KSC-EUC-H", 0, 100. }, + { "MunhwaGungSeoHeulim-Bold-KSC-EUC-H", 0.2, 100. } +}; + +static const psfont MunhwaHoonMin [] = { + { "MunhwaHoonMin-Regular-KSC-EUC-H", 0, 100. }, + { "MunhwaHoonMin-Regular-KSC-EUC-H", 0.2, 100. }, + { "MunhwaHoonMin-Regular-KSC-EUC-H", 0, 100. }, + { "MunhwaHoonMin-Regular-KSC-EUC-H", 0.2, 100. } +}; + +static const psfont BaekmukGulim [] = { + { "Baekmuk-Gulim-KSC-EUC-H", 0, 100. }, + { "Baekmuk-Gulim-KSC-EUC-H", 0.2, 100. }, + { "Baekmuk-Gulim-KSC-EUC-H", 0, 100. }, + { "Baekmuk-Gulim-KSC-EUC-H", 0.2, 100. } +}; + +static const psfont * const KoreanReplacements[] = { + BaekmukGulim, SMGothic, Munhwa, MunhwaGothic, MKai, MunhwaGungSeo, + MunhwaGungSeoHeulim, MunhwaHoonMin, Helvetica, 0 +}; + +class TQPSPrinterFontKorean + : public TQPSPrinterFontAsian { +public: + TQPSPrinterFontKorean(const TQFontEngine* f); + TQString extension() const; +}; + +TQPSPrinterFontKorean::TQPSPrinterFontKorean(const TQFontEngine* f) +{ + codec = TQTextCodec::codecForMib( 38 ); // eucKR + int type = getPsFontType( f ); + psname = makePSFontName( f, type ); + TQString best = "[ /" + psname + " 1.0 0.0 ]"; + replacementList.append( best ); + appendReplacements( replacementList, KoreanReplacements, type ); +} + +TQString TQPSPrinterFontKorean::extension() const +{ + return "-KSC-EUC-H"; +} +// ----------- traditional chinese ------------ + +// Arphic Public License Big5 TrueType fonts (on Debian and CLE and others) +static const psfont ShanHeiSun [] = { + { "ShanHeiSun-Light-ETen-B5-H", 0, 100. }, + { "ShanHeiSun-Light-ETen-B5-H", 0.2, 100. }, + { "ShanHeiSun-Light-ETen-B5-H", 0, 100. }, + { "ShanHeiSun-Light-ETen-B5-H", 0.2, 100. }, +}; +static const psfont ZenKai [] = { + { "ZenKai-Medium-ETen-B5-H", 0, 100. }, + { "ZenKai-Medium-Italic-ETen-B5-H", 0.2, 100. }, + { "ZenKai-Medium-Bold-ETen-B5-H", 0, 100. }, + { "ZenKai-Medium-BoldItalic-ETen-B5-H", 0.2, 100. }, +}; + +// Fonts on Turbolinux +static const psfont SongB5 [] = { + { "B5-MSung-Light-ETen-B5-H", 0, 100. }, + { "B5-MSung-Italic-ETen-B5-H", 0, 100. }, + { "B5-MSung-Bold-ETen-B5-H", 0, 100. }, + { "B5-MSung-BoldItalic-ETen-B5-H", 0, 100. }, +}; +static const psfont KaiB5 [] = { + { "B5-MKai-Medium-ETen-B5-H", 0, 100. }, + { "B5-MKai-Italic-ETen-B5-H", 0, 100. }, + { "B5-MKai-Bold-ETen-B5-H", 0, 100. }, + { "B5-MKai-BoldItalic-ETen-B5-H", 0, 100. }, +}; +static const psfont HeiB5 [] = { + { "B5-MHei-Medium-ETen-B5-H", 0, 100. }, + { "B5-MHei-Italic-ETen-B5-H", 0, 100. }, + { "B5-MHei-Bold-ETen-B5-H", 0, 100. }, + { "B5-MHei-BoldItalic-ETen-B5-H", 0, 100. }, +}; +static const psfont FangSongB5 [] = { + { "B5-CFangSong-Light-ETen-B5-H", 0, 100. }, + { "B5-CFangSong-Italic-ETen-B5-H", 0, 100. }, + { "B5-CFangSong-Bold-ETen-B5-H", 0, 100. }, + { "B5-CFangSong-BoldItalic-ETen-B5-H", 0, 100. }, +}; + +// Arphic fonts on Thiz Linux +static const psfont LinGothic [] = { + { "LinGothic-Light-ETen-B5-H", 0, 100. }, + { "LinGothic-Light-Italic-ETen-B5-H", 0.2, 100. }, + { "LinGothic-Light-Bold-ETen-B5-H", 0, 100. }, + { "LinGothic-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, +}; +static const psfont YenRound [] = { + { "YenRound-Light-ETen-B5-H", 0, 100. }, + { "YenRound-Light-Italic-ETen-B5-H", 0.2, 100. }, + { "YenRound-Light-Bold-ETen-B5-H", 0, 100. }, + { "YenRound-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, +}; + +// Dr. Wang Hann-Tzong's GPL'ed Big5 TrueType fonts +#if 0 // ### this is never used? +static const psfont HtWFangSong [] = { + { "HtW-FSong-Light-ETen-B5-H", 0, 100. }, + { "HtW-FSong-Light-Italic-ETen-B5-H", 0.2, 100. }, + { "HtW-FSong-Light-Bold-ETen-B5-H", 0, 100. }, + { "HtW-FSong-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, +}; +#endif + +static const psfont MingB5 [] = { + { "Ming-Light-ETen-B5-H", 0, 100. }, + { "Ming-Light-Italic-ETen-B5-H", 0.2, 100. }, + { "Ming-Light-Bold-ETen-B5-H", 0, 100. }, + { "Ming-Light-BoldItalic-ETen-B5-H", 0.2, 100. }, +}; + +// Microsoft's Ming/Sung font? +static const psfont MSung [] = { + { "MSung-Light-ETenms-B5-H", 0, 100. }, + { "MSung-Light-ETenms-B5-H", 0.2, 100. }, + { "MSung-Light-ETenms-B5-H", 0, 100. }, + { "MSung-Light-ETenms-B5-H", 0.2, 100. }, +}; +// "Standard Sung/Ming" font by Taiwan Ministry of Education +static const psfont MOESung [] = { + { "MOESung-Regular-B5-H", 0, 100. }, + { "MOESung-Regular-B5-H", 0.2, 100. }, + { "MOESung-Regular-B5-H", 0, 100. }, + { "MOESung-Regular-B5-H", 0.2, 100. }, +}; + +static const psfont MOEKai [] = { + { "MOEKai-Regular-B5-H", 0, 100. }, + { "MOEKai-Regular-B5-H", 0.2, 100. }, + { "MOEKai-Regular-B5-H", 0, 100. }, + { "MOEKai-Regular-B5-H", 0.2, 100. }, +}; + +static const psfont * const TraditionalReplacements[] = { + MOESung, SongB5, ShanHeiSun, MingB5, MSung, FangSongB5, KaiB5, ZenKai, HeiB5, + LinGothic, YenRound, MOEKai, Helvetica, 0 + }; + +#if 0 // ### these are never used? +static const psfont * const SongB5Replacements[] = { + SongB5, ShanHeiSun, MingB5, MSung, MOESung, Helvetica, 0 + }; + +static const psfont * const FangSongB5Replacements[] = { + FangSongB5, HtWFangSong, Courier, 0 + }; +static const psfont * const KaiB5Replacements[] = { + KaiB5, ZenKai, Times, 0 + }; +static const psfont * const HeiB5Replacements[] = { + HeiB5, LinGothic, YenRound, LucidaSans, 0 + }; +static const psfont * const YuanB5Replacements[] = { + YenRound, LinGothic, HeiB5, LucidaSans, 0 + }; +#endif + + +class TQPSPrinterFontTraditionalChinese + : public TQPSPrinterFontAsian { +public: + TQPSPrinterFontTraditionalChinese(const TQFontEngine* f); + TQString extension() const; +}; + +TQPSPrinterFontTraditionalChinese::TQPSPrinterFontTraditionalChinese(const TQFontEngine* f) +{ + codec = TQTextCodec::codecForMib( 2026 ); // Big5-0 + int type = getPsFontType( f ); + psname = makePSFontName( f, type ); + TQString best = "[ /" + psname + " 1.0 0.0 ]"; + replacementList.append( best ); + appendReplacements( replacementList, TraditionalReplacements, type ); +} + +TQString TQPSPrinterFontTraditionalChinese::extension() const +{ + return "-ETen-B5-H"; +} + +// ----------- simplified chinese ------------ + +#if 0 +// GB18030 fonts on XteamLinux (?) +static const psfont SimplifiedGBK2K [] = { + { "MSung-Light-GBK2K-H", 0, 100. }, + { "MSung-Light-GBK2K-H", 0.2, 100. }, + { "MKai-Medium-GBK2K-H", 0, 100. }, + { "MKai-Medium-GBK2K-H", 0.2, 100. }, +}; +#endif + +// GB18030 fonts on Turbolinux +static const psfont SongGBK2K [] = { + { "MSung-Light-GBK2K-H", 0, 100. }, + { "MSung-Italic-GBK2K-H", 0, 100. }, + { "MSung-Bold-GBK2K-H", 0, 100. }, + { "MSung-BoldItalic-GBK2K-H", 0, 100. }, +}; +static const psfont KaiGBK2K [] = { + { "MKai-Medium-GBK2K-H", 0, 100. }, + { "MKai-Italic-GBK2K-H", 0, 100. }, + { "MKai-Bold-GBK2K-H", 0, 100. }, + { "MKai-BoldItalic-GBK2K-H", 0, 100. }, +}; +static const psfont HeiGBK2K [] = { + { "MHei-Medium-GBK2K-H", 0, 100. }, + { "MHei-Italic-GBK2K-H", 0, 100. }, + { "MHei-Bold-GBK2K-H", 0, 100. }, + { "MHei-BoldItalic-GBK2K-H", 0, 100. }, +}; +static const psfont FangSongGBK2K [] = { + { "CFangSong-Light-GBK2K-H", 0, 100. }, + { "CFangSong-Italic-GBK2K-H", 0, 100. }, + { "CFangSong-Bold-GBK2K-H", 0, 100. }, + { "CFangSong-BoldItalic-GBK2K-H", 0, 100. }, +}; + +static const psfont Simplified [] = { + { "MSung-Light-GBK-EUC-H", 0, 100. }, + { "MSung-Light-GBK-EUC-H", 0.2, 100. }, + { "MKai-Medium-GBK-EUC-H", 0, 100. }, + { "MKai-Medium-GBK-EUC-H", 0.2, 100. }, +}; + +static const psfont MSungGBK [] = { + { "MSung-Light-GBK-EUC-H", 0, 100. }, + { "MSung-Light-GBK-EUC-H", 0.2, 100. }, + { "MSung-Light-GBK-EUC-H", 0, 100. }, + { "MSung-Light-GBK-EUC-H", 0.2, 100. }, +}; + +static const psfont FangSong [] = { + { "CFangSong-Light-GBK-EUC-H", 0, 100. }, + { "CFangSong-Light-GBK-EUC-H", 0.2, 100. }, + { "CFangSong-Light-GBK-EUC-H", 0, 100. }, + { "CFangSong-Light-GBK-EUC-H", 0.2, 100. }, +}; + +// Arphic Public License GB2312 TrueType fonts (on Debian and CLE and others) +static const psfont BousungEG [] = { + { "BousungEG-Light-GB-GB-EUC-H", 0, 100. }, + { "BousungEG-Light-GB-GB-EUC-H", 0.2, 100. }, + { "BousungEG-Light-GB-Bold-GB-EUC-H", 0, 100. }, + { "BousungEG-Light-GB-Bold-GB-EUC-H", 0.2, 100. }, +}; +static const psfont GBZenKai [] = { + { "GBZenKai-Medium-GB-GB-EUC-H", 0, 100. }, + { "GBZenKai-Medium-GB-GB-EUC-H", 0.2, 100. }, + { "GBZenKai-Medium-GB-Bold-GB-EUC-H", 0, 100. }, + { "GBZenKai-Medium-GB-Bold-GB-EUC-H", 0.2, 100. }, +}; + +static const psfont * const SimplifiedReplacements[] = { + SongGBK2K, FangSongGBK2K, KaiGBK2K, HeiGBK2K, + Simplified, MSungGBK, FangSong, BousungEG, GBZenKai, Helvetica, 0 + }; +#if 0 +static const psfont * const SongGBK2KReplacements[] = { + SongGBK2K, MSungGBK, BousungEG, Helvetica, 0 + }; +#endif +static const psfont * const FangSongGBK2KReplacements[] = { + FangSongGBK2K, FangSong, Courier, 0 + }; +static const psfont * const KaiGBK2KReplacements[] = { + KaiGBK2K, GBZenKai, Times, 0 + }; +static const psfont * const HeiGBK2KReplacements[] = { + HeiGBK2K, LucidaSans, 0 + }; + +class TQPSPrinterFontSimplifiedChinese + : public TQPSPrinterFontAsian { +public: + TQPSPrinterFontSimplifiedChinese(const TQFontEngine* f); + TQString extension() const; +}; + +TQPSPrinterFontSimplifiedChinese::TQPSPrinterFontSimplifiedChinese(const TQFontEngine* f) +{ + codec = TQTextCodec::codecForMib( 114 ); // GB18030 + int type = getPsFontType( f ); + TQString family = f->fontDef.family.lower(); + if( family.contains("kai",FALSE) ) { + psname = KaiGBK2K[type].psname; + appendReplacements( replacementList, KaiGBK2KReplacements, type ); + } else if( family.contains("fangsong",FALSE) ) { + psname = FangSongGBK2K[type].psname; + appendReplacements( replacementList, FangSongGBK2KReplacements, type ); + } else if( family.contains("hei",FALSE) ) { + psname = HeiGBK2K[type].psname; + appendReplacements( replacementList, HeiGBK2KReplacements, type ); + } else { + psname = SongGBK2K[type].psname; + appendReplacements( replacementList, SimplifiedReplacements, type ); + } + //tqDebug("simplified chinese: fontname is %s, psname=%s", f.family().latin1(), psname.latin1() ); +} + +TQString TQPSPrinterFontSimplifiedChinese::extension() const +{ + return "-GBK2K-H"; +} + +#endif + + +// ================== TQPSPrinterFont ==================== + +class TQPSPrinterFont { +public: + TQPSPrinterFont(const TQFont& f, int script, TQPSPrinterPrivate *priv); + ~TQPSPrinterFont(); + TQString postScriptFontName() { return p->postScriptFontName(); } + TQString defineFont( TQTextStream &stream, const TQString &ps, const TQFont &f, const TQString &key, + TQPSPrinterPrivate *d ) + { return p->defineFont( stream, ps, f, key, d ); } + void download(TQTextStream& s, bool global) { p->download(s, global); } + TQPSPrinterFontPrivate *handle() { return p; } + TQString xfontname; +private: + TQByteArray data; + TQPSPrinterFontPrivate* p; +}; + +TQPSPrinterFont::~TQPSPrinterFont() +{ + // the dict in TQFontPrivate does deletion for us. + // delete p; +} + + +TQPSPrinterFont::TQPSPrinterFont(const TQFont &f, int script, TQPSPrinterPrivate *priv) + : p(0) +{ + TQString fontfilename; + TQString fontname; + + enum { NONE, PFB, PFA, TTF } type = NONE; + + TQFontEngine *engine = f.d->engineForScript( (TQFont::Script) script ); + xfontname = makePSFontName( engine ); + +#if defined( TQ_WS_X11 ) + bool xlfd = FALSE; + //tqDebug("engine = %p name=%s, script=%d", engine, engine ? engine->name() : "(null)", script); + +#ifndef TQT_NO_XFTFREETYPE + if ( tqt_has_xft && engine && engine->type() == TQFontEngine::Xft ) { + XftPattern *pattern = static_cast( engine )->pattern(); + char *filename = 0; + XftPatternGetString (pattern, XFT_FILE, 0, &filename); + //tqDebug("filename for font is '%s'", filename); + if ( filename ) { + fontfilename = TQString::fromLocal8Bit( filename ); + xfontname = fontfilename; + } + } else +#endif + { + TQString rawName; + if ( engine && engine != (TQFontEngine *)-1 ) + rawName = engine->name(); + int index = rawName.find('-'); + if (index == 0) { + // this is an XLFD font name + for (int i=0; i < 6; i++) { + index = rawName.find('-',index+1); + } + xfontname = rawName.mid(0,index); + if ( xfontname.endsWith( "*" ) ) + xfontname.truncate( xfontname.length() - 1 ); + xlfd = TRUE; + } + } +#endif // TQ_WS_X11 +#ifndef TQT_NO_TEXTCODEC + // map some scripts to something more useful + if ( script == TQFont::Han ) { + TQTextCodec *lc = TQTextCodec::codecForLocale(); + switch( lc->mibEnum() ) { + case 36: // KS C 5601 + case 38: // EUC KR + script = TQFont::Hangul; + break; + + case 57: // gb2312.1980-0 + case 113: // GBK + case -113: // gbk-0 + case 114: // GB18030 + case -114: // gb18030-0 + case 2025: // GB2312 + case 2026: // Big5 + case -2026: // Big5-HKSCS + case 2101: // big5-0, big5.eten-0 + case -2101: // big5hkscs-0, hkscs-1 + break; + + case 16: // JIS7 + case 17: // SJIS + case 18: // EUC JP + case 63: // JIS X 0208 + default: + script = TQFont::Hiragana; + break; + } + } else if ( script == TQFont::Katakana ) + script = TQFont::Hiragana; + else if ( script == TQFont::Bopomofo ) + script = TQFont::Han; +#endif + + TQString searchname = xfontname; +#if defined(TQ_WS_X11) + // we need an extension here due to the fact that we use different + // fonts for different scripts + if ( xlfd && script >= TQFont::Han && script <= TQFont::Bopomofo ) + xfontname += "/" + toString( script ); +#endif + + //tqDebug("looking for font %s in dict", xfontname.latin1() ); + p = priv->fonts.find(xfontname); + if ( p ) + return; + +#if defined(TQ_WS_X11) + if ( xlfd ) { + + for (TQStringList::Iterator it=priv->fontpath.begin(); it!=priv->fontpath.end() && fontfilename.isEmpty(); ++it) { + if ((*it).left(1) != "/") continue; // not a path name, a font server + TQString fontmapname; + int num = 0; + // search font.dir and font.scale for the right file + while ( num < 2 ) { + if ( num == 0 ) + fontmapname = (*it) + "/fonts.scale"; + else + fontmapname = (*it) + "/fonts.dir"; + //tqWarning(fontmapname); + TQFile fontmap(fontmapname); + if (fontmap.open(IO_ReadOnly)) { + while (!fontmap.atEnd()) { + TQString mapping; + fontmap.readLine(mapping,512); + // fold to lower (since X folds to lowercase) + //tqWarning(xfontname); + //tqWarning(mapping); + if (mapping.lower().contains(searchname.lower())) { + int index = mapping.find(' ',0); + TQString ffn = mapping.mid(0,index); + // remove the most common bitmap formats + if( !ffn.contains( ".pcf" ) && !ffn.contains( ".bdf" ) && + !ffn.contains( ".spd" ) && !ffn.contains( ".phont" ) ) { + fontfilename = (*it) + TQString("/") + ffn; + if ( TQFile::exists(fontfilename) ) { + //tqDebug("found font file %s", fontfilename.latin1()); + break; + } else // unset fontfilename + fontfilename = TQString(); + } + } + } + fontmap.close(); + } + num++; + } + } + } +#endif + + //tqDebug("font=%s, fontname=%s, file=%s, p=%p", f.family().latin1(), xfontname.latin1(), fontfilename.latin1(), p); + + // memory mapping would be better here + if (fontfilename.length() > 0) { // maybe there is no file name + TQFile fontfile(fontfilename); + if ( fontfile.exists() ) { + //printf("font name %s size = %d\n",fontfilename.latin1(),fontfile.size()); + data = TQByteArray( fontfile.size() ); + + fontfile.open(IO_Raw | IO_ReadOnly); + fontfile.readBlock(data.data(), fontfile.size()); + fontfile.close(); + } + } + + if (!data.isNull() && data.size() > 0) { + unsigned char* d = (unsigned char *)data.data(); + if (d[0] == 0x80 && d[1] == 0x01 && d[6] == '%' && d[7] == '!') + type = PFB; + else if (d[0] == '%' && d[1] == '!' && d[2] == 'P' && d[3] == 'S') + type = PFA; + else if (d[0]==0x00 && d[1]==0x01 && d[2]==0x00 && d[3]==0x00) + type = TTF; + else + type = NONE; + } else + type = NONE; + + //tqDebug("font is of type %d", type ); + switch (type) { + case TTF : + p = new TQPSPrinterFontTTF(engine, data); + break; + case PFB: + p = new TQPSPrinterFontPFB(engine, data); + break; + case PFA: + p = new TQPSPrinterFontPFA(engine, data); + break; + case NONE: + default: + +#ifndef TQT_NO_TEXTCODEC + + if ( script == TQFont::Hiragana ) + p = new TQPSPrinterFontJapanese( engine ); + else if ( script == TQFont::Hangul ) + p = new TQPSPrinterFontKorean( engine ); + else if ( script == TQFont::Han ) { + TQTextCodec *lc = TQTextCodec::codecForLocale(); + switch( lc->mibEnum() ) { + case 2025: // GB2312 + case 57: // gb2312.1980-0 + case 113: // GBK + case -113: // gbk-0 + case 114: // GB18030 + case -114: // gb18030-0 + p = new TQPSPrinterFontSimplifiedChinese( engine ); + break; + case 2026: // Big5 + case -2026: // big5-0, big5.eten-0 + case 2101: // Big5-HKSCS + case -2101: // big5hkscs-0, hkscs-1 + p = new TQPSPrinterFontTraditionalChinese( engine ); + break; + default: + p = new TQPSPrinterFontJapanese( engine ); + } + } else +#endif + //tqDebug("didnt find font for %s", xfontname.latin1()); + p = new TQPSPrinterFontNotFound( engine ); + break; + } + + if (p->postScriptFontName() == "Symbol") + p->setSymbol(); + + // this is needed to make sure we don't get the same postscriptname twice + TQDictIterator it( priv->fonts ); + for( it.toFirst(); it.current(); ++it ) { + if ( *(*it) == *p ) { +// tqWarning("Post script driver: font already in dict"); + delete p; + p = *it; + return; + } + } + + //tqDebug("inserting font %s in dict psname=%s", xfontname.latin1(), p->postScriptFontName().latin1() ); + priv->fonts.insert( xfontname, p ); +} + +// ================= END OF PS FONT METHODS ============ + + +TQPSPrinterPrivate::TQPSPrinterPrivate( TQPrinter *prt, int filedes ) + : buffer( 0 ), outDevice( 0 ), fd( filedes ), pageBuffer( 0 ), fonts(27, FALSE), fontBuffer(0), savedImage( 0 ), + dirtypen( FALSE ), dirtybrush( FALSE ), dirtyBkColor( FALSE ), bkMode( TQt::TransparentMode ), dirtyBkMode( FALSE ), +#ifndef TQT_NO_TEXTCODEC + currentFontCodec( 0 ), +#endif + fm( TQFont() ), textY( 0 ) +{ + printer = prt; + headerFontNames.setAutoDelete( TRUE ); + pageFontNames.setAutoDelete( TRUE ); + fonts.setAutoDelete( TRUE ); + currentFontFile = 0; + scale = 1.; + scriptUsed = -1; + +#ifdef TQ_WS_X11 + // append tqsettings fontpath + TQSettings settings; + embedFonts = settings.readBoolEntry( "/qt/embedFonts", TRUE ); + + int npaths; + char** font_path; + font_path = XGetFontPath( tqt_xdisplay(), &npaths); + bool xfsconfig_read = FALSE; + for (int i=0; i read its config + bool finished = FALSE; + TQFile f("/etc/X11/fs/config"); + if ( !f.exists() ) + f.setName("/usr/X11R6/lib/X11/fs/config"); + if ( !f.exists() ) + f.setName("/usr/X11/lib/X11/fs/config"); + if ( f.exists() ) { + f.open(IO_ReadOnly); + while(f.status()==IO_Ok && !finished) { + TQString fs; + f.readLine(fs, 1024); + fs=fs.stripWhiteSpace(); + if (fs.left(9)=="catalogue" && fs.contains('=')) { + fs=fs.mid(fs.find('=')+1).stripWhiteSpace(); + bool end = FALSE; + while( f.status()==IO_Ok && !end ) { + if ( fs[int(fs.length())-1] == ',' ) + fs = fs.left(fs.length()-1); + else + end = TRUE; + if (fs[0] != '#' && !fs.contains(":unscaled")) + fontpath += fs; + f.readLine(fs, 1024); + fs=fs.stripWhiteSpace(); + } + finished = TRUE; + } + } + f.close(); + } + xfsconfig_read = TRUE; + } else if(!strstr(font_path[i], ":unscaled")) { + // Fonts paths marked :unscaled are always bitmapped fonts + // -> we can as well ignore them now and save time + fontpath += font_path[i]; + } + } + XFreeFontPath(font_path); + + // append tqsettings fontpath + TQStringList fp = settings.readListEntry( "/qt/fontPath", ':' ); + if ( !fp.isEmpty() ) + fontpath += fp; +#else + embedFonts = FALSE; +#endif +} + +TQPSPrinterPrivate::~TQPSPrinterPrivate() +{ + delete pageBuffer; +} + +void TQPSPrinterPrivate::setFont( const TQFont & fnt, int script ) +{ + TQFont f = fnt; + if ( f.rawMode() ) { + TQFont fnt( TQString::fromLatin1("Helvetica"), 12 ); + setFont( fnt, TQFont::Unicode ); + return; + } + if ( f.pointSize() == 0 ) { +#if defined(CHECK_RANGE) + tqWarning( "TQPrinter: Cannot set a font with zero point size." ); +#endif + f.setPointSize(TQApplication::font().pointSize()); + if ( f.pointSize() == 0 ) + f.setPointSize( 11 ); + } + + TQPSPrinterFont ff( f, script, this ); + TQString ps = ff.postScriptFontName(); + + TQString s = ps; + s.append( ' ' ); + s.prepend( ' ' ); + + TQString key = ff.xfontname; + + if ( f.pointSize() != -1 ) + key += " " + toString( f.pointSize() ); + else + key += " px" + toString( f.pixelSize() ); + TQString * tmp; + if ( !buffer ) + tmp = pageFontNames.find( key ); + else + tmp = headerFontNames.find( key ); + + TQString fontName; + if ( tmp ) + fontName = *tmp; + + if ( fontName.isEmpty() ) { + fontName = ff.defineFont( pageStream, ps, f, key, this ); + } + pageStream << fontName << " F\n"; + + ps.append( ' ' ); + ps.prepend( ' ' ); + if ( !fontsUsed.contains( ps ) ) + fontsUsed += ps; + +#ifndef TQT_NO_TEXTCODEC + TQTextCodec * codec = 0; +// ### +// #ifndef TQT_NO_TEXTCODEC +// i = 0; +// do { +// if ( unicodevalues[i].cs == f.charSet() ) +// codec = TQTextCodec::codecForMib( unicodevalues[i++].mib ); +// } while( codec == 0 && unicodevalues[i++].cs != unicodevalues_LAST ); +// #endif + currentFontCodec = codec; +#endif + currentFont = fontName; + currentFontFile = ff.handle(); + scriptUsed = script; +} + + +static void ps_r7( TQTextStream& stream, const char * s, int l ) +{ + int i = 0; + uchar line[79]; + int col = 0; + + while( i < l ) { + line[col++] = s[i++]; + if ( col >= 76 ) { + line[col++] = '\n'; + line[col++] = '\0'; + stream << (const char *)line; + col = 0; + } + } + if ( col > 0 ) { + while( (col&3) != 0 ) + line[col++] = '%'; // use a comment as padding + line[col++] = '\n'; + line[col++] = '\0'; + stream << (const char *)line; + } +} + + +static const int quoteSize = 3; // 1-8 pixels +static const int maxQuoteLength = 4+16+32+64+128+256; // magic extended quote +static const int quoteReach = 10; // ... 1-1024 pixels back +static const int tableSize = 1024; // 2 ** quoteReach; +static const int numAttempts = 128; + +static const int hashSize = 71; + +static const int None = INT_MAX; + +/* puts the lowest numBits of data into the out array starting at postion (byte/bit). + Adjusts byte and bit to point ot the next position. + + Need to make sure the out array is long enough before calling the method. +*/ +static void emitBits( char *out, int & byte, int & bit, + int numBits, uint data ) +{ + int b = 0; + uint d = data; + while( b < numBits ) { + if ( bit == 0 ) + out[byte] = 0; + if ( d & 1 ) + out[byte] = (uchar)out[byte] | ( 1 << bit ); + d = d >> 1; + b++; + bit++; + if ( bit > 6 ) { + bit = 0; + byte++; + } + } +} + +//#define DEBUG_COMPRESS +#ifdef DEBUG_COMPRESS +#include +#endif + +static TQByteArray compress( const TQImage & image, bool gray ) { +#ifdef DEBUG_COMPRESS + TQTime t; + t.start(); + int sizeUncompressed[11]; + for( int i = 0; i < 11; i++ ) + sizeUncompressed[i] = 0; + int sizeCompressed[11]; + for( int i = 0; i < 11; i++ ) + sizeCompressed[i] = 0; +#endif + + int width = image.width(); + int height = image.height(); + int depth = image.depth(); + int size = width*height; + + int pastPixel[tableSize]; + int mostRecentPixel[hashSize]; + if ( depth == 1 ) + size = (width+7)/8*height; + else if ( !gray ) + size = size*3; + + unsigned char *pixel = new unsigned char[size+1]; + int i = 0; + if ( depth == 1 ) { + TQImage::Endian bitOrder = image.bitOrder(); + memset( pixel, 0xff, size ); + for( int y=0; y < height; y++ ) { + uchar * s = image.scanLine( y ); + for( int x=0; x < width; x++ ) { + // need to copy bit for bit... + bool b = ( bitOrder == TQImage::LittleEndian ) ? + (*(s + (x >> 3)) >> (x & 7)) & 1 : + (*(s + (x >> 3)) << (x & 7)) & 0x80 ; + if ( b ) + pixel[i >> 3] ^= (0x80 >> ( i & 7 )); + i++; + } + // we need to align to 8 bit here + i = (i+7) & 0xffffff8; + } + } else if ( depth == 8 ) { + for( int y=0; y < height; y++ ) { + uchar * s = image.scanLine( y ); + for( int x=0; x < width; x++ ) { + TQRgb rgb = image.color( s[x] ); + if ( gray ) { + pixel[i] = (unsigned char) tqGray( rgb ); + i++; + } else { + pixel[i] = (unsigned char) tqRed( rgb ); + pixel[i+1] = (unsigned char) tqGreen( rgb ); + pixel[i+2] = (unsigned char) tqBlue( rgb ); + i += 3; + } + } + } + } else { + bool alpha = image.hasAlphaBuffer(); + for( int y=0; y < height; y++ ) { + TQRgb * s = (TQRgb*)(image.scanLine( y )); + for( int x=0; x < width; x++ ) { + TQRgb rgb = (*s++); + if ( alpha && tqAlpha( rgb ) < 0x40 ) // 25% alpha, convert to white - + rgb = tqRgb( 0xff, 0xff, 0xff ); + if ( gray ) { + pixel[i] = (unsigned char) tqGray( rgb ); + i++; + } else { + pixel[i] = (unsigned char) tqRed( rgb ); + pixel[i+1] = (unsigned char) tqGreen( rgb ); + pixel[i+2] = (unsigned char) tqBlue( rgb ); + i += 3; + } + } + } + } + + pixel[size] = 0; + + /* this compression function emits blocks of data, where each + block is an unquoted series of pixels, or a quote from earlier + pixels. if the six-letter string "banana" were a six-pixel + image, it might be unquoted "ban" followed by a 3-pixel quote + from -2. note that the final "a" is then copied from the + second "a", which is copied from the first "a" in the same copy + operation. + + the scanning for quotable blocks uses a cobol-like loop and a + hash table: we know how many pixels we need to quote, hash the + first and last pixel we need, and then go backwards in time + looking for some spot where those pixels of those two colours + occur at the right distance from each other. + + when we find a spot, we'll try a string-compare of all the + intervening pixels. we only do a maximum of 128 both-ends + compares or 64 full-string compares. it's more important to be + fast than get the ultimate in compression. + + The format of the compressed stream is as follows: + // 2 bits step size for search and backreference ( 1 or 3 ) + 1 bit compressed or uncompressed block follows + + uncompressed block: + 3 bits size of block in bytes + size*8 bits data + + compressed block: + 3 bits compression header + 0-2 size of block is 1-3 bytes + 3-7 size of block is bigger, 4-8 additional bits specifying size follow + 0/4-8 additional size fields + 10 location of backreference + */ + + for( i=0; i < hashSize; i++ ) + mostRecentPixel[i] = None; + int index = 0; + int emittedUntil = 0; + char *out = (char *)malloc( 256 * sizeof( char ) ); + int outLen = 256; + int outOffset = 0; + int outBit = 0; + + /* we process pixels serially, emitting as necessary/possible. */ + while( index <= size ) { + int bestCandidate = None; + int bestLength = 0; + i = index % tableSize; + int h = pixel[index] % hashSize; + int start, end; + start = end = pastPixel[i] = mostRecentPixel[h]; + mostRecentPixel[h] = index; + /* if our first candidate quote is unusable, or we don't need + to quote because we've already emitted something for this + pixel, just skip. */ + if ( start < index - tableSize || index >= size || + emittedUntil > index) + start = end = None; + int attempts = 0; + /* scan for suitable quote candidates: not too far back, and + if we've found one that's as big as it can get, don't look + for more */ + while( start != None && end != None && + bestLength < maxQuoteLength && + start >= index - tableSize && + end >= index - tableSize + bestLength ) { + /* scan backwards, looking for something good enough to + try a (slow) string comparison. we maintain indexes to + the start and the end of the quote candidate here */ + while( start != None && end != None && + ( pixel[start] != pixel[index] || + pixel[end] != pixel[index+bestLength] ) ) { + if ( attempts++ > numAttempts ) { + start = None; + } else if ( pixel[end] % hashSize == + pixel[index+bestLength] % hashSize ) { + /* we move the area along the end index' chain */ + end = pastPixel[end%tableSize]; + start = end - bestLength; + } else if ( pixel[start] % hashSize == + pixel[index] % hashSize ) { + /* ... or along the start index' chain */ + start = pastPixel[start%tableSize]; + end = start + bestLength; + } else { +#if 0 + /* this should never happen: both the start and + the end pointers ran off their tracks. */ + tqDebug( "oops! %06x %06x %06x %06x %5d %5d %5d %d", + pixel[start], pixel[end], + pixel[index], pixel[index+bestLength], + start, end, index, bestLength ); +#endif + /* but if it should happen, no problem. we'll just + say we found nothing, and the compression will + be a bit worse. */ + start = None; + } + /* if we've moved either index too far to use the + quote candidate, let's just give up here. there's + also a guard against "start" insanity. */ + if ( start < index - tableSize || start < 0 || start >= index ) + start = None; + if ( end < index - tableSize + bestLength || end < bestLength ) + end = None; + } + /* ok, now start and end point to an area of suitable + length whose first and last points match, or one/both + is/are set to None. */ + if ( start != None && end != None ) { + /* slow string compare... */ + int length = 0; + while( length < maxQuoteLength && + index+length < size && + pixel[start+length] == pixel[index+length] ) + length++; + /* if we've found something that overlaps the index + point, maybe we can move the quote point back? if + we're copying 10 pixels from 8 pixels back (an + overlap of 2), that'll be faster than copying from + 4 pixels back (an overlap of 6). */ + if ( start + length > index && length > 0 ) { + int d = index-start; + int equal = TRUE; + while( equal && start + length > index && + start > d && start-d >= index-tableSize ) { + int i = 0; + while( equal && i < d ) { + if( pixel[start+i] != pixel[start+i-d] ) + equal = FALSE; + i++; + } + if ( equal ) + start -= d; + } + } + /* if what we have is longer than the best previous + candidate, we'll use this one. */ + if ( length > bestLength ) { + attempts = 0; + bestCandidate = start; + bestLength = length; + if ( length < maxQuoteLength && index + length < size ) + end = mostRecentPixel[pixel[index+length]%hashSize]; + } else { + /* and if it ins't, we'll try some more. but we'll + count each string compare extra, since they're + so expensive. */ + attempts += 2; + if ( attempts > numAttempts ) { + start = None; + } else if ( pastPixel[start%tableSize] + bestLength < + pastPixel[end%tableSize] ) { + start = pastPixel[start%tableSize]; + end = start + bestLength; + } else { + end = pastPixel[end%tableSize]; + start = end - bestLength; + } + } + /* again, if we can't make use of the current quote + candidate, we don't try any more */ + if ( start < index - tableSize || start < 0 || start > size+1 ) + start = None; + if ( end < index - tableSize + bestLength || end < 0 || end > size+1 ) + end = None; + } + } + /* backreferences to 1 byte of data are actually more costly than + emitting the data directly, 2 bytes don't save much. */ + if ( bestCandidate != None && bestLength < 3 ) + bestCandidate = None; + /* at this point, bestCandidate is a candidate of bestLength + length, or else it's None. if we have such a candidate, or + we're at the end, we have to emit all unquoted data. */ + if ( index == size || bestCandidate != None ) { + /* we need a double loop, because there's a maximum length + on the "unquoted data" section. */ + while( emittedUntil < index ) { +#ifdef DEBUG_COMPRESS + int x = 0; + int bl = emittedUntil - index; + while ( (bl /= 2) ) + x++; + if ( x > 10 ) x = 10; + sizeUncompressed[x]++; +#endif + int l = TQMIN( 8, index - emittedUntil ); + if ( outOffset + l + 2 >= outLen ) { + outLen *= 2; + out = (char *) realloc( out, outLen ); + } + emitBits( out, outOffset, outBit, + 1, 0 ); + emitBits( out, outOffset, outBit, + quoteSize, l-1 ); + while( l-- ) { + emitBits( out, outOffset, outBit, + 8, pixel[emittedUntil] ); + emittedUntil++; + } + } + } + /* if we have some quoted data to output, do it. */ + if ( bestCandidate != None ) { +#ifdef DEBUG_COMPRESS + int x = 0; + int bl = bestLength; + while ( (bl /= 2) ) + x++; + if ( x > 10 ) x = 10; + sizeCompressed[x]++; +#endif + if ( outOffset + 4 >= outLen ) { + outLen *= 2; + out = (char *) realloc( out, outLen ); + } + emitBits( out, outOffset, outBit, + 1, 1 ); + int l = bestLength - 3; + const struct off_len { + int off; + int bits; + } ol_table [] = { + /* Warning: if you change the table here, change /uc in the PS code! */ + { 3, 0/*dummy*/ }, + { 16, 4 }, + { 32, 5 }, + { 64, 6 }, + { 128, 7 }, + { /*256*/ 0xfffffff, 8 }, + }; + + if ( l < ol_table[0].off ) { + emitBits( out, outOffset, outBit, + quoteSize, l ); + } else { + const off_len *ol = ol_table; + l -= ol->off; + ol++; + while ( l >= ol->off ) { + l -= ol->off; + ol++; + } + emitBits( out, outOffset, outBit, + quoteSize, ol->bits-1 ); + emitBits( out, outOffset, outBit, + ol->bits, l ); + } + emitBits( out, outOffset, outBit, + quoteReach, index - bestCandidate - 1 ); + emittedUntil += bestLength; + } + index++; + } + /* we've output all the data; time to clean up and finish off the + last characters. */ + if ( outBit ) + outOffset++; + i = 0; + /* we have to make sure the data is encoded in a stylish way :) */ + while( i < outOffset ) { + uchar c = out[i]; + c += 42; + if ( c > 'Z' && ( c != 't' || i == 0 || out[i-1] != 'Q' ) ) + c += 84; + out[i] = c; + i++; + } + TQByteArray outarr; + outarr.duplicate( out, outOffset ); + free( out ); + delete [] pixel; + +#ifdef DEBUG_COMPRESS + tqDebug( "------------- image compression statistics ----------------" ); + tqDebug(" compression time %d", t.elapsed() ); + tqDebug( "Size dist of uncompressed blocks:" ); + tqDebug( "\t%d\t%d\t%d\t%d\t%d\t%d\n", sizeUncompressed[0], sizeUncompressed[1], + sizeUncompressed[2], sizeUncompressed[3], sizeUncompressed[4], sizeUncompressed[5]); + tqDebug( "\t%d\t%d\t%d\t%d\t%d\n", sizeUncompressed[6], sizeUncompressed[7], + sizeUncompressed[8], sizeUncompressed[9], sizeUncompressed[10] ); + tqDebug( "Size dist of compressed blocks:" ); + tqDebug( "\t%d\t%d\t%d\t%d\t%d\t%d\n", sizeCompressed[0], sizeCompressed[1], + sizeCompressed[2], sizeCompressed[3], sizeCompressed[4], sizeCompressed[5]); + tqDebug( "\t%d\t%d\t%d\t%d\t%d\n", sizeCompressed[6], sizeCompressed[7], + sizeCompressed[8], sizeCompressed[9], sizeCompressed[10] ); + tqDebug( "===> total compression ratio %d/%d = %f", outOffset, size, (float)outOffset/(float)size ); + tqDebug( "-----------------------------------------------------------" ); +#endif + + return outarr; +} + +#undef XCOORD +#undef YCOORD +#undef WIDTH +#undef HEIGHT +#undef POINT +#undef RECT +#undef INT_ARG + +#define XCOORD(x) (float)(x) +#define YCOORD(y) (float)(y) +#define WIDTH(w) (float)(w) +#define HEIGHT(h) (float)(h) + +#define POINT(index) XCOORD(p[index].point->x()) << ' ' << \ + YCOORD(p[index].point->y()) << ' ' +#define RECT(index) XCOORD(p[index].rect->normalize().x()) << ' ' << \ + YCOORD(p[index].rect->normalize().y()) << ' ' << \ + WIDTH (p[index].rect->normalize().width()) << ' ' << \ + HEIGHT(p[index].rect->normalize().height()) << ' ' +#define INT_ARG(index) p[index].ival << ' ' + +static char returnbuffer[13]; +static const char * color( const TQColor &c, TQPrinter * printer ) +{ + if ( c == TQt::black ) + qstrcpy( returnbuffer, "B " ); + else if ( c == TQt::white ) + qstrcpy( returnbuffer, "W " ); + else if ( c.red() == c.green() && c.red() == c.blue() ) + sprintf( returnbuffer, "%d d2 ", c.red() ); + else if ( printer->colorMode() == TQPrinter::GrayScale ) + sprintf( returnbuffer, "%d d2 ", + tqGray( c.red(), c.green(),c.blue() ) ); + else + sprintf( returnbuffer, "%d %d %d ", + c.red(), c.green(), c.blue() ); + return returnbuffer; +} + + +static const char * psCap( TQt::PenCapStyle p ) +{ + if ( p == TQt::SquareCap ) + return "2 "; + else if ( p == TQt::RoundCap ) + return "1 "; + return "0 "; +} + + +static const char * psJoin( TQt::PenJoinStyle p ) { + if ( p == TQt::BevelJoin ) + return "2 "; + else if ( p == TQt::RoundJoin ) + return "1 "; + return "0 "; +} + + + +void TQPSPrinterPrivate::drawImage( TQPainter *paint, float x, float y, float w, float h, + const TQImage &img, const TQImage &mask ) +{ + if ( !w || !h || img.isNull() ) return; + + int width = img.width(); + int height = img.height(); + float scaleX = (float)width/w; + float scaleY = (float)height/h; + + bool gray = (printer->colorMode() == TQPrinter::GrayScale) || + img.allGray(); + int splitSize = 21830 * (gray ? 3 : 1 ); + if ( width * height > splitSize ) { // 65535/3, tolerance for broken printers + int images, subheight; + images = ( width * height + splitSize - 1 ) / splitSize; + subheight = ( height + images-1 ) / images; + while ( subheight * width > splitSize ) { + images++; + subheight = ( height + images-1 ) / images; + } + int suby = 0; + while( suby < height ) { + drawImage(paint, x, y + suby/scaleY, w, TQMIN( subheight, height-suby )/scaleY, + img.copy( 0, suby, width, TQMIN( subheight, height-suby ) ), + mask.isNull() ? mask : mask.copy( 0, suby, width, TQMIN( subheight, height-suby ) )); + suby += subheight; + } + } else { + TQByteArray out; + int size = 0; + const char *bits; + + if ( !mask.isNull() ) { + out = ::compress( mask, TRUE ); + size = (width+7)/8*height; + pageStream << "/mask " << size << " string uc\n"; + ps_r7( pageStream, out, out.size() ); + pageStream << "d\n"; + } + if ( img.depth() == 1 ) { + size = (width+7)/8*height; + bits = "1 "; + } else if ( gray ) { + size = width*height; + bits = "8 "; + } else { + size = width*height*3; + bits = "24 "; + } + + out = ::compress( img, gray ); + pageStream << "/sl " << size << " string uc\n"; + ps_r7( pageStream, out, out.size() ); + pageStream << "d\n" + << width << ' ' << height << "[" << scaleX << " 0 0 " << scaleY << " 0 0]sl " + << bits << (!mask.isNull() ? "mask " : "false ") + << x << ' ' << y << " di\n"; + } +} + + +void TQPSPrinterPrivate::matrixSetup( TQPainter *paint ) +{ +#ifndef TQT_NO_TRANSFORMATIONS + TQWMatrix tmp; + if ( paint->hasViewXForm() ) { + TQRect viewport = paint->viewport(); + TQRect window = paint->window(); + tmp.translate( viewport.x(), viewport.y() ); + tmp.scale( 1.0 * viewport.width() / window.width(), + 1.0 * viewport.height() / window.height() ); + tmp.translate( -window.x(), -window.y() ); + } + if ( paint->hasWorldXForm() ) { + tmp = paint->worldMatrix() * tmp; + } + pageStream << "[" + << tmp.m11() << ' ' << tmp.m12() << ' ' + << tmp.m21() << ' ' << tmp.m22() << ' ' + << tmp.dx() << ' ' << tmp.dy() + << "]ST\n"; +#else + TQPoint p(0,0); + p = paint->xForm(p); + pageStream << "[" + << 0 << ' ' << 0 << ' ' + << 0 << ' ' << 0 << ' ' + << p.x() << ' ' << p.y() + << "]ST\n"; +#endif + dirtyMatrix = FALSE; +} + +void TQPSPrinterPrivate::orientationSetup() +{ + if ( printer->orientation() == TQPrinter::Landscape ) + pageStream << "TQLS\n"; +} + + +void TQPSPrinterPrivate::emitHeader( bool finished ) +{ + TQString title = printer->docName(); + TQString creator = printer->creator(); + if ( !creator ) // default creator + creator = TQString::fromLatin1("TQt " TQT_VERSION_STR); + outDevice = new TQFile(); + (void)((TQFile *)outDevice)->open( IO_WriteOnly, fd ); + outStream.setDevice( outDevice ); + outStream << "%!PS-Adobe-1.0"; + TQPaintDeviceMetrics m( printer ); + scale = 72. / ((float) m.logicalDpiY()); + uint mtop, mleft, mbottom, mright; + printer->margins( &mtop, &mleft, &mbottom, &mright ); + int width = m.width(); + int height = m.height(); + bool fullPage = printer->fullPage(); + if ( finished && pageCount == 1 && printer->numCopies() == 1 && + ( ( printer->fullPage() && qt_gen_epsf ) || + ( printer->outputToFile() && printer->outputFileName().endsWith( ".eps" ) ) ) + ) { + if ( !boundingBox.isValid() ) + boundingBox.setRect( 0, 0, width, height ); + if ( printer->orientation() == TQPrinter::Landscape ) { + if ( !fullPage ) + boundingBox.moveBy( -mleft, -mtop ); + outStream << " EPSF-3.0\n%%BoundingBox: " + << (int)(m.height() - boundingBox.bottom())*scale << " " // llx + << (int)(m.width() - boundingBox.right())*scale - 1 << " " // lly + << (int)(m.height() - boundingBox.top())*scale + 1 << " " // urx + << (int)(m.width() - boundingBox.left())*scale; // ury + } else { + if ( !fullPage ) + boundingBox.moveBy( mleft, -mtop ); + outStream << " EPSF-3.0\n%%BoundingBox: " + << (int)(boundingBox.left())*scale << " " + << (int)(m.height() - boundingBox.bottom())*scale - 1 << " " + << (int)(boundingBox.right())*scale + 1 << " " + << (int)(m.height() - boundingBox.top())*scale; + } + } else { + int w = width + (fullPage ? 0 : mleft + mright); + int h = height + (fullPage ? 0 : mtop + mbottom); + w = (int)(w*scale); + h = (int)(h*scale); + // set a bounding box according to the DSC + if ( printer->orientation() == TQPrinter::Landscape ) + outStream << "\n%%BoundingBox: 0 0 " << h << " " << w; + else + outStream << "\n%%BoundingBox: 0 0 " << w << " " << h; + } + outStream << "\n" << wrapDSC( "%%Creator: " + creator ); + if ( !!title ) + outStream << wrapDSC( "%%Title: " + title ); + outStream << "%%CreationDate: " << TQDateTime::currentDateTime().toString(); + outStream << "\n%%Orientation: "; + if ( printer->orientation() == TQPrinter::Landscape ) + outStream << "Landscape"; + else + outStream << "Portrait"; + if ( finished ) + outStream << "\n%%Pages: " << pageCount << "\n" + << wrapDSC( "%%DocumentFonts: " + fontsUsed ); + else + outStream << "%%Pages: (atend)" + << "\n%%DocumentFonts: (atend)"; + outStream << "\n%%EndComments\n"; + + outStream << "%%BeginProlog\n"; + const char * const prologLicense = "% Prolog copyright 1994-2006 Trolltech. " + "You may copy this prolog in any way\n" + "% that is directly related to this " + "document. For other use of this prolog,\n" + "% see your licensing agreement for TQt.\n"; + outStream << prologLicense << ps_header << "\n"; + + // we have to do this here, as scaling can affect this. + TQString lineStyles = "/LArr[" // Pen styles: + " [] []" // solid line + " [ w s ] [ s w ]" // dash line + " [ s s ] [ s s ]" // dot line + " [ m s s s ] [ s m s s ]" // dash dot line + " [ m s s s s ] [ s m s s s s ]" // dash dot dot line + " ] d\n"; + lineStyles.replace( TQRegExp( "w" ), toString( 10./scale ) ); + lineStyles.replace( TQRegExp( "m" ), toString( 5./scale ) ); + lineStyles.replace( TQRegExp( "s" ), toString( 3./scale ) ); + + outStream << lineStyles; + + outStream << "/pageinit {\n"; + if ( !printer->fullPage() ) { + if ( printer->orientation() == TQPrinter::Portrait ) + outStream << mleft*scale << " " + << mbottom*scale << " translate\n"; + else + outStream << mtop*scale << " " + << mleft*scale << " translate\n"; + } + if ( printer->orientation() == TQPrinter::Portrait ) { + outStream << "% " << m.widthMM() << "*" << m.heightMM() + << "mm (portrait)\n0 " << height*scale + << " translate " << scale << " -" << scale << " scale/defM matrix CM d } d\n"; + } else { + outStream << "% " << m.heightMM() << "*" << m.widthMM() + << " mm (landscape)\n 90 rotate " << scale << " -" << scale << " scale/defM matrix CM d } d\n"; + } + outStream << "%%EndProlog\n"; + + + outStream << "%%BeginSetup\n"; + if ( printer->numCopies() > 1 ) { + outStream << "/#copies " << printer->numCopies() << " def\n"; + outStream << "/NumCopies " << printer->numCopies() << " SPD\n"; + outStream << "/Collate " << (printer->collateCopies() ? "true" : "false") << " SPD\n"; + } + if ( fontBuffer->buffer().size() ) { + if ( pageCount == 1 || finished ) + outStream << "% Fonts and encodings used\n"; + else + outStream << "% Fonts and encodings used on pages 1-" + << pageCount << "\n"; + TQDictIterator it(fonts); + while (it.current()) { + it.current()->download(outStream,TRUE); // true means its global + ++it; + } + outStream.writeRawBytes( fontBuffer->buffer().data(), + fontBuffer->buffer().size() ); + } + outStream << "%%EndSetup\n"; + + outStream.writeRawBytes( buffer->buffer().data(), + buffer->buffer().size() ); + + delete buffer; + buffer = 0; + fontStream.unsetDevice(); + delete fontBuffer; + fontBuffer = 0; +} + + +/* Called whenever a restore has been done. Currently done at the top of a + new page and whenever clipping is turned off. */ +void TQPSPrinterPrivate::resetDrawingTools( TQPainter *paint ) +{ + TQPen defaultPen; // default drawing tools + TQBrush defaultBrush; + + TQColor c = paint->backgroundColor(); + if ( c != TQt::white ) + pageStream << color( c, printer ) << "BC\n"; + + if ( paint->backgroundMode() != TQt::TransparentMode ) + pageStream << "/OMo true d\n"; + + //currentUsed = currentSet; + //setFont( currentSet ); + currentFontFile = 0; + + TQBrush b = paint->brush(); + if ( b != defaultBrush ) { + if ( b == TQt::CustomPattern ) { +#if defined(CHECK_RANGE) + tqWarning( "TQPrinter: Pixmap brush not supported" ); +#endif + } else { + cbrush = b; + } + } + + dirtypen = TRUE; + dirtybrush = TRUE; + + if ( paint->hasViewXForm() || paint->hasWorldXForm() ) + matrixSetup( paint ); +} + + +static void putRect( TQTextStream &stream, const TQRect &r ) +{ + stream << r.x() << " " + << r.y() << " " + << r.width() << " " + << r.height() << " "; +} + + +void TQPSPrinterPrivate::setClippingOff( TQPainter *paint ) +{ + pageStream << "CLO\n"; // clipping off, includes a restore + resetDrawingTools( paint ); // so drawing tools must be reset +} + + +void TQPSPrinterPrivate::clippingSetup( TQPainter *paint ) +{ + if ( paint->hasClipping() ) { + if ( !firstClipOnPage ) + setClippingOff( paint ); + const TQRegion rgn = paint->clipRegion(); + TQMemArray rects = rgn.rects(); + int i; + pageStream<< "CLSTART\n"; // start clipping + for( i = 0 ; i < (int)rects.size() ; i++ ) { + putRect( pageStream, rects[i] ); + pageStream << "ACR\n"; // add clip rect + if ( pageCount == 1 ) + boundingBox = boundingBox.unite( rects[i] ); + } + pageStream << "CLEND\n"; // end clipping + firstClipOnPage = FALSE; + } else { + if ( !firstClipOnPage ) // no need to turn off if first on page + setClippingOff( paint ); + // if we're painting without clipping, the bounding box must + // be everything. NOTE: this assumes that this function is + // only ever called when something is to be painted. + TQPaintDeviceMetrics m( printer ); + if ( !boundingBox.isValid() ) + boundingBox.setRect( 0, 0, m.width(), m.height() ); + } + dirtyClipping = FALSE; +} + +void TQPSPrinterPrivate::initPage(TQPainter *paint) +{ + + // a restore undefines all the fonts that have been defined + // inside the scope (normally within pages) and all the glyphs that + // have been added in the scope. + + TQDictIterator it(fonts); + while (it.current()) { + it.current()->restore(); + ++it; + } + if ( !buffer ) { + pageFontNames.clear(); + } + + pageStream.unsetDevice(); + if ( pageBuffer ) + delete pageBuffer; + pageBuffer = new TQBuffer(); + pageBuffer->open( IO_WriteOnly ); + pageStream.setEncoding( TQTextStream::Latin1 ); + pageStream.setDevice( pageBuffer ); + delete savedImage; + savedImage = 0; + textY = 0; + dirtyClipping = TRUE; + firstClipOnPage = TRUE; + + + resetDrawingTools( paint ); + dirtyNewPage = FALSE; + pageFontNumber = headerFontNumber; +} + +void TQPSPrinterPrivate::flushPage( bool last ) +{ + if ( last && !pageBuffer ) + return; + bool pageFonts = ( buffer == 0 ); + if ( buffer && +// ( last || pagesInBuffer++ > -1 || +// ( pagesInBuffer > 4 && buffer->size() > 262144 ) ) ) + (last || buffer->size() > 50000000) + ) { +// tqDebug("emiting header at page %d", pageCount ); + emitHeader( last ); + } + outStream << "%%Page: " + << pageCount << ' ' << pageCount << endl + << "%%BeginPageSetup\n" + << "QI\n"; + if (!dirtyNewPage) { + if ( pageFonts ) { + //tqDebug("page fonts for page %d", pageCount); + // we have already downloaded the header. Maybe we have page fonts here + TQDictIterator it(fonts); + while (it.current()) { + it.current()->download( outStream, FALSE ); // FALSE means its for the page only + ++it; + } + } + outStream << "%%EndPageSetup\n"; + if ( pageBuffer ) + outStream.writeRawBytes( pageBuffer->buffer().data(), + pageBuffer->buffer().size() ); + } + outStream << "\nQP\n"; + pageCount++; +} + +// ================ PSPrinter class ======================== + +TQPSPrinter::TQPSPrinter( TQPrinter *prt, int fd ) + : TQPaintDevice( TQInternal::Printer | TQInternal::ExternalDevice ) +{ + d = new TQPSPrinterPrivate( prt, fd ); +} + + +TQPSPrinter::~TQPSPrinter() +{ + if ( d->fd >= 0 ) +#if defined(_OS_WIN32_) + ::_close( d->fd ); +#else + ::close( d->fd ); +#endif + delete d; +} + + + +static void ignoreSigPipe(bool b) +{ + static struct sigaction *users_sigpipe_handler = 0; + + if (b) { + if (users_sigpipe_handler != 0) + return; // already ignoring sigpipe + + users_sigpipe_handler = new struct sigaction; + struct sigaction tmp_sigpipe_handler; + tmp_sigpipe_handler.sa_handler = SIG_IGN; + sigemptyset(&tmp_sigpipe_handler.sa_mask); + tmp_sigpipe_handler.sa_flags = 0; + + if (sigaction(SIGPIPE, &tmp_sigpipe_handler, users_sigpipe_handler) == -1) { + delete users_sigpipe_handler; + users_sigpipe_handler = 0; + } + } + else { + if (users_sigpipe_handler == 0) + return; // not ignoring sigpipe + + if (sigaction(SIGPIPE, users_sigpipe_handler, 0) == -1) + tqWarning("TQPSPrinter: could not restore SIGPIPE handler"); + + delete users_sigpipe_handler; + users_sigpipe_handler = 0; + } +} + +bool TQPSPrinter::cmd( int c , TQPainter *paint, TQPDevCmdParam *p ) +{ + if ( c == PdcBegin ) { // start painting + d->pagesInBuffer = 0; + d->buffer = new TQBuffer(); + d->buffer->open( IO_WriteOnly ); + d->outStream.setEncoding( TQTextStream::Latin1 ); + d->outStream.setDevice( d->buffer ); + d->fontBuffer = new TQBuffer(); + d->fontBuffer->open( IO_WriteOnly ); + d->fontStream.setEncoding( TQTextStream::Latin1 ); + d->fontStream.setDevice( d->fontBuffer ); + d->headerFontNumber = 0; + d->pageCount = 1; // initialize state + d->dirtyMatrix = TRUE; + d->dirtyClipping = TRUE; + d->dirtyNewPage = TRUE; + d->firstClipOnPage = TRUE; + d->boundingBox = TQRect( 0, 0, -1, -1 ); + d->fontsUsed = TQString::fromLatin1(""); + + TQPaintDeviceMetrics m( d->printer ); + d->scale = 72. / ((float) m.logicalDpiY()); + + return TRUE; + } + + if ( c == PdcEnd ) { // painting done + bool pageCountAtEnd = (d->buffer != 0); + + // we're writing to lp/lpr through a pipe, we don't want to crash with SIGPIPE + // if lp/lpr dies + ignoreSigPipe(TRUE); + d->flushPage( TRUE ); + d->outStream << "%%Trailer\n"; + if ( pageCountAtEnd ) + d->outStream << "%%Pages: " << d->pageCount - 1 << "\n" << + wrapDSC( "%%DocumentFonts: " + d->fontsUsed ); + d->outStream << "%%EOF\n"; + ignoreSigPipe(FALSE); + + d->outStream.unsetDevice(); + if ( d->outDevice ) + d->outDevice->close(); + if ( d->fd >= 0 ) + ::close( d->fd ); + d->fd = -1; + delete d->outDevice; + d->outDevice = 0; + } + + if ( c >= PdcDrawFirst && c <= PdcDrawLast ) { + if ( !paint ) + return FALSE; // sanity + if ( d->dirtyNewPage ) + d->initPage( paint ); + if ( d->dirtyMatrix ) + d->matrixSetup( paint ); + if ( d->dirtyClipping ) // Must be after matrixSetup and initPage + d->clippingSetup( paint ); + if ( d->dirtypen ) { + // we special-case for narrow solid lines with the default + // cap and join styles + if ( d->cpen.style() == TQt::SolidLine && d->cpen.width() == 0 && + d->cpen.capStyle() == TQt::FlatCap && + d->cpen.joinStyle() == TQt::MiterJoin ) + d->pageStream << color( d->cpen.color(), d->printer ) << "P1\n"; + else + d->pageStream << (int)d->cpen.style() << ' ' << d->cpen.width() + << ' ' << color( d->cpen.color(), d->printer ) + << psCap( d->cpen.capStyle() ) + << psJoin( d->cpen.joinStyle() ) << "PE\n"; + d->dirtypen = FALSE; + } + if ( d->dirtybrush ) { + // we special-case for nobrush and solid white, since + // those are the two most common brushes + if ( d->cbrush.style() == TQt::NoBrush ) + d->pageStream << "NB\n"; + else if ( d->cbrush.style() == TQt::SolidPattern && + d->cbrush.color() == TQt::white ) + d->pageStream << "WB\n"; + else + d->pageStream << (int)d->cbrush.style() << ' ' + << color( d->cbrush.color(), d->printer ) << "BR\n"; + d->dirtybrush = FALSE; + } + if ( d->dirtyBkColor ) { + d->pageStream << color( d->bkColor, d->printer ) << "BC\n"; + d->dirtyBkColor = FALSE; + } + if ( d->dirtyBkMode ) { + if ( d->bkMode == TQt::TransparentMode ) + d->pageStream << "/OMo false d\n"; + else + d->pageStream << "/OMo true d\n"; + d->dirtyBkMode = FALSE; + } + } + + switch( c ) { + case PdcDrawPoint: + d->pageStream << POINT(0) << "P\n"; + break; + case PdcMoveTo: + d->pageStream << POINT(0) << "M\n"; + break; + case PdcLineTo: + d->pageStream << POINT(0) << "L\n"; + break; + case PdcDrawLine: + if ( p[0].point->y() == p[1].point->y() ) + d->pageStream << POINT(1) << p[0].point->x() << " HL\n"; + else if ( p[0].point->x() == p[1].point->x() ) + d->pageStream << POINT(1) << p[0].point->y() << " VL\n"; + else + d->pageStream << POINT(1) << POINT(0) << "DL\n"; + break; + case PdcDrawRect: + d->pageStream << RECT(0) << "R\n"; + break; + case PdcDrawRoundRect: + d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "RR\n"; + break; + case PdcDrawEllipse: + d->pageStream << RECT(0) << "E\n"; + break; + case PdcDrawArc: + d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "A\n"; + break; + case PdcDrawPie: + d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "PIE\n"; + break; + case PdcDrawChord: + d->pageStream << RECT(0) << INT_ARG(1) << INT_ARG(2) << "CH\n"; + break; + case PdcDrawLineSegments: + if ( p[0].ptarr->size() > 0 ) { + TQPointArray a = *p[0].ptarr; + TQPoint pt; + d->pageStream << "NP\n"; + for ( int i=0; i<(int)a.size(); i+=2 ) { + pt = a.point( i ); + d->pageStream << XCOORD(pt.x()) << ' ' + << YCOORD(pt.y()) << " MT\n"; + pt = a.point( i+1 ); + d->pageStream << XCOORD(pt.x()) << ' ' + << YCOORD(pt.y()) << " LT\n"; + } + d->pageStream << "QS\n"; + } + break; + case PdcDrawPolyline: + if ( p[0].ptarr->size() > 1 ) { + TQPointArray a = *p[0].ptarr; + TQPoint pt = a.point( 0 ); + d->pageStream << "NP\n" + << XCOORD(pt.x()) << ' ' << YCOORD(pt.y()) << " MT\n"; + for ( int i=1; i<(int)a.size(); i++ ) { + pt = a.point( i ); + d->pageStream << XCOORD(pt.x()) << ' ' + << YCOORD(pt.y()) << " LT\n"; + } + d->pageStream << "QS\n"; + } + break; + case PdcDrawPolygon: + if ( p[0].ptarr->size() > 2 ) { + TQPointArray a = *p[0].ptarr; + if ( p[1].ival ) + d->pageStream << "/WFi true d\n"; + TQPoint pt = a.point(0); + d->pageStream << "NP\n"; + d->pageStream << XCOORD(pt.x()) << ' ' + << YCOORD(pt.y()) << " MT\n"; + for( int i=1; i<(int)a.size(); i++) { + pt = a.point( i ); + d->pageStream << XCOORD(pt.x()) << ' ' + << YCOORD(pt.y()) << " LT\n"; + } + d->pageStream << "CP BF QS\n"; + if ( p[1].ival ) + d->pageStream << "/WFi false d\n"; + } + break; + case PdcDrawCubicBezier: + if ( p[0].ptarr->size() == 4 ) { + d->pageStream << "NP\n"; + TQPointArray a = *p[0].ptarr; + d->pageStream << XCOORD(a[0].x()) << ' ' + << YCOORD(a[0].y()) << " MT "; + for ( int i=1; i<4; i++ ) { + d->pageStream << XCOORD(a[i].x()) << ' ' + << YCOORD(a[i].y()) << ' '; + } + d->pageStream << "BZ\n"; + } + break; + case PdcDrawText2: + // we use drawTextItem instead + return TRUE; + case PdcDrawText2Formatted: + return TRUE; + case PdcDrawTextItem: { + const TQTextItem *ti = p[1].textItem; + TQScriptItem &si = ti->engine->items[ti->item]; + int len = ti->engine->length( ti->item ); + if ( si.isSpace || si.isObject ) + return FALSE; + + if ( d->currentSet != d->currentUsed || d->scriptUsed != si.analysis.script || !d->currentFontFile ) { + d->currentUsed = d->currentSet; + d->setFont( d->currentSet, si.analysis.script ); + } + if( d->currentFontFile ) // better not crash in case somethig goes wrong. + d->currentFontFile->drawText( d->pageStream, *p[0].point, ti->engine, ti->item, + ti->engine->string.mid( si.position, len ), d, paint); + return FALSE; + } + case PdcDrawPixmap: { + if ( p[1].pixmap->isNull() ) + break; + TQRect r = *p[0].rect; + TQImage img; + img = *(p[1].pixmap); + TQImage mask; + if ( p[1].pixmap->mask() ) + mask = *(p[1].pixmap->mask()); + d->drawImage(paint, r.x(), r.y(), r.width(), r.height(), img, mask); + break; + } + case PdcDrawImage: { + if ( p[1].image->isNull() ) + break; + TQRect r = *(p[0].rect); + TQImage img = *(p[1].image); + TQImage mask; +#ifndef TQT_NO_IMAGE_DITHER_TO_1 + if ( img.hasAlphaBuffer() ) + mask = img.createAlphaMask(); +#endif + d->drawImage(paint, r.x(), r.y(), r.width(), r.height(), img, mask); + break; + } + case PdcSetBkColor: + { + if ( d->bkColor != *(p[0].color) ) { + d->bkColor = *(p[0].color); + d->dirtyBkColor = TRUE; + } + break; + } + case PdcSetBkMode: + { + if ( d->bkMode != p[0].ival ) { + d->bkMode = (TQt::BGMode) p[0].ival; + d->dirtyBkMode = TRUE; + } + break; + } + case PdcSetROP: +#if defined(CHECK_RANGE) + if ( p[0].ival != TQt::CopyROP ) + tqWarning( "TQPrinter: Raster operation setting not supported" ); +#endif + break; + case PdcSetBrushOrigin: + break; + case PdcSetFont: + d->currentSet = *(p[0].font); + d->fm = paint->fontMetrics(); + // turn these off - they confuse the 'avoid font change' logic + d->currentSet.setUnderline( FALSE ); + d->currentSet.setStrikeOut( FALSE ); + break; + case PdcSetPen: + if ( d->cpen != *(p[0].pen) ) { + d->dirtypen = TRUE; + d->cpen = *(p[0].pen); + } + break; + case PdcSetBrush: + if ( p[0].brush->style() == TQt::CustomPattern ) { +#if defined(CHECK_RANGE) + tqWarning( "TQPrinter: Pixmap brush not supported" ); +#endif + return FALSE; + } + if ( d->cbrush != *(p[0].brush) ) { + d->dirtybrush = TRUE; + d->cbrush = *(p[0].brush); + } + break; + case PdcSetTabStops: + case PdcSetTabArray: + return FALSE; + case PdcSetUnit: + break; + case PdcSetVXform: + case PdcSetWindow: + case PdcSetViewport: + case PdcSetWXform: + case PdcSetWMatrix: + case PdcRestoreWMatrix: + d->dirtyMatrix = TRUE; + break; + case PdcSetClip: + d->dirtyClipping = TRUE; + break; + case PdcSetClipRegion: + d->dirtyClipping = TRUE; + break; + case NewPage: + // we're writing to lp/lpr through a pipe, we don't want to crash with SIGPIPE + // if lp/lpr dies + ignoreSigPipe(TRUE); + d->flushPage(); + ignoreSigPipe(FALSE); + + d->dirtyNewPage = TRUE; + break; + case AbortPrinting: + break; + default: + break; + } + return TRUE; +} + +#endif // TQT_NO_PRINTER diff --git a/src/kernel/tqpsprinter.ps b/src/kernel/tqpsprinter.ps new file mode 100644 index 000000000..e73dd9510 --- /dev/null +++ b/src/kernel/tqpsprinter.ps @@ -0,0 +1,805 @@ +% the postscript header we use for our tqpsprinter in uncompressed and commented form. +% use the makepsheader perl script to generate a compressed version of this header +% you can then paste into tqpsprinter.cpp +% +% some compression of the code is done by the makepsheader script, so we don't need to +% write too criptically here. + +/d /def load def +/D {bind d} bind d +/d2 {dup dup} D +/B {0 d2} D +/W {255 d2} D +/ED {exch d} D +/D0 {0 ED} D +/LT {lineto} D +/MT {moveto} D +/S {stroke} D +/F {setfont} D +/SW {setlinewidth} D +/CP {closepath} D +/RL {rlineto} D +/NP {newpath} D +/CM {currentmatrix} D +/SM {setmatrix} D +/TR {translate} D +/SD {setdash} D +/SC {aload pop setrgbcolor} D +/CR {currentfile read pop} D +/i {index} D +/bs {bitshift} D +/scs {setcolorspace} D +/DB {dict dup begin} D +/DE {end d} D +/ie {ifelse} D +/sp {astore pop} D + +% ENDUNCOMPRESSED: Warning: leave this line in. +% Everything before this line will be left untouched by the compression + + + +/BSt 0 d % brush style +/LWi 1 d % line width +/PSt 1 d % pen style +/Cx 0 d % current x position +/Cy 0 d % current y position +/WFi false d % winding fill +/OMo false d % opaque mode (not transparent) + +/BCol [ 1 1 1 ] d % brush color +/PCol [ 0 0 0 ] d % pen color +/BkCol [ 1 1 1 ] d % background color +/BDArr [ % Brush dense patterns + 0.94 + 0.88 + 0.63 + 0.50 + 0.37 + 0.12 + 0.06 +] d +/defM matrix d + +/nS 0 d % number of saved painter states + +% LArr for the Pen styles is defined in emitHeader because of scaling + +% GPS: GetPenStyle +% Returns the line pattern (from pen style PSt). +% +% bool GPS pattern +% true : returns draw pattern +% false: returns fill pattern +/GPS { + PSt 1 ge PSt 5 le and % valid pen pattern? + { + { LArr PSt 1 sub 2 mul get } % draw pattern + { LArr PSt 2 mul 1 sub get } ifelse % opaque pattern + } + { [] } ifelse % out of range => solid line +} D + +% QS: QtStroke +% draw and fill current path +% +% - QS - +/QS { % stroke command + PSt 0 ne % != NO_PEN + { + gsave + LWi SW % set line width + true GPS 0 setdash S % draw line pattern + OMo PSt 1 ne and % opaque mode and not solid line? + { + BkCol SC + false GPS dup 0 get setdash S % fill in opaque pattern + } if + grestore + } if +} D + + + + +%% The following operations are used to read compressed data from the file +%% Until now this is only used for image compression + +% read 28 bits and leave them on tos +% +% - r28 num +/r28 { + % skip past whitespace and read one character + { currentfile read pop + dup 32 gt { exit } if + pop + } loop + % read three more + 3 { + currentfile read pop + } repeat + % make an accumulator + 0 + % for each character, shift the accumulator and add in the character + 4 { + 7 bitshift exch + dup 128 gt { 84 sub } if 42 sub 127 and + add + } repeat +} D + +/rA 0 d % accumulator +/rL 0 d % bits left + +% takes number of bits, leaves number +% +% num rB num +/rB { + rL 0 eq { + % if we have nothing, let's get something + /rA r28 d + /rL 28 d + } if + dup rL gt { + % if we don't have enough, take what we have and get more + rA exch rL sub rL exch + /rA 0 d /rL 0 d + rB exch bitshift add + } { + % else take some of what we have + dup rA 16#fffffff 3 -1 roll bitshift not and exch + % ... and update rL and rA + dup rL exch sub /rL ED + neg rA exch bitshift /rA ED + } ifelse +} D + +% uncompresses image data from currentfile until the string on the +% stack is full; leaves the string there. +% assumes that nothing could conceivably go wrong, ie. the compressed data has +% to be in the correct format and the length of the string has to be exactly right +% to hold the compressed data +% +% string uc string +% +%%% Warning: if you change the method here, change the table in tqpsprinter.cpp:compress()! +/uc { + /rL 0 d + 0 + { % string pos + dup 2 index length ge { exit } if + 1 rB + 1 eq { % compressed + 3 rB % string pos bits + dup 3 ge { + 1 add dup rB % string pos bits extra + 1 index 5 ge { + 1 index 6 ge { + 1 index 7 ge { + 1 index 8 ge { + 128 add + } if + 64 add + } if + 32 add + } if + 16 add + } if + 3 add + exch pop + } if + 3 add + % string pos length + exch 10 rB 1 add + % string length pos dist + { + dup 3 index lt { + dup + } { + 2 index + } ifelse % string length pos dist length-this-time + 4 index 3 index 3 index sub 2 index getinterval + 5 index 4 index 3 -1 roll putinterval + dup 4 -1 roll add 3 1 roll + 4 -1 roll exch sub + dup 0 eq { exit } if + 3 1 roll + } loop % string pos dist length + pop pop + } { % uncompressed + 3 rB 1 add + { + 2 copy 8 rB put 1 add + } repeat + } ifelse + } loop + pop +} D + +%% image drawing routines + +/sl D0 % ### is this needed ? + +% defines for QCI +/QCIgray D0 /QCIcolor D0 /QCIindex D0 + +% this method prints color images if colorimage is available, otherwise +% converts the string to a grayscale image and uses the reular postscript image +% operator for printing. +% Arguments are the same as for the image operator: +% +% width height bits/sample matrix datasrc QCI - +/QCI { + /colorimage where { + pop + false 3 colorimage + }{ % the hard way, based on PD code by John Walker + exec /QCIcolor ED + /QCIgray QCIcolor length 3 idiv string d + 0 1 QCIcolor length 3 idiv 1 sub + { /QCIindex ED + /x QCIindex 3 mul d + QCIgray QCIindex + QCIcolor x get 0.30 mul + QCIcolor x 1 add get 0.59 mul + QCIcolor x 2 add get 0.11 mul + add add cvi + put + } for + QCIgray image + } ifelse +} D + +% general image drawing routine, used from the postscript driver +% +% Draws images with and without mask with 1, 8 and 24(rgb) bits depth. +% +% width height matrix image 1|8|24 mask|false x y di +% +% width and height specify the width/height of the image, +% matrix a transformation matrix, image a procedure holding the image data +% (same for mask) and x/y an additional translation. +% +% ### should move the translation into the matrix!!! +/di +{ + gsave + translate + 1 index 1 eq { % bitmap + false eq { % no mask, draw solid background + pop + true 3 1 roll % width height false matrix image + 4 index + 4 index + false + 4 index + 4 index + imagemask + BkCol SC + imagemask + } { + pop + false 3 1 roll % width height false matrix image + imagemask + } ifelse + } { + dup false ne { + % have a mask, see if we can use it + /languagelevel where { + pop + languagelevel 3 ge + } { false } ifelse + } { + false + } ifelse + + { + % languagelevel3, we can use image mask and dicts + + % store the image mask + /ma exch d + % select colorspace according to 8|24 bit depth and set the decode array /dc + 8 eq { + /dc [0 1] d + /DeviceGray + } { + /dc [0 1 0 1 0 1] d + /DeviceRGB + } ifelse + setcolorspace + % the image data + /im exch d + % transformation matrix + /mt exch d + % width and height + /h exch def + /w exch def + % the image dict + /id + 7 dict dup begin + /ImageType 1 d + /Width w d + /Height h d + /ImageMatrix mt d + /DataSource im d + /BitsPerComponent 8 d + /Decode dc d + end d + % the mask dictionary + /md + 7 dict dup begin + /ImageType 1 d + /Width w d + /Height h d + /ImageMatrix mt d + /DataSource ma d + /BitsPerComponent 1 d + /Decode [0 1] d + end d + % and the combined image dict + 4 dict dup begin + /ImageType 3 d + /DataDict id d + /MaskDict md d + /InterleaveType 3 d + end + image + } { + pop % no mask or can't use it, get rid of it + 8 % width height image 8|24 8 matrix + 4 1 roll + 8 eq { % grayscale + image + } { %color + QCI + } ifelse + } ifelse + } ifelse + grestore +} d + + + + +/BF { % brush fill + gsave + BSt 1 eq % solid brush? + { + BCol SC + WFi { fill } { eofill } ifelse + } if + BSt 2 ge BSt 8 le and % dense pattern? + { + BDArr BSt 2 sub get /sc ED + % the following line scales the brush color according to the pattern. the higher the pattern the lighter the color. + BCol + { + 1. exch sub sc mul 1. exch sub + } forall + 3 array astore + SC + WFi { fill } { eofill } ifelse + } if + BSt 9 ge BSt 14 le and % brush pattern? + { + WFi { clip } { eoclip } ifelse + defM SM + pathbbox % left upper right lower + 3 index 3 index translate + 4 2 roll % right lower left upper + 3 2 roll % right left upper lower + exch % left right lower upper + sub /h ED + sub /w ED + OMo { + NP + 0 0 MT + 0 h RL + w 0 RL + 0 h neg RL + CP + BkCol SC + fill + } if + BCol SC + 0.3 SW + NP + BSt 9 eq BSt 11 eq or % horiz or cross pattern + { 0 4 h + { dup 0 exch MT w exch LT } for + } if + BSt 10 eq BSt 11 eq or % vert or cross pattern + { 0 4 w + { dup 0 MT h LT } for + } if + BSt 12 eq BSt 14 eq or % F-diag or diag cross + { w h gt + { 0 6 w h add + { dup 0 MT h sub h LT } for + } { 0 6 w h add + { dup 0 exch MT w sub w exch LT } for + } ifelse + } if + BSt 13 eq BSt 14 eq or % B-diag or diag cross + { w h gt + { 0 6 w h add + { dup h MT h sub 0 LT } for + } { 0 6 w h add + { dup w exch MT w sub 0 exch LT } for + } ifelse + } if + S + } if + BSt 24 eq % CustomPattern + + { + } if + grestore +} D + +% for arc +/mat matrix d +/ang1 D0 /ang2 D0 +/w D0 /h D0 +/x D0 /y D0 + +/ARC { % Generic ARC function [ X Y W H ang1 ang2 ] + /ang2 ED /ang1 ED /h ED /w ED /y ED /x ED + mat CM pop + x w 2 div add y h 2 div add TR + 1 h w div neg scale + ang2 0 ge + {0 0 w 2 div ang1 ang1 ang2 add arc } + {0 0 w 2 div ang1 ang1 ang2 add arcn} ifelse + mat SM +} D + +/C D0 + +/P { % PdcDrawPoint [x y] + NP + MT + 0.5 0.5 rmoveto + 0 -1 RL + -1 0 RL + 0 1 RL + CP + fill +} D + +/M { % PdcMoveTo [x y] + /Cy ED /Cx ED +} D + +/L { % PdcLineTo [x y] + NP + Cx Cy MT + /Cy ED /Cx ED + Cx Cy LT + QS +} D + +/DL { % PdcDrawLine [x1 y1 x0 y0] + NP + MT + LT + QS +} D + +/HL { % PdcDrawLine [x1 y x0] + 1 index DL +} D + +/VL { % PdcDrawLine [x y1 y0] + 2 index exch DL +} D + +/R { % PdcDrawRect [x y w h] + /h ED /w ED /y ED /x ED + NP + x y MT + 0 h RL + w 0 RL + 0 h neg RL + CP + BF + QS +} D + +/ACR { % add clip rect + /h ED /w ED /y ED /x ED + x y MT + 0 h RL + w 0 RL + 0 h neg RL + CP +} D + +/xr D0 /yr D0 +/rx D0 /ry D0 /rx2 D0 /ry2 D0 + +/RR { % PdcDrawRoundRect [x y w h xr yr] + /yr ED /xr ED /h ED /w ED /y ED /x ED + xr 0 le yr 0 le or + {x y w h R} % Do rect if one of rounding values is less than 0. + {xr 100 ge yr 100 ge or + {x y w h E} % Do ellipse if both rounding values are larger than 100 + { + /rx xr w mul 200 div d + /ry yr h mul 200 div d + /rx2 rx 2 mul d + /ry2 ry 2 mul d + NP + x rx add y MT + x y rx2 ry2 180 -90 + x y h add ry2 sub rx2 ry2 270 -90 + x w add rx2 sub y h add ry2 sub rx2 ry2 0 -90 + x w add rx2 sub y rx2 ry2 90 -90 + ARC ARC ARC ARC + CP + BF + QS + } ifelse + } ifelse +} D + +/E { % PdcDrawEllipse [x y w h] + /h ED /w ED /y ED /x ED + mat CM pop + x w 2 div add y h 2 div add translate + 1 h w div scale + NP + 0 0 w 2 div 0 360 arc + mat SM + BF + QS +} D + +/A { % PdcDrawArc [x y w h ang1 ang2] + 16 div exch 16 div exch + NP + ARC + QS +} D + +/PIE { % PdcDrawPie [x y w h ang1 ang2] + /ang2 ED /ang1 ED /h ED /w ED /y ED /x ED + NP + x w 2 div add y h 2 div add MT + x y w h ang1 16 div ang2 16 div ARC + CP + BF + QS +} D + +/CH { % PdcDrawChord [x y w h ang1 ang2] + 16 div exch 16 div exch + NP + ARC + CP + BF + QS +} D + +/BZ { % PdcDrawCubicBezier [4 points] + curveto + QS +} D + +/CRGB { % Compute RGB [R G B] => R/255 G/255 B/255 + 255 div 3 1 roll + 255 div 3 1 roll + 255 div 3 1 roll +} D + + +/BC { % PdcSetBkColor [R G B] + CRGB + BkCol astore pop +} D + +/BR { % PdcSetBrush [style R G B] + CRGB + BCol astore pop + /BSt ED +} D + +/WB { % set white solid brush + 1 W BR +} D + +/NB { % set nobrush + 0 B BR +} D + +/PE { % PdcSetPen [style width R G B Cap Join] + setlinejoin setlinecap + CRGB + PCol astore pop + /LWi ED + /PSt ED + LWi 0 eq { 0.25 /LWi ED } if % ### 3.0 remove this line + PCol SC +} D + +/P1 { % PdcSetPen [R G B] + 1 0 5 2 roll 0 0 PE +} D + +/ST { % SET TRANSFORM [matrix] + defM setmatrix + concat +} D + +%% Font handling + +% the next three commands are for defining fonts. The first one +% tries to find the most suitable printer font out of a fontlist. +% if encoding is false the default one will be used. +/MF { % newname encoding fontlist + % this function tries to find a suitable postscript font. + % We try quite hard not to get courier for a + % proportional font. The following takes an array of fonts. + % The algorithm will take the first font that + % gives a match (defined as not resulting in a courier font). + % each entry in the table is an array of the form [ /Fontname x-stretch slant ] + % x-strtch can be used to stretch/squeeze the font in x direction. + % This gives better results when eg substituting helvetica for arial + % slant is an optional slant. 0 is non slanted, 0.2 is a typical value for a syntetic oblique. + % encoding can be either an encoding vector of false if the default font encoding is requested. + true exch true exch % push a dummy on the stack, + { % so the loop over the array will leave a font in any case when exiting. + exch pop exch pop % (dummy | oldfont) (dummy | fontdict) fontarray + dup 0 get dup findfont % get the fontname from the array and load it + dup /FontName get % see if the font exists + 3 -1 roll eq { % see if fontname and the one provided are equal + exit + } if + } forall + exch % font fontarray + + % newname encoding font fontarray defines a postscript font + dup + 1 get /fxscale exch def % define scale, sland and encoding + 2 get /fslant exch def + exch /fencoding exch def + [ fxscale 0 fslant 1 0 0 ] makefont % transform font accordingly + fencoding false eq { % check if we have an encoding and use it if available + } { + dup maxlength dict begin % copy font + { + 1 index /FID ne % don't copy FID, as it's not allowed in PS Level 1 + {def}{pop pop}ifelse + } forall + /Encoding fencoding def % replace encoding + currentdict + end + } ifelse + definefont pop +} D + +% an embedded font. This is used for the base fonts of the composite font used later on. +/MFEmb { % newname encoding fontname + findfont dup length dict + begin + { + 1 index /FID ne + {d}{pop pop}ifelse + } forall + /Encoding ED currentdict + end + definefont pop +} D + +% DF: define font +% used to get a scaled version of an already loaded font +% +% newname pointsize fontmame DF - +/DF { + findfont + % get the fontsize on top of the stack and define font matrix + /fs 3 -1 roll d [ fs 0 0 fs -1 mul 0 0 ] + makefont + d +} D + +/ty 0 d +/Y { + /ty ED +} D + +/Tl { % draw underline/strikeout line: () w x y lw ->Tl-> () w x + gsave + setlinewidth + NP 1 index exch MT + 1 index 0 rlineto stroke + grestore +} D + +/XYT { % [string [x/y displacement array] width x] + ty MT % pops x + + /xyshow where { % interpreter has xyshow + pop pop + xyshow + } { % use ashow + exch pop % string cwidth + 1 index % string cwidth string + dup length 2 div exch % string cwidth length string !have to divide by 2 since we use unicode! + stringwidth pop % string cwidth length pwidth + 3 -1 roll % string length pwidth cwidth + exch sub exch div % string extraperchar + exch 0 exch % extraperchar 0 string + ashow + } ifelse +} D + +/AT { + ty MT % pops x + 1 index % string cwidth string + dup length 2 div exch % string cwidth length string !have to divide by 2 since we use unicode! + stringwidth pop % string cwidth length pwidth + 3 -1 roll % string length pwidth cwidth + exch sub exch div % string extraperchar + exch 0 exch % extraperchar 0 string + ashow +} D + +%% start of page +/QI { + /C save d + pageinit + /Cx 0 d % reset current x position + /Cy 0 d % reset current y position + /OMo false d +} D + +%% end of page +/QP { % show page + C restore + showpage +} D + +% merges one key value pair into the page device dict +% +% key value SPD - +/SPD { + /setpagedevice where { + 1 dict dup begin 3 1 roll def end + setpagedevice + } { pop pop } ifelse +} D + +/SV { % Save painter state + BSt LWi PSt Cx Cy WFi OMo BCol PCol BkCol + /nS nS 1 add d + gsave +} D + +/RS { % Restore painter state + nS 0 gt + { grestore + /BkCol ED /PCol ED /BCol ED /OMo ED /WFi ED + /Cy ED /Cx ED /PSt ED /LWi ED /BSt ED + /nS nS 1 sub d + } if +} D + +/CLSTART { % clipping start + /clipTmp matrix CM d % save current matrix + defM SM % Page default matrix + NP +} D + +/CLEND { % clipping end + clip + NP + clipTmp SM % restore the current matrix +} D + +/CLO { % clipping off + grestore % restore top of page state + gsave % save it back again + defM SM % set coordsys (defensive progr.) +} D + diff --git a/src/kernel/tqpsprinter_p.h b/src/kernel/tqpsprinter_p.h new file mode 100644 index 000000000..33e888c91 --- /dev/null +++ b/src/kernel/tqpsprinter_p.h @@ -0,0 +1,92 @@ +/********************************************************************** +** +** Definition of internal TQPSPrinter class. +** TQPSPrinter implements PostScript (tm) output via TQPrinter. +** +** Created : 940927 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQPSPRINTER_P_H +#define TQPSPRINTER_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of tqpsprinter.cpp and tqprinter_x11.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "tqprinter.h" +#include "tqtextstream.h" +#endif // QT_H + +#ifndef TQT_NO_PRINTER + +class TQPSPrinterPrivate; + +class TQ_EXPORT TQPSPrinter : public TQPaintDevice +{ +private: + // TQPrinter uses these + TQPSPrinter( TQPrinter *, int ); + ~TQPSPrinter(); + + bool cmd ( int, TQPainter *, TQPDevCmdParam * ); + + enum { NewPage = 100, AbortPrinting }; + + friend class TQPrinter; +private: + // not used by TQPrinter + TQPSPrinterPrivate *d; + + // Disabled copy constructor and operator= + TQPSPrinter( const TQPSPrinter & ); + TQPSPrinter &operator=( const TQPSPrinter & ); +}; + +#endif // TQT_NO_PRINTER + +#endif // TQPSPRINTER_P_H diff --git a/src/kernel/tqregion_x11.cpp b/src/kernel/tqregion_x11.cpp index 801aadb6d..a42b0f11e 100644 --- a/src/kernel/tqregion_x11.cpp +++ b/src/kernel/tqregion_x11.cpp @@ -43,7 +43,7 @@ #include "tqbuffer.h" #include "tqimage.h" #include "tqbitmap.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include diff --git a/src/kernel/tqrichtext.cpp b/src/kernel/tqrichtext.cpp new file mode 100644 index 000000000..9866a6c9c --- /dev/null +++ b/src/kernel/tqrichtext.cpp @@ -0,0 +1,8258 @@ +/**************************************************************************** +** +** Implementation of the internal TQt classes dealing with rich text +** +** Created : 990101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqrichtext_p.h" + +#ifndef TQT_NO_RICHTEXT + + +#include "tqstringlist.h" +#include "tqfont.h" +#include "tqtextstream.h" +#include "tqfile.h" +#include "ntqapplication.h" +#include "tqmap.h" +#include "tqfileinfo.h" +#include "tqstylesheet.h" +#include "tqmime.h" +#include "tqimage.h" +#include "tqdragobject.h" +#include "tqpaintdevicemetrics.h" +#include "tqpainter.h" +#include "tqdrawutil.h" +#include "tqcursor.h" +#include "tqptrstack.h" +#include "tqptrdict.h" +#include "tqstyle.h" +#include "tqcleanuphandler.h" +#include "tqtextengine_p.h" +#include + +#include + +static TQTextCursor* richTextExportStart = 0; +static TQTextCursor* richTextExportEnd = 0; + +class TQTextFormatCollection; + +const int border_tolerance = 2; + +#ifdef TQ_WS_WIN +#include "qt_windows.h" +#endif + +#define TQChar_linesep TQChar(0x2028U) + +static inline bool is_printer( TQPainter *p ) +{ + if ( !p || !p->device() ) + return FALSE; + return p->device()->devType() == TQInternal::Printer; +} + +static inline int scale( int value, TQPainter *painter ) +{ + if ( is_printer( painter ) ) { + TQPaintDeviceMetrics metrics( painter->device() ); +#if defined(TQ_WS_X11) + value = value * metrics.logicalDpiY() / + TQPaintDevice::x11AppDpiY( painter->device()->x11Screen() ); +#elif defined (TQ_WS_WIN) + HDC hdc = GetDC( 0 ); + int gdc = GetDeviceCaps( hdc, LOGPIXELSY ); + if ( gdc ) + value = value * metrics.logicalDpiY() / gdc; + ReleaseDC( 0, hdc ); +#elif defined (TQ_WS_MAC) + value = value * metrics.logicalDpiY() / 75; // ##### FIXME +#endif + } + return value; +} + + +inline bool isBreakable( TQTextString *string, int pos ) +{ + if (string->at(pos).nobreak) + return FALSE; + return (pos < string->length()-1 && string->at(pos+1).softBreak); +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void TQTextCommandHistory::addCommand( TQTextCommand *cmd ) +{ + if ( current < (int)history.count() - 1 ) { + TQPtrList commands; + commands.setAutoDelete( FALSE ); + + for( int i = 0; i <= current; ++i ) { + commands.insert( i, history.at( 0 ) ); + history.take( 0 ); + } + + commands.append( cmd ); + history.clear(); + history = commands; + history.setAutoDelete( TRUE ); + } else { + history.append( cmd ); + } + + if ( (int)history.count() > steps ) + history.removeFirst(); + else + ++current; +} + +TQTextCursor *TQTextCommandHistory::undo( TQTextCursor *c ) +{ + if ( current > -1 ) { + TQTextCursor *c2 = history.at( current )->unexecute( c ); + --current; + return c2; + } + return 0; +} + +TQTextCursor *TQTextCommandHistory::redo( TQTextCursor *c ) +{ + if ( current > -1 ) { + if ( current < (int)history.count() - 1 ) { + ++current; + return history.at( current )->execute( c ); + } + } else { + if ( history.count() > 0 ) { + ++current; + return history.at( current )->execute( c ); + } + } + return 0; +} + +bool TQTextCommandHistory::isUndoAvailable() +{ + return current > -1; +} + +bool TQTextCommandHistory::isRedoAvailable() +{ + return ( current > -1 && current < (int)history.count() - 1 ) || ( current == -1 && history.count() > 0 ); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextDeleteCommand::TQTextDeleteCommand( TQTextDocument *d, int i, int idx, const TQMemArray &str, + const TQByteArray& oldStyleInfo ) + : TQTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo ) +{ + for ( int j = 0; j < (int)text.size(); ++j ) { + if ( text[ j ].format() ) + text[ j ].format()->addRef(); + } +} + +TQTextDeleteCommand::TQTextDeleteCommand( TQTextParagraph *p, int idx, const TQMemArray &str ) + : TQTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) +{ + for ( int i = 0; i < (int)text.size(); ++i ) { + if ( text[ i ].format() ) + text[ i ].format()->addRef(); + } +} + +TQTextDeleteCommand::~TQTextDeleteCommand() +{ + for ( int i = 0; i < (int)text.size(); ++i ) { + if ( text[ i ].format() ) + text[ i ].format()->removeRef(); + } + text.resize( 0 ); +} + +TQTextCursor *TQTextDeleteCommand::execute( TQTextCursor *c ) +{ + TQTextParagraph *s = doc ? doc->paragAt( id ) : parag; + if ( !s ) { + tqWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() ); + return 0; + } + + cursor.setParagraph( s ); + cursor.setIndex( index ); + int len = text.size(); + if ( c ) + *c = cursor; + if ( doc ) { + doc->setSelectionStart( TQTextDocument::Temp, cursor ); + for ( int i = 0; i < len; ++i ) + cursor.gotoNextLetter(); + doc->setSelectionEnd( TQTextDocument::Temp, cursor ); + doc->removeSelectedText( TQTextDocument::Temp, &cursor ); + if ( c ) + *c = cursor; + } else { + s->remove( index, len ); + } + + return c; +} + +TQTextCursor *TQTextDeleteCommand::unexecute( TQTextCursor *c ) +{ + TQTextParagraph *s = doc ? doc->paragAt( id ) : parag; + if ( !s ) { + tqWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() ); + return 0; + } + + cursor.setParagraph( s ); + cursor.setIndex( index ); + TQString str = TQTextString::toString( text ); + cursor.insert( str, TRUE, &text ); + if ( c ) + *c = cursor; + cursor.setParagraph( s ); + cursor.setIndex( index ); + +#ifndef TQT_NO_DATASTREAM + if ( !styleInformation.isEmpty() ) { + TQDataStream styleStream( styleInformation, IO_ReadOnly ); + int num; + styleStream >> num; + TQTextParagraph *p = s; + while ( num-- && p ) { + p->readStyleInformation( styleStream ); + p = p->next(); + } + } +#endif + s = cursor.paragraph(); + while ( s ) { + s->format(); + s->setChanged( TRUE ); + if ( s == c->paragraph() ) + break; + s = s->next(); + } + + return &cursor; +} + +TQTextFormatCommand::TQTextFormatCommand( TQTextDocument *d, int sid, int sidx, int eid, int eidx, + const TQMemArray &old, TQTextFormat *f, int fl ) + : TQTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl ) +{ + format = d->formatCollection()->format( f ); + for ( int j = 0; j < (int)oldFormats.size(); ++j ) { + if ( oldFormats[ j ].format() ) + oldFormats[ j ].format()->addRef(); + } +} + +TQTextFormatCommand::~TQTextFormatCommand() +{ + format->removeRef(); + for ( int j = 0; j < (int)oldFormats.size(); ++j ) { + if ( oldFormats[ j ].format() ) + oldFormats[ j ].format()->removeRef(); + } +} + +TQTextCursor *TQTextFormatCommand::execute( TQTextCursor *c ) +{ + TQTextParagraph *sp = doc->paragAt( startId ); + TQTextParagraph *ep = doc->paragAt( endId ); + if ( !sp || !ep ) + return c; + + TQTextCursor start( doc ); + start.setParagraph( sp ); + start.setIndex( startIndex ); + TQTextCursor end( doc ); + end.setParagraph( ep ); + end.setIndex( endIndex ); + + doc->setSelectionStart( TQTextDocument::Temp, start ); + doc->setSelectionEnd( TQTextDocument::Temp, end ); + doc->setFormat( TQTextDocument::Temp, format, flags ); + doc->removeSelection( TQTextDocument::Temp ); + if ( endIndex == ep->length() ) + end.gotoLeft(); + *c = end; + return c; +} + +TQTextCursor *TQTextFormatCommand::unexecute( TQTextCursor *c ) +{ + TQTextParagraph *sp = doc->paragAt( startId ); + TQTextParagraph *ep = doc->paragAt( endId ); + if ( !sp || !ep ) + return 0; + + int idx = startIndex; + int fIndex = 0; + while ( fIndex < int(oldFormats.size()) ) { + if ( oldFormats.at( fIndex ).c == '\n' ) { + if ( idx > 0 ) { + if ( idx < sp->length() && fIndex > 0 ) + sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() ); + if ( sp == ep ) + break; + sp = sp->next(); + idx = 0; + } + fIndex++; + } + if ( oldFormats.at( fIndex ).format() ) + sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() ); + idx++; + fIndex++; + if ( fIndex >= (int)oldFormats.size() ) + break; + if ( idx >= sp->length() ) { + if ( sp == ep ) + break; + sp = sp->next(); + idx = 0; + } + } + + TQTextCursor end( doc ); + end.setParagraph( ep ); + end.setIndex( endIndex ); + if ( endIndex == ep->length() ) + end.gotoLeft(); + *c = end; + return c; +} + +TQTextStyleCommand::TQTextStyleCommand( TQTextDocument *d, int fParag, int lParag, const TQByteArray& beforeChange ) + : TQTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange ) +{ + after = readStyleInformation( d, fParag, lParag ); +} + + +TQByteArray TQTextStyleCommand::readStyleInformation( TQTextDocument* doc, int fParag, int lParag ) +{ + TQByteArray style; +#ifndef TQT_NO_DATASTREAM + TQTextParagraph *p = doc->paragAt( fParag ); + if ( !p ) + return style; + TQDataStream styleStream( style, IO_WriteOnly ); + int num = lParag - fParag + 1; + styleStream << num; + while ( num -- && p ) { + p->writeStyleInformation( styleStream ); + p = p->next(); + } +#endif + return style; +} + +void TQTextStyleCommand::writeStyleInformation( TQTextDocument* doc, int fParag, const TQByteArray& style ) +{ +#ifndef TQT_NO_DATASTREAM + TQTextParagraph *p = doc->paragAt( fParag ); + if ( !p ) + return; + TQDataStream styleStream( style, IO_ReadOnly ); + int num; + styleStream >> num; + while ( num-- && p ) { + p->readStyleInformation( styleStream ); + p = p->next(); + } +#endif +} + +TQTextCursor *TQTextStyleCommand::execute( TQTextCursor *c ) +{ + writeStyleInformation( doc, firstParag, after ); + return c; +} + +TQTextCursor *TQTextStyleCommand::unexecute( TQTextCursor *c ) +{ + writeStyleInformation( doc, firstParag, before ); + return c; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextCursor::TQTextCursor( TQTextDocument *d ) + : idx( 0 ), tmpX( -1 ), ox( 0 ), oy( 0 ), + valid( TRUE ) +{ + para = d ? d->firstParagraph() : 0; +} + +TQTextCursor::TQTextCursor( const TQTextCursor &c ) +{ + ox = c.ox; + oy = c.oy; + idx = c.idx; + para = c.para; + tmpX = c.tmpX; + indices = c.indices; + paras = c.paras; + xOffsets = c.xOffsets; + yOffsets = c.yOffsets; + valid = c.valid; +} + +TQTextCursor &TQTextCursor::operator=( const TQTextCursor &c ) +{ + ox = c.ox; + oy = c.oy; + idx = c.idx; + para = c.para; + tmpX = c.tmpX; + indices = c.indices; + paras = c.paras; + xOffsets = c.xOffsets; + yOffsets = c.yOffsets; + valid = c.valid; + + return *this; +} + +bool TQTextCursor::operator==( const TQTextCursor &c ) const +{ + return para == c.para && idx == c.idx; +} + +int TQTextCursor::totalOffsetX() const +{ + int xoff = ox; + for ( TQValueStack::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit ) + xoff += *xit; + return xoff; +} + +int TQTextCursor::totalOffsetY() const +{ + int yoff = oy; + for ( TQValueStack::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit ) + yoff += *yit; + return yoff; +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +void TQTextCursor::gotoIntoNested( const TQPoint &globalPos ) +{ + if ( !para ) + return; + Q_ASSERT( para->at( idx )->isCustom() ); + push(); + ox = 0; + int bl, y; + para->lineHeightOfChar( idx, &bl, &y ); + oy = y + para->rect().y(); + ox = para->at( idx )->x; + TQTextDocument* doc = document(); + para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, globalPos-TQPoint(ox,oy) ); +} +#endif + +void TQTextCursor::invalidateNested() +{ + if ( nestedDepth() ) { + TQValueStack::Iterator it = paras.begin(); + TQValueStack::Iterator it2 = indices.begin(); + for ( ; it != paras.end(); ++it, ++it2 ) { + if ( *it == para ) + continue; + (*it)->invalidate( 0 ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( (*it)->at( *it2 )->isCustom() ) + (*it)->at( *it2 )->customItem()->invalidate(); +#endif + } + } +} + +void TQTextCursor::insert( const TQString &str, bool checkNewLine, TQMemArray *formatting ) +{ + tmpX = -1; + bool justInsert = TRUE; + TQString s( str ); +#if defined(TQ_WS_WIN) + if ( checkNewLine ) { + int i = 0; + while ( ( i = s.find( '\r', i ) ) != -1 ) + s.remove( i ,1 ); + } +#endif + if ( checkNewLine ) + justInsert = s.find( '\n' ) == -1; + if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index + para->insert( idx, s.unicode(), s.length() ); + if ( formatting ) { + for ( int i = 0; i < (int)s.length(); ++i ) { + if ( formatting->at( i ).format() ) { + formatting->at( i ).format()->addRef(); + para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); + } + } + } + idx += s.length(); + } else { // we split at new lines + int start = -1; + int end; + int y = para->rect().y() + para->rect().height(); + int lastIndex = 0; + do { + end = s.find( '\n', start + 1 ); // find line break + if ( end == -1 ) // didn't find one, so end of line is end of string + end = s.length(); + int len = (start == -1 ? end : end - start - 1); + if ( len > 0 ) // insert the line + para->insert( idx, s.unicode() + start + 1, len ); + else + para->invalidate( 0 ); + if ( formatting ) { // set formats to the chars of the line + for ( int i = 0; i < len; ++i ) { + if ( formatting->at( i + lastIndex ).format() ) { + formatting->at( i + lastIndex ).format()->addRef(); + para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); + } + } + lastIndex += len; + } + start = end; // next start is at the end of this line + idx += len; // increase the index of the cursor to the end of the inserted text + if ( s[end] == '\n' ) { // if at the end was a line break, break the line + splitAndInsertEmptyParagraph( FALSE, TRUE ); + para->setEndState( -1 ); + para->prev()->format( -1, FALSE ); + lastIndex++; + } + + } while ( end < (int)s.length() ); + + para->format( -1, FALSE ); + int dy = para->rect().y() + para->rect().height() - y; + TQTextParagraph *p = para; + p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); + p = p->next(); + while ( p ) { + p->setParagId( p->prev()->paragId() + 1 ); + p->move( dy ); + p->invalidate( 0 ); + p->setEndState( -1 ); + p = p->next(); + } + } + + int h = para->rect().height(); + para->format( -1, TRUE ); + if ( h != para->rect().height() ) + invalidateNested(); + else if ( para->document() && para->document()->parent() ) + para->document()->nextDoubleBuffered = TRUE; + + fixCursorPosition(); +} + +void TQTextCursor::gotoLeft() +{ + if ( para->string()->isRightToLeft() ) + gotoNextLetter(); + else + gotoPreviousLetter(); +} + +void TQTextCursor::gotoPreviousLetter() +{ + tmpX = -1; + + if ( idx > 0 ) { + idx = para->string()->previousCursorPosition( idx ); +#ifndef TQT_NO_TEXTCUSTOMITEM + const TQTextStringChar *tsc = para->at( idx ); + if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) + processNesting( EnterEnd ); +#endif + } else if ( para->prev() ) { + para = para->prev(); + while ( !para->isVisible() && para->prev() ) + para = para->prev(); + idx = para->length() - 1; + } else if ( nestedDepth() ) { + pop(); + processNesting( Prev ); + if ( idx == -1 ) { + pop(); + if ( idx > 0 ) { + idx = para->string()->previousCursorPosition( idx ); +#ifndef TQT_NO_TEXTCUSTOMITEM + const TQTextStringChar *tsc = para->at( idx ); + if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) + processNesting( EnterEnd ); +#endif + } else if ( para->prev() ) { + para = para->prev(); + idx = para->length() - 1; + } + } + } +} + +void TQTextCursor::push() +{ + indices.push( idx ); + paras.push( para ); + xOffsets.push( ox ); + yOffsets.push( oy ); +} + +void TQTextCursor::pop() +{ + if ( indices.isEmpty() ) + return; + idx = indices.pop(); + para = paras.pop(); + ox = xOffsets.pop(); + oy = yOffsets.pop(); +} + +void TQTextCursor::restoreState() +{ + while ( !indices.isEmpty() ) + pop(); +} + +bool TQTextCursor::place( const TQPoint &p, TQTextParagraph *s, bool link, bool loosePlacing, bool matchBetweenCharacters ) +{ + TQPoint pos( p ); + TQRect r; + TQTextParagraph *str = s; + if ( pos.y() < s->rect().y() ) { + pos.setY( s->rect().y() ); +#ifdef TQ_WS_MACX + pos.setX( s->rect().x() ); +#endif + } + while ( s ) { + r = s->rect(); + r.setWidth( document() ? document()->width() : TQWIDGETSIZE_MAX ); + if ( s->isVisible() ) + str = s; + if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() ) + break; + if ( loosePlacing == TRUE && !s->next() ) { +#ifdef TQ_WS_MACX + pos.setX( s->rect().x() + s->rect().width() ); +#endif + break; + } + s = s->next(); + } + + if ( !s || !str ) + return FALSE; + + s = str; + + setParagraph( s ); + int y = s->rect().y(); + int lines = s->lines(); + TQTextStringChar *chr = 0; + int index = 0; + int i = 0; + int cy = 0; + int ch = 0; + for ( ; i < lines; ++i ) { + chr = s->lineStartOfLine( i, &index ); + cy = s->lineY( i ); + ch = s->lineHeight( i ); + if ( !chr ) + return FALSE; + if ( pos.y() <= y + cy + ch ) + break; + } + int nextLine; + if ( i < lines - 1 ) + s->lineStartOfLine( i+1, &nextLine ); + else + nextLine = s->length(); + i = index; + int x = s->rect().x(); + if ( pos.x() < x ) + pos.setX( x + 1 ); + int cw; + int curpos = -1; + int dist = 10000000; + bool inCustom = FALSE; + while ( i < nextLine ) { + chr = s->at(i); + int cpos = x + chr->x; + cw = s->string()->width( i ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( chr->isCustom() && chr->customItem()->isNested() ) { + if ( pos.x() >= cpos && pos.x() <= cpos + cw && + pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) { + inCustom = TRUE; + curpos = i; + break; + } + } else +#endif + { + if( chr->rightToLeft ) + cpos += cw; + int d = cpos - pos.x(); + bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft; + if ( ( matchBetweenCharacters == TRUE && (TQABS( d ) < dist || (dist == d && dm == TRUE )) && para->string()->validCursorPosition( i ) ) || + ( matchBetweenCharacters == FALSE && ( d == 0 || dm == TRUE ) ) ) { + dist = TQABS( d ); + if ( !link || ( pos.x() >= x + chr->x && ( loosePlacing == TRUE || pos.x() < cpos ) ) ) + curpos = i; + } + } + i++; + } + if ( curpos == -1 ) { + if ( loosePlacing == TRUE ) + curpos = s->length()-1; + else + return FALSE; + } + setIndex( curpos ); + +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) { + TQTextDocument *oldDoc = para->document(); + gotoIntoNested( pos ); + if ( oldDoc == para->document() ) + return TRUE; + TQPoint p( pos.x() - offsetX(), pos.y() - offsetY() ); + if ( !place( p, document()->firstParagraph(), link ) ) + pop(); + } +#endif + return TRUE; +} + +bool TQTextCursor::processNesting( Operation op ) +{ + if ( !para->document() ) + return FALSE; + TQTextDocument* doc = para->document(); + push(); + ox = para->at( idx )->x; + int bl, y; + para->lineHeightOfChar( idx, &bl, &y ); + oy = y + para->rect().y(); + bool ok = FALSE; + +#ifndef TQT_NO_TEXTCUSTOMITEM + switch ( op ) { + case EnterBegin: + ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy ); + break; + case EnterEnd: + ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE ); + break; + case Next: + ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy ); + break; + case Prev: + ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy ); + break; + case Down: + ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy ); + break; + case Up: + ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy ); + break; + } + if ( !ok ) +#endif + pop(); + return ok; +} + +void TQTextCursor::gotoRight() +{ + if ( para->string()->isRightToLeft() ) + gotoPreviousLetter(); + else + gotoNextLetter(); +} + +void TQTextCursor::gotoNextLetter() +{ + tmpX = -1; + +#ifndef TQT_NO_TEXTCUSTOMITEM + const TQTextStringChar *tsc = para->at( idx ); + if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { + if ( processNesting( EnterBegin ) ) + return; + } +#endif + + if ( idx < para->length() - 1 ) { + idx = para->string()->nextCursorPosition( idx ); + } else if ( para->next() ) { + para = para->next(); + while ( !para->isVisible() && para->next() ) + para = para->next(); + idx = 0; + } else if ( nestedDepth() ) { + pop(); + processNesting( Next ); + if ( idx == -1 ) { + pop(); + if ( idx < para->length() - 1 ) { + idx = para->string()->nextCursorPosition( idx ); + } else if ( para->next() ) { + para = para->next(); + idx = 0; + } + } + } +} + +void TQTextCursor::gotoUp() +{ + int indexOfLineStart; + int line; + TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); + if ( !c ) + return; + + if (tmpX < 0) + tmpX = x(); + + if ( indexOfLineStart == 0 ) { + if ( !para->prev() ) { + if ( !nestedDepth() ) + return; + pop(); + processNesting( Up ); + if ( idx == -1 ) { + pop(); + if ( !para->prev() ) + return; + idx = tmpX = 0; + } else { + tmpX = -1; + return; + } + } + TQTextParagraph *p = para->prev(); + while ( p && !p->isVisible() ) + p = p->prev(); + if ( p ) + para = p; + int lastLine = para->lines() - 1; + if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) ) + return; + idx = indexOfLineStart; + while (idx < para->length()-1 && para->at(idx)->x < tmpX) + ++idx; + if (idx > indexOfLineStart && + para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) + --idx; + } else { + --line; + int oldIndexOfLineStart = indexOfLineStart; + if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) + return; + idx = indexOfLineStart; + while (idx < oldIndexOfLineStart-1 && para->at(idx)->x < tmpX) + ++idx; + if (idx > indexOfLineStart && + para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) + --idx; + } + fixCursorPosition(); +} + +void TQTextCursor::gotoDown() +{ + int indexOfLineStart; + int line; + TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); + if ( !c ) + return; + + if (tmpX < 0) + tmpX = x(); + if ( line == para->lines() - 1 ) { + if ( !para->next() ) { + if ( !nestedDepth() ) + return; + pop(); + processNesting( Down ); + if ( idx == -1 ) { + pop(); + if ( !para->next() ) + return; + idx = tmpX = 0; + } else { + tmpX = -1; + return; + } + } + TQTextParagraph *s = para->next(); + while ( s && !s->isVisible() ) + s = s->next(); + if ( s ) + para = s; + if ( !para->lineStartOfLine( 0, &indexOfLineStart ) ) + return; + int end; + if ( para->lines() == 1 ) + end = para->length(); + else + para->lineStartOfLine( 1, &end ); + + idx = indexOfLineStart; + while (idx < end-1 && para->at(idx)->x < tmpX) + ++idx; + if (idx > indexOfLineStart && + para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) + --idx; + } else { + ++line; + int end; + if ( line == para->lines() - 1 ) + end = para->length(); + else + para->lineStartOfLine( line + 1, &end ); + if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) + return; + idx = indexOfLineStart; + while (idx < end-1 && para->at(idx)->x < tmpX) + ++idx; + if (idx > indexOfLineStart && + para->at(idx)->x - tmpX > tmpX - para->at(idx-1)->x) + --idx; + } + fixCursorPosition(); +} + +void TQTextCursor::gotoLineEnd() +{ + tmpX = -1; + int indexOfLineStart; + int line; + TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); + if ( !c ) + return; + + if ( line == para->lines() - 1 ) { + idx = para->length() - 1; + } else { + c = para->lineStartOfLine( ++line, &indexOfLineStart ); + indexOfLineStart--; + idx = indexOfLineStart; + } +} + +void TQTextCursor::gotoLineStart() +{ + tmpX = -1; + int indexOfLineStart; + int line; + TQTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); + if ( !c ) + return; + + idx = indexOfLineStart; +} + +void TQTextCursor::gotoHome() +{ + if ( topParagraph()->document() ) + gotoPosition( topParagraph()->document()->firstParagraph() ); + else + gotoLineStart(); +} + +void TQTextCursor::gotoEnd() +{ + if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() ) + gotoPosition( topParagraph()->document()->lastParagraph(), + topParagraph()->document()->lastParagraph()->length() - 1); + else + gotoLineEnd(); +} + +void TQTextCursor::gotoPageUp( int visibleHeight ) +{ + int targetY = globalY() - visibleHeight; + TQTextParagraph* old; int index; + do { + old = para; index = idx; + gotoUp(); + } while ( (old != para || index != idx) && globalY() > targetY ); +} + +void TQTextCursor::gotoPageDown( int visibleHeight ) +{ + int targetY = globalY() + visibleHeight; + TQTextParagraph* old; int index; + do { + old = para; index = idx; + gotoDown(); + } while ( (old != para || index != idx) && globalY() < targetY ); +} + +void TQTextCursor::gotoWordRight() +{ + if ( para->string()->isRightToLeft() ) + gotoPreviousWord(); + else + gotoNextWord(); +} + +void TQTextCursor::gotoWordLeft() +{ + if ( para->string()->isRightToLeft() ) + gotoNextWord(); + else + gotoPreviousWord(); +} + +static bool is_seperator( const TQChar &c, bool onlySpace ) +{ + if ( onlySpace ) + return c.isSpace(); + return c.isSpace() || + c == '\t' || + c == '.' || + c == ',' || + c == ':' || + c == ';' || + c == '-' || + c == '<' || + c == '>' || + c == '[' || + c == ']' || + c == '(' || + c == ')' || + c == '{' || + c == '}'; +} + +void TQTextCursor::gotoPreviousWord( bool onlySpace ) +{ + gotoPreviousLetter(); + tmpX = -1; + TQTextString *s = para->string(); + bool allowSame = FALSE; + if ( idx == ((int)s->length()-1) ) + return; + for ( int i = idx; i >= 0; --i ) { + if ( is_seperator( s->at( i ).c, onlySpace ) ) { + if ( !allowSame ) + continue; + idx = i + 1; + return; + } + if ( !allowSame && !is_seperator( s->at( i ).c, onlySpace ) ) + allowSame = TRUE; + } + idx = 0; +} + +void TQTextCursor::gotoNextWord( bool onlySpace ) +{ + tmpX = -1; + TQTextString *s = para->string(); + bool allowSame = FALSE; + for ( int i = idx; i < (int)s->length(); ++i ) { + if ( !is_seperator( s->at( i ).c, onlySpace ) ) { + if ( !allowSame ) + continue; + idx = i; + return; + } + if ( !allowSame && is_seperator( s->at( i ).c, onlySpace ) ) + allowSame = TRUE; + + } + + if ( idx < ((int)s->length()-1) ) { + gotoLineEnd(); + } else if ( para->next() ) { + TQTextParagraph *p = para->next(); + while ( p && !p->isVisible() ) + p = p->next(); + if ( s ) { + para = p; + idx = 0; + } + } else { + gotoLineEnd(); + } +} + +bool TQTextCursor::atParagStart() +{ + return idx == 0; +} + +bool TQTextCursor::atParagEnd() +{ + return idx == para->length() - 1; +} + +void TQTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds ) +{ + if ( !para->document() ) + return; + tmpX = -1; + TQTextFormat *f = 0; + if ( para->document()->useFormatCollection() ) { + f = para->at( idx )->format(); + if ( idx == para->length() - 1 && idx > 0 ) + f = para->at( idx - 1 )->format(); + if ( f->isMisspelled() ) { + f->removeRef(); + f = para->document()->formatCollection()->format( f->font(), f->color() ); + } + } + + if ( atParagEnd() ) { + TQTextParagraph *n = para->next(); + TQTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); + if ( f ) + s->setFormat( 0, 1, f, TRUE ); + s->copyParagData( para ); + if ( ind ) { + int oi, ni; + s->indent( &oi, &ni ); + para = s; + idx = ni; + } else { + para = s; + idx = 0; + } + } else if ( atParagStart() ) { + TQTextParagraph *p = para->prev(); + TQTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds ); + if ( f ) + s->setFormat( 0, 1, f, TRUE ); + s->copyParagData( para ); + if ( ind ) { + s->indent(); + s->format(); + indent(); + para->format(); + } + } else { + TQString str = para->string()->toString().mid( idx, 0xFFFFFF ); + TQTextParagraph *n = para->next(); + TQTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); + s->copyParagData( para ); + s->remove( 0, 1 ); + s->append( str, TRUE ); + for ( uint i = 0; i < str.length(); ++i ) { + TQTextStringChar* tsc = para->at( idx + i ); + s->setFormat( i, 1, tsc->format(), TRUE ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( tsc->isCustom() ) { + TQTextCustomItem * item = tsc->customItem(); + s->at( i )->setCustomItem( item ); + tsc->loseCustomItem(); + } +#endif + if ( tsc->isAnchor() ) + s->at( i )->setAnchor( tsc->anchorName(), + tsc->anchorHref() ); + } + para->truncate( idx ); + if ( ind ) { + int oi, ni; + s->indent( &oi, &ni ); + para = s; + idx = ni; + } else { + para = s; + idx = 0; + } + } + + invalidateNested(); +} + +bool TQTextCursor::remove() +{ + tmpX = -1; + if ( !atParagEnd() ) { + int next = para->string()->nextCursorPosition( idx ); + para->remove( idx, next-idx ); + int h = para->rect().height(); + para->format( -1, TRUE ); + if ( h != para->rect().height() ) + invalidateNested(); + else if ( para->document() && para->document()->parent() ) + para->document()->nextDoubleBuffered = TRUE; + return FALSE; + } else if ( para->next() ) { + para->join( para->next() ); + invalidateNested(); + return TRUE; + } + return FALSE; +} + +/* needed to implement backspace the correct way */ +bool TQTextCursor::removePreviousChar() +{ + tmpX = -1; + if ( !atParagStart() ) { + para->remove( idx-1, 1 ); + int h = para->rect().height(); + idx--; + // shouldn't be needed, just to make sure. + fixCursorPosition(); + para->format( -1, TRUE ); + if ( h != para->rect().height() ) + invalidateNested(); + else if ( para->document() && para->document()->parent() ) + para->document()->nextDoubleBuffered = TRUE; + return FALSE; + } else if ( para->prev() ) { + para = para->prev(); + para->join( para->next() ); + invalidateNested(); + return TRUE; + } + return FALSE; +} + +void TQTextCursor::indent() +{ + int oi = 0, ni = 0; + para->indent( &oi, &ni ); + if ( oi == ni ) + return; + + if ( idx >= oi ) + idx += ni - oi; + else + idx = ni; +} + +void TQTextCursor::fixCursorPosition() +{ + // searches for the closest valid cursor position + if ( para->string()->validCursorPosition( idx ) ) + return; + + int lineIdx; + TQTextStringChar *start = para->lineStartOfChar( idx, &lineIdx, 0 ); + int x = para->string()->at( idx ).x; + int diff = TQABS(start->x - x); + int best = lineIdx; + + TQTextStringChar *c = start; + ++c; + + TQTextStringChar *end = ¶->string()->at( para->length()-1 ); + while ( c <= end && !c->lineStart ) { + int xp = c->x; + if ( c->rightToLeft ) + xp += para->string()->width( lineIdx + (c-start) ); + int ndiff = TQABS(xp - x); + if ( ndiff < diff && para->string()->validCursorPosition(lineIdx + (c-start)) ) { + diff = ndiff; + best = lineIdx + (c-start); + } + ++c; + } + idx = best; +} + + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextDocument::TQTextDocument( TQTextDocument *p ) + : par( p ), parentPar( 0 ) +#ifndef TQT_NO_TEXTCUSTOMITEM + , tc( 0 ) +#endif + , tArray( 0 ), tStopWidth( 0 ) +{ + fCollection = par ? par->fCollection : new TQTextFormatCollection; + init(); +} + +void TQTextDocument::init() +{ + oTextValid = TRUE; + mightHaveCustomItems = FALSE; + if ( par ) + par->insertChild( this ); + pProcessor = 0; + useFC = TRUE; + pFormatter = 0; + indenter = 0; + fParag = 0; + txtFormat = TQt::AutoText; + preferRichText = FALSE; + pages = FALSE; + focusIndicator.parag = 0; + minw = 0; + wused = 0; + minwParag = curParag = 0; + align = AlignAuto; + nSelections = 1; + + setStyleSheet( TQStyleSheet::defaultSheet() ); +#ifndef TQT_NO_MIME + factory_ = TQMimeSourceFactory::defaultFactory(); +#endif + contxt = TQString::null; + + underlLinks = par ? par->underlLinks : TRUE; + backBrush = 0; + buf_pixmap = 0; + nextDoubleBuffered = FALSE; + + if ( par ) + withoutDoubleBuffer = par->withoutDoubleBuffer; + else + withoutDoubleBuffer = FALSE; + + lParag = fParag = createParagraph( this, 0, 0 ); + + cx = 0; + cy = 2; + if ( par ) + cx = cy = 0; + cw = 600; + vw = 0; + flow_ = new TQTextFlow; + flow_->setWidth( cw ); + + leftmargin = rightmargin = 4; + scaleFontsFactor = 1; + + + selectionColors[ Standard ] = TQApplication::palette().color( TQPalette::Active, TQColorGroup::Highlight ); + selectionText[ Standard ] = TRUE; + selectionText[ IMSelectionText ] = TRUE; + selectionText[ IMCompositionText ] = FALSE; + commandHistory = new TQTextCommandHistory( 100 ); + tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; +} + +TQTextDocument::~TQTextDocument() +{ + delete commandHistory; + if ( par ) + par->removeChild( this ); + clear(); + delete flow_; + if ( !par ) { + delete pFormatter; + delete fCollection; + } + delete pProcessor; + delete buf_pixmap; + delete indenter; + delete backBrush; + delete [] tArray; +} + +void TQTextDocument::clear( bool createEmptyParag ) +{ + while ( fParag ) { + TQTextParagraph *p = fParag->next(); + delete fParag; + fParag = p; + } + if ( flow_ ) + flow_->clear(); + fParag = lParag = 0; + if ( createEmptyParag ) + fParag = lParag = createParagraph( this ); + focusIndicator.parag = 0; + selections.clear(); + oText = TQString::null; + oTextValid = FALSE; +} + +int TQTextDocument::widthUsed() const +{ + return wused + 2*border_tolerance; +} + +int TQTextDocument::height() const +{ + int h = 0; + if ( lParag ) + h = lParag->rect().top() + lParag->rect().height() + 1; + int fh = flow_->boundingRect().bottom(); + return TQMAX( h, fh ); +} + + + +TQTextParagraph *TQTextDocument::createParagraph( TQTextDocument *d, TQTextParagraph *pr, TQTextParagraph *nx, bool updateIds ) +{ + return new TQTextParagraph( d, pr, nx, updateIds ); +} + +bool TQTextDocument::setMinimumWidth( int needed, int used, TQTextParagraph *p ) +{ + if ( needed == -1 ) { + minw = 0; + wused = 0; + p = 0; + } + if ( p == minwParag ) { + if (minw > needed) { + TQTextParagraph *tp = fParag; + while (tp) { + if (tp != p && tp->minwidth > needed) { + needed = tp->minwidth; + minwParag = tp; + } + tp = tp->n; + } + } + minw = needed; + emit minimumWidthChanged( minw ); + } else if ( needed > minw ) { + minw = needed; + minwParag = p; + emit minimumWidthChanged( minw ); + } + wused = TQMAX( wused, used ); + wused = TQMAX( wused, minw ); + cw = TQMAX( minw, cw ); + return TRUE; +} + +void TQTextDocument::setPlainText( const TQString &text ) +{ + preferRichText = FALSE; + clear(); + oTextValid = TRUE; + oText = text; + + int lastNl = 0; + int nl = text.find( '\n' ); + if ( nl == -1 ) { + lParag = createParagraph( this, lParag, 0 ); + if ( !fParag ) + fParag = lParag; + TQString s = text; + if ( !s.isEmpty() ) { + if ( s[ (int)s.length() - 1 ] == '\r' ) + s.remove( s.length() - 1, 1 ); + lParag->append( s ); + } + } else { + for (;;) { + lParag = createParagraph( this, lParag, 0 ); + if ( !fParag ) + fParag = lParag; + int l = nl - lastNl; + if ( l > 0 ) { + if (text.unicode()[nl-1] == '\r') + l--; + TQConstString cs(text.unicode()+lastNl, l); + lParag->append( cs.string() ); + } + if ( nl == (int)text.length() ) + break; + lastNl = nl + 1; + nl = text.find( '\n', nl + 1 ); + if ( nl == -1 ) + nl = text.length(); + } + } + if ( !lParag ) + lParag = fParag = createParagraph( this, 0, 0 ); +} + +struct TQ_EXPORT TQTextDocumentTag { + TQTextDocumentTag(){} + TQTextDocumentTag( const TQString&n, const TQStyleSheetItem* s, const TQTextFormat& f ) + :name(n),style(s), format(f), alignment(TQt::AlignAuto), direction(TQChar::DirON),liststyle(TQStyleSheetItem::ListDisc) { + wsm = TQStyleSheetItem::WhiteSpaceNormal; + } + TQString name; + const TQStyleSheetItem* style; + TQString anchorHref; + TQStyleSheetItem::WhiteSpaceMode wsm; + TQTextFormat format; + int alignment : 16; + int direction : 5; + TQStyleSheetItem::ListStyle liststyle; + + TQTextDocumentTag( const TQTextDocumentTag& t ) { + name = t.name; + style = t.style; + anchorHref = t.anchorHref; + wsm = t.wsm; + format = t.format; + alignment = t.alignment; + direction = t.direction; + liststyle = t.liststyle; + } + TQTextDocumentTag& operator=(const TQTextDocumentTag& t) { + name = t.name; + style = t.style; + anchorHref = t.anchorHref; + wsm = t.wsm; + format = t.format; + alignment = t.alignment; + direction = t.direction; + liststyle = t.liststyle; + return *this; + } + + TQ_DUMMY_COMPARISON_OPERATOR(TQTextDocumentTag) +}; + + +#define NEWPAR do{ if ( !hasNewPar) { \ + if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == TQChar_linesep ) \ + curpar->remove( curpar->length()-2, 1 ); \ + curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \ + hasNewPar = TRUE; \ + curpar->rtext = TRUE; \ + curpar->align = curtag.alignment; \ + curpar->lstyle = curtag.liststyle; \ + curpar->litem = ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ); \ + curpar->str->setDirection( (TQChar::Direction)curtag.direction ); \ + space = TRUE; \ + tabExpansionColumn = 0; \ + delete vec; vec = new TQPtrVector( (uint)tags.count() + 1); \ + int i = 0; \ + for ( TQValueStack::Iterator it = tags.begin(); it != tags.end(); ++it ) \ + vec->insert( i++, (*it).style ); \ + vec->insert( i, curtag.style ); \ + }while(FALSE); + + +void TQTextDocument::setRichText( const TQString &text, const TQString &context, const TQTextFormat *initialFormat ) +{ + preferRichText = TRUE; + if ( !context.isEmpty() ) + setContext( context ); + clear(); + fParag = lParag = createParagraph( this ); + oTextValid = TRUE; + oText = text; + setRichTextInternal( text, 0, initialFormat ); + fParag->rtext = TRUE; +} + +void TQTextDocument::setRichTextInternal( const TQString &text, TQTextCursor* cursor, const TQTextFormat *initialFormat ) +{ + TQTextParagraph* curpar = lParag; + int pos = 0; + TQValueStack tags; + if ( !initialFormat ) + initialFormat = formatCollection()->defaultFormat(); + TQTextDocumentTag initag( "", sheet_->item(""), *initialFormat ); + if ( bodyText.isValid() ) + initag.format.setColor( bodyText ); + TQTextDocumentTag curtag = initag; + bool space = TRUE; + bool canMergeLi = FALSE; + + bool textEditMode = FALSE; + int tabExpansionColumn = 0; + + const TQChar* doc = text.unicode(); + int length = text.length(); + bool hasNewPar = curpar->length() <= 1; + TQString anchorName; + + // style sheet handling for margin and line spacing calculation below + TQTextParagraph* stylesPar = curpar; + TQPtrVector* vec = 0; + TQPtrList< TQPtrVector > styles; + styles.setAutoDelete( TRUE ); + + if ( cursor ) { + cursor->splitAndInsertEmptyParagraph(); + TQTextCursor tmp = *cursor; + tmp.gotoPreviousLetter(); + stylesPar = curpar = tmp.paragraph(); + hasNewPar = TRUE; + textEditMode = TRUE; + } else { + NEWPAR; + } + + // set rtext spacing to FALSE for the initial paragraph. + curpar->rtext = FALSE; + + TQString wellKnownTags = "br hr wsp table qt body meta title"; + + while ( pos < length ) { + if ( hasPrefix(doc, length, pos, '<' ) ){ + if ( !hasPrefix( doc, length, pos+1, TQChar('/') ) ) { + // open tag + TQMap attr; + bool emptyTag = FALSE; + TQString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); + if ( tagname.isEmpty() ) + continue; // nothing we could do with this, probably parse error + + const TQStyleSheetItem* nstyle = sheet_->item(tagname); + + if ( nstyle ) { + // we might have to close some 'forgotten' tags + while ( !nstyle->allowedInContext( curtag.style ) ) { + TQString msg; + msg.sprintf( "TQText Warning: Document not valid ( '%s' not allowed in '%s' #%d)", + tagname.ascii(), curtag.style->name().ascii(), pos); + sheet_->error( msg ); + if ( tags.isEmpty() ) + break; + curtag = tags.pop(); + } + + /* special handling for p and li for HTML + compatibility. We do not want to embed blocks in + p, and we do not want new blocks inside non-empty + lis. Plus we want to merge empty lis sometimes. */ + if( nstyle->displayMode() == TQStyleSheetItem::DisplayListItem ) { + canMergeLi = TRUE; + } else if ( nstyle->displayMode() == TQStyleSheetItem::DisplayBlock ) { + while ( curtag.style->name() == "p" ) { + if ( tags.isEmpty() ) + break; + curtag = tags.pop(); + } + + if ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ) { + // we are in a li and a new block comes along + if ( nstyle->name() == "ul" || nstyle->name() == "ol" ) + hasNewPar = FALSE; // we want an empty li (like most browsers) + if ( !hasNewPar ) { + /* do not add new blocks inside + non-empty lis */ + while ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ) { + if ( tags.isEmpty() ) + break; + curtag = tags.pop(); + } + } else if ( canMergeLi ) { + /* we have an empty li and a block + comes along, merge them */ + nstyle = curtag.style; + } + canMergeLi = FALSE; + } + } + } + +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextCustomItem* custom = 0; +#else + bool custom = FALSE; +#endif + + // some well-known tags, some have a nstyle, some not + if ( wellKnownTags.find( tagname ) != -1 ) { + if ( tagname == "br" ) { + emptyTag = space = TRUE; + int index = TQMAX( curpar->length(),1) - 1; + TQTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); + curpar->append( TQChar_linesep ); + curpar->setFormat( index, 1, &format ); + hasNewPar = false; + } else if ( tagname == "hr" ) { + emptyTag = space = TRUE; +#ifndef TQT_NO_TEXTCUSTOMITEM + custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); +#endif + } else if ( tagname == "table" ) { + emptyTag = space = TRUE; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); + curpar->setAlignment( curtag.alignment ); + custom = parseTable( attr, format, doc, length, pos, curpar ); +#endif + } else if ( tagname == "qt" || tagname == "body" ) { + if ( attr.contains( "bgcolor" ) ) { + TQBrush *b = new TQBrush( TQColor( attr["bgcolor"] ) ); + setPaper( b ); + } + if ( attr.contains( "background" ) ) { +#ifndef TQT_NO_MIME + TQImage img; + TQString bg = attr["background"]; + const TQMimeSource* m = factory_->data( bg, contxt ); + if ( !m ) { + tqWarning("TQRichText: no mimesource for %s", bg.latin1() ); + } else { + if ( !TQImageDrag::decode( m, img ) ) { + tqWarning("TQTextImage: cannot decode %s", bg.latin1() ); + } + } + if ( !img.isNull() ) { + TQBrush *b = new TQBrush( TQColor(), TQPixmap( img ) ); + setPaper( b ); + } +#endif + } + if ( attr.contains( "text" ) ) { + TQColor c( attr["text"] ); + initag.format.setColor( c ); + curtag.format.setColor( c ); + bodyText = c; + } + if ( attr.contains( "link" ) ) + linkColor = TQColor( attr["link"] ); + if ( attr.contains( "title" ) ) + attribs.replace( "title", attr["title"] ); + + if ( textEditMode ) { + if ( attr.contains("style" ) ) { + TQString a = attr["style"]; + for ( int s = 0; s < a.contains(';')+1; s++ ) { + TQString style = a.section( ';', s, s ); + if ( style.startsWith("font-size:" ) && style.endsWith("pt") ) { + scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) / + style.mid( 10, style.length() - 12 ).toInt(); + } + } + } + nstyle = 0; // ignore body in textEditMode + } + // end qt- and body-tag handling + } else if ( tagname == "meta" ) { + if ( attr["name"] == "qrichtext" && attr["content"] == "1" ) + textEditMode = TRUE; + } else if ( tagname == "title" ) { + TQString title; + while ( pos < length ) { + if ( hasPrefix( doc, length, pos, TQChar('<') ) && hasPrefix( doc, length, pos+1, TQChar('/') ) && + parseCloseTag( doc, length, pos ) == "title" ) + break; + title += doc[ pos ]; + ++pos; + } + attribs.replace( "title", title ); + } + } // end of well-known tag handling + +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( !custom ) // try generic custom item + custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); +#endif + if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it + continue; + + if ( custom ) { +#ifndef TQT_NO_TEXTCUSTOMITEM + int index = TQMAX( curpar->length(),1) - 1; + TQTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); + curpar->append( TQChar('*') ); + TQTextFormat* f = formatCollection()->format( &format ); + curpar->setFormat( index, 1, f ); + curpar->at( index )->setCustomItem( custom ); + if ( !curtag.anchorHref.isEmpty() ) + curpar->at(index)->setAnchor( TQString::null, curtag.anchorHref ); + if ( !anchorName.isEmpty() ) { + curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); + anchorName = TQString::null; + } + registerCustomItem( custom, curpar ); + hasNewPar = FALSE; +#endif + } else if ( !emptyTag ) { + /* if we do nesting, push curtag on the stack, + otherwise reinint curag. */ + if ( curtag.style->name() != tagname || nstyle->selfNesting() ) { + tags.push( curtag ); + } else { + if ( !tags.isEmpty() ) + curtag = tags.top(); + else + curtag = initag; + } + + curtag.name = tagname; + curtag.style = nstyle; + curtag.name = tagname; + curtag.style = nstyle; + if ( nstyle->whiteSpaceMode() != TQStyleSheetItem::WhiteSpaceModeUndefined ) + curtag.wsm = nstyle->whiteSpaceMode(); + + /* netscape compatibility: eat a newline and only a newline if a pre block starts */ + if ( curtag.wsm == TQStyleSheetItem::WhiteSpacePre && + nstyle->displayMode() == TQStyleSheetItem::DisplayBlock ) + eat( doc, length, pos, '\n' ); + + /* ignore whitespace for inline elements if there + was already one*/ + if ( !textEditMode && + (curtag.wsm == TQStyleSheetItem::WhiteSpaceNormal + || curtag.wsm == TQStyleSheetItem::WhiteSpaceNoWrap) + && ( space || nstyle->displayMode() != TQStyleSheetItem::DisplayInline ) ) + eatSpace( doc, length, pos ); + + curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); + if ( nstyle->isAnchor() ) { + if ( !anchorName.isEmpty() ) + anchorName += "#" + attr["name"]; + else + anchorName = attr["name"]; + curtag.anchorHref = attr["href"]; + } + + if ( nstyle->alignment() != TQStyleSheetItem::Undefined ) + curtag.alignment = nstyle->alignment(); + + if ( nstyle->listStyle() != TQStyleSheetItem::ListStyleUndefined ) + curtag.liststyle = nstyle->listStyle(); + + if ( nstyle->displayMode() == TQStyleSheetItem::DisplayBlock + || nstyle->displayMode() == TQStyleSheetItem::DisplayListItem ) { + + if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") { + TQString type = attr["type"]; + if ( !type.isEmpty() ) { + if ( type == "1" ) { + curtag.liststyle = TQStyleSheetItem::ListDecimal; + } else if ( type == "a" ) { + curtag.liststyle = TQStyleSheetItem::ListLowerAlpha; + } else if ( type == "A" ) { + curtag.liststyle = TQStyleSheetItem::ListUpperAlpha; + } else { + type = type.lower(); + if ( type == "square" ) + curtag.liststyle = TQStyleSheetItem::ListSquare; + else if ( type == "disc" ) + curtag.liststyle = TQStyleSheetItem::ListDisc; + else if ( type == "circle" ) + curtag.liststyle = TQStyleSheetItem::ListCircle; + } + } + } + + + /* Internally we treat ordered and bullet + lists the same for margin calculations. In + order to have fast pointer compares in the + xMargin() functions we restrict ourselves to +
    . Once we calculate the margins in the + parser rathern than later, the unelegance of + this approach goes awy + */ + if ( nstyle->name() == "ul" ) + curtag.style = sheet_->item( "ol" ); + + if ( attr.contains( "align" ) ) { + TQString align = attr["align"].lower(); + if ( align == "center" ) + curtag.alignment = TQt::AlignCenter; + else if ( align == "right" ) + curtag.alignment = TQt::AlignRight; + else if ( align == "justify" ) + curtag.alignment = TQt::AlignJustify; + } + if ( attr.contains( "dir" ) ) { + TQString dir = attr["dir"]; + if ( dir == "rtl" ) + curtag.direction = TQChar::DirR; + else if ( dir == "ltr" ) + curtag.direction = TQChar::DirL; + } + + NEWPAR; + + if ( curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem ) { + if ( attr.contains( "value " ) ) + curpar->setListValue( attr["value"].toInt() ); + } + + if ( attr.contains( "style" ) ) { + TQString a = attr["style"]; + bool ok = TRUE; + for ( int s = 0; ok && s < a.contains(';')+1; s++ ) { + TQString style = a.section( ';', s, s ); + if ( style.startsWith("margin-top:" ) && style.endsWith("px") ) + curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); + else if ( style.startsWith("margin-bottom:" ) && style.endsWith("px") ) + curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); + else if ( style.startsWith("margin-left:" ) && style.endsWith("px") ) + curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); + else if ( style.startsWith("margin-right:" ) && style.endsWith("px") ) + curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); + else if ( style.startsWith("text-indent:" ) && style.endsWith("px") ) + curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); + } + if ( !ok ) // be pressmistic + curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; + } + } + } + } else { + TQString tagname = parseCloseTag( doc, length, pos ); + if ( tagname.isEmpty() ) + continue; // nothing we could do with this, probably parse error + if ( !sheet_->item( tagname ) ) // ignore unknown tags + continue; + if ( tagname == "li" ) + continue; + + // we close a block item. Since the text may continue, we need to have a new paragraph + bool needNewPar = curtag.style->displayMode() == TQStyleSheetItem::DisplayBlock + || curtag.style->displayMode() == TQStyleSheetItem::DisplayListItem; + + + // html slopiness: handle unbalanched tag closing + while ( curtag.name != tagname ) { + TQString msg; + msg.sprintf( "TQText Warning: Document not valid ( '%s' not closed before '%s' #%d)", + curtag.name.ascii(), tagname.ascii(), pos); + sheet_->error( msg ); + if ( tags.isEmpty() ) + break; + curtag = tags.pop(); + } + + + // close the tag + if ( !tags.isEmpty() ) + curtag = tags.pop(); + else + curtag = initag; + + if ( needNewPar ) { + if ( textEditMode && (tagname == "p" || tagname == "div" ) ) // preserve empty paragraphs + hasNewPar = FALSE; + NEWPAR; + } + } + } else { + // normal contents + TQString s; + TQChar c; + while ( pos < length && !hasPrefix(doc, length, pos, TQChar('<') ) ){ + if ( textEditMode ) { + // text edit mode: we handle all white space but ignore newlines + c = parseChar( doc, length, pos, TQStyleSheetItem::WhiteSpacePre ); + if ( c == TQChar_linesep ) + break; + } else { + int l = pos; + c = parseChar( doc, length, pos, curtag.wsm ); + + // in white space pre mode: treat any space as non breakable + // and expand tabs to eight character wide columns. + if ( curtag.wsm == TQStyleSheetItem::WhiteSpacePre ) { + if ( c == '\t' ) { + c = ' '; + while( (++tabExpansionColumn)%8 ) + s += c; + } + if ( c == TQChar_linesep ) + tabExpansionColumn = 0; + else + tabExpansionColumn++; + + } + if ( c == ' ' || c == TQChar_linesep ) { + /* avoid overlong paragraphs by forcing a new + paragraph after 4096 characters. This case can + occur when loading undiscovered plain text + documents in rich text mode. Instead of hanging + forever, we do the trick. + */ + if ( curtag.wsm == TQStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do { + if ( doc[l] == '\n' ) { + hasNewPar = FALSE; // for a new paragraph ... + NEWPAR; + hasNewPar = FALSE; // ... and make it non-reusable + c = '\n'; // make sure we break below + break; + } + } while ( ++l < pos ); + } + } + + if ( c == '\n' ) + break; // break on newlines, pre delievers a TQChar_linesep + + bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; + + if ( curtag.wsm == TQStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) + continue; + if ( c == '\r' ) + continue; + space = c_isSpace; + s += c; + } + if ( !s.isEmpty() && curtag.style->displayMode() != TQStyleSheetItem::DisplayNone ) { + hasNewPar = FALSE; + int index = TQMAX( curpar->length(),1) - 1; + curpar->append( s ); + if (curtag.wsm != TQStyleSheetItem::WhiteSpaceNormal) { + TQTextString *str = curpar->string(); + for (uint i = index; i < index + s.length(); ++i) + str->at(i).nobreak = TRUE; + } + + TQTextFormat* f = formatCollection()->format( &curtag.format ); + curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already + f->ref += s.length() -1; // that what friends are for... + if ( !curtag.anchorHref.isEmpty() ) { + for ( int i = 0; i < int(s.length()); i++ ) + curpar->at(index + i)->setAnchor( TQString::null, curtag.anchorHref ); + } + if ( !anchorName.isEmpty() ) { + for ( int i = 0; i < int(s.length()); i++ ) + curpar->at(index + i)->setAnchor( anchorName, curpar->at(index + i)->anchorHref() ); + anchorName = TQString::null; + } + } + } + } + + if ( hasNewPar && curpar != fParag && !cursor && stylesPar != curpar ) { + // cleanup unused last paragraphs + curpar = curpar->p; + delete curpar->n; + } + + if ( !anchorName.isEmpty() ) { + curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); + anchorName = TQString::null; + } + + + setRichTextMarginsInternal( styles, stylesPar ); + + if ( cursor ) { + cursor->gotoPreviousLetter(); + cursor->remove(); + } + delete vec; +} + +void TQTextDocument::setRichTextMarginsInternal( TQPtrList< TQPtrVector >& styles, TQTextParagraph* stylesPar ) +{ + // margin and line spacing calculation + TQPtrVector* prevStyle = 0; + TQPtrVector* curStyle = styles.first(); + TQPtrVector* nextStyle = styles.next(); + while ( stylesPar ) { + if ( !curStyle ) { + stylesPar = stylesPar->next(); + prevStyle = curStyle; + curStyle = nextStyle; + nextStyle = styles.next(); + continue; + } + + int i, mar; + TQStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0; + if ( mainStyle && mainStyle->displayMode() == TQStyleSheetItem::DisplayListItem ) + stylesPar->setListItem( TRUE ); + int numLists = 0; + for ( i = 0; i < (int)curStyle->size(); ++i ) { + if ( (*curStyle)[ i ]->displayMode() == TQStyleSheetItem::DisplayBlock + && (*curStyle)[ i ]->listStyle() != TQStyleSheetItem::ListStyleUndefined ) + numLists++; + } + stylesPar->ldepth = numLists; + if ( stylesPar->next() && nextStyle ) { + // also set the depth of the next paragraph, required for the margin calculation + numLists = 0; + for ( i = 0; i < (int)nextStyle->size(); ++i ) { + if ( (*nextStyle)[ i ]->displayMode() == TQStyleSheetItem::DisplayBlock + && (*nextStyle)[ i ]->listStyle() != TQStyleSheetItem::ListStyleUndefined ) + numLists++; + } + stylesPar->next()->ldepth = numLists; + } + + // do the top margin + TQStyleSheetItem* item = mainStyle; + int m; + if (stylesPar->utm > 0 ) { + m = stylesPar->utm-1; + stylesPar->utm = 0; + } else { + m = TQMAX(0, item->margin( TQStyleSheetItem::MarginTop ) ); + if ( stylesPar->ldepth ) { + if ( item->displayMode() == TQStyleSheetItem::DisplayListItem ) + m /= stylesPar->ldepth * stylesPar->ldepth; + else + m = 0; + } + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + if ( prevStyle && i < (int) prevStyle->size() && + ( item->displayMode() == TQStyleSheetItem::DisplayBlock && + (*prevStyle)[ i ] == item ) ) + break; + // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags + if ( item->listStyle() != TQStyleSheetItem::ListStyleUndefined && + ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) + continue; + mar = TQMAX( 0, item->margin( TQStyleSheetItem::MarginTop ) ); + m = TQMAX( m, mar ); + } + stylesPar->utm = m - stylesPar->topMargin(); + + // do the bottom margin + item = mainStyle; + if (stylesPar->ubm > 0 ) { + m = stylesPar->ubm-1; + stylesPar->ubm = 0; + } else { + m = TQMAX(0, item->margin( TQStyleSheetItem::MarginBottom ) ); + if ( stylesPar->ldepth ) { + if ( item->displayMode() == TQStyleSheetItem::DisplayListItem ) + m /= stylesPar->ldepth * stylesPar->ldepth; + else + m = 0; + } + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + if ( nextStyle && i < (int) nextStyle->size() && + ( item->displayMode() == TQStyleSheetItem::DisplayBlock && + (*nextStyle)[ i ] == item ) ) + break; + // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags + if ( item->listStyle() != TQStyleSheetItem::ListStyleUndefined && + ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) + continue; + mar = TQMAX(0, item->margin( TQStyleSheetItem::MarginBottom ) ); + m = TQMAX( m, mar ); + } + stylesPar->ubm = m - stylesPar->bottomMargin(); + + // do the left margin, simplyfied + item = mainStyle; + if (stylesPar->ulm > 0 ) { + m = stylesPar->ulm-1; + stylesPar->ulm = 0; + } else { + m = TQMAX( 0, item->margin( TQStyleSheetItem::MarginLeft ) ); + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + m += TQMAX( 0, item->margin( TQStyleSheetItem::MarginLeft ) ); + } + stylesPar->ulm = m - stylesPar->leftMargin(); + + // do the right margin, simplyfied + item = mainStyle; + if (stylesPar->urm > 0 ) { + m = stylesPar->urm-1; + stylesPar->urm = 0; + } else { + m = TQMAX( 0, item->margin( TQStyleSheetItem::MarginRight ) ); + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + m += TQMAX( 0, item->margin( TQStyleSheetItem::MarginRight ) ); + } + stylesPar->urm = m - stylesPar->rightMargin(); + + // do the first line margin, which really should be called text-indent + item = mainStyle; + if (stylesPar->uflm > 0 ) { + m = stylesPar->uflm-1; + stylesPar->uflm = 0; + } else { + m = TQMAX( 0, item->margin( TQStyleSheetItem::MarginFirstLine ) ); + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + mar = TQMAX( 0, item->margin( TQStyleSheetItem::MarginFirstLine ) ); + m = TQMAX( m, mar ); + } + stylesPar->uflm =m - stylesPar->firstLineMargin(); + + // do the bogus line "spacing", which really is just an extra margin + item = mainStyle; + for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + if ( item->lineSpacing() != TQStyleSheetItem::Undefined ) { + stylesPar->ulinespacing = item->lineSpacing(); + if ( formatCollection() && + stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() ) + stylesPar->ulinespacing += formatCollection()->defaultFormat()->height(); + break; + } + } + + stylesPar = stylesPar->next(); + prevStyle = curStyle; + curStyle = nextStyle; + nextStyle = styles.next(); + } +} + +void TQTextDocument::setText( const TQString &text, const TQString &context ) +{ + focusIndicator.parag = 0; + selections.clear(); + if ( ( txtFormat == TQt::AutoText && TQStyleSheet::mightBeRichText( text ) ) || + txtFormat == TQt::RichText ) + setRichText( text, context ); + else + setPlainText( text ); +} + +TQString TQTextDocument::plainText() const +{ + TQString buffer; + TQString s; + TQTextParagraph *p = fParag; + while ( p ) { + if ( !p->mightHaveCustomItems ) { + const TQTextString *ts = p->string(); // workaround VC++ and Borland + s = ts->toString(); // with FALSE we don't fix spaces (nbsp) + } else { + for ( int i = 0; i < p->length() - 1; ++i ) { +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( p->at( i )->isCustom() ) { + if ( p->at( i )->customItem()->isNested() ) { + s += "\n"; + TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); + TQPtrList cells = t->tableCells(); + for ( TQTextTableCell *c = cells.first(); c; c = cells.next() ) + s += c->richText()->plainText() + "\n"; + s += "\n"; + } + } else +#endif + { + s += p->at( i )->c; + } + } + } + s.remove( s.length() - 1, 1 ); + if ( p->next() ) + s += "\n"; + buffer += s; + p = p->next(); + } + return buffer; +} + +static TQString align_to_string( int a ) +{ + if ( a & TQt::AlignRight ) + return " align=\"right\""; + if ( a & TQt::AlignHCenter ) + return " align=\"center\""; + if ( a & TQt::AlignJustify ) + return " align=\"justify\""; + return TQString::null; +} + +static TQString direction_to_string( int d ) +{ + if ( d != TQChar::DirON ) + return ( d == TQChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" ); + return TQString::null; +} + +static TQString list_value_to_string( int v ) +{ + if ( v != -1 ) + return " listvalue=\"" + TQString::number( v ) + "\""; + return TQString::null; +} + +static TQString list_style_to_string( int v ) +{ + switch( v ) { + case TQStyleSheetItem::ListDecimal: return "\"1\""; + case TQStyleSheetItem::ListLowerAlpha: return "\"a\""; + case TQStyleSheetItem::ListUpperAlpha: return "\"A\""; + case TQStyleSheetItem::ListDisc: return "\"disc\""; + case TQStyleSheetItem::ListSquare: return "\"square\""; + case TQStyleSheetItem::ListCircle: return "\"circle\""; + default: + return TQString::null; + } +} + +static inline bool list_is_ordered( int v ) +{ + return v == TQStyleSheetItem::ListDecimal || + v == TQStyleSheetItem::ListLowerAlpha || + v == TQStyleSheetItem::ListUpperAlpha; +} + + +static TQString margin_to_string( TQStyleSheetItem* style, int t, int b, int l, int r, int fl ) +{ + TQString s; + if ( l > 0 ) + s += TQString(!!s?";":"") + "margin-left:" + TQString::number(l+TQMAX(0,style->margin(TQStyleSheetItem::MarginLeft))) + "px"; + if ( r > 0 ) + s += TQString(!!s?";":"") + "margin-right:" + TQString::number(r+TQMAX(0,style->margin(TQStyleSheetItem::MarginRight))) + "px"; + if ( t > 0 ) + s += TQString(!!s?";":"") + "margin-top:" + TQString::number(t+TQMAX(0,style->margin(TQStyleSheetItem::MarginTop))) + "px"; + if ( b > 0 ) + s += TQString(!!s?";":"") + "margin-bottom:" + TQString::number(b+TQMAX(0,style->margin(TQStyleSheetItem::MarginBottom))) + "px"; + if ( fl > 0 ) + s += TQString(!!s?";":"") + "text-indent:" + TQString::number(fl+TQMAX(0,style->margin(TQStyleSheetItem::MarginFirstLine))) + "px"; + if ( !!s ) + return " style=\"" + s + "\""; + return TQString::null; +} + +TQString TQTextDocument::richText() const +{ + TQString s = ""; + if ( !par ) { + s += "defaultFormat()->font().pointSize() ); + s += "pt;font-family:"; + s += formatCollection()->defaultFormat()->font().family(); + s +="\">"; + } + TQTextParagraph* p = fParag; + + TQStyleSheetItem* item_p = styleSheet()->item("p"); + TQStyleSheetItem* item_div = styleSheet()->item("div"); + TQStyleSheetItem* item_ul = styleSheet()->item("ul"); + TQStyleSheetItem* item_ol = styleSheet()->item("ol"); + TQStyleSheetItem* item_li = styleSheet()->item("li"); + if ( !item_p || !item_div || !item_ul || !item_ol || !item_li ) { + tqWarning( "TQTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, div, ul, ol, or li)" ); + return TQString::null; + } + int pastListDepth = 0; + int listDepth = 0; +#if 0 + int futureListDepth = 0; +#endif + TQMemArray listStyles(10); + + while ( p ) { + listDepth = p->listDepth(); + if ( listDepth < pastListDepth ) { + for ( int i = pastListDepth; i > listDepth; i-- ) + s += list_is_ordered( listStyles[i] ) ? "
" : ""; + s += '\n'; + } else if ( listDepth > pastListDepth ) { + s += '\n'; + listStyles.resize( TQMAX( (int)listStyles.size(), listDepth+1 ) ); + TQString list_type; + listStyles[listDepth] = p->listStyle(); + if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() ) + list_type = " type=" + list_style_to_string( p->listStyle() ); + for ( int i = pastListDepth; i < listDepth; i++ ) { + s += list_is_ordered( p->listStyle() ) ? ""; + } + } else { + s += '\n'; + } + + TQString ps = p->richText(); + +#if 0 + // for the bottom margin we need to know whether we are at the end of a list + futureListDepth = 0; + if ( listDepth > 0 && p->next() ) + futureListDepth = p->next()->listDepth(); +#endif + + if ( richTextExportStart && richTextExportStart->paragraph() ==p && + richTextExportStart->index() == 0 ) + s += ""; + + if ( p->isListItem() ) { + s += "listStyle() != listStyles[listDepth] ) + s += " type=" + list_style_to_string( p->listStyle() ); + s +=align_to_string( p->alignment() ); + s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); + s += list_value_to_string( p->listValue() ); + s += direction_to_string( p->direction() ); + s +=">"; + s += ps; + s += ""; + } else if ( p->listDepth() ) { + s += "alignment() ); + s += margin_to_string( item_div, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); + s +=direction_to_string( p->direction() ); + s += ">"; + s += ps; + s += ""; + } else { + // normal paragraph item + s += "alignment() ); + s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); + s +=direction_to_string( p->direction() ); + s += ">"; + s += ps; + s += "

"; + } + pastListDepth = listDepth; + p = p->next(); + } + while ( listDepth > 0 ) { + s += list_is_ordered( listStyles[listDepth] ) ? "" : ""; + listDepth--; + } + + if ( !par ) + s += "\n\n"; + + return s; +} + +TQString TQTextDocument::text() const +{ + if ( ( txtFormat == TQt::AutoText && preferRichText ) || txtFormat == TQt::RichText ) + return richText(); + return plainText(); +} + +TQString TQTextDocument::text( int parag ) const +{ + TQTextParagraph *p = paragAt( parag ); + if ( !p ) + return TQString::null; + + if ( ( txtFormat == TQt::AutoText && preferRichText ) || txtFormat == TQt::RichText ) + return p->richText(); + else + return p->string()->toString(); +} + +void TQTextDocument::invalidate() +{ + TQTextParagraph *s = fParag; + while ( s ) { + s->invalidate( 0 ); + s = s->next(); + } +} + +void TQTextDocument::selectionStart( int id, int ¶gId, int &index ) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return; + TQTextDocumentSelection &sel = *it; + paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); + index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); +} + +TQTextCursor TQTextDocument::selectionStartCursor( int id) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return TQTextCursor( this ); + TQTextDocumentSelection &sel = *it; + if ( sel.swapped ) + return sel.endCursor; + return sel.startCursor; +} + +TQTextCursor TQTextDocument::selectionEndCursor( int id) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return TQTextCursor( this ); + TQTextDocumentSelection &sel = *it; + if ( !sel.swapped ) + return sel.endCursor; + return sel.startCursor; +} + +void TQTextDocument::selectionEnd( int id, int ¶gId, int &index ) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return; + TQTextDocumentSelection &sel = *it; + paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); + index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); +} + +void TQTextDocument::addSelection( int id ) +{ + nSelections = TQMAX( nSelections, id + 1 ); +} + +static void setSelectionEndHelper( int id, TQTextDocumentSelection &sel, TQTextCursor &start, TQTextCursor &end ) +{ + TQTextCursor c1 = start; + TQTextCursor c2 = end; + if ( sel.swapped ) { + c1 = end; + c2 = start; + } + + c1.paragraph()->removeSelection( id ); + c2.paragraph()->removeSelection( id ); + if ( c1.paragraph() != c2.paragraph() ) { + c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 ); + c2.paragraph()->setSelection( id, 0, c2.index() ); + } else { + c1.paragraph()->setSelection( id, TQMIN( c1.index(), c2.index() ), TQMAX( c1.index(), c2.index() ) ); + } + + sel.startCursor = start; + sel.endCursor = end; + if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) + sel.swapped = sel.startCursor.index() > sel.endCursor.index(); +} + +bool TQTextDocument::setSelectionEnd( int id, const TQTextCursor &cursor ) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return FALSE; + TQTextDocumentSelection &sel = *it; + + TQTextCursor start = sel.startCursor; + TQTextCursor end = cursor; + + if ( start == end ) { + removeSelection( id ); + setSelectionStart( id, cursor ); + return TRUE; + } + + if ( sel.endCursor.paragraph() == end.paragraph() ) { + setSelectionEndHelper( id, sel, start, end ); + return TRUE; + } + + bool inSelection = FALSE; + TQTextCursor c( this ); + TQTextCursor tmp = sel.startCursor; + if ( sel.swapped ) + tmp = sel.endCursor; + tmp.restoreState(); + TQTextCursor tmp2 = cursor; + tmp2.restoreState(); + c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() ); + bool hadStart = FALSE; + bool hadEnd = FALSE; + bool hadStartParag = FALSE; + bool hadEndParag = FALSE; + bool hadOldStart = FALSE; + bool hadOldEnd = FALSE; + bool leftSelection = FALSE; + sel.swapped = FALSE; + for ( ;; ) { + if ( c == start ) + hadStart = TRUE; + if ( c == end ) + hadEnd = TRUE; + if ( c.paragraph() == start.paragraph() ) + hadStartParag = TRUE; + if ( c.paragraph() == end.paragraph() ) + hadEndParag = TRUE; + if ( c == sel.startCursor ) + hadOldStart = TRUE; + if ( c == sel.endCursor ) + hadOldEnd = TRUE; + + if ( !sel.swapped && + ( ( hadEnd && !hadStart ) || + ( hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) ) ) + sel.swapped = TRUE; + + if ( ( c == end && hadStartParag ) || + ( c == start && hadEndParag ) ) { + TQTextCursor tmp = c; + tmp.restoreState(); + if ( tmp.paragraph() != c.paragraph() ) { + int sstart = tmp.paragraph()->selectionStart( id ); + tmp.paragraph()->removeSelection( id ); + tmp.paragraph()->setSelection( id, sstart, tmp.index() ); + } + } + + if ( inSelection && + ( ( c == end && hadStart ) || ( c == start && hadEnd ) ) ) + leftSelection = TRUE; + else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) ) + inSelection = TRUE; + + bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd(); + c.paragraph()->removeSelection( id ); + if ( inSelection ) { + if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) { + c.paragraph()->setSelection( id, TQMIN( start.index(), end.index() ), TQMAX( start.index(), end.index() ) ); + } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) { + c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 ); + } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) { + c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 ); + } else if ( c.paragraph() == end.paragraph() && hadEndParag ) { + c.paragraph()->setSelection( id, 0, end.index() ); + } else if ( c.paragraph() == start.paragraph() && hadStartParag ) { + c.paragraph()->setSelection( id, 0, start.index() ); + } else { + c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 ); + } + } + + if ( leftSelection ) + inSelection = FALSE; + + if ( noSelectionAnymore ) + break; + // *ugle*hack optimization + TQTextParagraph *p = c.paragraph(); + if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) { + c.gotoNextLetter(); + if ( p == lastParagraph() && c.atParagEnd() ) + break; + } else { + if ( p->document()->parent() ) + do { + c.gotoNextLetter(); + } while ( c.paragraph() == p ); + else + c.setParagraph( p->next() ); + } + } + + if ( !sel.swapped ) + sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 ); + + sel.startCursor = start; + sel.endCursor = end; + if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) + sel.swapped = sel.startCursor.index() > sel.endCursor.index(); + + setSelectionEndHelper( id, sel, start, end ); + + return TRUE; +} + +void TQTextDocument::selectAll( int id ) +{ + removeSelection( id ); + + TQTextDocumentSelection sel; + sel.swapped = FALSE; + TQTextCursor c( this ); + + c.setParagraph( fParag ); + c.setIndex( 0 ); + sel.startCursor = c; + + c.setParagraph( lParag ); + c.setIndex( lParag->length() - 1 ); + sel.endCursor = c; + + selections.insert( id, sel ); + + TQTextParagraph *p = fParag; + while ( p ) { + p->setSelection( id, 0, p->length() - 1 ); + p = p->next(); + } + + for ( TQTextDocument *d = childList.first(); d; d = childList.next() ) + d->selectAll( id ); +} + +bool TQTextDocument::removeSelection( int id ) +{ + if ( !selections.contains( id ) ) + return FALSE; + + TQTextDocumentSelection &sel = selections[ id ]; + + TQTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor; + TQTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor; + TQTextParagraph* p = 0; + while ( start != end ) { + if ( p != start.paragraph() ) { + p = start.paragraph(); + p->removeSelection( id ); + //### avoid endless loop by all means necessary, did somebody mention refactoring? + if ( !parent() && p == lParag ) + break; + } + start.gotoNextLetter(); + } + p = start.paragraph(); + p->removeSelection( id ); + selections.remove( id ); + return TRUE; +} + +TQString TQTextDocument::selectedText( int id, bool asRichText ) const +{ + TQMap::ConstIterator it = selections.find( id ); + if ( it == selections.end() ) + return TQString::null; + + TQTextDocumentSelection sel = *it; + + + TQTextCursor c1 = sel.startCursor; + TQTextCursor c2 = sel.endCursor; + if ( sel.swapped ) { + c2 = sel.startCursor; + c1 = sel.endCursor; + } + + /* 3.0.3 improvement: Make it possible to get a reasonable + selection inside a table. This approach is very conservative: + make sure that both cursors have the same depth level and point + to paragraphs within the same text document. + + Meaning if you select text in two table cells, you will get the + entire table. This is still far better than the 3.0.2, where + you always got the entire table. + + ### Fix this properly when refactoring + */ + while ( c2.nestedDepth() > c1.nestedDepth() ) + c2.oneUp(); + while ( c1.nestedDepth() > c2.nestedDepth() ) + c1.oneUp(); + while ( c1.nestedDepth() && c2.nestedDepth() && + c1.paragraph()->document() != c2.paragraph()->document() ) { + c1.oneUp(); + c2.oneUp(); + } + // do not trust sel_swapped with tables. Fix this properly when refactoring as well + if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() || + (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) { + TQTextCursor tmp = c1; + c2 = c1; + c1 = tmp; + } + + // end selection 3.0.3 improvement + + if ( asRichText && !parent() ) { + richTextExportStart = &c1; + richTextExportEnd = &c2; + + TQString sel = richText(); + int from = sel.find( "" ); + if ( from >= 0 ) { + from += 20; + // find the previous span and move it into the start fragment before we clip it + TQString prevspan; + int pspan = sel.findRev( " sel.findRev( "', pspan ); + prevspan = sel.mid( pspan, spanend - pspan + 1 ); + } + int to = sel.findRev( "" ); + if ( from <= to ) + sel = "" + prevspan + sel.mid( from, to - from ); + } + richTextExportStart = richTextExportEnd = 0; + return sel; + } + + TQString s; + if ( c1.paragraph() == c2.paragraph() ) { + TQTextParagraph *p = c1.paragraph(); + int end = c2.index(); + if ( p->at( TQMAX( 0, end - 1 ) )->isCustom() ) + ++end; + if ( !p->mightHaveCustomItems ) { + s += p->string()->toString().mid( c1.index(), end - c1.index() ); + } else { + for ( int i = c1.index(); i < end; ++i ) { +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( p->at( i )->isCustom() ) { + if ( p->at( i )->customItem()->isNested() ) { + s += "\n"; + TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); + TQPtrList cells = t->tableCells(); + for ( TQTextTableCell *c = cells.first(); c; c = cells.next() ) + s += c->richText()->plainText() + "\n"; + s += "\n"; + } + } else +#endif + { + s += p->at( i )->c; + } + } + } + } else { + TQTextParagraph *p = c1.paragraph(); + int start = c1.index(); + while ( p ) { + int end = p == c2.paragraph() ? c2.index() : p->length() - 1; + if ( p == c2.paragraph() && p->at( TQMAX( 0, end - 1 ) )->isCustom() ) + ++end; + if ( !p->mightHaveCustomItems ) { + s += p->string()->toString().mid( start, end - start ); + if ( p != c2.paragraph() ) + s += "\n"; + } else { + for ( int i = start; i < end; ++i ) { +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( p->at( i )->isCustom() ) { + if ( p->at( i )->customItem()->isNested() ) { + s += "\n"; + TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); + TQPtrList cells = t->tableCells(); + for ( TQTextTableCell *c = cells.first(); c; c = cells.next() ) + s += c->richText()->plainText() + "\n"; + s += "\n"; + } + } else +#endif + { + s += p->at( i )->c; + } + } + } + start = 0; + if ( p == c2.paragraph() ) + break; + p = p->next(); + } + } + // ### workaround for plain text export until we get proper + // mime types: turn unicode line seperators into the more + // widely understood \n. Makes copy and pasting code snipplets + // from within Assistent possible + TQChar* uc = (TQChar*) s.unicode(); + for ( uint ii = 0; ii < s.length(); ii++ ) { + if ( uc[(int)ii] == TQChar_linesep ) + uc[(int)ii] = TQChar('\n'); + else if ( uc[(int)ii] == TQChar::nbsp ) + uc[(int)ii] = TQChar(' '); + } + return s; +} + +void TQTextDocument::setFormat( int id, TQTextFormat *f, int flags ) +{ + TQMap::ConstIterator it = selections.find( id ); + if ( it == selections.end() ) + return; + + TQTextDocumentSelection sel = *it; + + TQTextCursor c1 = sel.startCursor; + TQTextCursor c2 = sel.endCursor; + if ( sel.swapped ) { + c2 = sel.startCursor; + c1 = sel.endCursor; + } + + c2.restoreState(); + c1.restoreState(); + + if ( c1.paragraph() == c2.paragraph() ) { + c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); + return; + } + + c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags ); + TQTextParagraph *p = c1.paragraph()->next(); + while ( p && p != c2.paragraph() ) { + p->setFormat( 0, p->length(), f, TRUE, flags ); + p = p->next(); + } + c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags ); +} + +void TQTextDocument::removeSelectedText( int id, TQTextCursor *cursor ) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return; + + TQTextDocumentSelection sel = *it; + TQTextCursor c1 = sel.startCursor; + TQTextCursor c2 = sel.endCursor; + if ( sel.swapped ) { + c2 = sel.startCursor; + c1 = sel.endCursor; + } + + // ### no support for editing tables yet + if ( c1.nestedDepth() || c2.nestedDepth() ) + return; + + c2.restoreState(); + c1.restoreState(); + + *cursor = c1; + removeSelection( id ); + + if ( c1.paragraph() == c2.paragraph() ) { + c1.paragraph()->remove( c1.index(), c2.index() - c1.index() ); + return; + } + + if ( c1.paragraph() == fParag && c1.index() == 0 && + c2.paragraph() == lParag && c2.index() == lParag->length() - 1 ) + cursor->setValid( FALSE ); + + bool didGoLeft = FALSE; + if ( c1.index() == 0 && c1.paragraph() != fParag ) { + cursor->gotoPreviousLetter(); + didGoLeft = cursor->isValid(); + } + + c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() ); + TQTextParagraph *p = c1.paragraph()->next(); + int dy = 0; + TQTextParagraph *tmp; + while ( p && p != c2.paragraph() ) { + tmp = p->next(); + dy -= p->rect().height(); + delete p; + p = tmp; + } + c2.paragraph()->remove( 0, c2.index() ); + while ( p ) { + p->move( dy ); + p->invalidate( 0 ); + p->setEndState( -1 ); + p = p->next(); + } + + + c1.paragraph()->join( c2.paragraph() ); + + if ( didGoLeft ) + cursor->gotoNextLetter(); +} + +void TQTextDocument::indentSelection( int id ) +{ + TQMap::Iterator it = selections.find( id ); + if ( it == selections.end() ) + return; + + TQTextDocumentSelection sel = *it; + TQTextParagraph *startParag = sel.startCursor.paragraph(); + TQTextParagraph *endParag = sel.endCursor.paragraph(); + if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { + endParag = sel.startCursor.paragraph(); + startParag = sel.endCursor.paragraph(); + } + + TQTextParagraph *p = startParag; + while ( p && p != endParag ) { + p->indent(); + p = p->next(); + } +} + +void TQTextDocument::addCommand( TQTextCommand *cmd ) +{ + commandHistory->addCommand( cmd ); +} + +TQTextCursor *TQTextDocument::undo( TQTextCursor *c ) +{ + return commandHistory->undo( c ); +} + +TQTextCursor *TQTextDocument::redo( TQTextCursor *c ) +{ + return commandHistory->redo( c ); +} + +bool TQTextDocument::find( TQTextCursor& cursor, const TQString &expr, bool cs, bool wo, bool forward ) +{ + removeSelection( Standard ); + TQTextParagraph *p = 0; + if ( expr.isEmpty() ) + return FALSE; + for (;;) { + if ( p != cursor.paragraph() ) { + p = cursor.paragraph(); + TQString s = cursor.paragraph()->string()->toString(); + int start = cursor.index(); + for ( ;; ) { + int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs ); + int end = res + expr.length(); + if ( res == -1 || ( !forward && start <= res ) ) + break; + if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && + ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) { + removeSelection( Standard ); + cursor.setIndex( forward ? end : res ); + setSelectionStart( Standard, cursor ); + cursor.setIndex( forward ? res : end ); + setSelectionEnd( Standard, cursor ); + if ( !forward ) + cursor.setIndex( res ); + return TRUE; + } + start = res + (forward ? 1 : -1); + } + } + if ( forward ) { + if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd() ) + break; + cursor.gotoNextLetter(); + } else { + if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() ) + break; + cursor.gotoPreviousLetter(); + } + } + return FALSE; +} + +void TQTextDocument::setTextFormat( TQt::TextFormat f ) +{ + txtFormat = f; + if ( fParag == lParag && fParag->length() <= 1 ) + fParag->rtext = ( f == TQt::RichText ); +} + +TQt::TextFormat TQTextDocument::textFormat() const +{ + return txtFormat; +} + +bool TQTextDocument::inSelection( int selId, const TQPoint &pos ) const +{ + TQMap::ConstIterator it = selections.find( selId ); + if ( it == selections.end() ) + return FALSE; + + TQTextDocumentSelection sel = *it; + TQTextParagraph *startParag = sel.startCursor.paragraph(); + TQTextParagraph *endParag = sel.endCursor.paragraph(); + if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() && + sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) ) + return FALSE; + if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { + endParag = sel.startCursor.paragraph(); + startParag = sel.endCursor.paragraph(); + } + + TQTextParagraph *p = startParag; + while ( p ) { + if ( p->rect().contains( pos ) ) { + bool inSel = FALSE; + int selStart = p->selectionStart( selId ); + int selEnd = p->selectionEnd( selId ); + int y = 0; + int h = 0; + for ( int i = 0; i < p->length(); ++i ) { + if ( i == selStart ) + inSel = TRUE; + if ( i == selEnd ) + break; + if ( p->at( i )->lineStart ) { + y = (*p->lineStarts.find( i ))->y; + h = (*p->lineStarts.find( i ))->h; + } + if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) { + if ( inSel && pos.x() >= p->at( i )->x && + pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) ) + return TRUE; + } + } + } + if ( pos.y() < p->rect().y() ) + break; + if ( p == endParag ) + break; + p = p->next(); + } + + return FALSE; +} + +void TQTextDocument::doLayout( TQPainter *p, int w ) +{ + minw = wused = 0; + if ( !is_printer( p ) ) + p = 0; + withoutDoubleBuffer = ( p != 0 ); + TQPainter * oldPainter = TQTextFormat::painter(); + TQTextFormat::setPainter( p ); + tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; + flow_->setWidth( w ); + cw = w; + vw = w; + TQTextParagraph *parag = fParag; + while ( parag ) { + parag->invalidate( 0 ); + if ( p ) + parag->adjustToPainter( p ); + parag->format(); + parag = parag->next(); + } + TQTextFormat::setPainter( oldPainter ); +} + +TQPixmap *TQTextDocument::bufferPixmap( const TQSize &s ) +{ + if ( !buf_pixmap ) + buf_pixmap = new TQPixmap( s.expandedTo( TQSize(1,1) ) ); + else if ( buf_pixmap->size() != s ) + buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) ); + return buf_pixmap; +} + +void TQTextDocument::draw( TQPainter *p, const TQRect &rect, const TQColorGroup &cg, const TQBrush *paper ) +{ + if ( !firstParagraph() ) + return; + + if ( paper ) { + p->setBrushOrigin( -int( p->translationX() ), + -int( p->translationY() ) ); + + p->fillRect( rect, *paper ); + } + + TQPainter * oldPainter = TQTextFormat::painter(); + TQTextFormat::setPainter( p ); + + if ( formatCollection()->defaultFormat()->color() != cg.text() ) + setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); + + TQTextParagraph *parag = firstParagraph(); + while ( parag ) { + if ( !parag->isValid() ) + parag->format(); + int y = parag->rect().y(); + TQRect pr( parag->rect() ); + pr.setX( 0 ); + pr.setWidth( TQWIDGETSIZE_MAX ); + if ( !rect.isNull() && !rect.intersects( pr ) ) { + parag = parag->next(); + continue; + } + p->translate( 0, y ); + if ( rect.isValid() ) + parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() ); + else + parag->paint( *p, cg, 0, FALSE ); + p->translate( 0, -y ); + parag = parag->next(); + if ( !flow()->isEmpty() ) + flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE ); + } + TQTextFormat::setPainter(oldPainter); +} + +void TQTextDocument::drawParagraph( TQPainter *p, TQTextParagraph *parag, int cx, int cy, int cw, int ch, + TQPixmap *&doubleBuffer, const TQColorGroup &cg, + bool drawCursor, TQTextCursor *cursor, bool resetChanged ) +{ + TQPainter *painter = 0; + if ( resetChanged ) + parag->setChanged( FALSE ); + TQRect ir( parag->rect() ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if (!parag->tableCell()) +#endif + ir.setWidth(width()); + + bool uDoubleBuffer = useDoubleBuffer( parag, p ); + + if ( uDoubleBuffer ) { + painter = new TQPainter; + if ( cx >= 0 && cy >= 0 ) + ir = ir.intersect( TQRect( cx, cy, cw, ch ) ); + if ( !doubleBuffer || + ir.width() > doubleBuffer->width() || + ir.height() > doubleBuffer->height() ) { + doubleBuffer = bufferPixmap( ir.size() ); + painter->begin( doubleBuffer ); + } else { + painter->begin( doubleBuffer ); + } + } else { + painter = p; + painter->translate( ir.x(), ir.y() ); + } + + painter->setBrushOrigin( -ir.x(), -ir.y() ); + + if ( uDoubleBuffer || is_printer( painter ) ) + painter->fillRect( TQRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) ); + else if ( cursor && cursor->paragraph() == parag ) + painter->fillRect( TQRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ), + parag->backgroundBrush( cg ) ); + + painter->translate( -( ir.x() - parag->rect().x() ), + -( ir.y() - parag->rect().y() ) ); + parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch ); + + if ( uDoubleBuffer ) { + delete painter; + painter = 0; + p->drawPixmap( ir.topLeft(), *doubleBuffer, TQRect( TQPoint( 0, 0 ), ir.size() ) ); + } else { + painter->translate( -ir.x(), -ir.y() ); + } + + parag->document()->nextDoubleBuffered = FALSE; +} + +TQTextParagraph *TQTextDocument::draw( TQPainter *p, int cx, int cy, int cw, int ch, const TQColorGroup &cg, + bool onlyChanged, bool drawCursor, TQTextCursor *cursor, bool resetChanged ) +{ + if ( withoutDoubleBuffer || ( par && par->withoutDoubleBuffer ) ) { + withoutDoubleBuffer = TRUE; + TQRect r; + draw( p, r, cg ); + return 0; + } + withoutDoubleBuffer = FALSE; + + if ( !firstParagraph() ) + return 0; + + TQPainter * oldPainter = TQTextFormat::painter(); + TQTextFormat::setPainter( p ); + if ( formatCollection()->defaultFormat()->color() != cg.text() ) + setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); + + if ( cx < 0 && cy < 0 ) { + cx = 0; + cy = 0; + cw = width(); + ch = height(); + } + + TQTextParagraph *lastFormatted = 0; + TQTextParagraph *parag = firstParagraph(); + + TQPixmap *doubleBuffer = 0; + + while ( parag ) { + lastFormatted = parag; + if ( !parag->isValid() ) + parag->format(); + + TQRect pr = parag->rect(); + pr.setWidth( parag->document()->width() ); + if ( pr.y() > cy + ch ) + goto floating; + TQRect clipr( cx, cy, cw, ch ); + if ( !pr.intersects( clipr ) || ( onlyChanged && !parag->hasChanged() ) ) { + pr.setWidth( parag->document()->width() ); + parag = parag->next(); + continue; + } + + drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); + parag = parag->next(); + } + + parag = lastParagraph(); + + floating: + if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) { + if ( !parag->document()->parent() ) { + TQRect fillRect = TQRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), + parag->document()->height() - ( parag->rect().y() + parag->rect().height() ) ); + if ( TQRect( cx, cy, cw, ch ).intersects( fillRect ) ) + p->fillRect( fillRect, cg.brush( TQColorGroup::Base ) ); + } + if ( !flow()->isEmpty() ) { + TQRect cr( cx, cy, cw, ch ); + flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE ); + } + } + + if ( buf_pixmap && buf_pixmap->height() > 300 ) { + delete buf_pixmap; + buf_pixmap = 0; + } + + TQTextFormat::setPainter(oldPainter); + return lastFormatted; +} + +/* + #### this function only sets the default font size in the format collection + */ +void TQTextDocument::setDefaultFormat( const TQFont &font, const TQColor &color ) +{ + bool reformat = font != fCollection->defaultFormat()->font(); + for ( TQTextDocument *d = childList.first(); d; d = childList.next() ) + d->setDefaultFormat( font, color ); + fCollection->updateDefaultFormat( font, color, sheet_ ); + + if ( !reformat ) + return; + tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; + + // invalidate paragraphs and custom items + TQTextParagraph *p = fParag; + while ( p ) { + p->invalidate( 0 ); +#ifndef TQT_NO_TEXTCUSTOMITEM + for ( int i = 0; i < p->length() - 1; ++i ) + if ( p->at( i )->isCustom() ) + p->at( i )->customItem()->invalidate(); +#endif + p = p->next(); + } +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +void TQTextDocument::registerCustomItem( TQTextCustomItem *i, TQTextParagraph *p ) +{ + if ( i && i->placement() != TQTextCustomItem::PlaceInline ) { + flow_->registerFloatingItem( i ); + p->registerFloatingItem( i ); + } + if (i) i->setParagraph( p ); + p->mightHaveCustomItems = mightHaveCustomItems = TRUE; +} + +void TQTextDocument::unregisterCustomItem( TQTextCustomItem *i, TQTextParagraph *p ) +{ + p->unregisterFloatingItem( i ); + i->setParagraph( 0 ); + flow_->unregisterFloatingItem( i ); +} +#endif + +bool TQTextDocument::hasFocusParagraph() const +{ + return !!focusIndicator.parag; +} + +TQString TQTextDocument::focusHref() const +{ + return focusIndicator.href; +} + +TQString TQTextDocument::focusName() const +{ + return focusIndicator.name; +} + +bool TQTextDocument::focusNextPrevChild( bool next ) +{ + if ( !focusIndicator.parag ) { + if ( next ) { + focusIndicator.parag = fParag; + focusIndicator.start = 0; + focusIndicator.len = 0; + } else { + focusIndicator.parag = lParag; + focusIndicator.start = lParag->length(); + focusIndicator.len = 0; + } + } else { + focusIndicator.parag->setChanged( TRUE ); + } + focusIndicator.href = TQString::null; + focusIndicator.name = TQString::null; + + if ( next ) { + TQTextParagraph *p = focusIndicator.parag; + int index = focusIndicator.start + focusIndicator.len; + while ( p ) { + for ( int i = index; i < p->length(); ++i ) { + if ( p->at( i )->isAnchor() ) { + p->setChanged( TRUE ); + focusIndicator.parag = p; + focusIndicator.start = i; + focusIndicator.len = 0; + focusIndicator.href = p->at( i )->anchorHref(); + focusIndicator.name = p->at( i )->anchorName(); + while ( i < p->length() ) { + if ( !p->at( i )->isAnchor() ) + return TRUE; + focusIndicator.len++; + i++; + } +#ifndef TQT_NO_TEXTCUSTOMITEM + } else if ( p->at( i )->isCustom() ) { + if ( p->at( i )->customItem()->isNested() ) { + TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); + TQPtrList cells = t->tableCells(); + // first try to continue + TQTextTableCell *c; + bool resetCells = TRUE; + for ( c = cells.first(); c; c = cells.next() ) { + if ( c->richText()->hasFocusParagraph() ) { + if ( c->richText()->focusNextPrevChild( next ) ) { + p->setChanged( TRUE ); + focusIndicator.parag = p; + focusIndicator.start = i; + focusIndicator.len = 0; + focusIndicator.href = c->richText()->focusHref(); + focusIndicator.name = c->richText()->focusName(); + return TRUE; + } else { + resetCells = FALSE; + c = cells.next(); + break; + } + } + } + // now really try + if ( resetCells ) + c = cells.first(); + for ( ; c; c = cells.next() ) { + if ( c->richText()->focusNextPrevChild( next ) ) { + p->setChanged( TRUE ); + focusIndicator.parag = p; + focusIndicator.start = i; + focusIndicator.len = 0; + focusIndicator.href = c->richText()->focusHref(); + focusIndicator.name = c->richText()->focusName(); + return TRUE; + } + } + } +#endif + } + } + index = 0; + p = p->next(); + } + } else { + TQTextParagraph *p = focusIndicator.parag; + int index = focusIndicator.start - 1; + if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 ) + index++; + while ( p ) { + for ( int i = index; i >= 0; --i ) { + if ( p->at( i )->isAnchor() ) { + p->setChanged( TRUE ); + focusIndicator.parag = p; + focusIndicator.start = i; + focusIndicator.len = 0; + focusIndicator.href = p->at( i )->anchorHref(); + focusIndicator.name = p->at( i )->anchorName(); + while ( i >= -1 ) { + if ( i < 0 || !p->at( i )->isAnchor() ) { + focusIndicator.start++; + return TRUE; + } + if ( i < 0 ) + break; + focusIndicator.len++; + focusIndicator.start--; + i--; + } +#ifndef TQT_NO_TEXTCUSTOMITEM + } else if ( p->at( i )->isCustom() ) { + if ( p->at( i )->customItem()->isNested() ) { + TQTextTable *t = (TQTextTable*)p->at( i )->customItem(); + TQPtrList cells = t->tableCells(); + // first try to continue + TQTextTableCell *c; + bool resetCells = TRUE; + for ( c = cells.last(); c; c = cells.prev() ) { + if ( c->richText()->hasFocusParagraph() ) { + if ( c->richText()->focusNextPrevChild( next ) ) { + p->setChanged( TRUE ); + focusIndicator.parag = p; + focusIndicator.start = i; + focusIndicator.len = 0; + focusIndicator.href = c->richText()->focusHref(); + focusIndicator.name = c->richText()->focusName(); + return TRUE; + } else { + resetCells = FALSE; + c = cells.prev(); + break; + } + } + if ( cells.at() == 0 ) + break; + } + // now really try + if ( resetCells ) + c = cells.last(); + for ( ; c; c = cells.prev() ) { + if ( c->richText()->focusNextPrevChild( next ) ) { + p->setChanged( TRUE ); + focusIndicator.parag = p; + focusIndicator.start = i; + focusIndicator.len = 0; + focusIndicator.href = c->richText()->focusHref(); + focusIndicator.name = c->richText()->focusName(); + return TRUE; + } + if ( cells.at() == 0 ) + break; + } + } +#endif + } + } + p = p->prev(); + if ( p ) + index = p->length() - 1; + } + } + + focusIndicator.parag = 0; + + return FALSE; +} + +int TQTextDocument::length() const +{ + int l = -1; + TQTextParagraph *p = fParag; + while ( p ) { + l += p->length(); + p = p->next(); + } + return TQMAX(0,l); +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +int TQTextFormat::width( const TQChar &c ) const +{ + if ( c.unicode() == 0xad ) // soft hyphen + return 0; + if ( !pntr || !pntr->isActive() ) { + if ( c == '\t' ) + return fm.width( ' ' ); + if ( ha == AlignNormal ) { + int w; + if ( c.row() ) + w = fm.width( c ); + else + w = widths[ c.unicode() ]; + if ( w == 0 && !c.row() ) { + w = fm.width( c ); + ( (TQTextFormat*)this )->widths[ c.unicode() ] = w; + } + return w; + } else { + TQFont f( fn ); + if ( usePixelSizes ) + f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); + else + f.setPointSize( ( f.pointSize() * 2 ) / 3 ); + TQFontMetrics fm_( f ); + return fm_.width( c ); + } + } + + TQFont f( fn ); + if ( ha != AlignNormal ) { + if ( usePixelSizes ) + f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); + else + f.setPointSize( ( f.pointSize() * 2 ) / 3 ); + } + applyFont( f ); + + return pntr_fm->width( c ); +} + +int TQTextFormat::width( const TQString &str, int pos ) const +{ + int w = 0; + if ( str.unicode()[ pos ].unicode() == 0xad ) + return w; + if ( !pntr || !pntr->isActive() ) { + if ( ha == AlignNormal ) { + w = fm.charWidth( str, pos ); + } else { + TQFont f( fn ); + if ( usePixelSizes ) + f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); + else + f.setPointSize( ( f.pointSize() * 2 ) / 3 ); + TQFontMetrics fm_( f ); + w = fm_.charWidth( str, pos ); + } + } else { + TQFont f( fn ); + if ( ha != AlignNormal ) { + if ( usePixelSizes ) + f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); + else + f.setPointSize( ( f.pointSize() * 2 ) / 3 ); + } + applyFont( f ); + w = pntr_fm->charWidth( str, pos ); + } + return w; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextString::TQTextString() +{ + bidiDirty = TRUE; + bidi = FALSE; + rightToLeft = FALSE; + dir = TQChar::DirON; +} + +TQTextString::TQTextString( const TQTextString &s ) +{ + bidiDirty = TRUE; + bidi = s.bidi; + rightToLeft = s.rightToLeft; + dir = s.dir; + data = s.data; + data.detach(); + for ( int i = 0; i < (int)data.size(); ++i ) { + TQTextFormat *f = data[i].format(); + if ( f ) + f->addRef(); + } +} + +void TQTextString::insert( int index, const TQString &s, TQTextFormat *f ) +{ + insert( index, s.unicode(), s.length(), f ); +} + +void TQTextString::insert( int index, const TQChar *unicode, int len, TQTextFormat *f ) +{ + int os = data.size(); + data.resize( data.size() + len, TQGArray::SpeedOptim ); + if ( index < os ) { + memmove( data.data() + index + len, data.data() + index, + sizeof( TQTextStringChar ) * ( os - index ) ); + } + TQTextStringChar *ch = data.data() + index; + for ( int i = 0; i < len; ++i ) { + ch->x = 0; + ch->lineStart = 0; + ch->d.format = 0; + ch->nobreak = FALSE; + ch->type = TQTextStringChar::Regular; + ch->d.format = f; + ch->rightToLeft = 0; + ch->c = unicode[i]; + ++ch; + } + bidiDirty = TRUE; +} + +TQTextString::~TQTextString() +{ + clear(); +} + +void TQTextString::insert( int index, TQTextStringChar *c, bool doAddRefFormat ) +{ + int os = data.size(); + data.resize( data.size() + 1, TQGArray::SpeedOptim ); + if ( index < os ) { + memmove( data.data() + index + 1, data.data() + index, + sizeof( TQTextStringChar ) * ( os - index ) ); + } + TQTextStringChar &ch = data[ (int)index ]; + ch.c = c->c; + ch.x = 0; + ch.lineStart = 0; + ch.rightToLeft = 0; + ch.d.format = 0; + ch.type = TQTextStringChar::Regular; + ch.nobreak = FALSE; + if ( doAddRefFormat && c->format() ) + c->format()->addRef(); + ch.setFormat( c->format() ); + bidiDirty = TRUE; +} + +int TQTextString::appendParagraphs( TQTextParagraph *start, TQTextParagraph *end ) +{ + int paragCount = 0; + int newLength = data.size(); + TQTextParagraph *p = start; + for (; p != end; p = p->next()) { + newLength += p->length(); + ++paragCount; + } + + const int oldLength = data.size(); + data.resize(newLength, TQGArray::SpeedOptim); + + TQTextStringChar *d = &data[oldLength]; + for (p = start; p != end; p = p->next()) { + const TQTextStringChar * const src = p->at(0); + int i = 0; + for (; i < p->length() - 1; ++i) { + d[i].c = src[i].c; + d[i].x = 0; + d[i].lineStart = 0; + d[i].rightToLeft = 0; + d[i].type = TQTextStringChar::Regular; + d[i].nobreak = FALSE; + d[i].d.format = src[i].format(); + if (d[i].d.format) + d[i].d.format->addRef(); + } + d[i].x = 0; + d[i].lineStart = 0; + d[i].nobreak = FALSE; + d[i].type = TQTextStringChar::Regular; + d[i].d.format = 0; + d[i].rightToLeft = 0; + d[i].c = '\n'; + d += p->length(); + } + + bidiDirty = TRUE; + return paragCount; +} + +void TQTextString::truncate( int index ) +{ + index = TQMAX( index, 0 ); + index = TQMIN( index, (int)data.size() - 1 ); + if ( index < (int)data.size() ) { + for ( int i = index + 1; i < (int)data.size(); ++i ) { + TQTextStringChar &ch = data[ i ]; +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( !(ch.type == TQTextStringChar::Regular) ) { + delete ch.customItem(); + if ( ch.d.custom->format ) + ch.d.custom->format->removeRef(); + delete ch.d.custom; + ch.d.custom = 0; + } else +#endif + if ( ch.format() ) { + ch.format()->removeRef(); + } + } + } + data.truncate( index ); + bidiDirty = TRUE; +} + +void TQTextString::remove( int index, int len ) +{ + for ( int i = index; i < (int)data.size() && i - index < len; ++i ) { + TQTextStringChar &ch = data[ i ]; +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( !(ch.type == TQTextStringChar::Regular) ) { + delete ch.customItem(); + if ( ch.d.custom->format ) + ch.d.custom->format->removeRef(); + delete ch.d.custom; + ch.d.custom = 0; + } else +#endif + if ( ch.format() ) { + ch.format()->removeRef(); + } + } + memmove( data.data() + index, data.data() + index + len, + sizeof( TQTextStringChar ) * ( data.size() - index - len ) ); + data.resize( data.size() - len, TQGArray::SpeedOptim ); + bidiDirty = TRUE; +} + +void TQTextString::clear() +{ + for ( int i = 0; i < (int)data.count(); ++i ) { + TQTextStringChar &ch = data[ i ]; +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( !(ch.type == TQTextStringChar::Regular) ) { + if ( ch.customItem() && ch.customItem()->placement() == TQTextCustomItem::PlaceInline ) + delete ch.customItem(); + if ( ch.d.custom->format ) + ch.d.custom->format->removeRef(); + delete ch.d.custom; + ch.d.custom = 0; + } else +#endif + if ( ch.format() ) { + ch.format()->removeRef(); + } + } + data.resize( 0 ); + bidiDirty = TRUE; +} + +void TQTextString::setFormat( int index, TQTextFormat *f, bool useCollection ) +{ + TQTextStringChar &ch = data[ index ]; + if ( useCollection && ch.format() ) + ch.format()->removeRef(); + ch.setFormat( f ); +} + +void TQTextString::checkBidi() const +{ + TQTextString *that = (TQTextString *)this; + that->bidiDirty = FALSE; + int length = data.size(); + if ( !length ) { + that->bidi = FALSE; + that->rightToLeft = dir == TQChar::DirR; + return; + } + const TQTextStringChar *start = data.data(); + const TQTextStringChar *end = start + length; + + ((TQTextString *)this)->stringCache = toString(data); + + + // determines the properties we need for layouting + TQTextEngine textEngine( toString(), 0 ); + textEngine.direction = (TQChar::Direction) dir; + textEngine.itemize(TQTextEngine::SingleLine); + const TQCharAttributes *ca = textEngine.attributes() + length-1; + TQTextStringChar *ch = (TQTextStringChar *)end - 1; + TQScriptItem *item = &textEngine.items[textEngine.items.size()-1]; + unsigned char bidiLevel = item->analysis.bidiLevel; + if ( bidiLevel ) + that->bidi = TRUE; + int pos = length-1; + while ( ch >= start ) { + if ( item->position > pos ) { + --item; + Q_ASSERT( item >= &textEngine.items[0] ); + Q_ASSERT( item < &textEngine.items[textEngine.items.size()] ); + bidiLevel = item->analysis.bidiLevel; + if ( bidiLevel ) + that->bidi = TRUE; + } + ch->softBreak = ca->softBreak; + ch->whiteSpace = ca->whiteSpace; + ch->charStop = ca->charStop; + ch->wordStop = ca->wordStop; + ch->bidiLevel = bidiLevel; + ch->rightToLeft = (bidiLevel%2); + --ch; + --ca; + --pos; + } + + if ( dir == TQChar::DirR ) { + that->bidi = TRUE; + that->rightToLeft = TRUE; + } else if ( dir == TQChar::DirL ) { + that->rightToLeft = FALSE; + } else { + that->rightToLeft = (textEngine.direction == TQChar::DirR); + } +} + +void TQTextDocument::setStyleSheet( TQStyleSheet *s ) +{ + if ( !s ) + return; + sheet_ = s; + list_tm = list_bm = par_tm = par_bm = 12; + list_lm = 40; + li_tm = li_bm = 0; + TQStyleSheetItem* item = s->item( "ol" ); + if ( item ) { + list_tm = TQMAX(0,item->margin( TQStyleSheetItem::MarginTop )); + list_bm = TQMAX(0,item->margin( TQStyleSheetItem::MarginBottom )); + list_lm = TQMAX(0,item->margin( TQStyleSheetItem::MarginLeft )); + } + if ( (item = s->item( "li" ) ) ) { + li_tm = TQMAX(0,item->margin( TQStyleSheetItem::MarginTop )); + li_bm = TQMAX(0,item->margin( TQStyleSheetItem::MarginBottom )); + } + if ( (item = s->item( "p" ) ) ) { + par_tm = TQMAX(0,item->margin( TQStyleSheetItem::MarginTop )); + par_bm = TQMAX(0,item->margin( TQStyleSheetItem::MarginBottom )); + } +} + +void TQTextDocument::setUnderlineLinks( bool b ) { + underlLinks = b; + for ( TQTextDocument *d = childList.first(); d; d = childList.next() ) + d->setUnderlineLinks( b ); +} + +void TQTextStringChar::setFormat( TQTextFormat *f ) +{ + if ( type == Regular ) { + d.format = f; + } else { +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( !d.custom ) { + d.custom = new CustomData; + d.custom->custom = 0; + } + d.custom->format = f; +#endif + } +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +void TQTextStringChar::setCustomItem( TQTextCustomItem *i ) +{ + if ( type == Regular ) { + TQTextFormat *f = format(); + d.custom = new CustomData; + d.custom->format = f; + } else { + delete d.custom->custom; + } + d.custom->custom = i; + type = (type == Anchor ? CustomAnchor : Custom); +} + +void TQTextStringChar::loseCustomItem() +{ + if ( type == Custom ) { + TQTextFormat *f = d.custom->format; + d.custom->custom = 0; + delete d.custom; + type = Regular; + d.format = f; + } else if ( type == CustomAnchor ) { + d.custom->custom = 0; + type = Anchor; + } +} + +#endif + +TQString TQTextStringChar::anchorName() const +{ + if ( type == Regular ) + return TQString::null; + else + return d.custom->anchorName; +} + +TQString TQTextStringChar::anchorHref() const +{ + if ( type == Regular ) + return TQString::null; + else + return d.custom->anchorHref; +} + +void TQTextStringChar::setAnchor( const TQString& name, const TQString& href ) +{ + if ( type == Regular ) { + TQTextFormat *f = format(); + d.custom = new CustomData; +#ifndef TQT_NO_TEXTCUSTOMITEM + d.custom->custom = 0; +#endif + d.custom->format = f; + type = Anchor; + } else if ( type == Custom ) { + type = CustomAnchor; + } + d.custom->anchorName = name; + d.custom->anchorHref = href; +} + + +int TQTextString::width( int idx ) const +{ + int w = 0; + TQTextStringChar *c = &at( idx ); + if ( !c->charStop || c->c.unicode() == 0xad || c->c.unicode() == 0x2028 ) + return 0; +#ifndef TQT_NO_TEXTCUSTOMITEM + if( c->isCustom() ) { + if( c->customItem()->placement() == TQTextCustomItem::PlaceInline ) + w = c->customItem()->width; + } else +#endif + { + int r = c->c.row(); + if(r < 0x06 +#ifndef TQ_WS_WIN + // Uniscribe's handling of Asian makes the condition below fail. + || (r > 0x1f && !(r > 0xd7 && r < 0xe0)) +#endif + ) { + w = c->format()->width( c->c ); + } else { + w = c->format()->width(toString(), idx); + } + } + return w; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextParagraph::TQTextParagraph( TQTextDocument *d, TQTextParagraph *pr, TQTextParagraph *nx, bool updateIds ) + : p( pr ), n( nx ), docOrPseudo( d ), + changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE), + lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE), + mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE), + align( 0 ), lstyle( TQStyleSheetItem::ListDisc ), invalid( 0 ), mSelections( 0 ), +#ifndef TQT_NO_TEXTCUSTOMITEM + mFloatingItems( 0 ), +#endif + utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ), + tabStopWidth(0), minwidth(0), tArray(0), eData( 0 ), ldepth( 0 ) +{ + lstyle = TQStyleSheetItem::ListDisc; + if ( !hasdoc ) + docOrPseudo = new TQTextParagraphPseudoDocument; + bgcol = 0; + list_val = -1; + paintdevice = 0; + TQTextFormat* defFormat = formatCollection()->defaultFormat(); + if ( !hasdoc ) { + tabStopWidth = defFormat->width( 'x' ) * 8; + pseudoDocument()->commandHistory = new TQTextCommandHistory( 100 ); + } + + if ( p ) + p->n = this; + if ( n ) + n->p = this; + + if ( !p && hasdoc ) + document()->setFirstParagraph( this ); + if ( !n && hasdoc ) + document()->setLastParagraph( this ); + + state = -1; + + if ( p ) + id = p->id + 1; + else + id = 0; + if ( n && updateIds ) { + TQTextParagraph *s = n; + while ( s ) { + s->id = s->p->id + 1; + s->invalidateStyleCache(); + s = s->n; + } + } + + str = new TQTextString(); + TQChar ch(' '); + str->insert( 0, &ch, 1, formatCollection()->defaultFormat() ); +} + +TQTextParagraph::~TQTextParagraph() +{ + delete str; + if ( hasdoc ) { + TQTextDocument *doc = document(); + if ( this == doc->minwParag ) { + doc->minwParag = 0; + doc->minw = 0; + } + if ( this == doc->curParag ) + doc->curParag = 0; + } else { + delete pseudoDocument(); + } + delete [] tArray; + delete eData; + TQMap::Iterator it = lineStarts.begin(); + for ( ; it != lineStarts.end(); ++it ) + delete *it; + if ( mSelections ) + delete mSelections; +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( mFloatingItems ) + delete mFloatingItems; +#endif + if ( p ) + p->setNext( n ); + if ( n ) + n->setPrev( p ); + delete bgcol; +} + +void TQTextParagraph::setNext( TQTextParagraph *s ) +{ + n = s; + if ( !n && hasdoc ) + document()->setLastParagraph( this ); +} + +void TQTextParagraph::setPrev( TQTextParagraph *s ) +{ + p = s; + if ( !p && hasdoc ) + document()->setFirstParagraph( this ); +} + +void TQTextParagraph::invalidate( int chr ) +{ + if ( invalid < 0 ) + invalid = chr; + else + invalid = TQMIN( invalid, chr ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( mFloatingItems ) { + for ( TQTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) + i->ypos = -1; + } +#endif + invalidateStyleCache(); +} + +void TQTextParagraph::invalidateStyleCache() +{ + if ( list_val < 0 ) + list_val = -1; +} + + +void TQTextParagraph::insert( int index, const TQString &s ) +{ + insert( index, s.unicode(), s.length() ); +} + +void TQTextParagraph::insert( int index, const TQChar *unicode, int len ) +{ + if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() ) + str->insert( index, unicode, len, + document()->preProcessor()->format( TQTextPreProcessor::Standard ) ); + else + str->insert( index, unicode, len, formatCollection()->defaultFormat() ); + invalidate( index ); + needPreProcess = TRUE; +} + +void TQTextParagraph::truncate( int index ) +{ + str->truncate( index ); + insert( length(), " " ); + needPreProcess = TRUE; +} + +void TQTextParagraph::remove( int index, int len ) +{ + if ( index + len - str->length() > 0 ) + return; +#ifndef TQT_NO_TEXTCUSTOMITEM + for ( int i = index; i < index + len; ++i ) { + TQTextStringChar *c = at( i ); + if ( hasdoc && c->isCustom() ) { + document()->unregisterCustomItem( c->customItem(), this ); + } + } +#endif + str->remove( index, len ); + invalidate( 0 ); + needPreProcess = TRUE; +} + +void TQTextParagraph::join( TQTextParagraph *s ) +{ + int oh = r.height() + s->r.height(); + n = s->n; + if ( n ) + n->p = this; + else if ( hasdoc ) + document()->setLastParagraph( this ); + + int start = str->length(); + if ( length() > 0 && at( length() - 1 )->c == ' ' ) { + remove( length() - 1, 1 ); + --start; + } + append( s->str->toString(), TRUE ); + + for ( int i = 0; i < s->length(); ++i ) { + if ( !hasdoc || document()->useFormatCollection() ) { + s->str->at( i ).format()->addRef(); + str->setFormat( i + start, s->str->at( i ).format(), TRUE ); + } +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( s->str->at( i ).isCustom() ) { + TQTextCustomItem * item = s->str->at( i ).customItem(); + str->at( i + start ).setCustomItem( item ); + s->str->at( i ).loseCustomItem(); + if ( hasdoc ) { + document()->unregisterCustomItem( item, s ); + document()->registerCustomItem( item, this ); + } + } + if ( s->str->at( i ).isAnchor() ) { + str->at( i + start ).setAnchor( s->str->at( i ).anchorName(), + s->str->at( i ).anchorHref() ); + } +#endif + } + + if ( !extraData() && s->extraData() ) { + setExtraData( s->extraData() ); + s->setExtraData( 0 ); + } else if ( extraData() && s->extraData() ) { + extraData()->join( s->extraData() ); + } + delete s; + invalidate( 0 ); + r.setHeight( oh ); + needPreProcess = TRUE; + if ( n ) { + TQTextParagraph *s = n; + s->invalidate( 0 ); + while ( s ) { + s->id = s->p->id + 1; + s->state = -1; + s->needPreProcess = TRUE; + s->changed = TRUE; + s->invalidateStyleCache(); + s = s->n; + } + } + format(); + state = -1; +} + +void TQTextParagraph::move( int &dy ) +{ + if ( dy == 0 ) + return; + changed = TRUE; + r.moveBy( 0, dy ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( mFloatingItems ) { + for ( TQTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) + i->ypos += dy; + } +#endif + if ( p ) + p->lastInFrame = TRUE; + + // do page breaks if required + if ( hasdoc && document()->isPageBreakEnabled() ) { + int shift; + if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) { + if ( p ) + p->setChanged( TRUE ); + dy += shift; + } + } +} + +void TQTextParagraph::format( int start, bool doMove ) +{ + if ( !str || str->length() == 0 || !formatter() ) + return; + + if ( hasdoc && + document()->preProcessor() && + ( needPreProcess || state == -1 ) ) + document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid ); + needPreProcess = FALSE; + + if ( invalid == -1 ) + return; + + r.moveTopLeft( TQPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) ); + if ( p ) + p->lastInFrame = FALSE; + + movedDown = FALSE; + bool formattedAgain = FALSE; + + formatAgain: + + r.setWidth( documentWidth() ); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( hasdoc && mFloatingItems ) { + for ( TQTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) { + i->ypos = r.y(); + if ( i->placement() == TQTextCustomItem::PlaceRight ) { + i->xpos = r.x() + r.width() - i->width; + } + } + } +#endif + TQMap oldLineStarts = lineStarts; + lineStarts.clear(); + int y = formatter()->format( document(), this, start, oldLineStarts ); + + + r.setWidth( TQMAX( r.width(), formatter()->minimumWidth() ) ); + + + TQMap::Iterator it = oldLineStarts.begin(); + + for ( ; it != oldLineStarts.end(); ++it ) + delete *it; + + if ( !hasdoc ) { // qt_format_text bounding rect handling + it = lineStarts.begin(); + int usedw = 0; + for ( ; it != lineStarts.end(); ++it ) + usedw = TQMAX( usedw, (*it)->w ); + if ( r.width() <= 0 ) { + // if the user specifies an invalid rect, this means that the + // bounding box should grow to the width that the text actually + // needs + r.setWidth( usedw ); + } else { + r.setWidth( TQMIN( usedw, r.width() ) ); + } + } + + if ( y != r.height() ) + r.setHeight( y ); + + if ( !visible ) { + r.setHeight( 0 ); + } else { + int minw = minwidth = formatter()->minimumWidth(); + int wused = formatter()->widthUsed(); + wused = TQMAX( minw, wused ); + if ( hasdoc ) { + document()->setMinimumWidth( minw, wused, this ); + } else { + pseudoDocument()->minw = TQMAX( pseudoDocument()->minw, minw ); + pseudoDocument()->wused = TQMAX( pseudoDocument()->wused, wused ); + } + } + + // do page breaks if required + if ( hasdoc && document()->isPageBreakEnabled() ) { + int shift = document()->formatter()->formatVertically( document(), this ); + if ( shift && !formattedAgain ) { + formattedAgain = TRUE; + goto formatAgain; + } + } + + if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) { + int dy = ( r.y() + r.height() ) - n->r.y(); + TQTextParagraph *s = n; + bool makeInvalid = p && p->lastInFrame; + while ( s && dy ) { + if ( !s->isFullWidth() ) + makeInvalid = TRUE; + if ( makeInvalid ) + s->invalidate( 0 ); + s->move( dy ); + if ( s->lastInFrame ) + makeInvalid = TRUE; + s = s->n; + } + } + + firstFormat = FALSE; + changed = TRUE; + invalid = -1; + //##### string()->setTextChanged( FALSE ); +} + +int TQTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const +{ + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + TQMap::ConstIterator it = lineStarts.end(); + --it; + for ( ;; ) { + if ( i >= it.key() ) { + if ( bl ) + *bl = ( *it )->baseLine; + if ( y ) + *y = ( *it )->y; + return ( *it )->h; + } + if ( it == lineStarts.begin() ) + break; + --it; + } + + tqWarning( "TQTextParagraph::lineHeightOfChar: couldn't find lh for %d", i ); + return 15; +} + +TQTextStringChar *TQTextParagraph::lineStartOfChar( int i, int *index, int *line ) const +{ + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + int l = (int)lineStarts.count() - 1; + TQMap::ConstIterator it = lineStarts.end(); + --it; + for ( ;; ) { + if ( i >= it.key() ) { + if ( index ) + *index = it.key(); + if ( line ) + *line = l; + return &str->at( it.key() ); + } + if ( it == lineStarts.begin() ) + break; + --it; + --l; + } + + tqWarning( "TQTextParagraph::lineStartOfChar: couldn't find %d", i ); + return 0; +} + +int TQTextParagraph::lines() const +{ + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + return (int)lineStarts.count(); +} + +TQTextStringChar *TQTextParagraph::lineStartOfLine( int line, int *index ) const +{ + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + if ( line >= 0 && line < (int)lineStarts.count() ) { + TQMap::ConstIterator it = lineStarts.begin(); + while ( line-- > 0 ) + ++it; + int i = it.key(); + if ( index ) + *index = i; + return &str->at( i ); + } + + tqWarning( "TQTextParagraph::lineStartOfLine: couldn't find %d", line ); + return 0; +} + +int TQTextParagraph::leftGap() const +{ + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + if ( str->length() == 0) + return 0; + + int line = 0; + int x = str->length() ? str->at(0).x : 0; /* set x to x of first char */ + if ( str->isBidi() ) { + for ( int i = 1; i < str->length()-1; ++i ) + x = TQMIN(x, str->at(i).x); + return x; + } + + TQMap::ConstIterator it = lineStarts.begin(); + while (line < (int)lineStarts.count()) { + int i = it.key(); /* char index */ + x = TQMIN(x, str->at(i).x); + ++it; + ++line; + } + return x; +} + +void TQTextParagraph::setFormat( int index, int len, TQTextFormat *f, bool useCollection, int flags ) +{ + if ( !f ) + return; + if ( index < 0 ) + index = 0; + if ( index > str->length() - 1 ) + index = str->length() - 1; + if ( index + len >= str->length() ) + len = str->length() - index; + + TQTextFormatCollection *fc = 0; + if ( useCollection ) + fc = formatCollection(); + TQTextFormat *of; + for ( int i = 0; i < len; ++i ) { + of = str->at( i + index ).format(); + if ( !changed && ( !of || f->key() != of->key() ) ) + changed = TRUE; + if ( invalid == -1 && + ( f->font().family() != of->font().family() || + f->font().pointSize() != of->font().pointSize() || + f->font().weight() != of->font().weight() || + f->font().italic() != of->font().italic() || + f->vAlign() != of->vAlign() ) ) { + invalidate( 0 ); + } + if ( flags == -1 || flags == TQTextFormat::Format || !fc ) { + if ( fc ) + f = fc->format( f ); + str->setFormat( i + index, f, useCollection ); + } else { + TQTextFormat *fm = fc->format( of, f, flags ); + str->setFormat( i + index, fm, useCollection ); + } + } +} + +void TQTextParagraph::indent( int *oldIndent, int *newIndent ) +{ + if ( !hasdoc || !document()->indent() || isListItem() ) { + if ( oldIndent ) + *oldIndent = 0; + if ( newIndent ) + *newIndent = 0; + if ( oldIndent && newIndent ) + *newIndent = *oldIndent; + return; + } + document()->indent()->indent( document(), this, oldIndent, newIndent ); +} + +void TQTextParagraph::paint( TQPainter &painter, const TQColorGroup &cg, TQTextCursor *cursor, bool drawSelections, + int clipx, int clipy, int clipw, int cliph ) +{ + if ( !visible ) + return; + int i, y, h, baseLine, xstart, xend = 0; + i = y =h = baseLine = 0; + TQRect cursorRect; + drawSelections &= ( mSelections != 0 ); + // macintosh full-width selection style + bool fullWidthStyle = TQApplication::style().styleHint(TQStyle::SH_RichText_FullWidthSelection); + int fullSelectionWidth = 0; + if ( drawSelections && fullWidthStyle ) + fullSelectionWidth = (hasdoc ? document()->width() : r.width()); + + TQString qstr = str->toString(); + // detach string + qstr.setLength(qstr.length()); + // ### workaround so that \n are not drawn, actually this should + // be fixed in TQFont somewhere (under Windows you get ugly boxes + // otherwise) + TQChar* uc = (TQChar*) qstr.unicode(); + for ( uint ii = 0; ii < qstr.length(); ii++ ) + if ( uc[(int)ii]== '\n' || uc[(int)ii] == '\t' ) + uc[(int)ii] = 0x20; + + int line = -1; + int paintStart = 0; + TQTextStringChar *chr = 0; + TQTextStringChar *nextchr = at( 0 ); + for ( i = 0; i < length(); i++ ) { + chr = nextchr; + if ( i < length()-1 ) + nextchr = at( i+1 ); + + // we flush at end of document + bool flush = (i == length()-1); + bool ignoreSoftHyphen = FALSE; + if ( !flush ) { + // we flush at end of line + flush |= nextchr->lineStart; + // we flush on format changes + flush |= ( nextchr->format() != chr->format() ); + // we flush on link changes + flush |= ( nextchr->isLink() != chr->isLink() ); + // we flush on start of run + flush |= ( nextchr->bidiLevel != chr->bidiLevel ); + // we flush on bidi changes + flush |= ( nextchr->rightToLeft != chr->rightToLeft ); + // we flush before and after tabs + flush |= ( chr->c == '\t' || nextchr->c == '\t' ); + // we flush on soft hypens + if (chr->c.unicode() == 0xad) { + flush = TRUE; + if (!nextchr->lineStart) + ignoreSoftHyphen = TRUE; + } + // we flush on custom items + flush |= chr->isCustom(); + // we flush before custom items + flush |= nextchr->isCustom(); + // when painting justified, we flush on spaces + if ((alignment() & TQt::AlignJustify) == TQt::AlignJustify ) + flush |= chr->whiteSpace; + } + + // init a new line + if ( chr->lineStart ) { + ++line; + paintStart = i; + lineInfo( line, y, h, baseLine ); + if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave + break; + } + + // if this is the first line and we are a list item, draw the the bullet label + if ( line == 0 && isListItem() ) { + int x = chr->x; + if (str->isBidi()) { + if (str->isRightToLeft()) { + x = chr->x + str->width(0); + for (int k = 1; k < length(); ++k) { + if (str->at(k).lineStart) + break; + x = TQMAX(x, str->at(k).x + str->width(k)); + } + } else { + x = chr->x; + for (int k = 1; k < length(); ++k) { + if (str->at(k).lineStart) + break; + x = TQMIN(x, str->at(k).x); + } + } + } + drawLabel( &painter, x, y, 0, 0, baseLine, cg ); + } + } + + // check for cursor mark + if ( cursor && this == cursor->paragraph() && i == cursor->index() ) { + TQTextStringChar *c = i == 0 ? chr : chr - 1; + cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(), + 1, c->format()->height() ); + } + + if ( flush ) { // something changed, draw what we have so far + if ( chr->rightToLeft ) { + xstart = chr->x; + xend = at( paintStart )->x + str->width( paintStart ); + } else { + xstart = at( paintStart )->x; + xend = chr->x; + if ( i < length() - 1 ) { + if ( !str->at( i + 1 ).lineStart && + str->at( i + 1 ).rightToLeft == chr->rightToLeft ) + xend = str->at( i + 1 ).x; + else + xend += str->width( i ); + } + } + + if ( (clipx == -1 || clipw <= 0 || (xend >= clipx && xstart <= clipx + clipw)) && + ( clipy == -1 || clipy < y+r.y()+h ) ) { + if ( !chr->isCustom() ) + drawString( painter, qstr, paintStart, i - paintStart + (ignoreSoftHyphen ? 0 : 1), xstart, y, + baseLine, xend-xstart, h, drawSelections, fullSelectionWidth, + chr, cg, chr->rightToLeft ); +#ifndef TQT_NO_TEXTCUSTOMITEM + else if ( chr->customItem()->placement() == TQTextCustomItem::PlaceInline ) { + bool inSelection = FALSE; + if (drawSelections) { + TQMap::ConstIterator it = mSelections->find( TQTextDocument::Standard ); + inSelection = (it != mSelections->end() && (*it).start <= i && (*it).end > i); + } + chr->customItem()->draw( &painter, chr->x, y, + clipx == -1 ? clipx : (clipx - r.x()), + clipy == -1 ? clipy : (clipy - r.y()), + clipw, cliph, cg, inSelection ); + } +#endif + } + paintStart = i+1; + } + + } + + // time to draw the cursor + const int cursor_extent = 4; + if ( !cursorRect.isNull() && cursor && + ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) { + painter.fillRect( cursorRect, cg.color( TQColorGroup::Text ) ); + painter.save(); + if ( string()->isBidi() ) { + if ( at( cursor->index() )->rightToLeft ) { + painter.setPen( TQt::black ); + painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); + painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); + } else { + painter.setPen( TQt::black ); + painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); + painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); + } + } + painter.restore(); + } +} + +//#define BIDI_DEBUG + +void TQTextParagraph::setColorForSelection( TQColor &color, TQPainter &painter, + const TQColorGroup& cg, int selection ) +{ + if (selection < 0) + return; + color = ( hasdoc && selection != TQTextDocument::Standard ) ? + document()->selectionColor( selection ) : + cg.color( TQColorGroup::Highlight ); + if ( selection == TQTextDocument::IMCompositionText ) { +#ifndef TQ_WS_MACX + int h1, s1, v1, h2, s2, v2; + cg.color( TQColorGroup::Base ).hsv( &h1, &s1, &v1 ); + cg.color( TQColorGroup::Background ).hsv( &h2, &s2, &v2 ); + color.setHsv( h1, s1, ( v1 + v2 ) / 2 ); +#else + color = TQt::lightGray; +#endif + painter.setPen( cg.color( TQColorGroup::Text ) ); + } else if ( selection == TQTextDocument::IMSelectionText ) { + color = cg.color( TQColorGroup::Dark ); + painter.setPen( cg.color( TQColorGroup::BrightText ) ); + } else if ( !hasdoc || document()->invertSelectionText( selection ) ) { + painter.setPen( cg.color( TQColorGroup::HighlightedText ) ); + } +} + +void TQTextParagraph::drawString( TQPainter &painter, const TQString &str, int start, int len, int xstart, + int y, int baseLine, int w, int h, bool drawSelections, int fullSelectionWidth, + TQTextStringChar *formatChar, const TQColorGroup& cg, + bool rightToLeft ) +{ + bool plainText = hasdoc ? document()->textFormat() == TQt::PlainText : FALSE; + TQTextFormat* format = formatChar->format(); + + if ( !plainText || ( hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() ) ) + painter.setPen( TQPen( format->color() ) ); + else + painter.setPen( cg.text() ); + painter.setFont( format->font() ); + + if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) { + if ( format->useLinkColor() ) + painter.setPen(document()->linkColor.isValid() ? document()->linkColor : cg.link()); + if ( document()->underlineLinks() ) { + TQFont fn = format->font(); + fn.setUnderline( TRUE ); + painter.setFont( fn ); + } + } + + TQPainter::TextDirection dir = rightToLeft ? TQPainter::RTL : TQPainter::LTR; + + int real_length = len; + if (len && dir != TQPainter::RTL && start + len == length() ) // don't draw the last character (trailing space) + len--; + if (len && str.unicode()[start+len-1] == TQChar_linesep) + len--; + + + TQTextFormat::VerticalAlignment vAlign = format->vAlign(); + if ( vAlign != TQTextFormat::AlignNormal ) { + // sub or superscript + TQFont f( painter.font() ); + if ( format->fontSizesInPixels() ) + f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); + else + f.setPointSize( ( f.pointSize() * 2 ) / 3 ); + painter.setFont( f ); + int h = painter.fontMetrics().height(); + baseLine += (vAlign == TQTextFormat::AlignSubScript) ? h/6 : -h/2; + } + + bool allSelected = FALSE; + if (drawSelections) { + TQMap::ConstIterator it = mSelections->find( TQTextDocument::Standard ); + allSelected = (it != mSelections->end() && (*it).start <= start && (*it).end >= start+len); + } + if (!allSelected) + painter.drawText(xstart, y + baseLine, str, start, len, dir); + +#ifdef BIDI_DEBUG + painter.save(); + painter.setPen ( TQt::red ); + painter.drawLine( xstart, y, xstart, y + baseLine ); + painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 ); + int w = 0; + int i = 0; + while( i < len ) + w += painter.fontMetrics().charWidth( str, start + i++ ); + painter.setPen ( TQt::blue ); + painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine ); + painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 ); + painter.restore(); +#endif + + // check if we are in a selection and draw it + if (drawSelections) { + TQMap::ConstIterator it = mSelections->end(); + while ( it != mSelections->begin() ) { + --it; + int selStart = (*it).start; + int selEnd = (*it).end; + int tmpw = w; + + selStart = TQMAX(selStart, start); + int real_selEnd = TQMIN(selEnd, start+real_length); + selEnd = TQMIN(selEnd, start+len); + bool extendRight = FALSE; + bool extendLeft = FALSE; + bool selWrap = (real_selEnd == length()-1 && n && n->hasSelection(it.key())); + if (selWrap || this->str->at(real_selEnd).lineStart) { + extendRight = (fullSelectionWidth != 0); + if (!extendRight && !rightToLeft) + tmpw += painter.fontMetrics().width(' '); + } + if (fullSelectionWidth && (selStart == 0 || this->str->at(selStart).lineStart)) { + extendLeft = TRUE; + } + if (this->str->isRightToLeft() != rightToLeft) + extendLeft = extendRight = FALSE; + + if (this->str->isRightToLeft()) { + bool tmp = extendLeft; + extendLeft = extendRight; + extendRight = tmp; + } + + if (selStart < real_selEnd || + (selWrap && fullSelectionWidth && extendRight && + // don't draw the standard selection on a printer= + (it.key() != TQTextDocument::Standard || !is_printer( &painter)))) { + int selection = it.key(); + TQColor color; + setColorForSelection( color, painter, cg, selection ); + if (selStart != start || selEnd != start + len || selWrap) { + // have to clip + painter.save(); + int cs, ce; + if (rightToLeft) { + cs = (selEnd != start + len) ? + this->str->at(this->str->previousCursorPosition(selEnd)).x : xstart; + ce = (selStart != start) ? + this->str->at(this->str->previousCursorPosition(selStart)).x : xstart+tmpw; + } else { + cs = (selStart != start) ? this->str->at(selStart).x : xstart; + ce = (selEnd != start + len) ? this->str->at(selEnd).x : xstart+tmpw; + } + TQRect r(cs, y, ce-cs, h); + if (extendLeft) + r.setLeft(0); + if (extendRight) + r.setRight(fullSelectionWidth); + TQRegion reg(r); + if ( painter.hasClipping() ) + reg &= painter.clipRegion(TQPainter::CoordPainter); + painter.setClipRegion(reg, TQPainter::CoordPainter); + } + int xleft = xstart; + if ( extendLeft ) { + tmpw += xstart; + xleft = 0; + } + if ( extendRight ) + tmpw = fullSelectionWidth - xleft; + painter.fillRect( xleft, y, tmpw, h, color ); + painter.drawText( xstart, y + baseLine, str, start, len, dir ); + // draw preedit's underline + if (selection == TQTextDocument::IMCompositionText) + painter.drawLine(xstart, y + baseLine + 1, xstart + w, y + baseLine + 1); + if (selStart != start || selEnd != start + len || selWrap) + painter.restore(); + } + } + } + + if ( format->isMisspelled() ) { + painter.save(); + painter.setPen( TQPen( TQt::red, 1, TQt::DotLine ) ); + painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 ); + painter.restore(); + } + + if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() && + document()->focusIndicator.parag == this && + ( ( document()->focusIndicator.start >= start && + document()->focusIndicator.start + document()->focusIndicator.len <= start + len ) || + ( document()->focusIndicator.start <= start && + document()->focusIndicator.start + document()->focusIndicator.len >= start + len ) ) ) + painter.drawWinFocusRect( TQRect( xstart, y, w, h ) ); +} + +void TQTextParagraph::drawLabel( TQPainter* p, int x, int y, int w, int h, int base, const TQColorGroup& cg ) +{ + TQRect r ( x, y, w, h ); + TQStyleSheetItem::ListStyle s = listStyle(); + + p->save(); + TQTextFormat *format = at( 0 )->format(); + if ( format ) { + p->setPen( format->color() ); + p->setFont( format->font() ); + } + TQFontMetrics fm( p->fontMetrics() ); + int size = fm.lineSpacing() / 3; + + bool rtl = str->isRightToLeft(); + + switch ( s ) { + case TQStyleSheetItem::ListDecimal: + case TQStyleSheetItem::ListLowerAlpha: + case TQStyleSheetItem::ListUpperAlpha: + { + if ( list_val == -1 ) { // uninitialised list value, calcluate the right one + int depth = listDepth(); + list_val--; + // ### evil, square and expensive. This needs to be done when formatting, not when painting + TQTextParagraph* s = prev(); + int depth_s; + while ( s && (depth_s = s->listDepth()) >= depth ) { + if ( depth_s == depth && s->isListItem() ) + list_val--; + s = s->prev(); + } + } + + int n = list_val; + if ( n < -1 ) + n = -n - 1; + TQString l; + switch ( s ) { + case TQStyleSheetItem::ListLowerAlpha: + if ( n < 27 ) { + l = TQChar( ('a' + (char) (n-1))); + break; + } + case TQStyleSheetItem::ListUpperAlpha: + if ( n < 27 ) { + l = TQChar( ('A' + (char) (n-1))); + break; + } + break; + default: //TQStyleSheetItem::ListDecimal: + l.setNum( n ); + break; + } + if (rtl) + l.prepend(" ."); + else + l += TQString::fromLatin1(". "); + int x = ( rtl ? r.left() : r.right() - fm.width(l)); + p->drawText( x, r.top() + base, l ); + } + break; + case TQStyleSheetItem::ListSquare: + { + int x = rtl ? r.left() + size : r.right() - size*2; + TQRect er( x, r.top() + fm.height() / 2 - size / 2, size, size ); + p->fillRect( er , cg.brush( TQColorGroup::Text ) ); + } + break; + case TQStyleSheetItem::ListCircle: + { + int x = rtl ? r.left() + size : r.right() - size*2; + TQRect er( x, r.top() + fm.height() / 2 - size / 2, size, size); + p->drawEllipse( er ); + } + break; + case TQStyleSheetItem::ListDisc: + default: + { + p->setBrush( cg.brush( TQColorGroup::Text )); + int x = rtl ? r.left() + size : r.right() - size*2; + TQRect er( x, r.top() + fm.height() / 2 - size / 2, size, size); + p->drawEllipse( er ); + p->setBrush( TQt::NoBrush ); + } + break; + } + + p->restore(); +} + +#ifndef TQT_NO_DATASTREAM +void TQTextParagraph::readStyleInformation( TQDataStream& stream ) +{ + int int_align, int_lstyle; + uchar uchar_litem, uchar_rtext, uchar_dir; + stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm + >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir; + align = int_align; lstyle = (TQStyleSheetItem::ListStyle) int_lstyle; + litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (TQChar::Direction)uchar_dir ); + TQTextParagraph* s = prev() ? prev() : this; + while ( s ) { + s->invalidate( 0 ); + s = s->next(); + } +} + +void TQTextParagraph::writeStyleInformation( TQDataStream& stream ) const +{ + stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction(); +} +#endif + + +void TQTextParagraph::setListItem( bool li ) +{ + if ( (bool)litem == li ) + return; + litem = li; + changed = TRUE; + TQTextParagraph* s = prev() ? prev() : this; + while ( s ) { + s->invalidate( 0 ); + s = s->next(); + } +} + +void TQTextParagraph::setListDepth( int depth ) { + if ( !hasdoc || depth == ldepth ) + return; + ldepth = depth; + TQTextParagraph* s = prev() ? prev() : this; + while ( s ) { + s->invalidate( 0 ); + s = s->next(); + } +} + +int *TQTextParagraph::tabArray() const +{ + int *ta = tArray; + if ( !ta && hasdoc ) + ta = document()->tabArray(); + return ta; +} + +int TQTextParagraph::nextTab( int, int x ) +{ + int *ta = tArray; + if ( hasdoc ) { + if ( !ta ) + ta = document()->tabArray(); + tabStopWidth = document()->tabStopWidth(); + } + if ( ta ) { + int i = 0; + while ( ta[ i ] ) { + if ( ta[ i ] >= x ) + return tArray[ i ]; + ++i; + } + return tArray[ 0 ]; + } else { + int d; + if ( tabStopWidth != 0 ) + d = x / tabStopWidth; + else + return x; + return tabStopWidth * ( d + 1 ); + } +} + +void TQTextParagraph::adjustToPainter( TQPainter *p ) +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + for ( int i = 0; i < length(); ++i ) { + if ( at( i )->isCustom() ) + at( i )->customItem()->adjustToPainter( p ); + } +#endif +} + +TQTextFormatCollection *TQTextParagraph::formatCollection() const +{ + if ( hasdoc ) + return document()->formatCollection(); + TQTextFormatCollection* fc = &pseudoDocument()->collection; + if ( paintdevice != fc->paintDevice() ) + fc->setPaintDevice( paintdevice ); + return fc; +} + +TQString TQTextParagraph::richText() const +{ + TQString s; + TQTextStringChar *formatChar = 0; + TQString spaces; + bool doStart = richTextExportStart && richTextExportStart->paragraph() == this; + bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this; + int i; + TQString lastAnchorName; + for ( i = 0; i < length()-1; ++i ) { + if ( doStart && i && richTextExportStart->index() == i ) + s += ""; + if ( doEnd && richTextExportEnd->index() == i ) + s += ""; + TQTextStringChar *c = &str->at( i ); + if ( c->isAnchor() && !c->anchorName().isEmpty() && c->anchorName() != lastAnchorName ) { + lastAnchorName = c->anchorName(); + if ( c->anchorName().contains( '#' ) ) { + TQStringList l = TQStringList::split( '#', c->anchorName() ); + for ( TQStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) + s += ""; + } else { + s += "anchorName() + "\">"; + } + } + if ( !formatChar ) { + s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), + 0, TQString::null, c->anchorHref() ); + formatChar = c; + } else if ( ( formatChar->format()->key() != c->format()->key() ) || + (c->anchorHref() != formatChar->anchorHref() ) ) { + s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), + formatChar->format() , formatChar->anchorHref(), c->anchorHref() ); + formatChar = c; + } + if ( c->c == '<' ) + s += "<"; + else if ( c->c == '>' ) + s += ">"; + else if ( c->c =='&' ) + s += "&"; + else if ( c->c =='\"' ) + s += """; +#ifndef TQT_NO_TEXTCUSTOMITEM + else if ( c->isCustom() ) + s += c->customItem()->richText(); +#endif + else if ( c->c == '\n' || c->c == TQChar_linesep ) + s += "
"; // space on purpose for compatibility with Netscape, Lynx & Co. + else + s += c->c; + } + if ( doEnd && richTextExportEnd->index() == i ) + s += ""; + if ( formatChar ) + s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() ); + return s; +} + +void TQTextParagraph::addCommand( TQTextCommand *cmd ) +{ + if ( !hasdoc ) + pseudoDocument()->commandHistory->addCommand( cmd ); + else + document()->commands()->addCommand( cmd ); +} + +TQTextCursor *TQTextParagraph::undo( TQTextCursor *c ) +{ + if ( !hasdoc ) + return pseudoDocument()->commandHistory->undo( c ); + return document()->commands()->undo( c ); +} + +TQTextCursor *TQTextParagraph::redo( TQTextCursor *c ) +{ + if ( !hasdoc ) + return pseudoDocument()->commandHistory->redo( c ); + return document()->commands()->redo( c ); +} + +int TQTextParagraph::topMargin() const +{ + int m = 0; + if ( rtext ) { + m = isListItem() ? (document()->li_tm/TQMAX(1,listDepth()*listDepth())) : + ( listDepth() ? 0 : document()->par_tm ); + if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) ) + m = TQMAX( m, document()->list_tm ); + } + m += utm; + return scale( m, TQTextFormat::painter() ); +} + +int TQTextParagraph::bottomMargin() const +{ + int m = 0; + if ( rtext ) { + m = isListItem() ? (document()->li_bm/TQMAX(1,listDepth()*listDepth())) : + ( listDepth() ? 0 : document()->par_bm ); + if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) ) + m = TQMAX( m, document()->list_bm ); + } + m += ubm; + return scale( m, TQTextFormat::painter() ); +} + +int TQTextParagraph::leftMargin() const +{ + int m = ulm; + if ( listDepth() && !string()->isRightToLeft() ) + m += listDepth() * document()->list_lm; + return scale( m, TQTextFormat::painter() ); +} + +int TQTextParagraph::firstLineMargin() const +{ + int m = uflm; + return scale( m, TQTextFormat::painter() ); +} + +int TQTextParagraph::rightMargin() const +{ + int m = urm; + if ( listDepth() && string()->isRightToLeft() ) + m += listDepth() * document()->list_lm; + return scale( m, TQTextFormat::painter() ); +} + +int TQTextParagraph::lineSpacing() const +{ + int l = ulinespacing; + l = scale( l, TQTextFormat::painter() ); + return l; +} + +void TQTextParagraph::copyParagData( TQTextParagraph *parag ) +{ + rtext = parag->rtext; + lstyle = parag->lstyle; + ldepth = parag->ldepth; + litem = parag->litem; + align = parag->align; + utm = parag->utm; + ubm = parag->ubm; + urm = parag->urm; + ulm = parag->ulm; + uflm = parag->uflm; + ulinespacing = parag->ulinespacing; + TQColor *c = parag->backgroundColor(); + if ( c ) + setBackgroundColor( *c ); + str->setDirection( parag->str->direction() ); +} + +void TQTextParagraph::show() +{ + if ( visible || !hasdoc ) + return; + visible = TRUE; +} + +void TQTextParagraph::hide() +{ + if ( !visible || !hasdoc ) + return; + visible = FALSE; +} + +void TQTextParagraph::setDirection( TQChar::Direction d ) +{ + if ( str && str->direction() != d ) { + str->setDirection( d ); + invalidate( 0 ); + } +} + +TQChar::Direction TQTextParagraph::direction() const +{ + return (str ? str->direction() : TQChar::DirON ); +} + +void TQTextParagraph::setChanged( bool b, bool recursive ) +{ + changed = b; + if ( recursive ) { + if ( document() && document()->parentParagraph() ) + document()->parentParagraph()->setChanged( b, recursive ); + } +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +TQTextPreProcessor::TQTextPreProcessor() +{ +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextFormatter::TQTextFormatter() + : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE ) +{ +} + +TQTextLineStart *TQTextFormatter::formatLine( TQTextParagraph *parag, TQTextString *string, TQTextLineStart *line, + TQTextStringChar *startChar, TQTextStringChar *lastChar, int align, int space ) +{ + if ( lastChar < startChar ) + return new TQTextLineStart; +#ifndef TQT_NO_COMPLEXTEXT + if( string->isBidi() ) + return bidiReorderLine( parag, string, line, startChar, lastChar, align, space ); +#endif + int start = (startChar - &string->at(0)); + int last = (lastChar - &string->at(0) ); + + // ignore white space at the end of the line. + TQTextStringChar *ch = lastChar; + while ( ch > startChar && ch->whiteSpace ) { + space += ch->format()->width( ' ' ); + --ch; + } + + if (space < 0) + space = 0; + + // do alignment Auto == Left in this case + if ( align & TQt::AlignHCenter || align & TQt::AlignRight ) { + if ( align & TQt::AlignHCenter ) + space /= 2; + for ( int j = start; j <= last; ++j ) + string->at( j ).x += space; + } else if ( align & TQt::AlignJustify ) { + int numSpaces = 0; + // End at "last-1", the last space ends up with a width of 0 + for ( int j = last-1; j >= start; --j ) { + // Start at last tab, if any. + TQTextStringChar &ch = string->at( j ); + if ( ch.c == '\t' ) { + start = j+1; + break; + } + if(ch.whiteSpace) + numSpaces++; + } + int toAdd = 0; + for ( int k = start + 1; k <= last; ++k ) { + TQTextStringChar &ch = string->at( k ); + if( numSpaces && ch.whiteSpace ) { + int s = space / numSpaces; + toAdd += s; + space -= s; + numSpaces--; + } + string->at( k ).x += toAdd; + } + } + + if ( last >= 0 && last < string->length() ) + line->w = string->at( last ).x + string->width( last ); + else + line->w = 0; + + return new TQTextLineStart; +} + +#ifndef TQT_NO_COMPLEXTEXT + +#ifdef BIDI_DEBUG +#include +#endif + +// collects one line of the paragraph and transforms it to visual order +TQTextLineStart *TQTextFormatter::bidiReorderLine( TQTextParagraph * /*parag*/, TQTextString *text, TQTextLineStart *line, + TQTextStringChar *startChar, TQTextStringChar *lastChar, int align, int space ) +{ + // ignore white space at the end of the line. + int endSpaces = 0; + while ( lastChar > startChar && lastChar->whiteSpace ) { + space += lastChar->format()->width( ' ' ); + --lastChar; + ++endSpaces; + } + + int start = (startChar - &text->at(0)); + int last = (lastChar - &text->at(0) ); + + int length = lastChar - startChar + 1; + + + int x = startChar->x; + + unsigned char _levels[256]; + int _visual[256]; + + unsigned char *levels = _levels; + int *visual = _visual; + + if ( length > 255 ) { + levels = (unsigned char *)malloc( length*sizeof( unsigned char ) ); + visual = (int *)malloc( length*sizeof( int ) ); + } + + //tqDebug("bidiReorderLine: length=%d (%d-%d)", length, start, last ); + + TQTextStringChar *ch = startChar; + unsigned char *l = levels; + while ( ch <= lastChar ) { + //tqDebug( " level: %d", ch->bidiLevel ); + *(l++) = (ch++)->bidiLevel; + } + + TQTextEngine::bidiReorder( length, levels, visual ); + + // now construct the reordered string out of the runs... + + int numSpaces = 0; + // set the correct alignment. This is a bit messy.... + if( align == TQt::AlignAuto ) { + // align according to directionality of the paragraph... + if ( text->isRightToLeft() ) + align = TQt::AlignRight; + } + + // This is not really correct, but as we can't make the scrollbar move to the left of the origin, + // this ensures all text can be scrolled to and read. + if (space < 0) + space = 0; + + if ( align & TQt::AlignHCenter ) + x += space/2; + else if ( align & TQt::AlignRight ) + x += space; + else if ( align & TQt::AlignJustify ) { + // End at "last-1", the last space ends up with a width of 0 + for ( int j = last-1; j >= start; --j ) { + // Start at last tab, if any. + TQTextStringChar &ch = text->at( j ); + if ( ch.c == '\t' ) { + start = j+1; + break; + } + if(ch.whiteSpace) + numSpaces++; + } + } + + int toAdd = 0; + int xorig = x; + TQTextStringChar *lc = startChar + visual[0]; + for ( int i = 0; i < length; i++ ) { + TQTextStringChar *ch = startChar + visual[i]; + if (numSpaces && ch->whiteSpace) { + int s = space / numSpaces; + toAdd += s; + space -= s; + numSpaces--; + } + + if (lc->format() != ch->format() && !ch->c.isSpace() + && lc->format()->font().italic() && !ch->format()->font().italic()) { + int rb = lc->format()->fontMetrics().rightBearing(lc->c); + if (rb < 0) + x -= rb; + } + + ch->x = x + toAdd; + ch->rightToLeft = ch->bidiLevel % 2; + //tqDebug("visual: %d (%x) placed at %d rightToLeft=%d", visual[i], ch->c.unicode(), x +toAdd, ch->rightToLeft ); + int ww = 0; + if ( ch->c.unicode() >= 32 || ch->c == '\t' || ch->c == '\n' || ch->isCustom() ) { + ww = text->width( start+visual[i] ); + } else { + ww = ch->format()->width( ' ' ); + } + x += ww; + lc = ch; + } + x += toAdd; + + while ( endSpaces-- ) { + ++lastChar; + int sw = lastChar->format()->width( ' ' ); + if ( text->isRightToLeft() ) { + xorig -= sw; + lastChar->x = xorig; + ch->rightToLeft = TRUE; + } else { + lastChar->x = x; + x += sw; + ch->rightToLeft = FALSE; + } + } + + line->w = x; + + if ( length > 255 ) { + free( levels ); + free( visual ); + } + + return new TQTextLineStart; +} +#endif + + +void TQTextFormatter::insertLineStart( TQTextParagraph *parag, int index, TQTextLineStart *ls ) +{ + TQMap::Iterator it; + if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) { + parag->lineStartList().insert( index, ls ); + } else { + delete *it; + parag->lineStartList().remove( it ); + parag->lineStartList().insert( index, ls ); + } +} + + +/* Standard pagebreak algorithm using TQTextFlow::adjustFlow. Returns + the shift of the paragraphs bottom line. + */ +int TQTextFormatter::formatVertically( TQTextDocument* doc, TQTextParagraph* parag ) +{ + int oldHeight = parag->rect().height(); + TQMap& lineStarts = parag->lineStartList(); + TQMap::Iterator it = lineStarts.begin(); + int h = parag->prev() ? TQMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0; + for ( ; it != lineStarts.end() ; ++it ) { + TQTextLineStart * ls = it.data(); + ls->y = h; + TQTextStringChar *c = ¶g->string()->at(it.key()); +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( c && c->customItem() && c->customItem()->ownLine() ) { + int h = c->customItem()->height; + c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() ); + int delta = c->customItem()->height - h; + ls->h += delta; + if ( delta ) + parag->setMovedDown( TRUE ); + } else +#endif + { + + int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h ); + ls->y += shift; + if ( shift ) + parag->setMovedDown( TRUE ); + } + h = ls->y + ls->h; + } + int m = parag->bottomMargin(); + if ( !parag->next() ) + m = 0; + else + m = TQMAX(m, parag->next()->topMargin() ) / 2; + h += m; + parag->setHeight( h ); + return h - oldHeight; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextFormatterBreakInWords::TQTextFormatterBreakInWords() +{ +} + +#define SPACE(s) s + +int TQTextFormatterBreakInWords::format( TQTextDocument *doc,TQTextParagraph *parag, + int start, const TQMap & ) +{ + // make sure bidi information is correct. + (void )parag->string()->isBidi(); + + TQTextStringChar *c = 0; + TQTextStringChar *firstChar = 0; + int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; + int x = left + ( doc ? parag->firstLineMargin() : 0 ); + int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); + int y = parag->prev() ? TQMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; + int h = y; + int len = parag->length(); + if ( doc ) + x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 ); + int rm = parag->rightMargin(); + int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); + bool fullWidth = TRUE; + int minw = 0; + int wused = 0; + bool wrapEnabled = isWrapEnabled( parag ); + + start = 0; //######### what is the point with start?! (Matthias) + if ( start == 0 ) + c = ¶g->string()->at( 0 ); + + int i = start; + TQTextLineStart *lineStart = new TQTextLineStart( y, y, 0 ); + insertLineStart( parag, 0, lineStart ); + + TQPainter *painter = TQTextFormat::painter(); + + int col = 0; + int ww = 0; + TQChar lastChr; + for ( ; i < len; ++i, ++col ) { + if ( c ) + lastChr = c->c; + c = ¶g->string()->at( i ); + // ### the lines below should not be needed + if ( painter ) + c->format()->setPainter( painter ); + if ( i > 0 ) { + c->lineStart = 0; + } else { + c->lineStart = 1; + firstChar = c; + } + if ( c->c.unicode() >= 32 || c->isCustom() ) { + ww = parag->string()->width( i ); + } else if ( c->c == '\t' ) { + int nx = parag->nextTab( i, x - left ) + left; + if ( nx < x ) + ww = w - x; + else + ww = nx - x; + } else { + ww = c->format()->width( ' ' ); + } + +#ifndef TQT_NO_TEXTCUSTOMITEM + if ( c->isCustom() && c->customItem()->ownLine() ) { + x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; + w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); + c->customItem()->resize( w - x ); + w = dw; + y += h; + h = c->height(); + lineStart = new TQTextLineStart( y, h, h ); + insertLineStart( parag, i, lineStart ); + c->lineStart = 1; + firstChar = c; + x = 0xffffff; + continue; + } +#endif + + if ( wrapEnabled && + ( ( wrapAtColumn() == -1 && x + ww > w ) || + ( wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) ) { + x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; + w = dw; + y += h; + h = c->height(); + lineStart = formatLine( parag, parag->string(), lineStart, firstChar, c-1 ); + lineStart->y = y; + insertLineStart( parag, i, lineStart ); + lineStart->baseLine = c->ascent(); + lineStart->h = c->height(); + c->lineStart = 1; + firstChar = c; + col = 0; + if ( wrapAtColumn() != -1 ) + minw = TQMAX( minw, w ); + } else if ( lineStart ) { + lineStart->baseLine = TQMAX( lineStart->baseLine, c->ascent() ); + h = TQMAX( h, c->height() ); + lineStart->h = h; + } + + c->x = x; + x += ww; + wused = TQMAX( wused, x ); + } + + int m = parag->bottomMargin(); + if ( !parag->next() ) + m = 0; + else + m = TQMAX(m, parag->next()->topMargin() ) / 2; + parag->setFullWidth( fullWidth ); + y += h + m; + if ( doc ) + minw += doc->rightMargin(); + if ( !wrapEnabled ) + minw = TQMAX(minw, wused); + + thisminw = minw; + thiswused = wused; + return y; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextFormatterBreakWords::TQTextFormatterBreakWords() +{ +} + +#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \ + int yflow = lineStart->y + parag->rect().y();\ + int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \ + lineStart->y += shift;\ + y += shift;\ + }}while(FALSE) + +int TQTextFormatterBreakWords::format( TQTextDocument *doc, TQTextParagraph *parag, + int start, const TQMap & ) +{ + // make sure bidi information is correct. + (void )parag->string()->isBidi(); + + TQTextStringChar *c = 0; + TQTextStringChar *firstChar = 0; + TQTextString *string = parag->string(); + int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; + int x = left + ( doc ? parag->firstLineMargin() : 0 ); + int y = parag->prev() ? TQMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; + int h = y; + int len = parag->length(); + if ( doc ) + x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 ); + int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 ); + + int curLeft = x; + int rm = parag->rightMargin(); + int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0; + int w = dw - rdiff; + bool fullWidth = TRUE; + int marg = left + rdiff; + int minw = 0; + int wused = 0; + int tminw = marg; + int linespacing = doc ? parag->lineSpacing() : 0; + bool wrapEnabled = isWrapEnabled( parag ); + + start = 0; + + int i = start; + TQTextLineStart *lineStart = new TQTextLineStart( y, y, 0 ); + insertLineStart( parag, 0, lineStart ); + int lastBreak = -1; + int tmpBaseLine = 0, tmph = 0; + bool lastWasNonInlineCustom = FALSE; + + int align = parag->alignment(); + if ( align == TQt::AlignAuto && doc && doc->alignment() != TQt::AlignAuto ) + align = doc->alignment(); + + align &= TQt::AlignHorizontal_Mask; + + // ### hack. The last char in the paragraph is always invisible, + // ### and somehow sometimes has a wrong format. It changes + // ### between // layouting and printing. This corrects some + // ### layouting errors in BiDi mode due to this. + if ( len > 1 ) { + c = ¶g->string()->at(len - 1); + if (!c->isAnchor()) { + if (c->format()) + c->format()->removeRef(); + c->setFormat( string->at( len - 2 ).format() ); + if (c->format()) + c->format()->addRef(); + } + } + + c = ¶g->string()->at( 0 ); + + TQPainter *painter = TQTextFormat::painter(); + int col = 0; + int ww = 0; + TQChar lastChr = c->c; + TQTextFormat *lastFormat = c->format(); + for ( ; i < len; ++i, ++col ) { + if ( i ) { + c = ¶g->string()->at(i-1); + lastChr = c->c; + lastFormat = c->format(); + } + bool lastWasOwnLineCustomItem = lastBreak == -2; + bool hadBreakableChar = lastBreak != -1; + bool lastWasHardBreak = lastChr == TQChar_linesep; + + // ### next line should not be needed + if ( painter ) + c->format()->setPainter( painter ); + c = &string->at( i ); + + if (lastFormat != c->format() && !c->c.isSpace() + && lastFormat->font().italic() && !c->format()->font().italic()) { + int rb = lastFormat->fontMetrics().rightBearing(lastChr); + if (rb < 0) + x -= rb; + } + + if ( ( i > 0 && (x > curLeft || ww == 0) ) || lastWasNonInlineCustom ) { + c->lineStart = 0; + } else { + c->lineStart = 1; + firstChar = c; + } + + // ignore non spacing marks for column count. + if (col != 0 && ::category(c->c) == TQChar::Mark_NonSpacing) + --col; + +#ifndef TQT_NO_TEXTCUSTOMITEM + lastWasNonInlineCustom = ( c->isCustom() && c->customItem()->placement() != TQTextCustomItem::PlaceInline ); +#endif + + if ( c->c.unicode() >= 32 || c->isCustom() ) { + ww = string->width( i ); + } else if ( c->c == '\t' ) { + if ( align == TQt::AlignRight || align == TQt::AlignCenter ) { + // we can not (yet) do tabs + ww = c->format()->width(' ' ); + } else { + int tabx = lastWasHardBreak ? (left + ( doc ? parag->firstLineMargin() : 0 )) : x; + int nx = parag->nextTab( i, tabx - left ) + left; + if ( nx < tabx ) // strrrange... + ww = 0; + else + ww = nx - tabx; + } + } else { + ww = c->format()->width( ' ' ); + } + +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextCustomItem* ci = c->customItem(); + if ( c->isCustom() && ci->ownLine() ) { + TQTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x - ww) ); + x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; + w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); + ci->resize(w - x); + if ( ci->width < w - x ) { + if ( align & TQt::AlignHCenter ) + x = ( w - ci->width ) / 2; + else if ( align & TQt::AlignRight ) { + x = w - ci->width; + } + } + c->x = x; + curLeft = x; + if ( i == 0 || !isBreakable(string, i-1) || + string->at( i - 1 ).lineStart == 0 ) { + y += TQMAX( h, TQMAX( tmph, linespacing ) ); + tmph = c->height(); + h = tmph; + lineStart = lineStart2; + lineStart->y = y; + insertLineStart( parag, i, lineStart ); + c->lineStart = 1; + firstChar = c; + } else { + tmph = c->height(); + h = tmph; + delete lineStart2; + } + lineStart->h = h; + lineStart->baseLine = h; + tmpBaseLine = lineStart->baseLine; + lastBreak = -2; + x = w; + minw = TQMAX( minw, tminw ); + + int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 ); + if ( tw < TQWIDGETSIZE_MAX ) + tminw = tw; + else + tminw = marg; + wused = TQMAX( wused, ci->width ); + continue; + } else if ( c->isCustom() && ci->placement() != TQTextCustomItem::PlaceInline ) { + int tw = ci->minimumWidth(); + if ( tw < TQWIDGETSIZE_MAX ) + minw = TQMAX( minw, tw ); + } +#endif + // we break if + // 1. the last character was a hard break (TQChar_linesep) or + // 2. the last charater was a own-line custom item (eg. table or ruler) or + // 3. wrapping was enabled, it was not a space and following + // condition is true: We either had a breakable character + // previously or we ar allowed to break in words and - either + // we break at w pixels and the current char would exceed that + // or - we break at a column and the current character would + // exceed that. + if ( lastWasHardBreak || lastWasOwnLineCustomItem || + ( wrapEnabled && + ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) && + ( (wrapAtColumn() == -1 && x + ww > w) || + (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) ) + ) + ) { + if ( wrapAtColumn() != -1 ) + minw = TQMAX( minw, x + ww ); + // if a break was forced (no breakable char, hard break or own line custom item), break immediately.... + if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) { + if ( lineStart ) { + lineStart->baseLine = TQMAX( lineStart->baseLine, tmpBaseLine ); + h = TQMAX( h, tmph ); + lineStart->h = h; + DO_FLOW( lineStart ); + } + lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); + x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; + w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); + if ( !doc && c->c == '\t' ) { // qt_format_text tab handling + int nx = parag->nextTab( i, x - left ) + left; + if ( nx < x ) + ww = w - x; + else + ww = nx - x; + } + curLeft = x; + y += TQMAX( h, linespacing ); + tmph = c->height(); + h = 0; + lineStart->y = y; + insertLineStart( parag, i, lineStart ); + lineStart->baseLine = c->ascent(); + lineStart->h = c->height(); + c->lineStart = 1; + firstChar = c; + tmpBaseLine = lineStart->baseLine; + lastBreak = -1; + col = 0; + if ( allowBreakInWords() || lastWasHardBreak ) { + minw = TQMAX(minw, tminw); + tminw = marg + ww; + } + } else { // ... otherwise if we had a breakable char, break there + DO_FLOW( lineStart ); + c->x = x; + i = lastBreak; + lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i+1 ).x) ); + x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; + w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); + if ( !doc && c->c == '\t' ) { // qt_format_text tab handling + int nx = parag->nextTab( i, x - left ) + left; + if ( nx < x ) + ww = w - x; + else + ww = nx - x; + } + curLeft = x; + y += TQMAX( h, linespacing ); + tmph = c->height(); + h = tmph; + lineStart->y = y; + insertLineStart( parag, i + 1, lineStart ); + lineStart->baseLine = c->ascent(); + lineStart->h = c->height(); + c->lineStart = 1; + firstChar = c; + tmpBaseLine = lineStart->baseLine; + lastBreak = -1; + col = 0; + minw = TQMAX(minw, tminw); + tminw = marg; + continue; + } + } else if (lineStart && isBreakable(string, i)) { + if ( len <= 2 || i < len - 1 ) { + tmpBaseLine = TQMAX( tmpBaseLine, c->ascent() ); + tmph = TQMAX( tmph, c->height() ); + } + minw = TQMAX( minw, tminw ); + + tminw = marg + ww; + lineStart->baseLine = TQMAX( lineStart->baseLine, tmpBaseLine ); + h = TQMAX( h, tmph ); + lineStart->h = h; + if ( i < len - 2 || c->c != ' ' ) + lastBreak = i; + } else { + tminw += ww; + int cascent = c->ascent(); + int cheight = c->height(); + int belowBaseLine = TQMAX( tmph - tmpBaseLine, cheight-cascent ); + tmpBaseLine = TQMAX( tmpBaseLine, cascent ); + tmph = tmpBaseLine + belowBaseLine; + } + + c->x = x; + x += ww; + wused = TQMAX( wused, x ); + } + + if ( lineStart ) { + lineStart->baseLine = TQMAX( lineStart->baseLine, tmpBaseLine ); + h = TQMAX( h, tmph ); + lineStart->h = h; + // last line in a paragraph is not justified + if ( align == TQt::AlignJustify ) + align = TQt::AlignAuto; + DO_FLOW( lineStart ); + lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) ); + delete lineStart; + } + + minw = TQMAX( minw, tminw ); + if ( doc ) + minw += doc->rightMargin(); + + int m = parag->bottomMargin(); + if ( !parag->next() ) + m = 0; + else + m = TQMAX(m, parag->next()->topMargin() ) / 2; + parag->setFullWidth( fullWidth ); + y += TQMAX( h, linespacing ) + m; + + wused += rm; + if ( !wrapEnabled || wrapAtColumn() != -1 ) + minw = TQMAX(minw, wused); + + // This is the case where we are breaking wherever we darn well please + // in cases like that, the minw should not be the length of the entire + // word, because we necessarily want to show the word on the whole line. + // example: word wrap in iconview + if ( allowBreakInWords() && minw > wused ) + minw = wused; + + thisminw = minw; + thiswused = wused; + return y; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextIndent::TQTextIndent() +{ +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TQTextFormatCollection::TQTextFormatCollection() + : cKey( 307 ), paintdevice( 0 ) +{ + defFormat = new TQTextFormat( TQApplication::font(), + TQApplication::palette().color( TQPalette::Active, TQColorGroup::Text ) ); + lastFormat = cres = 0; + cflags = -1; + cKey.setAutoDelete( TRUE ); + cachedFormat = 0; +} + +TQTextFormatCollection::~TQTextFormatCollection() +{ + delete defFormat; +} + +void TQTextFormatCollection::setPaintDevice( TQPaintDevice *pd ) +{ + paintdevice = pd; + +#if defined(TQ_WS_X11) + int scr = ( paintdevice ) ? paintdevice->x11Screen() : TQPaintDevice::x11AppScreen(); + + defFormat->fn.x11SetScreen( scr ); + defFormat->update(); + + TQDictIterator it( cKey ); + TQTextFormat *format; + while ( ( format = it.current() ) != 0 ) { + ++it; + format->fn.x11SetScreen( scr ); + format->update(); + } +#endif // TQ_WS_X11 +} + +TQTextFormat *TQTextFormatCollection::format( TQTextFormat *f ) +{ + if ( f->parent() == this || f == defFormat ) { + lastFormat = f; + lastFormat->addRef(); + return lastFormat; + } + + if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) { + lastFormat->addRef(); + return lastFormat; + } + + TQTextFormat *fm = cKey.find( f->key() ); + if ( fm ) { + lastFormat = fm; + lastFormat->addRef(); + return lastFormat; + } + + if ( f->key() == defFormat->key() ) + return defFormat; + + lastFormat = createFormat( *f ); + lastFormat->collection = this; + cKey.insert( lastFormat->key(), lastFormat ); + return lastFormat; +} + +TQTextFormat *TQTextFormatCollection::format( TQTextFormat *of, TQTextFormat *nf, int flags ) +{ + if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) { + cres->addRef(); + return cres; + } + + cres = createFormat( *of ); + kof = of->key(); + knf = nf->key(); + cflags = flags; + if ( flags & TQTextFormat::Bold ) + cres->fn.setBold( nf->fn.bold() ); + if ( flags & TQTextFormat::Italic ) + cres->fn.setItalic( nf->fn.italic() ); + if ( flags & TQTextFormat::Underline ) + cres->fn.setUnderline( nf->fn.underline() ); + if ( flags & TQTextFormat::StrikeOut ) + cres->fn.setStrikeOut( nf->fn.strikeOut() ); + if ( flags & TQTextFormat::Family ) + cres->fn.setFamily( nf->fn.family() ); + if ( flags & TQTextFormat::Size ) { + if ( of->usePixelSizes ) + cres->fn.setPixelSize( nf->fn.pixelSize() ); + else + cres->fn.setPointSize( nf->fn.pointSize() ); + } + if ( flags & TQTextFormat::Color ) + cres->col = nf->col; + if ( flags & TQTextFormat::Misspelled ) + cres->missp = nf->missp; + if ( flags & TQTextFormat::VAlign ) + cres->ha = nf->ha; + cres->update(); + + TQTextFormat *fm = cKey.find( cres->key() ); + if ( !fm ) { + cres->collection = this; + cKey.insert( cres->key(), cres ); + } else { + delete cres; + cres = fm; + cres->addRef(); + } + + return cres; +} + +TQTextFormat *TQTextFormatCollection::format( const TQFont &f, const TQColor &c ) +{ + if ( cachedFormat && cfont == f && ccol == c ) { + cachedFormat->addRef(); + return cachedFormat; + } + + TQString key = TQTextFormat::getKey( f, c, FALSE, TQTextFormat::AlignNormal ); + cachedFormat = cKey.find( key ); + cfont = f; + ccol = c; + + if ( cachedFormat ) { + cachedFormat->addRef(); + return cachedFormat; + } + + if ( key == defFormat->key() ) + return defFormat; + + cachedFormat = createFormat( f, c ); + cachedFormat->collection = this; + cKey.insert( cachedFormat->key(), cachedFormat ); + if ( cachedFormat->key() != key ) + tqWarning("ASSERT: keys for format not identical: '%s '%s'", cachedFormat->key().latin1(), key.latin1() ); + return cachedFormat; +} + +void TQTextFormatCollection::remove( TQTextFormat *f ) +{ + if ( lastFormat == f ) + lastFormat = 0; + if ( cres == f ) + cres = 0; + if ( cachedFormat == f ) + cachedFormat = 0; + if (cKey.find(f->key()) == f) + cKey.remove( f->key() ); +} + +#define UPDATE( up, lo, rest ) \ + if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \ + fm->fn.set##up##rest( font.lo##rest() ) + +void TQTextFormatCollection::updateDefaultFormat( const TQFont &font, const TQColor &color, TQStyleSheet *sheet ) +{ + TQDictIterator it( cKey ); + TQTextFormat *fm; + bool usePixels = font.pointSize() == -1; + bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() : + font.pointSize() != defFormat->fn.pointSize(); + int base = usePixels ? font.pixelSize() : font.pointSize(); + while ( ( fm = it.current() ) ) { + ++it; + UPDATE( F, f, amily ); + UPDATE( W, w, eight ); + UPDATE( B, b, old ); + UPDATE( I, i, talic ); + UPDATE( U, u, nderline ); + if ( changeSize ) { + fm->stdSize = base; + fm->usePixelSizes = usePixels; + if ( usePixels ) + fm->fn.setPixelSize( fm->stdSize ); + else + fm->fn.setPointSize( fm->stdSize ); + sheet->scaleFont( fm->fn, fm->logicalFontSize ); + } + if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col ) + fm->col = color; + fm->update(); + } + + defFormat->fn = font; + defFormat->col = color; + defFormat->update(); + defFormat->stdSize = base; + defFormat->usePixelSizes = usePixels; + + updateKeys(); +} + +// the keys in cKey have changed, rebuild the hashtable +void TQTextFormatCollection::updateKeys() +{ + if ( cKey.isEmpty() ) + return; + cKey.setAutoDelete( FALSE ); + TQTextFormat** formats = new TQTextFormat*[ cKey.count() + 1 ]; + TQTextFormat **f = formats; + TQDictIterator it( cKey ); + while ( ( *f = it.current() ) ) { + ++it; + ++f; + } + cKey.clear(); + for ( f = formats; *f; f++ ) + cKey.insert( (*f)->key(), *f ); + cKey.setAutoDelete( TRUE ); + delete [] formats; +} + + + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +void TQTextFormat::setBold( bool b ) +{ + if ( b == fn.bold() ) + return; + fn.setBold( b ); + update(); +} + +void TQTextFormat::setMisspelled( bool b ) +{ + if ( b == (bool)missp ) + return; + missp = b; + update(); +} + +void TQTextFormat::setVAlign( VerticalAlignment a ) +{ + if ( a == ha ) + return; + ha = a; + update(); +} + +void TQTextFormat::setItalic( bool b ) +{ + if ( b == fn.italic() ) + return; + fn.setItalic( b ); + update(); +} + +void TQTextFormat::setUnderline( bool b ) +{ + if ( b == fn.underline() ) + return; + fn.setUnderline( b ); + update(); +} + +void TQTextFormat::setStrikeOut( bool b ) +{ + if ( b == fn.strikeOut() ) + return; + fn.setStrikeOut( b ); + update(); +} + +void TQTextFormat::setFamily( const TQString &f ) +{ + if ( f == fn.family() ) + return; + fn.setFamily( f ); + update(); +} + +void TQTextFormat::setPointSize( int s ) +{ + if ( s == fn.pointSize() ) + return; + fn.setPointSize( s ); + usePixelSizes = FALSE; + update(); +} + +void TQTextFormat::setFont( const TQFont &f ) +{ + if ( f == fn && !k.isEmpty() ) + return; + fn = f; + update(); +} + +void TQTextFormat::setColor( const TQColor &c ) +{ + if ( c == col ) + return; + col = c; + update(); +} + +TQString TQTextFormat::makeFormatChangeTags( TQTextFormat* defaultFormat, TQTextFormat *f, + const TQString& oldAnchorHref, const TQString& anchorHref ) const +{ + TQString tag; + if ( f ) + tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref ); + + if ( !anchorHref.isEmpty() ) + tag += ""; + + if ( font() != defaultFormat->font() + || vAlign() != defaultFormat->vAlign() + || color().rgb() != defaultFormat->color().rgb() ) { + TQString s; + if ( font().family() != defaultFormat->font().family() ) + s += TQString(!!s?";":"") + "font-family:" + fn.family(); + if ( font().italic() && font().italic() != defaultFormat->font().italic() ) + s += TQString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal"); + if ( font().pointSize() != defaultFormat->font().pointSize() ) + s += TQString(!!s?";":"") + "font-size:" + TQString::number( fn.pointSize() ) + "pt"; + if ( font().weight() != defaultFormat->font().weight() ) + s += TQString(!!s?";":"") + "font-weight:" + TQString::number( fn.weight() * 8 ); + TQString textDecoration; + bool none = FALSE; + if ( font().underline() != defaultFormat->font().underline() ) { + if (font().underline()) + textDecoration = "underline"; + else + none = TRUE; + } + if ( font().overline() != defaultFormat->font().overline() ) { + if (font().overline()) + textDecoration += " overline"; + else + none = TRUE; + } + if ( font().strikeOut() != defaultFormat->font().strikeOut() ) { + if (font().strikeOut()) + textDecoration += " line-through"; + else + none = TRUE; + } + if (none && textDecoration.isEmpty()) + textDecoration = "none"; + if (!textDecoration.isEmpty()) + s += TQString(!!s?";":"") + "text-decoration:" + textDecoration; + if ( vAlign() != defaultFormat->vAlign() ) { + s += TQString(!!s?";":"") + "vertical-align:"; + if ( vAlign() == TQTextFormat::AlignSuperScript ) + s += "super"; + else if ( vAlign() == TQTextFormat::AlignSubScript ) + s += "sub"; + else + s += "normal"; + } + if ( color().rgb() != defaultFormat->color().rgb() ) + s += TQString(!!s?";":"") + "color:" + col.name(); + if ( !s.isEmpty() ) + tag += ""; + } + + return tag; +} + +TQString TQTextFormat::makeFormatEndTags( TQTextFormat* defaultFormat, const TQString& anchorHref ) const +{ + TQString tag; + if ( font().family() != defaultFormat->font().family() + || font().pointSize() != defaultFormat->font().pointSize() + || font().weight() != defaultFormat->font().weight() + || font().italic() != defaultFormat->font().italic() + || font().underline() != defaultFormat->font().underline() + || font().strikeOut() != defaultFormat->font().strikeOut() + || vAlign() != defaultFormat->vAlign() + || color().rgb() != defaultFormat->color().rgb() ) + tag += ""; + if ( !anchorHref.isEmpty() ) + tag += ""; + return tag; +} + +TQTextFormat TQTextFormat::makeTextFormat( const TQStyleSheetItem *style, const TQMap& attr, double scaleFontsFactor ) const +{ + TQTextFormat format(*this); + if (!style ) + return format; + + if ( !style->isAnchor() && style->color().isValid() ) { + // the style is not an anchor and defines a color. + // It might be used inside an anchor and it should + // override the link color. + format.linkColor = FALSE; + } + switch ( style->verticalAlignment() ) { + case TQStyleSheetItem::VAlignBaseline: + format.setVAlign( TQTextFormat::AlignNormal ); + break; + case TQStyleSheetItem::VAlignSuper: + format.setVAlign( TQTextFormat::AlignSuperScript ); + break; + case TQStyleSheetItem::VAlignSub: + format.setVAlign( TQTextFormat::AlignSubScript ); + break; + } + + if ( style->fontWeight() != TQStyleSheetItem::Undefined ) + format.fn.setWeight( style->fontWeight() ); + if ( style->fontSize() != TQStyleSheetItem::Undefined ) { + format.fn.setPointSize( style->fontSize() ); + } else if ( style->logicalFontSize() != TQStyleSheetItem::Undefined ) { + format.logicalFontSize = style->logicalFontSize(); + if ( format.usePixelSizes ) + format.fn.setPixelSize( format.stdSize ); + else + format.fn.setPointSize( format.stdSize ); + style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); + } else if ( style->logicalFontSizeStep() ) { + format.logicalFontSize += style->logicalFontSizeStep(); + if ( format.usePixelSizes ) + format.fn.setPixelSize( format.stdSize ); + else + format.fn.setPointSize( format.stdSize ); + style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); + } + if ( !style->fontFamily().isEmpty() ) + format.fn.setFamily( style->fontFamily() ); + if ( style->color().isValid() ) + format.col = style->color(); + if ( style->definesFontItalic() ) + format.fn.setItalic( style->fontItalic() ); + if ( style->definesFontUnderline() ) + format.fn.setUnderline( style->fontUnderline() ); + if ( style->definesFontStrikeOut() ) + format.fn.setStrikeOut( style->fontStrikeOut() ); + + + if ( style->name() == "font") { + if ( attr.contains("color") ) { + TQString s = attr["color"]; + if ( !s.isEmpty() ) { + format.col.setNamedColor( s ); + format.linkColor = FALSE; + } + } + if ( attr.contains("face") ) { + TQString a = attr["face"]; + TQString family = a.section( ',', 0, 0 ); + if ( !!family ) + format.fn.setFamily( family ); + } + if ( attr.contains("size") ) { + TQString a = attr["size"]; + int n = a.toInt(); + if ( a[0] == '+' || a[0] == '-' ) + n += 3; + format.logicalFontSize = n; + if ( format.usePixelSizes ) + format.fn.setPixelSize( format.stdSize ); + else + format.fn.setPointSize( format.stdSize ); + style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); + } + } + if ( attr.contains("style" ) ) { + TQString a = attr["style"]; + for ( int s = 0; s < a.contains(';')+1; s++ ) { + TQString style = a.section( ';', s, s ); + if ( style.startsWith("font-size:" ) && style.endsWith("pt") ) { + format.logicalFontSize = 0; + int size = int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toDouble() ); + format.setPointSize( size ); + } else if ( style.startsWith("font-style:" ) ) { + TQString s = style.mid( 11 ).stripWhiteSpace(); + if ( s == "normal" ) + format.fn.setItalic( FALSE ); + else if ( s == "italic" || s == "oblique" ) + format.fn.setItalic( TRUE ); + } else if ( style.startsWith("font-weight:" ) ) { + TQString s = style.mid( 12 ); + bool ok = TRUE; + int n = s.toInt( &ok ); + if ( ok ) + format.fn.setWeight( n/8 ); + } else if ( style.startsWith("font-family:" ) ) { + TQString family = style.mid(12).section(',',0,0); + family.replace( '\"', ' ' ); + family.replace( '\'', ' ' ); + family = family.stripWhiteSpace(); + format.fn.setFamily( family ); + } else if ( style.startsWith("text-decoration:" ) ) { + TQString s = style.mid( 16 ); + format.fn.setOverline( s.find("overline") != -1 ); + format.fn.setStrikeOut( s.find("line-through") != -1 ); + format.fn.setUnderline( s.find("underline") != -1 ); + } else if ( style.startsWith("vertical-align:" ) ) { + TQString s = style.mid( 15 ).stripWhiteSpace(); + if ( s == "sub" ) + format.setVAlign( TQTextFormat::AlignSubScript ); + else if ( s == "super" ) + format.setVAlign( TQTextFormat::AlignSuperScript ); + else + format.setVAlign( TQTextFormat::AlignNormal ); + } else if ( style.startsWith("color:" ) ) { + format.col.setNamedColor( style.mid(6) ); + format.linkColor = FALSE; + } + } + } + + format.update(); + return format; +} + +#ifndef TQT_NO_TEXTCUSTOMITEM + +struct TQPixmapInt +{ + TQPixmapInt() : ref( 0 ) {} + TQPixmap pm; + int ref; + TQ_DUMMY_COMPARISON_OPERATOR(TQPixmapInt) +}; + +static TQMap *pixmap_map = 0; + +TQTextImage::TQTextImage( TQTextDocument *p, const TQMap &attr, const TQString& context, + TQMimeSourceFactory &factory ) + : TQTextCustomItem( p ) +{ + width = height = 0; + if ( attr.contains("width") ) + width = attr["width"].toInt(); + if ( attr.contains("height") ) + height = attr["height"].toInt(); + + reg = 0; + TQString imageName = attr["src"]; + + if (!imageName) + imageName = attr["source"]; + + if ( !imageName.isEmpty() ) { + imgId = TQString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory ); + if ( !pixmap_map ) + pixmap_map = new TQMap; + if ( pixmap_map->contains( imgId ) ) { + TQPixmapInt& pmi = pixmap_map->operator[](imgId); + pm = pmi.pm; + pmi.ref++; + width = pm.width(); + height = pm.height(); + } else { + TQImage img; + const TQMimeSource* m = + factory.data( imageName, context ); + if ( !m ) { + tqWarning("TQTextImage: no mimesource for %s", imageName.latin1() ); + } + else { + if ( !TQImageDrag::decode( m, img ) ) { + tqWarning("TQTextImage: cannot decode %s", imageName.latin1() ); + } + } + + if ( !img.isNull() ) { + if ( width == 0 ) { + width = img.width(); + if ( height != 0 ) { + width = img.width() * height / img.height(); + } + } + if ( height == 0 ) { + height = img.height(); + if ( width != img.width() ) { + height = img.height() * width / img.width(); + } + } + if ( img.width() != width || img.height() != height ){ +#ifndef TQT_NO_IMAGE_SMOOTHSCALE + img = img.smoothScale(width, height); +#endif + width = img.width(); + height = img.height(); + } + pm.convertFromImage( img ); + } + if ( !pm.isNull() ) { + TQPixmapInt& pmi = pixmap_map->operator[](imgId); + pmi.pm = pm; + pmi.ref++; + } + } + if ( pm.mask() ) { + TQRegion mask( *pm.mask() ); + TQRegion all( 0, 0, pm.width(), pm.height() ); + reg = new TQRegion( all.subtract( mask ) ); + } + } + + if ( pm.isNull() && (width*height)==0 ) + width = height = 50; + + place = PlaceInline; + if ( attr["align"] == "left" ) + place = PlaceLeft; + else if ( attr["align"] == "right" ) + place = PlaceRight; + + tmpwidth = width; + tmpheight = height; + + attributes = attr; +} + +TQTextImage::~TQTextImage() +{ + if ( pixmap_map && pixmap_map->contains( imgId ) ) { + TQPixmapInt& pmi = pixmap_map->operator[](imgId); + pmi.ref--; + if ( !pmi.ref ) { + pixmap_map->remove( imgId ); + if ( pixmap_map->isEmpty() ) { + delete pixmap_map; + pixmap_map = 0; + } + } + } + delete reg; +} + +TQString TQTextImage::richText() const +{ + TQString s; + s += "::ConstIterator it = attributes.begin(); + for ( ; it != attributes.end(); ++it ) { + s += it.key() + "="; + if ( (*it).find( ' ' ) != -1 ) + s += "\"" + *it + "\"" + " "; + else + s += *it + " "; + } + s += ">"; + return s; +} + +void TQTextImage::adjustToPainter( TQPainter* p ) +{ + width = scale( tmpwidth, p ); + height = scale( tmpheight, p ); +} + +#if !defined(TQ_WS_X11) +#include +#include +static TQPixmap *qrt_selection = 0; +static TQSingleCleanupHandler qrt_cleanup_pixmap; +static void qrt_createSelectionPixmap( const TQColorGroup &cg ) +{ + qrt_selection = new TQPixmap( 2, 2 ); + qrt_cleanup_pixmap.set( &qrt_selection ); + qrt_selection->fill( TQt::color0 ); + TQBitmap m( 2, 2 ); + m.fill( TQt::color1 ); + TQPainter p( &m ); + p.setPen( TQt::color0 ); + for ( int j = 0; j < 2; ++j ) { + p.drawPoint( j % 2, j ); + } + p.end(); + qrt_selection->setMask( m ); + qrt_selection->fill( cg.highlight() ); +} +#endif + +void TQTextImage::draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) +{ + if ( placement() != PlaceInline ) { + x = xpos; + y = ypos; + } + + if ( pm.isNull() ) { + p->fillRect( x , y, width, height, cg.dark() ); + return; + } + + if ( is_printer( p ) ) { + p->drawPixmap( TQRect( x, y, width, height ), pm ); + return; + } + + if ( placement() != PlaceInline && !TQRect( xpos, ypos, width, height ).intersects( TQRect( cx, cy, cw, ch ) ) ) + return; + + if ( placement() == PlaceInline ) + p->drawPixmap( x , y, pm ); + else + p->drawPixmap( cx , cy, pm, cx - x, cy - y, cw, ch ); + + if ( selected && placement() == PlaceInline && is_printer( p ) ) { +#if defined(TQ_WS_X11) + p->fillRect( TQRect( TQPoint( x, y ), pm.size() ), TQBrush( cg.highlight(), TQBrush::Dense4Pattern) ); +#else // in WIN32 Dense4Pattern doesn't work correctly (transparency problem), so work around it + if ( !qrt_selection ) + qrt_createSelectionPixmap( cg ); + p->drawTiledPixmap( x, y, pm.width(), pm.height(), *qrt_selection ); +#endif + } +} + +void TQTextHorizontalLine::adjustToPainter( TQPainter* p ) +{ + height = scale( tmpheight, p ); +} + + +TQTextHorizontalLine::TQTextHorizontalLine( TQTextDocument *p, const TQMap &attr, + const TQString &, + TQMimeSourceFactory & ) + : TQTextCustomItem( p ) +{ + height = tmpheight = 8; + if ( attr.find( "color" ) != attr.end() ) + color = TQColor( *attr.find( "color" ) ); + shade = attr.find( "noshade" ) == attr.end(); +} + +TQTextHorizontalLine::~TQTextHorizontalLine() +{ +} + +TQString TQTextHorizontalLine::richText() const +{ + return "
"; +} + +void TQTextHorizontalLine::draw( TQPainter* p, int x, int y, int , int , int , int , const TQColorGroup& cg, bool selected ) +{ + TQRect r( x, y, width, height); + if ( is_printer( p ) || !shade ) { + TQPen oldPen = p->pen(); + if ( !color.isValid() ) + p->setPen( TQPen( cg.text(), is_printer( p ) ? height/8 : TQMAX( 2, height/4 ) ) ); + else + p->setPen( TQPen( color, is_printer( p ) ? height/8 : TQMAX( 2, height/4 ) ) ); + p->drawLine( r.left()-1, y + height / 2, r.right() + 1, y + height / 2 ); + p->setPen( oldPen ); + } else { + TQColorGroup g( cg ); + if ( color.isValid() ) + g.setColor( TQColorGroup::Dark, color ); + if ( selected ) + p->fillRect( r, g.highlight() ); + qDrawShadeLine( p, r.left() - 1, y + height / 2, r.right() + 1, y + height / 2, g, TRUE, height / 8 ); + } +} +#endif //TQT_NO_TEXTCUSTOMITEM + +/*****************************************************************/ +// Small set of utility functions to make the parser a bit simpler +// + +bool TQTextDocument::hasPrefix(const TQChar* doc, int length, int pos, TQChar c) +{ + if ( pos + 1 > length ) + return FALSE; + return doc[ pos ].lower() == c.lower(); +} + +bool TQTextDocument::hasPrefix( const TQChar* doc, int length, int pos, const TQString& s ) +{ + if ( pos + (int) s.length() > length ) + return FALSE; + for ( int i = 0; i < (int)s.length(); i++ ) { + if ( doc[ pos + i ].lower() != s[ i ].lower() ) + return FALSE; + } + return TRUE; +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +static bool qt_is_cell_in_use( TQPtrList& cells, int row, int col ) +{ + for ( TQTextTableCell* c = cells.first(); c; c = cells.next() ) { + if ( row >= c->row() && row < c->row() + c->rowspan() + && col >= c->column() && col < c->column() + c->colspan() ) + return TRUE; + } + return FALSE; +} + +TQTextCustomItem* TQTextDocument::parseTable( const TQMap &attr, const TQTextFormat &fmt, + const TQChar* doc, int length, int& pos, TQTextParagraph *curpar ) +{ + + TQTextTable* table = new TQTextTable( this, attr ); + int row = -1; + int col = -1; + + TQString rowbgcolor; + TQString rowalign; + TQString tablebgcolor = attr["bgcolor"]; + + TQPtrList multicells; + + TQString tagname; + (void) eatSpace(doc, length, pos); + while ( pos < length) { + if (hasPrefix(doc, length, pos, TQChar('<')) ){ + if (hasPrefix(doc, length, pos+1, TQChar('/'))) { + tagname = parseCloseTag( doc, length, pos ); + if ( tagname == "table" ) { + return table; + } + } else { + TQMap attr2; + bool emptyTag = FALSE; + tagname = parseOpenTag( doc, length, pos, attr2, emptyTag ); + if ( tagname == "tr" ) { + rowbgcolor = attr2["bgcolor"]; + rowalign = attr2["align"]; + row++; + col = -1; + } + else if ( tagname == "td" || tagname == "th" ) { + col++; + while ( qt_is_cell_in_use( multicells, row, col ) ) { + col++; + } + + if ( row >= 0 && col >= 0 ) { + const TQStyleSheetItem* s = sheet_->item(tagname); + if ( !attr2.contains("bgcolor") ) { + if (!rowbgcolor.isEmpty() ) + attr2["bgcolor"] = rowbgcolor; + else if (!tablebgcolor.isEmpty() ) + attr2["bgcolor"] = tablebgcolor; + } + if ( !attr2.contains("align") ) { + if (!rowalign.isEmpty() ) + attr2["align"] = rowalign; + } + + // extract the cell contents + int end = pos; + while ( end < length + && !hasPrefix( doc, length, end, "richText()->parentPar = curpar; + if ( cell->colspan() > 1 || cell->rowspan() > 1 ) + multicells.append( cell ); + col += cell->colspan()-1; + pos = end; + } + } + } + + } else { + ++pos; + } + } + return table; +} +#endif // TQT_NO_TEXTCUSTOMITEM + +bool TQTextDocument::eatSpace(const TQChar* doc, int length, int& pos, bool includeNbsp ) +{ + int old_pos = pos; + while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != TQChar::nbsp ) ) ) + pos++; + return old_pos < pos; +} + +bool TQTextDocument::eat(const TQChar* doc, int length, int& pos, TQChar c) +{ + bool ok = pos < length && doc[pos] == c; + if ( ok ) + pos++; + return ok; +} +/*****************************************************************/ + +struct Entity { + const char * name; + TQ_UINT16 code; +}; + +static const Entity entitylist [] = { + { "AElig", 0x00c6 }, + { "Aacute", 0x00c1 }, + { "Acirc", 0x00c2 }, + { "Agrave", 0x00c0 }, + { "Alpha", 0x0391 }, + { "AMP", 38 }, + { "Aring", 0x00c5 }, + { "Atilde", 0x00c3 }, + { "Auml", 0x00c4 }, + { "Beta", 0x0392 }, + { "Ccedil", 0x00c7 }, + { "Chi", 0x03a7 }, + { "Dagger", 0x2021 }, + { "Delta", 0x0394 }, + { "ETH", 0x00d0 }, + { "Eacute", 0x00c9 }, + { "Ecirc", 0x00ca }, + { "Egrave", 0x00c8 }, + { "Epsilon", 0x0395 }, + { "Eta", 0x0397 }, + { "Euml", 0x00cb }, + { "Gamma", 0x0393 }, + { "GT", 62 }, + { "Iacute", 0x00cd }, + { "Icirc", 0x00ce }, + { "Igrave", 0x00cc }, + { "Iota", 0x0399 }, + { "Iuml", 0x00cf }, + { "Kappa", 0x039a }, + { "Lambda", 0x039b }, + { "LT", 60 }, + { "Mu", 0x039c }, + { "Ntilde", 0x00d1 }, + { "Nu", 0x039d }, + { "OElig", 0x0152 }, + { "Oacute", 0x00d3 }, + { "Ocirc", 0x00d4 }, + { "Ograve", 0x00d2 }, + { "Omega", 0x03a9 }, + { "Omicron", 0x039f }, + { "Oslash", 0x00d8 }, + { "Otilde", 0x00d5 }, + { "Ouml", 0x00d6 }, + { "Phi", 0x03a6 }, + { "Pi", 0x03a0 }, + { "Prime", 0x2033 }, + { "Psi", 0x03a8 }, + { "TQUOT", 34 }, + { "Rho", 0x03a1 }, + { "Scaron", 0x0160 }, + { "Sigma", 0x03a3 }, + { "THORN", 0x00de }, + { "Tau", 0x03a4 }, + { "Theta", 0x0398 }, + { "Uacute", 0x00da }, + { "Ucirc", 0x00db }, + { "Ugrave", 0x00d9 }, + { "Upsilon", 0x03a5 }, + { "Uuml", 0x00dc }, + { "Xi", 0x039e }, + { "Yacute", 0x00dd }, + { "Yuml", 0x0178 }, + { "Zeta", 0x0396 }, + { "aacute", 0x00e1 }, + { "acirc", 0x00e2 }, + { "acute", 0x00b4 }, + { "aelig", 0x00e6 }, + { "agrave", 0x00e0 }, + { "alefsym", 0x2135 }, + { "alpha", 0x03b1 }, + { "amp", 38 }, + { "and", 0x22a5 }, + { "ang", 0x2220 }, + { "apos", 0x0027 }, + { "aring", 0x00e5 }, + { "asymp", 0x2248 }, + { "atilde", 0x00e3 }, + { "auml", 0x00e4 }, + { "bdquo", 0x201e }, + { "beta", 0x03b2 }, + { "brvbar", 0x00a6 }, + { "bull", 0x2022 }, + { "cap", 0x2229 }, + { "ccedil", 0x00e7 }, + { "cedil", 0x00b8 }, + { "cent", 0x00a2 }, + { "chi", 0x03c7 }, + { "circ", 0x02c6 }, + { "clubs", 0x2663 }, + { "cong", 0x2245 }, + { "copy", 0x00a9 }, + { "crarr", 0x21b5 }, + { "cup", 0x222a }, + { "curren", 0x00a4 }, + { "dArr", 0x21d3 }, + { "dagger", 0x2020 }, + { "darr", 0x2193 }, + { "deg", 0x00b0 }, + { "delta", 0x03b4 }, + { "diams", 0x2666 }, + { "divide", 0x00f7 }, + { "eacute", 0x00e9 }, + { "ecirc", 0x00ea }, + { "egrave", 0x00e8 }, + { "empty", 0x2205 }, + { "emsp", 0x2003 }, + { "ensp", 0x2002 }, + { "epsilon", 0x03b5 }, + { "equiv", 0x2261 }, + { "eta", 0x03b7 }, + { "eth", 0x00f0 }, + { "euml", 0x00eb }, + { "euro", 0x20ac }, + { "exist", 0x2203 }, + { "fnof", 0x0192 }, + { "forall", 0x2200 }, + { "frac12", 0x00bd }, + { "frac14", 0x00bc }, + { "frac34", 0x00be }, + { "frasl", 0x2044 }, + { "gamma", 0x03b3 }, + { "ge", 0x2265 }, + { "gt", 62 }, + { "hArr", 0x21d4 }, + { "harr", 0x2194 }, + { "hearts", 0x2665 }, + { "hellip", 0x2026 }, + { "iacute", 0x00ed }, + { "icirc", 0x00ee }, + { "iexcl", 0x00a1 }, + { "igrave", 0x00ec }, + { "image", 0x2111 }, + { "infin", 0x221e }, + { "int", 0x222b }, + { "iota", 0x03b9 }, + { "iquest", 0x00bf }, + { "isin", 0x2208 }, + { "iuml", 0x00ef }, + { "kappa", 0x03ba }, + { "lArr", 0x21d0 }, + { "lambda", 0x03bb }, + { "lang", 0x2329 }, + { "laquo", 0x00ab }, + { "larr", 0x2190 }, + { "lceil", 0x2308 }, + { "ldquo", 0x201c }, + { "le", 0x2264 }, + { "lfloor", 0x230a }, + { "lowast", 0x2217 }, + { "loz", 0x25ca }, + { "lrm", 0x200e }, + { "lsaquo", 0x2039 }, + { "lsquo", 0x2018 }, + { "lt", 60 }, + { "macr", 0x00af }, + { "mdash", 0x2014 }, + { "micro", 0x00b5 }, + { "middot", 0x00b7 }, + { "minus", 0x2212 }, + { "mu", 0x03bc }, + { "nabla", 0x2207 }, + { "nbsp", 0x00a0 }, + { "ndash", 0x2013 }, + { "ne", 0x2260 }, + { "ni", 0x220b }, + { "not", 0x00ac }, + { "notin", 0x2209 }, + { "nsub", 0x2284 }, + { "ntilde", 0x00f1 }, + { "nu", 0x03bd }, + { "oacute", 0x00f3 }, + { "ocirc", 0x00f4 }, + { "oelig", 0x0153 }, + { "ograve", 0x00f2 }, + { "oline", 0x203e }, + { "omega", 0x03c9 }, + { "omicron", 0x03bf }, + { "oplus", 0x2295 }, + { "or", 0x22a6 }, + { "ordf", 0x00aa }, + { "ordm", 0x00ba }, + { "oslash", 0x00f8 }, + { "otilde", 0x00f5 }, + { "otimes", 0x2297 }, + { "ouml", 0x00f6 }, + { "para", 0x00b6 }, + { "part", 0x2202 }, + { "percnt", 0x0025 }, + { "permil", 0x2030 }, + { "perp", 0x22a5 }, + { "phi", 0x03c6 }, + { "pi", 0x03c0 }, + { "piv", 0x03d6 }, + { "plusmn", 0x00b1 }, + { "pound", 0x00a3 }, + { "prime", 0x2032 }, + { "prod", 0x220f }, + { "prop", 0x221d }, + { "psi", 0x03c8 }, + { "quot", 34 }, + { "rArr", 0x21d2 }, + { "radic", 0x221a }, + { "rang", 0x232a }, + { "raquo", 0x00bb }, + { "rarr", 0x2192 }, + { "rceil", 0x2309 }, + { "rdquo", 0x201d }, + { "real", 0x211c }, + { "reg", 0x00ae }, + { "rfloor", 0x230b }, + { "rho", 0x03c1 }, + { "rlm", 0x200f }, + { "rsaquo", 0x203a }, + { "rsquo", 0x2019 }, + { "sbquo", 0x201a }, + { "scaron", 0x0161 }, + { "sdot", 0x22c5 }, + { "sect", 0x00a7 }, + { "shy", 0x00ad }, + { "sigma", 0x03c3 }, + { "sigmaf", 0x03c2 }, + { "sim", 0x223c }, + { "spades", 0x2660 }, + { "sub", 0x2282 }, + { "sube", 0x2286 }, + { "sum", 0x2211 }, + { "sup1", 0x00b9 }, + { "sup2", 0x00b2 }, + { "sup3", 0x00b3 }, + { "sup", 0x2283 }, + { "supe", 0x2287 }, + { "szlig", 0x00df }, + { "tau", 0x03c4 }, + { "there4", 0x2234 }, + { "theta", 0x03b8 }, + { "thetasym", 0x03d1 }, + { "thinsp", 0x2009 }, + { "thorn", 0x00fe }, + { "tilde", 0x02dc }, + { "times", 0x00d7 }, + { "trade", 0x2122 }, + { "uArr", 0x21d1 }, + { "uacute", 0x00fa }, + { "uarr", 0x2191 }, + { "ucirc", 0x00fb }, + { "ugrave", 0x00f9 }, + { "uml", 0x00a8 }, + { "upsih", 0x03d2 }, + { "upsilon", 0x03c5 }, + { "uuml", 0x00fc }, + { "weierp", 0x2118 }, + { "xi", 0x03be }, + { "yacute", 0x00fd }, + { "yen", 0x00a5 }, + { "yuml", 0x00ff }, + { "zeta", 0x03b6 }, + { "zwj", 0x200d }, + { "zwnj", 0x200c }, + { "", 0x0000 } +}; + + + + + +static TQMap *html_map = 0; +static void tqt_cleanup_html_map() +{ + delete html_map; + html_map = 0; +} + +static TQMap *htmlMap() +{ + if ( !html_map ) { + html_map = new TQMap; + tqAddPostRoutine( tqt_cleanup_html_map ); + + const Entity *ent = entitylist; + while( ent->code ) { + html_map->insert( ent->name, TQChar(ent->code) ); + ent++; + } + } + return html_map; +} + +TQChar TQTextDocument::parseHTMLSpecialChar(const TQChar* doc, int length, int& pos) +{ + TQString s; + pos++; + int recoverpos = pos; + while ( pos < length && doc[pos] != ';' && !doc[pos].isSpace() && pos < recoverpos + 8 ) { + s += doc[pos]; + pos++; + } + if (doc[pos] != ';' && !doc[pos].isSpace() ) { + pos = recoverpos; + return '&'; + } + pos++; + + if ( s.length() > 1 && s[0] == '#') { + int off = 1; + int base = 10; + if (s[1] == 'x') { + off = 2; + base = 16; + } + bool ok; + int num = s.mid(off).toInt(&ok, base); + if ( num == 151 ) // ### hack for designer manual + return '-'; + if (ok) + return num; + } else { + TQMap::Iterator it = htmlMap()->find(s); + if ( it != htmlMap()->end() ) { + return *it; + } + } + + pos = recoverpos; + return '&'; +} + +TQString TQTextDocument::parseWord(const TQChar* doc, int length, int& pos, bool lower) +{ + TQString s; + + if (doc[pos] == '"') { + pos++; + while ( pos < length && doc[pos] != '"' ) { + if ( doc[pos] == '&' ) { + s += parseHTMLSpecialChar( doc, length, pos ); + } else { + s += doc[pos]; + pos++; + } + } + eat(doc, length, pos, '"'); + } else if (doc[pos] == '\'') { + pos++; + while ( pos < length && doc[pos] != '\'' ) { + s += doc[pos]; + pos++; + } + eat(doc, length, pos, '\''); + } else { + static TQString term = TQString::fromLatin1("/>"); + while ( pos < length + && doc[pos] != '>' + && !hasPrefix(doc, length, pos, term) + && doc[pos] != '<' + && doc[pos] != '=' + && !doc[pos].isSpace() ) + { + if ( doc[pos] == '&' ) { + s += parseHTMLSpecialChar( doc, length, pos ); + } else { + s += doc[pos]; + pos++; + } + } + if (lower) + s = s.lower(); + } + return s; +} + +TQChar TQTextDocument::parseChar(const TQChar* doc, int length, int& pos, TQStyleSheetItem::WhiteSpaceMode wsm ) +{ + if ( pos >= length ) + return TQChar::null; + + TQChar c = doc[pos++]; + + if (c == '<' ) + return TQChar::null; + + if ( c.isSpace() && c != TQChar::nbsp ) { + if ( wsm == TQStyleSheetItem::WhiteSpacePre ) { + if ( c == '\n' ) + return TQChar_linesep; + else + return c; + } else { // non-pre mode: collapse whitespace except nbsp + while ( pos< length && + doc[pos].isSpace() && doc[pos] != TQChar::nbsp ) + pos++; + return ' '; + } + } + else if ( c == '&' ) + return parseHTMLSpecialChar( doc, length, --pos ); + else + return c; +} + +TQString TQTextDocument::parseOpenTag(const TQChar* doc, int length, int& pos, + TQMap &attr, bool& emptyTag) +{ + emptyTag = FALSE; + pos++; + if ( hasPrefix(doc, length, pos, '!') ) { + if ( hasPrefix( doc, length, pos+1, "--")) { + pos += 3; + // eat comments + TQString pref = TQString::fromLatin1("-->"); + while ( !hasPrefix(doc, length, pos, pref ) && pos < length ) + pos++; + if ( hasPrefix(doc, length, pos, pref ) ) { + pos += 3; + eatSpace(doc, length, pos, TRUE); + } + emptyTag = TRUE; + return TQString::null; + } + else { + // eat strange internal tags + while ( !hasPrefix(doc, length, pos, '>') && pos < length ) + pos++; + if ( hasPrefix(doc, length, pos, '>') ) { + pos++; + eatSpace(doc, length, pos, TRUE); + } + return TQString::null; + } + } + + TQString tag = parseWord(doc, length, pos ); + eatSpace(doc, length, pos, TRUE); + static TQString term = TQString::fromLatin1("/>"); + static TQString s_TRUE = TQString::fromLatin1("TRUE"); + + while (doc[pos] != '>' && ! (emptyTag = hasPrefix(doc, length, pos, term) )) { + TQString key = parseWord(doc, length, pos ); + eatSpace(doc, length, pos, TRUE); + if ( key.isEmpty()) { + // error recovery + while ( pos < length && doc[pos] != '>' ) + pos++; + break; + } + TQString value; + if (hasPrefix(doc, length, pos, '=') ){ + pos++; + eatSpace(doc, length, pos); + value = parseWord(doc, length, pos, FALSE); + } + else + value = s_TRUE; + attr.insert(key.lower(), value ); + eatSpace(doc, length, pos, TRUE); + } + + if (emptyTag) { + eat(doc, length, pos, '/'); + eat(doc, length, pos, '>'); + } + else + eat(doc, length, pos, '>'); + + return tag; +} + +TQString TQTextDocument::parseCloseTag( const TQChar* doc, int length, int& pos ) +{ + pos++; + pos++; + TQString tag = parseWord(doc, length, pos ); + eatSpace(doc, length, pos, TRUE); + eat(doc, length, pos, '>'); + return tag; +} + +TQTextFlow::TQTextFlow() +{ + w = pagesize = 0; +} + +TQTextFlow::~TQTextFlow() +{ + clear(); +} + +void TQTextFlow::clear() +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + leftItems.setAutoDelete( TRUE ); + rightItems.setAutoDelete( TRUE ); + leftItems.clear(); + rightItems.clear(); + leftItems.setAutoDelete( FALSE ); + rightItems.setAutoDelete( FALSE ); +#endif +} + +void TQTextFlow::setWidth( int width ) +{ + w = width; +} + +int TQTextFlow::adjustLMargin( int yp, int, int margin, int space ) +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + for ( TQTextCustomItem* item = leftItems.first(); item; item = leftItems.next() ) { + if ( item->ypos == -1 ) + continue; + if ( yp >= item->ypos && yp < item->ypos + item->height ) + margin = TQMAX( margin, item->xpos + item->width + space ); + } +#endif + return margin; +} + +int TQTextFlow::adjustRMargin( int yp, int, int margin, int space ) +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + for ( TQTextCustomItem* item = rightItems.first(); item; item = rightItems.next() ) { + if ( item->ypos == -1 ) + continue; + if ( yp >= item->ypos && yp < item->ypos + item->height ) + margin = TQMAX( margin, w - item->xpos - space ); + } +#endif + return margin; +} + + +int TQTextFlow::adjustFlow( int y, int /*w*/, int h ) +{ + if ( pagesize > 0 ) { // check pages + int yinpage = y % pagesize; + if ( yinpage <= border_tolerance ) + return border_tolerance - yinpage; + else + if ( yinpage + h > pagesize - border_tolerance ) + return ( pagesize - yinpage ) + border_tolerance; + } + return 0; +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +void TQTextFlow::unregisterFloatingItem( TQTextCustomItem* item ) +{ + leftItems.removeRef( item ); + rightItems.removeRef( item ); +} + +void TQTextFlow::registerFloatingItem( TQTextCustomItem* item ) +{ + if ( item->placement() == TQTextCustomItem::PlaceRight ) { + if ( !rightItems.contains( item ) ) + rightItems.append( item ); + } else if ( item->placement() == TQTextCustomItem::PlaceLeft && + !leftItems.contains( item ) ) { + leftItems.append( item ); + } +} +#endif // TQT_NO_TEXTCUSTOMITEM + +TQRect TQTextFlow::boundingRect() const +{ + TQRect br; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQPtrListIterator l( leftItems ); + while( l.current() ) { + br = br.unite( l.current()->geometry() ); + ++l; + } + TQPtrListIterator r( rightItems ); + while( r.current() ) { + br = br.unite( r.current()->geometry() ); + ++r; + } +#endif + return br; +} + + +void TQTextFlow::drawFloatingItems( TQPainter* p, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextCustomItem *item; + for ( item = leftItems.first(); item; item = leftItems.next() ) { + if ( item->xpos == -1 || item->ypos == -1 ) + continue; + item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); + } + + for ( item = rightItems.first(); item; item = rightItems.next() ) { + if ( item->xpos == -1 || item->ypos == -1 ) + continue; + item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); + } +#endif +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#ifndef TQT_NO_TEXTCUSTOMITEM +void TQTextCustomItem::pageBreak( int /*y*/ , TQTextFlow* /*flow*/ ) +{ +} +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM +TQTextTable::TQTextTable( TQTextDocument *p, const TQMap & attr ) + : TQTextCustomItem( p ) +{ + cells.setAutoDelete( FALSE ); + cellspacing = 2; + if ( attr.contains("cellspacing") ) + cellspacing = attr["cellspacing"].toInt(); + cellpadding = 1; + if ( attr.contains("cellpadding") ) + cellpadding = attr["cellpadding"].toInt(); + border = innerborder = 0; + if ( attr.contains("border" ) ) { + TQString s( attr["border"] ); + if ( s == "TRUE" ) + border = 1; + else + border = attr["border"].toInt(); + } + us_b = border; + + innerborder = us_ib = border ? 1 : 0; + + if ( border ) + cellspacing += 2; + + us_ib = innerborder; + us_cs = cellspacing; + us_cp = cellpadding; + outerborder = cellspacing + border; + us_ob = outerborder; + layout = new TQGridLayout( 1, 1, cellspacing ); + + fixwidth = 0; + stretch = 0; + if ( attr.contains("width") ) { + bool b; + TQString s( attr["width"] ); + int w = s.toInt( &b ); + if ( b ) { + fixwidth = w; + } else { + s = s.stripWhiteSpace(); + if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) + stretch = s.left( s.length()-1).toInt(); + } + } + us_fixwidth = fixwidth; + + place = PlaceInline; + if ( attr["align"] == "left" ) + place = PlaceLeft; + else if ( attr["align"] == "right" ) + place = PlaceRight; + cachewidth = 0; + attributes = attr; + pageBreakFor = -1; +} + +TQTextTable::~TQTextTable() +{ + delete layout; +} + +TQString TQTextTable::richText() const +{ + TQString s; + s = "::ConstIterator it = attributes.begin(); + for ( ; it != attributes.end(); ++it ) + s += it.key() + "=" + *it + " "; + s += ">\n"; + + int lastRow = -1; + bool needEnd = FALSE; + TQPtrListIterator it2( cells ); + while ( it2.current() ) { + TQTextTableCell *cell = it2.current(); + ++it2; + if ( lastRow != cell->row() ) { + if ( lastRow != -1 ) + s += "\n"; + s += ""; + lastRow = cell->row(); + needEnd = TRUE; + } + s += "attributes.begin(); + for ( ; it != cell->attributes.end(); ++it ) + s += " " + it.key() + "=" + *it; + s += ">"; + s += cell->richText()->richText(); + s += ""; + } + if ( needEnd ) + s += "\n"; + s += "
\n"; + return s; +} + +void TQTextTable::setParagraph(TQTextParagraph *p) +{ + for ( TQTextTableCell* cell = cells.first(); cell; cell = cells.next() ) + cell->richText()->parentPar = p; + TQTextCustomItem::setParagraph(p); +} + +void TQTextTable::adjustToPainter( TQPainter* p ) +{ + cellspacing = scale( us_cs, p ); + cellpadding = scale( us_cp, p ); + border = scale( us_b , p ); + innerborder = scale( us_ib, p ); + outerborder = scale( us_ob ,p ); + fixwidth = scale( us_fixwidth, p); + width = 0; + cachewidth = 0; + for ( TQTextTableCell* cell = cells.first(); cell; cell = cells.next() ) + cell->adjustToPainter( p ); +} + +void TQTextTable::adjustCells( int y , int shift ) +{ + TQPtrListIterator it( cells ); + TQTextTableCell* cell; + bool enlarge = FALSE; + while ( ( cell = it.current() ) ) { + ++it; + TQRect r = cell->geometry(); + if ( y <= r.top() ) { + r.moveBy(0, shift ); + cell->setGeometry( r ); + enlarge = TRUE; + } else if ( y <= r.bottom() ) { + r.rBottom() += shift; + cell->setGeometry( r ); + enlarge = TRUE; + } + } + if ( enlarge ) + height += shift; +} + +void TQTextTable::pageBreak( int yt, TQTextFlow* flow ) +{ + if ( flow->pageSize() <= 0 ) + return; + if ( layout && pageBreakFor > 0 && pageBreakFor != yt ) { + layout->invalidate(); + int h = layout->heightForWidth( width-2*outerborder ); + layout->setGeometry( TQRect(0, 0, width-2*outerborder, h) ); + height = layout->geometry().height()+2*outerborder; + } + pageBreakFor = yt; + TQPtrListIterator it( cells ); + TQTextTableCell* cell; + while ( ( cell = it.current() ) ) { + ++it; + int y = yt + outerborder + cell->geometry().y(); + int shift = flow->adjustFlow( y - cellspacing, width, cell->richText()->height() + 2*cellspacing ); + adjustCells( y - outerborder - yt, shift ); + } +} + + +void TQTextTable::draw(TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) +{ + if ( placement() != PlaceInline ) { + x = xpos; + y = ypos; + } + + for (TQTextTableCell* cell = cells.first(); cell; cell = cells.next() ) { + if ( ( cx < 0 && cy < 0 ) || + TQRect( cx, cy, cw, ch ).intersects( TQRect( x + outerborder + cell->geometry().x(), + y + outerborder + cell->geometry().y(), + cell->geometry().width(), cell->geometry().height() ) ) ) { + cell->draw( p, x+outerborder, y+outerborder, cx, cy, cw, ch, cg, selected ); + if ( border ) { + TQRect r( x+outerborder+cell->geometry().x() - innerborder, + y+outerborder+cell->geometry().y() - innerborder, + cell->geometry().width() + 2 * innerborder, + cell->geometry().height() + 2 * innerborder ); + if ( is_printer( p ) ) { + TQPen oldPen = p->pen(); + TQRect r2 = r; + r2.addCoords( innerborder/2, innerborder/2, -innerborder/2, -innerborder/2 ); + p->setPen( TQPen( cg.text(), innerborder ) ); + p->drawRect( r2 ); + p->setPen( oldPen ); + } else { + int s = TQMAX( cellspacing-2*innerborder, 0); + if ( s ) { + p->fillRect( r.left()-s, r.top(), s+1, r.height(), cg.button() ); + p->fillRect( r.right(), r.top(), s+1, r.height(), cg.button() ); + p->fillRect( r.left()-s, r.top()-s, r.width()+2*s, s, cg.button() ); + p->fillRect( r.left()-s, r.bottom(), r.width()+2*s, s, cg.button() ); + } + qDrawShadePanel( p, r, cg, TRUE, innerborder ); + } + } + } + } + if ( border ) { + TQRect r ( x, y, width, height ); + if ( is_printer( p ) ) { + TQRect r2 = r; + r2.addCoords( border/2, border/2, -border/2, -border/2 ); + TQPen oldPen = p->pen(); + p->setPen( TQPen( cg.text(), border ) ); + p->drawRect( r2 ); + p->setPen( oldPen ); + } else { + int s = border+TQMAX( cellspacing-2*innerborder, 0); + if ( s ) { + p->fillRect( r.left(), r.top(), s, r.height(), cg.button() ); + p->fillRect( r.right()-s, r.top(), s, r.height(), cg.button() ); + p->fillRect( r.left(), r.top(), r.width(), s, cg.button() ); + p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() ); + } + qDrawShadePanel( p, r, cg, FALSE, border ); + } + } + +} + +int TQTextTable::minimumWidth() const +{ + return fixwidth ? fixwidth : ((layout ? layout->minimumSize().width() : 0) + 2 * outerborder); +} + +void TQTextTable::resize( int nwidth ) +{ + if ( fixwidth && cachewidth != 0 ) + return; + if ( nwidth == cachewidth ) + return; + + + cachewidth = nwidth; + int w = nwidth; + + format( w ); + + if ( stretch ) + nwidth = nwidth * stretch / 100; + + width = nwidth; + layout->invalidate(); + int shw = layout->sizeHint().width() + 2*outerborder; + int mw = layout->minimumSize().width() + 2*outerborder; + if ( stretch ) + width = TQMAX( mw, nwidth ); + else + width = TQMAX( mw, TQMIN( nwidth, shw ) ); + + if ( fixwidth ) + width = fixwidth; + + layout->invalidate(); + mw = layout->minimumSize().width() + 2*outerborder; + width = TQMAX( width, mw ); + + int h = layout->heightForWidth( width-2*outerborder ); + layout->setGeometry( TQRect(0, 0, width-2*outerborder, h) ); + height = layout->geometry().height()+2*outerborder; +} + +void TQTextTable::format( int w ) +{ + for ( int i = 0; i < (int)cells.count(); ++i ) { + TQTextTableCell *cell = cells.at( i ); + TQRect r = cell->geometry(); + r.setWidth( w - 2*outerborder ); + cell->setGeometry( r ); + } +} + +void TQTextTable::addCell( TQTextTableCell* cell ) +{ + cells.append( cell ); + layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1, + cell->column(), cell->column() + cell->colspan()-1 ); +} + +bool TQTextTable::enter( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd ) +{ + currCell.remove( c ); + if ( !atEnd ) + return next( c, doc, parag, idx, ox, oy ); + currCell.insert( c, cells.count() ); + return prev( c, doc, parag, idx, ox, oy ); +} + +bool TQTextTable::enterAt( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, const TQPoint &pos ) +{ + currCell.remove( c ); + int lastCell = -1; + int lastY = -1; + int i; + for ( i = 0; i < (int)cells.count(); ++i ) { + TQTextTableCell *cell = cells.at( i ); + if ( !cell ) + continue; + TQRect r( cell->geometry().x(), + cell->geometry().y(), + cell->geometry().width() + 2 * innerborder + 2 * outerborder, + cell->geometry().height() + 2 * innerborder + 2 * outerborder ); + + if ( r.left() <= pos.x() && r.right() >= pos.x() ) { + if ( cell->geometry().y() > lastY ) { + lastCell = i; + lastY = cell->geometry().y(); + } + if ( r.top() <= pos.y() && r.bottom() >= pos.y() ) { + currCell.insert( c, i ); + break; + } + } + } + if ( i == (int) cells.count() ) + return FALSE; // no cell found + + if ( currCell.find( c ) == currCell.end() ) { + if ( lastY != -1 ) + currCell.insert( c, lastCell ); + else + return FALSE; + } + + TQTextTableCell *cell = cells.at( *currCell.find( c ) ); + if ( !cell ) + return FALSE; + doc = cell->richText(); + parag = doc->firstParagraph(); + idx = 0; + ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); + oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; + return TRUE; +} + +bool TQTextTable::next( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) +{ + int cc = -1; + if ( currCell.find( c ) != currCell.end() ) + cc = *currCell.find( c ); + if ( cc > (int)cells.count() - 1 || cc < 0 ) + cc = -1; + currCell.remove( c ); + currCell.insert( c, ++cc ); + if ( cc >= (int)cells.count() ) { + currCell.insert( c, 0 ); + TQTextCustomItem::next( c, doc, parag, idx, ox, oy ); + TQTextTableCell *cell = cells.first(); + if ( !cell ) + return FALSE; + doc = cell->richText(); + idx = -1; + return TRUE; + } + + if ( currCell.find( c ) == currCell.end() ) + return FALSE; + TQTextTableCell *cell = cells.at( *currCell.find( c ) ); + if ( !cell ) + return FALSE; + doc = cell->richText(); + parag = doc->firstParagraph(); + idx = 0; + ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); + oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; + return TRUE; +} + +bool TQTextTable::prev( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) +{ + int cc = -1; + if ( currCell.find( c ) != currCell.end() ) + cc = *currCell.find( c ); + if ( cc > (int)cells.count() - 1 || cc < 0 ) + cc = cells.count(); + currCell.remove( c ); + currCell.insert( c, --cc ); + if ( cc < 0 ) { + currCell.insert( c, 0 ); + TQTextCustomItem::prev( c, doc, parag, idx, ox, oy ); + TQTextTableCell *cell = cells.first(); + if ( !cell ) + return FALSE; + doc = cell->richText(); + idx = -1; + return TRUE; + } + + if ( currCell.find( c ) == currCell.end() ) + return FALSE; + TQTextTableCell *cell = cells.at( *currCell.find( c ) ); + if ( !cell ) + return FALSE; + doc = cell->richText(); + parag = doc->lastParagraph(); + idx = parag->length() - 1; + ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); + oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; + return TRUE; +} + +bool TQTextTable::down( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) +{ + if ( currCell.find( c ) == currCell.end() ) + return FALSE; + TQTextTableCell *cell = cells.at( *currCell.find( c ) ); + if ( cell->row_ == layout->numRows() - 1 ) { + currCell.insert( c, 0 ); + TQTextCustomItem::down( c, doc, parag, idx, ox, oy ); + TQTextTableCell *cell = cells.first(); + if ( !cell ) + return FALSE; + doc = cell->richText(); + idx = -1; + return TRUE; + } + + int oldRow = cell->row_; + int oldCol = cell->col_; + if ( currCell.find( c ) == currCell.end() ) + return FALSE; + int cc = *currCell.find( c ); + for ( int i = cc; i < (int)cells.count(); ++i ) { + cell = cells.at( i ); + if ( cell->row_ > oldRow && cell->col_ == oldCol ) { + currCell.insert( c, i ); + break; + } + } + doc = cell->richText(); + if ( !cell ) + return FALSE; + parag = doc->firstParagraph(); + idx = 0; + ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); + oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; + return TRUE; +} + +bool TQTextTable::up( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ) +{ + if ( currCell.find( c ) == currCell.end() ) + return FALSE; + TQTextTableCell *cell = cells.at( *currCell.find( c ) ); + if ( cell->row_ == 0 ) { + currCell.insert( c, 0 ); + TQTextCustomItem::up( c, doc, parag, idx, ox, oy ); + TQTextTableCell *cell = cells.first(); + if ( !cell ) + return FALSE; + doc = cell->richText(); + idx = -1; + return TRUE; + } + + int oldRow = cell->row_; + int oldCol = cell->col_; + if ( currCell.find( c ) == currCell.end() ) + return FALSE; + int cc = *currCell.find( c ); + for ( int i = cc; i >= 0; --i ) { + cell = cells.at( i ); + if ( cell->row_ < oldRow && cell->col_ == oldCol ) { + currCell.insert( c, i ); + break; + } + } + doc = cell->richText(); + if ( !cell ) + return FALSE; + parag = doc->lastParagraph(); + idx = parag->length() - 1; + ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); + oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; + return TRUE; +} + +TQTextTableCell::TQTextTableCell( TQTextTable* table, + int row, int column, + const TQMap &attr, + const TQStyleSheetItem* /*style*/, // ### use them + const TQTextFormat& fmt, const TQString& context, + TQMimeSourceFactory &factory, TQStyleSheet *sheet, + const TQString& doc) +{ + cached_width = -1; + cached_sizehint = -1; + + maxw = TQWIDGETSIZE_MAX; + minw = 0; + + parent = table; + row_ = row; + col_ = column; + stretch_ = 0; + richtext = new TQTextDocument( table->parent ); + richtext->formatCollection()->setPaintDevice( table->parent->formatCollection()->paintDevice() ); + richtext->bodyText = fmt.color(); + richtext->setTableCell( this ); + TQString a = *attr.find( "align" ); + if ( !a.isEmpty() ) { + a = a.lower(); + if ( a == "left" ) + richtext->setAlignment( TQt::AlignLeft ); + else if ( a == "center" ) + richtext->setAlignment( TQt::AlignHCenter ); + else if ( a == "right" ) + richtext->setAlignment( TQt::AlignRight ); + } + align = 0; + TQString va = *attr.find( "valign" ); + if ( !va.isEmpty() ) { + va = va.lower(); + if ( va == "top" ) + align |= TQt::AlignTop; + else if ( va == "center" || va == "middle" ) + align |= TQt::AlignVCenter; + else if ( va == "bottom" ) + align |= TQt::AlignBottom; + } + richtext->setFormatter( table->parent->formatter() ); + richtext->setUseFormatCollection( table->parent->useFormatCollection() ); + richtext->setMimeSourceFactory( &factory ); + richtext->setStyleSheet( sheet ); + richtext->setRichText( doc, context, &fmt ); + rowspan_ = 1; + colspan_ = 1; + if ( attr.contains("colspan") ) + colspan_ = attr["colspan"].toInt(); + if ( attr.contains("rowspan") ) + rowspan_ = attr["rowspan"].toInt(); + + background = 0; + if ( attr.contains("bgcolor") ) { + background = new TQBrush(TQColor( attr["bgcolor"] )); + } + + + hasFixedWidth = FALSE; + if ( attr.contains("width") ) { + bool b; + TQString s( attr["width"] ); + int w = s.toInt( &b ); + if ( b ) { + maxw = w; + minw = maxw; + hasFixedWidth = TRUE; + } else { + s = s.stripWhiteSpace(); + if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) + stretch_ = s.left( s.length()-1).toInt(); + } + } + + attributes = attr; + + parent->addCell( this ); +} + +TQTextTableCell::~TQTextTableCell() +{ + delete background; + background = 0; + delete richtext; + richtext = 0; +} + +TQSize TQTextTableCell::sizeHint() const +{ + int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); + int used = richtext->widthUsed() + extra; + + if (stretch_ ) { + int w = parent->width * stretch_ / 100 - 2*parent->cellspacing - 2*parent->cellpadding; + return TQSize( TQMIN( w, maxw ), 0 ).expandedTo( minimumSize() ); + } + + return TQSize( used, 0 ).expandedTo( minimumSize() ); +} + +TQSize TQTextTableCell::minimumSize() const +{ + int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); + return TQSize( TQMAX( richtext->minimumWidth() + extra, minw), 0 ); +} + +TQSize TQTextTableCell::maximumSize() const +{ + return TQSize( maxw, TQWIDGETSIZE_MAX ); +} + +TQSizePolicy::ExpandData TQTextTableCell::expanding() const +{ + return TQSizePolicy::BothDirections; +} + +bool TQTextTableCell::isEmpty() const +{ + return FALSE; +} +void TQTextTableCell::setGeometry( const TQRect& r ) +{ + int extra = 2 * ( parent->innerborder + parent->cellpadding ); + if ( r.width() != cached_width ) + richtext->doLayout( TQTextFormat::painter(), r.width() - extra ); + cached_width = r.width(); + geom = r; +} + +TQRect TQTextTableCell::geometry() const +{ + return geom; +} + +bool TQTextTableCell::hasHeightForWidth() const +{ + return TRUE; +} + +int TQTextTableCell::heightForWidth( int w ) const +{ + int extra = 2 * ( parent->innerborder + parent->cellpadding ); + w = TQMAX( minw, w ); + + if ( cached_width != w ) { + TQTextTableCell* that = (TQTextTableCell*) this; + that->richtext->doLayout( TQTextFormat::painter(), w - extra ); + that->cached_width = w; + } + return richtext->height() + extra; +} + +void TQTextTableCell::adjustToPainter( TQPainter* p ) +{ + TQTextParagraph *parag = richtext->firstParagraph(); + while ( parag ) { + parag->adjustToPainter( p ); + parag = parag->next(); + } +} + +int TQTextTableCell::horizontalAlignmentOffset() const +{ + return parent->cellpadding; +} + +int TQTextTableCell::verticalAlignmentOffset() const +{ + if ( (align & TQt::AlignVCenter ) == TQt::AlignVCenter ) + return ( geom.height() - richtext->height() ) / 2; + else if ( ( align & TQt::AlignBottom ) == TQt::AlignBottom ) + return geom.height() - parent->cellpadding - richtext->height() ; + return parent->cellpadding; +} + +void TQTextTableCell::draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool ) +{ + if ( cached_width != geom.width() ) { + int extra = 2 * ( parent->innerborder + parent->cellpadding ); + richtext->doLayout( p, geom.width() - extra ); + cached_width = geom.width(); + } + TQColorGroup g( cg ); + if ( background ) + g.setBrush( TQColorGroup::Base, *background ); + else if ( richtext->paper() ) + g.setBrush( TQColorGroup::Base, *richtext->paper() ); + + p->save(); + p->translate( x + geom.x(), y + geom.y() ); + if ( background ) + p->fillRect( 0, 0, geom.width(), geom.height(), *background ); + else if ( richtext->paper() ) + p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() ); + + p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() ); + + TQRegion r; + if ( cx >= 0 && cy >= 0 ) + richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ), + cy - ( y + geom.y() + verticalAlignmentOffset() ), + cw, ch, g, FALSE, FALSE, 0 ); + else + richtext->draw( p, -1, -1, -1, -1, g, FALSE, FALSE, 0 ); + + p->restore(); +} +#endif + +#endif //TQT_NO_RICHTEXT diff --git a/src/kernel/tqrichtext_p.cpp b/src/kernel/tqrichtext_p.cpp new file mode 100644 index 000000000..e9417d2a9 --- /dev/null +++ b/src/kernel/tqrichtext_p.cpp @@ -0,0 +1,655 @@ +/**************************************************************************** +** +** Implementation of the internal TQt classes dealing with rich text +** +** Created : 990101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqrichtext_p.h" + +#ifndef TQT_NO_RICHTEXT + +TQTextCommand::~TQTextCommand() {} +TQTextCommand::Commands TQTextCommand::type() const { return Invalid; } + + +#ifndef TQT_NO_TEXTCUSTOMITEM +TQTextCustomItem::~TQTextCustomItem() {} +void TQTextCustomItem::adjustToPainter( TQPainter* p){ if ( p ) width = 0; } +TQTextCustomItem::Placement TQTextCustomItem::placement() const { return PlaceInline; } + +bool TQTextCustomItem::ownLine() const { return FALSE; } +void TQTextCustomItem::resize( int nwidth ){ width = nwidth; } +void TQTextCustomItem::invalidate() {} + +bool TQTextCustomItem::isNested() const { return FALSE; } +int TQTextCustomItem::minimumWidth() const { return 0; } + +TQString TQTextCustomItem::richText() const { return TQString::null; } + +bool TQTextCustomItem::enter( TQTextCursor *, TQTextDocument*&, TQTextParagraph *&, int &, int &, int &, bool ) +{ + return TRUE; +} +bool TQTextCustomItem::enterAt( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int &, const TQPoint & ) +{ + return TRUE; +} +bool TQTextCustomItem::next( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) +{ + return TRUE; +} +bool TQTextCustomItem::prev( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) +{ + return TRUE; +} +bool TQTextCustomItem::down( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) +{ + return TRUE; +} +bool TQTextCustomItem::up( TQTextCursor *, TQTextDocument *&, TQTextParagraph *&, int &, int &, int & ) +{ + return TRUE; +} +#endif // TQT_NO_TEXTCUSTOMITEM + +void TQTextFlow::setPageSize( int ps ) { pagesize = ps; } +#ifndef TQT_NO_TEXTCUSTOMITEM +bool TQTextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); } +#else +bool TQTextFlow::isEmpty() { return TRUE; } +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM +void TQTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; } + +void TQTextTable::invalidate() { cachewidth = -1; } +#endif + +TQTextParagraphData::~TQTextParagraphData() {} +void TQTextParagraphData::join( TQTextParagraphData * ) {} + +TQTextFormatter::~TQTextFormatter() {} +void TQTextFormatter::setWrapEnabled( bool b ) { wrapEnabled = b; } +void TQTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; } + + + +int TQTextCursor::x() const +{ + if ( idx >= para->length() ) + return 0; + TQTextStringChar *c = para->at( idx ); + int curx = c->x; + if ( !c->rightToLeft && + c->c.isSpace() && + idx > 0 && + para->at( idx - 1 )->c != '\t' && + !c->lineStart && + ( para->alignment() & TQt::AlignJustify ) == TQt::AlignJustify ) + curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 ); + if ( c->rightToLeft ) + curx += para->string()->width( idx ); + return curx; +} + +int TQTextCursor::y() const +{ + int dummy, line; + para->lineStartOfChar( idx, &dummy, &line ); + return para->lineY( line ); +} + +int TQTextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); } +int TQTextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); } + +TQTextDocument *TQTextCursor::document() const +{ + return para ? para->document() : 0; +} + +void TQTextCursor::gotoPosition( TQTextParagraph* p, int index ) +{ + if ( para && p != para ) { + while ( !indices.isEmpty() && para->document() != p->document() ) + pop(); + Q_ASSERT( indices.isEmpty() || para->document() == p->document() ); + } + para = p; + if ( index < 0 || index >= para->length() ) { +#if defined(QT_CHECK_RANGE) + tqWarning( "TQTextCursor::gotoParagraph Index: %d out of range", index ); +#endif + if ( index < 0 || para->length() == 0 ) + index = 0; + else + index = para->length() - 1; + } + + tmpX = -1; + idx = index; + fixCursorPosition(); +} + +bool TQTextDocument::hasSelection( int id, bool visible ) const +{ + return ( selections.find( id ) != selections.end() && + ( !visible || + ( (TQTextDocument*)this )->selectionStartCursor( id ) != + ( (TQTextDocument*)this )->selectionEndCursor( id ) ) ); +} + +void TQTextDocument::setSelectionStart( int id, const TQTextCursor &cursor ) +{ + TQTextDocumentSelection sel; + sel.startCursor = cursor; + sel.endCursor = cursor; + sel.swapped = FALSE; + selections[ id ] = sel; +} + +TQTextParagraph *TQTextDocument::paragAt( int i ) const +{ + TQTextParagraph* p = curParag; + if ( !p || p->paragId() > i ) + p = fParag; + while ( p && p->paragId() != i ) + p = p->next(); + ((TQTextDocument*)this)->curParag = p; + return p; +} + + +TQTextFormat::~TQTextFormat() +{ +} + +TQTextFormat::TQTextFormat() + : fm( TQFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( tqApp->font().pointSize() ) +{ + ref = 0; + + usePixelSizes = FALSE; + if ( stdSize == -1 ) { + stdSize = tqApp->font().pixelSize(); + usePixelSizes = TRUE; + } + + missp = FALSE; + ha = AlignNormal; + collection = 0; +} + +TQTextFormat::TQTextFormat( const TQStyleSheetItem *style ) + : fm( TQFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( tqApp->font().pointSize() ) +{ + ref = 0; + + usePixelSizes = FALSE; + if ( stdSize == -1 ) { + stdSize = tqApp->font().pixelSize(); + usePixelSizes = TRUE; + } + + missp = FALSE; + ha = AlignNormal; + collection = 0; + fn = TQFont( style->fontFamily(), + style->fontSize(), + style->fontWeight(), + style->fontItalic() ); + fn.setUnderline( style->fontUnderline() ); + fn.setStrikeOut( style->fontStrikeOut() ); + col = style->color(); + fm = TQFontMetrics( fn ); + leftBearing = fm.minLeftBearing(); + rightBearing = fm.minRightBearing(); + hei = fm.lineSpacing(); + asc = fm.ascent() + (fm.leading()+1)/2; + dsc = fm.descent(); + missp = FALSE; + ha = AlignNormal; + memset( widths, 0, 256 ); + generateKey(); + addRef(); +} + +TQTextFormat::TQTextFormat( const TQFont &f, const TQColor &c, TQTextFormatCollection *parent ) + : fn( f ), col( c ), fm( TQFontMetrics( f ) ), linkColor( TRUE ), + logicalFontSize( 3 ), stdSize( f.pointSize() ) +{ + ref = 0; + usePixelSizes = FALSE; + if ( stdSize == -1 ) { + stdSize = f.pixelSize(); + usePixelSizes = TRUE; + } + collection = parent; + leftBearing = fm.minLeftBearing(); + rightBearing = fm.minRightBearing(); + hei = fm.lineSpacing(); + asc = fm.ascent() + (fm.leading()+1)/2; + dsc = fm.descent(); + missp = FALSE; + ha = AlignNormal; + memset( widths, 0, 256 ); + generateKey(); + addRef(); +} + +TQTextFormat::TQTextFormat( const TQTextFormat &f ) + : fm( f.fm ) +{ + ref = 0; + collection = 0; + fn = f.fn; + col = f.col; + leftBearing = f.leftBearing; + rightBearing = f.rightBearing; + memset( widths, 0, 256 ); + hei = f.hei; + asc = f.asc; + dsc = f.dsc; + stdSize = f.stdSize; + usePixelSizes = f.usePixelSizes; + logicalFontSize = f.logicalFontSize; + missp = f.missp; + ha = f.ha; + k = f.k; + linkColor = f.linkColor; + addRef(); +} + +TQTextFormat& TQTextFormat::operator=( const TQTextFormat &f ) +{ + ref = 0; + collection = f.collection; + fn = f.fn; + col = f.col; + fm = f.fm; + leftBearing = f.leftBearing; + rightBearing = f.rightBearing; + memset( widths, 0, 256 ); + hei = f.hei; + asc = f.asc; + dsc = f.dsc; + stdSize = f.stdSize; + usePixelSizes = f.usePixelSizes; + logicalFontSize = f.logicalFontSize; + missp = f.missp; + ha = f.ha; + k = f.k; + linkColor = f.linkColor; + addRef(); + return *this; +} + +void TQTextFormat::update() +{ + fm = TQFontMetrics( fn ); + leftBearing = fm.minLeftBearing(); + rightBearing = fm.minRightBearing(); + hei = fm.lineSpacing(); + asc = fm.ascent() + (fm.leading()+1)/2; + dsc = fm.descent(); + memset( widths, 0, 256 ); + generateKey(); +} + + +TQPainter* TQTextFormat::pntr = 0; +TQFontMetrics* TQTextFormat::pntr_fm = 0; +int TQTextFormat::pntr_ldg=-1; +int TQTextFormat::pntr_asc=-1; +int TQTextFormat::pntr_hei=-1; +int TQTextFormat::pntr_dsc=-1; + +void TQTextFormat::cleanupPrivateData() { + delete TQTextFormat::pntr_fm; + TQTextFormat::pntr_fm = 0; + TQTextFormat::pntr = 0; + + // Not really necessary, but better to tidy-up everything + TQTextFormat::pntr_fm = 0; + TQTextFormat::pntr_ldg=-1; + TQTextFormat::pntr_asc=-1; + TQTextFormat::pntr_hei=-1; + TQTextFormat::pntr_dsc=-1; +} + +void TQTextFormat::setPainter( TQPainter *p ) +{ + pntr = p; +} + +TQPainter* TQTextFormat::painter() +{ + return pntr; +} + +void TQTextFormat::applyFont( const TQFont &f ) +{ + TQFontMetrics fm( pntr->fontMetrics() ); + + if ( !pntr_fm ) { + tqAddPostRoutine( &TQTextFormat::cleanupPrivateData ); + } + + if ( !pntr_fm + || pntr_fm->painter != pntr + || pntr_fm->d != fm.d + || !pntr->font().isCopyOf( f ) + ) { + pntr->setFont( f ); + delete pntr_fm; + pntr_fm = new TQFontMetrics( pntr->fontMetrics() ); + pntr_ldg = pntr_fm->leading(); + pntr_asc = pntr_fm->ascent()+(pntr_ldg+1)/2; + pntr_hei = pntr_fm->lineSpacing(); + pntr_dsc = -1; + } +} + +int TQTextFormat::minLeftBearing() const +{ + if ( !pntr || !pntr->isActive() ) + return leftBearing; + applyFont( fn ); + return pntr_fm->minLeftBearing(); +} + +int TQTextFormat::minRightBearing() const +{ + if ( !pntr || !pntr->isActive() ) + return rightBearing; + applyFont( fn ); + return pntr_fm->minRightBearing(); +} + +int TQTextFormat::height() const +{ + if ( !pntr || !pntr->isActive() ) + return hei; + applyFont( fn ); + return pntr_hei; +} + +int TQTextFormat::ascent() const +{ + if ( !pntr || !pntr->isActive() ) + return asc; + applyFont( fn ); + return pntr_asc; +} + +int TQTextFormat::descent() const +{ + if ( !pntr || !pntr->isActive() ) + return dsc; + applyFont( fn ); + if ( pntr_dsc < 0 ) + pntr_dsc = pntr_fm->descent(); + return pntr_dsc; +} + +int TQTextFormat::leading() const +{ + if ( !pntr || !pntr->isActive() ) + return fm.leading(); + applyFont( fn ); + return pntr_ldg; +} + +void TQTextFormat::generateKey() +{ + k = getKey( fn, col, isMisspelled(), vAlign() ); +} + +TQString TQTextFormat::getKey( const TQFont &fn, const TQColor &col, bool misspelled, VerticalAlignment a ) +{ + TQString k = fn.key(); + k += '/'; + k += TQString::number( (uint)col.rgb() ); + k += '/'; + k += TQString::number( (int)misspelled ); + k += '/'; + k += TQString::number( (int)a ); + return k; +} + +TQString TQTextString::toString( const TQMemArray &data ) +{ + TQString s; + int l = data.size(); + s.setUnicode( 0, l ); + TQTextStringChar *c = data.data(); + TQChar *uc = (TQChar *)s.unicode(); + while ( l-- ) + *(uc++) = (c++)->c; + + return s; +} + +void TQTextParagraph::setSelection( int id, int start, int end ) +{ + TQMap::ConstIterator it = selections().find( id ); + if ( it != mSelections->end() ) { + if ( start == ( *it ).start && end == ( *it ).end ) + return; + } + + TQTextParagraphSelection sel; + sel.start = start; + sel.end = end; + (*mSelections)[ id ] = sel; + setChanged( TRUE, TRUE ); +} + +void TQTextParagraph::removeSelection( int id ) +{ + if ( !hasSelection( id ) ) + return; + if ( mSelections ) + mSelections->remove( id ); + setChanged( TRUE, TRUE ); +} + +int TQTextParagraph::selectionStart( int id ) const +{ + if ( !mSelections ) + return -1; + TQMap::ConstIterator it = mSelections->find( id ); + if ( it == mSelections->end() ) + return -1; + return ( *it ).start; +} + +int TQTextParagraph::selectionEnd( int id ) const +{ + if ( !mSelections ) + return -1; + TQMap::ConstIterator it = mSelections->find( id ); + if ( it == mSelections->end() ) + return -1; + return ( *it ).end; +} + +bool TQTextParagraph::hasSelection( int id ) const +{ + return mSelections ? mSelections->contains( id ) : FALSE; +} + +bool TQTextParagraph::fullSelected( int id ) const +{ + if ( !mSelections ) + return FALSE; + TQMap::ConstIterator it = mSelections->find( id ); + if ( it == mSelections->end() ) + return FALSE; + return ( *it ).start == 0 && ( *it ).end == str->length() - 1; +} + +int TQTextParagraph::lineY( int l ) const +{ + if ( l > (int)lineStarts.count() - 1 ) { + tqWarning( "TQTextParagraph::lineY: line %d out of range!", l ); + return 0; + } + + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + TQMap::ConstIterator it = lineStarts.begin(); + while ( l-- > 0 ) + ++it; + return ( *it )->y; +} + +int TQTextParagraph::lineBaseLine( int l ) const +{ + if ( l > (int)lineStarts.count() - 1 ) { + tqWarning( "TQTextParagraph::lineBaseLine: line %d out of range!", l ); + return 10; + } + + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + TQMap::ConstIterator it = lineStarts.begin(); + while ( l-- > 0 ) + ++it; + return ( *it )->baseLine; +} + +int TQTextParagraph::lineHeight( int l ) const +{ + if ( l > (int)lineStarts.count() - 1 ) { + tqWarning( "TQTextParagraph::lineHeight: line %d out of range!", l ); + return 15; + } + + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + TQMap::ConstIterator it = lineStarts.begin(); + while ( l-- > 0 ) + ++it; + return ( *it )->h; +} + +void TQTextParagraph::lineInfo( int l, int &y, int &h, int &bl ) const +{ + if ( l > (int)lineStarts.count() - 1 ) { + tqWarning( "TQTextParagraph::lineInfo: line %d out of range!", l ); + tqDebug( "%d %d", (int)lineStarts.count() - 1, l ); + y = 0; + h = 15; + bl = 10; + return; + } + + if ( !isValid() ) + ( (TQTextParagraph*)this )->format(); + + TQMap::ConstIterator it = lineStarts.begin(); + while ( l-- > 0 ) + ++it; + y = ( *it )->y; + h = ( *it )->h; + bl = ( *it )->baseLine; +} + + +void TQTextParagraph::setAlignment( int a ) +{ + if ( a == (int)align ) + return; + align = a; + invalidate( 0 ); +} + +TQTextFormatter *TQTextParagraph::formatter() const +{ + if ( hasdoc ) + return document()->formatter(); + if ( pseudoDocument()->pFormatter ) + return pseudoDocument()->pFormatter; + return ( ( (TQTextParagraph*)this )->pseudoDocument()->pFormatter = new TQTextFormatterBreakWords ); +} + +void TQTextParagraph::setTabArray( int *a ) +{ + delete [] tArray; + tArray = a; +} + +void TQTextParagraph::setTabStops( int tw ) +{ + if ( hasdoc ) + document()->setTabStops( tw ); + else + tabStopWidth = tw; +} + +TQMap &TQTextParagraph::selections() const +{ + if ( !mSelections ) + ((TQTextParagraph *)this)->mSelections = new TQMap; + return *mSelections; +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +TQPtrList &TQTextParagraph::floatingItems() const +{ + if ( !mFloatingItems ) + ((TQTextParagraph *)this)->mFloatingItems = new TQPtrList; + return *mFloatingItems; +} +#endif + +TQTextStringChar::~TQTextStringChar() +{ + if ( format() ) + format()->removeRef(); + if ( type ) // not Regular + delete d.custom; +} + +TQTextParagraphPseudoDocument::TQTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0),collection(){} +TQTextParagraphPseudoDocument::~TQTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; } + + +#endif //TQT_NO_RICHTEXT diff --git a/src/kernel/tqrichtext_p.h b/src/kernel/tqrichtext_p.h new file mode 100644 index 000000000..1032c74eb --- /dev/null +++ b/src/kernel/tqrichtext_p.h @@ -0,0 +1,2142 @@ +/**************************************************************************** +** +** Definition of internal rich text classes +** +** Created : 990124 +** +** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQRICHTEXT_P_H +#define TQRICHTEXT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of a number of TQt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqstring.h" +#include "tqptrlist.h" +#include "tqrect.h" +#include "tqfontmetrics.h" +#include "tqintdict.h" +#include "tqmap.h" +#include "tqstringlist.h" +#include "tqfont.h" +#include "tqcolor.h" +#include "tqsize.h" +#include "tqvaluelist.h" +#include "tqvaluestack.h" +#include "tqobject.h" +#include "tqdict.h" +#include "tqpixmap.h" +#include "tqstylesheet.h" +#include "tqptrvector.h" +#include "tqpainter.h" +#include "tqlayout.h" +#include "tqobject.h" +#include "ntqapplication.h" +#endif // QT_H + +#ifndef TQT_NO_RICHTEXT + +class TQTextDocument; +class TQTextString; +class TQTextPreProcessor; +class TQTextFormat; +class TQTextCursor; +class TQTextParagraph; +class TQTextFormatter; +class TQTextIndent; +class TQTextFormatCollection; +class TQStyleSheetItem; +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQTextCustomItem; +#endif +class TQTextFlow; +struct TQBidiContext; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextStringChar +{ + friend class TQTextString; + +public: + // this is never called, initialize variables in TQTextString::insert()!!! + TQTextStringChar() : nobreak(FALSE), lineStart( 0 ), type( Regular ) {d.format=0;} + ~TQTextStringChar(); + + struct CustomData + { + TQTextFormat *format; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextCustomItem *custom; +#endif + TQString anchorName; + TQString anchorHref; + }; + enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 }; + + TQChar c; + // this is the same struct as in tqtextengine_p.h. Don't change! + uchar softBreak :1; // Potential linebreak point + uchar whiteSpace :1; // A unicode whitespace character, except NBSP, ZWNBSP + uchar charStop :1; // Valid cursor position (for left/right arrow) + uchar wordStop :1; // Valid cursor position (for ctrl + left/right arrow) + uchar nobreak :1; + + uchar lineStart : 1; + uchar /*Type*/ type : 2; + uchar bidiLevel :7; + uchar rightToLeft : 1; + + int x; + union { + TQTextFormat* format; + CustomData* custom; + } d; + + + int height() const; + int ascent() const; + int descent() const; + bool isCustom() const { return (type & Custom) != 0; } + TQTextFormat *format() const; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextCustomItem *customItem() const; +#endif + void setFormat( TQTextFormat *f ); +#ifndef TQT_NO_TEXTCUSTOMITEM + void setCustomItem( TQTextCustomItem *i ); +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM + void loseCustomItem(); +#endif + + + bool isAnchor() const { return ( type & Anchor) != 0; } + bool isLink() const { return isAnchor() && !!d.custom->anchorHref; } + TQString anchorName() const; + TQString anchorHref() const; + void setAnchor( const TQString& name, const TQString& href ); + +private: + TQTextStringChar &operator=( const TQTextStringChar & ) { + //abort(); + return *this; + } + TQTextStringChar( const TQTextStringChar & ) { + } + friend class TQTextParagraph; +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMemArray; +// MOC_SKIP_END +#endif + +class TQ_EXPORT TQTextString +{ +public: + + TQTextString(); + TQTextString( const TQTextString &s ); + virtual ~TQTextString(); + + static TQString toString( const TQMemArray &data ); + TQString toString() const; + + inline TQTextStringChar &at( int i ) const { return data[ i ]; } + inline int length() const { return data.size(); } + + int width( int idx ) const; + + void insert( int index, const TQString &s, TQTextFormat *f ); + void insert( int index, const TQChar *unicode, int len, TQTextFormat *f ); + void insert( int index, TQTextStringChar *c, bool doAddRefFormat = FALSE ); + void truncate( int index ); + void remove( int index, int len ); + void clear(); + + void setFormat( int index, TQTextFormat *f, bool useCollection ); + + void setBidi( bool b ) { bidi = b; } + bool isBidi() const; + bool isRightToLeft() const; + TQChar::Direction direction() const; + void setDirection( TQChar::Direction d ) { dir = d; bidiDirty = TRUE; } + + TQMemArray rawData() const { return data.copy(); } + + void operator=( const TQString &s ) { clear(); insert( 0, s, 0 ); } + void operator+=( const TQString &s ) { insert( length(), s, 0 ); } + void prepend( const TQString &s ) { insert( 0, s, 0 ); } + int appendParagraphs( TQTextParagraph *start, TQTextParagraph *end ); + + // return next and previous valid cursor positions. + bool validCursorPosition( int idx ); + int nextCursorPosition( int idx ); + int previousCursorPosition( int idx ); + +private: + void checkBidi() const; + + TQMemArray data; + TQString stringCache; + uint bidiDirty : 1; + uint bidi : 1; // true when the paragraph has right to left characters + uint rightToLeft : 1; + uint dir : 5; +}; + +inline bool TQTextString::isBidi() const +{ + if ( bidiDirty ) + checkBidi(); + return bidi; +} + +inline bool TQTextString::isRightToLeft() const +{ + if ( bidiDirty ) + checkBidi(); + return rightToLeft; +} + +inline TQString TQTextString::toString() const +{ + if(bidiDirty) + checkBidi(); + return stringCache; +} + +inline TQChar::Direction TQTextString::direction() const +{ + return (TQChar::Direction) dir; +} + +inline int TQTextString::nextCursorPosition( int next ) +{ + if ( bidiDirty ) + checkBidi(); + + const TQTextStringChar *c = data.data(); + int len = length(); + + if ( next < len - 1 ) { + next++; + while ( next < len - 1 && !c[next].charStop ) + next++; + } + return next; +} + +inline int TQTextString::previousCursorPosition( int prev ) +{ + if ( bidiDirty ) + checkBidi(); + + const TQTextStringChar *c = data.data(); + + if ( prev ) { + prev--; + while ( prev && !c[prev].charStop ) + prev--; + } + return prev; +} + +inline bool TQTextString::validCursorPosition( int idx ) +{ + if ( bidiDirty ) + checkBidi(); + + return (at( idx ).charStop); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueStack; +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueStack; +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQValueStack; +// MOC_SKIP_END +#endif + +class TQ_EXPORT TQTextCursor +{ +public: + TQTextCursor( TQTextDocument *d = 0 ); + TQTextCursor( const TQTextCursor &c ); + TQTextCursor &operator=( const TQTextCursor &c ); + virtual ~TQTextCursor() {} + + bool operator==( const TQTextCursor &c ) const; + bool operator!=( const TQTextCursor &c ) const { return !(*this == c); } + + inline TQTextParagraph *paragraph() const { return para; } + + TQTextDocument *document() const; + int index() const; + + void gotoPosition( TQTextParagraph* p, int index = 0); + void setIndex( int index ) { gotoPosition(paragraph(), index ); } + void setParagraph( TQTextParagraph*p ) { gotoPosition(p, 0 ); } + + void gotoLeft(); + void gotoRight(); + void gotoNextLetter(); + void gotoPreviousLetter(); + void gotoUp(); + void gotoDown(); + void gotoLineEnd(); + void gotoLineStart(); + void gotoHome(); + void gotoEnd(); + void gotoPageUp( int visibleHeight ); + void gotoPageDown( int visibleHeight ); + void gotoNextWord( bool onlySpace = FALSE ); + void gotoPreviousWord( bool onlySpace = FALSE ); + void gotoWordLeft(); + void gotoWordRight(); + + void insert( const TQString &s, bool checkNewLine, TQMemArray *formatting = 0 ); + void splitAndInsertEmptyParagraph( bool ind = TRUE, bool updateIds = TRUE ); + bool remove(); + bool removePreviousChar(); + void indent(); + + bool atParagStart(); + bool atParagEnd(); + + int x() const; // x in current paragraph + int y() const; // y in current paragraph + + int globalX() const; + int globalY() const; + + TQTextParagraph *topParagraph() const { return paras.isEmpty() ? para : paras.first(); } + int offsetX() const { return ox; } // inner document offset + int offsetY() const { return oy; } // inner document offset + int totalOffsetX() const; // total document offset + int totalOffsetY() const; // total document offset + + bool place( const TQPoint &pos, TQTextParagraph *s ) { return place( pos, s, FALSE ); } + bool place( const TQPoint &pos, TQTextParagraph *s, bool link ) { return place( pos, s, link, TRUE, TRUE ); } + bool place( const TQPoint &pos, TQTextParagraph *s, bool link, bool loosePlacing, bool matchBetweenCharacters ); + void restoreState(); + + + int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast + void oneUp() { if ( !indices.isEmpty() ) pop(); } + void setValid( bool b ) { valid = b; } + bool isValid() const { return valid; } + + void fixCursorPosition(); +private: + enum Operation { EnterBegin, EnterEnd, Next, Prev, Up, Down }; + + void push(); + void pop(); + bool processNesting( Operation op ); + void invalidateNested(); + void gotoIntoNested( const TQPoint &globalPos ); + + TQTextParagraph *para; + int idx, tmpX; + int ox, oy; + TQValueStack indices; + TQValueStack paras; + TQValueStack xOffsets; + TQValueStack yOffsets; + uint valid : 1; + +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextCommand +{ +public: + enum Commands { Invalid, Insert, Delete, Format, Style }; + + TQTextCommand( TQTextDocument *d ) : doc( d ), cursor( d ) {} + virtual ~TQTextCommand(); + + virtual Commands type() const; + + virtual TQTextCursor *execute( TQTextCursor *c ) = 0; + virtual TQTextCursor *unexecute( TQTextCursor *c ) = 0; + +protected: + TQTextDocument *doc; + TQTextCursor cursor; + +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; +// MOC_SKIP_END +#endif + +class TQ_EXPORT TQTextCommandHistory +{ +public: + TQTextCommandHistory( int s ) : current( -1 ), steps( s ) { history.setAutoDelete( TRUE ); } + virtual ~TQTextCommandHistory(); + + void clear() { history.clear(); current = -1; } + + void addCommand( TQTextCommand *cmd ); + TQTextCursor *undo( TQTextCursor *c ); + TQTextCursor *redo( TQTextCursor *c ); + + bool isUndoAvailable(); + bool isRedoAvailable(); + + void setUndoDepth( int d ) { steps = d; } + int undoDepth() const { return steps; } + + int historySize() const { return history.count(); } + int currentPosition() const { return current; } + +private: + TQPtrList history; + int current, steps; + +}; + +inline TQTextCommandHistory::~TQTextCommandHistory() +{ + clear(); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQ_EXPORT TQTextCustomItem +{ +public: + TQTextCustomItem( TQTextDocument *p ) + : xpos(0), ypos(-1), width(-1), height(0), parent( p ) + {} + virtual ~TQTextCustomItem(); + virtual void draw(TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ) = 0; + + virtual void adjustToPainter( TQPainter* ); + + enum Placement { PlaceInline = 0, PlaceLeft, PlaceRight }; + virtual Placement placement() const; + bool placeInline() { return placement() == PlaceInline; } + + virtual bool ownLine() const; + virtual void resize( int nwidth ); + virtual void invalidate(); + virtual int ascent() const { return height; } + + virtual bool isNested() const; + virtual int minimumWidth() const; + + virtual TQString richText() const; + + int xpos; // used for floating items + int ypos; // used for floating items + int width; + int height; + + TQRect geometry() const { return TQRect( xpos, ypos, width, height ); } + + virtual bool enter( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); + virtual bool enterAt( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, const TQPoint & ); + virtual bool next( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool prev( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool down( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool up( TQTextCursor *, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + + virtual void setParagraph( TQTextParagraph *p ) { parag = p; } + TQTextParagraph *paragraph() const { return parag; } + + TQTextDocument *parent; + TQTextParagraph *parag; + + virtual void pageBreak( int y, TQTextFlow* flow ); +}; +#endif + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +//Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +// MOC_SKIP_END +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQ_EXPORT TQTextImage : public TQTextCustomItem +{ +public: + TQTextImage( TQTextDocument *p, const TQMap &attr, const TQString& context, + TQMimeSourceFactory &factory ); + virtual ~TQTextImage(); + + Placement placement() const { return place; } + void adjustToPainter( TQPainter* ); + int minimumWidth() const { return width; } + + TQString richText() const; + + void draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); + +private: + TQRegion* reg; + TQPixmap pm; + Placement place; + int tmpwidth, tmpheight; + TQMap attributes; + TQString imgId; + +}; +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQ_EXPORT TQTextHorizontalLine : public TQTextCustomItem +{ +public: + TQTextHorizontalLine( TQTextDocument *p, const TQMap &attr, const TQString& context, + TQMimeSourceFactory &factory ); + virtual ~TQTextHorizontalLine(); + + void adjustToPainter( TQPainter* ); + void draw(TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); + TQString richText() const; + + bool ownLine() const { return TRUE; } + +private: + int tmpheight; + TQColor color; + bool shade; + +}; +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; +// MOC_SKIP_END +#endif +#endif + +class TQ_EXPORT TQTextFlow +{ + friend class TQTextDocument; +#ifndef TQT_NO_TEXTCUSTOMITEM + friend class TQTextTableCell; +#endif + +public: + TQTextFlow(); + virtual ~TQTextFlow(); + + virtual void setWidth( int width ); + int width() const; + + virtual void setPageSize( int ps ); + int pageSize() const { return pagesize; } + + virtual int adjustLMargin( int yp, int h, int margin, int space ); + virtual int adjustRMargin( int yp, int h, int margin, int space ); + +#ifndef TQT_NO_TEXTCUSTOMITEM + virtual void registerFloatingItem( TQTextCustomItem* item ); + virtual void unregisterFloatingItem( TQTextCustomItem* item ); +#endif + virtual TQRect boundingRect() const; + virtual void drawFloatingItems(TQPainter* p, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); + + virtual int adjustFlow( int y, int w, int h ); // adjusts y according to the defined pagesize. Returns the shift. + + virtual bool isEmpty(); + + void clear(); + +private: + int w; + int pagesize; + +#ifndef TQT_NO_TEXTCUSTOMITEM + TQPtrList leftItems; + TQPtrList rightItems; +#endif +}; + +inline int TQTextFlow::width() const { return w; } + +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQTextTable; + +class TQ_EXPORT TQTextTableCell : public TQLayoutItem +{ + friend class TQTextTable; + +public: + TQTextTableCell( TQTextTable* table, + int row, int column, + const TQMap &attr, + const TQStyleSheetItem* style, + const TQTextFormat& fmt, const TQString& context, + TQMimeSourceFactory &factory, TQStyleSheet *sheet, const TQString& doc ); + virtual ~TQTextTableCell(); + + TQSize sizeHint() const ; + TQSize minimumSize() const ; + TQSize maximumSize() const ; + TQSizePolicy::ExpandData expanding() const; + bool isEmpty() const; + void setGeometry( const TQRect& ) ; + TQRect geometry() const; + + bool hasHeightForWidth() const; + int heightForWidth( int ) const; + + void adjustToPainter( TQPainter* ); + + int row() const { return row_; } + int column() const { return col_; } + int rowspan() const { return rowspan_; } + int colspan() const { return colspan_; } + int stretch() const { return stretch_; } + + TQTextDocument* richText() const { return richtext; } + TQTextTable* table() const { return parent; } + + void draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected ); + + TQBrush *backGround() const { return background; } + virtual void invalidate(); + + int verticalAlignmentOffset() const; + int horizontalAlignmentOffset() const; + +private: + TQRect geom; + TQTextTable* parent; + TQTextDocument* richtext; + int row_; + int col_; + int rowspan_; + int colspan_; + int stretch_; + int maxw; + int minw; + bool hasFixedWidth; + TQBrush *background; + int cached_width; + int cached_sizehint; + TQMap attributes; + int align; +}; +#endif + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +// MOC_SKIP_END +#endif + +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQ_EXPORT TQTextTable: public TQTextCustomItem +{ + friend class TQTextTableCell; + +public: + TQTextTable( TQTextDocument *p, const TQMap &attr ); + virtual ~TQTextTable(); + + void adjustToPainter( TQPainter *p ); + void pageBreak( int y, TQTextFlow* flow ); + void draw( TQPainter* p, int x, int y, int cx, int cy, int cw, int ch, + const TQColorGroup& cg, bool selected ); + + bool noErase() const { return TRUE; } + bool ownLine() const { return TRUE; } + Placement placement() const { return place; } + bool isNested() const { return TRUE; } + void resize( int nwidth ); + virtual void invalidate(); + + virtual bool enter( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); + virtual bool enterAt( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy, const TQPoint &pos ); + virtual bool next( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool prev( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool down( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool up( TQTextCursor *c, TQTextDocument *&doc, TQTextParagraph *¶g, int &idx, int &ox, int &oy ); + + TQString richText() const; + + int minimumWidth() const; + + TQPtrList tableCells() const { return cells; } + + bool isStretching() const { return stretch; } + void setParagraph(TQTextParagraph *p); + +private: + void format( int w ); + void addCell( TQTextTableCell* cell ); + +private: + TQGridLayout* layout; + TQPtrList cells; + int cachewidth; + int fixwidth; + int cellpadding; + int cellspacing; + int border; + int outerborder; + int stretch; + int innerborder; + int us_cp, us_ib, us_b, us_ob, us_cs; + int us_fixwidth; + TQMap attributes; + TQMap currCell; + Placement place; + void adjustCells( int y , int shift ); + int pageBreakFor; +}; +#endif +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#ifndef TQT_NO_TEXTCUSTOMITEM +class TQTextTableCell; +class TQTextParagraph; +#endif + +struct TQ_EXPORT TQTextDocumentSelection +{ + TQTextCursor startCursor, endCursor; + bool swapped; + TQ_DUMMY_COMPARISON_OPERATOR(TQTextDocumentSelection) +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +//Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQPtrList; +// MOC_SKIP_END +#endif + +class TQ_EXPORT TQTextDocument : public TQObject +{ + TQ_OBJECT + +#ifndef TQT_NO_TEXTCUSTOMITEM + friend class TQTextTableCell; +#endif + friend class TQTextCursor; + friend class TQTextEdit; + friend class TQTextParagraph; + friend class TQTextTable; + +public: + enum SelectionIds { + Standard = 0, + IMSelectionText = 31998, + IMCompositionText = 31999, // this must be higher! + Temp = 32000 // This selection must not be drawn, it's used e.g. by undo/redo to + // remove multiple lines with removeSelectedText() + }; + + TQTextDocument( TQTextDocument *p ); + virtual ~TQTextDocument(); + + TQTextDocument *parent() const { return par; } + TQTextParagraph *parentParagraph() const { return parentPar; } + + void setText( const TQString &text, const TQString &context ); + TQMap attributes() const { return attribs; } + void setAttributes( const TQMap &attr ) { attribs = attr; } + + TQString text() const; + TQString text( int parag ) const; + TQString originalText() const; + + int x() const; + int y() const; + int width() const; + int widthUsed() const; + int visibleWidth() const; + int height() const; + void setWidth( int w ); + int minimumWidth() const; + bool setMinimumWidth( int needed, int used = -1, TQTextParagraph *parag = 0 ); + + void setY( int y ); + int leftMargin() const; + void setLeftMargin( int lm ); + int rightMargin() const; + void setRightMargin( int rm ); + + TQTextParagraph *firstParagraph() const; + TQTextParagraph *lastParagraph() const; + void setFirstParagraph( TQTextParagraph *p ); + void setLastParagraph( TQTextParagraph *p ); + + void invalidate(); + + void setPreProcessor( TQTextPreProcessor *sh ); + TQTextPreProcessor *preProcessor() const; + + void setFormatter( TQTextFormatter *f ); + TQTextFormatter *formatter() const; + + void setIndent( TQTextIndent *i ); + TQTextIndent *indent() const; + + TQColor selectionColor( int id ) const; + bool invertSelectionText( int id ) const; + void setSelectionColor( int id, const TQColor &c ); + void setInvertSelectionText( int id, bool b ); + bool hasSelection( int id, bool visible = FALSE ) const; + void setSelectionStart( int id, const TQTextCursor &cursor ); + bool setSelectionEnd( int id, const TQTextCursor &cursor ); + void selectAll( int id ); + bool removeSelection( int id ); + void selectionStart( int id, int ¶gId, int &index ); + TQTextCursor selectionStartCursor( int id ); + TQTextCursor selectionEndCursor( int id ); + void selectionEnd( int id, int ¶gId, int &index ); + void setFormat( int id, TQTextFormat *f, int flags ); + int numSelections() const { return nSelections; } + void addSelection( int id ); + + TQString selectedText( int id, bool asRichText = FALSE ) const; + void removeSelectedText( int id, TQTextCursor *cursor ); + void indentSelection( int id ); + + TQTextParagraph *paragAt( int i ) const; + + void addCommand( TQTextCommand *cmd ); + TQTextCursor *undo( TQTextCursor *c = 0 ); + TQTextCursor *redo( TQTextCursor *c = 0 ); + TQTextCommandHistory *commands() const { return commandHistory; } + + TQTextFormatCollection *formatCollection() const; + + bool find( TQTextCursor &cursor, const TQString &expr, bool cs, bool wo, bool forward); + + void setTextFormat( TQt::TextFormat f ); + TQt::TextFormat textFormat() const; + + bool inSelection( int selId, const TQPoint &pos ) const; + + TQStyleSheet *styleSheet() const { return sheet_; } +#ifndef TQT_NO_MIME + TQMimeSourceFactory *mimeSourceFactory() const { return factory_; } +#endif + TQString context() const { return contxt; } + + void setStyleSheet( TQStyleSheet *s ); + void setDefaultFormat( const TQFont &font, const TQColor &color ); +#ifndef TQT_NO_MIME + void setMimeSourceFactory( TQMimeSourceFactory *f ) { if ( f ) factory_ = f; } +#endif + void setContext( const TQString &c ) { if ( !c.isEmpty() ) contxt = c; } + + void setUnderlineLinks( bool b ); + bool underlineLinks() const { return underlLinks; } + + void setPaper( TQBrush *brush ) { if ( backBrush ) delete backBrush; backBrush = brush; } + TQBrush *paper() const { return backBrush; } + + void doLayout( TQPainter *p, int w ); + void draw( TQPainter *p, const TQRect& rect, const TQColorGroup &cg, const TQBrush *paper = 0 ); + bool useDoubleBuffer( TQTextParagraph *parag, TQPainter *p ); + + void drawParagraph( TQPainter *p, TQTextParagraph *parag, int cx, int cy, int cw, int ch, + TQPixmap *&doubleBuffer, const TQColorGroup &cg, + bool drawCursor, TQTextCursor *cursor, bool resetChanged = TRUE ); + TQTextParagraph *draw( TQPainter *p, int cx, int cy, int cw, int ch, const TQColorGroup &cg, + bool onlyChanged = FALSE, bool drawCursor = FALSE, TQTextCursor *cursor = 0, + bool resetChanged = TRUE ); + +#ifndef TQT_NO_TEXTCUSTOMITEM + void registerCustomItem( TQTextCustomItem *i, TQTextParagraph *p ); + void unregisterCustomItem( TQTextCustomItem *i, TQTextParagraph *p ); +#endif + + void setFlow( TQTextFlow *f ); + void takeFlow(); + TQTextFlow *flow() const { return flow_; } + bool isPageBreakEnabled() const { return pages; } + void setPageBreakEnabled( bool b ) { pages = b; } + + void setUseFormatCollection( bool b ) { useFC = b; } + bool useFormatCollection() const { return useFC; } + +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextTableCell *tableCell() const { return tc; } + void setTableCell( TQTextTableCell *c ) { tc = c; } +#endif + + void setPlainText( const TQString &text ); + void setRichText( const TQString &text, const TQString &context, const TQTextFormat *initialFormat = 0 ); + TQString richText() const; + TQString plainText() const; + + bool focusNextPrevChild( bool next ); + + int alignment() const; + void setAlignment( int a ); + + int *tabArray() const; + int tabStopWidth() const; + void setTabArray( int *a ); + void setTabStops( int tw ); + + void setUndoDepth( int d ) { commandHistory->setUndoDepth( d ); } + int undoDepth() const { return commandHistory->undoDepth(); } + + int length() const; + void clear( bool createEmptyParag = FALSE ); + + virtual TQTextParagraph *createParagraph( TQTextDocument *d, TQTextParagraph *pr = 0, TQTextParagraph *nx = 0, bool updateIds = TRUE ); + void insertChild( TQObject *o ) { TQObject::insertChild( o ); } + void removeChild( TQObject *o ) { TQObject::removeChild( o ); } + void insertChild( TQTextDocument *d ) { childList.append( d ); } + void removeChild( TQTextDocument *d ) { childList.removeRef( d ); } + TQPtrList children() const { return childList; } + + bool hasFocusParagraph() const; + TQString focusHref() const; + TQString focusName() const; + + void invalidateOriginalText() { oTextValid = FALSE; oText = ""; } + +signals: + void minimumWidthChanged( int ); + +private: + void init(); + TQPixmap *bufferPixmap( const TQSize &s ); + // HTML parser + bool hasPrefix(const TQChar* doc, int length, int pos, TQChar c); + bool hasPrefix(const TQChar* doc, int length, int pos, const TQString& s); +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextCustomItem* parseTable( const TQMap &attr, const TQTextFormat &fmt, + const TQChar* doc, int length, int& pos, TQTextParagraph *curpar ); +#endif + bool eatSpace(const TQChar* doc, int length, int& pos, bool includeNbsp = FALSE ); + bool eat(const TQChar* doc, int length, int& pos, TQChar c); + TQString parseOpenTag(const TQChar* doc, int length, int& pos, TQMap &attr, bool& emptyTag); + TQString parseCloseTag( const TQChar* doc, int length, int& pos ); + TQChar parseHTMLSpecialChar(const TQChar* doc, int length, int& pos); + TQString parseWord(const TQChar* doc, int length, int& pos, bool lower = TRUE); + TQChar parseChar(const TQChar* doc, int length, int& pos, TQStyleSheetItem::WhiteSpaceMode wsm ); + void setRichTextInternal( const TQString &text, TQTextCursor* cursor = 0, const TQTextFormat *initialFormat = 0 ); + void setRichTextMarginsInternal( TQPtrList< TQPtrVector >& styles, TQTextParagraph* stylesPar ); + +private: + struct TQ_EXPORT Focus { + TQTextParagraph *parag; + int start, len; + TQString href; + TQString name; + }; + + int cx, cy, cw, vw; + TQTextParagraph *fParag, *lParag; + TQTextPreProcessor *pProcessor; + TQMap selectionColors; + TQMap selections; + TQMap selectionText; + TQTextCommandHistory *commandHistory; + TQTextFormatter *pFormatter; + TQTextIndent *indenter; + TQTextFormatCollection *fCollection; + TQt::TextFormat txtFormat; + uint preferRichText : 1; + uint pages : 1; + uint useFC : 1; + uint withoutDoubleBuffer : 1; + uint underlLinks : 1; + uint nextDoubleBuffered : 1; + uint oTextValid : 1; + uint mightHaveCustomItems : 1; + int align; + int nSelections; + TQTextFlow *flow_; + TQTextDocument *par; + TQTextParagraph *parentPar; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextTableCell *tc; +#endif + TQBrush *backBrush; + TQPixmap *buf_pixmap; + Focus focusIndicator; + int minw; + int wused; + int leftmargin; + int rightmargin; + TQTextParagraph *minwParag, *curParag; + TQStyleSheet* sheet_; +#ifndef TQT_NO_MIME + TQMimeSourceFactory* factory_; +#endif + TQString contxt; + TQMap attribs; + int *tArray; + int tStopWidth; + int uDepth; + TQString oText; + TQPtrList childList; + TQColor linkColor, bodyText; + double scaleFontsFactor; + + short list_tm,list_bm, list_lm, li_tm, li_bm, par_tm, par_bm; +#if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= + TQTextDocument( const TQTextDocument & ); + TQTextDocument &operator=( const TQTextDocument & ); +#endif +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +class TQ_EXPORT TQTextDeleteCommand : public TQTextCommand +{ +public: + TQTextDeleteCommand( TQTextDocument *d, int i, int idx, const TQMemArray &str, + const TQByteArray& oldStyle ); + TQTextDeleteCommand( TQTextParagraph *p, int idx, const TQMemArray &str ); + virtual ~TQTextDeleteCommand(); + + Commands type() const { return Delete; } + TQTextCursor *execute( TQTextCursor *c ); + TQTextCursor *unexecute( TQTextCursor *c ); + +protected: + int id, index; + TQTextParagraph *parag; + TQMemArray text; + TQByteArray styleInformation; + +}; + +class TQ_EXPORT TQTextInsertCommand : public TQTextDeleteCommand +{ +public: + TQTextInsertCommand( TQTextDocument *d, int i, int idx, const TQMemArray &str, + const TQByteArray& oldStyleInfo ) + : TQTextDeleteCommand( d, i, idx, str, oldStyleInfo ) {} + TQTextInsertCommand( TQTextParagraph *p, int idx, const TQMemArray &str ) + : TQTextDeleteCommand( p, idx, str ) {} + virtual ~TQTextInsertCommand() {} + + Commands type() const { return Insert; } + TQTextCursor *execute( TQTextCursor *c ) { return TQTextDeleteCommand::unexecute( c ); } + TQTextCursor *unexecute( TQTextCursor *c ) { return TQTextDeleteCommand::execute( c ); } + +}; + +class TQ_EXPORT TQTextFormatCommand : public TQTextCommand +{ +public: + TQTextFormatCommand( TQTextDocument *d, int sid, int sidx, int eid, int eidx, const TQMemArray &old, TQTextFormat *f, int fl ); + virtual ~TQTextFormatCommand(); + + Commands type() const { return Format; } + TQTextCursor *execute( TQTextCursor *c ); + TQTextCursor *unexecute( TQTextCursor *c ); + +protected: + int startId, startIndex, endId, endIndex; + TQTextFormat *format; + TQMemArray oldFormats; + int flags; + +}; + +class TQ_EXPORT TQTextStyleCommand : public TQTextCommand +{ +public: + TQTextStyleCommand( TQTextDocument *d, int fParag, int lParag, const TQByteArray& beforeChange ); + virtual ~TQTextStyleCommand() {} + + Commands type() const { return Style; } + TQTextCursor *execute( TQTextCursor *c ); + TQTextCursor *unexecute( TQTextCursor *c ); + + static TQByteArray readStyleInformation( TQTextDocument* d, int fParag, int lParag ); + static void writeStyleInformation( TQTextDocument* d, int fParag, const TQByteArray& style ); + +private: + int firstParag, lastParag; + TQByteArray before; + TQByteArray after; +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +struct TQ_EXPORT TQTextParagraphSelection +{ + TQTextParagraphSelection() : start(0), end(0) { } + int start, end; + TQ_DUMMY_COMPARISON_OPERATOR(TQTextParagraphSelection) +}; + +struct TQ_EXPORT TQTextLineStart +{ + TQTextLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) + { } + TQTextLineStart( int y_, int bl, int h_ ) : y( y_ ), baseLine( bl ), h( h_ ), + w( 0 ) + { } + +public: + int y, baseLine, h; + int w; +}; + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQMap; +// MOC_SKIP_END +#endif + +class TQ_EXPORT TQTextParagraphData +{ +public: + TQTextParagraphData() {} + virtual ~TQTextParagraphData(); + virtual void join( TQTextParagraphData * ); +}; + +class TQTextParagraphPseudoDocument; + +class TQSyntaxHighlighter; + +class TQ_EXPORT TQTextParagraph +{ + friend class TQTextDocument; + friend class TQTextCursor; + friend class TQSyntaxHighlighter; + +public: + TQTextParagraph( TQTextDocument *d, TQTextParagraph *pr = 0, TQTextParagraph *nx = 0, bool updateIds = TRUE ); + ~TQTextParagraph(); + + TQTextString *string() const; + TQTextStringChar *at( int i ) const; // maybe remove later + int leftGap() const; + int length() const; // maybe remove later + + void setListStyle( TQStyleSheetItem::ListStyle ls ) { lstyle = ls; changed = TRUE; } + TQStyleSheetItem::ListStyle listStyle() const { return (TQStyleSheetItem::ListStyle)lstyle; } + void setListItem( bool li ); + bool isListItem() const { return litem; } + void setListValue( int v ) { list_val = v; } + int listValue() const { return list_val > 0 ? list_val : -1; } + + void setListDepth( int depth ); + int listDepth() const { return ldepth; } + +// void setFormat( TQTextFormat *fm ); +// TQTextFormat *paragFormat() const; + + inline TQTextDocument *document() const { + if (hasdoc) return (TQTextDocument*) docOrPseudo; + return 0; + } + TQTextParagraphPseudoDocument *pseudoDocument() const; + + TQRect rect() const; + void setHeight( int h ) { r.setHeight( h ); } + void show(); + void hide(); + bool isVisible() const { return visible; } + + TQTextParagraph *prev() const; + TQTextParagraph *next() const; + void setPrev( TQTextParagraph *s ); + void setNext( TQTextParagraph *s ); + + void insert( int index, const TQString &s ); + void insert( int index, const TQChar *unicode, int len ); + void append( const TQString &s, bool reallyAtEnd = FALSE ); + void truncate( int index ); + void remove( int index, int len ); + void join( TQTextParagraph *s ); + + void invalidate( int chr ); + + void move( int &dy ); + void format( int start = -1, bool doMove = TRUE ); + + bool isValid() const; + bool hasChanged() const; + void setChanged( bool b, bool recursive = FALSE ); + + int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const; + TQTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const; + int lines() const; + TQTextStringChar *lineStartOfLine( int line, int *index = 0 ) const; + int lineY( int l ) const; + int lineBaseLine( int l ) const; + int lineHeight( int l ) const; + void lineInfo( int l, int &y, int &h, int &bl ) const; + + void setSelection( int id, int start, int end ); + void removeSelection( int id ); + int selectionStart( int id ) const; + int selectionEnd( int id ) const; + bool hasSelection( int id ) const; + bool hasAnySelection() const; + bool fullSelected( int id ) const; + + void setEndState( int s ); + int endState() const; + + void setParagId( int i ); + int paragId() const; + + bool firstPreProcess() const; + void setFirstPreProcess( bool b ); + + void indent( int *oldIndent = 0, int *newIndent = 0 ); + + void setExtraData( TQTextParagraphData *data ); + TQTextParagraphData *extraData() const; + + TQMap &lineStartList(); + + void setFormat( int index, int len, TQTextFormat *f, bool useCollection = TRUE, int flags = -1 ); + + void setAlignment( int a ); + int alignment() const; + + void paint( TQPainter &painter, const TQColorGroup &cg, TQTextCursor *cursor = 0, bool drawSelections = FALSE, + int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 ); + + int topMargin() const; + int bottomMargin() const; + int leftMargin() const; + int firstLineMargin() const; + int rightMargin() const; + int lineSpacing() const; + +#ifndef TQT_NO_TEXTCUSTOMITEM + void registerFloatingItem( TQTextCustomItem *i ); + void unregisterFloatingItem( TQTextCustomItem *i ); +#endif + + void setFullWidth( bool b ) { fullWidth = b; } + bool isFullWidth() const { return fullWidth; } + +#ifndef TQT_NO_TEXTCUSTOMITEM + TQTextTableCell *tableCell() const; +#endif + + TQBrush *background() const; + + int documentWidth() const; + int documentVisibleWidth() const; + int documentX() const; + int documentY() const; + TQTextFormatCollection *formatCollection() const; + TQTextFormatter *formatter() const; + + int nextTab( int i, int x ); + int *tabArray() const; + void setTabArray( int *a ); + void setTabStops( int tw ); + + void adjustToPainter( TQPainter *p ); + + void setNewLinesAllowed( bool b ); + bool isNewLinesAllowed() const; + + TQString richText() const; + + void addCommand( TQTextCommand *cmd ); + TQTextCursor *undo( TQTextCursor *c = 0 ); + TQTextCursor *redo( TQTextCursor *c = 0 ); + TQTextCommandHistory *commands() const; + void copyParagData( TQTextParagraph *parag ); + + void setBreakable( bool b ) { breakable = b; } + bool isBreakable() const { return breakable; } + + void setBackgroundColor( const TQColor &c ); + TQColor *backgroundColor() const { return bgcol; } + void clearBackgroundColor(); + + void setMovedDown( bool b ) { movedDown = b; } + bool wasMovedDown() const { return movedDown; } + + void setDirection( TQChar::Direction d ); + TQChar::Direction direction() const; + void setPaintDevice( TQPaintDevice *pd ) { paintdevice = pd; } + + void readStyleInformation( TQDataStream& stream ); + void writeStyleInformation( TQDataStream& stream ) const; + +protected: + void setColorForSelection( TQColor &c, TQPainter &p, const TQColorGroup& cg, int selection ); + void drawLabel( TQPainter* p, int x, int y, int w, int h, int base, const TQColorGroup& cg ); + void drawString( TQPainter &painter, const TQString &str, int start, int len, int xstart, + int y, int baseLine, int w, int h, bool drawSelections, int fullSelectionWidth, + TQTextStringChar *formatChar, const TQColorGroup& cg, + bool rightToLeft ); + +private: + TQMap &selections() const; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQPtrList &floatingItems() const; +#endif + TQBrush backgroundBrush( const TQColorGroup&cg ) { if ( bgcol ) return *bgcol; return cg.brush( TQColorGroup::Base ); } + void invalidateStyleCache(); + + TQMap lineStarts; + TQRect r; + TQTextParagraph *p, *n; + void *docOrPseudo; + uint changed : 1; + uint firstFormat : 1; + uint firstPProcess : 1; + uint needPreProcess : 1; + uint fullWidth : 1; + uint lastInFrame : 1; + uint visible : 1; + uint breakable : 1; + uint movedDown : 1; + uint mightHaveCustomItems : 1; + uint hasdoc : 1; + uint litem : 1; // whether the paragraph is a list item + uint rtext : 1; // whether the paragraph needs rich text margin + int align : 4; + uint /*TQStyleSheetItem::ListStyle*/ lstyle : 4; + int invalid; + int state, id; + TQTextString *str; + TQMap *mSelections; +#ifndef TQT_NO_TEXTCUSTOMITEM + TQPtrList *mFloatingItems; +#endif + short utm, ubm, ulm, urm, uflm, ulinespacing; + short tabStopWidth; + int minwidth; + int *tArray; + TQTextParagraphData *eData; + short list_val; + ushort ldepth; + TQColor *bgcol; + TQPaintDevice *paintdevice; +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextFormatter +{ +public: + TQTextFormatter(); + virtual ~TQTextFormatter(); + + virtual int format( TQTextDocument *doc, TQTextParagraph *parag, int start, const TQMap &oldLineStarts ) = 0; + virtual int formatVertically( TQTextDocument* doc, TQTextParagraph* parag ); + + bool isWrapEnabled( TQTextParagraph *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} + int wrapAtColumn() const { return wrapColumn;} + virtual void setWrapEnabled( bool b ); + virtual void setWrapAtColumn( int c ); + virtual void setAllowBreakInWords( bool b ) { biw = b; } + bool allowBreakInWords() const { return biw; } + + int minimumWidth() const { return thisminw; } + int widthUsed() const { return thiswused; } + +protected: + virtual TQTextLineStart *formatLine( TQTextParagraph *parag, TQTextString *string, TQTextLineStart *line, TQTextStringChar *start, + TQTextStringChar *last, int align = TQt::AlignAuto, int space = 0 ); +#ifndef TQT_NO_COMPLEXTEXT + virtual TQTextLineStart *bidiReorderLine( TQTextParagraph *parag, TQTextString *string, TQTextLineStart *line, TQTextStringChar *start, + TQTextStringChar *last, int align, int space ); +#endif + void insertLineStart( TQTextParagraph *parag, int index, TQTextLineStart *ls ); + + int thisminw; + int thiswused; + +private: + bool wrapEnabled; + int wrapColumn; + bool biw; + +#ifdef HAVE_THAI_BREAKS + static TQCString *thaiCache; + static TQTextString *cachedString; + static ThBreakIterator *thaiIt; +#endif +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextFormatterBreakInWords : public TQTextFormatter +{ +public: + TQTextFormatterBreakInWords(); + virtual ~TQTextFormatterBreakInWords() {} + + int format( TQTextDocument *doc, TQTextParagraph *parag, int start, const TQMap &oldLineStarts ); + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextFormatterBreakWords : public TQTextFormatter +{ +public: + TQTextFormatterBreakWords(); + virtual ~TQTextFormatterBreakWords() {} + + int format( TQTextDocument *doc, TQTextParagraph *parag, int start, const TQMap &oldLineStarts ); + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextIndent +{ +public: + TQTextIndent(); + virtual ~TQTextIndent() {} + + virtual void indent( TQTextDocument *doc, TQTextParagraph *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextPreProcessor +{ +public: + enum Ids { + Standard = 0 + }; + + TQTextPreProcessor(); + virtual ~TQTextPreProcessor() {} + + virtual void process( TQTextDocument *doc, TQTextParagraph *, int, bool = TRUE ) = 0; + virtual TQTextFormat *format( int id ) = 0; + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +class TQ_EXPORT TQTextFormat +{ + friend class TQTextFormatCollection; + friend class TQTextDocument; + +public: + enum Flags { + NoFlags, + Bold = 1, + Italic = 2, + Underline = 4, + Family = 8, + Size = 16, + Color = 32, + Misspelled = 64, + VAlign = 128, + StrikeOut= 256, + Font = Bold | Italic | Underline | Family | Size | StrikeOut, + Format = Font | Color | Misspelled | VAlign + }; + + enum VerticalAlignment { AlignNormal, AlignSuperScript, AlignSubScript }; + + TQTextFormat(); + virtual ~TQTextFormat(); + + TQTextFormat( const TQStyleSheetItem *s ); + TQTextFormat( const TQFont &f, const TQColor &c, TQTextFormatCollection *parent = 0 ); + TQTextFormat( const TQTextFormat &fm ); + TQTextFormat makeTextFormat( const TQStyleSheetItem *style, const TQMap& attr, double scaleFontsFactor ) const; + TQTextFormat& operator=( const TQTextFormat &fm ); + TQColor color() const; + TQFont font() const; + TQFontMetrics fontMetrics() const { return fm; } + bool isMisspelled() const; + VerticalAlignment vAlign() const; + int minLeftBearing() const; + int minRightBearing() const; + int width( const TQChar &c ) const; + int width( const TQString &str, int pos ) const; + int height() const; + int ascent() const; + int descent() const; + int leading() const; + bool useLinkColor() const; + + void setBold( bool b ); + void setItalic( bool b ); + void setUnderline( bool b ); + void setStrikeOut( bool b ); + void setFamily( const TQString &f ); + void setPointSize( int s ); + void setFont( const TQFont &f ); + void setColor( const TQColor &c ); + void setMisspelled( bool b ); + void setVAlign( VerticalAlignment a ); + + bool operator==( const TQTextFormat &f ) const; + TQTextFormatCollection *parent() const; + const TQString &key() const; + + static TQString getKey( const TQFont &f, const TQColor &c, bool misspelled, VerticalAlignment vAlign ); + + void addRef(); + void removeRef(); + + TQString makeFormatChangeTags( TQTextFormat* defaultFormat, TQTextFormat *f, const TQString& oldAnchorHref, const TQString& anchorHref ) const; + TQString makeFormatEndTags( TQTextFormat* defaultFormat, const TQString& anchorHref ) const; + + static void setPainter( TQPainter *p ); + static TQPainter* painter(); + + bool fontSizesInPixels() { return usePixelSizes; } + +protected: + virtual void generateKey(); + +private: + void update(); + static void applyFont( const TQFont &f ); + static void cleanupPrivateData(); + +private: + TQFont fn; + TQColor col; + TQFontMetrics fm; + uint missp : 1; + uint linkColor : 1; + uint usePixelSizes : 1; + int leftBearing, rightBearing; + VerticalAlignment ha; + uchar widths[ 256 ]; + int hei, asc, dsc; + TQTextFormatCollection *collection; + int ref; + TQString k; + int logicalFontSize; + int stdSize; + static TQPainter *pntr; + static TQFontMetrics *pntr_fm; + static int pntr_asc; + static int pntr_hei; + static int pntr_ldg; + static int pntr_dsc; + +}; + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#if defined(Q_TEMPLATEDLL) +// MOC_SKIP_BEGIN +Q_TEMPLATE_EXTERN template class TQ_EXPORT TQDict; +// MOC_SKIP_END +#endif + +class TQ_EXPORT TQTextFormatCollection +{ + friend class TQTextDocument; + friend class TQTextFormat; + +public: + TQTextFormatCollection(); + virtual ~TQTextFormatCollection(); + + void setDefaultFormat( TQTextFormat *f ); + TQTextFormat *defaultFormat() const; + virtual TQTextFormat *format( TQTextFormat *f ); + virtual TQTextFormat *format( TQTextFormat *of, TQTextFormat *nf, int flags ); + virtual TQTextFormat *format( const TQFont &f, const TQColor &c ); + virtual void remove( TQTextFormat *f ); + virtual TQTextFormat *createFormat( const TQTextFormat &f ) { return new TQTextFormat( f ); } + virtual TQTextFormat *createFormat( const TQFont &f, const TQColor &c ) { return new TQTextFormat( f, c, this ); } + + void updateDefaultFormat( const TQFont &font, const TQColor &c, TQStyleSheet *sheet ); + + TQPaintDevice *paintDevice() const { return paintdevice; } + void setPaintDevice( TQPaintDevice * ); + +private: + void updateKeys(); + +private: + TQTextFormat *defFormat, *lastFormat, *cachedFormat; + TQDict cKey; + TQTextFormat *cres; + TQFont cfont; + TQColor ccol; + TQString kof, knf; + int cflags; + + TQPaintDevice *paintdevice; +}; + +class TQ_EXPORT TQTextParagraphPseudoDocument +{ +public: + TQTextParagraphPseudoDocument(); + ~TQTextParagraphPseudoDocument(); + TQRect docRect; + TQTextFormatter *pFormatter; + TQTextCommandHistory *commandHistory; + int minw; + int wused; + TQTextFormatCollection collection; +}; + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline int TQTextParagraph::length() const +{ + return str->length(); +} + +inline TQRect TQTextParagraph::rect() const +{ + return r; +} + +inline int TQTextCursor::index() const +{ + return idx; +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline int TQTextDocument::x() const +{ + return cx; +} + +inline int TQTextDocument::y() const +{ + return cy; +} + +inline int TQTextDocument::width() const +{ + return TQMAX( cw, flow_->width() ); +} + +inline int TQTextDocument::visibleWidth() const +{ + return vw; +} + +inline TQTextParagraph *TQTextDocument::firstParagraph() const +{ + return fParag; +} + +inline TQTextParagraph *TQTextDocument::lastParagraph() const +{ + return lParag; +} + +inline void TQTextDocument::setFirstParagraph( TQTextParagraph *p ) +{ + fParag = p; +} + +inline void TQTextDocument::setLastParagraph( TQTextParagraph *p ) +{ + lParag = p; +} + +inline void TQTextDocument::setWidth( int w ) +{ + cw = TQMAX( w, minw ); + flow_->setWidth( cw ); + vw = w; +} + +inline int TQTextDocument::minimumWidth() const +{ + return minw; +} + +inline void TQTextDocument::setY( int y ) +{ + cy = y; +} + +inline int TQTextDocument::leftMargin() const +{ + return leftmargin; +} + +inline void TQTextDocument::setLeftMargin( int lm ) +{ + leftmargin = lm; +} + +inline int TQTextDocument::rightMargin() const +{ + return rightmargin; +} + +inline void TQTextDocument::setRightMargin( int rm ) +{ + rightmargin = rm; +} + +inline TQTextPreProcessor *TQTextDocument::preProcessor() const +{ + return pProcessor; +} + +inline void TQTextDocument::setPreProcessor( TQTextPreProcessor * sh ) +{ + pProcessor = sh; +} + +inline void TQTextDocument::setFormatter( TQTextFormatter *f ) +{ + delete pFormatter; + pFormatter = f; +} + +inline TQTextFormatter *TQTextDocument::formatter() const +{ + return pFormatter; +} + +inline void TQTextDocument::setIndent( TQTextIndent *i ) +{ + indenter = i; +} + +inline TQTextIndent *TQTextDocument::indent() const +{ + return indenter; +} + +inline TQColor TQTextDocument::selectionColor( int id ) const +{ + return selectionColors[ id ]; +} + +inline bool TQTextDocument::invertSelectionText( int id ) const +{ + return selectionText[ id ]; +} + +inline void TQTextDocument::setSelectionColor( int id, const TQColor &c ) +{ + selectionColors[ id ] = c; +} + +inline void TQTextDocument::setInvertSelectionText( int id, bool b ) +{ + selectionText[ id ] = b; +} + +inline TQTextFormatCollection *TQTextDocument::formatCollection() const +{ + return fCollection; +} + +inline int TQTextDocument::alignment() const +{ + return align; +} + +inline void TQTextDocument::setAlignment( int a ) +{ + align = a; +} + +inline int *TQTextDocument::tabArray() const +{ + return tArray; +} + +inline int TQTextDocument::tabStopWidth() const +{ + return tStopWidth; +} + +inline void TQTextDocument::setTabArray( int *a ) +{ + tArray = a; +} + +inline void TQTextDocument::setTabStops( int tw ) +{ + tStopWidth = tw; +} + +inline TQString TQTextDocument::originalText() const +{ + if ( oTextValid ) + return oText; + return text(); +} + +inline void TQTextDocument::setFlow( TQTextFlow *f ) +{ + if ( flow_ ) + delete flow_; + flow_ = f; +} + +inline void TQTextDocument::takeFlow() +{ + flow_ = 0; +} + +inline bool TQTextDocument::useDoubleBuffer( TQTextParagraph *parag, TQPainter *p ) +{ + return ( !parag->document()->parent() || parag->document()->nextDoubleBuffered ) && + ( !p || !p->device() || p->device()->devType() != TQInternal::Printer ); +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline TQColor TQTextFormat::color() const +{ + return col; +} + +inline TQFont TQTextFormat::font() const +{ + return fn; +} + +inline bool TQTextFormat::isMisspelled() const +{ + return missp; +} + +inline TQTextFormat::VerticalAlignment TQTextFormat::vAlign() const +{ + return ha; +} + +inline bool TQTextFormat::operator==( const TQTextFormat &f ) const +{ + return k == f.k; +} + +inline TQTextFormatCollection *TQTextFormat::parent() const +{ + return collection; +} + +inline void TQTextFormat::addRef() +{ + ref++; +} + +inline void TQTextFormat::removeRef() +{ + ref--; + if ( !collection ) + return; + if ( this == collection->defFormat ) + return; + if ( ref == 0 ) + collection->remove( this ); +} + +inline const TQString &TQTextFormat::key() const +{ + return k; +} + +inline bool TQTextFormat::useLinkColor() const +{ + return linkColor; +} + +inline TQTextStringChar *TQTextParagraph::at( int i ) const +{ + return &str->at( i ); +} + +inline bool TQTextParagraph::isValid() const +{ + return invalid == -1; +} + +inline bool TQTextParagraph::hasChanged() const +{ + return changed; +} + +inline void TQTextParagraph::setBackgroundColor( const TQColor & c ) +{ + delete bgcol; + bgcol = new TQColor( c ); + setChanged( TRUE ); +} + +inline void TQTextParagraph::clearBackgroundColor() +{ + delete bgcol; bgcol = 0; setChanged( TRUE ); +} + +inline void TQTextParagraph::append( const TQString &s, bool reallyAtEnd ) +{ + if ( reallyAtEnd ) + insert( str->length(), s ); + else + insert( TQMAX( str->length() - 1, 0 ), s ); +} + +inline TQTextParagraph *TQTextParagraph::prev() const +{ + return p; +} + +inline TQTextParagraph *TQTextParagraph::next() const +{ + return n; +} + +inline bool TQTextParagraph::hasAnySelection() const +{ + return mSelections ? !selections().isEmpty() : FALSE; +} + +inline void TQTextParagraph::setEndState( int s ) +{ + if ( s == state ) + return; + state = s; +} + +inline int TQTextParagraph::endState() const +{ + return state; +} + +inline void TQTextParagraph::setParagId( int i ) +{ + id = i; +} + +inline int TQTextParagraph::paragId() const +{ + if ( id == -1 ) + tqWarning( "invalid parag id!!!!!!!! (%p)", (void*)this ); + return id; +} + +inline bool TQTextParagraph::firstPreProcess() const +{ + return firstPProcess; +} + +inline void TQTextParagraph::setFirstPreProcess( bool b ) +{ + firstPProcess = b; +} + +inline TQMap &TQTextParagraph::lineStartList() +{ + return lineStarts; +} + +inline TQTextString *TQTextParagraph::string() const +{ + return str; +} + +inline TQTextParagraphPseudoDocument *TQTextParagraph::pseudoDocument() const +{ + if ( hasdoc ) + return 0; + return (TQTextParagraphPseudoDocument*) docOrPseudo; +} + + +#ifndef TQT_NO_TEXTCUSTOMITEM +inline TQTextTableCell *TQTextParagraph::tableCell() const +{ + return hasdoc ? document()->tableCell () : 0; +} +#endif + +inline TQTextCommandHistory *TQTextParagraph::commands() const +{ + return hasdoc ? document()->commands() : pseudoDocument()->commandHistory; +} + + +inline int TQTextParagraph::alignment() const +{ + return align; +} + +#ifndef TQT_NO_TEXTCUSTOMITEM +inline void TQTextParagraph::registerFloatingItem( TQTextCustomItem *i ) +{ + floatingItems().append( i ); +} + +inline void TQTextParagraph::unregisterFloatingItem( TQTextCustomItem *i ) +{ + floatingItems().removeRef( i ); +} +#endif + +inline TQBrush *TQTextParagraph::background() const +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + return tableCell() ? tableCell()->backGround() : 0; +#else + return 0; +#endif +} + +inline int TQTextParagraph::documentWidth() const +{ + return hasdoc ? document()->width() : pseudoDocument()->docRect.width(); +} + +inline int TQTextParagraph::documentVisibleWidth() const +{ + return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width(); +} + +inline int TQTextParagraph::documentX() const +{ + return hasdoc ? document()->x() : pseudoDocument()->docRect.x(); +} + +inline int TQTextParagraph::documentY() const +{ + return hasdoc ? document()->y() : pseudoDocument()->docRect.y(); +} + +inline void TQTextParagraph::setExtraData( TQTextParagraphData *data ) +{ + eData = data; +} + +inline TQTextParagraphData *TQTextParagraph::extraData() const +{ + return eData; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline void TQTextFormatCollection::setDefaultFormat( TQTextFormat *f ) +{ + defFormat = f; +} + +inline TQTextFormat *TQTextFormatCollection::defaultFormat() const +{ + return defFormat; +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +inline TQTextFormat *TQTextStringChar::format() const +{ + return (type == Regular) ? d.format : d.custom->format; +} + + +#ifndef TQT_NO_TEXTCUSTOMITEM +inline TQTextCustomItem *TQTextStringChar::customItem() const +{ + return isCustom() ? d.custom->custom : 0; +} +#endif + +inline int TQTextStringChar::height() const +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + return !isCustom() ? format()->height() : ( customItem()->placement() == TQTextCustomItem::PlaceInline ? customItem()->height : 0 ); +#else + return format()->height(); +#endif +} + +inline int TQTextStringChar::ascent() const +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + return !isCustom() ? format()->ascent() : ( customItem()->placement() == TQTextCustomItem::PlaceInline ? customItem()->ascent() : 0 ); +#else + return format()->ascent(); +#endif +} + +inline int TQTextStringChar::descent() const +{ +#ifndef TQT_NO_TEXTCUSTOMITEM + return !isCustom() ? format()->descent() : 0; +#else + return format()->descent(); +#endif +} + +#endif //TQT_NO_RICHTEXT + +#endif diff --git a/src/kernel/tqscriptengine.cpp b/src/kernel/tqscriptengine.cpp new file mode 100644 index 000000000..2d97c84d5 --- /dev/null +++ b/src/kernel/tqscriptengine.cpp @@ -0,0 +1,1622 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqscriptengine_p.h" + +#include "tqstring.h" +#include "tqrect.h" +#include "tqfont.h" +#include +#include "tqtextengine_p.h" +#include "tqfontengine_p.h" +#include + +#undef None +#undef Pre +#undef Above +#undef Below + +const int Prealloc = 256; +template +class TQVarLengthArray +{ +public: + inline explicit TQVarLengthArray(int size = 0); + inline ~TQVarLengthArray() { + if (ptr != reinterpret_cast(array)) + free(ptr); + } + + inline int size() const { return s; } + inline int count() const { return s; } + inline bool isEmpty() const { return (s == 0); } + inline void resize(int size); + inline void clear() { resize(0); } + + inline int capacity() const { return a; } + inline void reserve(int size); + + inline T &operator[](int idx) { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + inline const T &operator[](int idx) const { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + + inline void append(const T &t) { + const int idx = s; + resize(idx + 1); + ptr[idx] = t; + } + + inline T *data() { return ptr; } + inline const T *data() const { return ptr; } + inline const T * constData() const { return ptr; } + +private: + void realloc(int size, int alloc); + + int a; + int s; + T *ptr; + TQ_UINT64 array[((Prealloc * sizeof(T)) / sizeof(TQ_UINT64)) + 1]; +}; + +template +TQ_INLINE_TEMPLATES TQVarLengthArray::TQVarLengthArray(int asize) + : s(asize) { + if (s > Prealloc) { + ptr = reinterpret_cast(malloc(s * sizeof(T))); + a = s; + } else { + ptr = reinterpret_cast(array); + a = Prealloc; + } +} + + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Basic processing +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +static inline void positionCluster(TQShaperItem *item, int gfrom, int glast) +{ + int nmarks = glast - gfrom; + if (nmarks <= 0) { + tqWarning("positionCluster: no marks to position!"); + return; + } + + TQFontEngine *f = item->font; + + glyph_metrics_t baseInfo = f->boundingBox(item->glyphs[gfrom]); + + if (item->script == TQFont::Hebrew) + // we need to attach below the baseline, because of the hebrew iud. + baseInfo.height = TQMAX(baseInfo.height, -baseInfo.y); + + TQRect baseRect(baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height); + +// tqDebug("---> positionCluster: cluster from %d to %d", gfrom, glast); +// tqDebug("baseInfo: %f/%f (%f/%f) off=%f/%f", baseInfo.x, baseInfo.y, baseInfo.width, baseInfo.height, baseInfo.xoff, baseInfo.yoff); + + int size = (f->ascent()/10); + int offsetBase = (size - 4) / 4 + TQMIN(size, 4) + 1; +// tqDebug("offset = %f", offsetBase); + + bool rightToLeft = item->flags & TQTextEngine::RightToLeft; + + int i; + unsigned char lastCmb = 0; + TQRect attachmentRect; + + for(i = 1; i <= nmarks; i++) { + glyph_t mark = item->glyphs[gfrom+i]; + TQPoint p; + glyph_metrics_t markInfo = f->boundingBox(mark); + TQRect markRect(markInfo.x, markInfo.y, markInfo.width, markInfo.height); +// tqDebug("markInfo: %f/%f (%f/%f) off=%f/%f", markInfo.x, markInfo.y, markInfo.width, markInfo.height, markInfo.xoff, markInfo.yoff); + + int offset = offsetBase; + unsigned char cmb = item->attributes[gfrom+i].combiningClass; + + // ### maybe the whole position determination should move down to heuristicSetGlyphAttributes. Would save some + // bits in the glyphAttributes structure. + if (cmb < 200) { + // fixed position classes. We approximate by mapping to one of the others. + // currently I added only the ones for arabic, hebrew, lao and thai. + + // for Lao and Thai marks with class 0, see below (heuristicSetGlyphAttributes) + + // add a bit more offset to arabic, a bit hacky + if (cmb >= 27 && cmb <= 36 && offset < 3) + offset +=1; + // below + if ((cmb >= 10 && cmb <= 18) || + cmb == 20 || cmb == 22 || + cmb == 29 || cmb == 32) + cmb = TQChar::Combining_Below; + // above + else if (cmb == 23 || cmb == 27 || cmb == 28 || + cmb == 30 || cmb == 31 || (cmb >= 33 && cmb <= 36)) + cmb = TQChar::Combining_Above; + //below-right + else if (cmb == 9 || cmb == 103 || cmb == 118) + cmb = TQChar::Combining_BelowRight; + // above-right + else if (cmb == 24 || cmb == 107 || cmb == 122) + cmb = TQChar::Combining_AboveRight; + else if (cmb == 25) + cmb = TQChar::Combining_AboveLeft; + // fixed: + // 19 21 + + } + + // combining marks of different class don't interact. Reset the rectangle. + if (cmb != lastCmb) { + //tqDebug("resetting rect"); + attachmentRect = baseRect; + } + + switch(cmb) { + case TQChar::Combining_DoubleBelow: + // ### wrong in rtl context! + case TQChar::Combining_BelowLeft: + p += TQPoint(0, offset); + case TQChar::Combining_BelowLeftAttached: + p += attachmentRect.bottomLeft() - markRect.topLeft(); + break; + case TQChar::Combining_Below: + p += TQPoint(0, offset); + case TQChar::Combining_BelowAttached: + p += attachmentRect.bottomLeft() - markRect.topLeft(); + p += TQPoint((attachmentRect.width() - markRect.width())/2 , 0); + break; + case TQChar::Combining_BelowRight: + p += TQPoint(0, offset); + case TQChar::Combining_BelowRightAttached: + p += attachmentRect.bottomRight() - markRect.topRight(); + break; + case TQChar::Combining_Left: + p += TQPoint(-offset, 0); + case TQChar::Combining_LeftAttached: + break; + case TQChar::Combining_Right: + p += TQPoint(offset, 0); + case TQChar::Combining_RightAttached: + break; + case TQChar::Combining_DoubleAbove: + // ### wrong in RTL context! + case TQChar::Combining_AboveLeft: + p += TQPoint(0, -offset); + case TQChar::Combining_AboveLeftAttached: + p += attachmentRect.topLeft() - markRect.bottomLeft(); + break; + case TQChar::Combining_Above: + p += TQPoint(0, -offset); + case TQChar::Combining_AboveAttached: + p += attachmentRect.topLeft() - markRect.bottomLeft(); + p += TQPoint((attachmentRect.width() - markRect.width())/2 , 0); + break; + case TQChar::Combining_AboveRight: + p += TQPoint(0, -offset); + case TQChar::Combining_AboveRightAttached: + p += attachmentRect.topRight() - markRect.bottomRight(); + break; + + case TQChar::Combining_IotaSubscript: + default: + break; + } +// tqDebug("char=%x combiningClass = %d offset=%d/%d", mark, cmb, p.x(), p.y()); + markRect.moveBy(p.x(), p.y()); + attachmentRect |= markRect; + lastCmb = cmb; + if (rightToLeft) { + item->offsets[gfrom+i].x = p.x(); + item->offsets[gfrom+i].y = p.y(); + } else { + item->offsets[gfrom+i].x = p.x() - baseInfo.xoff; + item->offsets[gfrom+i].y = p.y() - baseInfo.yoff; + } + item->advances[gfrom+i] = 0; + } + item->has_positioning = TRUE; +} + + +void qt_heuristicPosition(TQShaperItem *item) +{ + int cEnd = -1; + int i = item->num_glyphs; + while (i--) { + if (cEnd == -1 && item->attributes[i].mark) { + cEnd = i; + } else if (cEnd != -1 && !item->attributes[i].mark) { + positionCluster(item, i, cEnd); + cEnd = -1; + } + } +} + + + +// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs +// and no reordering. +// also computes logClusters heuristically +static void heuristicSetGlyphAttributes(TQShaperItem *item, const TQChar *uc, int length) +{ + // justification is missing here!!!!! + + if ( item->num_glyphs != length ) + tqWarning("TQScriptEngine::heuristicSetGlyphAttributes: char length and num glyphs disagree" ); + + unsigned short *logClusters = item->log_clusters; + + int i; + for (i = 0; i < length; ++i) + logClusters[i] = i; + + // first char in a run is never (treated as) a mark + int cStart = 0; + item->attributes[0].mark = FALSE; + item->attributes[0].clusterStart = TRUE; + item->attributes[0].combiningClass = 0; + if (qIsZeroWidthChar(uc[0].unicode())) { + item->attributes[0].zeroWidth = TRUE; + item->advances[0] = 0; + item->has_positioning = TRUE; + } else { + item->attributes[0].zeroWidth = FALSE; + } + + int lastCat = ::category(uc[0]); + for (i = 1; i < length; ++i) { + int cat = ::category(uc[i]); + if (qIsZeroWidthChar(uc[i].unicode())) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = TRUE; + item->attributes[i].zeroWidth = TRUE; + item->attributes[i].combiningClass = 0; + cStart = i; + item->advances[i] = 0; + item->has_positioning = TRUE; + } else if (cat != TQChar::Mark_NonSpacing) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = TRUE; + item->attributes[i].combiningClass = 0; + cStart = i; + } else { + int cmb = ::combiningClass(uc[i]); + + if (cmb == 0) { + // Fix 0 combining classes + if ((uc[i].unicode() & 0xff00) == 0x0e00) { + // thai or lao + unsigned char col = uc[i].cell(); + if (col == 0x31 || + col == 0x34 || + col == 0x35 || + col == 0x36 || + col == 0x37 || + col == 0x47 || + col == 0x4c || + col == 0x4d || + col == 0x4e) { + cmb = TQChar::Combining_AboveRight; + } else if (col == 0xb1 || + col == 0xb4 || + col == 0xb5 || + col == 0xb6 || + col == 0xb7 || + col == 0xbb || + col == 0xcc || + col == 0xcd) { + cmb = TQChar::Combining_Above; + } else if (col == 0xbc) { + cmb = TQChar::Combining_Below; + } + } + } + + item->attributes[i].mark = TRUE; + item->attributes[i].clusterStart = FALSE; + item->attributes[i].combiningClass = cmb; + logClusters[i] = cStart; + item->advances[i] = 0; + item->has_positioning = TRUE; + } + + if (lastCat == TQChar::Separator_Space) + item->attributes[i-1].justification = GlyphAttributes::Space; + else if (cat != TQChar::Mark_NonSpacing) + item->attributes[i-1].justification = GlyphAttributes::Character; + else + item->attributes[i-1].justification = GlyphAttributes::NoJustification; + + lastCat = cat; + } +} + +static void heuristicSetGlyphAttributes(TQShaperItem *item) +{ + heuristicSetGlyphAttributes(item, item->string->unicode() + item->from, item->length); +} + + +static bool basic_shape(TQShaperItem *item) +{ + if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + heuristicSetGlyphAttributes(item); + qt_heuristicPosition(item); + return TRUE; +} + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Middle eastern languages +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +// Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly +// ligatures one does not want in modern Hebrew (as lam-alef ligatures). +enum { + CcmpProperty = 0x1 +}; +#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) +static const TQOpenType::Features hebrew_features[] = { + { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, + {0, 0} +}; +#endif +/* Hebrew shaping. In the non opentype case we try to use the + presentation forms specified for Hebrew. Especially for the + ligatures with Dagesh this gives much better results than we could + achieve manually. +*/ +static bool hebrew_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script == TQFont::Hebrew); + +#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) + TQOpenType *openType = item->font->openType(); + + if (openType && openType->supportsScript(item->script)) { + openType->selectScript(item->script, hebrew_features); + + if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + heuristicSetGlyphAttributes(item); + openType->shape(item); + return openType->positionAndAdd(item); + } +#endif + + enum { + Dagesh = 0x5bc, + ShinDot = 0x5c1, + SinDot = 0x5c2, + Patah = 0x5b7, + Qamats = 0x5b8, + Holam = 0x5b9, + Rafe = 0x5bf + }; + unsigned short chars[512]; + TQChar *shapedChars = item->length > 256 ? (TQChar *)::malloc(2*item->length * sizeof(TQChar)) : (TQChar *)chars; + + const TQChar *uc = item->string->unicode() + item->from; + unsigned short *logClusters = item->log_clusters; + + *shapedChars = *uc; + logClusters[0] = 0; + int slen = 1; + int cluster_start = 0; + int i; + for (i = 1; i < item->length; ++i) { + ushort base = shapedChars[slen-1].unicode(); + ushort shaped = 0; + bool invalid = FALSE; + if (uc[i].unicode() == Dagesh) { + if (base >= 0x5d0 + && base <= 0x5ea + && base != 0x5d7 + && base != 0x5dd + && base != 0x5df + && base != 0x5e2 + && base != 0x5e5) { + shaped = base - 0x5d0 + 0xfb30; + } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) { + shaped = base + 2; + } else { + invalid = TRUE; + } + } else if (uc[i].unicode() == ShinDot) { + if (base == 0x05e9) + shaped = 0xfb2a; + else if (base == 0xfb49) + shaped = 0xfb2c; + else + invalid = TRUE; + } else if (uc[i].unicode() == SinDot) { + if (base == 0x05e9) + shaped = 0xfb2b; + else if (base == 0xfb49) + shaped = 0xfb2d; + else + invalid = TRUE; + } else if (uc[i].unicode() == Patah) { + if (base == 0x5d0) + shaped = 0xfb2e; + } else if (uc[i].unicode() == Qamats) { + if (base == 0x5d0) + shaped = 0xfb2f; + } else if (uc[i].unicode() == Holam) { + if (base == 0x5d5) + shaped = 0xfb4b; + } else if (uc[i].unicode() == Rafe) { + if (base == 0x5d1) + shaped = 0xfb4c; + else if (base == 0x5db) + shaped = 0xfb4d; + else if (base == 0x5e4) + shaped = 0xfb4e; + } + + if (invalid) { + shapedChars[slen] = 0x25cc; + item->attributes[slen].clusterStart = TRUE; + item->attributes[slen].mark = FALSE; + item->attributes[slen].combiningClass = 0; + cluster_start = slen; + ++slen; + } + if (shaped) { + if (item->font->canRender((TQChar *)&shaped, 1)) { + shapedChars[slen-1] = TQChar(shaped); + } else + shaped = 0; + } + if (!shaped) { + shapedChars[slen] = uc[i]; + if (::category(uc[i]) != TQChar::Mark_NonSpacing) { + item->attributes[slen].clusterStart = TRUE; + item->attributes[slen].mark = FALSE; + item->attributes[slen].combiningClass = 0; + cluster_start = slen; + } else { + item->attributes[slen].clusterStart = FALSE; + item->attributes[slen].mark = TRUE; + item->attributes[slen].combiningClass = ::combiningClass(uc[i]); + } + ++slen; + } + logClusters[i] = cluster_start; + } + + if (item->font->stringToCMap(shapedChars, slen, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + for (i = 0; i < item->num_glyphs; ++i) { + if (item->attributes[i].mark) + item->advances[i] = 0; + } + qt_heuristicPosition(item); + + if (item->length > 256) + ::free(shapedChars); + return TRUE; +} + +// these groups correspond to the groups defined in the Unicode standard. +// Some of these groups are equal whith regards to both joining and line breaking behaviour, +// and thus have the same enum value +// +// I'm not sure the mapping of syriac to arabic enums is correct with regards to justification, but as +// I couldn't find any better document I'll hope for the best. +enum ArabicGroup { + // NonJoining + ArabicNone, + ArabicSpace, + // Transparent + Transparent, + // Causing + Center, + Kashida, + + // Arabic + // Dual + Beh, + Noon, + Meem = Noon, + Heh = Noon, + KnottedHeh = Noon, + HehGoal = Noon, + SwashKaf = Noon, + Yeh, + Hah, + Seen, + Sad = Seen, + Tah, + Kaf = Tah, + Gaf = Tah, + Lam = Tah, + Ain, + Feh = Ain, + Qaf = Ain, + // Right + Alef, + Waw, + Dal, + TehMarbuta = Dal, + Reh, + HamzaOnHehGoal, + YehWithTail = HamzaOnHehGoal, + YehBarre = HamzaOnHehGoal, + + // Syriac + // Dual + Beth = Beh, + Gamal = Ain, + Heth = Noon, + Teth = Hah, + Yudh = Noon, + Kaph = Noon, + Lamadh = Lam, + Mim = Noon, + Nun = Noon, + Semakh = Noon, + FinalSemakh = Noon, + SyriacE = Ain, + Pe = Ain, + ReversedPe = Hah, + Qaph = Noon, + Shin = Noon, + Fe = Ain, + + // Right + Alaph = Alef, + Dalath = Dal, + He = Dal, + SyriacWaw = Waw, + Zain = Alef, + YudhHe = Waw, + Sadhe = HamzaOnHehGoal, + Taw = Dal, + + // Compiler bug? Otherwise ArabicGroupsEnd would be equal to Dal + 1. + Dummy = HamzaOnHehGoal, + ArabicGroupsEnd +}; + +static const unsigned char arabic_group[0x150] = { + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + + ArabicNone, ArabicNone, Alef, Alef, + Waw, Alef, Yeh, Alef, + Beh, TehMarbuta, Beh, Beh, + Hah, Hah, Hah, Dal, + + Dal, Reh, Reh, Seen, + Seen, Sad, Sad, Tah, + Tah, Ain, Ain, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + + // 0x640 + Kashida, Feh, Qaf, Kaf, + Lam, Meem, Noon, Heh, + Waw, Yeh, Yeh, Transparent, + Transparent, Transparent, Transparent, Transparent, + + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, Transparent, Transparent, + Transparent, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, Beh, Qaf, + + Transparent, Alef, Alef, Alef, + ArabicNone, Alef, Waw, Waw, + Yeh, Beh, Beh, Beh, + Beh, Beh, Beh, Beh, + + // 0x680 + Beh, Hah, Hah, Hah, + Hah, Hah, Hah, Hah, + Dal, Dal, Dal, Dal, + Dal, Dal, Dal, Dal, + + Dal, Reh, Reh, Reh, + Reh, Reh, Reh, Reh, + Reh, Reh, Seen, Seen, + Seen, Sad, Sad, Tah, + + Ain, Feh, Feh, Feh, + Feh, Feh, Feh, Qaf, + Qaf, Gaf, SwashKaf, Gaf, + Kaf, Kaf, Kaf, Gaf, + + Gaf, Gaf, Gaf, Gaf, + Gaf, Lam, Lam, Lam, + Lam, Noon, Noon, Noon, + Noon, Noon, KnottedHeh, Hah, + + // 0x6c0 + TehMarbuta, HehGoal, HamzaOnHehGoal, HamzaOnHehGoal, + Waw, Waw, Waw, Waw, + Waw, Waw, Waw, Waw, + Yeh, YehWithTail, Yeh, Waw, + + Yeh, Yeh, YehBarre, YehBarre, + ArabicNone, TehMarbuta, Transparent, Transparent, + Transparent, Transparent, Transparent, Transparent, + Transparent, ArabicNone, ArabicNone, Transparent, + + Transparent, Transparent, Transparent, Transparent, + Transparent, ArabicNone, ArabicNone, Transparent, + Transparent, ArabicNone, Transparent, Transparent, + Transparent, Transparent, Dal, Reh, + + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, Seen, Sad, + Ain, ArabicNone, ArabicNone, KnottedHeh, + + // 0x700 + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + ArabicNone, ArabicNone, ArabicNone, ArabicNone, + + Alaph, Transparent, Beth, Gamal, + Gamal, Dalath, Dalath, He, + SyriacWaw, Zain, Heth, Teth, + Teth, Yudh, YudhHe, Kaph, + + Lamadh, Mim, Nun, Semakh, + FinalSemakh, SyriacE, Pe, ReversedPe, + Sadhe, Qaph, Dalath, Shin, + Taw, Beth, Gamal, Dalath, + + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, Transparent, Transparent, + + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, Transparent, Transparent, + Transparent, Transparent, Transparent, ArabicNone, + ArabicNone, Zain, Kaph, Fe, +}; + +static inline ArabicGroup arabicGroup(unsigned short uc) +{ + if (uc >= 0x0600 && uc < 0x750) + return (ArabicGroup) arabic_group[uc-0x600]; + else if (uc == 0x200d) + return Center; + else if (::category(uc) == TQChar::Separator_Space) + return ArabicSpace; + else + return ArabicNone; +} + + +/* + Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on + arabic). + + Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent). + transparent joining is not encoded in TQChar::joining(), but applies to all combining marks and format marks. + + Right join-causing: dual + center + Left join-causing: dual + right + center + + Rules are as follows (for a string already in visual order, as we have it here): + + R1 Transparent characters do not affect joining behaviour. + R2 A right joining character, that has a right join-causing char on the right will get form XRight + (R3 A left joining character, that has a left join-causing char on the left will get form XLeft) + Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode + R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on + the right will get form XMedial + R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left + will get form XRight + R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right + will get form XLeft + R7 Otherwise the character will get form XIsolated + + Additionally we have to do the minimal ligature support for lam-alef ligatures: + + L1 Transparent characters do not affect ligature behaviour. + L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft) + L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated) + + The state table below handles rules R1-R7. +*/ + +enum Shape { + XIsolated, + XFinal, + XInitial, + XMedial, + // intermediate state + XCausing +}; + + +enum Joining { + JNone, + JCausing, + JDual, + JRight, + JTransparent +}; + + +static const Joining joining_for_group[ArabicGroupsEnd] = { + // NonJoining + JNone, // ArabicNone + JNone, // ArabicSpace + // Transparent + JTransparent, // Transparent + // Causing + JCausing, // Center + JCausing, // Kashida + // Dual + JDual, // Beh + JDual, // Noon + JDual, // Yeh + JDual, // Hah + JDual, // Seen + JDual, // Tah + JDual, // Ain + // Right + JRight, // Alef + JRight, // Waw + JRight, // Dal + JRight, // Reh + JRight // HamzaOnHehGoal +}; + + +struct JoiningPair { + Shape form1; + Shape form2; +}; + +static const JoiningPair joining_table[5][4] = +// None, Causing, Dual, Right +{ + { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XInitial }, { XIsolated, XIsolated } }, // XIsolated + { { XFinal, XIsolated }, { XFinal, XCausing }, { XFinal, XInitial }, { XFinal, XIsolated } }, // XFinal + { { XIsolated, XIsolated }, { XInitial, XCausing }, { XInitial, XMedial }, { XInitial, XFinal } }, // XInitial + { { XFinal, XIsolated }, { XMedial, XCausing }, { XMedial, XMedial }, { XMedial, XFinal } }, // XMedial + { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XMedial }, { XIsolated, XFinal } }, // XCausing +}; + + +/* +According to http://www.microsoft.com/middleeast/Arabicdev/IE6/KBase.asp + +1. Find the priority of the connecting opportunities in each word +2. Add expansion at the highest priority connection opportunity +3. If more than one connection opportunity have the same highest value, + use the opportunity closest to the end of the word. + +Following is a chart that provides the priority for connection +opportunities and where expansion occurs. The character group names +are those in table 6.6 of the UNICODE 2.0 book. + + +PrioritY Glyph Condition Kashida Location + +Arabic_Kashida User inserted Kashida The user entered a Kashida in a position. After the user + (Shift+j or Shift+[E with hat]) Thus, it is the highest priority to insert an inserted kashida + automatic kashida. + +Arabic_Seen Seen, Sad Connecting to the next character. After the character. + (Initial or medial form). + +Arabic_HaaDal Teh Marbutah, Haa, Dal Connecting to previous character. Before the final form + of these characters. + +Arabic_Alef Alef, Tah, Lam, Connecting to previous character. Before the final form + Kaf and Gaf of these characters. + +Arabic_BaRa Reh, Yeh Connected to medial Beh Before preceding medial Baa + +Arabic_Waw Waw, Ain, Qaf, Feh Connecting to previous character. Before the final form of + these characters. + +Arabic_Normal Other connecting Connecting to previous character. Before the final form + characters of these characters. + + + +This seems to imply that we have at most one kashida point per arabic word. + +*/ + +struct TQArabicProperties { + unsigned char shape; + unsigned char justification; +}; + + +static void getArabicProperties(const unsigned short *chars, int len, TQArabicProperties *properties) +{ +// tqDebug("arabicSyriacOpenTypeShape: properties:"); + int lastPos = 0; + int lastGroup = ArabicNone; + + ArabicGroup group = arabicGroup(chars[0]); + Joining j = joining_for_group[group]; + Shape shape = joining_table[XIsolated][j].form2; + properties[0].justification = GlyphAttributes::NoJustification; + + for (int i = 1; i < len; ++i) { + // #### fix handling for spaces and punktuation + properties[i].justification = GlyphAttributes::NoJustification; + + group = arabicGroup(chars[i]); + j = joining_for_group[group]; + + if (j == JTransparent) { + properties[i].shape = XIsolated; + continue; + } + + properties[lastPos].shape = joining_table[shape][j].form1; + shape = joining_table[shape][j].form2; + + switch(lastGroup) { + case Seen: + if (properties[lastPos].shape == XInitial || properties[lastPos].shape == XMedial) + properties[i-1].justification = GlyphAttributes::Arabic_Seen; + break; + case Hah: + if (properties[lastPos].shape == XFinal) + properties[lastPos-1].justification = GlyphAttributes::Arabic_HaaDal; + break; + case Alef: + if (properties[lastPos].shape == XFinal) + properties[lastPos-1].justification = GlyphAttributes::Arabic_Alef; + break; + case Ain: + if (properties[lastPos].shape == XFinal) + properties[lastPos-1].justification = GlyphAttributes::Arabic_Waw; + break; + case Noon: + if (properties[lastPos].shape == XFinal) + properties[lastPos-1].justification = GlyphAttributes::Arabic_Normal; + break; + case ArabicNone: + break; + + default: + Q_ASSERT(FALSE); + } + + lastGroup = ArabicNone; + + switch(group) { + case ArabicNone: + case Transparent: + // ### Center should probably be treated as transparent when it comes to justification. + case Center: + break; + case ArabicSpace: + properties[i].justification = GlyphAttributes::Arabic_Space; + break; + case Kashida: + properties[i].justification = GlyphAttributes::Arabic_Kashida; + break; + case Seen: + lastGroup = Seen; + break; + + case Hah: + case Dal: + lastGroup = Hah; + break; + + case Alef: + case Tah: + lastGroup = Alef; + break; + + case Yeh: + case Reh: + if (properties[lastPos].shape == XMedial && arabicGroup(chars[lastPos]) == Beh) + properties[lastPos-1].justification = GlyphAttributes::Arabic_BaRa; + break; + + case Ain: + case Waw: + lastGroup = Ain; + break; + + case Noon: + case Beh: + case HamzaOnHehGoal: + lastGroup = Noon; + break; + case ArabicGroupsEnd: + Q_ASSERT(FALSE); + } + + lastPos = i; + } + properties[lastPos].shape = joining_table[shape][JNone].form1; + + +// for (int i = 0; i < len; ++i) +// tqDebug("arabic properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification); +} + + + + + + +// The unicode to unicode shaping codec. +// does only presentation forms B at the moment, but that should be enough for +// simple display +static const ushort arabicUnicodeMapping[256][2] = { + // base of shaped forms, and number-1 of them (0 for non shaping, + // 1 for right binding and 3 for dual binding + + // These are just the glyphs available in Unicode, + // some characters are in R class, but have no glyphs in Unicode. + + { 0x0600, 0 }, // 0x0600 + { 0x0601, 0 }, // 0x0601 + { 0x0602, 0 }, // 0x0602 + { 0x0603, 0 }, // 0x0603 + { 0x0604, 0 }, // 0x0604 + { 0x0605, 0 }, // 0x0605 + { 0x0606, 0 }, // 0x0606 + { 0x0607, 0 }, // 0x0607 + { 0x0608, 0 }, // 0x0608 + { 0x0609, 0 }, // 0x0609 + { 0x060A, 0 }, // 0x060A + { 0x060B, 0 }, // 0x060B + { 0x060C, 0 }, // 0x060C + { 0x060D, 0 }, // 0x060D + { 0x060E, 0 }, // 0x060E + { 0x060F, 0 }, // 0x060F + + { 0x0610, 0 }, // 0x0610 + { 0x0611, 0 }, // 0x0611 + { 0x0612, 0 }, // 0x0612 + { 0x0613, 0 }, // 0x0613 + { 0x0614, 0 }, // 0x0614 + { 0x0615, 0 }, // 0x0615 + { 0x0616, 0 }, // 0x0616 + { 0x0617, 0 }, // 0x0617 + { 0x0618, 0 }, // 0x0618 + { 0x0619, 0 }, // 0x0619 + { 0x061A, 0 }, // 0x061A + { 0x061B, 0 }, // 0x061B + { 0x061C, 0 }, // 0x061C + { 0x061D, 0 }, // 0x061D + { 0x061E, 0 }, // 0x061E + { 0x061F, 0 }, // 0x061F + + { 0x0620, 0 }, // 0x0620 + { 0xFE80, 0 }, // 0x0621 HAMZA + { 0xFE81, 1 }, // 0x0622 R ALEF WITH MADDA ABOVE + { 0xFE83, 1 }, // 0x0623 R ALEF WITH HAMZA ABOVE + { 0xFE85, 1 }, // 0x0624 R WAW WITH HAMZA ABOVE + { 0xFE87, 1 }, // 0x0625 R ALEF WITH HAMZA BELOW + { 0xFE89, 3 }, // 0x0626 D YEH WITH HAMZA ABOVE + { 0xFE8D, 1 }, // 0x0627 R ALEF + { 0xFE8F, 3 }, // 0x0628 D BEH + { 0xFE93, 1 }, // 0x0629 R TEH MARBUTA + { 0xFE95, 3 }, // 0x062A D TEH + { 0xFE99, 3 }, // 0x062B D THEH + { 0xFE9D, 3 }, // 0x062C D JEEM + { 0xFEA1, 3 }, // 0x062D D HAH + { 0xFEA5, 3 }, // 0x062E D KHAH + { 0xFEA9, 1 }, // 0x062F R DAL + + { 0xFEAB, 1 }, // 0x0630 R THAL + { 0xFEAD, 1 }, // 0x0631 R REH + { 0xFEAF, 1 }, // 0x0632 R ZAIN + { 0xFEB1, 3 }, // 0x0633 D SEEN + { 0xFEB5, 3 }, // 0x0634 D SHEEN + { 0xFEB9, 3 }, // 0x0635 D SAD + { 0xFEBD, 3 }, // 0x0636 D DAD + { 0xFEC1, 3 }, // 0x0637 D TAH + { 0xFEC5, 3 }, // 0x0638 D ZAH + { 0xFEC9, 3 }, // 0x0639 D AIN + { 0xFECD, 3 }, // 0x063A D GHAIN + { 0x063B, 0 }, // 0x063B + { 0x063C, 0 }, // 0x063C + { 0x063D, 0 }, // 0x063D + { 0x063E, 0 }, // 0x063E + { 0x063F, 0 }, // 0x063F + + { 0x0640, 0 }, // 0x0640 C TATWEEL // ### Join Causing, only one glyph + { 0xFED1, 3 }, // 0x0641 D FEH + { 0xFED5, 3 }, // 0x0642 D TQAF + { 0xFED9, 3 }, // 0x0643 D KAF + { 0xFEDD, 3 }, // 0x0644 D LAM + { 0xFEE1, 3 }, // 0x0645 D MEEM + { 0xFEE5, 3 }, // 0x0646 D NOON + { 0xFEE9, 3 }, // 0x0647 D HEH + { 0xFEED, 1 }, // 0x0648 R WAW + { 0x0649, 3 }, // 0x0649 ALEF MAKSURA // ### Dual, glyphs not consecutive, handle in code. + { 0xFEF1, 3 }, // 0x064A D YEH + { 0x064B, 0 }, // 0x064B + { 0x064C, 0 }, // 0x064C + { 0x064D, 0 }, // 0x064D + { 0x064E, 0 }, // 0x064E + { 0x064F, 0 }, // 0x064F + + { 0x0650, 0 }, // 0x0650 + { 0x0651, 0 }, // 0x0651 + { 0x0652, 0 }, // 0x0652 + { 0x0653, 0 }, // 0x0653 + { 0x0654, 0 }, // 0x0654 + { 0x0655, 0 }, // 0x0655 + { 0x0656, 0 }, // 0x0656 + { 0x0657, 0 }, // 0x0657 + { 0x0658, 0 }, // 0x0658 + { 0x0659, 0 }, // 0x0659 + { 0x065A, 0 }, // 0x065A + { 0x065B, 0 }, // 0x065B + { 0x065C, 0 }, // 0x065C + { 0x065D, 0 }, // 0x065D + { 0x065E, 0 }, // 0x065E + { 0x065F, 0 }, // 0x065F + + { 0x0660, 0 }, // 0x0660 + { 0x0661, 0 }, // 0x0661 + { 0x0662, 0 }, // 0x0662 + { 0x0663, 0 }, // 0x0663 + { 0x0664, 0 }, // 0x0664 + { 0x0665, 0 }, // 0x0665 + { 0x0666, 0 }, // 0x0666 + { 0x0667, 0 }, // 0x0667 + { 0x0668, 0 }, // 0x0668 + { 0x0669, 0 }, // 0x0669 + { 0x066A, 0 }, // 0x066A + { 0x066B, 0 }, // 0x066B + { 0x066C, 0 }, // 0x066C + { 0x066D, 0 }, // 0x066D + { 0x066E, 0 }, // 0x066E + { 0x066F, 0 }, // 0x066F + + { 0x0670, 0 }, // 0x0670 + { 0xFB50, 1 }, // 0x0671 R ALEF WASLA + { 0x0672, 0 }, // 0x0672 + { 0x0673, 0 }, // 0x0673 + { 0x0674, 0 }, // 0x0674 + { 0x0675, 0 }, // 0x0675 + { 0x0676, 0 }, // 0x0676 + { 0x0677, 0 }, // 0x0677 + { 0x0678, 0 }, // 0x0678 + { 0xFB66, 3 }, // 0x0679 D TTEH + { 0xFB5E, 3 }, // 0x067A D TTEHEH + { 0xFB52, 3 }, // 0x067B D BEEH + { 0x067C, 0 }, // 0x067C + { 0x067D, 0 }, // 0x067D + { 0xFB56, 3 }, // 0x067E D PEH + { 0xFB62, 3 }, // 0x067F D TEHEH + + { 0xFB5A, 3 }, // 0x0680 D BEHEH + { 0x0681, 0 }, // 0x0681 + { 0x0682, 0 }, // 0x0682 + { 0xFB76, 3 }, // 0x0683 D NYEH + { 0xFB72, 3 }, // 0x0684 D DYEH + { 0x0685, 0 }, // 0x0685 + { 0xFB7A, 3 }, // 0x0686 D TCHEH + { 0xFB7E, 3 }, // 0x0687 D TCHEHEH + { 0xFB88, 1 }, // 0x0688 R DDAL + { 0x0689, 0 }, // 0x0689 + { 0x068A, 0 }, // 0x068A + { 0x068B, 0 }, // 0x068B + { 0xFB84, 1 }, // 0x068C R DAHAL + { 0xFB82, 1 }, // 0x068D R DDAHAL + { 0xFB86, 1 }, // 0x068E R DUL + { 0x068F, 0 }, // 0x068F + + { 0x0690, 0 }, // 0x0690 + { 0xFB8C, 1 }, // 0x0691 R RREH + { 0x0692, 0 }, // 0x0692 + { 0x0693, 0 }, // 0x0693 + { 0x0694, 0 }, // 0x0694 + { 0x0695, 0 }, // 0x0695 + { 0x0696, 0 }, // 0x0696 + { 0x0697, 0 }, // 0x0697 + { 0xFB8A, 1 }, // 0x0698 R JEH + { 0x0699, 0 }, // 0x0699 + { 0x069A, 0 }, // 0x069A + { 0x069B, 0 }, // 0x069B + { 0x069C, 0 }, // 0x069C + { 0x069D, 0 }, // 0x069D + { 0x069E, 0 }, // 0x069E + { 0x069F, 0 }, // 0x069F + + { 0x06A0, 0 }, // 0x06A0 + { 0x06A1, 0 }, // 0x06A1 + { 0x06A2, 0 }, // 0x06A2 + { 0x06A3, 0 }, // 0x06A3 + { 0xFB6A, 3 }, // 0x06A4 D VEH + { 0x06A5, 0 }, // 0x06A5 + { 0xFB6E, 3 }, // 0x06A6 D PEHEH + { 0x06A7, 0 }, // 0x06A7 + { 0x06A8, 0 }, // 0x06A8 + { 0xFB8E, 3 }, // 0x06A9 D KEHEH + { 0x06AA, 0 }, // 0x06AA + { 0x06AB, 0 }, // 0x06AB + { 0x06AC, 0 }, // 0x06AC + { 0xFBD3, 3 }, // 0x06AD D NG + { 0x06AE, 0 }, // 0x06AE + { 0xFB92, 3 }, // 0x06AF D GAF + + { 0x06B0, 0 }, // 0x06B0 + { 0xFB9A, 3 }, // 0x06B1 D NGOEH + { 0x06B2, 0 }, // 0x06B2 + { 0xFB96, 3 }, // 0x06B3 D GUEH + { 0x06B4, 0 }, // 0x06B4 + { 0x06B5, 0 }, // 0x06B5 + { 0x06B6, 0 }, // 0x06B6 + { 0x06B7, 0 }, // 0x06B7 + { 0x06B8, 0 }, // 0x06B8 + { 0x06B9, 0 }, // 0x06B9 + { 0xFB9E, 1 }, // 0x06BA R NOON GHUNNA + { 0xFBA0, 3 }, // 0x06BB D RNOON + { 0x06BC, 0 }, // 0x06BC + { 0x06BD, 0 }, // 0x06BD + { 0xFBAA, 3 }, // 0x06BE D HEH DOACHASHMEE + { 0x06BF, 0 }, // 0x06BF + + { 0xFBA4, 1 }, // 0x06C0 R HEH WITH YEH ABOVE + { 0xFBA6, 3 }, // 0x06C1 D HEH GOAL + { 0x06C2, 0 }, // 0x06C2 + { 0x06C3, 0 }, // 0x06C3 + { 0x06C4, 0 }, // 0x06C4 + { 0xFBE0, 1 }, // 0x06C5 R KIRGHIZ OE + { 0xFBD9, 1 }, // 0x06C6 R OE + { 0xFBD7, 1 }, // 0x06C7 R U + { 0xFBDB, 1 }, // 0x06C8 R YU + { 0xFBE2, 1 }, // 0x06C9 R KIRGHIZ YU + { 0x06CA, 0 }, // 0x06CA + { 0xFBDE, 1 }, // 0x06CB R VE + { 0xFBFC, 3 }, // 0x06CC D FARSI YEH + { 0x06CD, 0 }, // 0x06CD + { 0x06CE, 0 }, // 0x06CE + { 0x06CF, 0 }, // 0x06CF + + { 0xFBE4, 3 }, // 0x06D0 D E + { 0x06D1, 0 }, // 0x06D1 + { 0xFBAE, 1 }, // 0x06D2 R YEH BARREE + { 0xFBB0, 1 }, // 0x06D3 R YEH BARREE WITH HAMZA ABOVE + { 0x06D4, 0 }, // 0x06D4 + { 0x06D5, 0 }, // 0x06D5 + { 0x06D6, 0 }, // 0x06D6 + { 0x06D7, 0 }, // 0x06D7 + { 0x06D8, 0 }, // 0x06D8 + { 0x06D9, 0 }, // 0x06D9 + { 0x06DA, 0 }, // 0x06DA + { 0x06DB, 0 }, // 0x06DB + { 0x06DC, 0 }, // 0x06DC + { 0x06DD, 0 }, // 0x06DD + { 0x06DE, 0 }, // 0x06DE + { 0x06DF, 0 }, // 0x06DF + + { 0x06E0, 0 }, // 0x06E0 + { 0x06E1, 0 }, // 0x06E1 + { 0x06E2, 0 }, // 0x06E2 + { 0x06E3, 0 }, // 0x06E3 + { 0x06E4, 0 }, // 0x06E4 + { 0x06E5, 0 }, // 0x06E5 + { 0x06E6, 0 }, // 0x06E6 + { 0x06E7, 0 }, // 0x06E7 + { 0x06E8, 0 }, // 0x06E8 + { 0x06E9, 0 }, // 0x06E9 + { 0x06EA, 0 }, // 0x06EA + { 0x06EB, 0 }, // 0x06EB + { 0x06EC, 0 }, // 0x06EC + { 0x06ED, 0 }, // 0x06ED + { 0x06EE, 0 }, // 0x06EE + { 0x06EF, 0 }, // 0x06EF + + { 0x06F0, 0 }, // 0x06F0 + { 0x06F1, 0 }, // 0x06F1 + { 0x06F2, 0 }, // 0x06F2 + { 0x06F3, 0 }, // 0x06F3 + { 0x06F4, 0 }, // 0x06F4 + { 0x06F5, 0 }, // 0x06F5 + { 0x06F6, 0 }, // 0x06F6 + { 0x06F7, 0 }, // 0x06F7 + { 0x06F8, 0 }, // 0x06F8 + { 0x06F9, 0 }, // 0x06F9 + { 0x06FA, 0 }, // 0x06FA + { 0x06FB, 0 }, // 0x06FB + { 0x06FC, 0 }, // 0x06FC + { 0x06FD, 0 }, // 0x06FD + { 0x06FE, 0 }, // 0x06FE + { 0x06FF, 0 } // 0x06FF +}; + +// the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, this table does +static const ushort alefMaksura[4] = {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}; + +// this is a bit tricky. Alef always binds to the right, so the second parameter descibing the shape +// of the lam can be either initial of medial. So initial maps to the isolated form of the ligature, +// medial to the final form +static const ushort arabicUnicodeLamAlefMapping[6][4] = { + { 0xfffd, 0xfffd, 0xfef5, 0xfef6 }, // 0x622 R Alef with Madda above + { 0xfffd, 0xfffd, 0xfef7, 0xfef8 }, // 0x623 R Alef with Hamza above + { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x624 // Just to fill the table ;-) + { 0xfffd, 0xfffd, 0xfef9, 0xfefa }, // 0x625 R Alef with Hamza below + { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x626 // Just to fill the table ;-) + { 0xfffd, 0xfffd, 0xfefb, 0xfefc } // 0x627 R Alef +}; + +static inline int getShape(uchar cell, int shape) +{ + // the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, handle this here + uint ch = (cell != 0x49) + ? (shape ? arabicUnicodeMapping[cell][0] + shape : 0x600+cell) + : alefMaksura[shape] ; + return ch; +} + + +/* + Two small helper functions for arabic shaping. +*/ +static inline const TQChar prevChar(const TQString *str, int pos) +{ + //tqDebug("leftChar: pos=%d", pos); + pos--; + const TQChar *ch = str->unicode() + pos; + while(pos > -1) { + if(::category(*ch) != TQChar::Mark_NonSpacing) + return *ch; + pos--; + ch--; + } + return TQChar::replacement; +} + +static inline const TQChar nextChar(const TQString *str, int pos) +{ + pos++; + int len = str->length(); + const TQChar *ch = str->unicode() + pos; + while(pos < len) { + //tqDebug("rightChar: %d isLetter=%d, joining=%d", pos, ch.isLetter(), ch.joining()); + if(::category(*ch) != TQChar::Mark_NonSpacing) + return *ch; + // assume it's a transparent char, this might not be 100% correct + pos++; + ch++; + } + return TQChar::replacement; +} + + +static void shapedString(const TQString *uc, int from, int len, TQChar *shapeBuffer, int *shapedLength, + bool reverse, GlyphAttributes *attributes, unsigned short *logClusters) +{ + Q_ASSERT((int)uc->length() >= from + len); + + if(len == 0) { + *shapedLength = 0; + return; + } + + TQVarLengthArray props(len + 2); + TQArabicProperties *properties = props.data(); + int f = from; + int l = len; + if (from > 0) { + --f; + ++l; + ++properties; + } + if (f + l < (int)uc->length()) { + ++l; + } + getArabicProperties((const unsigned short *)(uc->unicode()+f), l, props.data()); + + const TQChar *ch = uc->unicode() + from; + TQChar *data = shapeBuffer; + int clusterStart = 0; + + for (int i = 0; i < len; i++) { + uchar r = ch->row(); + int gpos = data - shapeBuffer; + + if (r != 0x06) { + if (r == 0x20) { + uchar c = ch->cell(); + if (c == 0x0c || c == 0x0d) + // remove ZWJ and ZWNJ + goto skip; + } + if (reverse) + *data = mirroredChar(*ch); + else + *data = *ch; + } else { + uchar c = ch->cell(); + int pos = i + from; + int shape = properties[i].shape; +// tqDebug("mapping U+%x to shape %d glyph=0x%x", ch->unicode(), shape, getShape(c, shape)); + // take care of lam-alef ligatures (lam right of alef) + ushort map; + switch (c) { + case 0x44: { // lam + const TQChar pch = nextChar(uc, pos); + if (pch.row() == 0x06) { + switch (pch.cell()) { + case 0x22: + case 0x23: + case 0x25: + case 0x27: +// tqDebug(" lam of lam-alef ligature"); + map = arabicUnicodeLamAlefMapping[pch.cell() - 0x22][shape]; + goto next; + default: + break; + } + } + break; + } + case 0x22: // alef with madda + case 0x23: // alef with hamza above + case 0x25: // alef with hamza below + case 0x27: // alef + if (prevChar(uc, pos).unicode() == 0x0644) { + // have a lam alef ligature + //tqDebug(" alef of lam-alef ligature"); + goto skip; + } + default: + break; + } + map = getShape(c, shape); + next: + *data = map; + } + // ##### Fixme + //attributes[gpos].zeroWidth = zeroWidth; + if (::category(*ch) == TQChar::Mark_NonSpacing) { + attributes[gpos].mark = TRUE; +// tqDebug("glyph %d (char %d) is mark!", gpos, i); + } else { + attributes[gpos].mark = FALSE; + clusterStart = data - shapeBuffer; + } + attributes[gpos].clusterStart = !attributes[gpos].mark; + attributes[gpos].combiningClass = combiningClass(*ch); + attributes[gpos].justification = properties[i].justification; +// tqDebug("data[%d] = %x (from %x)", gpos, (uint)data->unicode(), ch->unicode()); + data++; + skip: + ch++; + logClusters[i] = clusterStart; + } + *shapedLength = data - shapeBuffer; +} + +#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) + +enum { + InitProperty = 0x2, + IsolProperty = 0x4, + FinaProperty = 0x8, + MediProperty = 0x10, + RligProperty = 0x20, + CaltProperty = 0x40, + LigaProperty = 0x80, + DligProperty = 0x100, + CswhProperty = 0x200, + MsetProperty = 0x400 +}; + +static const TQOpenType::Features arabic_features[] = { + { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, + { FT_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty }, + { FT_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty }, + { FT_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty }, + { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, + { FT_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty }, + { FT_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty }, + { FT_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty }, + { FT_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty }, + { FT_MAKE_TAG('c', 's', 'w', 'h'), CswhProperty }, + // mset is used in old Win95 fonts that don't have a 'mark' positioning table. + { FT_MAKE_TAG('m', 's', 'e', 't'), MsetProperty }, + {0, 0} +}; + +static const TQOpenType::Features syriac_features[] = { + { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, + { FT_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty }, + { FT_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty }, + { FT_MAKE_TAG('f', 'i', 'n', '2'), FinaProperty }, + { FT_MAKE_TAG('f', 'i', 'n', '3'), FinaProperty }, + { FT_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty }, + { FT_MAKE_TAG('m', 'e', 'd', '2'), MediProperty }, + { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, + { FT_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty }, + { FT_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty }, + { FT_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty }, + { FT_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty }, + {0, 0} +}; + +static bool arabicSyriacOpenTypeShape(TQOpenType *openType, TQShaperItem *item, bool *ot_ok) +{ + *ot_ok = true; + + openType->selectScript(item->script, item->script == TQFont::Arabic ? arabic_features : syriac_features); + int nglyphs = item->num_glyphs; + if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + heuristicSetGlyphAttributes(item); + + unsigned short *logClusters = item->log_clusters; + const unsigned short *uc = (const unsigned short *)item->string->unicode() + item->from; + + TQVarLengthArray props(item->length+2); + TQArabicProperties *properties = props.data(); + int f = 0; + int l = item->length; + if (item->from > 0) { + --f; + ++l; + ++properties; + } + if (f + l < (int)item->string->length()) { + ++l; + } + getArabicProperties((const unsigned short *)(uc+f), l, props.data()); + + TQVarLengthArray apply(item->num_glyphs); + + + // Hack to remove ZWJ and ZWNJ from rendered output. + int j = 0; + for (int i = 0; i < item->num_glyphs; i++) { + if (uc[i] == 0x200c || uc[i] == 0x200d) + continue; + item->glyphs[j] = item->glyphs[i]; + item->attributes[j] = item->attributes[i]; + item->advances[j] = item->advances[i]; + item->offsets[j] = item->offsets[i]; + properties[j] = properties[i]; + item->attributes[j].justification = properties[i].justification; + logClusters[i] = logClusters[j]; + ++j; + } + item->num_glyphs = j; + + for (int i = 0; i < item->num_glyphs; i++) { + apply[i] = 0; + + if (properties[i].shape == XIsolated) + apply[i] |= MediProperty|FinaProperty|InitProperty; + else if (properties[i].shape == XMedial) + apply[i] |= IsolProperty|FinaProperty|InitProperty; + else if (properties[i].shape == XFinal) + apply[i] |= IsolProperty|MediProperty|InitProperty; + else if (properties[i].shape == XInitial) + apply[i] |= IsolProperty|MediProperty|FinaProperty; + } + + if (!openType->shape(item, apply.data())) { + *ot_ok = false; + return false; + } + item->num_glyphs = nglyphs; + return openType->positionAndAdd(item); +} + +#endif + +// #### stil missing: identify invalid character combinations +static bool arabic_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script == TQFont::Arabic); + +#if defined(TQ_WS_X11) && !defined(TQT_NO_XFTFREETYPE) + TQOpenType *openType = item->font->openType(); + + if (openType && openType->supportsScript(TQFont::Arabic)) { + bool ot_ok; + if (arabicSyriacOpenTypeShape(openType, item, &ot_ok)) + return true; + if (ot_ok) + return false; + // fall through to the non OT code + } +#endif + + TQVarLengthArray shapedChars(item->length); + + int slen; + shapedString(item->string, item->from, item->length, (TQChar *)shapedChars.data(), &slen, + item->flags & TQTextEngine::RightToLeft, + item->attributes, item->log_clusters); + + if (item->font->stringToCMap((TQChar *)shapedChars.data(), slen, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + for (int i = 0; i < slen; ++i) + if (item->attributes[i].mark) + item->advances[i] = 0; + qt_heuristicPosition(item); + return TRUE; +} + +#if defined(TQ_WS_X11) +# include "tqscriptengine_x11.cpp" +#elif defined(TQ_WS_WIN) +# include "tqscriptengine_win.cpp" +#elif defined(TQ_WS_MAC) +# include "tqscriptengine_mac.cpp" +#endif diff --git a/src/kernel/tqscriptengine_p.h b/src/kernel/tqscriptengine_p.h new file mode 100644 index 000000000..77dd87b96 --- /dev/null +++ b/src/kernel/tqscriptengine_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the $MODULE$ of the TQt Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +****************************************************************************/ + +#ifndef TQSCRIPTENGINE_P_H +#define TQSCRIPTENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "tqtextengine_p.h" + +class TQString; +struct TQCharAttributes; + +struct TQShaperItem { + int script; + const TQString *string; + int from; + int length; + TQFontEngine *font; + glyph_t *glyphs; + advance_t *advances; + qoffset_t *offsets; + GlyphAttributes *attributes; + int num_glyphs; // in: available glyphs out: glyphs used/needed + unsigned short *log_clusters; + int flags; + bool has_positioning; +}; + +// return true if ok. +typedef bool (*ShapeFunction)(TQShaperItem *item); +typedef void (*AttributeFunction)(int script, const TQString &, int, int, TQCharAttributes *); + +struct q_scriptEngine { + ShapeFunction shape; + AttributeFunction charAttributes; +}; + +extern const q_scriptEngine scriptEngines[]; + +#endif // TQSCRIPTENGINE_P_H diff --git a/src/kernel/tqscriptengine_x11.cpp b/src/kernel/tqscriptengine_x11.cpp new file mode 100644 index 000000000..5d22fdf49 --- /dev/null +++ b/src/kernel/tqscriptengine_x11.cpp @@ -0,0 +1,3744 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +// ------------------------------------------------------------------------------------------------------------------ +// +// Continuation of middle eastern languages +// +// ------------------------------------------------------------------------------------------------------------------ + +// #### stil missing: identify invalid character combinations +static bool syriac_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script == TQFont::Syriac); + +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + if (openType && openType->supportsScript(TQFont::Syriac)) { + bool ot_ok; + if (arabicSyriacOpenTypeShape(openType, item, &ot_ok)) + return true; + if (ot_ok) + return false; + // fall through to the non OT code + } +#endif + return basic_shape(item); +} + + +static bool thaana_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script == TQFont::Thaana); + +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + + if (openType && openType->supportsScript(item->script)) { + openType->selectScript(TQFont::Thaana); + if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + heuristicSetGlyphAttributes(item); + openType->shape(item); + return openType->positionAndAdd(item); + } +#endif + return basic_shape(item); +} + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Indic languages +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +enum Form { + Invalid = 0x0, + Unknown = Invalid, + Consonant, + Nukta, + Halant, + Matra, + VowelMark, + StressMark, + IndependentVowel, + LengthMark, + Control, + Other +}; + +static const unsigned char indicForms[0xe00-0x900] = { + // Devangari + Invalid, VowelMark, VowelMark, VowelMark, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Nukta, Other, Matra, Matra, + + Matra, Matra, Matra, Matra, + Matra, Matra, Matra, Matra, + Matra, Matra, Matra, Matra, + Matra, Halant, Unknown, Unknown, + + Other, StressMark, StressMark, StressMark, + StressMark, Unknown, Unknown, Unknown, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + IndependentVowel, IndependentVowel, VowelMark, VowelMark, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Consonant, + Consonant, Consonant /* ??? */, Consonant, Consonant, + + // Bengali + Invalid, VowelMark, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, Invalid, Invalid, IndependentVowel, + + IndependentVowel, Invalid, Invalid, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Invalid, Consonant, Invalid, + Invalid, Invalid, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Nukta, Other, Matra, Matra, + + Matra, Matra, Matra, Matra, + Matra, Invalid, Invalid, Matra, + Matra, Invalid, Invalid, Matra, + Matra, Halant, Consonant, Unknown, + + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, VowelMark, + Invalid, Invalid, Invalid, Invalid, + Consonant, Consonant, Invalid, Consonant, + + IndependentVowel, IndependentVowel, VowelMark, VowelMark, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Consonant, Consonant, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Gurmukhi + Invalid, VowelMark, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, Invalid, + Invalid, Invalid, Invalid, IndependentVowel, + + IndependentVowel, Invalid, Invalid, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Invalid, Consonant, Consonant, + Invalid, Consonant, Consonant, Invalid, + Consonant, Consonant, Unknown, Unknown, + Nukta, Other, Matra, Matra, + + Matra, Matra, Matra, Invalid, + Invalid, Invalid, Invalid, Matra, + Matra, Invalid, Invalid, Matra, + Matra, Halant, Unknown, Unknown, + + Invalid, Invalid, Invalid, Invalid, + Invalid, Unknown, Unknown, Unknown, + Invalid, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Invalid, + + Other, Other, Invalid, Invalid, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + StressMark, StressMark, Consonant, Consonant, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Gujarati + Invalid, VowelMark, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, Invalid, IndependentVowel, + + IndependentVowel, IndependentVowel, Invalid, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Invalid, Consonant, Consonant, + Invalid, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Nukta, Other, Matra, Matra, + + Matra, Matra, Matra, Matra, + Matra, Matra, Invalid, Matra, + Matra, Matra, Invalid, Matra, + Matra, Halant, Unknown, Unknown, + + Other, Unknown, Unknown, Unknown, + Unknown, Unknown, Unknown, Unknown, + Unknown, Unknown, Unknown, Unknown, + Unknown, Unknown, Unknown, Unknown, + + IndependentVowel, IndependentVowel, VowelMark, VowelMark, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Oriya + Invalid, VowelMark, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, Invalid, Invalid, IndependentVowel, + + IndependentVowel, Invalid, Invalid, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Invalid, Consonant, Consonant, + Invalid, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Nukta, Other, Matra, Matra, + + Matra, Matra, Matra, Matra, + Invalid, Invalid, Invalid, Matra, + Matra, Invalid, Invalid, Matra, + Matra, Halant, Unknown, Unknown, + + Other, Invalid, Invalid, Invalid, + Invalid, Unknown, LengthMark, LengthMark, + Invalid, Invalid, Invalid, Invalid, + Consonant, Consonant, Invalid, Consonant, + + IndependentVowel, IndependentVowel, Invalid, Invalid, + Invalid, Invalid, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Consonant, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + //Tamil + Invalid, Invalid, VowelMark, Other, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, Invalid, + Invalid, Invalid, IndependentVowel, IndependentVowel, + + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + IndependentVowel, Consonant, Invalid, Invalid, + Invalid, Consonant, Consonant, Invalid, + Consonant, Invalid, Consonant, Consonant, + + Invalid, Invalid, Invalid, Consonant, + Consonant, Invalid, Invalid, Invalid, + Consonant, Consonant, Consonant, Invalid, + Invalid, Invalid, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Invalid, Invalid, Matra, Matra, + + Matra, Matra, Matra, Invalid, + Invalid, Invalid, Matra, Matra, + Matra, Invalid, Matra, Matra, + Matra, Halant, Invalid, Invalid, + + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, LengthMark, + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, Invalid, + + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Telugu + Invalid, VowelMark, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Invalid, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Invalid, Invalid, Matra, Matra, + + Matra, Matra, Matra, Matra, + Matra, Invalid, Matra, Matra, + Matra, Invalid, Matra, Matra, + Matra, Halant, Invalid, Invalid, + + Invalid, Invalid, Invalid, Invalid, + Invalid, LengthMark, Matra, Invalid, + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, Invalid, + + IndependentVowel, IndependentVowel, Invalid, Invalid, + Invalid, Invalid, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Kannada + Invalid, Invalid, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Invalid, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Nukta, Other, Matra, Matra, + + Matra, Matra, Matra, Matra, + Matra, Invalid, Matra, Matra, + Matra, Invalid, Matra, Matra, + Matra, Halant, Invalid, Invalid, + + Invalid, Invalid, Invalid, Invalid, + Invalid, LengthMark, LengthMark, Invalid, + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Consonant, Invalid, + + IndependentVowel, IndependentVowel, VowelMark, VowelMark, + Invalid, Invalid, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Malayalam + Invalid, Invalid, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + + IndependentVowel, Invalid, IndependentVowel, IndependentVowel, + IndependentVowel, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Unknown, Unknown, + Invalid, Invalid, Matra, Matra, + + Matra, Matra, Matra, Matra, + Invalid, Invalid, Matra, Matra, + Matra, Invalid, Matra, Matra, + Matra, Halant, Invalid, Invalid, + + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, LengthMark, + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, Invalid, + + IndependentVowel, IndependentVowel, Invalid, Invalid, + Invalid, Invalid, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, + + // Sinhala + Invalid, Invalid, VowelMark, VowelMark, + Invalid, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + + IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel, + IndependentVowel, IndependentVowel, IndependentVowel, Invalid, + Invalid, Invalid, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + + Consonant, Consonant, Invalid, Consonant, + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Consonant, + Invalid, Consonant, Invalid, Invalid, + + Consonant, Consonant, Consonant, Consonant, + Consonant, Consonant, Consonant, Invalid, + Invalid, Invalid, Halant, Invalid, + Invalid, Invalid, Invalid, Matra, + + Matra, Matra, Matra, Matra, + Matra, Invalid, Matra, Invalid, + Matra, Matra, Matra, Matra, + Matra, Matra, Matra, Matra, + + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, Invalid, + Invalid, Invalid, Invalid, Invalid, + + Invalid, Invalid, Matra, Matra, + Other, Other, Other, Other, + Other, Other, Other, Other, + Other, Other, Other, Other, +}; + +enum Position { + None, + Pre, + Above, + Below, + Post, + Split, + Base, + Reph, + Vattu, + Inherit +}; + +static const unsigned char indicPosition[0xe00-0x900] = { + // Devanagari + None, Above, Above, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + Below, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, Post, Pre, + + Post, Below, Below, Below, + Below, Above, Above, Above, + Above, Post, Post, Post, + Post, None, None, None, + + None, Above, Below, Above, + Above, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, Below, Below, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Bengali + None, Above, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + Below, None, None, Post, + + Below, None, None, None, + None, None, None, None, + None, None, None, None, + Below, None, Post, Pre, + + Post, Below, Below, Below, + Below, None, None, Pre, + Pre, None, None, Split, + Split, Below, None, None, + + None, None, None, None, + None, None, None, Post, + None, None, None, None, + None, None, None, None, + + None, None, Below, Below, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Gurmukhi + None, Above, Above, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, Post, + + Below, None, None, None, + None, Below, None, None, + None, Below, None, None, + Below, None, Post, Pre, + + Post, Below, Below, None, + None, None, None, Above, + Above, None, None, Above, + Above, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + Above, Above, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Gujarati + None, Above, Above, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + Below, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, Post, Pre, + + Post, Below, Below, Below, + Below, Above, None, Above, + Above, Post, None, Post, + Post, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, Below, Below, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Oriya + None, Above, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + Below, None, None, None, + Below, None, None, None, + Below, Below, Below, Post, + + Below, None, Below, Below, + None, None, None, None, + None, None, None, None, + None, None, Post, Above, + + Post, Below, Below, Below, + None, None, None, Pre, + Split, None, None, Split, + Split, None, None, None, + + None, None, None, None, + None, None, Above, Post, + None, None, None, None, + None, None, None, Post, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, Below, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Tamil + None, None, Above, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, Post, Post, + + Above, Below, Below, None, + None, None, Pre, Pre, + Pre, None, Split, Split, + Split, Halant, None, None, + + None, None, None, None, + None, None, None, Post, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Telugu + None, Post, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, Below, Below, Below, + Below, Below, Below, Below, + Below, Below, Below, Below, + + Below, Below, Below, Below, + Below, Below, Below, Below, + Below, None, Below, Below, + Below, Below, Below, Below, + + Below, None, Below, Below, + None, Below, Below, Below, + Below, Below, None, None, + None, None, Post, Above, + + Above, Post, Post, Post, + Post, None, Above, Above, + Split, None, Post, Above, + Above, Halant, None, None, + + None, None, None, None, + None, Above, Below, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Kannada + None, None, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, Below, Below, Below, + Below, Below, Below, Below, + Below, Below, Below, Below, + + Below, Below, Below, Below, + Below, Below, Below, Below, + Below, Below, Below, Below, + Below, Below, Below, Below, + + Below, None, Below, Below, + None, Below, Below, Below, + Below, Below, None, None, + None, None, Post, Above, + + Split, Post, Post, Post, + Post, None, Above, Split, + Split, None, Split, Split, + Above, Halant, None, None, + + None, None, None, None, + None, Post, Post, None, + None, None, None, None, + None, None, Below, None, + + None, None, Below, Below, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Malayalam + None, None, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, Post, + + Post, None, Below, None, + None, Post, None, None, + None, None, None, None, + None, None, Post, Post, + + Post, Post, Post, Post, + None, None, Pre, Pre, + Pre, None, Split, Split, + Split, Halant, None, None, + + None, None, None, None, + None, None, None, Post, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + // Sinhala + None, None, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, Post, + + Post, Post, Above, Above, + Below, None, Below, None, + Post, Pre, Split, Pre, + Split, Split, Split, Post, + + None, None, None, None, + None, None, None, None, + None, None, None, None, + None, None, None, None, + + None, None, Post, Post, + None, None, None, None, + None, None, None, None, + None, None, None, None +}; + +static inline Form form(unsigned short uc) { + if (uc < 0x900 || uc > 0xdff) { + if (uc == 0x25cc) + return Consonant; + if (uc == 0x200c || uc == 0x200d) + return Control; + return Other; + } + return (Form)indicForms[uc-0x900]; +} + +static inline Position indic_position(unsigned short uc) { + if (uc < 0x900 || uc > 0xdff) + return None; + return (Position) indicPosition[uc-0x900]; +} + + +enum IndicScriptProperties { + HasReph = 0x01, + HasSplit = 0x02 +}; + +const uchar scriptProperties[10] = { + // Devanagari, + HasReph, + // Bengali, + HasReph|HasSplit, + // Gurmukhi, + 0, + // Gujarati, + HasReph, + // Oriya, + HasReph|HasSplit, + // Tamil, + HasSplit, + // Telugu, + HasSplit, + // Kannada, + HasSplit|HasReph, + // Malayalam, + HasSplit, + // Sinhala, + HasSplit +}; + +struct IndicOrdering { + Form form; + Position position; +}; + +static const IndicOrdering devanagari_order [] = { + { Consonant, Below }, + { Matra, Below }, + { VowelMark, Below }, + { StressMark, Below }, + { Matra, Above }, + { Matra, Post }, + { Consonant, Reph }, + { VowelMark, Above }, + { StressMark, Above }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering bengali_order [] = { + { Consonant, Below }, + { Matra, Below }, + { Matra, Above }, + { Consonant, Reph }, + { VowelMark, Above }, + { Consonant, Post }, + { Matra, Post }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering gurmukhi_order [] = { + { Consonant, Below }, + { Matra, Below }, + { Matra, Above }, + { Consonant, Post }, + { Matra, Post }, + { VowelMark, Above }, + { (Form)0, None } +}; + +static const IndicOrdering tamil_order [] = { + { Matra, Above }, + { Matra, Post }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering telugu_order [] = { + { Matra, Above }, + { Matra, Below }, + { Matra, Post }, + { Consonant, Below }, + { Consonant, Post }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering kannada_order [] = { + { Matra, Above }, + { Matra, Post }, + { Consonant, Below }, + { Consonant, Post }, + { LengthMark, Post }, + { Consonant, Reph }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering malayalam_order [] = { + { Consonant, Below }, + { Matra, Below }, + { Consonant, Reph }, + { Consonant, Post }, + { Matra, Post }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering sinhala_order [] = { + { Matra, Below }, + { Matra, Above }, + { Matra, Post }, + { VowelMark, Post }, + { (Form)0, None } +}; + +static const IndicOrdering * const indic_order[] = { + devanagari_order, // Devanagari + bengali_order, // Bengali + gurmukhi_order, // Gurmukhi + devanagari_order, // Gujarati + bengali_order, // Oriya + tamil_order, // Tamil + telugu_order, // Telugu + kannada_order, // Kannada + malayalam_order, // Malayalam + sinhala_order // Sinhala +}; + + + +// vowel matras that have to be split into two parts. +static const unsigned short split_matras[] = { + // matra, split1, split2 + + // bengalis + 0x9cb, 0x9c7, 0x9be, + 0x9cc, 0x9c7, 0x9d7, + // oriya + 0xb48, 0xb47, 0xb56, + 0xb4b, 0xb47, 0xb3e, + 0xb4c, 0xb47, 0xb57, + // tamil + 0xbca, 0xbc6, 0xbbe, + 0xbcb, 0xbc7, 0xbbe, + 0xbcc, 0xbc6, 0xbd7, + // telugu + 0xc48, 0xc46, 0xc56, + // kannada + 0xcc0, 0xcbf, 0xcd5, + 0xcc7, 0xcc6, 0xcd5, + 0xcc8, 0xcc6, 0xcd6, + 0xcca, 0xcc6, 0xcc2, + 0xccb, 0xcca, 0xcd5, + // malayalam + 0xd4a, 0xd46, 0xd3e, + 0xd4b, 0xd47, 0xd3e, + 0xd4c, 0xd46, 0xd57, + // sinhala + 0xdda, 0xdd9, 0xdca, + 0xddc, 0xdd9, 0xdcf, + 0xddd, 0xddc, 0xdca, + 0xdde, 0xdd9, 0xddf, + 0xffff +}; + +static inline void splitMatra(unsigned short *reordered, int matra, int &len, int &base) +{ + unsigned short matra_uc = reordered[matra]; + //tqDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]); + + const unsigned short *split = split_matras; + while (split[0] < matra_uc) + split += 3; + + assert(*split == matra_uc); + ++split; + + if (indic_position(*split) == Pre) { + reordered[matra] = split[1]; + memmove(reordered + 1, reordered, len*sizeof(unsigned short)); + reordered[0] = split[0]; + base++; + } else { + memmove(reordered + matra + 1, reordered + matra, (len-matra)*sizeof(unsigned short)); + reordered[matra] = split[0]; + reordered[matra+1] = split[1]; + } + len++; +} + +enum IndicProperties { + // these two are already defined +// CcmpProperty = 0x1, +// InitProperty = 0x2, + NuktaProperty = 0x4, + AkhantProperty = 0x8, + RephProperty = 0x10, + PreFormProperty = 0x20, + BelowFormProperty = 0x40, + AboveFormProperty = 0x80, + HalfFormProperty = 0x100, + PostFormProperty = 0x200, + VattuProperty = 0x400, + PreSubstProperty = 0x800, + BelowSubstProperty = 0x1000, + AboveSubstProperty = 0x2000, + PostSubstProperty = 0x4000, + HalantProperty = 0x8000, + CligProperty = 0x10000 +}; + +#ifndef TQT_NO_XFTFREETYPE +static const TQOpenType::Features indic_features[] = { + { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, + { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, + { FT_MAKE_TAG('n', 'u', 'k', 't'), NuktaProperty }, + { FT_MAKE_TAG('a', 'k', 'h', 'n'), AkhantProperty }, + { FT_MAKE_TAG('r', 'p', 'h', 'f'), RephProperty }, + { FT_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty }, + { FT_MAKE_TAG('h', 'a', 'l', 'f'), HalfFormProperty }, + { FT_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty }, + { FT_MAKE_TAG('v', 'a', 't', 'u'), VattuProperty }, + { FT_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty }, + { FT_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty }, + { FT_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty }, + { FT_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty }, + { FT_MAKE_TAG('h', 'a', 'l', 'n'), HalantProperty }, + { 0, 0 } +}; +#endif + +// #define INDIC_DEBUG +#ifdef INDIC_DEBUG +#define IDEBUG tqDebug +#else +#define IDEBUG if(0) tqDebug +#endif + +#ifdef INDIC_DEBUG +static TQString propertiesToString(int properties) +{ + TQString res; + properties = ~properties; + if (properties & CcmpProperty) + res += "Ccmp "; + if (properties & InitProperty) + res += "Init "; + if (properties & NuktaProperty) + res += "Nukta "; + if (properties & AkhantProperty) + res += "Akhant "; + if (properties & RephProperty) + res += "Reph "; + if (properties & PreFormProperty) + res += "PreForm "; + if (properties & BelowFormProperty) + res += "BelowForm "; + if (properties & AboveFormProperty) + res += "AboveForm "; + if (properties & HalfFormProperty) + res += "HalfForm "; + if (properties & PostFormProperty) + res += "PostForm "; + if (properties & VattuProperty) + res += "Vattu "; + if (properties & PreSubstProperty) + res += "PreSubst "; + if (properties & BelowSubstProperty) + res += "BelowSubst "; + if (properties & AboveSubstProperty) + res += "AboveSubst "; + if (properties & PostSubstProperty) + res += "PostSubst "; + if (properties & HalantProperty) + res += "Halant "; + if (properties & CligProperty) + res += "Clig "; + return res; +} +#endif + +static bool indic_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool invalid) +{ + Q_UNUSED(openType) + int script = item->script; + Q_ASSERT(script >= TQFont::Devanagari && script <= TQFont::Sinhala); + const unsigned short script_base = 0x0900 + 0x80*(script-TQFont::Devanagari); + const unsigned short ra = script_base + 0x30; + const unsigned short halant = script_base + 0x4d; + const unsigned short nukta = script_base + 0x3c; + + int len = item->length; + IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->from, item->length, invalid); + + if (item->num_glyphs < len+4) { + item->num_glyphs = len+4; + return FALSE; + } + + TQVarLengthArray reordered(len+4); + TQVarLengthArray position(len+4); + + unsigned char properties = scriptProperties[script-TQFont::Devanagari]; + + if (invalid) { + *reordered.data() = 0x25cc; + memcpy(reordered.data()+1, item->string->unicode() + item->from, len*sizeof(TQChar)); + len++; + } else { + memcpy(reordered.data(), item->string->unicode() + item->from, len*sizeof(TQChar)); + } + if (reordered[len-1] == 0x200c) // zero width non joiner + len--; + + int i; + int base = 0; + int reph = -1; + +#ifdef INDIC_DEBUG + IDEBUG("original:"); + for (i = 0; i < len; i++) { + IDEBUG(" %d: %4x", i, reordered[i]); + } +#endif + + if (len != 1) { + unsigned short *uc = reordered.data(); + bool beginsWithRa = FALSE; + + // Rule 1: find base consonant + // + // The shaping engine finds the base consonant of the + // syllable, using the following algorithm: starting from the + // end of the syllable, move backwards until a consonant is + // found that does not have a below-base or post-base form + // (post-base forms have to follow below-base forms), or + // arrive at the first consonant. The consonant stopped at + // will be the base. + // + // * If the syllable starts with Ra + H (in a script that has + // 'Reph'), Ra is excluded from candidates for base + // consonants. + // + // * In Kannada and Telugu, the base consonant cannot be + // farther than 3 consonants from the end of the syllable. + // #### replace the HasReph property by testing if the feature exists in the font! + if (form(*uc) == Consonant || (script == TQFont::Bengali && form(*uc) == IndependentVowel)) { + beginsWithRa = (properties & HasReph) && ((len > 2) && *uc == ra && *(uc+1) == halant); + + if (beginsWithRa && form(*(uc+2)) == Control) + beginsWithRa = FALSE; + + base = (beginsWithRa ? 2 : 0); + IDEBUG(" length = %d, beginsWithRa = %d, base=%d", len, beginsWithRa, base); + + int lastConsonant = 0; + int matra = -1; + // we remember: + // * the last consonant since we need it for rule 2 + // * the matras position for rule 3 and 4 + + // figure out possible base glyphs + memset(position.data(), 0, len); + if (script == TQFont::Devanagari || script == TQFont::Gujarati) { + bool vattu = FALSE; + for (i = base; i < len; ++i) { + position[i] = form(uc[i]); + if (position[i] == Consonant) { + lastConsonant = i; + vattu = (!vattu && uc[i] == ra); + if (vattu) { + IDEBUG("excluding vattu glyph at %d from base candidates", i); + position[i] = Vattu; + } + } else if (position[i] == Matra) { + matra = i; + } + } + } else { + for (i = base; i < len; ++i) { + position[i] = form(uc[i]); + if (position[i] == Consonant) + lastConsonant = i; + else if (matra < 0 && position[i] == Matra) + matra = i; + } + } + int skipped = 0; + Position pos = Post; + for (i = len-1; i > base; i--) { + if (position[i] != Consonant && (position[i] != Control || script == TQFont::Kannada)) + continue; + + Position charPosition = indic_position(uc[i]); + if (pos == Post && charPosition == Post) { + pos = Post; + } else if ((pos == Post || pos == Below) && charPosition == Below) { + if (script == TQFont::Devanagari || script == TQFont::Gujarati) + base = i; + pos = Below; + } else { + base = i; + break; + } + if (skipped == 2 && (script == TQFont::Kannada || script == TQFont::Telugu)) { + base = i; + break; + } + ++skipped; + } + + IDEBUG(" base consonant at %d skipped=%d, lastConsonant=%d", base, skipped, lastConsonant); + + // Rule 2: + // + // If the base consonant is not the last one, Uniscribe + // moves the halant from the base consonant to the last + // one. + if (lastConsonant > base) { + int halantPos = 0; + if (uc[base+1] == halant) + halantPos = base + 1; + else if (uc[base+1] == nukta && uc[base+2] == halant) + halantPos = base + 2; + if (halantPos > 0) { + IDEBUG(" moving halant from %d to %d!", base+1, lastConsonant); + for (i = halantPos; i < lastConsonant; i++) + uc[i] = uc[i+1]; + uc[lastConsonant] = halant; + } + } + + // Rule 3: + // + // If the syllable starts with Ra + H, Uniscribe moves + // this combination so that it follows either: + + // * the post-base 'matra' (if any) or the base consonant + // (in scripts that show similarity to Devanagari, i.e., + // Devanagari, Gujarati, Bengali) + // * the base consonant (other scripts) + // * the end of the syllable (Kannada) + + Position matra_position = None; + if (matra > 0) + matra_position = indic_position(uc[matra]); + IDEBUG(" matra at %d with form %d, base=%d", matra, matra_position, base); + + if (beginsWithRa && base != 0) { + int toPos = base+1; + if (toPos < len && uc[toPos] == nukta) + toPos++; + if (toPos < len && uc[toPos] == halant) + toPos++; + if (toPos < len && uc[toPos] == 0x200d) + toPos++; + if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant) + toPos += 2; + if (script == TQFont::Devanagari || script == TQFont::Gujarati || script == TQFont::Bengali) { + if (matra_position == Post || matra_position == Split) { + toPos = matra+1; + matra -= 2; + } + } else if (script == TQFont::Kannada) { + toPos = len; + matra -= 2; + } + + IDEBUG("moving leading ra+halant to position %d", toPos); + for (i = 2; i < toPos; i++) + uc[i-2] = uc[i]; + uc[toPos-2] = ra; + uc[toPos-1] = halant; + base -= 2; + if (properties & HasReph) + reph = toPos-2; + } + + // Rule 4: + + // Uniscribe splits two- or three-part matras into their + // parts. This splitting is a character-to-character + // operation). + // + // Uniscribe describes some moving operations for these + // matras here. For shaping however all pre matras need + // to be at the begining of the syllable, so we just move + // them there now. + if (matra_position == Split) { + splitMatra(uc, matra, len, base); + // Handle three-part matras (0xccb in Kannada) + matra_position = indic_position(uc[matra]); + if (matra_position == Split) + splitMatra(uc, matra, len, base); + } else if (matra_position == Pre) { + unsigned short m = uc[matra]; + while (matra--) + uc[matra+1] = uc[matra]; + uc[0] = m; + base++; + } + } + + // Rule 5: + // + // Uniscribe classifies consonants and 'matra' parts as + // pre-base, above-base (Reph), below-base or post-base. This + // classification exists on the character code level and is + // language-dependent, not font-dependent. + for (i = 0; i < base; ++i) + position[i] = Pre; + position[base] = Base; + for (i = base+1; i < len; ++i) { + position[i] = indic_position(uc[i]); + // #### replace by adjusting table + if (uc[i] == nukta || uc[i] == halant) + position[i] = Inherit; + } + if (reph > 0) { + // recalculate reph, it might have changed. + for (i = base+1; i < len; ++i) + if (uc[i] == ra) + reph = i; + position[reph] = Reph; + position[reph+1] = Inherit; + } + + // all reordering happens now to the chars after the base + int fixed = base+1; + if (fixed < len && uc[fixed] == nukta) + fixed++; + if (fixed < len && uc[fixed] == halant) + fixed++; + if (fixed < len && uc[fixed] == 0x200d) + fixed++; + +#ifdef INDIC_DEBUG + for (i = fixed; i < len; ++i) + IDEBUG("position[%d] = %d, form=%d", i, position[i], form(uc[i])); +#endif + // we continuosly position the matras and vowel marks and increase the fixed + // until we reached the end. + const IndicOrdering *finalOrder = indic_order[script-TQFont::Devanagari]; + + IDEBUG(" reordering pass:"); + //IDEBUG(" base=%d fixed=%d", base, fixed); + int toMove = 0; + while (finalOrder[toMove].form && fixed < len-1) { + //IDEBUG(" fixed = %d, moving form %d with pos %d", fixed, finalOrder[toMove].form, finalOrder[toMove].position); + for (i = fixed; i < len; i++) { + if (form(uc[i]) == finalOrder[toMove].form && + position[i] == finalOrder[toMove].position) { + // need to move this glyph + int to = fixed; + if (i < len-1 && position[i+1] == Inherit) { + IDEBUG(" moving two chars from %d to %d", i, to); + unsigned short ch = uc[i]; + unsigned short ch2 = uc[i+1]; + unsigned char pos = position[i]; + for (int j = i+1; j > to+1; j--) { + uc[j] = uc[j-2]; + position[j] = position[j-2]; + } + uc[to] = ch; + uc[to+1] = ch2; + position[to] = pos; + position[to+1] = pos; + fixed += 2; + } else { + IDEBUG(" moving one char from %d to %d", i, to); + unsigned short ch = uc[i]; + unsigned char pos = position[i]; + for (int j = i; j > to; j--) { + uc[j] = uc[j-1]; + position[j] = position[j-1]; + } + uc[to] = ch; + position[to] = pos; + fixed++; + } + } + } + toMove++; + } + + } + + if (reph > 0) { + // recalculate reph, it might have changed. + for (i = base+1; i < len; ++i) + if (reordered[i] == ra) + reph = i; + } + + if (item->font->stringToCMap((const TQChar *)reordered.data(), len, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + + IDEBUG(" base=%d, reph=%d", base, reph); + IDEBUG("reordered:"); + for (i = 0; i < len; i++) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = FALSE; + item->attributes[i].justification = 0; + item->attributes[i].zeroWidth = FALSE; + IDEBUG(" %d: %4x", i, reordered[i]); + } + + // now we have the syllable in the right order, and can start running it through open type. + + bool control = FALSE; + for (i = 0; i < len; ++i) + control |= (form(reordered[i]) == Control); + +#ifndef TQT_NO_XFTFREETYPE + if (openType) { + + // we need to keep track of where the base glyph is for some + // scripts and use the cluster feature for this. This + // also means we have to correct the logCluster output from + // the open type engine manually afterwards. for indic this + // is rather simple, as all chars just point to the first + // glyph in the syllable. + TQVarLengthArray clusters(len); + TQVarLengthArray properties(len); + + for (i = 0; i < len; ++i) + clusters[i] = i; + + // features we should always apply + for (i = 0; i < len; ++i) + properties[i] = ~(CcmpProperty + | NuktaProperty + | VattuProperty + | PreSubstProperty + | BelowSubstProperty + | AboveSubstProperty + | HalantProperty + | PositioningProperties); + + // Ccmp always applies + // Init + if (item->from == 0 + || !(item->string->unicode()[item->from-1].isLetter() || item->string->unicode()[item->from-1].isMark())) + properties[0] &= ~InitProperty; + + // Nukta always applies + // Akhant + for (i = 0; i <= base; ++i) + properties[i] &= ~AkhantProperty; + // Reph + if (reph >= 0) { + properties[reph] &= ~RephProperty; + properties[reph+1] &= ~RephProperty; + } + // BelowForm + for (i = base+1; i < len; ++i) + properties[i] &= ~BelowFormProperty; + + if (script == TQFont::Devanagari || script == TQFont::Gujarati) { + // vattu glyphs need this aswell + bool vattu = FALSE; + for (i = base-2; i > 1; --i) { + if (form(reordered[i]) == Consonant) { + vattu = (!vattu && reordered[i] == ra); + if (vattu) { + IDEBUG("forming vattu ligature at %d", i); + properties[i] &= ~BelowFormProperty; + properties[i+1] &= ~BelowFormProperty; + } + } + } + } + // HalfFormProperty + for (i = 0; i < base; ++i) + properties[i] &= ~HalfFormProperty; + if (control) { + for (i = 2; i < len; ++i) { + if (reordered[i] == 0x200d /* ZWJ */) { + properties[i-1] &= ~HalfFormProperty; + properties[i-2] &= ~HalfFormProperty; + } else if (reordered[i] == 0x200c /* ZWNJ */) { + properties[i-1] &= ~HalfFormProperty; + properties[i-2] &= ~HalfFormProperty; + } + } + } + // PostFormProperty + for (i = base+1; i < len; ++i) + properties[i] &= ~PostFormProperty; + // vattu always applies + // pres always applies + // blws always applies + // abvs always applies + + // psts + // ### this looks slightly different from before, but I believe it's correct + if (reordered[len-1] != halant || base != len-2) + properties[base] &= ~PostSubstProperty; + for (i = base+1; i < len; ++i) + properties[i] &= ~PostSubstProperty; + + // halant always applies + +#ifdef INDIC_DEBUG + { + IDEBUG("OT properties:"); + for (int i = 0; i < len; ++i) + tqDebug(" i: %s", ::propertiesToString(properties[i]).toLatin1().data()); + } +#endif + + // initialize + item->log_clusters = clusters.data(); + openType->shape(item, properties.data()); + + int newLen = openType->len(); + OTL_GlyphItem otl_glyphs = openType->glyphs(); + + // move the left matra back to it's correct position in malayalam and tamil + if ((script == TQFont::Malayalam || script == TQFont::Tamil) && (form(reordered[0]) == Matra)) { +// tqDebug("reordering matra, len=%d", newLen); + // need to find the base in the shaped string and move the matra there + int basePos = 0; + while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base) + basePos++; + --basePos; + if (basePos < newLen && basePos > 1) { +// tqDebug("moving prebase matra to position %d in syllable newlen=%d", basePos, newLen); + OTL_GlyphItemRec m = otl_glyphs[0]; + --basePos; + for (i = 0; i < basePos; ++i) + otl_glyphs[i] = otl_glyphs[i+1]; + otl_glyphs[basePos] = m; + } + } + + if (!openType->positionAndAdd(item, FALSE)) + return FALSE; + + if (control) { + IDEBUG("found a control char in the syllable"); + int i = 0, j = 0; + while (i < item->num_glyphs) { + if (form(reordered[otl_glyphs[i].cluster]) == Control) { + ++i; + if (i >= item->num_glyphs) + break; + } + item->glyphs[j] = item->glyphs[i]; + ++i; + ++j; + } + item->num_glyphs = j; + } + + } +#endif + + item->attributes[0].clusterStart = TRUE; + IDEBUG("<<<<<<"); + return TRUE; +} + + +/* syllables are of the form: + + (Consonant Nukta? Halant)* Consonant Matra? VowelMark? StressMark? + (Consonant Nukta? Halant)* Consonant Halant + IndependentVowel VowelMark? StressMark? + + We return syllable boundaries on invalid combinations aswell +*/ +static int indic_nextSyllableBoundary(int script, const TQString &s, int start, int end, bool *invalid) +{ + *invalid = FALSE; + IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end); + const TQChar *uc = s.unicode()+start; + + int pos = 0; + Form state = form(uc[pos].unicode()); + IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos].unicode()); + pos++; + + if (state != Consonant && state != IndependentVowel) { + if (state != Other) + *invalid = TRUE; + goto finish; + } + + while (pos < end - start) { + Form newState = form(uc[pos].unicode()); + IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos].unicode()); + switch(newState) { + case Control: + newState = state; + if (state == Halant && uc[pos].unicode() == 0x200d /* ZWJ */) + break; + // the control character should be the last char in the item + ++pos; + goto finish; + case Consonant: + if (state == Halant && (script != TQFont::Sinhala || uc[pos-1].unicode() == 0x200d /* ZWJ */)) + break; + goto finish; + case Halant: + if (state == Nukta || state == Consonant) + break; + // Bengali has a special exception allowing the combination Vowel_A/E + Halant + Ya + if (script == TQFont::Bengali && pos == 1 && + (uc[0].unicode() == 0x0985 || uc[0].unicode() == 0x098f)) + break; + goto finish; + case Nukta: + if (state == Consonant) + break; + goto finish; + case StressMark: + if (state == VowelMark) + break; + // fall through + case VowelMark: + if (state == Matra || state == IndependentVowel) + break; + // fall through + case Matra: + if (state == Consonant || state == Nukta) + break; + // ### not sure if this is correct. If it is, does it apply only to Bengali or should + // it work for all Indic languages? + // the combination Independent_A + Vowel Sign AA is allowed. + if (script == TQFont::Bengali && uc[pos].unicode() == 0x9be && uc[pos-1].unicode() == 0x985) + break; + if (script == TQFont::Tamil && state == Matra) { + if (uc[pos-1].unicode() == 0x0bc6 && + (uc[pos].unicode() == 0xbbe || uc[pos].unicode() == 0xbd7)) + break; + if (uc[pos-1].unicode() == 0x0bc7 && uc[pos].unicode() == 0xbbe) + break; + } + goto finish; + + case LengthMark: + case IndependentVowel: + case Invalid: + case Other: + goto finish; + } + state = newState; + pos++; + } + finish: + return pos+start; +} + +static bool indic_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script >= TQFont::Devanagari && item->script <= TQFont::Sinhala); + +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + if (openType) + openType->selectScript(item->script, indic_features); +#else + TQOpenType *openType = 0; +#endif + unsigned short *logClusters = item->log_clusters; + + TQShaperItem syllable = *item; + int first_glyph = 0; + + int sstart = item->from; + int end = sstart + item->length; + IDEBUG("indic_shape: from %d length %d", item->from, item->length); + while (sstart < end) { + bool invalid; + int send = indic_nextSyllableBoundary(item->script, *item->string, sstart, end, &invalid); + IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, + invalid ? "TRUE" : "FALSE"); + syllable.from = sstart; + syllable.length = send-sstart; + syllable.glyphs = item->glyphs + first_glyph; + syllable.offsets = item->offsets + first_glyph; + syllable.advances = item->advances + first_glyph; + syllable.attributes = item->attributes + first_glyph; + syllable.num_glyphs = item->num_glyphs - first_glyph; + if (!indic_shape_syllable(openType, &syllable, invalid)) { + IDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); + item->num_glyphs += syllable.num_glyphs; + return FALSE; + } + item->has_positioning |= syllable.has_positioning; + + // fix logcluster array + IDEBUG("syllable:"); + int i; + for (i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) + IDEBUG(" %d -> glyph %x", i, item->glyphs[i]); + IDEBUG(" logclusters:"); + for (i = sstart; i < send; ++i) { + IDEBUG(" %d -> glyph %d", i, first_glyph); + logClusters[i-item->from] = first_glyph; + } + sstart = send; + first_glyph += syllable.num_glyphs; + } + item->num_glyphs = first_glyph; + return TRUE; +} + + +static void indic_attributes(int script, const TQString &text, int from, int len, TQCharAttributes *attributes) +{ + int end = from + len; + const TQChar *uc = text.unicode() + from; + attributes += from; + int i = 0; + while (i < len) { + bool invalid; + int boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from; + attributes[i].charStop = TRUE; + + if (boundary > len-1) boundary = len; + i++; + while (i < boundary) { + attributes[i].charStop = FALSE; + ++uc; + ++i; + } + assert(i == boundary); + } + + +} + + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Thai and Lao +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +#include +#include + + +static void thaiWordBreaks(const TQChar *string, const int len, TQCharAttributes *attributes) +{ +#ifndef TQT_NO_TEXTCODEC + typedef int (*th_brk_def)(const char*, int[], int); + static TQTextCodec *thaiCodec = TQTextCodec::codecForMib(2259); + static th_brk_def th_brk = 0; + +#ifndef TQT_NO_LIBRARY + /* load libthai dynamically */ + if (!th_brk && thaiCodec) { + th_brk = (th_brk_def)TQLibrary::resolve("thai", "th_brk"); + if (!th_brk) + thaiCodec = 0; + } +#endif + + if (!th_brk) + return; + + TQCString cstr = thaiCodec->fromUnicode(TQConstString(string, len).string()); + + int brp[128]; + int *break_positions = brp; + int numbreaks = th_brk(cstr.data(), break_positions, 128); + if (numbreaks > 128) { + break_positions = new int[numbreaks]; + numbreaks = th_brk(cstr.data(),break_positions, numbreaks); + } + + attributes[0].softBreak = TRUE; + int i; + for (i = 1; i < len; ++i) + attributes[i].softBreak = FALSE; + + for (i = 0; i < numbreaks; ++i) + attributes[break_positions[i]].softBreak = TRUE; + + if (break_positions != brp) + delete [] break_positions; +#endif +} + + +static void thai_attributes( int script, const TQString &text, int from, int len, TQCharAttributes *attributes ) +{ + Q_UNUSED(script); + Q_ASSERT(script == TQFont::Thai); + thaiWordBreaks(text.unicode() + from, len, attributes); +} + + + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Tibetan +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +// tibetan syllables are of the form: +// head position consonant +// first sub-joined consonant +// ....intermediate sub-joined consonants (if any) +// last sub-joined consonant +// sub-joined vowel (a-chung U+0F71) +// standard or compound vowel sign (or 'virama' for devanagari transliteration) + +enum TibetanForm { + TibetanOther, + TibetanHeadConsonant, + TibetanSubjoinedConsonant, + TibetanSubjoinedVowel, + TibetanVowel +}; + +// this table starts at U+0f40 +static const unsigned char tibetanForm[0x80] = { + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, + TibetanOther, TibetanOther, TibetanOther, TibetanOther, + + TibetanOther, TibetanVowel, TibetanVowel, TibetanVowel, + TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, + TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, + TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, + + TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, + TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel, + TibetanOther, TibetanOther, TibetanOther, TibetanOther, + TibetanOther, TibetanOther, TibetanOther, TibetanOther, + + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, + TibetanSubjoinedConsonant, TibetanOther, TibetanOther, TibetanOther +}; + + +static inline TibetanForm tibetan_form(const TQChar &c) +{ + return (TibetanForm)tibetanForm[c.unicode() - 0x0f40]; +} + +#ifndef TQT_NO_XFTFREETYPE +static const TQOpenType::Features tibetan_features[] = { + { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, + { FT_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty }, + { FT_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty }, + {0, 0} +}; +#endif + +static bool tibetan_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool invalid) +{ + Q_UNUSED(openType) + int len = item->length; + + if (item->num_glyphs < item->length + 4) { + item->num_glyphs = item->length + 4; + return FALSE; + } + + int i; + TQVarLengthArray reordered(len+4); + + const TQChar *str = item->string->unicode() + item->from; + if (invalid) { + *reordered.data() = 0x25cc; + memcpy(reordered.data()+1, str, len*sizeof(TQChar)); + len++; + str = (TQChar *)reordered.data(); + } + + if (item->font->stringToCMap(str, len, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + for (i = 0; i < item->length; i++) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = FALSE; + item->attributes[i].justification = 0; + item->attributes[i].zeroWidth = FALSE; + IDEBUG(" %d: %4x", i, str[i].unicode()); + } + + // now we have the syllable in the right order, and can start running it through open type. + +#ifndef TQT_NO_XFTFREETYPE + if (openType && openType->supportsScript(TQFont::Tibetan)) { + openType->selectScript(TQFont::Tibetan, tibetan_features); + + openType->shape(item); + if (!openType->positionAndAdd(item, FALSE)) + return FALSE; + } +#endif + + item->attributes[0].clusterStart = TRUE; + return TRUE; +} + + +static int tibetan_nextSyllableBoundary(const TQString &s, int start, int end, bool *invalid) +{ + const TQChar *uc = s.unicode() + start; + + int pos = 0; + TibetanForm state = tibetan_form(*uc); + +// tqDebug("state[%d]=%d (uc=%4x)", pos, state, uc[pos].unicode()); + pos++; + + if (state != TibetanHeadConsonant) { + if (state != TibetanOther) + *invalid = TRUE; + goto finish; + } + + while (pos < end - start) { + TibetanForm newState = tibetan_form(uc[pos]); + switch(newState) { + case TibetanSubjoinedConsonant: + case TibetanSubjoinedVowel: + if (state != TibetanHeadConsonant && + state != TibetanSubjoinedConsonant) + goto finish; + state = newState; + break; + case TibetanVowel: + if (state != TibetanHeadConsonant && + state != TibetanSubjoinedConsonant && + state != TibetanSubjoinedVowel) + goto finish; + break; + case TibetanOther: + case TibetanHeadConsonant: + goto finish; + } + pos++; + } + +finish: + *invalid = FALSE; + return start+pos; +} + +static bool tibetan_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script == TQFont::Tibetan); + +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + if (openType && !openType->supportsScript(item->script)) + openType = 0; +#else + TQOpenType *openType = 0; +#endif + unsigned short *logClusters = item->log_clusters; + + TQShaperItem syllable = *item; + int first_glyph = 0; + + int sstart = item->from; + int end = sstart + item->length; + while (sstart < end) { + bool invalid; + int send = tibetan_nextSyllableBoundary(*(item->string), sstart, end, &invalid); + IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, + invalid ? "TRUE" : "FALSE"); + syllable.from = sstart; + syllable.length = send-sstart; + syllable.glyphs = item->glyphs + first_glyph; + syllable.offsets = item->offsets + first_glyph; + syllable.advances = item->advances + first_glyph; + syllable.attributes = item->attributes + first_glyph; + syllable.num_glyphs = item->num_glyphs - first_glyph; + if (!tibetan_shape_syllable(openType, &syllable, invalid)) { + item->num_glyphs += syllable.num_glyphs; + return FALSE; + } + item->has_positioning |= syllable.has_positioning; + + // fix logcluster array + for (int i = sstart; i < send; ++i) + logClusters[i-item->from] = first_glyph; + sstart = send; + first_glyph += syllable.num_glyphs; + } + item->num_glyphs = first_glyph; + return TRUE; +} + +static void tibetan_attributes(int script, const TQString &text, int from, int len, TQCharAttributes *attributes) +{ + Q_UNUSED(script); + + int end = from + len; + const TQChar *uc = text.unicode() + from; + attributes += from; + int i = 0; + while (i < len) { + bool invalid; + int boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from; + + attributes[i].charStop = TRUE; + + if (boundary > len-1) boundary = len; + i++; + while (i < boundary) { + attributes[i].charStop = FALSE; + ++uc; + ++i; + } + assert(i == boundary); + } +} + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Khmer +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + + +// Vocabulary +// Base -> A consonant or an independent vowel in its full (not subscript) form. It is the +// center of the syllable, it can be surrounded by coeng (subscript) consonants, vowels, +// split vowels, signs... but there is only one base in a syllable, it has to be coded as +// the first character of the syllable. +// split vowel --> vowel that has two parts placed separately (e.g. Before and after the consonant). +// Khmer language has five of them. Khmer split vowels either have one part before the +// base and one after the base or they have a part before the base and a part above the base. +// The first part of all Khmer split vowels is the same character, identical to +// the glyph of Khmer dependent vowel SRA EI +// coeng --> modifier used in Khmer to construct coeng (subscript) consonants +// Differently than indian languages, the coeng modifies the consonant that follows it, +// not the one preceding it Each consonant has two forms, the base form and the subscript form +// the base form is the normal one (using the consonants code-point), the subscript form is +// displayed when the combination coeng + consonant is encountered. +// Consonant of type 1 -> A consonant which has subscript for that only occupies space under a base consonant +// Consonant of type 2.-> Its subscript form occupies space under and before the base (only one, RO) +// Consonant of Type 3 -> Its subscript form occupies space under and after the base (KHO, CHHO, THHO, BA, YO, SA) +// Consonant shifter -> Khmer has to series of consonants. The same dependent vowel has different sounds +// if it is attached to a consonant of the first series or a consonant of the second series +// Most consonants have an equivalent in the other series, but some of theme exist only in +// one series (for example SA). If we want to use the consonant SA with a vowel sound that +// can only be done with a vowel sound that corresponds to a vowel accompanying a consonant +// of the other series, then we need to use a consonant shifter: TRIISAP or MUSIKATOAN +// x17C9 y x17CA. TRIISAP changes a first series consonant to second series sound and +// MUSIKATOAN a second series consonant to have a first series vowel sound. +// Consonant shifter are both normally supercript marks, but, when they are followed by a +// superscript, they change shape and take the form of subscript dependent vowel SRA U. +// If they are in the same syllable as a coeng consonant, Unicode 3.0 says that they +// should be typed before the coeng. Unicode 4.0 breaks the standard and says that it should +// be placed after the coeng consonant. +// Dependent vowel -> In khmer dependent vowels can be placed above, below, before or after the base +// Each vowel has its own position. Only one vowel per syllable is allowed. +// Signs -> Khmer has above signs and post signs. Only one above sign and/or one post sign are +// Allowed in a syllable. +// +// +// order is important here! This order must be the same that is found in each horizontal +// line in the statetable for Khmer (see khmerStateTable) . +// +enum KhmerCharClassValues { + CC_RESERVED = 0, + CC_CONSONANT = 1, // Consonant of type 1 or independent vowel + CC_CONSONANT2 = 2, // Consonant of type 2 + CC_CONSONANT3 = 3, // Consonant of type 3 + CC_ZERO_WIDTH_NJ_MARK = 4, // Zero Width non joiner character (0x200C) + CC_CONSONANT_SHIFTER = 5, + CC_ROBAT = 6, // Khmer special diacritic accent -treated differently in state table + CC_COENG = 7, // Subscript consonant combining character + CC_DEPENDENT_VOWEL = 8, + CC_SIGN_ABOVE = 9, + CC_SIGN_AFTER = 10, + CC_ZERO_WIDTH_J_MARK = 11, // Zero width joiner character + CC_COUNT = 12 // This is the number of character classes +}; + + +enum KhmerCharClassFlags { + CF_CLASS_MASK = 0x0000FFFF, + + CF_CONSONANT = 0x01000000, // flag to speed up comparing + CF_SPLIT_VOWEL = 0x02000000, // flag for a split vowel -> the first part is added in front of the syllable + CF_DOTTED_CIRCLE = 0x04000000, // add a dotted circle if a character with this flag is the first in a syllable + CF_COENG = 0x08000000, // flag to speed up comparing + CF_SHIFTER = 0x10000000, // flag to speed up comparing + CF_ABOVE_VOWEL = 0x20000000, // flag to speed up comparing + + // position flags + CF_POS_BEFORE = 0x00080000, + CF_POS_BELOW = 0x00040000, + CF_POS_ABOVE = 0x00020000, + CF_POS_AFTER = 0x00010000, + CF_POS_MASK = 0x000f0000 +}; + + +// Characters that get refered to by name +enum KhmerChar { + C_SIGN_ZWNJ = 0x200C, + C_SIGN_ZWJ = 0x200D, + C_DOTTED_CIRCLE = 0x25CC, + C_RO = 0x179A, + C_VOWEL_AA = 0x17B6, + C_SIGN_NIKAHIT = 0x17C6, + C_VOWEL_E = 0x17C1, + C_COENG = 0x17D2 +}; + + +// simple classes, they are used in the statetable (in this file) to control the length of a syllable +// they are also used to know where a character should be placed (location in reference to the base character) +// and also to know if a character, when independently displayed, should be displayed with a dotted-circle to +// indicate error in syllable construction +// +enum { + _xx = CC_RESERVED, + _sa = CC_SIGN_ABOVE | CF_DOTTED_CIRCLE | CF_POS_ABOVE, + _sp = CC_SIGN_AFTER | CF_DOTTED_CIRCLE| CF_POS_AFTER, + _c1 = CC_CONSONANT | CF_CONSONANT, + _c2 = CC_CONSONANT2 | CF_CONSONANT, + _c3 = CC_CONSONANT3 | CF_CONSONANT, + _rb = CC_ROBAT | CF_POS_ABOVE | CF_DOTTED_CIRCLE, + _cs = CC_CONSONANT_SHIFTER | CF_DOTTED_CIRCLE | CF_SHIFTER, + _dl = CC_DEPENDENT_VOWEL | CF_POS_BEFORE | CF_DOTTED_CIRCLE, + _db = CC_DEPENDENT_VOWEL | CF_POS_BELOW | CF_DOTTED_CIRCLE, + _da = CC_DEPENDENT_VOWEL | CF_POS_ABOVE | CF_DOTTED_CIRCLE | CF_ABOVE_VOWEL, + _dr = CC_DEPENDENT_VOWEL | CF_POS_AFTER | CF_DOTTED_CIRCLE, + _co = CC_COENG | CF_COENG | CF_DOTTED_CIRCLE, + + // split vowel + _va = _da | CF_SPLIT_VOWEL, + _vr = _dr | CF_SPLIT_VOWEL +}; + + +// Character class: a character class value +// ORed with character class flags. +// +typedef unsigned long KhmerCharClass; + + +// Character class tables +// _xx character does not combine into syllable, such as numbers, puntuation marks, non-Khmer signs... +// _sa Sign placed above the base +// _sp Sign placed after the base +// _c1 Consonant of type 1 or independent vowel (independent vowels behave as type 1 consonants) +// _c2 Consonant of type 2 (only RO) +// _c3 Consonant of type 3 +// _rb Khmer sign robat u17CC. combining mark for subscript consonants +// _cd Consonant-shifter +// _dl Dependent vowel placed before the base (left of the base) +// _db Dependent vowel placed below the base +// _da Dependent vowel placed above the base +// _dr Dependent vowel placed behind the base (right of the base) +// _co Khmer combining mark COENG u17D2, combines with the consonant or independent vowel following +// it to create a subscript consonant or independent vowel +// _va Khmer split vowel in wich the first part is before the base and the second one above the base +// _vr Khmer split vowel in wich the first part is before the base and the second one behind (right of) the base +// +static const KhmerCharClass khmerCharClasses[] = { + _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c1, _c1, // 1780 - 178F + _c1, _c1, _c1, _c1, _c3, _c1, _c1, _c1, _c1, _c3, _c2, _c1, _c1, _c1, _c3, _c3, // 1790 - 179F + _c1, _c3, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, _c1, // 17A0 - 17AF + _c1, _c1, _c1, _c1, _dr, _dr, _dr, _da, _da, _da, _da, _db, _db, _db, _va, _vr, // 17B0 - 17BF + _vr, _dl, _dl, _dl, _vr, _vr, _sa, _sp, _sp, _cs, _cs, _sa, _rb, _sa, _sa, _sa, // 17C0 - 17CF + _sa, _sa, _co, _sa, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _xx, _sa, _xx, _xx // 17D0 - 17DF +}; + +// this enum must reflect the range of khmerCharClasses +enum KhmerCharClassesRange { + KhmerFirstChar = 0x1780, + KhmerLastChar = 0x17df +}; + +// Below we define how a character in the input string is either in the khmerCharClasses table +// (in which case we get its type back), a ZWJ or ZWNJ (two characters that may appear +// within the syllable, but are not in the table) we also get their type back, or an unknown object +// in which case we get _xx (CC_RESERVED) back +// +static inline KhmerCharClass getKhmerCharClass(const TQChar &uc) +{ + if (uc.unicode() == C_SIGN_ZWJ) { + return CC_ZERO_WIDTH_J_MARK; + } + + if (uc.unicode() == C_SIGN_ZWNJ) { + return CC_ZERO_WIDTH_NJ_MARK; + } + + if (uc.unicode() < KhmerFirstChar || uc.unicode() > KhmerLastChar) { + return CC_RESERVED; + } + + return khmerCharClasses[uc.unicode() - KhmerFirstChar]; +} + + +// The stateTable is used to calculate the end (the length) of a well +// formed Khmer Syllable. +// +// Each horizontal line is ordered exactly the same way as the values in KhmerClassTable +// CharClassValues. This coincidence of values allows the follow up of the table. +// +// Each line corresponds to a state, which does not necessarily need to be a type +// of component... for example, state 2 is a base, with is always a first character +// in the syllable, but the state could be produced a consonant of any type when +// it is the first character that is analysed (in ground state). +// +// Differentiating 3 types of consonants is necessary in order to +// forbid the use of certain combinations, such as having a second +// coeng after a coeng RO, +// The inexistent possibility of having a type 3 after another type 3 is permitted, +// eliminating it would very much complicate the table, and it does not create typing +// problems, as the case above. +// +// The table is quite complex, in order to limit the number of coeng consonants +// to 2 (by means of the table). +// +// There a peculiarity, as far as Unicode is concerned: +// - The consonant-shifter is considered in two possible different +// locations, the one considered in Unicode 3.0 and the one considered in +// Unicode 4.0. (there is a backwards compatibility problem in this standard). +// +// +// xx independent character, such as a number, punctuation sign or non-khmer char +// +// c1 Khmer consonant of type 1 or an independent vowel +// that is, a letter in which the subscript for is only under the +// base, not taking any space to the right or to the left +// +// c2 Khmer consonant of type 2, the coeng form takes space under +// and to the left of the base (only RO is of this type) +// +// c3 Khmer consonant of type 3. Its subscript form takes space under +// and to the right of the base. +// +// cs Khmer consonant shifter +// +// rb Khmer robat +// +// co coeng character (u17D2) +// +// dv dependent vowel (including split vowels, they are treated in the same way). +// even if dv is not defined above, the component that is really tested for is +// KhmerClassTable::CC_DEPENDENT_VOWEL, which is common to all dependent vowels +// +// zwj Zero Width joiner +// +// zwnj Zero width non joiner +// +// sa above sign +// +// sp post sign +// +// there are lines with equal content but for an easier understanding +// (and maybe change in the future) we did not join them +// +static const signed char khmerStateTable[][CC_COUNT] = +{ + // xx c1 c2 c3 zwnj cs rb co dv sa sp zwj + { 1, 2, 2, 2, 1, 1, 1, 6, 1, 1, 1, 2}, // 0 - ground state + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 - exit state (or sign to the right of the syllable) + {-1, -1, -1, -1, 3, 4, 5, 6, 16, 17, 1, -1}, // 2 - Base consonant + {-1, -1, -1, -1, -1, 4, -1, -1, 16, -1, -1, -1}, // 3 - First ZWNJ before a register shifter It can only be followed by a shifter or a vowel + {-1, -1, -1, -1, 15, -1, -1, 6, 16, 17, 1, 14}, // 4 - First register shifter + {-1, -1, -1, -1, -1, -1, -1, -1, 20, -1, 1, -1}, // 5 - Robat + {-1, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1}, // 6 - First Coeng + {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, // 7 - First consonant of type 1 after coeng + {-1, -1, -1, -1, 12, 13, -1, -1, 16, 17, 1, 14}, // 8 - First consonant of type 2 after coeng + {-1, -1, -1, -1, 12, 13, -1, 10, 16, 17, 1, 14}, // 9 - First consonant or type 3 after ceong + {-1, 11, 11, 11, -1, -1, -1, -1, -1, -1, -1, -1}, // 10 - Second Coeng (no register shifter before) + {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, // 11 - Second coeng consonant (or ind. vowel) no register shifter before + {-1, -1, -1, -1, -1, 13, -1, -1, 16, -1, -1, -1}, // 12 - Second ZWNJ before a register shifter + {-1, -1, -1, -1, 15, -1, -1, -1, 16, 17, 1, 14}, // 13 - Second register shifter + {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, // 14 - ZWJ before vowel + {-1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1}, // 15 - ZWNJ before vowel + {-1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 1, 18}, // 16 - dependent vowel + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 18}, // 17 - sign above + {-1, -1, -1, -1, -1, -1, -1, 19, -1, -1, -1, -1}, // 18 - ZWJ after vowel + {-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1}, // 19 - Third coeng + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, // 20 - dependent vowel after a Robat +}; + + +// #define KHMER_DEBUG +#ifdef KHMER_DEBUG +#define KHDEBUG tqDebug +#else +#define KHDEBUG if(0) tqDebug +#endif + +// Given an input string of characters and a location in which to start looking +// calculate, using the state table, which one is the last character of the syllable +// that starts in the starting position. +// +static inline int khmer_nextSyllableBoundary(const TQString &s, int start, int end, bool *invalid) +{ + *invalid = FALSE; + const TQChar *uc = s.unicode() + start; + int state = 0; + int pos = start; + + while (pos < end) { + KhmerCharClass charClass = getKhmerCharClass(*uc); + if (pos == start) { + *invalid = (charClass > 0) && ! (charClass & CF_CONSONANT); + } + state = khmerStateTable[state][charClass & CF_CLASS_MASK]; + + KHDEBUG("state[%d]=%d class=%8lx (uc=%4x)", pos - start, state, + charClass, uc->unicode() ); + + if (state < 0) { + break; + } + ++uc; + ++pos; + } + return pos; +} + + +#ifndef TQT_NO_XFTFREETYPE +static const TQOpenType::Features khmer_features[] = { + { FT_MAKE_TAG( 'p', 'r', 'e', 'f' ), PreFormProperty }, + { FT_MAKE_TAG( 'b', 'l', 'w', 'f' ), BelowFormProperty }, + { FT_MAKE_TAG( 'a', 'b', 'v', 'f' ), AboveFormProperty }, + { FT_MAKE_TAG( 'p', 's', 't', 'f' ), PostFormProperty }, + { FT_MAKE_TAG( 'p', 'r', 'e', 's' ), PreSubstProperty }, + { FT_MAKE_TAG( 'b', 'l', 'w', 's' ), BelowSubstProperty }, + { FT_MAKE_TAG( 'a', 'b', 'v', 's' ), AboveSubstProperty }, + { FT_MAKE_TAG( 'p', 's', 't', 's' ), PostSubstProperty }, + { FT_MAKE_TAG( 'c', 'l', 'i', 'g' ), CligProperty }, + { 0, 0 } +}; +#endif + + +static bool khmer_shape_syllable(TQOpenType *openType, TQShaperItem *item) +{ +#ifndef TQT_NO_XFTFREETYPE + if (openType) + openType->selectScript(TQFont::Khmer, khmer_features); +#endif + // according to the specs this is the max length one can get + // ### the real value should be smaller + assert(item->length < 13); + + KHDEBUG("syllable from %d len %d, str='%s'", item->from, item->length, + item->string->mid(item->from, item->length).utf8().data()); + + int len = 0; + int syllableEnd = item->from + item->length; + unsigned short reordered[16]; + unsigned char properties[16]; + enum { + AboveForm = 0x01, + PreForm = 0x02, + PostForm = 0x04, + BelowForm = 0x08 + }; + memset(properties, 0, 16*sizeof(unsigned char)); + +#ifdef KHMER_DEBUG + tqDebug("original:"); + for (int i = from; i < syllableEnd; i++) { + tqDebug(" %d: %4x", i, string[i].unicode()); + } +#endif + + // write a pre vowel or the pre part of a split vowel first + // and look out for coeng + ro. RO is the only vowel of type 2, and + // therefore the only one that requires saving space before the base. + // + int coengRo = -1; // There is no Coeng Ro, if found this value will change + int i; + for (i = item->from; i < syllableEnd; i += 1) { + KhmerCharClass charClass = getKhmerCharClass(item->string->at(i)); + + // if a split vowel, write the pre part. In Khmer the pre part + // is the same for all split vowels, same glyph as pre vowel C_VOWEL_E + if (charClass & CF_SPLIT_VOWEL) { + reordered[len] = C_VOWEL_E; + properties[len] = PreForm; + ++len; + break; // there can be only one vowel + } + // if a vowel with pos before write it out + if (charClass & CF_POS_BEFORE) { + reordered[len] = item->string->at(i).unicode(); + properties[len] = PreForm; + ++len; + break; // there can be only one vowel + } + // look for coeng + ro and remember position + // works because coeng + ro is always in front of a vowel (if there is a vowel) + // and because CC_CONSONANT2 is enough to identify it, as it is the only consonant + // with this flag + if ( (charClass & CF_COENG) && (i + 1 < syllableEnd) && + ( (getKhmerCharClass(item->string->at(i+1)) & CF_CLASS_MASK) == CC_CONSONANT2) ) { + coengRo = i; + } + } + + // write coeng + ro if found + if (coengRo > -1) { + reordered[len] = C_COENG; + properties[len] = PreForm; + ++len; + reordered[len] = C_RO; + properties[len] = PreForm; + ++len; + } + + // shall we add a dotted circle? + // If in the position in which the base should be (first char in the string) there is + // a character that has the Dotted circle flag (a character that cannot be a base) + // then write a dotted circle + if (getKhmerCharClass(item->string->at(item->from)) & CF_DOTTED_CIRCLE) { + reordered[len] = C_DOTTED_CIRCLE; + ++len; + } + + // copy what is left to the output, skipping before vowels and + // coeng Ro if they are present + for (i = item->from; i < syllableEnd; i += 1) { + TQChar uc = item->string->at(i); + KhmerCharClass charClass = getKhmerCharClass(uc); + + // skip a before vowel, it was already processed + if (charClass & CF_POS_BEFORE) { + continue; + } + + // skip coeng + ro, it was already processed + if (i == coengRo) { + i += 1; + continue; + } + + switch (charClass & CF_POS_MASK) + { + case CF_POS_ABOVE : + reordered[len] = uc.unicode(); + properties[len] = AboveForm; + ++len; + break; + + case CF_POS_AFTER : + reordered[len] = uc.unicode(); + properties[len] = PostForm; + ++len; + break; + + case CF_POS_BELOW : + reordered[len] = uc.unicode(); + properties[len] = BelowForm; + ++len; + break; + + default: + // assign the correct flags to a coeng consonant + // Consonants of type 3 are taged as Post forms and those type 1 as below forms + if ( (charClass & CF_COENG) && i + 1 < syllableEnd ) { + unsigned char property = (getKhmerCharClass(item->string->at(i+1)) & CF_CLASS_MASK) == CC_CONSONANT3 ? + PostForm : BelowForm; + reordered[len] = uc.unicode(); + properties[len] = property; + ++len; + i += 1; + reordered[len] = item->string->at(i).unicode(); + properties[len] = property; + ++len; + break; + } + + // if a shifter is followed by an above vowel change the shifter to below form, + // an above vowel can have two possible positions i + 1 or i + 3 + // (position i+1 corresponds to unicode 3, position i+3 to Unicode 4) + // and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two + // different positions, right after the shifter or after a vowel (Unicode 4) + if ( (charClass & CF_SHIFTER) && (i + 1 < syllableEnd) ) { + if (getKhmerCharClass(item->string->at(i+1)) & CF_ABOVE_VOWEL ) { + reordered[len] = uc.unicode(); + properties[len] = BelowForm; + ++len; + break; + } + if (i + 2 < syllableEnd && + (item->string->at(i+1).unicode() == C_VOWEL_AA) && + (item->string->at(i+2).unicode() == C_SIGN_NIKAHIT) ) + { + reordered[len] = uc.unicode(); + properties[len] = BelowForm; + ++len; + break; + } + if (i + 3 < syllableEnd && (getKhmerCharClass(item->string->at(i+3)) & CF_ABOVE_VOWEL) ) { + reordered[len] = uc.unicode(); + properties[len] = BelowForm; + ++len; + break; + } + if (i + 4 < syllableEnd && + (item->string->at(i+3).unicode() == C_VOWEL_AA) && + (item->string->at(i+4).unicode() == C_SIGN_NIKAHIT) ) + { + reordered[len] = uc.unicode(); + properties[len] = BelowForm; + ++len; + break; + } + } + + // default - any other characters + reordered[len] = uc.unicode(); + ++len; + break; + } // switch + } // for + + if (item->font->stringToCMap((const TQChar *)reordered, len, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + KHDEBUG("after shaping: len=%d", len); + for (i = 0; i < len; i++) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = FALSE; + item->attributes[i].justification = 0; + item->attributes[i].zeroWidth = FALSE; + KHDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]); + } + + // now we have the syllable in the right order, and can start running it through open type. + +#ifndef TQT_NO_XFTFREETYPE + if (openType) { + uint where[16]; + + for (int i = 0; i < len; ++i) { + where[i] = ~(PreSubstProperty + | BelowSubstProperty + | AboveSubstProperty + | PostSubstProperty + | CligProperty + | PositioningProperties); + if (properties[i] == PreForm) + where[i] &= ~PreFormProperty; + else if (properties[i] == BelowForm) + where[i] &= ~BelowFormProperty; + else if (properties[i] == AboveForm) + where[i] &= ~AboveFormProperty; + else if (properties[i] == PostForm) + where[i] &= ~PostFormProperty; + } + + openType->shape(item, where); + if (!openType->positionAndAdd(item, FALSE)) + return FALSE; + } else +#endif + { + KHDEBUG("Not using openType"); + Q_UNUSED(openType); + } + + item->attributes[0].clusterStart = TRUE; + return TRUE; +} + +static bool khmer_shape(TQShaperItem *item) +{ + assert(item->script == TQFont::Khmer); + +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + if (openType && !openType->supportsScript(item->script)) + openType = 0; +#else + TQOpenType *openType = 0; +#endif + unsigned short *logClusters = item->log_clusters; + + TQShaperItem syllable = *item; + int first_glyph = 0; + + int sstart = item->from; + int end = sstart + item->length; + KHDEBUG("khmer_shape: from %d length %d", item->from, item->length); + while (sstart < end) { + bool invalid; + int send = khmer_nextSyllableBoundary(*item->string, sstart, end, &invalid); + KHDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, + invalid ? "TRUE" : "FALSE"); + syllable.from = sstart; + syllable.length = send-sstart; + syllable.glyphs = item->glyphs + first_glyph; + syllable.offsets = item->offsets + first_glyph; + syllable.advances = item->advances + first_glyph; + syllable.attributes = item->attributes + first_glyph; + syllable.num_glyphs = item->num_glyphs - first_glyph; + if (!khmer_shape_syllable(openType, &syllable)) { + KHDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); + item->num_glyphs += syllable.num_glyphs; + return FALSE; + } + item->has_positioning |= syllable.has_positioning; + + // fix logcluster array + KHDEBUG("syllable:"); + int i; + for (i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) + KHDEBUG(" %d -> glyph %x", i, item->glyphs[i]); + KHDEBUG(" logclusters:"); + for (i = sstart; i < send; ++i) { + KHDEBUG(" %d -> glyph %d", i, first_glyph); + logClusters[i-item->from] = first_glyph; + } + sstart = send; + first_glyph += syllable.num_glyphs; + } + item->num_glyphs = first_glyph; + return TRUE; +} + +static void khmer_attributes( int script, const TQString &text, int from, int len, TQCharAttributes *attributes ) +{ + Q_UNUSED(script); + + int end = from + len; + const TQChar *uc = text.unicode() + from; + attributes += from; + int i = 0; + while ( i < len ) { + bool invalid; + int boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from; + + attributes[i].charStop = TRUE; + + if ( boundary > len-1 ) boundary = len; + i++; + while ( i < boundary ) { + attributes[i].charStop = FALSE; + ++uc; + ++i; + } + assert( i == boundary ); + } +} + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Myanmar +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +enum MymrCharClassValues +{ + Mymr_CC_RESERVED = 0, + Mymr_CC_CONSONANT = 1, /* Consonant of type 1, that has subscript form */ + Mymr_CC_CONSONANT2 = 2, /* Consonant of type 2, that has no subscript form */ + Mymr_CC_NGA = 3, /* Consonant NGA */ + Mymr_CC_YA = 4, /* Consonant YA */ + Mymr_CC_RA = 5, /* Consonant RA */ + Mymr_CC_WA = 6, /* Consonant WA */ + Mymr_CC_HA = 7, /* Consonant HA */ + Mymr_CC_IND_VOWEL = 8, /* Independent vowel */ + Mymr_CC_ZERO_WIDTH_NJ_MARK = 9, /* Zero Width non joiner character (0x200C) */ + Mymr_CC_VIRAMA = 10, /* Subscript consonant combining character */ + Mymr_CC_PRE_VOWEL = 11, /* Dependent vowel, prebase (Vowel e) */ + Mymr_CC_BELOW_VOWEL = 12, /* Dependent vowel, prebase (Vowel u, uu) */ + Mymr_CC_ABOVE_VOWEL = 13, /* Dependent vowel, prebase (Vowel i, ii, ai) */ + Mymr_CC_POST_VOWEL = 14, /* Dependent vowel, prebase (Vowel aa) */ + Mymr_CC_SIGN_ABOVE = 15, + Mymr_CC_SIGN_BELOW = 16, + Mymr_CC_SIGN_AFTER = 17, + Mymr_CC_ZERO_WIDTH_J_MARK = 18, /* Zero width joiner character */ + Mymr_CC_COUNT = 19 /* This is the number of character classes */ +}; + +enum MymrCharClassFlags +{ + Mymr_CF_CLASS_MASK = 0x0000FFFF, + + Mymr_CF_CONSONANT = 0x01000000, /* flag to speed up comparing */ + Mymr_CF_MEDIAL = 0x02000000, /* flag to speed up comparing */ + Mymr_CF_IND_VOWEL = 0x04000000, /* flag to speed up comparing */ + Mymr_CF_DEP_VOWEL = 0x08000000, /* flag to speed up comparing */ + Mymr_CF_DOTTED_CIRCLE = 0x10000000, /* add a dotted circle if a character with this flag is the first in a syllable */ + Mymr_CF_VIRAMA = 0x20000000, /* flag to speed up comparing */ + + /* position flags */ + Mymr_CF_POS_BEFORE = 0x00080000, + Mymr_CF_POS_BELOW = 0x00040000, + Mymr_CF_POS_ABOVE = 0x00020000, + Mymr_CF_POS_AFTER = 0x00010000, + Mymr_CF_POS_MASK = 0x000f0000, + + Mymr_CF_AFTER_KINZI = 0x00100000 +}; + +/* Characters that get refrered to by name */ +enum MymrChar +{ + Mymr_C_SIGN_ZWNJ = 0x200C, + Mymr_C_SIGN_ZWJ = 0x200D, + Mymr_C_DOTTED_CIRCLE = 0x25CC, + Mymr_C_RA = 0x101B, + Mymr_C_YA = 0x101A, + Mymr_C_NGA = 0x1004, + Mymr_C_VOWEL_E = 0x1031, + Mymr_C_VIRAMA = 0x1039 +}; + +enum +{ + Mymr_xx = Mymr_CC_RESERVED, + Mymr_c1 = Mymr_CC_CONSONANT | Mymr_CF_CONSONANT | Mymr_CF_POS_BELOW, + Mymr_c2 = Mymr_CC_CONSONANT2 | Mymr_CF_CONSONANT, + Mymr_ng = Mymr_CC_NGA | Mymr_CF_CONSONANT | Mymr_CF_POS_ABOVE, + Mymr_ya = Mymr_CC_YA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_AFTER | Mymr_CF_AFTER_KINZI, + Mymr_ra = Mymr_CC_RA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BEFORE, + Mymr_wa = Mymr_CC_WA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW, + Mymr_ha = Mymr_CC_HA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW, + Mymr_id = Mymr_CC_IND_VOWEL | Mymr_CF_IND_VOWEL, + Mymr_vi = Mymr_CC_VIRAMA | Mymr_CF_VIRAMA | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE, + Mymr_dl = Mymr_CC_PRE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BEFORE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, + Mymr_db = Mymr_CC_BELOW_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, + Mymr_da = Mymr_CC_ABOVE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, + Mymr_dr = Mymr_CC_POST_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, + Mymr_sa = Mymr_CC_SIGN_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_ABOVE | Mymr_CF_AFTER_KINZI, + Mymr_sb = Mymr_CC_SIGN_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_BELOW | Mymr_CF_AFTER_KINZI, + Mymr_sp = Mymr_CC_SIGN_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI +}; + + +typedef int MymrCharClass; + + +static const MymrCharClass mymrCharClasses[] = +{ + Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_ng, Mymr_c1, Mymr_c1, Mymr_c1, + Mymr_c1, Mymr_c1, Mymr_c2, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, /* 1000 - 100F */ + Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, Mymr_c1, + Mymr_c1, Mymr_c1, Mymr_ya, Mymr_ra, Mymr_c1, Mymr_wa, Mymr_c1, Mymr_ha, /* 1010 - 101F */ + Mymr_c2, Mymr_c2, Mymr_xx, Mymr_id, Mymr_id, Mymr_id, Mymr_id, Mymr_id, + Mymr_xx, Mymr_id, Mymr_id, Mymr_xx, Mymr_dr, Mymr_da, Mymr_da, Mymr_db, /* 1020 - 102F */ + Mymr_db, Mymr_dl, Mymr_da, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_sa, Mymr_sb, + Mymr_sp, Mymr_vi, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1030 - 103F */ + Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, + Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1040 - 104F */ + Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, + Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, Mymr_xx, /* 1050 - 105F */ +}; + +static MymrCharClass +getMyanmarCharClass (const TQChar &ch) +{ + if (ch.unicode() == Mymr_C_SIGN_ZWJ) + return Mymr_CC_ZERO_WIDTH_J_MARK; + + if (ch.unicode() == Mymr_C_SIGN_ZWNJ) + return Mymr_CC_ZERO_WIDTH_NJ_MARK; + + if (ch.unicode() < 0x1000 || ch.unicode() > 0x105f) + return Mymr_CC_RESERVED; + + return mymrCharClasses[ch.unicode() - 0x1000]; +} + +static const signed char mymrStateTable[][Mymr_CC_COUNT] = +{ +// xx c1, c2 ng ya ra wa ha id zwnj vi dl db da dr sa sb sp zwj + { 1, 4, 4, 2, 4, 4, 4, 4, 24, 1, 27, 17, 18, 19, 20, 21, 1, 1, 4}, // 0 - ground state + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 1 - exit state (or sp to the right of the syllable) + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 17, 18, 19, 20, 21, -1, -1, 4}, // 2 - NGA + {-1, 4, 4, 4, 4, 4, 4, 4, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 3 - Virama after NGA + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 17, 18, 19, 20, 21, 1, 1, -1}, // 4 - Base consonant + {-2, 6, -2, -2, 7, 8, 9, 10, -2, 23, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 5 - First virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 17, 18, 19, 20, 21, -1, -1, -1}, // 6 - c1 after virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, // 7 - ya after virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, // 8 - ra after virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, -1, -1}, // 9 - wa after virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, // 10 - ha after virama + {-1, -1, -1, -1, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 11 - Virama after NGA+zwj + {-2, -2, -2, -2, -2, -2, 13, 14, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 12 - Second virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 17, 18, 19, 20, 21, -1, -1, -1}, // 13 - wa after virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, // 14 - ha after virama + {-2, -2, -2, -2, -2, -2, -2, 16, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 15 - Third virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, -1, -1, -1}, // 16 - ha after virama + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 1, 1, -1}, // 17 - dl, Dependent vowel e + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, 21, 1, 1, -1}, // 18 - db, Dependent vowel u,uu + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1}, // 19 - da, Dependent vowel i,ii,ai + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, 1, 1, -1}, // 20 - dr, Dependent vowel aa + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, // 21 - sa, Sign anusvara + {-1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 22 - atha + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1}, // 23 - zwnj for atha + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1}, // 24 - Independent vowel + {-2, -2, -2, -2, 26, 26, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, // 25 - Virama after subscript consonant + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 17, 18, 19, 20, 21, -1, 1, -1}, // 26 - ra/ya after subscript consonant + virama + {-1, 6, -1, -1, 7, 8, 9, 10, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // 27 - Virama after ground state +// exit state -2 is for invalid order of medials and combination of invalids +// with virama where virama should treat as start of next syllable +}; + + + +// #define MYANMAR_DEBUG +#ifdef MYANMAR_DEBUG +#define MMDEBUG tqDebug +#else +#define MMDEBUG if(0) tqDebug +#endif + +// Given an input string of characters and a location in which to start looking +// calculate, using the state table, which one is the last character of the syllable +// that starts in the starting position. +// +static inline int myanmar_nextSyllableBoundary(const TQString &s, int start, int end, bool *invalid) +{ + *invalid = FALSE; + const TQChar *uc = s.unicode() + start; + int state = 0; + int pos = start; + + while (pos < end) { + MymrCharClass charClass = getMyanmarCharClass(*uc); + state = mymrStateTable[state][charClass & Mymr_CF_CLASS_MASK]; + if (pos == start) + *invalid = charClass & Mymr_CF_DOTTED_CIRCLE; + + MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, uc->unicode() ); + + if (state < 0) { + if (state < -1) + --pos; + break; + } + ++uc; + ++pos; + } + return pos; +} + + +#ifndef TQT_NO_XFTFREETYPE +// ###### might have to change order of above and below forms and substitutions, +// but according to Unicode below comes before above +static const TQOpenType::Features myanmar_features[] = { + { FT_MAKE_TAG( 'p', 'r', 'e', 'f' ), PreFormProperty }, + { FT_MAKE_TAG( 'b', 'l', 'w', 'f' ), BelowFormProperty }, + { FT_MAKE_TAG( 'a', 'b', 'v', 'f' ), AboveFormProperty }, + { FT_MAKE_TAG( 'p', 's', 't', 'f' ), PostFormProperty }, + { FT_MAKE_TAG( 'p', 'r', 'e', 's' ), PreSubstProperty }, + { FT_MAKE_TAG( 'b', 'l', 'w', 's' ), BelowSubstProperty }, + { FT_MAKE_TAG( 'a', 'b', 'v', 's' ), AboveSubstProperty }, + { FT_MAKE_TAG( 'p', 's', 't', 's' ), PostSubstProperty }, + { FT_MAKE_TAG( 'r', 'l', 'i', 'g' ), CligProperty }, // Myanmar1 uses this instead of the other features + { 0, 0 } +}; +#endif + + +// Visual order before shaping should be: +// +// [Vowel Mark E] +// [Virama + Medial Ra] +// [Base] +// [Virama + Consonant] +// [Nga + Virama] (Kinzi) ### should probably come before post forms (medial ya) +// [Vowels] +// [Marks] +// +// This means that we can keep the logical order apart from having to +// move the pre vowel, medial ra and kinzi + +static bool myanmar_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool invalid) +{ +#ifndef TQT_NO_XFTFREETYPE + if (openType) + openType->selectScript(TQFont::Myanmar, myanmar_features); +#endif + // according to the table the max length of a syllable should be around 14 chars + assert(item->length < 32); + + MMDEBUG("\nsyllable from %d len %d, str='%s'", item->from, item->length, + item->string->mid(item->from, item->length).utf8().data()); + + const TQChar *uc = item->string->unicode() + item->from; +#ifdef MYANMAR_DEBUG + tqDebug("original:"); + for (int i = 0; i < item->length; i++) { + tqDebug(" %d: %4x", i, uc[i].unicode()); + } +#endif + int vowel_e = -1; + int kinzi = -1; + int medial_ra = -1; + int base = -1; + int i; + for (i = 0; i < item->length; ++i) { + ushort chr = uc[i].unicode(); + + if (chr == Mymr_C_VOWEL_E) { + vowel_e = i; + continue; + } + if (i == 0 + && chr == Mymr_C_NGA + && i + 2 < item->length + && uc[i+1].unicode() == Mymr_C_VIRAMA) { + int mc = getMyanmarCharClass(uc[i+2]); + //MMDEBUG("maybe kinzi: mc=%x", mc); + if ((mc & Mymr_CF_CONSONANT) == Mymr_CF_CONSONANT) { + kinzi = i; + continue; + } + } + if (base >= 0 + && chr == Mymr_C_VIRAMA + && i + 1 < item->length + && uc[i+1].unicode() == Mymr_C_RA) { + medial_ra = i; + continue; + } + if (base < 0) + base = i; + } + + MMDEBUG("\n base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base, vowel_e, kinzi, medial_ra); + int len = 0; + unsigned short reordered[32]; + unsigned char properties[32]; + enum { + AboveForm = 0x01, + PreForm = 0x02, + PostForm = 0x04, + BelowForm = 0x08 + }; + memset(properties, 0, 32*sizeof(unsigned char)); + + // write vowel_e if found + if (vowel_e >= 0) { + reordered[0] = Mymr_C_VOWEL_E; + len = 1; + } + // write medial_ra + if (medial_ra >= 0) { + reordered[len] = Mymr_C_VIRAMA; + reordered[len+1] = Mymr_C_RA; + properties[len] = PreForm; + properties[len+1] = PreForm; + len += 2; + } + + // shall we add a dotted circle? + // If in the position in which the base should be (first char in the string) there is + // a character that has the Dotted circle flag (a character that cannot be a base) + // then write a dotted circle + if (invalid) { + reordered[len] = C_DOTTED_CIRCLE; + ++len; + } + + bool lastWasVirama = FALSE; + int basePos = -1; + // copy the rest of the syllable to the output, inserting the kinzi + // at the correct place + for (i = 0; i < item->length; ++i) { + if (i == vowel_e) + continue; + if (i == medial_ra || i == kinzi) { + ++i; + continue; + } + + ushort chr = uc[i].unicode(); + MymrCharClass cc = getMyanmarCharClass(uc[i]); + if (kinzi >= 0 && i > base && (cc & Mymr_CF_AFTER_KINZI)) { + reordered[len] = Mymr_C_NGA; + reordered[len+1] = Mymr_C_VIRAMA; + properties[len-1] = AboveForm; + properties[len] = AboveForm; + len += 2; + kinzi = -1; + } + + if (lastWasVirama) { + int prop = 0; + switch(cc & Mymr_CF_POS_MASK) { + case Mymr_CF_POS_BEFORE: + prop = PreForm; + break; + case Mymr_CF_POS_BELOW: + prop = BelowForm; + break; + case Mymr_CF_POS_ABOVE: + prop = AboveForm; + break; + case Mymr_CF_POS_AFTER: + prop = PostForm; + break; + default: + break; + } + properties[len-1] = prop; + properties[len] = prop; + if(basePos >= 0 && basePos == len-2) + properties[len-2] = prop; + } + lastWasVirama = (chr == Mymr_C_VIRAMA); + if(i == base) + basePos = len; + + if ((chr != Mymr_C_SIGN_ZWNJ && chr != Mymr_C_SIGN_ZWJ) || !len) { + reordered[len] = chr; + ++len; + } + } + if (kinzi >= 0) { + reordered[len] = Mymr_C_NGA; + reordered[len+1] = Mymr_C_VIRAMA; + properties[len] = AboveForm; + properties[len+1] = AboveForm; + len += 2; + } + + if (item->font->stringToCMap((const TQChar *)reordered, len, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + + MMDEBUG("after shaping: len=%d", len); + for (i = 0; i < len; i++) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = FALSE; + item->attributes[i].justification = 0; + item->attributes[i].zeroWidth = FALSE; + MMDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]); + } + + // now we have the syllable in the right order, and can start running it through open type. + +#ifndef TQT_NO_XFTFREETYPE + if (openType) { + uint where[32]; + + for (int i = 0; i < len; ++i) { + where[i] = ~(PreSubstProperty + | BelowSubstProperty + | AboveSubstProperty + | PostSubstProperty + | CligProperty + | PositioningProperties); + if (properties[i] == PreForm) + where[i] &= ~PreFormProperty; + else if (properties[i] == BelowForm) + where[i] &= ~BelowFormProperty; + else if (properties[i] == AboveForm) + where[i] &= ~AboveFormProperty; + else if (properties[i] == PostForm) + where[i] &= ~PostFormProperty; + } + + openType->shape(item, where); + if (!openType->positionAndAdd(item, FALSE)) + return FALSE; + } else +#endif + { + MMDEBUG("Not using openType"); + Q_UNUSED(openType); + } + + item->attributes[0].clusterStart = TRUE; + return TRUE; +} + +static bool myanmar_shape(TQShaperItem *item) +{ + assert(item->script == TQFont::Myanmar); + +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + if (openType && !openType->supportsScript(item->script)) + openType = 0; +#else + TQOpenType *openType = 0; +#endif + unsigned short *logClusters = item->log_clusters; + + TQShaperItem syllable = *item; + int first_glyph = 0; + + int sstart = item->from; + int end = sstart + item->length; + MMDEBUG("myanmar_shape: from %d length %d", item->from, item->length); + while (sstart < end) { + bool invalid; + int send = myanmar_nextSyllableBoundary(*item->string, sstart, end, &invalid); + MMDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, + invalid ? "TRUE" : "FALSE"); + syllable.from = sstart; + syllable.length = send-sstart; + syllable.glyphs = item->glyphs + first_glyph; + syllable.offsets = item->offsets + first_glyph; + syllable.advances = item->advances + first_glyph; + syllable.attributes = item->attributes + first_glyph; + syllable.num_glyphs = item->num_glyphs - first_glyph; + if (!myanmar_shape_syllable(openType, &syllable, invalid)) { + MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); + item->num_glyphs += syllable.num_glyphs; + return FALSE; + } + item->has_positioning |= syllable.has_positioning; + + // fix logcluster array + MMDEBUG("syllable:"); + int i; + for (i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) + MMDEBUG(" %d -> glyph %x", i, item->glyphs[i]); + MMDEBUG(" logclusters:"); + for (i = sstart; i < send; ++i) { + MMDEBUG(" %d -> glyph %d", i, first_glyph); + logClusters[i-item->from] = first_glyph; + } + sstart = send; + first_glyph += syllable.num_glyphs; + } + item->num_glyphs = first_glyph; + return TRUE; +} + +static void myanmar_attributes( int script, const TQString &text, int from, int len, TQCharAttributes *attributes ) +{ + Q_UNUSED(script); + + int end = from + len; + const TQChar *uc = text.unicode() + from; + attributes += from; + int i = 0; + while ( i < len ) { + bool invalid; + int boundary = myanmar_nextSyllableBoundary( text, from+i, end, &invalid ) - from; + + attributes[i].charStop = TRUE; + attributes[i].softBreak = TRUE; + + if ( boundary > len-1 ) boundary = len; + i++; + while ( i < boundary ) { + attributes[i].charStop = FALSE; + attributes[i].softBreak = FALSE; + ++uc; + ++i; + } + assert( i == boundary ); + } +} + +// -------------------------------------------------------------------------------------------------------------------------------------------- +// +// Hangul +// +// -------------------------------------------------------------------------------------------------------------------------------------------- + +// Hangul is a syllable based script. Unicode reserves a large range +// for precomposed hangul, where syllables are already precomposed to +// their final glyph shape. In addition, a so called jamo range is +// defined, that can be used to express old Hangul. Modern hangul +// syllables can also be expressed as jamo, and should be composed +// into syllables. The operation is rather simple and mathematical. + +// Every hangul jamo is classified as being either a Leading consonant +// (L), and intermediat Vowel (V) or a trailing consonant (T). Modern +// hangul syllables (the ones in the precomposed area can be of type +// LV or LVT. +// +// Syllable breaks do _not_ occur between: +// +// L L, V or precomposed +// V, LV V, T +// LVT, T T +// +// A standard syllable is of the form L+V+T*. The above rules allow +// nonstandard syllables L*V*T*. To transform them into standard +// syllables fill characers L_f and V_f can be inserted. + +enum { + Hangul_SBase = 0xac00, + Hangul_LBase = 0x1100, + Hangul_VBase = 0x1161, + Hangul_TBase = 0x11a7, + Hangul_SCount = 11172, + Hangul_LCount = 19, + Hangul_VCount = 21, + Hangul_TCount = 28, + Hangul_NCount = 21*28 +}; + +static inline bool hangul_isPrecomposed(unsigned short uc) { + return (uc >= Hangul_SBase && uc < Hangul_SBase + Hangul_SCount); +} + +static inline bool hangul_isLV(unsigned short uc) { + return ((uc - Hangul_SBase) % Hangul_TCount == 0); +} + +enum HangulType { + L, + V, + T, + LV, + LVT, + X +}; + +static inline HangulType hangul_type(unsigned short uc) { + if (uc > Hangul_SBase && uc < Hangul_SBase + Hangul_SCount) + return hangul_isLV(uc) ? LV : LVT; + if (uc < Hangul_LBase || uc > 0x11ff) + return X; + if (uc < Hangul_VBase) + return L; + if (uc < Hangul_TBase) + return V; + return T; +} + +static int hangul_nextSyllableBoundary(const TQString &s, int start, int end) +{ + const TQChar *uc = s.unicode() + start; + + HangulType state = hangul_type(uc->unicode()); + int pos = 1; + + while (pos < end - start) { + HangulType newState = hangul_type(uc[pos].unicode()); + switch(newState) { + case X: + goto finish; + case L: + case V: + case T: + if (state > newState) + goto finish; + state = newState; + break; + case LV: + if (state > L) + goto finish; + state = V; + break; + case LVT: + if (state > L) + goto finish; + state = T; + } + ++pos; + } + + finish: + return start+pos; +} + +#ifndef TQT_NO_XFTFREETYPE +static const TQOpenType::Features hangul_features [] = { + { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, + { FT_MAKE_TAG('l', 'j', 'm', 'o'), CcmpProperty }, + { FT_MAKE_TAG('j', 'j', 'm', 'o'), CcmpProperty }, + { FT_MAKE_TAG('t', 'j', 'm', 'o'), CcmpProperty }, + { 0, 0 } +}; +#endif + +static bool hangul_shape_syllable(TQOpenType *openType, TQShaperItem *item) +{ + Q_UNUSED(openType) + const TQChar *ch = item->string->unicode() + item->from; + + int i; + unsigned short composed = 0; + // see if we can compose the syllable into a modern hangul + if (item->length == 2) { + int LIndex = ch[0].unicode() - Hangul_LBase; + int VIndex = ch[1].unicode() - Hangul_VBase; + if (LIndex >= 0 && LIndex < Hangul_LCount && + VIndex >= 0 && VIndex < Hangul_VCount) + composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + Hangul_SBase; + } else if (item->length == 3) { + int LIndex = ch[0].unicode() - Hangul_LBase; + int VIndex = ch[1].unicode() - Hangul_VBase; + int TIndex = ch[2].unicode() - Hangul_TBase; + if (LIndex >= 0 && LIndex < Hangul_LCount && + VIndex >= 0 && VIndex < Hangul_VCount && + TIndex >= 0 && TIndex < Hangul_TCount) + composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + TIndex + Hangul_SBase; + } + + + int len = item->length; + TQChar c(composed); + + // ### icc says 'chars' is unused + // const TQChar *chars = ch; + + // if we have a modern hangul use the composed form + if (composed) { + // chars = &c; + len = 1; + } + + if (item->font->stringToCMap(ch, len, item->glyphs, item->advances, + &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError) + return FALSE; + for (i = 0; i < len; i++) { + item->attributes[i].mark = FALSE; + item->attributes[i].clusterStart = FALSE; + item->attributes[i].justification = 0; + item->attributes[i].zeroWidth = FALSE; + IDEBUG(" %d: %4x", i, ch[i].unicode()); + } + +#ifndef TQT_NO_XFTFREETYPE + if (openType && !composed) { + + TQVarLengthArray logClusters(len); + for (i = 0; i < len; ++i) + logClusters[i] = i; + item->log_clusters = logClusters.data(); + + openType->shape(item); + if (!openType->positionAndAdd(item, FALSE)) + return FALSE; + + } +#endif + + item->attributes[0].clusterStart = TRUE; + return TRUE; +} + +static bool hangul_shape(TQShaperItem *item) +{ + Q_ASSERT(item->script == TQFont::Hangul); + + const TQChar *uc = item->string->unicode() + item->from; + + bool allPrecomposed = TRUE; + for (int i = 0; i < item->length; ++i) { + if (!hangul_isPrecomposed(uc[i].unicode())) { + allPrecomposed = FALSE; + break; + } + } + + if (!allPrecomposed) { +#ifndef TQT_NO_XFTFREETYPE + TQOpenType *openType = item->font->openType(); + if (openType && !openType->supportsScript(item->script)) + openType = 0; + if (openType) + openType->selectScript(TQFont::Hangul, hangul_features); +#else + TQOpenType *openType = 0; +#endif + + unsigned short *logClusters = item->log_clusters; + + TQShaperItem syllable = *item; + int first_glyph = 0; + + int sstart = item->from; + int end = sstart + item->length; + while (sstart < end) { + int send = hangul_nextSyllableBoundary(*(item->string), sstart, end); + + syllable.from = sstart; + syllable.length = send-sstart; + syllable.glyphs = item->glyphs + first_glyph; + syllable.offsets = item->offsets + first_glyph; + syllable.advances = item->advances + first_glyph; + syllable.attributes = item->attributes + first_glyph; + syllable.num_glyphs = item->num_glyphs - first_glyph; + if (!hangul_shape_syllable(openType, &syllable)) { + item->num_glyphs += syllable.num_glyphs; + return FALSE; + } + item->has_positioning |= syllable.has_positioning; + // fix logcluster array + for (int i = sstart; i < send; ++i) + logClusters[i-item->from] = first_glyph; + sstart = send; + first_glyph += syllable.num_glyphs; + } + item->num_glyphs = first_glyph; + return TRUE; + } + + return basic_shape(item); +} + +static void hangul_attributes(int script, const TQString &text, int from, int len, TQCharAttributes *attributes) +{ + Q_UNUSED(script); + + int end = from + len; + const TQChar *uc = text.unicode() + from; + attributes += from; + int i = 0; + while (i < len) { + int boundary = hangul_nextSyllableBoundary(text, from+i, end) - from; + + attributes[i].charStop = TRUE; + + if (boundary > len-1) boundary = len; + i++; + while (i < boundary) { + attributes[i].charStop = FALSE; + ++uc; + ++i; + } + assert(i == boundary); + } +} + +// ----------------------------------------------------------------------------------------------- +// +// The script engine jump table +// +// ----------------------------------------------------------------------------------------------- + +const q_scriptEngine scriptEngines[] = { + // Latin, + { basic_shape, 0 }, + // Greek, + { basic_shape, 0 }, + // Cyrillic, + { basic_shape, 0 }, + // Armenian, + { basic_shape, 0 }, + // Georgian, + { basic_shape, 0 }, + // Runic, + { basic_shape, 0 }, + // Ogham, + { basic_shape, 0 }, + // SpacingModifiers, + { basic_shape, 0 }, + // CombiningMarks, + { basic_shape, 0 }, + + // // Middle Eastern Scripts + // Hebrew, + { hebrew_shape, 0 }, + // Arabic, + { arabic_shape, 0 }, + // Syriac, + { syriac_shape, 0 }, + // Thaana, + { thaana_shape, 0 }, + + // // South and Southeast Asian Scripts + // Devanagari, + { indic_shape, indic_attributes }, + // Bengali, + { indic_shape, indic_attributes }, + // Gurmukhi, + { indic_shape, indic_attributes }, + // Gujarati, + { indic_shape, indic_attributes }, + // Oriya, + { indic_shape, indic_attributes }, + // Tamil, + { indic_shape, indic_attributes }, + // Telugu, + { indic_shape, indic_attributes }, + // Kannada, + { indic_shape, indic_attributes }, + // Malayalam, + { indic_shape, indic_attributes }, + // Sinhala, + { indic_shape, indic_attributes }, + // Thai, + { basic_shape, thai_attributes }, + // Lao, + { basic_shape, thai_attributes }, + // Tibetan, + { tibetan_shape, tibetan_attributes }, + // Myanmar, + { myanmar_shape, myanmar_attributes }, + // Khmer, + { khmer_shape, khmer_attributes }, + + // // East Asian Scripts + // Han, + { basic_shape, 0 }, + // Hiragana, + { basic_shape, 0 }, + // Katakana, + { basic_shape, 0 }, + // Hangul, + { hangul_shape, hangul_attributes }, + // Bopomofo, + { basic_shape, 0 }, + // Yi, + { basic_shape, 0 }, + + // // Additional Scripts + // Ethiopic, + { basic_shape, 0 }, + // Cherokee, + { basic_shape, 0 }, + // CanadianAboriginal, + { basic_shape, 0 }, + // Mongolian, + { basic_shape, 0 }, + + // // Symbols + // CurrencySymbols, + { basic_shape, 0 }, + // LetterlikeSymbols, + { basic_shape, 0 }, + // NumberForms, + { basic_shape, 0 }, + // MathematicalOperators, + { basic_shape, 0 }, + // TechnicalSymbols, + { basic_shape, 0 }, + // GeometricSymbols, + { basic_shape, 0 }, + // MiscellaneousSymbols, + { basic_shape, 0 }, + // EnclosedAndSquare, + { basic_shape, 0 }, + // Braille, + { basic_shape, 0 }, + + // Unicode, + { basic_shape, 0 }, + //Tagalog, + { basic_shape, 0 }, + //Hanunoo, + { basic_shape, 0 }, + //Buhid, + { basic_shape, 0 }, + //Tagbanwa, + { basic_shape, 0 }, + // KatakanaHalfWidth + { basic_shape, 0 }, + // Limbu + { basic_shape, 0 }, + // TaiLe + { basic_shape, 0 } +}; diff --git a/src/kernel/tqsimplerichtext.cpp b/src/kernel/tqsimplerichtext.cpp index eccf9190d..4c98f1fd3 100644 --- a/src/kernel/tqsimplerichtext.cpp +++ b/src/kernel/tqsimplerichtext.cpp @@ -41,7 +41,7 @@ #include "tqsimplerichtext.h" #ifndef TQT_NO_RICHTEXT -#include "qrichtext_p.h" +#include "tqrichtext_p.h" #include "ntqapplication.h" class TQSimpleRichTextData diff --git a/src/kernel/tqsizegrip.cpp b/src/kernel/tqsizegrip.cpp index 18ff03d28..017c3e6a0 100644 --- a/src/kernel/tqsizegrip.cpp +++ b/src/kernel/tqsizegrip.cpp @@ -47,7 +47,7 @@ #include "tqstyle.h" #if defined(TQ_WS_X11) -#include "qt_x11_p.h" +#include "tqt_x11_p.h" extern Atom qt_sizegrip; // defined in qapplication_x11.cpp #elif defined (TQ_WS_WIN ) #include "tqobjectlist.h" diff --git a/src/kernel/tqstylesheet.cpp b/src/kernel/tqstylesheet.cpp index dbc8d4670..c03cc792e 100644 --- a/src/kernel/tqstylesheet.cpp +++ b/src/kernel/tqstylesheet.cpp @@ -42,7 +42,7 @@ #ifndef TQT_NO_RICHTEXT -#include "private/qrichtext_p.h" +#include "private/tqrichtext_p.h" #include "tqlayout.h" #include "tqpainter.h" #include "tqcleanuphandler.h" diff --git a/src/kernel/tqt3.h b/src/kernel/tqt3.h index 8a04bdf30..cff4b0895 100644 --- a/src/kernel/tqt3.h +++ b/src/kernel/tqt3.h @@ -272,30 +272,30 @@ #include #if defined( QT_MOC_CPP ) || defined( QT_H_CPP ) || defined( Q_OS_MACX ) -#include -#include -#include "private/qcom_p.h" +#include +#include +#include "private/tqcom_p.h" #include "private/tqimageformatinterface_p.h" #include "private/tqisciicodec_p.h" #include "private/tqlayoutengine_p.h" -#include "private/qcomlibrary_p.h" -#include "private/qeffects_p.h" +#include "private/tqcomlibrary_p.h" +#include "private/tqeffects_p.h" #include "private/tqgpluginmanager_p.h" -#include "private/qinternal_p.h" +#include "private/tqinternal_p.h" #include "private/tqsqldriverinterface_p.h" #include "private/tqsqlmanager_p.h" #include "private/qlock_p.h" #include "private/tqcomponentfactory_p.h" #include "private/tqstyleinterface_p.h" -#include "private/qrichtext_p.h" -#include "private/qsvgdevice_p.h" +#include "private/tqrichtext_p.h" +#include "private/tqsvgdevice_p.h" #include "private/tqfontcodecs_p.h" #include "private/tqtextcodecinterface_p.h" -#include "private/qpsprinter_p.h" -#include "private/qtitlebar_p.h" -#include "private/qucom_p.h" -#include "private/qucomextra_p.h" -#include "private/qpluginmanager_p.h" +#include "private/tqpsprinter_p.h" +#include "private/tqtitlebar_p.h" +#include "private/tqucom_p.h" +#include "private/tqucomextra_p.h" +#include "private/tqpluginmanager_p.h" #include "private/tqdir_p.h" #include "private/tqsettings_p.h" #include "private/tqsqlextension_p.h" diff --git a/src/kernel/tqt_x11.pri b/src/kernel/tqt_x11.pri new file mode 100644 index 000000000..c81055eb3 --- /dev/null +++ b/src/kernel/tqt_x11.pri @@ -0,0 +1,23 @@ +unix { + !xinerama:DEFINES += TQT_NO_XINERAMA + !xshape:DEFINES += TQT_NO_SHAPE + !xcursor:DEFINES += TQT_NO_XCURSOR + !xrandr:DEFINES += TQT_NO_XRANDR + !xrender:DEFINES += TQT_NO_XRENDER + !xftfreetype:DEFINES += TQT_NO_XFTFREETYPE + !xkb:DEFINES += TQT_NO_XKB + xft2header:DEFINES+=QT_USE_XFT2_HEADER + + SOURCES += $$KERNEL_CPP/qtaddons_x11.cpp + PRECOMPILED_HEADER = kernel/qt_pch.h + + SOURCES += $$KERNEL_CPP/tqttdeintegration_x11.cpp + HEADERS += $$KERNEL_H/tqttdeintegration_x11_p.h +} + +nas { + DEFINES += QT_NAS_SUPPORT + LIBS += -laudio -lXt +} + +!x11sm:DEFINES += TQT_NO_SM_SUPPORT diff --git a/src/kernel/tqt_x11_p.h b/src/kernel/tqt_x11_p.h new file mode 100644 index 000000000..5d807238a --- /dev/null +++ b/src/kernel/tqt_x11_p.h @@ -0,0 +1,280 @@ +/**************************************************************************** +** +** Includes X11 system header files. +** +** Created : 981123 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQT_X11_H +#define TQT_X11_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of q*_x11.cpp. This header file may change from version to version +// without notice, or even be removed. +// +// + + +#ifndef QT_H +#include "tqwindowdefs.h" +#endif // QT_H + +// the following is necessary to work around breakage in many versions +// of XFree86's Xlib.h still in use +// ### which versions? +#if defined(_XLIB_H_) // crude hack, but... +#error "cannot include before this file" +#endif +#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback +#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback +#define XSetIMValues qt_XSetIMValues +#include +#undef XRegisterIMInstantiateCallback +#undef XUnregisterIMInstantiateCallback +#undef XSetIMValues + +#include +#include +#include + + +//#define TQT_NO_SHAPE +#ifdef TQT_NO_SHAPE +#define XShapeCombineRegion(a,b,c,d,e,f,g) +#define XShapeCombineMask(a,b,c,d,e,f,g) +#else +#include +#endif // TQT_NO_SHAPE + + +// the wacom tablet (currently just the IRIX version) +#if defined (QT_TABLET_SUPPORT) +# include +#if defined (Q_OS_IRIX) +# include // wacom driver defines for IRIX (quite handy) +#endif +#endif // QT_TABLET_SUPPORT + + +// #define TQT_NO_XINERAMA +#ifndef TQT_NO_XINERAMA +# if 0 // ### Xsun, but how to detect it? +// Xinerama is only supported in Solaris 7 with patches 107648/108376 and +// Solaris 8 or above which introduce the X11R6.4 Xserver. +// To switch the Xinerama functionality on, you need to add the "+xinerama" +// argument to the Xsun start line. +// At least Solaris 7 and 8 are missing Xinerama system headers and function +// declarations (bug 4284701). +// The Xinerama API is not documented. In theory it could change but it +// probably won't because Sun are using it in at least dtlogin (bug 4221829). +extern "C" Bool XPanoramiXQueryExtension( + Display*, + int*, + int* +); +extern "C" Status XPanoramiXQueryVersion( + Display*, + int*, + int* +); +extern "C" Status XPanoramiXGetState( + Display*, + Drawable, + XPanoramiXInfo* +); +extern "C" Status XPanoramiXGetScreenCount( + Display *, + Drawable, + XPanoramiXInfo* +); +extern "C" Status XPanoramiXGetScreenSize( + Display*, + Drawable, + int, + XPanoramiXInfo* +); +# else // XFree86 +// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3). +extern "C" { +# include +} +# endif +#endif // TQT_NO_XINERAMA + +// #define TQT_NO_XRANDR +#ifndef TQT_NO_XRANDR +# include +#endif // TQT_NO_XRANDR + +// #define TQT_NO_XRENDER +#ifndef TQT_NO_XRENDER +# include +// #define TQT_NO_XFTFREETYPE +# ifndef TQT_NO_XFTFREETYPE +// This hacks around the freetype poeple putting an #error into freetype.h in 2.1.7, making +// it impossible to use an updated freetype with older Xft header files. +# include +# ifdef QT_USE_XFT2_HEADER +# include +# else +# include +# endif // QT_USE_XFT2_HEADER +# if defined(XFT_VERSION) && XFT_VERSION >= 20000 +# define QT_XFT2 +# else +# include +// Xft1 doesn't have these functions, so we implement them in qtaddons_x11.cpp +extern "C" { + TQt::HANDLE XftDrawPicture( XftDraw * ); + void XftDrawSetClipRectangles(XftDraw *, int, int, XRectangle *, int); + void XftDrawSetSubwindowMode(XftDraw *, int); +} +# endif // XFT_VERSION +# endif // TQT_NO_XFTFREETYPE +#else +// make sure TQT_NO_XFTFREETYPE is defined if TQT_NO_XRENDER is defined +# ifndef TQT_NO_XFTFREETYPE +# define TQT_NO_XFTFREETYPE +# endif +#endif // TQT_NO_XRENDER + + +#ifndef TQT_NO_XSYNC +# include +#endif // TQT_NO_XSYNC + + +#ifndef TQT_NO_XKB +# include +#endif // TQT_NO_XKB + + +#if !defined(XlibSpecificationRelease) +# define X11R4 +typedef char *XPointer; +#else +# undef X11R4 +#endif + +// #define TQT_NO_XIM +#if defined(X11R4) +// X11R4 does not have XIM +#define TQT_NO_XIM +#elif defined(Q_OS_OSF) && (XlibSpecificationRelease < 6) +// broken in Xlib up to OSF/1 3.2 +#define TQT_NO_XIM +#elif defined(Q_OS_AIX) +// broken in Xlib up to what version of AIX? +#define TQT_NO_XIM +#elif defined(TQT_NO_DEBUG) && defined(Q_OS_IRIX) +// XmbLookupString broken on IRIX +// XCreateIC broken when compiling -64 on IRIX 6.5.2 +#define TQT_NO_XIM +#elif defined(Q_OS_HPUX) && defined(__LP64__) +// XCreateIC broken when compiling 64-bit ELF on HP-UX 11.0 +#define TQT_NO_XIM +#elif defined(Q_OS_SCO) +// ### suggested by user... +// ### #define TQT_NO_XIM +#endif // TQT_NO_XIM + + +/* + * Solaris patch 108652-47 and higher fixes crases in + * XRegisterIMInstantiateCallback, but the function doesn't seem to + * work. + * + * Instead, we disabled R6 input, and open the input method + * immediately at application start. + */ +#if !defined(TQT_NO_XIM) && (XlibSpecificationRelease >= 6) && \ + !defined(Q_OS_SOLARIS) +#define USE_X11R6_XIM + +//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback +//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2. +//######### Many old X11R6 header files lack XSetIMValues. +//######### Therefore, we have to declare these functions ourselves. + +extern "C" Bool XRegisterIMInstantiateCallback( + Display*, + struct _XrmHashBucketRec*, + char*, + char*, + XIMProc, //XFree86 has XIDProc, which has to be wrong + XPointer +); + +extern "C" Bool XUnregisterIMInstantiateCallback( + Display*, + struct _XrmHashBucketRec*, + char*, + char*, + XIMProc, //XFree86 has XIDProc, which has to be wrong + XPointer +); + +extern "C" char *XSetIMValues( XIM /* im */, ... ); + +#endif + +#ifndef TQT_NO_XIM +// some platforms (eg. Solaris 2.51) don't have these defines in Xlib.h +#ifndef XNResetState +#define XNResetState "resetState" +#endif +#ifndef XIMPreserveState +#define XIMPreserveState (1L<<1) +#endif +#endif + + +#ifndef X11R4 +# include +#endif // X11R4 + + +#ifdef QT_MITSHM +# include +#endif // QT_MITSHM + + +#endif // TQT_X11_H diff --git a/src/kernel/tqtextengine.cpp b/src/kernel/tqtextengine.cpp index 8280340c9..6c046a5b8 100644 --- a/src/kernel/tqtextengine.cpp +++ b/src/kernel/tqtextengine.cpp @@ -38,12 +38,12 @@ #include "tqtextengine_p.h" -#include "qscriptengine_p.h" +#include "tqscriptengine_p.h" #include #include "tqfontdata_p.h" #include "tqfontengine_p.h" #include -#include +#include #include // ----------------------------------------------------------------------------------------------------- diff --git a/src/kernel/tqucomextra.cpp b/src/kernel/tqucomextra.cpp new file mode 100644 index 000000000..f44355adc --- /dev/null +++ b/src/kernel/tqucomextra.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Implementation of extra TQUcom classes +** +** Created : 990101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqucomextra_p.h" +#include + + +#ifndef TQT_NO_VARIANT +// 6dc75d58-a1d9-4417-b591-d45c63a3a4ea +const TQUuid TID_QUType_TQVariant( 0x6dc75d58, 0xa1d9, 0x4417, 0xb5, 0x91, 0xd4, 0x5c, 0x63, 0xa3, 0xa4, 0xea ); +TQUType_TQVariant static_QUType_TQVariant; + +const TQUuid *TQUType_TQVariant::uuid() const { return &TID_QUType_TQVariant; } +const char *TQUType_TQVariant::desc() const { return "TQVariant"; } + +void TQUType_TQVariant::set( TQUObject *o, const TQVariant& v ) +{ + o->payload.ptr = new TQVariant( v ); + o->type = this; +} + +TQVariant &TQUType_TQVariant::get( TQUObject * o ) +{ + return *(TQVariant*)o->payload.ptr; +} + +bool TQUType_TQVariant::canConvertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( o->type, &static_QUType_TQString ) + || isEqual( o->type, &static_QUType_int ) + || isEqual( o->type, &static_QUType_bool ) + || isEqual( o->type, &static_QUType_double ) + || isEqual( o->type, &static_QUType_charstar ) ) + return TRUE; + return t->canConvertTo( o, this ); +} + +bool TQUType_TQVariant::canConvertTo( TQUObject * /*o*/, TQUType * /*t*/ ) +{ + return FALSE; +} + +bool TQUType_TQVariant::convertFrom( TQUObject *o, TQUType *t ) +{ + TQVariant *var = 0; + if ( isEqual( o->type, &static_QUType_TQString ) ) + var = new TQVariant( static_QUType_TQString.get( o ) ); + else if ( isEqual( o->type, &static_QUType_int ) ) + var = new TQVariant( static_QUType_int.get( o ) ); + else if ( isEqual( o->type, &static_QUType_bool ) ) + var = new TQVariant( static_QUType_bool.get( o ) ); + else if ( isEqual( o->type, &static_QUType_double ) ) + var = new TQVariant( static_QUType_double.get( o ) ); + else if ( isEqual( o->type, &static_QUType_charstar ) ) + var = new TQVariant( static_QUType_charstar.get( o ) ); + else + return t->convertTo( o, this ); + + o->type->clear( o ); + o->payload.ptr = var; + o->type = this; + return TRUE; +} + +bool TQUType_TQVariant::convertTo( TQUObject * /*o*/, TQUType * /*t*/ ) +{ + return FALSE; +} + +void TQUType_TQVariant::clear( TQUObject *o ) +{ + delete (TQVariant*)o->payload.ptr; + o->payload.ptr = 0; +} + +int TQUType_TQVariant::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_TQVariant::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + + +#endif + +const TQUuid TID_QUType_varptr( 0x8d48b3a8, 0xbd7f, 0x11d5, 0x8d, 0x74, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3 ); +TQUType_varptr static_QUType_varptr; +const TQUuid *TQUType_varptr::uuid() const { return &TID_QUType_varptr; } +const char *TQUType_varptr::desc() const { return "varptr"; } + +void TQUType_varptr::set( TQUObject *o, const void* v ) +{ + o->payload.ptr = (void*) v; + o->type = this; +} + +bool TQUType_varptr::canConvertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_ptr ) ) + return TRUE; + return t->canConvertTo( o, this ); +} + +bool TQUType_varptr::canConvertTo( TQUObject *, TQUType * t) +{ + return isEqual( t, &static_QUType_ptr ); +} + +bool TQUType_varptr::convertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_ptr ) ) + ; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool TQUType_varptr::convertTo( TQUObject *o, TQUType * t) +{ + if ( isEqual( t, &static_QUType_ptr ) ) { + o->type = &static_QUType_ptr; + return TRUE; + } + return FALSE; +} + +int TQUType_varptr::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_varptr::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} diff --git a/src/kernel/tqucomextra_p.h b/src/kernel/tqucomextra_p.h new file mode 100644 index 000000000..57f6b37a6 --- /dev/null +++ b/src/kernel/tqucomextra_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Definition of extra TQUcom classes +** +** Created : 990101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQUCOMEXTRA_P_H +#define TQUCOMEXTRA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include +#endif // QT_H + +#if __GNUC__ - 0 > 3 +#pragma GCC system_header +#endif + +class TQVariant; + +#ifndef TQT_NO_VARIANT +// 6dc75d58-a1d9-4417-b591-d45c63a3a4ea +extern const TQUuid TID_QUType_TQVariant; + +struct TQ_EXPORT TQUType_TQVariant : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, const TQVariant & ); + TQVariant &get( TQUObject * o ); + + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ); + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_TQVariant static_QUType_TQVariant; +#endif //TQT_NO_VARIANT + + +// {0x8d48b3a8, 0xbd7f, 0x11d5, 0x8d, 0x74, 0x00, 0xc0, 0xf0, 0x3b, 0xc0, 0xf3 } +extern TQ_EXPORT const TQUuid TID_QUType_varptr; +struct TQ_EXPORT TQUType_varptr : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, const void* ); + void* &get( TQUObject * o ) { return o->payload.ptr; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_varptr static_QUType_varptr; + + +#endif // TQUCOMEXTRA_P_H + diff --git a/src/kernel/tqwidget_x11.cpp b/src/kernel/tqwidget_x11.cpp index cc16871a7..2f90c4905 100644 --- a/src/kernel/tqwidget_x11.cpp +++ b/src/kernel/tqwidget_x11.cpp @@ -50,7 +50,7 @@ #include "tqtextcodec.h" #include "tqdatetime.h" #include "tqcursor.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" #include // NOT REVISED diff --git a/src/kernel/tqwidgetcreate_x11.cpp b/src/kernel/tqwidgetcreate_x11.cpp index b34fe9613..33ec8c20f 100644 --- a/src/kernel/tqwidgetcreate_x11.cpp +++ b/src/kernel/tqwidgetcreate_x11.cpp @@ -39,7 +39,7 @@ **********************************************************************/ #include "tqwidget.h" -#include "qt_x11_p.h" +#include "tqt_x11_p.h" /* diff --git a/src/libqt.map b/src/libqt.map index 9134b5638..fe7884041 100644 --- a/src/libqt.map +++ b/src/libqt.map @@ -20,10 +20,10 @@ TQHttpResponseHeader::*; TQMainWindowLayout::*; Q*Private::*; # collides with TQGuardedPtrPrivate - QPSPrinter*; + TQPSPrinter*; Q*RegExpEngine::*; Q*SvgDevice::*; - *QSvgDeviceState*; + *TQSvgDeviceState*; ImgElement::*; PixElement::*; QRenameEdit::*; @@ -36,7 +36,7 @@ QSVChildRec::*; qt_xdnd_*; QTipLabel::*; - QUnicodeTables::*; + TQUnicodeTables::*; QViewportWidget::*; QWFlagWidget::*; TQWorkspaceChild::*; diff --git a/src/moc/moc.pro b/src/moc/moc.pro index e26c4893f..b8ff335d7 100644 --- a/src/moc/moc.pro +++ b/src/moc/moc.pro @@ -29,7 +29,7 @@ SOURCES = ../tools/tqbuffer.cpp \ ../tools/tqregexp.cpp \ ../tools/tqstring.cpp \ ../tools/tqlocale.cpp \ - ../tools/qunicodetables.cpp \ + ../tools/tqunicodetables.cpp \ ../tools/tqstringlist.cpp \ ../tools/tqtextstream.cpp \ ../tools/tqbitarray.cpp \ diff --git a/src/moc/moc.y b/src/moc/moc.y index 5f9ffa10a..7eb667842 100644 --- a/src/moc/moc.y +++ b/src/moc/moc.y @@ -2906,7 +2906,7 @@ void generateClass() // generate C++ source code for a class } fprintf( out, "#include <%stqmetaobject.h>\n", (const char*)g->qtPath ); fprintf( out, "#include <%sntqapplication.h>\n\n", (const char*)g->qtPath ); - fprintf( out, "#include <%sprivate/qucomextra_p.h>\n", (const char*)g->qtPath ); + fprintf( out, "#include <%sprivate/tqucomextra_p.h>\n", (const char*)g->qtPath ); fprintf( out, "#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != %d)\n", formatRevision ); fprintf( out, "#error \"This file was generated using the moc from %s." " It\"\n#error \"cannot be used with the include files from" diff --git a/src/moc/moc_yacc.cpp b/src/moc/moc_yacc.cpp index d038c0b7e..83994e260 100644 --- a/src/moc/moc_yacc.cpp +++ b/src/moc/moc_yacc.cpp @@ -5781,7 +5781,7 @@ void generateClass() // generate C++ source code for a class } fprintf( out, "#include <%stqmetaobject.h>\n", (const char*)g->qtPath ); fprintf( out, "#include <%sntqapplication.h>\n\n", (const char*)g->qtPath ); - fprintf( out, "#include <%sprivate/qucomextra_p.h>\n", (const char*)g->qtPath ); + fprintf( out, "#include <%sprivate/tqucomextra_p.h>\n", (const char*)g->qtPath ); fprintf( out, "#if !defined(Q_MOC_OUTPUT_REVISION) || (Q_MOC_OUTPUT_REVISION != %d)\n", formatRevision ); fprintf( out, "#error \"This file was generated using the moc from %s." " It\"\n#error \"cannot be used with the include files from" diff --git a/src/network/tqhttp.cpp b/src/network/tqhttp.cpp index 6bf6f1740..389a731c7 100644 --- a/src/network/tqhttp.cpp +++ b/src/network/tqhttp.cpp @@ -51,7 +51,7 @@ #include "tqbuffer.h" #include "tqurloperator.h" #include "tqtimer.h" -#include "private/qinternal_p.h" +#include "private/tqinternal_p.h" //#define TQHTTP_DEBUG diff --git a/src/network/tqsocket.cpp b/src/network/tqsocket.cpp index 3a088c514..9314318d1 100644 --- a/src/network/tqsocket.cpp +++ b/src/network/tqsocket.cpp @@ -44,7 +44,7 @@ #include "tqtimer.h" #include "tqsocketdevice.h" #include "tqdns.h" -#include "private/qinternal_p.h" +#include "private/tqinternal_p.h" #include #ifndef NO_ERRNO_H diff --git a/src/opengl/tqgl.cpp b/src/opengl/tqgl.cpp index 991d697af..4ec6dec30 100644 --- a/src/opengl/tqgl.cpp +++ b/src/opengl/tqgl.cpp @@ -49,7 +49,7 @@ static TQGLFormat* qgl_default_format = 0; static TQGLFormat* qgl_default_overlay_format = 0; #if defined(TQ_WS_X11) -#include "private/qt_x11_p.h" +#include "private/tqt_x11_p.h" #define INT32 dummy_INT32 #define INT8 dummy_INT8 #include diff --git a/src/qt.pro b/src/qt.pro index 903d9b396..17de6ea1b 100644 --- a/src/qt.pro +++ b/src/qt.pro @@ -128,7 +128,7 @@ largefile { include($$KERNEL_CPP/qt_compat.pri) #platforms -x11:include($$KERNEL_CPP/qt_x11.pri) +x11:include($$KERNEL_CPP/tqt_x11.pri) mac:include($$KERNEL_CPP/qt_mac.pri) win32:include($$KERNEL_CPP/qt_win.pri) @@ -168,14 +168,14 @@ unix { wince-* { CONFIG -= incremental message( ...removing plugin stuff... (not permanent) ) - HEADERS -= $$TOOLS_CPP/qcomlibrary.h \ + HEADERS -= $$TOOLS_CPP/tqcomlibrary.h \ $$KERNEL_CPP/tqgplugin.h \ $$KERNEL_CPP/tqimageformatplugin.h \ $$STYLES_CPP/tqstyleplugin.h \ $$CODECS_CPP/tqtextcodecplugin.h \ $$WIDGETS_CPP/tqwidgetplugin.h - SOURCES -= $$TOOLS_CPP/qcomlibrary.cpp \ + SOURCES -= $$TOOLS_CPP/tqcomlibrary.cpp \ $$KERNEL_CPP/tqgplugin.cpp \ $$KERNEL_CPP/tqimageformatplugin.cpp \ $$STYLES_CPP/tqstyleplugin.cpp \ diff --git a/src/sql/drivers/odbc/tqsql_odbc.cpp b/src/sql/drivers/odbc/tqsql_odbc.cpp index a9a3aa468..82dd6247d 100644 --- a/src/sql/drivers/odbc/tqsql_odbc.cpp +++ b/src/sql/drivers/odbc/tqsql_odbc.cpp @@ -47,7 +47,7 @@ #endif #include #include -#include +#include #include // undefine this to prevent initial check of the ODBC driver diff --git a/src/sql/tqsqldatabase.cpp b/src/sql/tqsqldatabase.cpp index 1f8cfe6c2..ccdaea94d 100644 --- a/src/sql/tqsqldatabase.cpp +++ b/src/sql/tqsqldatabase.cpp @@ -79,7 +79,7 @@ #include "tqsqlresult.h" #include "tqsqldriver.h" #include "tqsqldriverinterface_p.h" -#include +#include #include #include "tqobject.h" #include "tqguardedptr.h" diff --git a/src/sql/tqsqldriverinterface_p.h b/src/sql/tqsqldriverinterface_p.h index 851770366..c15efac58 100644 --- a/src/sql/tqsqldriverinterface_p.h +++ b/src/sql/tqsqldriverinterface_p.h @@ -54,7 +54,7 @@ // #ifndef QT_H -#include +#include #endif // QT_H #if !defined( TQT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL ) diff --git a/src/styles/tqcommonstyle.cpp b/src/styles/tqcommonstyle.cpp index 287bc5e8b..02b878c38 100644 --- a/src/styles/tqcommonstyle.cpp +++ b/src/styles/tqcommonstyle.cpp @@ -71,7 +71,7 @@ #include "private/tqdialogbuttons_p.h" #include #include -#include "../widgets/qtitlebar_p.h" +#include "../widgets/tqtitlebar_p.h" #include /*! diff --git a/src/styles/tqstylefactory.cpp b/src/styles/tqstylefactory.cpp index 29a3ad5ec..d66fbe72d 100644 --- a/src/styles/tqstylefactory.cpp +++ b/src/styles/tqstylefactory.cpp @@ -68,7 +68,7 @@ TQString p2qstring(const unsigned char *c); //tqglobal.cpp #endif #include -#include +#include #ifndef TQT_NO_COMPONENT class TQStyleFactoryPrivate : public TQObject { diff --git a/src/styles/tqstyleinterface_p.h b/src/styles/tqstyleinterface_p.h index 500dcfef3..5c8bd42db 100644 --- a/src/styles/tqstyleinterface_p.h +++ b/src/styles/tqstyleinterface_p.h @@ -52,7 +52,7 @@ // #ifndef QT_H -#include +#include #endif // QT_H #ifndef TQT_NO_STYLE diff --git a/src/tools/qcom_p.h b/src/tools/qcom_p.h deleted file mode 100644 index 0c9d60d01..000000000 --- a/src/tools/qcom_p.h +++ /dev/null @@ -1,344 +0,0 @@ -/**************************************************************************** -** -** ... -** -** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQCOM_P_H -#define TQCOM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of a number of TQt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqstringlist.h" -#include "tquuid.h" -#endif // QT_H - -#if __GNUC__ - 0 > 3 -#pragma GCC system_header -#endif - -#ifndef TQT_NO_COMPONENT - -class TQObject; -struct TQUInterfaceDescription; -struct TQUObject; - -#define TQRESULT unsigned long -#define TQS_OK (TQRESULT)0x00000000 -#define TQS_FALSE (TQRESULT)0x00000001 - -#define TQE_NOTIMPL (TQRESULT)0x80000001 -#define TQE_OUTOFMEMORY (TQRESULT)0x80000002 -#define TQE_INVALIDARG (TQRESULT)0x80000003 -#define TQE_NOINTERFACE (TQRESULT)0x80000004 -#define TQE_NOCOMPONENT (TQRESULT)0x80000005 - - -// {1D8518CD-E8F5-4366-99E8-879FD7E482DE} -#ifndef IID_QUnknown -#define IID_QUnknown TQUuid(0x1d8518cd, 0xe8f5, 0x4366, 0x99, 0xe8, 0x87, 0x9f, 0xd7, 0xe4, 0x82, 0xde) -#endif - -struct TQ_EXPORT TQUnknownInterface -{ - virtual TQRESULT queryInterface( const TQUuid&, TQUnknownInterface** ) = 0; - virtual ulong addRef() = 0; - virtual ulong release() = 0; -}; - -// {FBAC965E-A441-413F-935E-CDF582573FAB} -#ifndef IID_QDispatch -#define IID_QDispatch TQUuid( 0xfbac965e, 0xa441, 0x413f, 0x93, 0x5e, 0xcd, 0xf5, 0x82, 0x57, 0x3f, 0xab) -#endif - -// the dispatch interface that inherits the unknown interface.. It is -// used to explore interfaces during runtime and to do dynamic calls. -struct TQ_EXPORT TQDispatchInterface : public TQUnknownInterface -{ - // returns the interface description of this dispatch interface. - virtual const TQUInterfaceDescription* interfaceDescription() const = 0; - - // returns the event description of this dispatch interface. - virtual const TQUInterfaceDescription* eventsDescription() const = 0; - - // invokes method id with parameters V*. Returns some sort of - // exception code. - virtual TQRESULT invoke( int id, TQUObject* o ) = 0; - - // installs listener as event listener - virtual void installListener( TQDispatchInterface* listener ) = 0; - - // remove listener as event listener - virtual void removeListener( TQDispatchInterface* listener ) = 0; -}; - -template -class TQInterfacePtr -{ -public: - TQInterfacePtr():iface(0){} - - TQInterfacePtr( T* i) { - if ( (iface = i) ) - iface->addRef(); - } - - TQInterfacePtr(const TQInterfacePtr &p) { - if ( (iface = p.iface) ) - iface->addRef(); - } - - ~TQInterfacePtr() { - if ( iface ) - iface->release(); - } - - TQInterfacePtr &operator=(const TQInterfacePtr &p) { - if ( iface != p.iface ) { - if ( iface ) - iface->release(); - if ( (iface = p.iface) ) - iface->addRef(); - } - return *this; - } - - TQInterfacePtr &operator=(T* i) { - if (iface != i ) { - if ( iface ) - iface->release(); - if ( (iface = i) ) - iface->addRef(); - } - return *this; - } - - bool operator==( const TQInterfacePtr &p ) const { return iface == p.iface; } - - bool operator!= ( const TQInterfacePtr& p ) const { return !( *this == p ); } - - bool isNull() const { return !iface; } - - T* operator->() const { return iface; } - - T& operator*() const { return *iface; } - - operator T*() const { return iface; } - - TQUnknownInterface** operator &() const { - if( iface ) - iface->release(); - return (TQUnknownInterface**)&iface; - } - - T** operator &() { - if ( iface ) - iface->release(); - return &iface; - } - -private: - T* iface; -}; - -// {10A1501B-4C5F-4914-95DD-C400486CF900} -#ifndef IID_QObject -#define IID_QObject TQUuid( 0x10a1501b, 0x4c5f, 0x4914, 0x95, 0xdd, 0xc4, 0x00, 0x48, 0x6c, 0xf9, 0x00) -#endif - -struct TQ_EXPORT TQObjectInterface -{ - virtual TQObject* qObject() = 0; -}; - -// {5F3968A5-F451-45b1-96FB-061AD98F926E} -#ifndef IID_QComponentInformation -#define IID_QComponentInformation TQUuid(0x5f3968a5, 0xf451, 0x45b1, 0x96, 0xfb, 0x6, 0x1a, 0xd9, 0x8f, 0x92, 0x6e) -#endif - -struct TQ_EXPORT TQComponentInformationInterface : public TQUnknownInterface -{ - virtual TQString name() const = 0; - virtual TQString description() const = 0; - virtual TQString author() const = 0; - virtual TQString version() const = 0; -}; - -// {6CAA771B-17BB-4988-9E78-BA5CDDAAC31E} -#ifndef IID_QComponentFactory -#define IID_QComponentFactory TQUuid( 0x6caa771b, 0x17bb, 0x4988, 0x9e, 0x78, 0xba, 0x5c, 0xdd, 0xaa, 0xc3, 0x1e) -#endif - -struct TQ_EXPORT TQComponentFactoryInterface : public TQUnknownInterface -{ - virtual TQRESULT createInstance( const TQUuid &cid, const TQUuid &iid, TQUnknownInterface** instance, TQUnknownInterface *outer ) = 0; -}; - -// {D16111D4-E1E7-4C47-8599-24483DAE2E07} -#ifndef IID_QLibrary -#define IID_QLibrary TQUuid( 0xd16111d4, 0xe1e7, 0x4c47, 0x85, 0x99, 0x24, 0x48, 0x3d, 0xae, 0x2e, 0x07) -#endif - -struct TQ_EXPORT TQLibraryInterface : public TQUnknownInterface -{ - virtual bool init() = 0; - virtual void cleanup() = 0; - virtual bool canUnload() const = 0; -}; - -// {3F8FDC44-3015-4f3e-B6D6-E4AAAABDEAAD} -#ifndef IID_QFeatureList -#define IID_QFeatureList TQUuid(0x3f8fdc44, 0x3015, 0x4f3e, 0xb6, 0xd6, 0xe4, 0xaa, 0xaa, 0xbd, 0xea, 0xad) -#endif - -struct TQ_EXPORT TQFeatureListInterface : public TQUnknownInterface -{ - virtual TQStringList featureList() const = 0; -}; - -// {B5FEB5DE-E0CD-4E37-B0EB-8A812499A0C1} -#ifndef IID_QComponentRegistration -#define IID_QComponentRegistration TQUuid( 0xb5feb5de, 0xe0cd, 0x4e37, 0xb0, 0xeb, 0x8a, 0x81, 0x24, 0x99, 0xa0, 0xc1) -#endif - -struct TQ_EXPORT TQComponentRegistrationInterface : public TQUnknownInterface -{ - virtual bool registerComponents( const TQString &filepath ) const = 0; - virtual bool unregisterComponents() const = 0; -}; - -// internal class that wraps an initialized ulong -struct TQ_EXPORT TQtULong -{ - TQtULong() : ref( 0 ) { } - operator unsigned long () const { return ref; } - unsigned long& operator++() { return ++ref; } - unsigned long operator++( int ) { return ref++; } - unsigned long& operator--() { return --ref; } - unsigned long operator--( int ) { return ref--; } - - unsigned long ref; -}; -// default implementation of ref counting. A variable "ulong ref" has to be a member - - -#define TQ_REFCOUNT \ -private: \ - TQtULong qtrefcount; \ -public: \ - ulong addRef() {return qtrefcount++;} \ - ulong release() {if(!--qtrefcount){delete this;return 0;}return qtrefcount;} - -#ifndef Q_EXPORT_COMPONENT -#if defined(TQT_THREAD_SUPPORT) -#define QT_THREADED_BUILD 1 -#define Q_UCM_FLAGS_STRING "11" -#else -#define QT_THREADED_BUILD 0 -#define Q_UCM_FLAGS_STRING "01" -#endif - -#ifndef TQ_EXTERN_C -#ifdef __cplusplus -#define TQ_EXTERN_C extern "C" -#else -#define TQ_EXTERN_C extern -#endif -#endif - -// this is duplicated at Q_PLUGIN_VERIFICATION_DATA in tqgplugin.h -// NOTE: if you change pattern, you MUST change the pattern in -// qcomlibrary.cpp as well. changing the pattern will break all -// backwards compatibility as well (no old plugins will be loaded). -#ifndef Q_UCM_VERIFICATION_DATA -# define Q_UCM_VERIFICATION_DATA \ - static const char *qt_ucm_verification_data = \ - "pattern=" "QT_UCM_VERIFICATION_DATA" "\n" \ - "version=" TQT_VERSION_STR "\n" \ - "flags=" Q_UCM_FLAGS_STRING "\n" \ - "buildkey=" TQT_BUILD_KEY "\0"; -#endif // Q_UCM_VERIFICATION_DATA - -// This macro expands to the default implementation of ucm_instantiate. -#ifndef Q_CREATE_INSTANCE -# define Q_CREATE_INSTANCE( IMPLEMENTATION ) \ - IMPLEMENTATION *i = new IMPLEMENTATION; \ - TQUnknownInterface* iface = 0; \ - i->queryInterface( IID_QUnknown, &iface ); \ - return iface; -#endif // Q_CREATE_INSTANCE - -# ifdef TQ_WS_WIN -# ifdef Q_CC_BOR -# define Q_EXPORT_COMPONENT() \ - Q_UCM_VERIFICATION_DATA \ - TQ_EXTERN_C __declspec(dllexport) \ - const char * __stdcall qt_ucm_query_verification_data() \ - { return qt_ucm_verification_data; } \ - TQ_EXTERN_C TQ_EXPORT __declspec(dllexport) TQUnknownInterface* \ - __stdcall ucm_instantiate() -# else -# define Q_EXPORT_COMPONENT() \ - Q_UCM_VERIFICATION_DATA \ - TQ_EXTERN_C __declspec(dllexport) \ - const char *qt_ucm_query_verification_data() \ - { return qt_ucm_verification_data; } \ - TQ_EXTERN_C TQ_EXPORT __declspec(dllexport) TQUnknownInterface* ucm_instantiate() -# endif -# else -# define Q_EXPORT_COMPONENT() \ - Q_UCM_VERIFICATION_DATA \ - TQ_EXTERN_C \ - const char *qt_ucm_query_verification_data() \ - { return qt_ucm_verification_data; } \ - TQ_EXTERN_C TQ_EXPORT TQUnknownInterface* ucm_instantiate() -# endif -# define Q_EXPORT_INTERFACE() Q_EXPORT_COMPONENT() -#endif - -#endif //TQT_NO_COMPONENT - -#endif //TQCOM_P_H diff --git a/src/tools/qcomlibrary.cpp b/src/tools/qcomlibrary.cpp deleted file mode 100644 index 5f40bdc9f..000000000 --- a/src/tools/qcomlibrary.cpp +++ /dev/null @@ -1,538 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQComLibrary class -** -** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qcomlibrary_p.h" - -#ifndef TQT_NO_COMPONENT -#include -#include -#include -#include -#include -#ifndef NO_ERRNO_H -#include -#endif // NO_ERROR_H - -#ifdef TQT_THREAD_SUPPORT -# include "tqmutexpool_p.h" -#endif // TQT_THREAD_SUPPORT - -#ifndef QT_DEBUG_COMPONENT -# if defined(QT_DEBUG) -# define QT_DEBUG_COMPONENT 1 -# endif -#endif - - -TQComLibrary::TQComLibrary( const TQString &filename ) - : TQLibrary( filename ), entry( 0 ), libiface( 0 ), qt_version( 0 ) -{ -} - -TQComLibrary::~TQComLibrary() -{ - if ( autoUnload() ) - unload(); - if ( libiface ) - libiface->release(); - if ( entry ) - entry->release(); -} - -bool TQComLibrary::unload() -{ - int refs = entry ? entry->release() : 0; - entry = 0; - if (refs || !libiface) - return FALSE; - - libiface->cleanup(); - if ( !libiface->canUnload() ) - return FALSE; - libiface->release(); - libiface = 0; - - return TQLibrary::unload(); -} - -static bool qt_verify( const TQString& library, uint version, uint flags, - const TQCString &key, bool warn ) -{ - uint our_flags = 1; -#if defined(TQT_THREAD_SUPPORT) - our_flags |= 2; -#endif - - if ( (flags & 1) == 0 ) { - if ( warn ) - tqWarning( "Conflict in %s:\n" - " Plugin cannot be queried successfully!", - (const char*) TQFile::encodeName(library) ); - } else if ( ( version > TQT_VERSION ) || - ( ( TQT_VERSION & 0xff0000 ) > ( version & 0xff0000 ) ) ) { - if ( warn ) - tqWarning( "Conflict in %s:\n" - " Plugin uses incompatible TQt library (%d.%d.%d)!", - (const char*) TQFile::encodeName(library), - (version&0xff0000) >> 16, (version&0xff00) >> 8, version&0xff ); - } else if ( (flags & 2) != (our_flags & 2) ) { - if ( warn ) - tqWarning( "Conflict in %s:\n" - " Plugin uses %s TQt library!", - (const char*) TQFile::encodeName(library), - (flags & 2) ? "multi threaded" : "single threaded" ); - } else if ( key != TQT_BUILD_KEY ) { - if ( warn ) - tqWarning( "Conflict in %s:\n" - " Plugin uses incompatible TQt library!\n" - " expected build key \"%s\", got \"%s\".", - (const char*) TQFile::encodeName(library), - TQT_BUILD_KEY, - key.isEmpty() ? "" : (const char *) key ); - } else { - return TRUE; - } - return FALSE; -} - -struct qt_token_info -{ - qt_token_info( const char *f, const ulong fc ) - : fields( f ), field_count( fc ), results( fc ), lengths( fc ) - { - results.fill( 0 ); - lengths.fill( 0 ); - } - - const char *fields; - const ulong field_count; - - TQMemArray results; - TQMemArray lengths; -}; - -/* - return values: - 1 parse ok - 0 eos - -1 parse error -*/ -static int qt_tokenize( const char *s, ulong s_len, ulong *advance, - const qt_token_info &token_info ) -{ - ulong pos = 0, field = 0, fieldlen = 0; - char current; - int ret = -1; - *advance = 0; - for (;;) { - current = s[ pos ]; - - // next char - ++pos; - ++fieldlen; - ++*advance; - - if ( ! current || pos == s_len + 1 ) { - // save result - token_info.results[ (int)field ] = s; - token_info.lengths[ (int)field ] = fieldlen - 1; - - // end of string - ret = 0; - break; - } - - if ( current == token_info.fields[ field ] ) { - // save result - token_info.results[ (int)field ] = s; - token_info.lengths[ (int)field ] = fieldlen - 1; - - // end of field - fieldlen = 0; - ++field; - if ( field == token_info.field_count - 1 ) { - // parse ok - ret = 1; - } - if ( field == token_info.field_count ) { - // done parsing - break; - } - - // reset string and its length - s = s + pos; - s_len -= pos; - pos = 0; - } - } - - return ret; -} - -/* - returns TRUE if the string s was correctly parsed, FALSE otherwise. -*/ -static bool qt_parse_pattern( const char *s, uint *version, uint *flags, - TQCString *key ) -{ - bool ret = TRUE; - - qt_token_info pinfo("=\n", 2); - int parse; - ulong at = 0, advance, parselen = tqstrlen( s ); - do { - parse = qt_tokenize( s + at, parselen, &advance, pinfo ); - if ( parse == -1 ) { - ret = FALSE; - break; - } - - at += advance; - parselen -= advance; - - if ( tqstrncmp( "version", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { - // parse version string - qt_token_info pinfo2("..-", 3); - if ( qt_tokenize( pinfo.results[ 1 ], pinfo.lengths[ 1 ], - &advance, pinfo2 ) != -1 ) { - TQCString m( pinfo2.results[ 0 ], pinfo2.lengths[ 0 ] + 1 ); - TQCString n( pinfo2.results[ 1 ], pinfo2.lengths[ 1 ] + 1 ); - TQCString p( pinfo2.results[ 2 ], pinfo2.lengths[ 2 ] + 1 ); - *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt(); - } else { - ret = FALSE; - break; - } - } else if ( tqstrncmp( "flags", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { - // parse flags string - char ch; - *flags = 0; - ulong p = 0, c = 0, bit = 0; - while ( p < pinfo.lengths[ 1 ] ) { - ch = pinfo.results[ 1 ][ p ]; - bit = pinfo.lengths[ 1 ] - p - 1; - c = 1 << bit; - if ( ch == '1' ) { - *flags |= c; - } else if ( ch != '0' ) { - ret = FALSE; - break; - } - ++p; - } - } else if ( tqstrncmp( "buildkey", pinfo.results[ 0 ], - pinfo.lengths[ 0 ] ) == 0 ){ - // save buildkey - *key = TQCString( pinfo.results[ 1 ], pinfo.lengths[ 1 ] + 1 ); - } - } while ( parse == 1 && parselen > 0 ); - - return ret; -} - -#if defined(Q_OS_UNIX) - -#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) -# define USE_MMAP -# include -# include -#endif // Q_OS_FREEBSD || Q_OS_LINUX - -static long qt_find_pattern( const char *s, ulong s_len, - const char *pattern, ulong p_len ) -{ - /* - this uses the same algorithm as TQString::findRev... - - we search from the end of the file because on the supported - systems, the read-only data/text segments are placed at the end - of the file. HOWEVER, when building with debugging enabled, all - the debug symbols are placed AFTER the data/text segments. - - what does this mean? when building in release mode, the search - is fast because the data we are looking for is at the end of the - file... when building in debug mode, the search is slower - because we have to skip over all the debugging symbols first - */ - - if ( ! s || ! pattern || p_len > s_len ) return -1; - ulong i, hs = 0, hp = 0, delta = s_len - p_len; - - for (i = 0; i < p_len; ++i ) { - hs += s[delta + i]; - hp += pattern[i]; - } - i = delta; - for (;;) { - if ( hs == hp && tqstrncmp( s + i, pattern, p_len ) == 0 ) - return i; - if ( i == 0 ) - break; - --i; - hs -= s[i + p_len]; - hs += s[i]; - } - - return -1; -} - -/* - This opens the specified library, mmaps it into memory, and searches - for the QT_UCM_VERIFICATION_DATA. The advantage of this approach is that - we can get the verification data without have to actually load the library. - This lets us detect mismatches more safely. - - Returns FALSE if version/flags/key information is not present, or if the - information could not be read. - Returns TRUE if version/flags/key information is present and succesfully read. -*/ -static bool qt_unix_query( const TQString &library, uint *version, uint *flags, - TQCString *key ) -{ - TQFile file( library ); - if (! file.open( IO_ReadOnly ) ) { - tqWarning( "%s: %s", (const char*) TQFile::encodeName(library), - strerror( errno ) ); - return FALSE; - } - - TQByteArray data; - char *filedata = 0; - ulong fdlen = 0; - -#ifdef USE_MMAP - char *mapaddr = 0; - size_t maplen = file.size(); - mapaddr = (char *) mmap( mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0 ); - if ( mapaddr != MAP_FAILED ) { - // mmap succeeded - filedata = mapaddr; - fdlen = maplen; - } else { - // mmap failed - tqWarning( "mmap: %s", strerror( errno ) ); -#endif // USE_MMAP - // try reading the data into memory instead - data = file.readAll(); - filedata = data.data(); - fdlen = data.size(); -#ifdef USE_MMAP - } -#endif // USE_MMAP - - // verify that the pattern is present in the plugin - const char *pattern = "pattern=QT_UCM_VERIFICATION_DATA"; - const ulong plen = tqstrlen( pattern ); - long pos = qt_find_pattern( filedata, fdlen, pattern, plen ); - - bool ret = FALSE; - if ( pos >= 0 ) { - ret = qt_parse_pattern( filedata + pos, version, flags, key ); - } - -#ifdef USE_MMAP - if ( mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0 ) { - tqWarning( "munmap: %s", strerror( errno ) ); - } -#endif // USE_MMAP - - file.close(); - return ret; -} - -#endif // Q_OS_UNIX - - -static TQSettings *cache = 0; -static TQSingleCleanupHandler cleanup_cache; - -void TQComLibrary::createInstanceInternal() -{ - if ( library().isEmpty() ) - return; - - TQFileInfo fileinfo( library() ); - TQString lastModified = fileinfo.lastModified().toString(TQt::ISODate); - TQString regkey = TQString("/TQt Plugins %1.%2/%3") - .arg( ( TQT_VERSION & 0xff0000 ) >> 16 ) - .arg( ( TQT_VERSION & 0xff00 ) >> 8 ) - .arg( library() ); - TQStringList reg; - uint flags = 0; - TQCString key; - bool query_done = FALSE; - bool warn_mismatch = TRUE; - -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &cache ) : 0 ); -#endif // TQT_THREAD_SUPPORT - - if ( ! cache ) { - cache = new TQSettings; - cache->insertSearchPath( TQSettings::Windows, "/Trolltech" ); - cleanup_cache.set( &cache ); - } - - reg = cache->readListEntry( regkey ); - if ( reg.count() == 4 ) { - // check timestamp - if ( lastModified == reg[3] ) { - qt_version = reg[0].toUInt(0, 16); - flags = reg[1].toUInt(0, 16); - key = reg[2].latin1(); - - query_done = TRUE; - warn_mismatch = FALSE; - } - } - -#if defined(Q_OS_UNIX) - if ( ! query_done ) { - // get the query information directly from the plugin without loading - if ( qt_unix_query( library(), &qt_version, &flags, &key ) ) { - // info read succesfully from library - query_done = TRUE; - } - } -#else // !Q_OS_UNIX - if ( ! query_done ) { - // get the query information by loading the plugin - if ( !isLoaded() ) { - Q_ASSERT( entry == 0 ); - if ( !load() ) - return; - } - -# ifdef Q_CC_BOR - typedef const char * __stdcall (*UCMQueryVerificationDataProc)(); -# else - typedef const char * (*UCMQueryVerificationDataProc)(); -# endif - UCMQueryVerificationDataProc ucmQueryVerificationdataProc; - ucmQueryVerificationdataProc = - (UCMQueryVerificationDataProc) resolve( "qt_ucm_query_verification_data" ); - - if ( !ucmQueryVerificationdataProc || - !qt_parse_pattern( ucmQueryVerificationdataProc(), - &qt_version, &flags, &key ) ) { - qt_version = flags = 0; - key = "unknown"; - } else { - query_done = TRUE; - } - } -#endif // Q_OS_UNIX - - TQStringList queried; - queried << TQString::number( qt_version,16 ) - << TQString::number( flags, 16 ) - << key - << lastModified; - - if ( queried != reg ) { - cache->writeEntry( regkey, queried ); - // delete the cache, which forces the settings to be written - delete cache; - cache = 0; - } - - if ( ! query_done ) { - if ( warn_mismatch ) { - tqWarning( "Conflict in %s:\n Plugin cannot be queried successfully!", - (const char*) TQFile::encodeName( library() ) ); - } - unload(); - return; - } - - if ( ! qt_verify( library(), qt_version, flags, key, warn_mismatch ) ) { - unload(); - return; - } else if ( !isLoaded() ) { - Q_ASSERT( entry == 0 ); - if ( !load() ) - return; - } - -#ifdef Q_CC_BOR - typedef TQUnknownInterface* __stdcall (*UCMInstanceProc)(); -#else - typedef TQUnknownInterface* (*UCMInstanceProc)(); -#endif - UCMInstanceProc ucmInstanceProc; - ucmInstanceProc = (UCMInstanceProc) resolve( "ucm_instantiate" ); -#if defined(QT_DEBUG_COMPONENT) - if ( !ucmInstanceProc ) - tqWarning( "%s: Not a UCOM library.", (const char*) TQFile::encodeName(library()) ); -#endif - entry = ucmInstanceProc ? ucmInstanceProc() : 0; - - if ( entry ) { - if ( entry->queryInterface( IID_QLibrary, (TQUnknownInterface**)&libiface ) == TQS_OK ) { - if ( libiface && !libiface->init() ) { - libiface->release(); - libiface = 0; - unload(); - return; - } - } - } else { -#if defined(QT_DEBUG_COMPONENT) - tqWarning( "%s: No exported component provided.", (const char*) TQFile::encodeName(library()) ); -#endif - unload(); - } -} - -TQRESULT TQComLibrary::queryInterface( const TQUuid& request, TQUnknownInterface** iface ) -{ - if ( !entry ) - createInstanceInternal(); - return entry ? entry->queryInterface( request, iface ) : TQE_NOCOMPONENT; -} - -uint TQComLibrary::qtVersion() -{ - if ( !entry ) - createInstanceInternal(); - return entry ? qt_version : 0; -} - - -#endif // TQT_NO_COMPONENT diff --git a/src/tools/qcomlibrary_p.h b/src/tools/qcomlibrary_p.h deleted file mode 100644 index ede724194..000000000 --- a/src/tools/qcomlibrary_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Definition of TQComLibrary class -** -** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQCOMLIBRARY_P_H -#define TQCOMLIBRARY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of a number of TQt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "qcom_p.h" -#include "tqlibrary.h" -#endif // QT_H - -#ifndef TQT_NO_COMPONENT - -class TQ_EXPORT TQComLibrary : public TQLibrary -{ -public: - TQComLibrary( const TQString &filename ); - ~TQComLibrary(); - - bool unload(); - TQRESULT queryInterface( const TQUuid &iid, TQUnknownInterface **iface ); - uint qtVersion(); - -private: - void createInstanceInternal(); - - TQUnknownInterface *entry; - TQLibraryInterface *libiface; - uint qt_version; - -}; - -#endif //TQT_NO_COMPONENT - -#endif diff --git a/src/tools/qcriticalsection_p.cpp b/src/tools/qcriticalsection_p.cpp deleted file mode 100644 index 20c2127b0..000000000 --- a/src/tools/qcriticalsection_p.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQCriticalSection class -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#if defined(TQT_THREAD_SUPPORT) - -#include "qt_windows.h" - -#include - -class TQCriticalSectionPrivate -{ -public: - TQCriticalSectionPrivate() {} - - CRITICAL_SECTION section; -}; - - -TQCriticalSection::TQCriticalSection() -{ - d = new TQCriticalSectionPrivate; - InitializeCriticalSection( &d->section ); -} - -TQCriticalSection::~TQCriticalSection() -{ - DeleteCriticalSection( &d->section ); - delete d; -} - -void TQCriticalSection::enter() -{ - EnterCriticalSection( &d->section ); -} - -void TQCriticalSection::leave() -{ - LeaveCriticalSection( &d->section ); -} - -#endif diff --git a/src/tools/qcriticalsection_p.h b/src/tools/qcriticalsection_p.h deleted file mode 100644 index 330e141e1..000000000 --- a/src/tools/qcriticalsection_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Definition of TQCriticalSection class -** -** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQCRITICALSECTION_P_H -#define TQCRITICALSECTION_P_H - -#ifndef QT_H -#endif // QT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of TQt Remote Control. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// -// - -#if defined(TQT_THREAD_SUPPORT) - -#if defined(TQ_WS_WIN) - -/* - TQCriticalSection -*/ - -class TQCriticalSectionPrivate; - -class TQCriticalSection -{ -public: - TQCriticalSection(); - ~TQCriticalSection(); - void enter(); - void leave(); - -private: - TQCriticalSectionPrivate *d; -}; - -#endif - -#endif - -#endif diff --git a/src/tools/qpluginmanager_p.h b/src/tools/qpluginmanager_p.h deleted file mode 100644 index 4e42eed0f..000000000 --- a/src/tools/qpluginmanager_p.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Definition of TQPluginManager class -** -** Created : 000101 -** -** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQPLUGINMANAGER_P_H -#define TQPLUGINMANAGER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of a number of TQt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqgpluginmanager_p.h" -#endif // QT_H - -#ifndef TQT_NO_COMPONENT - -template -class TQPluginManager : public TQGPluginManager -{ -public: - TQPluginManager( const TQUuid& id, const TQStringList& paths = TQString::null, const TQString &suffix = TQString::null, bool cs = TRUE ) - : TQGPluginManager( id, paths, suffix, cs ) {} - TQRESULT queryInterface(const TQString& feature, Type** iface) const - { - return queryUnknownInterface( feature, (TQUnknownInterface**)iface ); - } -}; - -#endif //TQT_NO_COMPONENT - -#endif //TQPLUGINMANAGER_P_H diff --git a/src/tools/qt_tools.pri b/src/tools/qt_tools.pri index c8eacaee8..36c144e99 100644 --- a/src/tools/qt_tools.pri +++ b/src/tools/qt_tools.pri @@ -10,7 +10,7 @@ tools { $$TOOLS_H/tqcache.h \ $$TOOLS_H/tqcleanuphandler.h \ $$TOOLS_P/tqcomponentfactory_p.h \ - $$TOOLS_P/qcomlibrary_p.h \ + $$TOOLS_P/tqcomlibrary_p.h \ $$TOOLS_H/tqcstring.h \ $$TOOLS_H/tqdatastream.h \ $$TOOLS_H/tqdatetime.h \ @@ -40,7 +40,7 @@ tools { $$TOOLS_H/tqmutex.h \ $$TOOLS_P/tqmutex_p.h \ $$TOOLS_P/tqmutexpool_p.h \ - $$TOOLS_P/qpluginmanager_p.h \ + $$TOOLS_P/tqpluginmanager_p.h \ $$TOOLS_H/tqptrcollection.h \ $$TOOLS_H/tqptrdict.h \ $$TOOLS_H/tqptrqueue.h \ @@ -57,14 +57,14 @@ tools { $$TOOLS_H/tqtextstream.h \ $$TOOLS_P/tqthreadinstance_p.h \ $$TOOLS_H/tqthreadstorage.h\ - $$TOOLS_P/qunicodetables_p.h \ + $$TOOLS_P/tqunicodetables_p.h \ $$TOOLS_H/tqptrvector.h \ $$TOOLS_H/tqvaluelist.h \ $$TOOLS_H/tqvaluestack.h \ $$TOOLS_H/tqvaluevector.h \ $$TOOLS_H/tqwaitcondition.h \ - $$TOOLS_P/qcom_p.h \ - $$TOOLS_P/qucom_p.h \ + $$TOOLS_P/tqcom_p.h \ + $$TOOLS_P/tqucom_p.h \ $$TOOLS_H/tquuid.h win32:SOURCES += $$TOOLS_CPP/tqdir_win.cpp \ @@ -75,7 +75,7 @@ tools { $$TOOLS_CPP/tqmutex_win.cpp \ $$TOOLS_CPP/tqwaitcondition_win.cpp \ $$TOOLS_CPP/tqthreadstorage_win.cpp \ - $$TOOLS_CPP/qcriticalsection_p.cpp + $$TOOLS_CPP/tqcriticalsection_p.cpp win32-borland:SOURCES += $$TOOLS_CPP/tqwinexport.cpp @@ -108,7 +108,7 @@ tools { SOURCES += $$TOOLS_CPP/tqbitarray.cpp \ $$TOOLS_CPP/tqbuffer.cpp \ $$TOOLS_CPP/tqcomponentfactory.cpp \ - $$TOOLS_CPP/qcomlibrary.cpp \ + $$TOOLS_CPP/tqcomlibrary.cpp \ $$TOOLS_CPP/tqcstring.cpp \ $$TOOLS_CPP/tqdatastream.cpp \ $$TOOLS_CPP/tqdatetime.cpp \ @@ -135,8 +135,8 @@ tools { $$TOOLS_CPP/tqsettings.cpp \ $$TOOLS_CPP/tqstringlist.cpp \ $$TOOLS_CPP/tqtextstream.cpp \ - $$TOOLS_CPP/qunicodetables.cpp \ - $$TOOLS_CPP/qucom.cpp \ + $$TOOLS_CPP/tqunicodetables.cpp \ + $$TOOLS_CPP/tqucom.cpp \ $$TOOLS_CPP/tquuid.cpp irix-cc* { diff --git a/src/tools/qucom.cpp b/src/tools/qucom.cpp deleted file mode 100644 index 8444c7f3b..000000000 --- a/src/tools/qucom.cpp +++ /dev/null @@ -1,573 +0,0 @@ -/**************************************************************************** -** -** Implementation of the TQUcom classes -** -** Created : 990101 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "private/qucom_p.h" -#include "private/qucomextra_p.h" - -#include "tqvariant.h" - -#include - -// Standard types - -// {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} -const TQUuid TID_QUType_Null( 0xde56510e, 0x4e9f, 0x4b76, 0xa3, 0xc2, 0xd1, 0xe2, 0xef, 0x42, 0xf1, 0xac ); -const TQUuid *TQUType_Null::uuid() const { return &TID_QUType_Null; } -const char *TQUType_Null::desc() const { return "null"; } -bool TQUType_Null::canConvertFrom( TQUObject *, TQUType * ) { return FALSE; } -bool TQUType_Null::canConvertTo( TQUObject *, TQUType * ) { return FALSE; } -bool TQUType_Null::convertFrom( TQUObject *, TQUType * ) { return FALSE; } -bool TQUType_Null::convertTo( TQUObject *, TQUType * ) { return FALSE; } -void TQUType_Null::clear( TQUObject *) {} -int TQUType_Null::serializeTo( TQUObject *, TQUBuffer * ) { return 0; } -int TQUType_Null::serializeFrom( TQUObject *, TQUBuffer * ) { return 0; } -TQUType_Null static_QUType_Null; - - -// {7EE17B08-5419-47e2-9776-8EEA112DCAEC} -const TQUuid TID_QUType_enum( 0x7ee17b08, 0x5419, 0x47e2, 0x97, 0x76, 0x8e, 0xea, 0x11, 0x2d, 0xca, 0xec ); -TQUType_enum static_QUType_enum; -const TQUuid *TQUType_enum::uuid() const { return &TID_QUType_enum; } -const char *TQUType_enum::desc() const { return "enum"; } -void TQUType_enum::set( TQUObject *o, int v ) -{ - o->payload.i = v; - o->type = this; -} - -bool TQUType_enum::canConvertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? - return TRUE; - - return t->canConvertTo( o, this ); -} - -bool TQUType_enum::canConvertTo( TQUObject * /*o*/, TQUType *t ) -{ - return isEqual( t, &static_QUType_int ); -} - -bool TQUType_enum::convertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? - ; - else - return t->convertTo( o, this ); - - o->type = this; - return TRUE; -} - -bool TQUType_enum::convertTo( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) { - o->type = &static_QUType_int; - return TRUE; - } - return FALSE; -} - -int TQUType_enum::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_enum::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {8AC26448-5AB4-49eb-968C-8F30AB13D732} -const TQUuid TID_QUType_ptr( 0x8ac26448, 0x5ab4, 0x49eb, 0x96, 0x8c, 0x8f, 0x30, 0xab, 0x13, 0xd7, 0x32 ); -TQUType_ptr static_QUType_ptr; -const TQUuid *TQUType_ptr::uuid() const { return &TID_QUType_ptr; } -const char *TQUType_ptr::desc() const { return "ptr"; } - -void TQUType_ptr::set( TQUObject *o, const void* v ) -{ - o->payload.ptr = (void*) v; - o->type = this; -} - -bool TQUType_ptr::canConvertFrom( TQUObject *o, TQUType *t ) -{ - return t->canConvertTo( o, this ); -} - -bool TQUType_ptr::canConvertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -bool TQUType_ptr::convertFrom( TQUObject *o, TQUType *t ) -{ - return t->convertTo( o, this ); -} - -bool TQUType_ptr::convertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -int TQUType_ptr::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_ptr::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {97A2594D-6496-4402-A11E-55AEF2D4D25C} -const TQUuid TID_QUType_iface( 0x97a2594d, 0x6496, 0x4402, 0xa1, 0x1e, 0x55, 0xae, 0xf2, 0xd4, 0xd2, 0x5c ); -TQUType_iface static_QUType_iface; -const TQUuid *TQUType_iface::uuid() const { return &TID_QUType_iface; } -const char *TQUType_iface::desc() const { return "UnknownInterface"; } - -void TQUType_iface::set( TQUObject *o, TQUnknownInterface* iface ) -{ - o->payload.iface = iface; - o->type = this; -} - -bool TQUType_iface::canConvertFrom( TQUObject *o, TQUType *t ) -{ - return t->canConvertTo( o, this ); -} - -bool TQUType_iface::canConvertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -bool TQUType_iface::convertFrom( TQUObject *o, TQUType *t ) -{ - return t->convertTo( o, this ); -} - -bool TQUType_iface::convertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -int TQUType_iface::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_iface::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} -const TQUuid TID_QUType_idisp( 0x2f358164, 0xe28f, 0x4bf4, 0x9f, 0xa9, 0x4e, 0xc, 0xdc, 0xab, 0xa5, 0xb ); -TQUType_idisp static_QUType_idisp; -const TQUuid *TQUType_idisp::uuid() const { return &TID_QUType_idisp; } -const char *TQUType_idisp::desc() const { return "DispatchInterface"; } - -void TQUType_idisp::set( TQUObject *o, TQDispatchInterface* idisp ) -{ - o->payload.idisp = idisp; - o->type = this; -} - -bool TQUType_idisp::canConvertFrom( TQUObject *o, TQUType *t ) -{ - return t->canConvertTo( o, this ); -} - -bool TQUType_idisp::canConvertTo( TQUObject * /*o*/, TQUType *t ) -{ - return isEqual( t, &static_QUType_iface ); -} - -bool TQUType_idisp::convertFrom( TQUObject *o, TQUType *t ) -{ - return t->convertTo( o, this ); -} - -bool TQUType_idisp::convertTo( TQUObject *o, TQUType *t ) -{ -#ifndef TQT_NO_COMPONENT - if ( isEqual( t, &static_QUType_iface ) ) { - o->payload.iface = (TQUnknownInterface*)o->payload.idisp; - o->type = &static_QUType_iface; - return TRUE; - } -#endif - return FALSE; -} - -int TQUType_idisp::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_idisp::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {CA42115D-13D0-456c-82B5-FC10187F313E} -const TQUuid TID_QUType_bool( 0xca42115d, 0x13d0, 0x456c, 0x82, 0xb5, 0xfc, 0x10, 0x18, 0x7f, 0x31, 0x3e ); -TQUType_bool static_QUType_bool; -const TQUuid *TQUType_bool::uuid() const { return &TID_QUType_bool; } -const char *TQUType_bool::desc() const { return "bool"; } - -void TQUType_bool::set( TQUObject *o, bool v ) -{ - o->payload.b = v; - o->type = this; -} - -bool TQUType_bool::canConvertFrom( TQUObject *o, TQUType *t ) -{ - return t->canConvertTo( o, this ); -} - -bool TQUType_bool::canConvertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -bool TQUType_bool::convertFrom( TQUObject *o, TQUType *t ) -{ - return t->convertTo( o, this ); -} - -bool TQUType_bool::convertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -int TQUType_bool::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_bool::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} -const TQUuid TID_QUType_int( 0x53c1f3be, 0x73c3, 0x4c7d, 0x9e, 0x5, 0xcc, 0xf0, 0x9e, 0xb6, 0x76, 0xb5 ); -TQUType_int static_QUType_int; -const TQUuid *TQUType_int::uuid() const { return &TID_QUType_int; } -const char *TQUType_int::desc() const { return "int"; } - -void TQUType_int::set( TQUObject *o, int v ) -{ - o->payload.i = v; - o->type = this; -} - -bool TQUType_int::canConvertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_double ) ) - return TRUE; - - return t->canConvertTo( o, this ); -} - -bool TQUType_int::canConvertTo( TQUObject * /*o*/, TQUType *t ) -{ - return isEqual( t, &static_QUType_double ); -} - -bool TQUType_int::convertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_double ) ) - o->payload.i = (long)o->payload.d; - else - return t->convertTo( o, this ); - - o->type = this; - return TRUE; -} - -bool TQUType_int::convertTo( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_double ) ) { - o->payload.d = (double)o->payload.i; - o->type = &static_QUType_double; - } else - return FALSE; - return TRUE; -} - -int TQUType_int::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_int::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {2D0974E5-0BA6-4ec2-8837-C198972CB48C} -const TQUuid TID_QUType_double( 0x2d0974e5, 0xba6, 0x4ec2, 0x88, 0x37, 0xc1, 0x98, 0x97, 0x2c, 0xb4, 0x8c ); -TQUType_double static_QUType_double; -const TQUuid *TQUType_double::uuid() const { return &TID_QUType_double; } -const char *TQUType_double::desc() const {return "double"; } - -void TQUType_double::set( TQUObject *o, double v ) -{ - o->payload.d = v; - o->type = this; -} - -bool TQUType_double::canConvertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) - return TRUE; - - return t->canConvertTo( o, this ); -} - -bool TQUType_double::canConvertTo( TQUObject * /*o*/, TQUType *t ) -{ - return isEqual( t, &static_QUType_int ); -} - -bool TQUType_double::convertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) - o->payload.d = (double)o->payload.i; - else - return t->convertTo( o, this ); - - o->type = this; - return TRUE; -} - -bool TQUType_double::convertTo( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_int ) ) { - o->payload.i = (int) o->payload.d; - o->type = &static_QUType_int; - } else if ( isEqual( t, &static_QUType_double ) ) { - o->payload.d = (double) o->payload.f; - o->type = &static_QUType_double; - } else - return FALSE; - return TRUE; -} - -int TQUType_double::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_double::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -// {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} -const TQUuid TID_QUType_charstar( 0xefcdd1d4, 0x77a3, 0x4b8e, 0x8d, 0x46, 0xdc, 0x14, 0xb8, 0xd3, 0x93, 0xe9 ); -TQUType_charstar static_QUType_charstar; -const TQUuid *TQUType_charstar::uuid() const { return &TID_QUType_charstar; } -const char *TQUType_charstar::desc() const { return "char*"; } - -void TQUType_charstar::set( TQUObject *o, const char* v, bool take ) -{ - if ( take ) { - if ( v ) { - o->payload.charstar.ptr = new char[ strlen(v) + 1 ]; - strcpy( o->payload.charstar.ptr, v ); - } else { - o->payload.charstar.ptr = 0; - } - o->payload.charstar.owner = TRUE; - } else { - o->payload.charstar.ptr = (char*) v; - o->payload.charstar.owner = FALSE; - } - o->type = this; -} - -bool TQUType_charstar::canConvertFrom( TQUObject *o, TQUType *t ) -{ - return t->canConvertTo( o, this ); -} - -bool TQUType_charstar::canConvertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -bool TQUType_charstar::convertFrom( TQUObject *o, TQUType *t ) -{ - return t->convertTo( o, this ); -} - -bool TQUType_charstar::convertTo( TQUObject *, TQUType * ) -{ - return FALSE; -} - -void TQUType_charstar::clear( TQUObject *o ) -{ - if ( o->payload.charstar.owner ) - delete [] o->payload.charstar.ptr; - o->payload.charstar.ptr = 0; -} - -int TQUType_charstar::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_charstar::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - - -// TQt specific types - -// {44C2A547-01E7-4e56-8559-35AF9D2F42B7} -const TQUuid TID_QUType_TQString( 0x44c2a547, 0x1e7, 0x4e56, 0x85, 0x59, 0x35, 0xaf, 0x9d, 0x2f, 0x42, 0xb7 ); -TQUType_TQString static_QUType_TQString; -const TQUuid *TQUType_TQString::uuid() const { return &TID_QUType_TQString; } -const char *TQUType_TQString::desc() const { return "TQString"; } - -void TQUType_TQString::set( TQUObject *o, const TQString& v ) -{ - o->payload.ptr = new TQString( v ); - o->type = this; -} - -bool TQUType_TQString::canConvertFrom( TQUObject *o, TQUType *t ) -{ - if ( isEqual( t, &static_QUType_charstar ) || - isEqual( t, &static_QUType_double ) || - isEqual( t, &static_QUType_int ) ) - return TRUE; - - return t->canConvertTo( o, this ); -} - -bool TQUType_TQString::canConvertTo( TQUObject * /*o*/, TQUType *t ) -{ - return isEqual( t, &static_QUType_charstar ) || - isEqual( t, &static_QUType_int ) || - isEqual( t, &static_QUType_double ); -} - -bool TQUType_TQString::convertFrom( TQUObject *o, TQUType *t ) -{ - TQString *str = 0; - if ( isEqual( t, &static_QUType_charstar ) ) - str = new TQString( o->payload.charstar.ptr ); - else if ( isEqual( t, &static_QUType_double ) ) - str = new TQString( TQString::number( o->payload.d ) ); - else if ( isEqual( t, &static_QUType_int ) ) - str = new TQString( TQString::number( o->payload.i ) ); - else - return t->convertTo( o, this ); - - o->type->clear( o ); - o->payload.ptr = str; - o->type = this; - return TRUE; -} - -bool TQUType_TQString::convertTo( TQUObject *o, TQUType *t ) -{ - TQString *str = (TQString *)o->payload.ptr; - if ( isEqual( t, &static_QUType_charstar ) ) { - o->payload.charstar.ptr = tqstrdup( str->local8Bit().data() ); - o->payload.charstar.owner = TRUE; - o->type = &static_QUType_charstar; - } else if ( isEqual( t, &static_QUType_int ) ) { - o->payload.l = str->toLong(); - o->type = &static_QUType_int; - } else if ( isEqual( t, &static_QUType_double ) ) { - o->payload.d = str->toDouble(); - o->type = &static_QUType_double; - } else { - return FALSE; - } - delete str; - return TRUE; -} - -int TQUType_TQString::serializeTo( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -int TQUType_TQString::serializeFrom( TQUObject *, TQUBuffer * ) -{ - return 0; -} - -void TQUType_TQString::clear( TQUObject *o ) -{ - delete (TQString*)o->payload.ptr; - o->payload.ptr = 0; -} - -TQUObject* TQUObject::deepCopy(TQUObject* newLocation) { - TQUObject* ret; - if (newLocation) { - ret = new(newLocation) TQUObject(*this); - } - else { - ret = new TQUObject(*this); - } - // Any type that has a clear() method must be copied here! - if (*(type->uuid()) == TID_QUType_charstar) { - static_QUType_charstar.set( ret, (const char *)static_QUType_charstar.get(this), true ); - } - if (*(type->uuid()) == TID_QUType_TQString) { - static_QUType_TQString.set( ret, (TQString)static_QUType_TQString.get(this) ); - } - if (*(type->uuid()) == TID_QUType_TQVariant) { - static_QUType_TQVariant.set( ret, (TQVariant)static_QUType_TQVariant.get(this) ); - } - return ret; -} diff --git a/src/tools/qucom_p.h b/src/tools/qucom_p.h deleted file mode 100644 index 761d5cee4..000000000 --- a/src/tools/qucom_p.h +++ /dev/null @@ -1,472 +0,0 @@ -/**************************************************************************** -** -** Definition of the TQUcom interfaces -** -** Created : 990101 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the tools module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQUCOM_P_H -#define TQUCOM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of a number of TQt sources files. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqstring.h" -#include "tquuid.h" -#endif // QT_H - -#ifdef check -#undef check -#endif - -#if __GNUC__ - 0 > 3 -#pragma GCC system_header -#endif - -struct TQUObject; -struct TQUInterfaceDescription; -struct TQUnknownInterface; -struct TQDispatchInterface; - - -struct TQ_EXPORT TQUBuffer -{ - virtual long read( char *data, ulong maxlen ) = 0; - virtual long write( const char *data, ulong len ) = 0; -}; - - -// A type for a TQUObject -struct TQ_EXPORT TQUType -{ - virtual const TQUuid *uuid() const = 0; - virtual const char *desc() const = 0; - - - virtual bool canConvertFrom( TQUObject *, TQUType * ) = 0; - // virtual private, only called by canConvertFrom - virtual bool canConvertTo( TQUObject *, TQUType * ) = 0; - - - virtual bool convertFrom( TQUObject *, TQUType * ) = 0; - // virtual private, only called by convertFrom - virtual bool convertTo( TQUObject *, TQUType * ) = 0; - - virtual void clear( TQUObject * ) = 0; - - virtual int serializeTo( TQUObject *, TQUBuffer * ) = 0; - virtual int serializeFrom( TQUObject *, TQUBuffer * ) = 0; - - static bool isEqual( const TQUType *t1, const TQUType *t2 ); - static bool check( TQUObject* o, TQUType* t ); -}; - - -// {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} -extern TQ_EXPORT const TQUuid TID_QUType_Null; -struct TQ_EXPORT TQUType_Null : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ); - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_Null static_QUType_Null; - - -// The magic TQUObject -struct TQ_EXPORT TQUObject -{ -public: // scary MSVC bug makes this necessary - TQUObject() : type( &static_QUType_Null ), isLastObject(false) {} - ~TQUObject() { type->clear( this ); } - - TQUType *type; - - // the unavoidable union - union - { - bool b; - - char c; - short s; - int i; - long l; - - unsigned char uc; - unsigned short us; - unsigned int ui; - unsigned long ul; - - float f; - double d; - - char byte[16]; - - struct { - char* data; - unsigned long size; - } bytearray; - - void* ptr; - - struct { - void *ptr; - bool owner; - } voidstar; - - struct { - char *ptr; - bool owner; - } charstar; - - struct { - char *ptr; - bool owner; - } utf8; - - struct { - char *ptr; - bool owner; - } local8bit; - - TQUnknownInterface* iface; - TQDispatchInterface* idisp; - - } payload; - - TQUObject* deepCopy(TQUObject*); - bool isLastObject; -}; - - -// A parameter description describes one method parameters. A -// parameter has a name, a type and a flag describing whether it's an -// in parameter, an out parameter, or both ways -struct TQ_EXPORT TQUParameter -{ - const char* name; - TQUType *type; - const void* typeExtra; //Usually 0, UEnum* for TQUType_enum, const char* for TQUType_ptr, int* for TQUType_varptr - enum { In = 1, Out = 2, InOut = In | Out }; - int inOut; -}; - -// A method description describes one method. A method has a name and -// an array of parameters. -struct TQ_EXPORT TQUMethod -{ - const char* name; - int count; - const TQUParameter* parameters; -}; - -// A Property description. Not used yet in the example. -struct TQ_EXPORT TQUProperty -{ - const char* name; - TQUType* type; - const void* typeExtra; //type dependend. Usually 0, but UEnum for TQUTypeenum or const char* for TQUTypeptr - - int set; // -1 undefined - int get; // -1 undefined - - int designable; // -1 FALSE, -2 TRUE, else method - int stored; // -1 FALSE, -2 TRUE, else method -}; - -// An interface description describes one interface, that is all its -// methods and properties. -struct TQ_EXPORT TQUInterfaceDescription -{ - int methodCount; - const TQUMethod* methods; - int propertyCount; - const TQUProperty* properties; -}; - - -// A component description describe one component, that is its name, -// vendor, release, info, its component uuid and all its interface -// uuids. -struct TQ_EXPORT TQUComponentDescription -{ - const char* name; - const char* vendor; - const char* release; - const char* info; - TQUuid cid; - int count; - const TQUuid* interfaces; -}; - - -// A component server description describe one component server, that -// is its name, vendor, release, info and the descriptions of all -// components it can instantiate. -struct TQ_EXPORT TQUComponentServerDescription -{ - const char* name; - const char* vendor; - const char* release; - const char* info; - int count; - const TQUComponentDescription* components; -}; - - - -struct TQ_EXPORT TQUEnumItem // - a name/value pair -{ - const char *key; - int value; -}; - -struct TQ_EXPORT TQUEnum -{ - const char *name; // - enumerator name - unsigned int count; // - number of values - const TQUEnumItem *items; // - the name/value pairs - bool set; // whether enum has to be treated as a set -}; - -inline bool TQUType::isEqual( const TQUType *t1, const TQUType *t2 ) { - return t1 == t2 || t1->uuid() == t2->uuid() || - *(t1->uuid()) == *(t2->uuid()); -} - -inline bool TQUType::check( TQUObject* o, TQUType* t ) { - return isEqual( o->type, t ) || t->convertFrom( o, o->type ); -} - - - -// {7EE17B08-5419-47e2-9776-8EEA112DCAEC} -extern TQ_EXPORT const TQUuid TID_QUType_enum; -struct TQ_EXPORT TQUType_enum : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, int ); - int &get( TQUObject * o ) { return o->payload.i; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_enum static_QUType_enum; - - -// {8AC26448-5AB4-49eb-968C-8F30AB13D732} -extern TQ_EXPORT const TQUuid TID_QUType_ptr; -struct TQ_EXPORT TQUType_ptr : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, const void* ); - void* &get( TQUObject * o ) { return o->payload.ptr; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_ptr static_QUType_ptr; - -// {97A2594D-6496-4402-A11E-55AEF2D4D25C} -extern TQ_EXPORT const TQUuid TID_QUType_iface; -struct TQ_EXPORT TQUType_iface : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, TQUnknownInterface* ); - TQUnknownInterface* &get( TQUObject *o ){ return o->payload.iface; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_iface static_QUType_iface; - -// {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} -extern TQ_EXPORT const TQUuid TID_QUType_idisp; -struct TQ_EXPORT TQUType_idisp : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, TQDispatchInterface* ); - TQDispatchInterface* &get( TQUObject *o ){ return o->payload.idisp; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_idisp static_QUType_idisp; - -// {CA42115D-13D0-456c-82B5-FC10187F313E} -extern TQ_EXPORT const TQUuid TID_QUType_bool; -struct TQ_EXPORT TQUType_bool : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, bool ); - bool &get( TQUObject *o ) { return o->payload.b; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_bool static_QUType_bool; - -// {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} -extern TQ_EXPORT const TQUuid TID_QUType_int; -struct TQ_EXPORT TQUType_int : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, int ); - int &get( TQUObject *o ) { return o->payload.i; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_int static_QUType_int; - - -// {2D0974E5-0BA6-4ec2-8837-C198972CB48C} -extern TQ_EXPORT const TQUuid TID_QUType_double; -struct TQ_EXPORT TQUType_double : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, double ); - double &get( TQUObject *o ) { return o->payload.d; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ) {} - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); -}; -extern TQ_EXPORT TQUType_double static_QUType_double; - - -// {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} -extern TQ_EXPORT const TQUuid TID_QUType_charstar; -struct TQ_EXPORT TQUType_charstar : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, const char*, bool take = FALSE ); - char* get( TQUObject *o ){ return o->payload.charstar.ptr; } - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ); - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); - -}; -extern TQ_EXPORT TQUType_charstar static_QUType_charstar; - -// {44C2A547-01E7-4e56-8559-35AF9D2F42B7} -extern const TQUuid TID_QUType_TQString; - -struct TQ_EXPORT TQUType_TQString : public TQUType -{ - const TQUuid *uuid() const; - const char *desc() const; - - void set( TQUObject *, const TQString & ); - TQString &get( TQUObject * o ) { return *(TQString*)o->payload.ptr; } - - bool canConvertFrom( TQUObject *, TQUType * ); - bool canConvertTo( TQUObject *, TQUType * ); - bool convertFrom( TQUObject *, TQUType * ); - bool convertTo( TQUObject *, TQUType * ); - void clear( TQUObject * ); - int serializeTo( TQUObject *, TQUBuffer * ); - int serializeFrom( TQUObject *, TQUBuffer * ); - -}; -extern TQ_EXPORT TQUType_TQString static_QUType_TQString; - - -#endif // TQUCOM_P_H diff --git a/src/tools/qunicodetables.cpp b/src/tools/qunicodetables.cpp deleted file mode 100644 index b442bcbff..000000000 --- a/src/tools/qunicodetables.cpp +++ /dev/null @@ -1,13257 +0,0 @@ -/**************************************************************************** -** -** ??? -** -** Copyright (C) 2002-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qunicodetables_p.h" - -/* ------------------------------------------------------------------------- - * unicode information - * these tables are generated from the unicode reference file - * ftp://ftp.unicode.org/Public/3.2-Update/UnicodeData.txt - * - * Lars - * ------------------------------------------------------------------------- - */ - -/* ------------------------------------------------------------------------- -2021-04-12 - -Data between - -// START OF GENERATED DATA -and -// END OF GENERATED DATA - -regenerated by adding new character data to UnicodeData-3.2.0.txt[*] -with unedited ArabicShaping-3.2.0.txt and LineBreak-3.2.0.txt -and using perl-5.10 - -[*] https://unicode.org/Public/3.2-Update/ - * ------------------------------------------------------------------------- - */ - -/* Perl script to generate (run perl -x tools/qunicodetables.cpp) - -#!perl - -sub numberize -{ - my(%r, $n, $id); - for $id ( @_ ) { - $i = $id; - $i="" if $i eq "EMPTY"; - $r{$i}=$n++; - } - return %r; -} - - -sub readUnicodeDataLine { - $code = shift @_; - for $n (qw{ - name category combining_class bidi_category - character_decomposition decimal_digit_value digit_value - numeric_value mirrored oldname comment - uppercase lowercase titlecase}) - { - $id = shift @_; - $codes = "${n}_code"; - if ( defined %$codes && defined $$codes{$id} ) { - $id = $$codes{$id}; - } - ${$n}{$code}=$id; - } - $decomp = $character_decomposition{$code}; - if ( length $decomp == 0 ) { - $decomp = ""; - } - if (substr($decomp, 0, 1) ne '<') { - $decomp = " " . $decomp; - } - @_ = split(" ", $decomp); - $tag = shift @_; - $tag = $character_decomposition_tag{$tag}; - $decomp = join( ", 0x", @_ ); - $decomp = "0x".$decomp; - $decomposition{$code} = $decomp; - $decomposition_tag{$code} = $tag; - $decomposition_pos{$code} = $position; - $len = scalar(@_); - $decomposition_len{$code} = $len; - -# we use canonical decompositions longer than 1 char -# we exlude Arabic ligatures from the table - if($len > 1 and $tag == 1) { -# ligature to add... - $start = shift @_; - $ligature{$start} = $ligature{$start}." ".$code; - } - -# adjust position - if($len != 0) { - $position += $len + 3; - } -} - - -# Code to integer mappings... -# -%category_code = numberize(qw{ - EMPTY - Mn Mc Me - Nd Nl No - Zs Zl Zp - Cc Cf Cs Co Cn - - Lu Ll Lt Lm Lo - Pc Pd Ps Pe Pi Pf Po - Sm Sc Sk So -}); -%bidi_category_code = numberize(qw{ - L R EN ES ET AN CS B S WS ON LRE LRO AL RLE RLO PDF NSM BN}); -%character_decomposition_tag = numberize(qw{ - - - -}); -%mirrored_code = numberize(qw{N Y}); - -%joining_code = numberize(qw{U D R C}); - -# we map AI and XX to AL for now, as we can't handle them any better -%line_break_code = numberize(qw{OP CL QU GL NS EX SY - IS PR PO NU AL ID IN HY - BA BB B2 - ZW CM - SA - BK CR LF SG CB SP -}); - -# Read data into hashes... -# -open IN, "UnicodeData-3.2.0.txt"; -$position = 1; -while () { - @fields = split /;/; - if ( length($fields[0]) < 5 ) { - if ( $fields[1] =~ /, First>/ ) { - $codeRangeBegin = $fields[0]; - } elsif ( $fields[1] =~ /, Last>/ ) { - for ( $i=hex($codeRangeBegin); $i<=hex($fields[0]); $i+=1 ) { - @fields2 = @fields; - $fields2[0] = sprintf "%lX", $i; - readUnicodeDataLine @fields2; - } - } else { - readUnicodeDataLine @fields; - } - } -} - -open IN2, "ArabicShaping-3.2.0.txt"; -$position = 1; -while () { - @fields = split /;/; - $code = shift @fields; - $dummy = shift @fields; - $join = shift @fields; - $join =~ s/ //g; - $join = $joining_code{$join}; - $joining{$code}=$join; -} - -open IN3, "LineBreak-3.2.0.txt"; -$position = 1; -while () { - @fields = split /;/; - $code = shift @fields; - $break = shift @fields; - if (length($break) > 0) { - chomp $break; - $break =~ s/ .*$//; - - $from = $code; - $to = $code; - if ( length($code) > 5 ) { - $from =~ s,\.\..*,,; - $to =~ s/......//; -# print "$from..$to = $break\n"; - } - if($break eq "AI") { - $break = "AL"; - } - if($break eq "XX") { - $break = "AL"; - } - for ( $i=hex($from); $i<=hex($to); $i+=1 ) { - $breaks{sprintf("%04X",$i)}=$line_break_code{$break}; - } - } -} - -# Build pages... -# -$rowtable_txt = ""; -$row_txt = ""; -$pos = 1; -for $row ( 0..255 ) { - $nonzero=0; - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$row,$cell); - $info = $category{$code}; - $info = 0 if !defined $info; - $txt .= "\n " if $cell%8 == 0; - $txt .= "$info, "; - } - $therow = $row{$txt}; - if ( !defined $therow ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $row{$txt}=$therow; - $pos += 1; - $size += 256; - } - $rowtable_txt .= "\n " if $row%8 == 0; - $rowtable_txt .= "$therow, "; -} - -print "// START OF GENERATED DATA\n\n"; -print "#ifndef TQT_NO_UNICODETABLES\n\n"; - -# Print pages... -# - -print "const TQ_UINT8 TQUnicodeTables::unicode_info[] = {"; -print $rowtable_txt; -$size += 256; -print "\n\n"; -print $row_txt; -print "};\n\n"; -print "// $size bytes\n\n"; - -# Build decomposition tables -# -$rowtable_txt = ""; -$row_txt = ""; -$table_txt = - "const TQ_UINT16 TQUnicodeTables::decomposition_map[] = {\n 0,\n"; -$pos = 1; -for $row ( 0..255 ) { - $nonzero=0; - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$row,$cell); - $txt .= "\n " if $cell%8 == 0; - if( $decomposition_tag{$code} != 0 ) { - $txt .= " $decomposition_pos{$code},"; - $table_txt .= " $decomposition_tag{$code},"; - $table_txt .= " 0x$code,"; - $table_txt .= " $decomposition{$code}, 0,\n"; - $size += 2 * $decomposition_len{$code} + 6; - } else { - $txt .= " 0,"; - } - } - $therow = $row{$txt}; - if ( !defined $therow ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $row{$txt}=$therow; - $pos += 1; - $size += 512; - } - $rowtable_txt .= "\n " if $row%8 == 0; - $rowtable_txt .= "$therow, "; -} - -# Print decomposition tables -# -print "$table_txt\n};\n\n"; - -print "const TQ_UINT16 TQUnicodeTables::decomposition_info[] = {"; -print "$rowtable_txt\n"; -$size += 512; -print $row_txt; -print "};\n\n"; -print "// $size bytes\n\n"; - - -# build ligature tables -# -$size = 0; -$position = 1; -$pos = 1; -$rowtable_txt = ""; -$row_txt = ""; -$table_txt = - "const TQ_UINT16 TQUnicodeTables::ligature_map[] = {\n 0,\n"; -for $lig_row ( 0..255 ) { - $nonzero=0; - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$lig_row,$cell); - $txt .= "\n " if $cell%8 == 0; - if( defined $ligature{$code} ) { - $txt .= " $position,"; - @ligature = split(" ", $ligature{$code}); -# we need to sort ligatures according to their length. -# long ones have to come first! - @ligature_sort = sort { $decomposition_len{$b} <=> $decomposition_len{$a} } @ligature; -# now replace each code by its position in -# the decomposition map. - undef(@lig_pos); - for $n (@ligature_sort) { - push(@lig_pos, $decomposition_pos{$n}); - } -# debug info - if( 0 ) { - print "ligatures: $ligature{$code}\n"; - $sort = join(" ", @ligature_sort); - print "sorted : $sort\n"; - } - $lig = join(", ", @lig_pos); - $table_txt .= " $lig, 0,\n"; - $size += 2 * scalar(@ligature) + 2; - $position += scalar(@ligature) + 1; - } else { - $txt .= " 0,"; - } - } - $therow = $lig_row{$txt}; - if ( !defined $therow ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $lig_row{$txt}=$therow; - $pos += 1; - $size += 512; - } - $rowtable_txt .= "\n " if $lig_row%8 == 0; - $rowtable_txt .= "$therow, "; -} - -# Print ligature tables -# -print "$table_txt\n};\n\n"; -print "const TQ_UINT16 TQUnicodeTables::ligature_info[] = {"; -print "$rowtable_txt\n\n"; -$size+=512; -print $row_txt; -print "};\n\n"; -print "// $size bytes\n\n"; - - - -# Build direction/joining/mirrored pages... -# -$rowtable_txt = ""; -$row_txt = ""; -$pos = 1; -for $dir_row ( 0..255 ) { - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$dir_row,$cell); - $dir = $bidi_category{$code}; - $dir = 0 if !defined $dir; - $join = $joining{$code}; - $join = 0 if !defined $join; - $mirr = $mirrored{$code}; - $mirr = 0 if !defined $mirr; - $info = $dir + 32*$join + 128*$mirr; - $txt .= "\n " if $cell%8 == 0; - $txt .= "$info, "; - } - $therow = $dir_row{$txt}; - if ( !defined $therow ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $dir_row{$txt}=$therow; - $pos += 1; - $size+=256; - } - $rowtable_txt .= "\n " if $dir_row%8 == 0; - $rowtable_txt .= "$therow, "; -} - -# Print pages... -# -print "const TQ_UINT8 TQUnicodeTables::direction_info[] = {"; -print "$rowtable_txt\n\n"; -$size+=256; -print $row_txt; -print "};\n\n"; -print "// $size bytes\n\n"; - -# Build table of combining classes -# -$rowtable_txt = ""; -$row_txt = ""; -$pos = 1; -for $combining_row ( 0..255 ) { - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$combining_row,$cell); - $info = $combining_class{$code}; - $info = 0 if !defined $info; - $txt .= "\n " if $cell%8 == 0; - $txt .= "$info, "; - } - $therow = $combining_row{$txt}; - if ( !defined $therow ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $combining_row{$txt}=$therow; - $pos += 1; - $size += 256; - } - $rowtable_txt .= "\n " if $combining_row%8 == 0; - $rowtable_txt .= "$therow, "; -} - -# Print pages... -# -print "const TQ_UINT8 TQUnicodeTables::combining_info[] = {"; -print "$rowtable_txt\n\n"; -$size+=256; -print $row_txt; -print "};\n\n"; -print "// $size bytes\n\n"; - -# Build case info -# -$rowtable_txt = ""; -$row_txt = ""; -$pos = 1; -for $row ( 0..255 ) { - $nonzero=0; - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$row,$cell); - $info = $uppercase{$code}; - if ( length( $info ) eq 0 ) { - $info = $lowercase{$code}; - } - $info =~ s/^0+//; - if ( length( $info ) eq 0 ) { - $info = "0"; - } else { - $info = "0x".lc($info); - } - if ( length( $info ) ne 1 ) { - $nonzero = 1; - } - $txt .= "\n " if $cell%8 == 0; - $txt .= "$info, "; - } - $therow = $case_row{$txt}; - if ( !defined $therow && $nonzero ne 0 ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $case_row{$txt}=$therow; - $pos += 1; - $size += 512; - } - $rowtable_txt .= "\n " if $row%8 == 0; - if ( $nonzero ne 0 ) { - $rowtable_txt .= "$therow, "; - } else { - $rowtable_txt .= "0, "; - } -} - -# Print pages... -# -print "const TQ_UINT16 TQUnicodeTables::case_info[] = {"; -print "$rowtable_txt\n\n"; -$size+=512; -print $row_txt; -print "};\n"; -print "// $size bytes\n\n"; - -# Build decimal info -# -$rowtable_txt = ""; -$row_txt = ""; -$pos = 1; -for $row ( 0..255 ) { - $nonzero=0; - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$row,$cell); - $info = $digit_value{$code}; - if ( length( $info ) eq 0 ) { - $info = -1; - } else { - $nonzero = 1; - } - $txt .= "\n " if $cell%8 == 0; - $txt .= "$info, "; - } - $therow = $decimal_row{$txt}; - if ( !defined $therow && $nonzero ne 0 ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $decimal_row{$txt}=$therow; - $pos += 1; - $size += 256; - } - $rowtable_txt .= "\n " if $row%8 == 0; - if ( $nonzero ne 0 ) { - $rowtable_txt .= "$therow, "; - } else { - $rowtable_txt .= "0, "; - } -} - -# Print pages... -# -print "const TQ_INT8 TQUnicodeTables::decimal_info[] = {"; -print "$rowtable_txt\n\n"; -$size+=512; -print $row_txt; -print "};\n"; -print "// $size bytes\n\n"; - - -# Build line break info -# -$rowtable_txt = ""; -$row_txt = ""; -$pos = 1; -for $row ( 0..255 ) { - $txt = ""; - for $cell ( 0..255 ) { - $code = sprintf("%02X%02X",$row,$cell); - $info = $breaks{$code}; - if ( length( $info ) eq 0 ) { - $info = $line_break_code{"AL"}; - } - $txt .= "\n " if $cell%8 == 0; - $txt .= "$info, "; - } - $therow = $lb_row{$txt}; - if ( !defined $therow ) { - $therow = sprintf("%d",$pos); - $row_txt = $row_txt."$txt\n"; - $lb_row{$txt}=$therow; - $pos += 1; - $size += 256; - } - $rowtable_txt .= "\n " if $row%8 == 0; - $rowtable_txt .= "$therow, "; -} - -# Print pages... -# -print "const TQ_UINT8 TQUnicodeTables::line_break_info[] = {"; -print "$rowtable_txt\n\n"; -$size+=512; -print $row_txt; -print "};\n"; -print "// $size bytes\n\n"; - - - -print "#endif\n\n"; -print "// END OF GENERATED DATA\n\n"; - - -__END__ - -*/ - -// START OF GENERATED DATA - -#ifndef TQT_NO_UNICODETABLES - -const TQ_UINT8 TQUnicodeTables::unicode_info[] = { - 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, 9, 9, 9, 9, 9, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 30, 9, 9, 9, 38, 39, - 40, 41, 42, 43, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 44, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 45, - 22, 22, 22, 22, 46, 9, 9, 9, - 9, 9, 9, 9, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 47, - 48, 48, 48, 48, 48, 48, 48, 48, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, - 49, 22, 50, 51, 22, 52, 53, 54, - - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 7, 26, 26, 26, 28, 26, 26, 26, - 22, 23, 26, 27, 26, 21, 26, 26, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 26, 26, 27, 27, 27, 26, - 26, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 22, 26, 23, 29, 20, - 29, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 22, 27, 23, 27, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 7, 26, 28, 28, 28, 28, 30, 30, - 29, 30, 16, 24, 27, 21, 30, 29, - 30, 27, 6, 6, 29, 16, 30, 26, - 29, 6, 16, 25, 6, 6, 6, 26, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 27, - 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 27, - 16, 16, 16, 16, 16, 16, 16, 16, - - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 16, 15, 16, 15, 16, 15, 16, 15, - 16, 15, 16, 15, 16, 15, 16, 15, - 16, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 15, 16, 15, 16, 15, 16, 16, - 16, 15, 15, 16, 15, 16, 15, 15, - 16, 15, 15, 15, 16, 16, 15, 15, - 15, 15, 16, 15, 15, 16, 15, 15, - 15, 16, 16, 16, 15, 15, 16, 15, - 15, 16, 15, 16, 15, 16, 15, 15, - 16, 15, 16, 16, 15, 16, 15, 15, - 16, 15, 15, 15, 16, 15, 16, 15, - 15, 16, 16, 19, 15, 16, 16, 16, - 19, 19, 19, 19, 15, 17, 16, 15, - 17, 16, 15, 17, 16, 15, 16, 15, - 16, 15, 16, 15, 16, 15, 16, 15, - 16, 15, 16, 15, 16, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 16, 15, 17, 16, 15, 16, 15, 15, - 15, 16, 15, 16, 15, 16, 15, 16, - - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 0, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 15, 16, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 0, 0, - 18, 18, 18, 18, 18, 18, 18, 18, - 18, 29, 29, 18, 18, 18, 18, 18, - 18, 18, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, - 18, 18, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, - 18, 18, 18, 18, 18, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 18, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 29, 29, 0, 0, - 0, 0, 18, 0, 0, 0, 26, 0, - 0, 0, 0, 0, 29, 29, 15, 26, - 15, 15, 15, 0, 15, 0, 15, 15, - 16, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 0, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 0, - 16, 16, 15, 15, 15, 16, 16, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 16, 16, 16, 16, 15, 16, 27, 0, - 0, 15, 15, 16, 0, 0, 0, 0, - - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 30, 1, 1, 1, 1, 0, - 3, 3, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 15, 16, 15, 16, 15, 16, 15, - 16, 15, 16, 15, 16, 15, 16, 0, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 0, 0, - 15, 16, 0, 0, 0, 0, 0, 0, - - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 0, - 0, 18, 26, 26, 26, 26, 26, 26, - 0, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 0, 26, 21, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 1, 1, 1, 26, 1, - 26, 1, 1, 26, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, - 19, 19, 19, 26, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 26, 0, 0, 0, 26, - 0, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, - 18, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 26, 26, 26, 26, 19, 19, - 1, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 26, 19, 1, 1, - 1, 1, 1, 1, 1, 11, 3, 1, - 1, 1, 1, 1, 1, 18, 18, 1, - 1, 30, 1, 1, 1, 1, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 19, 19, 19, 30, 30, 0, - - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 0, 11, - 19, 1, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 19, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 1, 1, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 0, 1, 19, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 1, 0, 0, - 19, 1, 1, 1, 1, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 1, 1, 26, 26, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 26, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 19, - 19, 0, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 0, 0, 0, 19, 19, - 19, 19, 0, 0, 1, 0, 2, 2, - 2, 1, 1, 1, 1, 0, 0, 2, - 2, 0, 0, 2, 2, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 19, 19, 0, 19, - 19, 19, 1, 1, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 19, 19, 28, 28, 6, 6, 6, 6, - 6, 6, 30, 0, 0, 0, 0, 0, - - 0, 0, 1, 0, 0, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 19, - 19, 0, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 0, 19, 19, 0, - 19, 19, 0, 0, 1, 0, 2, 2, - 2, 1, 1, 0, 0, 0, 0, 1, - 1, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 19, 19, 19, 19, 0, 19, 0, - 0, 0, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 1, 1, 19, 19, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 0, 19, 0, 19, - 19, 19, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 0, 19, 19, 19, - 19, 19, 0, 0, 1, 19, 2, 2, - 2, 1, 1, 1, 1, 1, 0, 1, - 1, 2, 0, 2, 2, 1, 0, 0, - 19, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 0, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 1, 2, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 19, - 19, 0, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 0, 0, 19, 19, - 19, 19, 0, 0, 1, 19, 2, 1, - 2, 1, 1, 1, 0, 0, 0, 2, - 2, 0, 0, 2, 2, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, - 0, 0, 0, 0, 19, 19, 0, 19, - 19, 19, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 30, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 19, 0, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 19, 19, - 19, 0, 19, 19, 19, 19, 0, 0, - 0, 19, 19, 0, 19, 0, 19, 19, - 0, 0, 0, 19, 19, 0, 0, 0, - 19, 19, 19, 0, 0, 0, 19, 19, - 19, 19, 19, 19, 19, 19, 0, 19, - 19, 19, 0, 0, 0, 0, 2, 2, - 1, 2, 2, 0, 0, 0, 2, 2, - 2, 0, 2, 2, 2, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 6, 6, 6, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 2, 2, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 0, 19, 19, 19, - 19, 19, 0, 0, 0, 0, 1, 1, - 1, 2, 2, 2, 2, 0, 1, 1, - 1, 0, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 0, 19, 19, 19, - 19, 19, 0, 0, 0, 0, 2, 1, - 2, 2, 2, 2, 2, 0, 1, 2, - 2, 0, 2, 2, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 19, 0, - 19, 19, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 2, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 0, 0, 0, 2, 2, - 2, 1, 1, 1, 0, 0, 2, 2, - 2, 0, 2, 2, 2, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 0, 0, 0, 0, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 2, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 0, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 0, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 0, - 0, 0, 1, 0, 0, 0, 0, 2, - 2, 2, 1, 1, 1, 0, 1, 0, - 2, 2, 2, 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 2, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 1, 19, 19, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 28, - 19, 19, 19, 19, 19, 19, 18, 1, - 1, 1, 1, 1, 1, 1, 1, 26, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 26, 26, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 19, 19, 0, 19, 0, 0, 19, - 19, 0, 19, 0, 0, 19, 0, 0, - 0, 0, 0, 0, 19, 19, 19, 19, - 0, 19, 19, 19, 19, 19, 19, 19, - 0, 19, 19, 19, 0, 19, 0, 19, - 0, 0, 19, 19, 0, 19, 19, 19, - 19, 1, 19, 19, 1, 1, 1, 1, - 1, 1, 0, 1, 1, 19, 0, 0, - 19, 19, 19, 19, 19, 0, 18, 0, - 1, 1, 1, 1, 1, 1, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 19, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 19, 30, 30, 30, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 30, 30, 30, 30, 30, - 1, 1, 30, 30, 30, 30, 30, 30, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 30, 1, 30, 1, - 30, 1, 22, 23, 22, 23, 2, 2, - 19, 19, 19, 19, 19, 19, 19, 19, - 0, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, - 1, 1, 1, 1, 1, 26, 1, 1, - 19, 19, 19, 19, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 30, 30, - 30, 30, 30, 30, 30, 30, 1, 30, - 30, 30, 30, 30, 30, 0, 0, 30, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 19, 19, 19, 19, 19, - 0, 19, 19, 0, 2, 1, 1, 1, - 1, 2, 1, 0, 0, 0, 1, 1, - 2, 1, 0, 0, 0, 0, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 26, 26, 26, 26, 26, 26, - 19, 19, 19, 19, 19, 19, 2, 2, - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 0, 0, 26, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 0, 0, 0, 0, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 0, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 0, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 0, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 0, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 0, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 0, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 0, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, - 0, 26, 26, 26, 26, 26, 26, 26, - 26, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 26, 26, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 7, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 22, 23, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 26, 26, 26, 5, 5, - 5, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, - 19, 19, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 1, 1, 1, 26, 26, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 19, 19, - 19, 0, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 2, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 26, 26, 26, 18, - 26, 26, 26, 28, 19, 0, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 26, 26, 26, 26, 26, 26, 21, 26, - 26, 26, 26, 1, 1, 1, 11, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 18, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 16, 16, - 16, 16, 16, 16, 0, 0, 15, 0, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 15, 16, 15, 16, 15, 16, - 15, 16, 0, 0, 0, 0, 0, 0, - - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 0, 0, - 15, 15, 15, 15, 15, 15, 0, 0, - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 0, 0, - 15, 15, 15, 15, 15, 15, 0, 0, - 16, 16, 16, 16, 16, 16, 16, 16, - 0, 15, 0, 15, 0, 15, 0, 15, - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 0, 0, - 16, 16, 16, 16, 16, 16, 16, 16, - 17, 17, 17, 17, 17, 17, 17, 17, - 16, 16, 16, 16, 16, 16, 16, 16, - 17, 17, 17, 17, 17, 17, 17, 17, - 16, 16, 16, 16, 16, 16, 16, 16, - 17, 17, 17, 17, 17, 17, 17, 17, - 16, 16, 16, 16, 16, 0, 16, 16, - 15, 15, 15, 15, 17, 29, 16, 29, - 29, 29, 16, 16, 16, 0, 16, 16, - 15, 15, 15, 15, 17, 29, 29, 29, - 16, 16, 16, 16, 0, 0, 16, 16, - 15, 15, 15, 15, 0, 29, 29, 29, - 16, 16, 16, 16, 16, 16, 16, 16, - 15, 15, 15, 15, 15, 29, 29, 29, - 0, 0, 16, 16, 16, 0, 16, 16, - 15, 15, 15, 15, 17, 29, 29, 0, - - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 11, 11, 11, 11, - 21, 21, 21, 21, 21, 21, 26, 26, - 24, 25, 22, 24, 24, 25, 22, 24, - 26, 26, 26, 26, 26, 26, 26, 26, - 8, 9, 11, 11, 11, 11, 11, 7, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 24, 25, 26, 26, 26, 26, 20, - 20, 26, 26, 26, 27, 22, 23, 26, - 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 27, 0, 0, 0, 0, 26, - 0, 0, 0, 0, 0, 0, 0, 7, - 11, 11, 11, 11, 0, 0, 0, 0, - 0, 0, 11, 11, 11, 11, 11, 11, - 6, 16, 0, 0, 6, 6, 6, 6, - 6, 6, 27, 27, 27, 22, 23, 16, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 27, 27, 27, 22, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 3, 3, - 3, 1, 3, 3, 3, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 30, 30, 15, 30, 30, 30, 30, 15, - 30, 30, 16, 15, 15, 15, 16, 16, - 15, 15, 15, 16, 30, 15, 30, 30, - 30, 15, 15, 15, 15, 15, 30, 30, - 30, 30, 30, 30, 15, 30, 15, 30, - 15, 30, 15, 15, 15, 15, 30, 16, - 15, 15, 30, 15, 16, 19, 19, 19, - 19, 16, 30, 0, 0, 16, 15, 15, - 27, 27, 27, 27, 27, 15, 16, 16, - 16, 16, 30, 27, 0, 0, 0, 0, - 0, 0, 0, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 27, 27, 27, 27, 27, 30, 30, 30, - 30, 30, 27, 27, 30, 30, 30, 30, - 27, 30, 30, 27, 30, 30, 27, 30, - 30, 30, 30, 30, 30, 30, 27, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 27, 27, - 30, 30, 27, 30, 27, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - - 30, 30, 30, 30, 30, 30, 30, 30, - 27, 27, 27, 27, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 27, 27, 30, 30, 30, 30, 30, 30, - 30, 22, 23, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 27, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 22, 23, 26, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 0, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 27, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 27, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 27, 27, 27, 27, 27, 27, 27, 27, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 0, 30, 30, - 0, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 27, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 30, 30, 30, 30, 0, 30, 30, - 30, 30, 0, 0, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 0, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 30, 0, 30, - 30, 30, 30, 0, 0, 0, 30, 0, - 30, 30, 30, 30, 30, 30, 30, 0, - 0, 30, 30, 30, 30, 30, 30, 30, - 22, 23, 22, 23, 22, 23, 22, 23, - 22, 23, 22, 23, 22, 23, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 30, 0, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 0, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 22, 23, - 22, 23, 22, 23, 0, 0, 0, 0, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 22, 23, 22, 23, 22, - 23, 22, 23, 22, 23, 22, 23, 22, - 23, 22, 23, 22, 23, 22, 23, 22, - 23, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 22, 23, 22, 23, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 22, 23, 27, 27, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 0, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 0, 0, 0, - - 7, 26, 26, 26, 30, 18, 19, 5, - 22, 23, 22, 23, 22, 23, 22, 23, - 22, 23, 30, 30, 22, 23, 22, 23, - 22, 23, 22, 23, 21, 22, 23, 23, - 30, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 1, 1, 1, 1, 1, 1, - 21, 18, 18, 18, 18, 18, 30, 30, - 5, 5, 5, 18, 19, 26, 30, 30, - 0, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 0, 1, 1, 29, 29, 18, 18, 19, - 21, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 20, 18, 18, 18, 19, - - 0, 0, 0, 0, 0, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 0, - 0, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 30, 30, 6, 6, 6, 6, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 0, 0, 0, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 0, 0, 30, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 0, 0, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - 0, 0, 0, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 0, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 16, 16, 16, 16, 16, 16, 16, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 16, 16, 16, 16, 16, - 0, 0, 0, 0, 0, 19, 1, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 27, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 19, 19, 19, 19, 19, 0, 19, 0, - 19, 19, 0, 19, 19, 0, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 22, 23, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 0, 0, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 28, 0, 0, 0, - - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 26, 21, 21, 20, 20, 22, 23, 22, - 23, 22, 23, 22, 23, 22, 23, 22, - 23, 22, 23, 22, 23, 26, 26, 0, - 0, 26, 26, 26, 26, 20, 20, 20, - 26, 26, 26, 0, 26, 26, 26, 26, - 21, 22, 23, 22, 23, 22, 23, 26, - 26, 26, 27, 21, 27, 27, 27, 0, - 26, 28, 26, 26, 0, 0, 0, 0, - 19, 19, 19, 19, 19, 0, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 0, 0, 11, - - 0, 26, 26, 26, 28, 26, 26, 26, - 22, 23, 26, 27, 26, 21, 26, 26, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 26, 26, 27, 27, 27, 26, - 26, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 22, 26, 23, 29, 20, - 29, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 22, 27, 23, 27, 22, - 23, 26, 22, 23, 26, 20, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 18, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 18, 18, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 0, - 0, 0, 19, 19, 19, 19, 19, 19, - 0, 0, 19, 19, 19, 19, 19, 19, - 0, 0, 19, 19, 19, 19, 19, 19, - 0, 0, 19, 19, 19, 0, 0, 0, - 28, 28, 27, 29, 30, 28, 28, 0, - 30, 27, 27, 27, 27, 30, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 11, 11, 11, 30, 30, 0, 0, -}; - -// 14080 bytes - -const TQ_UINT16 TQUnicodeTables::decomposition_map[] = { - 0, - 3, 0x00A0, 0x0020, 0, - 16, 0x00A8, 0x0020, 0x0308, 0, - 9, 0x00AA, 0x0061, 0, - 16, 0x00AF, 0x0020, 0x0304, 0, - 9, 0x00B2, 0x0032, 0, - 9, 0x00B3, 0x0033, 0, - 16, 0x00B4, 0x0020, 0x0301, 0, - 16, 0x00B5, 0x03BC, 0, - 16, 0x00B8, 0x0020, 0x0327, 0, - 9, 0x00B9, 0x0031, 0, - 9, 0x00BA, 0x006F, 0, - 17, 0x00BC, 0x0031, 0x2044, 0x0034, 0, - 17, 0x00BD, 0x0031, 0x2044, 0x0032, 0, - 17, 0x00BE, 0x0033, 0x2044, 0x0034, 0, - 1, 0x00C0, 0x0041, 0x0300, 0, - 1, 0x00C1, 0x0041, 0x0301, 0, - 1, 0x00C2, 0x0041, 0x0302, 0, - 1, 0x00C3, 0x0041, 0x0303, 0, - 1, 0x00C4, 0x0041, 0x0308, 0, - 1, 0x00C5, 0x0041, 0x030A, 0, - 1, 0x00C7, 0x0043, 0x0327, 0, - 1, 0x00C8, 0x0045, 0x0300, 0, - 1, 0x00C9, 0x0045, 0x0301, 0, - 1, 0x00CA, 0x0045, 0x0302, 0, - 1, 0x00CB, 0x0045, 0x0308, 0, - 1, 0x00CC, 0x0049, 0x0300, 0, - 1, 0x00CD, 0x0049, 0x0301, 0, - 1, 0x00CE, 0x0049, 0x0302, 0, - 1, 0x00CF, 0x0049, 0x0308, 0, - 1, 0x00D1, 0x004E, 0x0303, 0, - 1, 0x00D2, 0x004F, 0x0300, 0, - 1, 0x00D3, 0x004F, 0x0301, 0, - 1, 0x00D4, 0x004F, 0x0302, 0, - 1, 0x00D5, 0x004F, 0x0303, 0, - 1, 0x00D6, 0x004F, 0x0308, 0, - 1, 0x00D9, 0x0055, 0x0300, 0, - 1, 0x00DA, 0x0055, 0x0301, 0, - 1, 0x00DB, 0x0055, 0x0302, 0, - 1, 0x00DC, 0x0055, 0x0308, 0, - 1, 0x00DD, 0x0059, 0x0301, 0, - 1, 0x00E0, 0x0061, 0x0300, 0, - 1, 0x00E1, 0x0061, 0x0301, 0, - 1, 0x00E2, 0x0061, 0x0302, 0, - 1, 0x00E3, 0x0061, 0x0303, 0, - 1, 0x00E4, 0x0061, 0x0308, 0, - 1, 0x00E5, 0x0061, 0x030A, 0, - 1, 0x00E7, 0x0063, 0x0327, 0, - 1, 0x00E8, 0x0065, 0x0300, 0, - 1, 0x00E9, 0x0065, 0x0301, 0, - 1, 0x00EA, 0x0065, 0x0302, 0, - 1, 0x00EB, 0x0065, 0x0308, 0, - 1, 0x00EC, 0x0069, 0x0300, 0, - 1, 0x00ED, 0x0069, 0x0301, 0, - 1, 0x00EE, 0x0069, 0x0302, 0, - 1, 0x00EF, 0x0069, 0x0308, 0, - 1, 0x00F1, 0x006E, 0x0303, 0, - 1, 0x00F2, 0x006F, 0x0300, 0, - 1, 0x00F3, 0x006F, 0x0301, 0, - 1, 0x00F4, 0x006F, 0x0302, 0, - 1, 0x00F5, 0x006F, 0x0303, 0, - 1, 0x00F6, 0x006F, 0x0308, 0, - 1, 0x00F9, 0x0075, 0x0300, 0, - 1, 0x00FA, 0x0075, 0x0301, 0, - 1, 0x00FB, 0x0075, 0x0302, 0, - 1, 0x00FC, 0x0075, 0x0308, 0, - 1, 0x00FD, 0x0079, 0x0301, 0, - 1, 0x00FF, 0x0079, 0x0308, 0, - 1, 0x0100, 0x0041, 0x0304, 0, - 1, 0x0101, 0x0061, 0x0304, 0, - 1, 0x0102, 0x0041, 0x0306, 0, - 1, 0x0103, 0x0061, 0x0306, 0, - 1, 0x0104, 0x0041, 0x0328, 0, - 1, 0x0105, 0x0061, 0x0328, 0, - 1, 0x0106, 0x0043, 0x0301, 0, - 1, 0x0107, 0x0063, 0x0301, 0, - 1, 0x0108, 0x0043, 0x0302, 0, - 1, 0x0109, 0x0063, 0x0302, 0, - 1, 0x010A, 0x0043, 0x0307, 0, - 1, 0x010B, 0x0063, 0x0307, 0, - 1, 0x010C, 0x0043, 0x030C, 0, - 1, 0x010D, 0x0063, 0x030C, 0, - 1, 0x010E, 0x0044, 0x030C, 0, - 1, 0x010F, 0x0064, 0x030C, 0, - 1, 0x0112, 0x0045, 0x0304, 0, - 1, 0x0113, 0x0065, 0x0304, 0, - 1, 0x0114, 0x0045, 0x0306, 0, - 1, 0x0115, 0x0065, 0x0306, 0, - 1, 0x0116, 0x0045, 0x0307, 0, - 1, 0x0117, 0x0065, 0x0307, 0, - 1, 0x0118, 0x0045, 0x0328, 0, - 1, 0x0119, 0x0065, 0x0328, 0, - 1, 0x011A, 0x0045, 0x030C, 0, - 1, 0x011B, 0x0065, 0x030C, 0, - 1, 0x011C, 0x0047, 0x0302, 0, - 1, 0x011D, 0x0067, 0x0302, 0, - 1, 0x011E, 0x0047, 0x0306, 0, - 1, 0x011F, 0x0067, 0x0306, 0, - 1, 0x0120, 0x0047, 0x0307, 0, - 1, 0x0121, 0x0067, 0x0307, 0, - 1, 0x0122, 0x0047, 0x0327, 0, - 1, 0x0123, 0x0067, 0x0327, 0, - 1, 0x0124, 0x0048, 0x0302, 0, - 1, 0x0125, 0x0068, 0x0302, 0, - 1, 0x0128, 0x0049, 0x0303, 0, - 1, 0x0129, 0x0069, 0x0303, 0, - 1, 0x012A, 0x0049, 0x0304, 0, - 1, 0x012B, 0x0069, 0x0304, 0, - 1, 0x012C, 0x0049, 0x0306, 0, - 1, 0x012D, 0x0069, 0x0306, 0, - 1, 0x012E, 0x0049, 0x0328, 0, - 1, 0x012F, 0x0069, 0x0328, 0, - 1, 0x0130, 0x0049, 0x0307, 0, - 16, 0x0132, 0x0049, 0x004A, 0, - 16, 0x0133, 0x0069, 0x006A, 0, - 1, 0x0134, 0x004A, 0x0302, 0, - 1, 0x0135, 0x006A, 0x0302, 0, - 1, 0x0136, 0x004B, 0x0327, 0, - 1, 0x0137, 0x006B, 0x0327, 0, - 1, 0x0139, 0x004C, 0x0301, 0, - 1, 0x013A, 0x006C, 0x0301, 0, - 1, 0x013B, 0x004C, 0x0327, 0, - 1, 0x013C, 0x006C, 0x0327, 0, - 1, 0x013D, 0x004C, 0x030C, 0, - 1, 0x013E, 0x006C, 0x030C, 0, - 16, 0x013F, 0x004C, 0x00B7, 0, - 16, 0x0140, 0x006C, 0x00B7, 0, - 1, 0x0143, 0x004E, 0x0301, 0, - 1, 0x0144, 0x006E, 0x0301, 0, - 1, 0x0145, 0x004E, 0x0327, 0, - 1, 0x0146, 0x006E, 0x0327, 0, - 1, 0x0147, 0x004E, 0x030C, 0, - 1, 0x0148, 0x006E, 0x030C, 0, - 16, 0x0149, 0x02BC, 0x006E, 0, - 1, 0x014C, 0x004F, 0x0304, 0, - 1, 0x014D, 0x006F, 0x0304, 0, - 1, 0x014E, 0x004F, 0x0306, 0, - 1, 0x014F, 0x006F, 0x0306, 0, - 1, 0x0150, 0x004F, 0x030B, 0, - 1, 0x0151, 0x006F, 0x030B, 0, - 1, 0x0154, 0x0052, 0x0301, 0, - 1, 0x0155, 0x0072, 0x0301, 0, - 1, 0x0156, 0x0052, 0x0327, 0, - 1, 0x0157, 0x0072, 0x0327, 0, - 1, 0x0158, 0x0052, 0x030C, 0, - 1, 0x0159, 0x0072, 0x030C, 0, - 1, 0x015A, 0x0053, 0x0301, 0, - 1, 0x015B, 0x0073, 0x0301, 0, - 1, 0x015C, 0x0053, 0x0302, 0, - 1, 0x015D, 0x0073, 0x0302, 0, - 1, 0x015E, 0x0053, 0x0327, 0, - 1, 0x015F, 0x0073, 0x0327, 0, - 1, 0x0160, 0x0053, 0x030C, 0, - 1, 0x0161, 0x0073, 0x030C, 0, - 1, 0x0162, 0x0054, 0x0327, 0, - 1, 0x0163, 0x0074, 0x0327, 0, - 1, 0x0164, 0x0054, 0x030C, 0, - 1, 0x0165, 0x0074, 0x030C, 0, - 1, 0x0168, 0x0055, 0x0303, 0, - 1, 0x0169, 0x0075, 0x0303, 0, - 1, 0x016A, 0x0055, 0x0304, 0, - 1, 0x016B, 0x0075, 0x0304, 0, - 1, 0x016C, 0x0055, 0x0306, 0, - 1, 0x016D, 0x0075, 0x0306, 0, - 1, 0x016E, 0x0055, 0x030A, 0, - 1, 0x016F, 0x0075, 0x030A, 0, - 1, 0x0170, 0x0055, 0x030B, 0, - 1, 0x0171, 0x0075, 0x030B, 0, - 1, 0x0172, 0x0055, 0x0328, 0, - 1, 0x0173, 0x0075, 0x0328, 0, - 1, 0x0174, 0x0057, 0x0302, 0, - 1, 0x0175, 0x0077, 0x0302, 0, - 1, 0x0176, 0x0059, 0x0302, 0, - 1, 0x0177, 0x0079, 0x0302, 0, - 1, 0x0178, 0x0059, 0x0308, 0, - 1, 0x0179, 0x005A, 0x0301, 0, - 1, 0x017A, 0x007A, 0x0301, 0, - 1, 0x017B, 0x005A, 0x0307, 0, - 1, 0x017C, 0x007A, 0x0307, 0, - 1, 0x017D, 0x005A, 0x030C, 0, - 1, 0x017E, 0x007A, 0x030C, 0, - 16, 0x017F, 0x0073, 0, - 1, 0x01A0, 0x004F, 0x031B, 0, - 1, 0x01A1, 0x006F, 0x031B, 0, - 1, 0x01AF, 0x0055, 0x031B, 0, - 1, 0x01B0, 0x0075, 0x031B, 0, - 16, 0x01C4, 0x0044, 0x017D, 0, - 16, 0x01C5, 0x0044, 0x017E, 0, - 16, 0x01C6, 0x0064, 0x017E, 0, - 16, 0x01C7, 0x004C, 0x004A, 0, - 16, 0x01C8, 0x004C, 0x006A, 0, - 16, 0x01C9, 0x006C, 0x006A, 0, - 16, 0x01CA, 0x004E, 0x004A, 0, - 16, 0x01CB, 0x004E, 0x006A, 0, - 16, 0x01CC, 0x006E, 0x006A, 0, - 1, 0x01CD, 0x0041, 0x030C, 0, - 1, 0x01CE, 0x0061, 0x030C, 0, - 1, 0x01CF, 0x0049, 0x030C, 0, - 1, 0x01D0, 0x0069, 0x030C, 0, - 1, 0x01D1, 0x004F, 0x030C, 0, - 1, 0x01D2, 0x006F, 0x030C, 0, - 1, 0x01D3, 0x0055, 0x030C, 0, - 1, 0x01D4, 0x0075, 0x030C, 0, - 1, 0x01D5, 0x00DC, 0x0304, 0, - 1, 0x01D6, 0x00FC, 0x0304, 0, - 1, 0x01D7, 0x00DC, 0x0301, 0, - 1, 0x01D8, 0x00FC, 0x0301, 0, - 1, 0x01D9, 0x00DC, 0x030C, 0, - 1, 0x01DA, 0x00FC, 0x030C, 0, - 1, 0x01DB, 0x00DC, 0x0300, 0, - 1, 0x01DC, 0x00FC, 0x0300, 0, - 1, 0x01DE, 0x00C4, 0x0304, 0, - 1, 0x01DF, 0x00E4, 0x0304, 0, - 1, 0x01E0, 0x0226, 0x0304, 0, - 1, 0x01E1, 0x0227, 0x0304, 0, - 1, 0x01E2, 0x00C6, 0x0304, 0, - 1, 0x01E3, 0x00E6, 0x0304, 0, - 1, 0x01E6, 0x0047, 0x030C, 0, - 1, 0x01E7, 0x0067, 0x030C, 0, - 1, 0x01E8, 0x004B, 0x030C, 0, - 1, 0x01E9, 0x006B, 0x030C, 0, - 1, 0x01EA, 0x004F, 0x0328, 0, - 1, 0x01EB, 0x006F, 0x0328, 0, - 1, 0x01EC, 0x01EA, 0x0304, 0, - 1, 0x01ED, 0x01EB, 0x0304, 0, - 1, 0x01EE, 0x01B7, 0x030C, 0, - 1, 0x01EF, 0x0292, 0x030C, 0, - 1, 0x01F0, 0x006A, 0x030C, 0, - 16, 0x01F1, 0x0044, 0x005A, 0, - 16, 0x01F2, 0x0044, 0x007A, 0, - 16, 0x01F3, 0x0064, 0x007A, 0, - 1, 0x01F4, 0x0047, 0x0301, 0, - 1, 0x01F5, 0x0067, 0x0301, 0, - 1, 0x01F8, 0x004E, 0x0300, 0, - 1, 0x01F9, 0x006E, 0x0300, 0, - 1, 0x01FA, 0x00C5, 0x0301, 0, - 1, 0x01FB, 0x00E5, 0x0301, 0, - 1, 0x01FC, 0x00C6, 0x0301, 0, - 1, 0x01FD, 0x00E6, 0x0301, 0, - 1, 0x01FE, 0x00D8, 0x0301, 0, - 1, 0x01FF, 0x00F8, 0x0301, 0, - 1, 0x0200, 0x0041, 0x030F, 0, - 1, 0x0201, 0x0061, 0x030F, 0, - 1, 0x0202, 0x0041, 0x0311, 0, - 1, 0x0203, 0x0061, 0x0311, 0, - 1, 0x0204, 0x0045, 0x030F, 0, - 1, 0x0205, 0x0065, 0x030F, 0, - 1, 0x0206, 0x0045, 0x0311, 0, - 1, 0x0207, 0x0065, 0x0311, 0, - 1, 0x0208, 0x0049, 0x030F, 0, - 1, 0x0209, 0x0069, 0x030F, 0, - 1, 0x020A, 0x0049, 0x0311, 0, - 1, 0x020B, 0x0069, 0x0311, 0, - 1, 0x020C, 0x004F, 0x030F, 0, - 1, 0x020D, 0x006F, 0x030F, 0, - 1, 0x020E, 0x004F, 0x0311, 0, - 1, 0x020F, 0x006F, 0x0311, 0, - 1, 0x0210, 0x0052, 0x030F, 0, - 1, 0x0211, 0x0072, 0x030F, 0, - 1, 0x0212, 0x0052, 0x0311, 0, - 1, 0x0213, 0x0072, 0x0311, 0, - 1, 0x0214, 0x0055, 0x030F, 0, - 1, 0x0215, 0x0075, 0x030F, 0, - 1, 0x0216, 0x0055, 0x0311, 0, - 1, 0x0217, 0x0075, 0x0311, 0, - 1, 0x0218, 0x0053, 0x0326, 0, - 1, 0x0219, 0x0073, 0x0326, 0, - 1, 0x021A, 0x0054, 0x0326, 0, - 1, 0x021B, 0x0074, 0x0326, 0, - 1, 0x021E, 0x0048, 0x030C, 0, - 1, 0x021F, 0x0068, 0x030C, 0, - 1, 0x0226, 0x0041, 0x0307, 0, - 1, 0x0227, 0x0061, 0x0307, 0, - 1, 0x0228, 0x0045, 0x0327, 0, - 1, 0x0229, 0x0065, 0x0327, 0, - 1, 0x022A, 0x00D6, 0x0304, 0, - 1, 0x022B, 0x00F6, 0x0304, 0, - 1, 0x022C, 0x00D5, 0x0304, 0, - 1, 0x022D, 0x00F5, 0x0304, 0, - 1, 0x022E, 0x004F, 0x0307, 0, - 1, 0x022F, 0x006F, 0x0307, 0, - 1, 0x0230, 0x022E, 0x0304, 0, - 1, 0x0231, 0x022F, 0x0304, 0, - 1, 0x0232, 0x0059, 0x0304, 0, - 1, 0x0233, 0x0079, 0x0304, 0, - 9, 0x02B0, 0x0068, 0, - 9, 0x02B1, 0x0266, 0, - 9, 0x02B2, 0x006A, 0, - 9, 0x02B3, 0x0072, 0, - 9, 0x02B4, 0x0279, 0, - 9, 0x02B5, 0x027B, 0, - 9, 0x02B6, 0x0281, 0, - 9, 0x02B7, 0x0077, 0, - 9, 0x02B8, 0x0079, 0, - 16, 0x02D8, 0x0020, 0x0306, 0, - 16, 0x02D9, 0x0020, 0x0307, 0, - 16, 0x02DA, 0x0020, 0x030A, 0, - 16, 0x02DB, 0x0020, 0x0328, 0, - 16, 0x02DC, 0x0020, 0x0303, 0, - 16, 0x02DD, 0x0020, 0x030B, 0, - 9, 0x02E0, 0x0263, 0, - 9, 0x02E1, 0x006C, 0, - 9, 0x02E2, 0x0073, 0, - 9, 0x02E3, 0x0078, 0, - 9, 0x02E4, 0x0295, 0, - 1, 0x0340, 0x0300, 0, - 1, 0x0341, 0x0301, 0, - 1, 0x0343, 0x0313, 0, - 1, 0x0344, 0x0308, 0x0301, 0, - 1, 0x0374, 0x02B9, 0, - 16, 0x037A, 0x0020, 0x0345, 0, - 1, 0x037E, 0x003B, 0, - 16, 0x0384, 0x0020, 0x0301, 0, - 1, 0x0385, 0x00A8, 0x0301, 0, - 1, 0x0386, 0x0391, 0x0301, 0, - 1, 0x0387, 0x00B7, 0, - 1, 0x0388, 0x0395, 0x0301, 0, - 1, 0x0389, 0x0397, 0x0301, 0, - 1, 0x038A, 0x0399, 0x0301, 0, - 1, 0x038C, 0x039F, 0x0301, 0, - 1, 0x038E, 0x03A5, 0x0301, 0, - 1, 0x038F, 0x03A9, 0x0301, 0, - 1, 0x0390, 0x03CA, 0x0301, 0, - 1, 0x03AA, 0x0399, 0x0308, 0, - 1, 0x03AB, 0x03A5, 0x0308, 0, - 1, 0x03AC, 0x03B1, 0x0301, 0, - 1, 0x03AD, 0x03B5, 0x0301, 0, - 1, 0x03AE, 0x03B7, 0x0301, 0, - 1, 0x03AF, 0x03B9, 0x0301, 0, - 1, 0x03B0, 0x03CB, 0x0301, 0, - 1, 0x03CA, 0x03B9, 0x0308, 0, - 1, 0x03CB, 0x03C5, 0x0308, 0, - 1, 0x03CC, 0x03BF, 0x0301, 0, - 1, 0x03CD, 0x03C5, 0x0301, 0, - 1, 0x03CE, 0x03C9, 0x0301, 0, - 16, 0x03D0, 0x03B2, 0, - 16, 0x03D1, 0x03B8, 0, - 16, 0x03D2, 0x03A5, 0, - 1, 0x03D3, 0x03D2, 0x0301, 0, - 1, 0x03D4, 0x03D2, 0x0308, 0, - 16, 0x03D5, 0x03C6, 0, - 16, 0x03D6, 0x03C0, 0, - 16, 0x03F0, 0x03BA, 0, - 16, 0x03F1, 0x03C1, 0, - 16, 0x03F4, 0x0398, 0, - 16, 0x03F5, 0x03B5, 0, - 1, 0x0400, 0x0415, 0x0300, 0, - 1, 0x0401, 0x0415, 0x0308, 0, - 1, 0x0403, 0x0413, 0x0301, 0, - 1, 0x0407, 0x0406, 0x0308, 0, - 1, 0x040C, 0x041A, 0x0301, 0, - 1, 0x040D, 0x0418, 0x0300, 0, - 1, 0x040E, 0x0423, 0x0306, 0, - 1, 0x0419, 0x0418, 0x0306, 0, - 1, 0x0439, 0x0438, 0x0306, 0, - 1, 0x0450, 0x0435, 0x0300, 0, - 1, 0x0451, 0x0435, 0x0308, 0, - 1, 0x0453, 0x0433, 0x0301, 0, - 1, 0x0457, 0x0456, 0x0308, 0, - 1, 0x045C, 0x043A, 0x0301, 0, - 1, 0x045D, 0x0438, 0x0300, 0, - 1, 0x045E, 0x0443, 0x0306, 0, - 1, 0x0476, 0x0474, 0x030F, 0, - 1, 0x0477, 0x0475, 0x030F, 0, - 1, 0x04C1, 0x0416, 0x0306, 0, - 1, 0x04C2, 0x0436, 0x0306, 0, - 1, 0x04D0, 0x0410, 0x0306, 0, - 1, 0x04D1, 0x0430, 0x0306, 0, - 1, 0x04D2, 0x0410, 0x0308, 0, - 1, 0x04D3, 0x0430, 0x0308, 0, - 1, 0x04D6, 0x0415, 0x0306, 0, - 1, 0x04D7, 0x0435, 0x0306, 0, - 1, 0x04DA, 0x04D8, 0x0308, 0, - 1, 0x04DB, 0x04D9, 0x0308, 0, - 1, 0x04DC, 0x0416, 0x0308, 0, - 1, 0x04DD, 0x0436, 0x0308, 0, - 1, 0x04DE, 0x0417, 0x0308, 0, - 1, 0x04DF, 0x0437, 0x0308, 0, - 1, 0x04E2, 0x0418, 0x0304, 0, - 1, 0x04E3, 0x0438, 0x0304, 0, - 1, 0x04E4, 0x0418, 0x0308, 0, - 1, 0x04E5, 0x0438, 0x0308, 0, - 1, 0x04E6, 0x041E, 0x0308, 0, - 1, 0x04E7, 0x043E, 0x0308, 0, - 1, 0x04EA, 0x04E8, 0x0308, 0, - 1, 0x04EB, 0x04E9, 0x0308, 0, - 1, 0x04EC, 0x042D, 0x0308, 0, - 1, 0x04ED, 0x044D, 0x0308, 0, - 1, 0x04EE, 0x0423, 0x0304, 0, - 1, 0x04EF, 0x0443, 0x0304, 0, - 1, 0x04F0, 0x0423, 0x0308, 0, - 1, 0x04F1, 0x0443, 0x0308, 0, - 1, 0x04F2, 0x0423, 0x030B, 0, - 1, 0x04F3, 0x0443, 0x030B, 0, - 1, 0x04F4, 0x0427, 0x0308, 0, - 1, 0x04F5, 0x0447, 0x0308, 0, - 1, 0x04F8, 0x042B, 0x0308, 0, - 1, 0x04F9, 0x044B, 0x0308, 0, - 16, 0x0587, 0x0565, 0x0582, 0, - 1, 0x0622, 0x0627, 0x0653, 0, - 1, 0x0623, 0x0627, 0x0654, 0, - 1, 0x0624, 0x0648, 0x0654, 0, - 1, 0x0625, 0x0627, 0x0655, 0, - 1, 0x0626, 0x064A, 0x0654, 0, - 16, 0x0675, 0x0627, 0x0674, 0, - 16, 0x0676, 0x0648, 0x0674, 0, - 16, 0x0677, 0x06C7, 0x0674, 0, - 16, 0x0678, 0x064A, 0x0674, 0, - 1, 0x06C0, 0x06D5, 0x0654, 0, - 1, 0x06C2, 0x06C1, 0x0654, 0, - 1, 0x06D3, 0x06D2, 0x0654, 0, - 1, 0x0929, 0x0928, 0x093C, 0, - 1, 0x0931, 0x0930, 0x093C, 0, - 1, 0x0934, 0x0933, 0x093C, 0, - 1, 0x0958, 0x0915, 0x093C, 0, - 1, 0x0959, 0x0916, 0x093C, 0, - 1, 0x095A, 0x0917, 0x093C, 0, - 1, 0x095B, 0x091C, 0x093C, 0, - 1, 0x095C, 0x0921, 0x093C, 0, - 1, 0x095D, 0x0922, 0x093C, 0, - 1, 0x095E, 0x092B, 0x093C, 0, - 1, 0x095F, 0x092F, 0x093C, 0, - 1, 0x09CB, 0x09C7, 0x09BE, 0, - 1, 0x09CC, 0x09C7, 0x09D7, 0, - 1, 0x09DC, 0x09A1, 0x09BC, 0, - 1, 0x09DD, 0x09A2, 0x09BC, 0, - 1, 0x09DF, 0x09AF, 0x09BC, 0, - 1, 0x0A33, 0x0A32, 0x0A3C, 0, - 1, 0x0A36, 0x0A38, 0x0A3C, 0, - 1, 0x0A59, 0x0A16, 0x0A3C, 0, - 1, 0x0A5A, 0x0A17, 0x0A3C, 0, - 1, 0x0A5B, 0x0A1C, 0x0A3C, 0, - 1, 0x0A5E, 0x0A2B, 0x0A3C, 0, - 1, 0x0B48, 0x0B47, 0x0B56, 0, - 1, 0x0B4B, 0x0B47, 0x0B3E, 0, - 1, 0x0B4C, 0x0B47, 0x0B57, 0, - 1, 0x0B5C, 0x0B21, 0x0B3C, 0, - 1, 0x0B5D, 0x0B22, 0x0B3C, 0, - 1, 0x0B94, 0x0B92, 0x0BD7, 0, - 1, 0x0BCA, 0x0BC6, 0x0BBE, 0, - 1, 0x0BCB, 0x0BC7, 0x0BBE, 0, - 1, 0x0BCC, 0x0BC6, 0x0BD7, 0, - 1, 0x0C48, 0x0C46, 0x0C56, 0, - 1, 0x0CC0, 0x0CBF, 0x0CD5, 0, - 1, 0x0CC7, 0x0CC6, 0x0CD5, 0, - 1, 0x0CC8, 0x0CC6, 0x0CD6, 0, - 1, 0x0CCA, 0x0CC6, 0x0CC2, 0, - 1, 0x0CCB, 0x0CCA, 0x0CD5, 0, - 1, 0x0D4A, 0x0D46, 0x0D3E, 0, - 1, 0x0D4B, 0x0D47, 0x0D3E, 0, - 1, 0x0D4C, 0x0D46, 0x0D57, 0, - 1, 0x0DDA, 0x0DD9, 0x0DCA, 0, - 1, 0x0DDC, 0x0DD9, 0x0DCF, 0, - 1, 0x0DDD, 0x0DDC, 0x0DCA, 0, - 1, 0x0DDE, 0x0DD9, 0x0DDF, 0, - 16, 0x0E33, 0x0E4D, 0x0E32, 0, - 16, 0x0EB3, 0x0ECD, 0x0EB2, 0, - 16, 0x0EDC, 0x0EAB, 0x0E99, 0, - 16, 0x0EDD, 0x0EAB, 0x0EA1, 0, - 3, 0x0F0C, 0x0F0B, 0, - 1, 0x0F43, 0x0F42, 0x0FB7, 0, - 1, 0x0F4D, 0x0F4C, 0x0FB7, 0, - 1, 0x0F52, 0x0F51, 0x0FB7, 0, - 1, 0x0F57, 0x0F56, 0x0FB7, 0, - 1, 0x0F5C, 0x0F5B, 0x0FB7, 0, - 1, 0x0F69, 0x0F40, 0x0FB5, 0, - 1, 0x0F73, 0x0F71, 0x0F72, 0, - 1, 0x0F75, 0x0F71, 0x0F74, 0, - 1, 0x0F76, 0x0FB2, 0x0F80, 0, - 16, 0x0F77, 0x0FB2, 0x0F81, 0, - 1, 0x0F78, 0x0FB3, 0x0F80, 0, - 16, 0x0F79, 0x0FB3, 0x0F81, 0, - 1, 0x0F81, 0x0F71, 0x0F80, 0, - 1, 0x0F93, 0x0F92, 0x0FB7, 0, - 1, 0x0F9D, 0x0F9C, 0x0FB7, 0, - 1, 0x0FA2, 0x0FA1, 0x0FB7, 0, - 1, 0x0FA7, 0x0FA6, 0x0FB7, 0, - 1, 0x0FAC, 0x0FAB, 0x0FB7, 0, - 1, 0x0FB9, 0x0F90, 0x0FB5, 0, - 1, 0x1026, 0x1025, 0x102E, 0, - 1, 0x1E00, 0x0041, 0x0325, 0, - 1, 0x1E01, 0x0061, 0x0325, 0, - 1, 0x1E02, 0x0042, 0x0307, 0, - 1, 0x1E03, 0x0062, 0x0307, 0, - 1, 0x1E04, 0x0042, 0x0323, 0, - 1, 0x1E05, 0x0062, 0x0323, 0, - 1, 0x1E06, 0x0042, 0x0331, 0, - 1, 0x1E07, 0x0062, 0x0331, 0, - 1, 0x1E08, 0x00C7, 0x0301, 0, - 1, 0x1E09, 0x00E7, 0x0301, 0, - 1, 0x1E0A, 0x0044, 0x0307, 0, - 1, 0x1E0B, 0x0064, 0x0307, 0, - 1, 0x1E0C, 0x0044, 0x0323, 0, - 1, 0x1E0D, 0x0064, 0x0323, 0, - 1, 0x1E0E, 0x0044, 0x0331, 0, - 1, 0x1E0F, 0x0064, 0x0331, 0, - 1, 0x1E10, 0x0044, 0x0327, 0, - 1, 0x1E11, 0x0064, 0x0327, 0, - 1, 0x1E12, 0x0044, 0x032D, 0, - 1, 0x1E13, 0x0064, 0x032D, 0, - 1, 0x1E14, 0x0112, 0x0300, 0, - 1, 0x1E15, 0x0113, 0x0300, 0, - 1, 0x1E16, 0x0112, 0x0301, 0, - 1, 0x1E17, 0x0113, 0x0301, 0, - 1, 0x1E18, 0x0045, 0x032D, 0, - 1, 0x1E19, 0x0065, 0x032D, 0, - 1, 0x1E1A, 0x0045, 0x0330, 0, - 1, 0x1E1B, 0x0065, 0x0330, 0, - 1, 0x1E1C, 0x0228, 0x0306, 0, - 1, 0x1E1D, 0x0229, 0x0306, 0, - 1, 0x1E1E, 0x0046, 0x0307, 0, - 1, 0x1E1F, 0x0066, 0x0307, 0, - 1, 0x1E20, 0x0047, 0x0304, 0, - 1, 0x1E21, 0x0067, 0x0304, 0, - 1, 0x1E22, 0x0048, 0x0307, 0, - 1, 0x1E23, 0x0068, 0x0307, 0, - 1, 0x1E24, 0x0048, 0x0323, 0, - 1, 0x1E25, 0x0068, 0x0323, 0, - 1, 0x1E26, 0x0048, 0x0308, 0, - 1, 0x1E27, 0x0068, 0x0308, 0, - 1, 0x1E28, 0x0048, 0x0327, 0, - 1, 0x1E29, 0x0068, 0x0327, 0, - 1, 0x1E2A, 0x0048, 0x032E, 0, - 1, 0x1E2B, 0x0068, 0x032E, 0, - 1, 0x1E2C, 0x0049, 0x0330, 0, - 1, 0x1E2D, 0x0069, 0x0330, 0, - 1, 0x1E2E, 0x00CF, 0x0301, 0, - 1, 0x1E2F, 0x00EF, 0x0301, 0, - 1, 0x1E30, 0x004B, 0x0301, 0, - 1, 0x1E31, 0x006B, 0x0301, 0, - 1, 0x1E32, 0x004B, 0x0323, 0, - 1, 0x1E33, 0x006B, 0x0323, 0, - 1, 0x1E34, 0x004B, 0x0331, 0, - 1, 0x1E35, 0x006B, 0x0331, 0, - 1, 0x1E36, 0x004C, 0x0323, 0, - 1, 0x1E37, 0x006C, 0x0323, 0, - 1, 0x1E38, 0x1E36, 0x0304, 0, - 1, 0x1E39, 0x1E37, 0x0304, 0, - 1, 0x1E3A, 0x004C, 0x0331, 0, - 1, 0x1E3B, 0x006C, 0x0331, 0, - 1, 0x1E3C, 0x004C, 0x032D, 0, - 1, 0x1E3D, 0x006C, 0x032D, 0, - 1, 0x1E3E, 0x004D, 0x0301, 0, - 1, 0x1E3F, 0x006D, 0x0301, 0, - 1, 0x1E40, 0x004D, 0x0307, 0, - 1, 0x1E41, 0x006D, 0x0307, 0, - 1, 0x1E42, 0x004D, 0x0323, 0, - 1, 0x1E43, 0x006D, 0x0323, 0, - 1, 0x1E44, 0x004E, 0x0307, 0, - 1, 0x1E45, 0x006E, 0x0307, 0, - 1, 0x1E46, 0x004E, 0x0323, 0, - 1, 0x1E47, 0x006E, 0x0323, 0, - 1, 0x1E48, 0x004E, 0x0331, 0, - 1, 0x1E49, 0x006E, 0x0331, 0, - 1, 0x1E4A, 0x004E, 0x032D, 0, - 1, 0x1E4B, 0x006E, 0x032D, 0, - 1, 0x1E4C, 0x00D5, 0x0301, 0, - 1, 0x1E4D, 0x00F5, 0x0301, 0, - 1, 0x1E4E, 0x00D5, 0x0308, 0, - 1, 0x1E4F, 0x00F5, 0x0308, 0, - 1, 0x1E50, 0x014C, 0x0300, 0, - 1, 0x1E51, 0x014D, 0x0300, 0, - 1, 0x1E52, 0x014C, 0x0301, 0, - 1, 0x1E53, 0x014D, 0x0301, 0, - 1, 0x1E54, 0x0050, 0x0301, 0, - 1, 0x1E55, 0x0070, 0x0301, 0, - 1, 0x1E56, 0x0050, 0x0307, 0, - 1, 0x1E57, 0x0070, 0x0307, 0, - 1, 0x1E58, 0x0052, 0x0307, 0, - 1, 0x1E59, 0x0072, 0x0307, 0, - 1, 0x1E5A, 0x0052, 0x0323, 0, - 1, 0x1E5B, 0x0072, 0x0323, 0, - 1, 0x1E5C, 0x1E5A, 0x0304, 0, - 1, 0x1E5D, 0x1E5B, 0x0304, 0, - 1, 0x1E5E, 0x0052, 0x0331, 0, - 1, 0x1E5F, 0x0072, 0x0331, 0, - 1, 0x1E60, 0x0053, 0x0307, 0, - 1, 0x1E61, 0x0073, 0x0307, 0, - 1, 0x1E62, 0x0053, 0x0323, 0, - 1, 0x1E63, 0x0073, 0x0323, 0, - 1, 0x1E64, 0x015A, 0x0307, 0, - 1, 0x1E65, 0x015B, 0x0307, 0, - 1, 0x1E66, 0x0160, 0x0307, 0, - 1, 0x1E67, 0x0161, 0x0307, 0, - 1, 0x1E68, 0x1E62, 0x0307, 0, - 1, 0x1E69, 0x1E63, 0x0307, 0, - 1, 0x1E6A, 0x0054, 0x0307, 0, - 1, 0x1E6B, 0x0074, 0x0307, 0, - 1, 0x1E6C, 0x0054, 0x0323, 0, - 1, 0x1E6D, 0x0074, 0x0323, 0, - 1, 0x1E6E, 0x0054, 0x0331, 0, - 1, 0x1E6F, 0x0074, 0x0331, 0, - 1, 0x1E70, 0x0054, 0x032D, 0, - 1, 0x1E71, 0x0074, 0x032D, 0, - 1, 0x1E72, 0x0055, 0x0324, 0, - 1, 0x1E73, 0x0075, 0x0324, 0, - 1, 0x1E74, 0x0055, 0x0330, 0, - 1, 0x1E75, 0x0075, 0x0330, 0, - 1, 0x1E76, 0x0055, 0x032D, 0, - 1, 0x1E77, 0x0075, 0x032D, 0, - 1, 0x1E78, 0x0168, 0x0301, 0, - 1, 0x1E79, 0x0169, 0x0301, 0, - 1, 0x1E7A, 0x016A, 0x0308, 0, - 1, 0x1E7B, 0x016B, 0x0308, 0, - 1, 0x1E7C, 0x0056, 0x0303, 0, - 1, 0x1E7D, 0x0076, 0x0303, 0, - 1, 0x1E7E, 0x0056, 0x0323, 0, - 1, 0x1E7F, 0x0076, 0x0323, 0, - 1, 0x1E80, 0x0057, 0x0300, 0, - 1, 0x1E81, 0x0077, 0x0300, 0, - 1, 0x1E82, 0x0057, 0x0301, 0, - 1, 0x1E83, 0x0077, 0x0301, 0, - 1, 0x1E84, 0x0057, 0x0308, 0, - 1, 0x1E85, 0x0077, 0x0308, 0, - 1, 0x1E86, 0x0057, 0x0307, 0, - 1, 0x1E87, 0x0077, 0x0307, 0, - 1, 0x1E88, 0x0057, 0x0323, 0, - 1, 0x1E89, 0x0077, 0x0323, 0, - 1, 0x1E8A, 0x0058, 0x0307, 0, - 1, 0x1E8B, 0x0078, 0x0307, 0, - 1, 0x1E8C, 0x0058, 0x0308, 0, - 1, 0x1E8D, 0x0078, 0x0308, 0, - 1, 0x1E8E, 0x0059, 0x0307, 0, - 1, 0x1E8F, 0x0079, 0x0307, 0, - 1, 0x1E90, 0x005A, 0x0302, 0, - 1, 0x1E91, 0x007A, 0x0302, 0, - 1, 0x1E92, 0x005A, 0x0323, 0, - 1, 0x1E93, 0x007A, 0x0323, 0, - 1, 0x1E94, 0x005A, 0x0331, 0, - 1, 0x1E95, 0x007A, 0x0331, 0, - 1, 0x1E96, 0x0068, 0x0331, 0, - 1, 0x1E97, 0x0074, 0x0308, 0, - 1, 0x1E98, 0x0077, 0x030A, 0, - 1, 0x1E99, 0x0079, 0x030A, 0, - 16, 0x1E9A, 0x0061, 0x02BE, 0, - 1, 0x1E9B, 0x017F, 0x0307, 0, - 1, 0x1EA0, 0x0041, 0x0323, 0, - 1, 0x1EA1, 0x0061, 0x0323, 0, - 1, 0x1EA2, 0x0041, 0x0309, 0, - 1, 0x1EA3, 0x0061, 0x0309, 0, - 1, 0x1EA4, 0x00C2, 0x0301, 0, - 1, 0x1EA5, 0x00E2, 0x0301, 0, - 1, 0x1EA6, 0x00C2, 0x0300, 0, - 1, 0x1EA7, 0x00E2, 0x0300, 0, - 1, 0x1EA8, 0x00C2, 0x0309, 0, - 1, 0x1EA9, 0x00E2, 0x0309, 0, - 1, 0x1EAA, 0x00C2, 0x0303, 0, - 1, 0x1EAB, 0x00E2, 0x0303, 0, - 1, 0x1EAC, 0x1EA0, 0x0302, 0, - 1, 0x1EAD, 0x1EA1, 0x0302, 0, - 1, 0x1EAE, 0x0102, 0x0301, 0, - 1, 0x1EAF, 0x0103, 0x0301, 0, - 1, 0x1EB0, 0x0102, 0x0300, 0, - 1, 0x1EB1, 0x0103, 0x0300, 0, - 1, 0x1EB2, 0x0102, 0x0309, 0, - 1, 0x1EB3, 0x0103, 0x0309, 0, - 1, 0x1EB4, 0x0102, 0x0303, 0, - 1, 0x1EB5, 0x0103, 0x0303, 0, - 1, 0x1EB6, 0x1EA0, 0x0306, 0, - 1, 0x1EB7, 0x1EA1, 0x0306, 0, - 1, 0x1EB8, 0x0045, 0x0323, 0, - 1, 0x1EB9, 0x0065, 0x0323, 0, - 1, 0x1EBA, 0x0045, 0x0309, 0, - 1, 0x1EBB, 0x0065, 0x0309, 0, - 1, 0x1EBC, 0x0045, 0x0303, 0, - 1, 0x1EBD, 0x0065, 0x0303, 0, - 1, 0x1EBE, 0x00CA, 0x0301, 0, - 1, 0x1EBF, 0x00EA, 0x0301, 0, - 1, 0x1EC0, 0x00CA, 0x0300, 0, - 1, 0x1EC1, 0x00EA, 0x0300, 0, - 1, 0x1EC2, 0x00CA, 0x0309, 0, - 1, 0x1EC3, 0x00EA, 0x0309, 0, - 1, 0x1EC4, 0x00CA, 0x0303, 0, - 1, 0x1EC5, 0x00EA, 0x0303, 0, - 1, 0x1EC6, 0x1EB8, 0x0302, 0, - 1, 0x1EC7, 0x1EB9, 0x0302, 0, - 1, 0x1EC8, 0x0049, 0x0309, 0, - 1, 0x1EC9, 0x0069, 0x0309, 0, - 1, 0x1ECA, 0x0049, 0x0323, 0, - 1, 0x1ECB, 0x0069, 0x0323, 0, - 1, 0x1ECC, 0x004F, 0x0323, 0, - 1, 0x1ECD, 0x006F, 0x0323, 0, - 1, 0x1ECE, 0x004F, 0x0309, 0, - 1, 0x1ECF, 0x006F, 0x0309, 0, - 1, 0x1ED0, 0x00D4, 0x0301, 0, - 1, 0x1ED1, 0x00F4, 0x0301, 0, - 1, 0x1ED2, 0x00D4, 0x0300, 0, - 1, 0x1ED3, 0x00F4, 0x0300, 0, - 1, 0x1ED4, 0x00D4, 0x0309, 0, - 1, 0x1ED5, 0x00F4, 0x0309, 0, - 1, 0x1ED6, 0x00D4, 0x0303, 0, - 1, 0x1ED7, 0x00F4, 0x0303, 0, - 1, 0x1ED8, 0x1ECC, 0x0302, 0, - 1, 0x1ED9, 0x1ECD, 0x0302, 0, - 1, 0x1EDA, 0x01A0, 0x0301, 0, - 1, 0x1EDB, 0x01A1, 0x0301, 0, - 1, 0x1EDC, 0x01A0, 0x0300, 0, - 1, 0x1EDD, 0x01A1, 0x0300, 0, - 1, 0x1EDE, 0x01A0, 0x0309, 0, - 1, 0x1EDF, 0x01A1, 0x0309, 0, - 1, 0x1EE0, 0x01A0, 0x0303, 0, - 1, 0x1EE1, 0x01A1, 0x0303, 0, - 1, 0x1EE2, 0x01A0, 0x0323, 0, - 1, 0x1EE3, 0x01A1, 0x0323, 0, - 1, 0x1EE4, 0x0055, 0x0323, 0, - 1, 0x1EE5, 0x0075, 0x0323, 0, - 1, 0x1EE6, 0x0055, 0x0309, 0, - 1, 0x1EE7, 0x0075, 0x0309, 0, - 1, 0x1EE8, 0x01AF, 0x0301, 0, - 1, 0x1EE9, 0x01B0, 0x0301, 0, - 1, 0x1EEA, 0x01AF, 0x0300, 0, - 1, 0x1EEB, 0x01B0, 0x0300, 0, - 1, 0x1EEC, 0x01AF, 0x0309, 0, - 1, 0x1EED, 0x01B0, 0x0309, 0, - 1, 0x1EEE, 0x01AF, 0x0303, 0, - 1, 0x1EEF, 0x01B0, 0x0303, 0, - 1, 0x1EF0, 0x01AF, 0x0323, 0, - 1, 0x1EF1, 0x01B0, 0x0323, 0, - 1, 0x1EF2, 0x0059, 0x0300, 0, - 1, 0x1EF3, 0x0079, 0x0300, 0, - 1, 0x1EF4, 0x0059, 0x0323, 0, - 1, 0x1EF5, 0x0079, 0x0323, 0, - 1, 0x1EF6, 0x0059, 0x0309, 0, - 1, 0x1EF7, 0x0079, 0x0309, 0, - 1, 0x1EF8, 0x0059, 0x0303, 0, - 1, 0x1EF9, 0x0079, 0x0303, 0, - 1, 0x1F00, 0x03B1, 0x0313, 0, - 1, 0x1F01, 0x03B1, 0x0314, 0, - 1, 0x1F02, 0x1F00, 0x0300, 0, - 1, 0x1F03, 0x1F01, 0x0300, 0, - 1, 0x1F04, 0x1F00, 0x0301, 0, - 1, 0x1F05, 0x1F01, 0x0301, 0, - 1, 0x1F06, 0x1F00, 0x0342, 0, - 1, 0x1F07, 0x1F01, 0x0342, 0, - 1, 0x1F08, 0x0391, 0x0313, 0, - 1, 0x1F09, 0x0391, 0x0314, 0, - 1, 0x1F0A, 0x1F08, 0x0300, 0, - 1, 0x1F0B, 0x1F09, 0x0300, 0, - 1, 0x1F0C, 0x1F08, 0x0301, 0, - 1, 0x1F0D, 0x1F09, 0x0301, 0, - 1, 0x1F0E, 0x1F08, 0x0342, 0, - 1, 0x1F0F, 0x1F09, 0x0342, 0, - 1, 0x1F10, 0x03B5, 0x0313, 0, - 1, 0x1F11, 0x03B5, 0x0314, 0, - 1, 0x1F12, 0x1F10, 0x0300, 0, - 1, 0x1F13, 0x1F11, 0x0300, 0, - 1, 0x1F14, 0x1F10, 0x0301, 0, - 1, 0x1F15, 0x1F11, 0x0301, 0, - 1, 0x1F18, 0x0395, 0x0313, 0, - 1, 0x1F19, 0x0395, 0x0314, 0, - 1, 0x1F1A, 0x1F18, 0x0300, 0, - 1, 0x1F1B, 0x1F19, 0x0300, 0, - 1, 0x1F1C, 0x1F18, 0x0301, 0, - 1, 0x1F1D, 0x1F19, 0x0301, 0, - 1, 0x1F20, 0x03B7, 0x0313, 0, - 1, 0x1F21, 0x03B7, 0x0314, 0, - 1, 0x1F22, 0x1F20, 0x0300, 0, - 1, 0x1F23, 0x1F21, 0x0300, 0, - 1, 0x1F24, 0x1F20, 0x0301, 0, - 1, 0x1F25, 0x1F21, 0x0301, 0, - 1, 0x1F26, 0x1F20, 0x0342, 0, - 1, 0x1F27, 0x1F21, 0x0342, 0, - 1, 0x1F28, 0x0397, 0x0313, 0, - 1, 0x1F29, 0x0397, 0x0314, 0, - 1, 0x1F2A, 0x1F28, 0x0300, 0, - 1, 0x1F2B, 0x1F29, 0x0300, 0, - 1, 0x1F2C, 0x1F28, 0x0301, 0, - 1, 0x1F2D, 0x1F29, 0x0301, 0, - 1, 0x1F2E, 0x1F28, 0x0342, 0, - 1, 0x1F2F, 0x1F29, 0x0342, 0, - 1, 0x1F30, 0x03B9, 0x0313, 0, - 1, 0x1F31, 0x03B9, 0x0314, 0, - 1, 0x1F32, 0x1F30, 0x0300, 0, - 1, 0x1F33, 0x1F31, 0x0300, 0, - 1, 0x1F34, 0x1F30, 0x0301, 0, - 1, 0x1F35, 0x1F31, 0x0301, 0, - 1, 0x1F36, 0x1F30, 0x0342, 0, - 1, 0x1F37, 0x1F31, 0x0342, 0, - 1, 0x1F38, 0x0399, 0x0313, 0, - 1, 0x1F39, 0x0399, 0x0314, 0, - 1, 0x1F3A, 0x1F38, 0x0300, 0, - 1, 0x1F3B, 0x1F39, 0x0300, 0, - 1, 0x1F3C, 0x1F38, 0x0301, 0, - 1, 0x1F3D, 0x1F39, 0x0301, 0, - 1, 0x1F3E, 0x1F38, 0x0342, 0, - 1, 0x1F3F, 0x1F39, 0x0342, 0, - 1, 0x1F40, 0x03BF, 0x0313, 0, - 1, 0x1F41, 0x03BF, 0x0314, 0, - 1, 0x1F42, 0x1F40, 0x0300, 0, - 1, 0x1F43, 0x1F41, 0x0300, 0, - 1, 0x1F44, 0x1F40, 0x0301, 0, - 1, 0x1F45, 0x1F41, 0x0301, 0, - 1, 0x1F48, 0x039F, 0x0313, 0, - 1, 0x1F49, 0x039F, 0x0314, 0, - 1, 0x1F4A, 0x1F48, 0x0300, 0, - 1, 0x1F4B, 0x1F49, 0x0300, 0, - 1, 0x1F4C, 0x1F48, 0x0301, 0, - 1, 0x1F4D, 0x1F49, 0x0301, 0, - 1, 0x1F50, 0x03C5, 0x0313, 0, - 1, 0x1F51, 0x03C5, 0x0314, 0, - 1, 0x1F52, 0x1F50, 0x0300, 0, - 1, 0x1F53, 0x1F51, 0x0300, 0, - 1, 0x1F54, 0x1F50, 0x0301, 0, - 1, 0x1F55, 0x1F51, 0x0301, 0, - 1, 0x1F56, 0x1F50, 0x0342, 0, - 1, 0x1F57, 0x1F51, 0x0342, 0, - 1, 0x1F59, 0x03A5, 0x0314, 0, - 1, 0x1F5B, 0x1F59, 0x0300, 0, - 1, 0x1F5D, 0x1F59, 0x0301, 0, - 1, 0x1F5F, 0x1F59, 0x0342, 0, - 1, 0x1F60, 0x03C9, 0x0313, 0, - 1, 0x1F61, 0x03C9, 0x0314, 0, - 1, 0x1F62, 0x1F60, 0x0300, 0, - 1, 0x1F63, 0x1F61, 0x0300, 0, - 1, 0x1F64, 0x1F60, 0x0301, 0, - 1, 0x1F65, 0x1F61, 0x0301, 0, - 1, 0x1F66, 0x1F60, 0x0342, 0, - 1, 0x1F67, 0x1F61, 0x0342, 0, - 1, 0x1F68, 0x03A9, 0x0313, 0, - 1, 0x1F69, 0x03A9, 0x0314, 0, - 1, 0x1F6A, 0x1F68, 0x0300, 0, - 1, 0x1F6B, 0x1F69, 0x0300, 0, - 1, 0x1F6C, 0x1F68, 0x0301, 0, - 1, 0x1F6D, 0x1F69, 0x0301, 0, - 1, 0x1F6E, 0x1F68, 0x0342, 0, - 1, 0x1F6F, 0x1F69, 0x0342, 0, - 1, 0x1F70, 0x03B1, 0x0300, 0, - 1, 0x1F71, 0x03AC, 0, - 1, 0x1F72, 0x03B5, 0x0300, 0, - 1, 0x1F73, 0x03AD, 0, - 1, 0x1F74, 0x03B7, 0x0300, 0, - 1, 0x1F75, 0x03AE, 0, - 1, 0x1F76, 0x03B9, 0x0300, 0, - 1, 0x1F77, 0x03AF, 0, - 1, 0x1F78, 0x03BF, 0x0300, 0, - 1, 0x1F79, 0x03CC, 0, - 1, 0x1F7A, 0x03C5, 0x0300, 0, - 1, 0x1F7B, 0x03CD, 0, - 1, 0x1F7C, 0x03C9, 0x0300, 0, - 1, 0x1F7D, 0x03CE, 0, - 1, 0x1F80, 0x1F00, 0x0345, 0, - 1, 0x1F81, 0x1F01, 0x0345, 0, - 1, 0x1F82, 0x1F02, 0x0345, 0, - 1, 0x1F83, 0x1F03, 0x0345, 0, - 1, 0x1F84, 0x1F04, 0x0345, 0, - 1, 0x1F85, 0x1F05, 0x0345, 0, - 1, 0x1F86, 0x1F06, 0x0345, 0, - 1, 0x1F87, 0x1F07, 0x0345, 0, - 1, 0x1F88, 0x1F08, 0x0345, 0, - 1, 0x1F89, 0x1F09, 0x0345, 0, - 1, 0x1F8A, 0x1F0A, 0x0345, 0, - 1, 0x1F8B, 0x1F0B, 0x0345, 0, - 1, 0x1F8C, 0x1F0C, 0x0345, 0, - 1, 0x1F8D, 0x1F0D, 0x0345, 0, - 1, 0x1F8E, 0x1F0E, 0x0345, 0, - 1, 0x1F8F, 0x1F0F, 0x0345, 0, - 1, 0x1F90, 0x1F20, 0x0345, 0, - 1, 0x1F91, 0x1F21, 0x0345, 0, - 1, 0x1F92, 0x1F22, 0x0345, 0, - 1, 0x1F93, 0x1F23, 0x0345, 0, - 1, 0x1F94, 0x1F24, 0x0345, 0, - 1, 0x1F95, 0x1F25, 0x0345, 0, - 1, 0x1F96, 0x1F26, 0x0345, 0, - 1, 0x1F97, 0x1F27, 0x0345, 0, - 1, 0x1F98, 0x1F28, 0x0345, 0, - 1, 0x1F99, 0x1F29, 0x0345, 0, - 1, 0x1F9A, 0x1F2A, 0x0345, 0, - 1, 0x1F9B, 0x1F2B, 0x0345, 0, - 1, 0x1F9C, 0x1F2C, 0x0345, 0, - 1, 0x1F9D, 0x1F2D, 0x0345, 0, - 1, 0x1F9E, 0x1F2E, 0x0345, 0, - 1, 0x1F9F, 0x1F2F, 0x0345, 0, - 1, 0x1FA0, 0x1F60, 0x0345, 0, - 1, 0x1FA1, 0x1F61, 0x0345, 0, - 1, 0x1FA2, 0x1F62, 0x0345, 0, - 1, 0x1FA3, 0x1F63, 0x0345, 0, - 1, 0x1FA4, 0x1F64, 0x0345, 0, - 1, 0x1FA5, 0x1F65, 0x0345, 0, - 1, 0x1FA6, 0x1F66, 0x0345, 0, - 1, 0x1FA7, 0x1F67, 0x0345, 0, - 1, 0x1FA8, 0x1F68, 0x0345, 0, - 1, 0x1FA9, 0x1F69, 0x0345, 0, - 1, 0x1FAA, 0x1F6A, 0x0345, 0, - 1, 0x1FAB, 0x1F6B, 0x0345, 0, - 1, 0x1FAC, 0x1F6C, 0x0345, 0, - 1, 0x1FAD, 0x1F6D, 0x0345, 0, - 1, 0x1FAE, 0x1F6E, 0x0345, 0, - 1, 0x1FAF, 0x1F6F, 0x0345, 0, - 1, 0x1FB0, 0x03B1, 0x0306, 0, - 1, 0x1FB1, 0x03B1, 0x0304, 0, - 1, 0x1FB2, 0x1F70, 0x0345, 0, - 1, 0x1FB3, 0x03B1, 0x0345, 0, - 1, 0x1FB4, 0x03AC, 0x0345, 0, - 1, 0x1FB6, 0x03B1, 0x0342, 0, - 1, 0x1FB7, 0x1FB6, 0x0345, 0, - 1, 0x1FB8, 0x0391, 0x0306, 0, - 1, 0x1FB9, 0x0391, 0x0304, 0, - 1, 0x1FBA, 0x0391, 0x0300, 0, - 1, 0x1FBB, 0x0386, 0, - 1, 0x1FBC, 0x0391, 0x0345, 0, - 16, 0x1FBD, 0x0020, 0x0313, 0, - 1, 0x1FBE, 0x03B9, 0, - 16, 0x1FBF, 0x0020, 0x0313, 0, - 16, 0x1FC0, 0x0020, 0x0342, 0, - 1, 0x1FC1, 0x00A8, 0x0342, 0, - 1, 0x1FC2, 0x1F74, 0x0345, 0, - 1, 0x1FC3, 0x03B7, 0x0345, 0, - 1, 0x1FC4, 0x03AE, 0x0345, 0, - 1, 0x1FC6, 0x03B7, 0x0342, 0, - 1, 0x1FC7, 0x1FC6, 0x0345, 0, - 1, 0x1FC8, 0x0395, 0x0300, 0, - 1, 0x1FC9, 0x0388, 0, - 1, 0x1FCA, 0x0397, 0x0300, 0, - 1, 0x1FCB, 0x0389, 0, - 1, 0x1FCC, 0x0397, 0x0345, 0, - 1, 0x1FCD, 0x1FBF, 0x0300, 0, - 1, 0x1FCE, 0x1FBF, 0x0301, 0, - 1, 0x1FCF, 0x1FBF, 0x0342, 0, - 1, 0x1FD0, 0x03B9, 0x0306, 0, - 1, 0x1FD1, 0x03B9, 0x0304, 0, - 1, 0x1FD2, 0x03CA, 0x0300, 0, - 1, 0x1FD3, 0x0390, 0, - 1, 0x1FD6, 0x03B9, 0x0342, 0, - 1, 0x1FD7, 0x03CA, 0x0342, 0, - 1, 0x1FD8, 0x0399, 0x0306, 0, - 1, 0x1FD9, 0x0399, 0x0304, 0, - 1, 0x1FDA, 0x0399, 0x0300, 0, - 1, 0x1FDB, 0x038A, 0, - 1, 0x1FDD, 0x1FFE, 0x0300, 0, - 1, 0x1FDE, 0x1FFE, 0x0301, 0, - 1, 0x1FDF, 0x1FFE, 0x0342, 0, - 1, 0x1FE0, 0x03C5, 0x0306, 0, - 1, 0x1FE1, 0x03C5, 0x0304, 0, - 1, 0x1FE2, 0x03CB, 0x0300, 0, - 1, 0x1FE3, 0x03B0, 0, - 1, 0x1FE4, 0x03C1, 0x0313, 0, - 1, 0x1FE5, 0x03C1, 0x0314, 0, - 1, 0x1FE6, 0x03C5, 0x0342, 0, - 1, 0x1FE7, 0x03CB, 0x0342, 0, - 1, 0x1FE8, 0x03A5, 0x0306, 0, - 1, 0x1FE9, 0x03A5, 0x0304, 0, - 1, 0x1FEA, 0x03A5, 0x0300, 0, - 1, 0x1FEB, 0x038E, 0, - 1, 0x1FEC, 0x03A1, 0x0314, 0, - 1, 0x1FED, 0x00A8, 0x0300, 0, - 1, 0x1FEE, 0x0385, 0, - 1, 0x1FEF, 0x0060, 0, - 1, 0x1FF2, 0x1F7C, 0x0345, 0, - 1, 0x1FF3, 0x03C9, 0x0345, 0, - 1, 0x1FF4, 0x03CE, 0x0345, 0, - 1, 0x1FF6, 0x03C9, 0x0342, 0, - 1, 0x1FF7, 0x1FF6, 0x0345, 0, - 1, 0x1FF8, 0x039F, 0x0300, 0, - 1, 0x1FF9, 0x038C, 0, - 1, 0x1FFA, 0x03A9, 0x0300, 0, - 1, 0x1FFB, 0x038F, 0, - 1, 0x1FFC, 0x03A9, 0x0345, 0, - 1, 0x1FFD, 0x00B4, 0, - 16, 0x1FFE, 0x0020, 0x0314, 0, - 1, 0x2000, 0x2002, 0, - 1, 0x2001, 0x2003, 0, - 16, 0x2002, 0x0020, 0, - 16, 0x2003, 0x0020, 0, - 16, 0x2004, 0x0020, 0, - 16, 0x2005, 0x0020, 0, - 16, 0x2006, 0x0020, 0, - 3, 0x2007, 0x0020, 0, - 16, 0x2008, 0x0020, 0, - 16, 0x2009, 0x0020, 0, - 16, 0x200A, 0x0020, 0, - 3, 0x2011, 0x2010, 0, - 16, 0x2017, 0x0020, 0x0333, 0, - 16, 0x2024, 0x002E, 0, - 16, 0x2025, 0x002E, 0x002E, 0, - 16, 0x2026, 0x002E, 0x002E, 0x002E, 0, - 3, 0x202F, 0x0020, 0, - 16, 0x2033, 0x2032, 0x2032, 0, - 16, 0x2034, 0x2032, 0x2032, 0x2032, 0, - 16, 0x2036, 0x2035, 0x2035, 0, - 16, 0x2037, 0x2035, 0x2035, 0x2035, 0, - 16, 0x203C, 0x0021, 0x0021, 0, - 16, 0x203E, 0x0020, 0x0305, 0, - 16, 0x2047, 0x003F, 0x003F, 0, - 16, 0x2048, 0x003F, 0x0021, 0, - 16, 0x2049, 0x0021, 0x003F, 0, - 16, 0x2057, 0x2032, 0x2032, 0x2032, 0x2032, 0, - 16, 0x205F, 0x0020, 0, - 9, 0x2070, 0x0030, 0, - 9, 0x2071, 0x0069, 0, - 9, 0x2074, 0x0034, 0, - 9, 0x2075, 0x0035, 0, - 9, 0x2076, 0x0036, 0, - 9, 0x2077, 0x0037, 0, - 9, 0x2078, 0x0038, 0, - 9, 0x2079, 0x0039, 0, - 9, 0x207A, 0x002B, 0, - 9, 0x207B, 0x2212, 0, - 9, 0x207C, 0x003D, 0, - 9, 0x207D, 0x0028, 0, - 9, 0x207E, 0x0029, 0, - 9, 0x207F, 0x006E, 0, - 10, 0x2080, 0x0030, 0, - 10, 0x2081, 0x0031, 0, - 10, 0x2082, 0x0032, 0, - 10, 0x2083, 0x0033, 0, - 10, 0x2084, 0x0034, 0, - 10, 0x2085, 0x0035, 0, - 10, 0x2086, 0x0036, 0, - 10, 0x2087, 0x0037, 0, - 10, 0x2088, 0x0038, 0, - 10, 0x2089, 0x0039, 0, - 10, 0x208A, 0x002B, 0, - 10, 0x208B, 0x2212, 0, - 10, 0x208C, 0x003D, 0, - 10, 0x208D, 0x0028, 0, - 10, 0x208E, 0x0029, 0, - 16, 0x20A8, 0x0052, 0x0073, 0, - 16, 0x2100, 0x0061, 0x002F, 0x0063, 0, - 16, 0x2101, 0x0061, 0x002F, 0x0073, 0, - 2, 0x2102, 0x0043, 0, - 16, 0x2103, 0x00B0, 0x0043, 0, - 16, 0x2105, 0x0063, 0x002F, 0x006F, 0, - 16, 0x2106, 0x0063, 0x002F, 0x0075, 0, - 16, 0x2107, 0x0190, 0, - 16, 0x2109, 0x00B0, 0x0046, 0, - 2, 0x210A, 0x0067, 0, - 2, 0x210B, 0x0048, 0, - 2, 0x210C, 0x0048, 0, - 2, 0x210D, 0x0048, 0, - 2, 0x210E, 0x0068, 0, - 2, 0x210F, 0x0127, 0, - 2, 0x2110, 0x0049, 0, - 2, 0x2111, 0x0049, 0, - 2, 0x2112, 0x004C, 0, - 2, 0x2113, 0x006C, 0, - 2, 0x2115, 0x004E, 0, - 16, 0x2116, 0x004E, 0x006F, 0, - 2, 0x2119, 0x0050, 0, - 2, 0x211A, 0x0051, 0, - 2, 0x211B, 0x0052, 0, - 2, 0x211C, 0x0052, 0, - 2, 0x211D, 0x0052, 0, - 9, 0x2120, 0x0053, 0x004D, 0, - 16, 0x2121, 0x0054, 0x0045, 0x004C, 0, - 9, 0x2122, 0x0054, 0x004D, 0, - 2, 0x2124, 0x005A, 0, - 1, 0x2126, 0x03A9, 0, - 2, 0x2128, 0x005A, 0, - 1, 0x212A, 0x004B, 0, - 1, 0x212B, 0x00C5, 0, - 2, 0x212C, 0x0042, 0, - 2, 0x212D, 0x0043, 0, - 2, 0x212F, 0x0065, 0, - 2, 0x2130, 0x0045, 0, - 2, 0x2131, 0x0046, 0, - 2, 0x2133, 0x004D, 0, - 2, 0x2134, 0x006F, 0, - 16, 0x2135, 0x05D0, 0, - 16, 0x2136, 0x05D1, 0, - 16, 0x2137, 0x05D2, 0, - 16, 0x2138, 0x05D3, 0, - 2, 0x2139, 0x0069, 0, - 2, 0x213D, 0x03B3, 0, - 2, 0x213E, 0x0393, 0, - 2, 0x213F, 0x03A0, 0, - 2, 0x2140, 0x2211, 0, - 2, 0x2145, 0x0044, 0, - 2, 0x2146, 0x0064, 0, - 2, 0x2147, 0x0065, 0, - 2, 0x2148, 0x0069, 0, - 2, 0x2149, 0x006A, 0, - 17, 0x2153, 0x0031, 0x2044, 0x0033, 0, - 17, 0x2154, 0x0032, 0x2044, 0x0033, 0, - 17, 0x2155, 0x0031, 0x2044, 0x0035, 0, - 17, 0x2156, 0x0032, 0x2044, 0x0035, 0, - 17, 0x2157, 0x0033, 0x2044, 0x0035, 0, - 17, 0x2158, 0x0034, 0x2044, 0x0035, 0, - 17, 0x2159, 0x0031, 0x2044, 0x0036, 0, - 17, 0x215A, 0x0035, 0x2044, 0x0036, 0, - 17, 0x215B, 0x0031, 0x2044, 0x0038, 0, - 17, 0x215C, 0x0033, 0x2044, 0x0038, 0, - 17, 0x215D, 0x0035, 0x2044, 0x0038, 0, - 17, 0x215E, 0x0037, 0x2044, 0x0038, 0, - 17, 0x215F, 0x0031, 0x2044, 0, - 16, 0x2160, 0x0049, 0, - 16, 0x2161, 0x0049, 0x0049, 0, - 16, 0x2162, 0x0049, 0x0049, 0x0049, 0, - 16, 0x2163, 0x0049, 0x0056, 0, - 16, 0x2164, 0x0056, 0, - 16, 0x2165, 0x0056, 0x0049, 0, - 16, 0x2166, 0x0056, 0x0049, 0x0049, 0, - 16, 0x2167, 0x0056, 0x0049, 0x0049, 0x0049, 0, - 16, 0x2168, 0x0049, 0x0058, 0, - 16, 0x2169, 0x0058, 0, - 16, 0x216A, 0x0058, 0x0049, 0, - 16, 0x216B, 0x0058, 0x0049, 0x0049, 0, - 16, 0x216C, 0x004C, 0, - 16, 0x216D, 0x0043, 0, - 16, 0x216E, 0x0044, 0, - 16, 0x216F, 0x004D, 0, - 16, 0x2170, 0x0069, 0, - 16, 0x2171, 0x0069, 0x0069, 0, - 16, 0x2172, 0x0069, 0x0069, 0x0069, 0, - 16, 0x2173, 0x0069, 0x0076, 0, - 16, 0x2174, 0x0076, 0, - 16, 0x2175, 0x0076, 0x0069, 0, - 16, 0x2176, 0x0076, 0x0069, 0x0069, 0, - 16, 0x2177, 0x0076, 0x0069, 0x0069, 0x0069, 0, - 16, 0x2178, 0x0069, 0x0078, 0, - 16, 0x2179, 0x0078, 0, - 16, 0x217A, 0x0078, 0x0069, 0, - 16, 0x217B, 0x0078, 0x0069, 0x0069, 0, - 16, 0x217C, 0x006C, 0, - 16, 0x217D, 0x0063, 0, - 16, 0x217E, 0x0064, 0, - 16, 0x217F, 0x006D, 0, - 1, 0x219A, 0x2190, 0x0338, 0, - 1, 0x219B, 0x2192, 0x0338, 0, - 1, 0x21AE, 0x2194, 0x0338, 0, - 1, 0x21CD, 0x21D0, 0x0338, 0, - 1, 0x21CE, 0x21D4, 0x0338, 0, - 1, 0x21CF, 0x21D2, 0x0338, 0, - 1, 0x2204, 0x2203, 0x0338, 0, - 1, 0x2209, 0x2208, 0x0338, 0, - 1, 0x220C, 0x220B, 0x0338, 0, - 1, 0x2224, 0x2223, 0x0338, 0, - 1, 0x2226, 0x2225, 0x0338, 0, - 16, 0x222C, 0x222B, 0x222B, 0, - 16, 0x222D, 0x222B, 0x222B, 0x222B, 0, - 16, 0x222F, 0x222E, 0x222E, 0, - 16, 0x2230, 0x222E, 0x222E, 0x222E, 0, - 1, 0x2241, 0x223C, 0x0338, 0, - 1, 0x2244, 0x2243, 0x0338, 0, - 1, 0x2247, 0x2245, 0x0338, 0, - 1, 0x2249, 0x2248, 0x0338, 0, - 1, 0x2260, 0x003D, 0x0338, 0, - 1, 0x2262, 0x2261, 0x0338, 0, - 1, 0x226D, 0x224D, 0x0338, 0, - 1, 0x226E, 0x003C, 0x0338, 0, - 1, 0x226F, 0x003E, 0x0338, 0, - 1, 0x2270, 0x2264, 0x0338, 0, - 1, 0x2271, 0x2265, 0x0338, 0, - 1, 0x2274, 0x2272, 0x0338, 0, - 1, 0x2275, 0x2273, 0x0338, 0, - 1, 0x2278, 0x2276, 0x0338, 0, - 1, 0x2279, 0x2277, 0x0338, 0, - 1, 0x2280, 0x227A, 0x0338, 0, - 1, 0x2281, 0x227B, 0x0338, 0, - 1, 0x2284, 0x2282, 0x0338, 0, - 1, 0x2285, 0x2283, 0x0338, 0, - 1, 0x2288, 0x2286, 0x0338, 0, - 1, 0x2289, 0x2287, 0x0338, 0, - 1, 0x22AC, 0x22A2, 0x0338, 0, - 1, 0x22AD, 0x22A8, 0x0338, 0, - 1, 0x22AE, 0x22A9, 0x0338, 0, - 1, 0x22AF, 0x22AB, 0x0338, 0, - 1, 0x22E0, 0x227C, 0x0338, 0, - 1, 0x22E1, 0x227D, 0x0338, 0, - 1, 0x22E2, 0x2291, 0x0338, 0, - 1, 0x22E3, 0x2292, 0x0338, 0, - 1, 0x22EA, 0x22B2, 0x0338, 0, - 1, 0x22EB, 0x22B3, 0x0338, 0, - 1, 0x22EC, 0x22B4, 0x0338, 0, - 1, 0x22ED, 0x22B5, 0x0338, 0, - 1, 0x2329, 0x3008, 0, - 1, 0x232A, 0x3009, 0, - 8, 0x2460, 0x0031, 0, - 8, 0x2461, 0x0032, 0, - 8, 0x2462, 0x0033, 0, - 8, 0x2463, 0x0034, 0, - 8, 0x2464, 0x0035, 0, - 8, 0x2465, 0x0036, 0, - 8, 0x2466, 0x0037, 0, - 8, 0x2467, 0x0038, 0, - 8, 0x2468, 0x0039, 0, - 8, 0x2469, 0x0031, 0x0030, 0, - 8, 0x246A, 0x0031, 0x0031, 0, - 8, 0x246B, 0x0031, 0x0032, 0, - 8, 0x246C, 0x0031, 0x0033, 0, - 8, 0x246D, 0x0031, 0x0034, 0, - 8, 0x246E, 0x0031, 0x0035, 0, - 8, 0x246F, 0x0031, 0x0036, 0, - 8, 0x2470, 0x0031, 0x0037, 0, - 8, 0x2471, 0x0031, 0x0038, 0, - 8, 0x2472, 0x0031, 0x0039, 0, - 8, 0x2473, 0x0032, 0x0030, 0, - 16, 0x2474, 0x0028, 0x0031, 0x0029, 0, - 16, 0x2475, 0x0028, 0x0032, 0x0029, 0, - 16, 0x2476, 0x0028, 0x0033, 0x0029, 0, - 16, 0x2477, 0x0028, 0x0034, 0x0029, 0, - 16, 0x2478, 0x0028, 0x0035, 0x0029, 0, - 16, 0x2479, 0x0028, 0x0036, 0x0029, 0, - 16, 0x247A, 0x0028, 0x0037, 0x0029, 0, - 16, 0x247B, 0x0028, 0x0038, 0x0029, 0, - 16, 0x247C, 0x0028, 0x0039, 0x0029, 0, - 16, 0x247D, 0x0028, 0x0031, 0x0030, 0x0029, 0, - 16, 0x247E, 0x0028, 0x0031, 0x0031, 0x0029, 0, - 16, 0x247F, 0x0028, 0x0031, 0x0032, 0x0029, 0, - 16, 0x2480, 0x0028, 0x0031, 0x0033, 0x0029, 0, - 16, 0x2481, 0x0028, 0x0031, 0x0034, 0x0029, 0, - 16, 0x2482, 0x0028, 0x0031, 0x0035, 0x0029, 0, - 16, 0x2483, 0x0028, 0x0031, 0x0036, 0x0029, 0, - 16, 0x2484, 0x0028, 0x0031, 0x0037, 0x0029, 0, - 16, 0x2485, 0x0028, 0x0031, 0x0038, 0x0029, 0, - 16, 0x2486, 0x0028, 0x0031, 0x0039, 0x0029, 0, - 16, 0x2487, 0x0028, 0x0032, 0x0030, 0x0029, 0, - 16, 0x2488, 0x0031, 0x002E, 0, - 16, 0x2489, 0x0032, 0x002E, 0, - 16, 0x248A, 0x0033, 0x002E, 0, - 16, 0x248B, 0x0034, 0x002E, 0, - 16, 0x248C, 0x0035, 0x002E, 0, - 16, 0x248D, 0x0036, 0x002E, 0, - 16, 0x248E, 0x0037, 0x002E, 0, - 16, 0x248F, 0x0038, 0x002E, 0, - 16, 0x2490, 0x0039, 0x002E, 0, - 16, 0x2491, 0x0031, 0x0030, 0x002E, 0, - 16, 0x2492, 0x0031, 0x0031, 0x002E, 0, - 16, 0x2493, 0x0031, 0x0032, 0x002E, 0, - 16, 0x2494, 0x0031, 0x0033, 0x002E, 0, - 16, 0x2495, 0x0031, 0x0034, 0x002E, 0, - 16, 0x2496, 0x0031, 0x0035, 0x002E, 0, - 16, 0x2497, 0x0031, 0x0036, 0x002E, 0, - 16, 0x2498, 0x0031, 0x0037, 0x002E, 0, - 16, 0x2499, 0x0031, 0x0038, 0x002E, 0, - 16, 0x249A, 0x0031, 0x0039, 0x002E, 0, - 16, 0x249B, 0x0032, 0x0030, 0x002E, 0, - 16, 0x249C, 0x0028, 0x0061, 0x0029, 0, - 16, 0x249D, 0x0028, 0x0062, 0x0029, 0, - 16, 0x249E, 0x0028, 0x0063, 0x0029, 0, - 16, 0x249F, 0x0028, 0x0064, 0x0029, 0, - 16, 0x24A0, 0x0028, 0x0065, 0x0029, 0, - 16, 0x24A1, 0x0028, 0x0066, 0x0029, 0, - 16, 0x24A2, 0x0028, 0x0067, 0x0029, 0, - 16, 0x24A3, 0x0028, 0x0068, 0x0029, 0, - 16, 0x24A4, 0x0028, 0x0069, 0x0029, 0, - 16, 0x24A5, 0x0028, 0x006A, 0x0029, 0, - 16, 0x24A6, 0x0028, 0x006B, 0x0029, 0, - 16, 0x24A7, 0x0028, 0x006C, 0x0029, 0, - 16, 0x24A8, 0x0028, 0x006D, 0x0029, 0, - 16, 0x24A9, 0x0028, 0x006E, 0x0029, 0, - 16, 0x24AA, 0x0028, 0x006F, 0x0029, 0, - 16, 0x24AB, 0x0028, 0x0070, 0x0029, 0, - 16, 0x24AC, 0x0028, 0x0071, 0x0029, 0, - 16, 0x24AD, 0x0028, 0x0072, 0x0029, 0, - 16, 0x24AE, 0x0028, 0x0073, 0x0029, 0, - 16, 0x24AF, 0x0028, 0x0074, 0x0029, 0, - 16, 0x24B0, 0x0028, 0x0075, 0x0029, 0, - 16, 0x24B1, 0x0028, 0x0076, 0x0029, 0, - 16, 0x24B2, 0x0028, 0x0077, 0x0029, 0, - 16, 0x24B3, 0x0028, 0x0078, 0x0029, 0, - 16, 0x24B4, 0x0028, 0x0079, 0x0029, 0, - 16, 0x24B5, 0x0028, 0x007A, 0x0029, 0, - 8, 0x24B6, 0x0041, 0, - 8, 0x24B7, 0x0042, 0, - 8, 0x24B8, 0x0043, 0, - 8, 0x24B9, 0x0044, 0, - 8, 0x24BA, 0x0045, 0, - 8, 0x24BB, 0x0046, 0, - 8, 0x24BC, 0x0047, 0, - 8, 0x24BD, 0x0048, 0, - 8, 0x24BE, 0x0049, 0, - 8, 0x24BF, 0x004A, 0, - 8, 0x24C0, 0x004B, 0, - 8, 0x24C1, 0x004C, 0, - 8, 0x24C2, 0x004D, 0, - 8, 0x24C3, 0x004E, 0, - 8, 0x24C4, 0x004F, 0, - 8, 0x24C5, 0x0050, 0, - 8, 0x24C6, 0x0051, 0, - 8, 0x24C7, 0x0052, 0, - 8, 0x24C8, 0x0053, 0, - 8, 0x24C9, 0x0054, 0, - 8, 0x24CA, 0x0055, 0, - 8, 0x24CB, 0x0056, 0, - 8, 0x24CC, 0x0057, 0, - 8, 0x24CD, 0x0058, 0, - 8, 0x24CE, 0x0059, 0, - 8, 0x24CF, 0x005A, 0, - 8, 0x24D0, 0x0061, 0, - 8, 0x24D1, 0x0062, 0, - 8, 0x24D2, 0x0063, 0, - 8, 0x24D3, 0x0064, 0, - 8, 0x24D4, 0x0065, 0, - 8, 0x24D5, 0x0066, 0, - 8, 0x24D6, 0x0067, 0, - 8, 0x24D7, 0x0068, 0, - 8, 0x24D8, 0x0069, 0, - 8, 0x24D9, 0x006A, 0, - 8, 0x24DA, 0x006B, 0, - 8, 0x24DB, 0x006C, 0, - 8, 0x24DC, 0x006D, 0, - 8, 0x24DD, 0x006E, 0, - 8, 0x24DE, 0x006F, 0, - 8, 0x24DF, 0x0070, 0, - 8, 0x24E0, 0x0071, 0, - 8, 0x24E1, 0x0072, 0, - 8, 0x24E2, 0x0073, 0, - 8, 0x24E3, 0x0074, 0, - 8, 0x24E4, 0x0075, 0, - 8, 0x24E5, 0x0076, 0, - 8, 0x24E6, 0x0077, 0, - 8, 0x24E7, 0x0078, 0, - 8, 0x24E8, 0x0079, 0, - 8, 0x24E9, 0x007A, 0, - 8, 0x24EA, 0x0030, 0, - 16, 0x2A0C, 0x222B, 0x222B, 0x222B, 0x222B, 0, - 16, 0x2A74, 0x003A, 0x003A, 0x003D, 0, - 16, 0x2A75, 0x003D, 0x003D, 0, - 16, 0x2A76, 0x003D, 0x003D, 0x003D, 0, - 1, 0x2ADC, 0x2ADD, 0x0338, 0, - 16, 0x2E9F, 0x6BCD, 0, - 16, 0x2EF3, 0x9F9F, 0, - 16, 0x2F00, 0x4E00, 0, - 16, 0x2F01, 0x4E28, 0, - 16, 0x2F02, 0x4E36, 0, - 16, 0x2F03, 0x4E3F, 0, - 16, 0x2F04, 0x4E59, 0, - 16, 0x2F05, 0x4E85, 0, - 16, 0x2F06, 0x4E8C, 0, - 16, 0x2F07, 0x4EA0, 0, - 16, 0x2F08, 0x4EBA, 0, - 16, 0x2F09, 0x513F, 0, - 16, 0x2F0A, 0x5165, 0, - 16, 0x2F0B, 0x516B, 0, - 16, 0x2F0C, 0x5182, 0, - 16, 0x2F0D, 0x5196, 0, - 16, 0x2F0E, 0x51AB, 0, - 16, 0x2F0F, 0x51E0, 0, - 16, 0x2F10, 0x51F5, 0, - 16, 0x2F11, 0x5200, 0, - 16, 0x2F12, 0x529B, 0, - 16, 0x2F13, 0x52F9, 0, - 16, 0x2F14, 0x5315, 0, - 16, 0x2F15, 0x531A, 0, - 16, 0x2F16, 0x5338, 0, - 16, 0x2F17, 0x5341, 0, - 16, 0x2F18, 0x535C, 0, - 16, 0x2F19, 0x5369, 0, - 16, 0x2F1A, 0x5382, 0, - 16, 0x2F1B, 0x53B6, 0, - 16, 0x2F1C, 0x53C8, 0, - 16, 0x2F1D, 0x53E3, 0, - 16, 0x2F1E, 0x56D7, 0, - 16, 0x2F1F, 0x571F, 0, - 16, 0x2F20, 0x58EB, 0, - 16, 0x2F21, 0x5902, 0, - 16, 0x2F22, 0x590A, 0, - 16, 0x2F23, 0x5915, 0, - 16, 0x2F24, 0x5927, 0, - 16, 0x2F25, 0x5973, 0, - 16, 0x2F26, 0x5B50, 0, - 16, 0x2F27, 0x5B80, 0, - 16, 0x2F28, 0x5BF8, 0, - 16, 0x2F29, 0x5C0F, 0, - 16, 0x2F2A, 0x5C22, 0, - 16, 0x2F2B, 0x5C38, 0, - 16, 0x2F2C, 0x5C6E, 0, - 16, 0x2F2D, 0x5C71, 0, - 16, 0x2F2E, 0x5DDB, 0, - 16, 0x2F2F, 0x5DE5, 0, - 16, 0x2F30, 0x5DF1, 0, - 16, 0x2F31, 0x5DFE, 0, - 16, 0x2F32, 0x5E72, 0, - 16, 0x2F33, 0x5E7A, 0, - 16, 0x2F34, 0x5E7F, 0, - 16, 0x2F35, 0x5EF4, 0, - 16, 0x2F36, 0x5EFE, 0, - 16, 0x2F37, 0x5F0B, 0, - 16, 0x2F38, 0x5F13, 0, - 16, 0x2F39, 0x5F50, 0, - 16, 0x2F3A, 0x5F61, 0, - 16, 0x2F3B, 0x5F73, 0, - 16, 0x2F3C, 0x5FC3, 0, - 16, 0x2F3D, 0x6208, 0, - 16, 0x2F3E, 0x6236, 0, - 16, 0x2F3F, 0x624B, 0, - 16, 0x2F40, 0x652F, 0, - 16, 0x2F41, 0x6534, 0, - 16, 0x2F42, 0x6587, 0, - 16, 0x2F43, 0x6597, 0, - 16, 0x2F44, 0x65A4, 0, - 16, 0x2F45, 0x65B9, 0, - 16, 0x2F46, 0x65E0, 0, - 16, 0x2F47, 0x65E5, 0, - 16, 0x2F48, 0x66F0, 0, - 16, 0x2F49, 0x6708, 0, - 16, 0x2F4A, 0x6728, 0, - 16, 0x2F4B, 0x6B20, 0, - 16, 0x2F4C, 0x6B62, 0, - 16, 0x2F4D, 0x6B79, 0, - 16, 0x2F4E, 0x6BB3, 0, - 16, 0x2F4F, 0x6BCB, 0, - 16, 0x2F50, 0x6BD4, 0, - 16, 0x2F51, 0x6BDB, 0, - 16, 0x2F52, 0x6C0F, 0, - 16, 0x2F53, 0x6C14, 0, - 16, 0x2F54, 0x6C34, 0, - 16, 0x2F55, 0x706B, 0, - 16, 0x2F56, 0x722A, 0, - 16, 0x2F57, 0x7236, 0, - 16, 0x2F58, 0x723B, 0, - 16, 0x2F59, 0x723F, 0, - 16, 0x2F5A, 0x7247, 0, - 16, 0x2F5B, 0x7259, 0, - 16, 0x2F5C, 0x725B, 0, - 16, 0x2F5D, 0x72AC, 0, - 16, 0x2F5E, 0x7384, 0, - 16, 0x2F5F, 0x7389, 0, - 16, 0x2F60, 0x74DC, 0, - 16, 0x2F61, 0x74E6, 0, - 16, 0x2F62, 0x7518, 0, - 16, 0x2F63, 0x751F, 0, - 16, 0x2F64, 0x7528, 0, - 16, 0x2F65, 0x7530, 0, - 16, 0x2F66, 0x758B, 0, - 16, 0x2F67, 0x7592, 0, - 16, 0x2F68, 0x7676, 0, - 16, 0x2F69, 0x767D, 0, - 16, 0x2F6A, 0x76AE, 0, - 16, 0x2F6B, 0x76BF, 0, - 16, 0x2F6C, 0x76EE, 0, - 16, 0x2F6D, 0x77DB, 0, - 16, 0x2F6E, 0x77E2, 0, - 16, 0x2F6F, 0x77F3, 0, - 16, 0x2F70, 0x793A, 0, - 16, 0x2F71, 0x79B8, 0, - 16, 0x2F72, 0x79BE, 0, - 16, 0x2F73, 0x7A74, 0, - 16, 0x2F74, 0x7ACB, 0, - 16, 0x2F75, 0x7AF9, 0, - 16, 0x2F76, 0x7C73, 0, - 16, 0x2F77, 0x7CF8, 0, - 16, 0x2F78, 0x7F36, 0, - 16, 0x2F79, 0x7F51, 0, - 16, 0x2F7A, 0x7F8A, 0, - 16, 0x2F7B, 0x7FBD, 0, - 16, 0x2F7C, 0x8001, 0, - 16, 0x2F7D, 0x800C, 0, - 16, 0x2F7E, 0x8012, 0, - 16, 0x2F7F, 0x8033, 0, - 16, 0x2F80, 0x807F, 0, - 16, 0x2F81, 0x8089, 0, - 16, 0x2F82, 0x81E3, 0, - 16, 0x2F83, 0x81EA, 0, - 16, 0x2F84, 0x81F3, 0, - 16, 0x2F85, 0x81FC, 0, - 16, 0x2F86, 0x820C, 0, - 16, 0x2F87, 0x821B, 0, - 16, 0x2F88, 0x821F, 0, - 16, 0x2F89, 0x826E, 0, - 16, 0x2F8A, 0x8272, 0, - 16, 0x2F8B, 0x8278, 0, - 16, 0x2F8C, 0x864D, 0, - 16, 0x2F8D, 0x866B, 0, - 16, 0x2F8E, 0x8840, 0, - 16, 0x2F8F, 0x884C, 0, - 16, 0x2F90, 0x8863, 0, - 16, 0x2F91, 0x897E, 0, - 16, 0x2F92, 0x898B, 0, - 16, 0x2F93, 0x89D2, 0, - 16, 0x2F94, 0x8A00, 0, - 16, 0x2F95, 0x8C37, 0, - 16, 0x2F96, 0x8C46, 0, - 16, 0x2F97, 0x8C55, 0, - 16, 0x2F98, 0x8C78, 0, - 16, 0x2F99, 0x8C9D, 0, - 16, 0x2F9A, 0x8D64, 0, - 16, 0x2F9B, 0x8D70, 0, - 16, 0x2F9C, 0x8DB3, 0, - 16, 0x2F9D, 0x8EAB, 0, - 16, 0x2F9E, 0x8ECA, 0, - 16, 0x2F9F, 0x8F9B, 0, - 16, 0x2FA0, 0x8FB0, 0, - 16, 0x2FA1, 0x8FB5, 0, - 16, 0x2FA2, 0x9091, 0, - 16, 0x2FA3, 0x9149, 0, - 16, 0x2FA4, 0x91C6, 0, - 16, 0x2FA5, 0x91CC, 0, - 16, 0x2FA6, 0x91D1, 0, - 16, 0x2FA7, 0x9577, 0, - 16, 0x2FA8, 0x9580, 0, - 16, 0x2FA9, 0x961C, 0, - 16, 0x2FAA, 0x96B6, 0, - 16, 0x2FAB, 0x96B9, 0, - 16, 0x2FAC, 0x96E8, 0, - 16, 0x2FAD, 0x9751, 0, - 16, 0x2FAE, 0x975E, 0, - 16, 0x2FAF, 0x9762, 0, - 16, 0x2FB0, 0x9769, 0, - 16, 0x2FB1, 0x97CB, 0, - 16, 0x2FB2, 0x97ED, 0, - 16, 0x2FB3, 0x97F3, 0, - 16, 0x2FB4, 0x9801, 0, - 16, 0x2FB5, 0x98A8, 0, - 16, 0x2FB6, 0x98DB, 0, - 16, 0x2FB7, 0x98DF, 0, - 16, 0x2FB8, 0x9996, 0, - 16, 0x2FB9, 0x9999, 0, - 16, 0x2FBA, 0x99AC, 0, - 16, 0x2FBB, 0x9AA8, 0, - 16, 0x2FBC, 0x9AD8, 0, - 16, 0x2FBD, 0x9ADF, 0, - 16, 0x2FBE, 0x9B25, 0, - 16, 0x2FBF, 0x9B2F, 0, - 16, 0x2FC0, 0x9B32, 0, - 16, 0x2FC1, 0x9B3C, 0, - 16, 0x2FC2, 0x9B5A, 0, - 16, 0x2FC3, 0x9CE5, 0, - 16, 0x2FC4, 0x9E75, 0, - 16, 0x2FC5, 0x9E7F, 0, - 16, 0x2FC6, 0x9EA5, 0, - 16, 0x2FC7, 0x9EBB, 0, - 16, 0x2FC8, 0x9EC3, 0, - 16, 0x2FC9, 0x9ECD, 0, - 16, 0x2FCA, 0x9ED1, 0, - 16, 0x2FCB, 0x9EF9, 0, - 16, 0x2FCC, 0x9EFD, 0, - 16, 0x2FCD, 0x9F0E, 0, - 16, 0x2FCE, 0x9F13, 0, - 16, 0x2FCF, 0x9F20, 0, - 16, 0x2FD0, 0x9F3B, 0, - 16, 0x2FD1, 0x9F4A, 0, - 16, 0x2FD2, 0x9F52, 0, - 16, 0x2FD3, 0x9F8D, 0, - 16, 0x2FD4, 0x9F9C, 0, - 16, 0x2FD5, 0x9FA0, 0, - 12, 0x3000, 0x0020, 0, - 16, 0x3036, 0x3012, 0, - 16, 0x3038, 0x5341, 0, - 16, 0x3039, 0x5344, 0, - 16, 0x303A, 0x5345, 0, - 1, 0x304C, 0x304B, 0x3099, 0, - 1, 0x304E, 0x304D, 0x3099, 0, - 1, 0x3050, 0x304F, 0x3099, 0, - 1, 0x3052, 0x3051, 0x3099, 0, - 1, 0x3054, 0x3053, 0x3099, 0, - 1, 0x3056, 0x3055, 0x3099, 0, - 1, 0x3058, 0x3057, 0x3099, 0, - 1, 0x305A, 0x3059, 0x3099, 0, - 1, 0x305C, 0x305B, 0x3099, 0, - 1, 0x305E, 0x305D, 0x3099, 0, - 1, 0x3060, 0x305F, 0x3099, 0, - 1, 0x3062, 0x3061, 0x3099, 0, - 1, 0x3065, 0x3064, 0x3099, 0, - 1, 0x3067, 0x3066, 0x3099, 0, - 1, 0x3069, 0x3068, 0x3099, 0, - 1, 0x3070, 0x306F, 0x3099, 0, - 1, 0x3071, 0x306F, 0x309A, 0, - 1, 0x3073, 0x3072, 0x3099, 0, - 1, 0x3074, 0x3072, 0x309A, 0, - 1, 0x3076, 0x3075, 0x3099, 0, - 1, 0x3077, 0x3075, 0x309A, 0, - 1, 0x3079, 0x3078, 0x3099, 0, - 1, 0x307A, 0x3078, 0x309A, 0, - 1, 0x307C, 0x307B, 0x3099, 0, - 1, 0x307D, 0x307B, 0x309A, 0, - 1, 0x3094, 0x3046, 0x3099, 0, - 16, 0x309B, 0x0020, 0x3099, 0, - 16, 0x309C, 0x0020, 0x309A, 0, - 1, 0x309E, 0x309D, 0x3099, 0, - 11, 0x309F, 0x3088, 0x308A, 0, - 1, 0x30AC, 0x30AB, 0x3099, 0, - 1, 0x30AE, 0x30AD, 0x3099, 0, - 1, 0x30B0, 0x30AF, 0x3099, 0, - 1, 0x30B2, 0x30B1, 0x3099, 0, - 1, 0x30B4, 0x30B3, 0x3099, 0, - 1, 0x30B6, 0x30B5, 0x3099, 0, - 1, 0x30B8, 0x30B7, 0x3099, 0, - 1, 0x30BA, 0x30B9, 0x3099, 0, - 1, 0x30BC, 0x30BB, 0x3099, 0, - 1, 0x30BE, 0x30BD, 0x3099, 0, - 1, 0x30C0, 0x30BF, 0x3099, 0, - 1, 0x30C2, 0x30C1, 0x3099, 0, - 1, 0x30C5, 0x30C4, 0x3099, 0, - 1, 0x30C7, 0x30C6, 0x3099, 0, - 1, 0x30C9, 0x30C8, 0x3099, 0, - 1, 0x30D0, 0x30CF, 0x3099, 0, - 1, 0x30D1, 0x30CF, 0x309A, 0, - 1, 0x30D3, 0x30D2, 0x3099, 0, - 1, 0x30D4, 0x30D2, 0x309A, 0, - 1, 0x30D6, 0x30D5, 0x3099, 0, - 1, 0x30D7, 0x30D5, 0x309A, 0, - 1, 0x30D9, 0x30D8, 0x3099, 0, - 1, 0x30DA, 0x30D8, 0x309A, 0, - 1, 0x30DC, 0x30DB, 0x3099, 0, - 1, 0x30DD, 0x30DB, 0x309A, 0, - 1, 0x30F4, 0x30A6, 0x3099, 0, - 1, 0x30F7, 0x30EF, 0x3099, 0, - 1, 0x30F8, 0x30F0, 0x3099, 0, - 1, 0x30F9, 0x30F1, 0x3099, 0, - 1, 0x30FA, 0x30F2, 0x3099, 0, - 1, 0x30FE, 0x30FD, 0x3099, 0, - 11, 0x30FF, 0x30B3, 0x30C8, 0, - 16, 0x3131, 0x1100, 0, - 16, 0x3132, 0x1101, 0, - 16, 0x3133, 0x11AA, 0, - 16, 0x3134, 0x1102, 0, - 16, 0x3135, 0x11AC, 0, - 16, 0x3136, 0x11AD, 0, - 16, 0x3137, 0x1103, 0, - 16, 0x3138, 0x1104, 0, - 16, 0x3139, 0x1105, 0, - 16, 0x313A, 0x11B0, 0, - 16, 0x313B, 0x11B1, 0, - 16, 0x313C, 0x11B2, 0, - 16, 0x313D, 0x11B3, 0, - 16, 0x313E, 0x11B4, 0, - 16, 0x313F, 0x11B5, 0, - 16, 0x3140, 0x111A, 0, - 16, 0x3141, 0x1106, 0, - 16, 0x3142, 0x1107, 0, - 16, 0x3143, 0x1108, 0, - 16, 0x3144, 0x1121, 0, - 16, 0x3145, 0x1109, 0, - 16, 0x3146, 0x110A, 0, - 16, 0x3147, 0x110B, 0, - 16, 0x3148, 0x110C, 0, - 16, 0x3149, 0x110D, 0, - 16, 0x314A, 0x110E, 0, - 16, 0x314B, 0x110F, 0, - 16, 0x314C, 0x1110, 0, - 16, 0x314D, 0x1111, 0, - 16, 0x314E, 0x1112, 0, - 16, 0x314F, 0x1161, 0, - 16, 0x3150, 0x1162, 0, - 16, 0x3151, 0x1163, 0, - 16, 0x3152, 0x1164, 0, - 16, 0x3153, 0x1165, 0, - 16, 0x3154, 0x1166, 0, - 16, 0x3155, 0x1167, 0, - 16, 0x3156, 0x1168, 0, - 16, 0x3157, 0x1169, 0, - 16, 0x3158, 0x116A, 0, - 16, 0x3159, 0x116B, 0, - 16, 0x315A, 0x116C, 0, - 16, 0x315B, 0x116D, 0, - 16, 0x315C, 0x116E, 0, - 16, 0x315D, 0x116F, 0, - 16, 0x315E, 0x1170, 0, - 16, 0x315F, 0x1171, 0, - 16, 0x3160, 0x1172, 0, - 16, 0x3161, 0x1173, 0, - 16, 0x3162, 0x1174, 0, - 16, 0x3163, 0x1175, 0, - 16, 0x3164, 0x1160, 0, - 16, 0x3165, 0x1114, 0, - 16, 0x3166, 0x1115, 0, - 16, 0x3167, 0x11C7, 0, - 16, 0x3168, 0x11C8, 0, - 16, 0x3169, 0x11CC, 0, - 16, 0x316A, 0x11CE, 0, - 16, 0x316B, 0x11D3, 0, - 16, 0x316C, 0x11D7, 0, - 16, 0x316D, 0x11D9, 0, - 16, 0x316E, 0x111C, 0, - 16, 0x316F, 0x11DD, 0, - 16, 0x3170, 0x11DF, 0, - 16, 0x3171, 0x111D, 0, - 16, 0x3172, 0x111E, 0, - 16, 0x3173, 0x1120, 0, - 16, 0x3174, 0x1122, 0, - 16, 0x3175, 0x1123, 0, - 16, 0x3176, 0x1127, 0, - 16, 0x3177, 0x1129, 0, - 16, 0x3178, 0x112B, 0, - 16, 0x3179, 0x112C, 0, - 16, 0x317A, 0x112D, 0, - 16, 0x317B, 0x112E, 0, - 16, 0x317C, 0x112F, 0, - 16, 0x317D, 0x1132, 0, - 16, 0x317E, 0x1136, 0, - 16, 0x317F, 0x1140, 0, - 16, 0x3180, 0x1147, 0, - 16, 0x3181, 0x114C, 0, - 16, 0x3182, 0x11F1, 0, - 16, 0x3183, 0x11F2, 0, - 16, 0x3184, 0x1157, 0, - 16, 0x3185, 0x1158, 0, - 16, 0x3186, 0x1159, 0, - 16, 0x3187, 0x1184, 0, - 16, 0x3188, 0x1185, 0, - 16, 0x3189, 0x1188, 0, - 16, 0x318A, 0x1191, 0, - 16, 0x318B, 0x1192, 0, - 16, 0x318C, 0x1194, 0, - 16, 0x318D, 0x119E, 0, - 16, 0x318E, 0x11A1, 0, - 9, 0x3192, 0x4E00, 0, - 9, 0x3193, 0x4E8C, 0, - 9, 0x3194, 0x4E09, 0, - 9, 0x3195, 0x56DB, 0, - 9, 0x3196, 0x4E0A, 0, - 9, 0x3197, 0x4E2D, 0, - 9, 0x3198, 0x4E0B, 0, - 9, 0x3199, 0x7532, 0, - 9, 0x319A, 0x4E59, 0, - 9, 0x319B, 0x4E19, 0, - 9, 0x319C, 0x4E01, 0, - 9, 0x319D, 0x5929, 0, - 9, 0x319E, 0x5730, 0, - 9, 0x319F, 0x4EBA, 0, - 16, 0x3200, 0x0028, 0x1100, 0x0029, 0, - 16, 0x3201, 0x0028, 0x1102, 0x0029, 0, - 16, 0x3202, 0x0028, 0x1103, 0x0029, 0, - 16, 0x3203, 0x0028, 0x1105, 0x0029, 0, - 16, 0x3204, 0x0028, 0x1106, 0x0029, 0, - 16, 0x3205, 0x0028, 0x1107, 0x0029, 0, - 16, 0x3206, 0x0028, 0x1109, 0x0029, 0, - 16, 0x3207, 0x0028, 0x110B, 0x0029, 0, - 16, 0x3208, 0x0028, 0x110C, 0x0029, 0, - 16, 0x3209, 0x0028, 0x110E, 0x0029, 0, - 16, 0x320A, 0x0028, 0x110F, 0x0029, 0, - 16, 0x320B, 0x0028, 0x1110, 0x0029, 0, - 16, 0x320C, 0x0028, 0x1111, 0x0029, 0, - 16, 0x320D, 0x0028, 0x1112, 0x0029, 0, - 16, 0x320E, 0x0028, 0x1100, 0x1161, 0x0029, 0, - 16, 0x320F, 0x0028, 0x1102, 0x1161, 0x0029, 0, - 16, 0x3210, 0x0028, 0x1103, 0x1161, 0x0029, 0, - 16, 0x3211, 0x0028, 0x1105, 0x1161, 0x0029, 0, - 16, 0x3212, 0x0028, 0x1106, 0x1161, 0x0029, 0, - 16, 0x3213, 0x0028, 0x1107, 0x1161, 0x0029, 0, - 16, 0x3214, 0x0028, 0x1109, 0x1161, 0x0029, 0, - 16, 0x3215, 0x0028, 0x110B, 0x1161, 0x0029, 0, - 16, 0x3216, 0x0028, 0x110C, 0x1161, 0x0029, 0, - 16, 0x3217, 0x0028, 0x110E, 0x1161, 0x0029, 0, - 16, 0x3218, 0x0028, 0x110F, 0x1161, 0x0029, 0, - 16, 0x3219, 0x0028, 0x1110, 0x1161, 0x0029, 0, - 16, 0x321A, 0x0028, 0x1111, 0x1161, 0x0029, 0, - 16, 0x321B, 0x0028, 0x1112, 0x1161, 0x0029, 0, - 16, 0x321C, 0x0028, 0x110C, 0x116E, 0x0029, 0, - 16, 0x3220, 0x0028, 0x4E00, 0x0029, 0, - 16, 0x3221, 0x0028, 0x4E8C, 0x0029, 0, - 16, 0x3222, 0x0028, 0x4E09, 0x0029, 0, - 16, 0x3223, 0x0028, 0x56DB, 0x0029, 0, - 16, 0x3224, 0x0028, 0x4E94, 0x0029, 0, - 16, 0x3225, 0x0028, 0x516D, 0x0029, 0, - 16, 0x3226, 0x0028, 0x4E03, 0x0029, 0, - 16, 0x3227, 0x0028, 0x516B, 0x0029, 0, - 16, 0x3228, 0x0028, 0x4E5D, 0x0029, 0, - 16, 0x3229, 0x0028, 0x5341, 0x0029, 0, - 16, 0x322A, 0x0028, 0x6708, 0x0029, 0, - 16, 0x322B, 0x0028, 0x706B, 0x0029, 0, - 16, 0x322C, 0x0028, 0x6C34, 0x0029, 0, - 16, 0x322D, 0x0028, 0x6728, 0x0029, 0, - 16, 0x322E, 0x0028, 0x91D1, 0x0029, 0, - 16, 0x322F, 0x0028, 0x571F, 0x0029, 0, - 16, 0x3230, 0x0028, 0x65E5, 0x0029, 0, - 16, 0x3231, 0x0028, 0x682A, 0x0029, 0, - 16, 0x3232, 0x0028, 0x6709, 0x0029, 0, - 16, 0x3233, 0x0028, 0x793E, 0x0029, 0, - 16, 0x3234, 0x0028, 0x540D, 0x0029, 0, - 16, 0x3235, 0x0028, 0x7279, 0x0029, 0, - 16, 0x3236, 0x0028, 0x8CA1, 0x0029, 0, - 16, 0x3237, 0x0028, 0x795D, 0x0029, 0, - 16, 0x3238, 0x0028, 0x52B4, 0x0029, 0, - 16, 0x3239, 0x0028, 0x4EE3, 0x0029, 0, - 16, 0x323A, 0x0028, 0x547C, 0x0029, 0, - 16, 0x323B, 0x0028, 0x5B66, 0x0029, 0, - 16, 0x323C, 0x0028, 0x76E3, 0x0029, 0, - 16, 0x323D, 0x0028, 0x4F01, 0x0029, 0, - 16, 0x323E, 0x0028, 0x8CC7, 0x0029, 0, - 16, 0x323F, 0x0028, 0x5354, 0x0029, 0, - 16, 0x3240, 0x0028, 0x796D, 0x0029, 0, - 16, 0x3241, 0x0028, 0x4F11, 0x0029, 0, - 16, 0x3242, 0x0028, 0x81EA, 0x0029, 0, - 16, 0x3243, 0x0028, 0x81F3, 0x0029, 0, - 8, 0x3251, 0x0032, 0x0031, 0, - 8, 0x3252, 0x0032, 0x0032, 0, - 8, 0x3253, 0x0032, 0x0033, 0, - 8, 0x3254, 0x0032, 0x0034, 0, - 8, 0x3255, 0x0032, 0x0035, 0, - 8, 0x3256, 0x0032, 0x0036, 0, - 8, 0x3257, 0x0032, 0x0037, 0, - 8, 0x3258, 0x0032, 0x0038, 0, - 8, 0x3259, 0x0032, 0x0039, 0, - 8, 0x325A, 0x0033, 0x0030, 0, - 8, 0x325B, 0x0033, 0x0031, 0, - 8, 0x325C, 0x0033, 0x0032, 0, - 8, 0x325D, 0x0033, 0x0033, 0, - 8, 0x325E, 0x0033, 0x0034, 0, - 8, 0x325F, 0x0033, 0x0035, 0, - 8, 0x3260, 0x1100, 0, - 8, 0x3261, 0x1102, 0, - 8, 0x3262, 0x1103, 0, - 8, 0x3263, 0x1105, 0, - 8, 0x3264, 0x1106, 0, - 8, 0x3265, 0x1107, 0, - 8, 0x3266, 0x1109, 0, - 8, 0x3267, 0x110B, 0, - 8, 0x3268, 0x110C, 0, - 8, 0x3269, 0x110E, 0, - 8, 0x326A, 0x110F, 0, - 8, 0x326B, 0x1110, 0, - 8, 0x326C, 0x1111, 0, - 8, 0x326D, 0x1112, 0, - 8, 0x326E, 0x1100, 0x1161, 0, - 8, 0x326F, 0x1102, 0x1161, 0, - 8, 0x3270, 0x1103, 0x1161, 0, - 8, 0x3271, 0x1105, 0x1161, 0, - 8, 0x3272, 0x1106, 0x1161, 0, - 8, 0x3273, 0x1107, 0x1161, 0, - 8, 0x3274, 0x1109, 0x1161, 0, - 8, 0x3275, 0x110B, 0x1161, 0, - 8, 0x3276, 0x110C, 0x1161, 0, - 8, 0x3277, 0x110E, 0x1161, 0, - 8, 0x3278, 0x110F, 0x1161, 0, - 8, 0x3279, 0x1110, 0x1161, 0, - 8, 0x327A, 0x1111, 0x1161, 0, - 8, 0x327B, 0x1112, 0x1161, 0, - 8, 0x3280, 0x4E00, 0, - 8, 0x3281, 0x4E8C, 0, - 8, 0x3282, 0x4E09, 0, - 8, 0x3283, 0x56DB, 0, - 8, 0x3284, 0x4E94, 0, - 8, 0x3285, 0x516D, 0, - 8, 0x3286, 0x4E03, 0, - 8, 0x3287, 0x516B, 0, - 8, 0x3288, 0x4E5D, 0, - 8, 0x3289, 0x5341, 0, - 8, 0x328A, 0x6708, 0, - 8, 0x328B, 0x706B, 0, - 8, 0x328C, 0x6C34, 0, - 8, 0x328D, 0x6728, 0, - 8, 0x328E, 0x91D1, 0, - 8, 0x328F, 0x571F, 0, - 8, 0x3290, 0x65E5, 0, - 8, 0x3291, 0x682A, 0, - 8, 0x3292, 0x6709, 0, - 8, 0x3293, 0x793E, 0, - 8, 0x3294, 0x540D, 0, - 8, 0x3295, 0x7279, 0, - 8, 0x3296, 0x8CA1, 0, - 8, 0x3297, 0x795D, 0, - 8, 0x3298, 0x52B4, 0, - 8, 0x3299, 0x79D8, 0, - 8, 0x329A, 0x7537, 0, - 8, 0x329B, 0x5973, 0, - 8, 0x329C, 0x9069, 0, - 8, 0x329D, 0x512A, 0, - 8, 0x329E, 0x5370, 0, - 8, 0x329F, 0x6CE8, 0, - 8, 0x32A0, 0x9805, 0, - 8, 0x32A1, 0x4F11, 0, - 8, 0x32A2, 0x5199, 0, - 8, 0x32A3, 0x6B63, 0, - 8, 0x32A4, 0x4E0A, 0, - 8, 0x32A5, 0x4E2D, 0, - 8, 0x32A6, 0x4E0B, 0, - 8, 0x32A7, 0x5DE6, 0, - 8, 0x32A8, 0x53F3, 0, - 8, 0x32A9, 0x533B, 0, - 8, 0x32AA, 0x5B97, 0, - 8, 0x32AB, 0x5B66, 0, - 8, 0x32AC, 0x76E3, 0, - 8, 0x32AD, 0x4F01, 0, - 8, 0x32AE, 0x8CC7, 0, - 8, 0x32AF, 0x5354, 0, - 8, 0x32B0, 0x591C, 0, - 8, 0x32B1, 0x0033, 0x0036, 0, - 8, 0x32B2, 0x0033, 0x0037, 0, - 8, 0x32B3, 0x0033, 0x0038, 0, - 8, 0x32B4, 0x0033, 0x0039, 0, - 8, 0x32B5, 0x0034, 0x0030, 0, - 8, 0x32B6, 0x0034, 0x0031, 0, - 8, 0x32B7, 0x0034, 0x0032, 0, - 8, 0x32B8, 0x0034, 0x0033, 0, - 8, 0x32B9, 0x0034, 0x0034, 0, - 8, 0x32BA, 0x0034, 0x0035, 0, - 8, 0x32BB, 0x0034, 0x0036, 0, - 8, 0x32BC, 0x0034, 0x0037, 0, - 8, 0x32BD, 0x0034, 0x0038, 0, - 8, 0x32BE, 0x0034, 0x0039, 0, - 8, 0x32BF, 0x0035, 0x0030, 0, - 16, 0x32C0, 0x0031, 0x6708, 0, - 16, 0x32C1, 0x0032, 0x6708, 0, - 16, 0x32C2, 0x0033, 0x6708, 0, - 16, 0x32C3, 0x0034, 0x6708, 0, - 16, 0x32C4, 0x0035, 0x6708, 0, - 16, 0x32C5, 0x0036, 0x6708, 0, - 16, 0x32C6, 0x0037, 0x6708, 0, - 16, 0x32C7, 0x0038, 0x6708, 0, - 16, 0x32C8, 0x0039, 0x6708, 0, - 16, 0x32C9, 0x0031, 0x0030, 0x6708, 0, - 16, 0x32CA, 0x0031, 0x0031, 0x6708, 0, - 16, 0x32CB, 0x0031, 0x0032, 0x6708, 0, - 8, 0x32D0, 0x30A2, 0, - 8, 0x32D1, 0x30A4, 0, - 8, 0x32D2, 0x30A6, 0, - 8, 0x32D3, 0x30A8, 0, - 8, 0x32D4, 0x30AA, 0, - 8, 0x32D5, 0x30AB, 0, - 8, 0x32D6, 0x30AD, 0, - 8, 0x32D7, 0x30AF, 0, - 8, 0x32D8, 0x30B1, 0, - 8, 0x32D9, 0x30B3, 0, - 8, 0x32DA, 0x30B5, 0, - 8, 0x32DB, 0x30B7, 0, - 8, 0x32DC, 0x30B9, 0, - 8, 0x32DD, 0x30BB, 0, - 8, 0x32DE, 0x30BD, 0, - 8, 0x32DF, 0x30BF, 0, - 8, 0x32E0, 0x30C1, 0, - 8, 0x32E1, 0x30C4, 0, - 8, 0x32E2, 0x30C6, 0, - 8, 0x32E3, 0x30C8, 0, - 8, 0x32E4, 0x30CA, 0, - 8, 0x32E5, 0x30CB, 0, - 8, 0x32E6, 0x30CC, 0, - 8, 0x32E7, 0x30CD, 0, - 8, 0x32E8, 0x30CE, 0, - 8, 0x32E9, 0x30CF, 0, - 8, 0x32EA, 0x30D2, 0, - 8, 0x32EB, 0x30D5, 0, - 8, 0x32EC, 0x30D8, 0, - 8, 0x32ED, 0x30DB, 0, - 8, 0x32EE, 0x30DE, 0, - 8, 0x32EF, 0x30DF, 0, - 8, 0x32F0, 0x30E0, 0, - 8, 0x32F1, 0x30E1, 0, - 8, 0x32F2, 0x30E2, 0, - 8, 0x32F3, 0x30E4, 0, - 8, 0x32F4, 0x30E6, 0, - 8, 0x32F5, 0x30E8, 0, - 8, 0x32F6, 0x30E9, 0, - 8, 0x32F7, 0x30EA, 0, - 8, 0x32F8, 0x30EB, 0, - 8, 0x32F9, 0x30EC, 0, - 8, 0x32FA, 0x30ED, 0, - 8, 0x32FB, 0x30EF, 0, - 8, 0x32FC, 0x30F0, 0, - 8, 0x32FD, 0x30F1, 0, - 8, 0x32FE, 0x30F2, 0, - 15, 0x3300, 0x30A2, 0x30D1, 0x30FC, 0x30C8, 0, - 15, 0x3301, 0x30A2, 0x30EB, 0x30D5, 0x30A1, 0, - 15, 0x3302, 0x30A2, 0x30F3, 0x30DA, 0x30A2, 0, - 15, 0x3303, 0x30A2, 0x30FC, 0x30EB, 0, - 15, 0x3304, 0x30A4, 0x30CB, 0x30F3, 0x30B0, 0, - 15, 0x3305, 0x30A4, 0x30F3, 0x30C1, 0, - 15, 0x3306, 0x30A6, 0x30A9, 0x30F3, 0, - 15, 0x3307, 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9, 0, - 15, 0x3308, 0x30A8, 0x30FC, 0x30AB, 0x30FC, 0, - 15, 0x3309, 0x30AA, 0x30F3, 0x30B9, 0, - 15, 0x330A, 0x30AA, 0x30FC, 0x30E0, 0, - 15, 0x330B, 0x30AB, 0x30A4, 0x30EA, 0, - 15, 0x330C, 0x30AB, 0x30E9, 0x30C3, 0x30C8, 0, - 15, 0x330D, 0x30AB, 0x30ED, 0x30EA, 0x30FC, 0, - 15, 0x330E, 0x30AC, 0x30ED, 0x30F3, 0, - 15, 0x330F, 0x30AC, 0x30F3, 0x30DE, 0, - 15, 0x3310, 0x30AE, 0x30AC, 0, - 15, 0x3311, 0x30AE, 0x30CB, 0x30FC, 0, - 15, 0x3312, 0x30AD, 0x30E5, 0x30EA, 0x30FC, 0, - 15, 0x3313, 0x30AE, 0x30EB, 0x30C0, 0x30FC, 0, - 15, 0x3314, 0x30AD, 0x30ED, 0, - 15, 0x3315, 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0, 0, - 15, 0x3316, 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0, - 15, 0x3317, 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8, 0, - 15, 0x3318, 0x30B0, 0x30E9, 0x30E0, 0, - 15, 0x3319, 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3, 0, - 15, 0x331A, 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED, 0, - 15, 0x331B, 0x30AF, 0x30ED, 0x30FC, 0x30CD, 0, - 15, 0x331C, 0x30B1, 0x30FC, 0x30B9, 0, - 15, 0x331D, 0x30B3, 0x30EB, 0x30CA, 0, - 15, 0x331E, 0x30B3, 0x30FC, 0x30DD, 0, - 15, 0x331F, 0x30B5, 0x30A4, 0x30AF, 0x30EB, 0, - 15, 0x3320, 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0, 0, - 15, 0x3321, 0x30B7, 0x30EA, 0x30F3, 0x30B0, 0, - 15, 0x3322, 0x30BB, 0x30F3, 0x30C1, 0, - 15, 0x3323, 0x30BB, 0x30F3, 0x30C8, 0, - 15, 0x3324, 0x30C0, 0x30FC, 0x30B9, 0, - 15, 0x3325, 0x30C7, 0x30B7, 0, - 15, 0x3326, 0x30C9, 0x30EB, 0, - 15, 0x3327, 0x30C8, 0x30F3, 0, - 15, 0x3328, 0x30CA, 0x30CE, 0, - 15, 0x3329, 0x30CE, 0x30C3, 0x30C8, 0, - 15, 0x332A, 0x30CF, 0x30A4, 0x30C4, 0, - 15, 0x332B, 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8, 0, - 15, 0x332C, 0x30D1, 0x30FC, 0x30C4, 0, - 15, 0x332D, 0x30D0, 0x30FC, 0x30EC, 0x30EB, 0, - 15, 0x332E, 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB, 0, - 15, 0x332F, 0x30D4, 0x30AF, 0x30EB, 0, - 15, 0x3330, 0x30D4, 0x30B3, 0, - 15, 0x3331, 0x30D3, 0x30EB, 0, - 15, 0x3332, 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9, 0, - 15, 0x3333, 0x30D5, 0x30A3, 0x30FC, 0x30C8, 0, - 15, 0x3334, 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB, 0, - 15, 0x3335, 0x30D5, 0x30E9, 0x30F3, 0, - 15, 0x3336, 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB, 0, - 15, 0x3337, 0x30DA, 0x30BD, 0, - 15, 0x3338, 0x30DA, 0x30CB, 0x30D2, 0, - 15, 0x3339, 0x30D8, 0x30EB, 0x30C4, 0, - 15, 0x333A, 0x30DA, 0x30F3, 0x30B9, 0, - 15, 0x333B, 0x30DA, 0x30FC, 0x30B8, 0, - 15, 0x333C, 0x30D9, 0x30FC, 0x30BF, 0, - 15, 0x333D, 0x30DD, 0x30A4, 0x30F3, 0x30C8, 0, - 15, 0x333E, 0x30DC, 0x30EB, 0x30C8, 0, - 15, 0x333F, 0x30DB, 0x30F3, 0, - 15, 0x3340, 0x30DD, 0x30F3, 0x30C9, 0, - 15, 0x3341, 0x30DB, 0x30FC, 0x30EB, 0, - 15, 0x3342, 0x30DB, 0x30FC, 0x30F3, 0, - 15, 0x3343, 0x30DE, 0x30A4, 0x30AF, 0x30ED, 0, - 15, 0x3344, 0x30DE, 0x30A4, 0x30EB, 0, - 15, 0x3345, 0x30DE, 0x30C3, 0x30CF, 0, - 15, 0x3346, 0x30DE, 0x30EB, 0x30AF, 0, - 15, 0x3347, 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3, 0, - 15, 0x3348, 0x30DF, 0x30AF, 0x30ED, 0x30F3, 0, - 15, 0x3349, 0x30DF, 0x30EA, 0, - 15, 0x334A, 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB, 0, - 15, 0x334B, 0x30E1, 0x30AC, 0, - 15, 0x334C, 0x30E1, 0x30AC, 0x30C8, 0x30F3, 0, - 15, 0x334D, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0, - 15, 0x334E, 0x30E4, 0x30FC, 0x30C9, 0, - 15, 0x334F, 0x30E4, 0x30FC, 0x30EB, 0, - 15, 0x3350, 0x30E6, 0x30A2, 0x30F3, 0, - 15, 0x3351, 0x30EA, 0x30C3, 0x30C8, 0x30EB, 0, - 15, 0x3352, 0x30EA, 0x30E9, 0, - 15, 0x3353, 0x30EB, 0x30D4, 0x30FC, 0, - 15, 0x3354, 0x30EB, 0x30FC, 0x30D6, 0x30EB, 0, - 15, 0x3355, 0x30EC, 0x30E0, 0, - 15, 0x3356, 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3, 0, - 15, 0x3357, 0x30EF, 0x30C3, 0x30C8, 0, - 16, 0x3358, 0x0030, 0x70B9, 0, - 16, 0x3359, 0x0031, 0x70B9, 0, - 16, 0x335A, 0x0032, 0x70B9, 0, - 16, 0x335B, 0x0033, 0x70B9, 0, - 16, 0x335C, 0x0034, 0x70B9, 0, - 16, 0x335D, 0x0035, 0x70B9, 0, - 16, 0x335E, 0x0036, 0x70B9, 0, - 16, 0x335F, 0x0037, 0x70B9, 0, - 16, 0x3360, 0x0038, 0x70B9, 0, - 16, 0x3361, 0x0039, 0x70B9, 0, - 16, 0x3362, 0x0031, 0x0030, 0x70B9, 0, - 16, 0x3363, 0x0031, 0x0031, 0x70B9, 0, - 16, 0x3364, 0x0031, 0x0032, 0x70B9, 0, - 16, 0x3365, 0x0031, 0x0033, 0x70B9, 0, - 16, 0x3366, 0x0031, 0x0034, 0x70B9, 0, - 16, 0x3367, 0x0031, 0x0035, 0x70B9, 0, - 16, 0x3368, 0x0031, 0x0036, 0x70B9, 0, - 16, 0x3369, 0x0031, 0x0037, 0x70B9, 0, - 16, 0x336A, 0x0031, 0x0038, 0x70B9, 0, - 16, 0x336B, 0x0031, 0x0039, 0x70B9, 0, - 16, 0x336C, 0x0032, 0x0030, 0x70B9, 0, - 16, 0x336D, 0x0032, 0x0031, 0x70B9, 0, - 16, 0x336E, 0x0032, 0x0032, 0x70B9, 0, - 16, 0x336F, 0x0032, 0x0033, 0x70B9, 0, - 16, 0x3370, 0x0032, 0x0034, 0x70B9, 0, - 15, 0x3371, 0x0068, 0x0050, 0x0061, 0, - 15, 0x3372, 0x0064, 0x0061, 0, - 15, 0x3373, 0x0041, 0x0055, 0, - 15, 0x3374, 0x0062, 0x0061, 0x0072, 0, - 15, 0x3375, 0x006F, 0x0056, 0, - 15, 0x3376, 0x0070, 0x0063, 0, - 15, 0x337B, 0x5E73, 0x6210, 0, - 15, 0x337C, 0x662D, 0x548C, 0, - 15, 0x337D, 0x5927, 0x6B63, 0, - 15, 0x337E, 0x660E, 0x6CBB, 0, - 15, 0x337F, 0x682A, 0x5F0F, 0x4F1A, 0x793E, 0, - 15, 0x3380, 0x0070, 0x0041, 0, - 15, 0x3381, 0x006E, 0x0041, 0, - 15, 0x3382, 0x03BC, 0x0041, 0, - 15, 0x3383, 0x006D, 0x0041, 0, - 15, 0x3384, 0x006B, 0x0041, 0, - 15, 0x3385, 0x004B, 0x0042, 0, - 15, 0x3386, 0x004D, 0x0042, 0, - 15, 0x3387, 0x0047, 0x0042, 0, - 15, 0x3388, 0x0063, 0x0061, 0x006C, 0, - 15, 0x3389, 0x006B, 0x0063, 0x0061, 0x006C, 0, - 15, 0x338A, 0x0070, 0x0046, 0, - 15, 0x338B, 0x006E, 0x0046, 0, - 15, 0x338C, 0x03BC, 0x0046, 0, - 15, 0x338D, 0x03BC, 0x0067, 0, - 15, 0x338E, 0x006D, 0x0067, 0, - 15, 0x338F, 0x006B, 0x0067, 0, - 15, 0x3390, 0x0048, 0x007A, 0, - 15, 0x3391, 0x006B, 0x0048, 0x007A, 0, - 15, 0x3392, 0x004D, 0x0048, 0x007A, 0, - 15, 0x3393, 0x0047, 0x0048, 0x007A, 0, - 15, 0x3394, 0x0054, 0x0048, 0x007A, 0, - 15, 0x3395, 0x03BC, 0x2113, 0, - 15, 0x3396, 0x006D, 0x2113, 0, - 15, 0x3397, 0x0064, 0x2113, 0, - 15, 0x3398, 0x006B, 0x2113, 0, - 15, 0x3399, 0x0066, 0x006D, 0, - 15, 0x339A, 0x006E, 0x006D, 0, - 15, 0x339B, 0x03BC, 0x006D, 0, - 15, 0x339C, 0x006D, 0x006D, 0, - 15, 0x339D, 0x0063, 0x006D, 0, - 15, 0x339E, 0x006B, 0x006D, 0, - 15, 0x339F, 0x006D, 0x006D, 0x00B2, 0, - 15, 0x33A0, 0x0063, 0x006D, 0x00B2, 0, - 15, 0x33A1, 0x006D, 0x00B2, 0, - 15, 0x33A2, 0x006B, 0x006D, 0x00B2, 0, - 15, 0x33A3, 0x006D, 0x006D, 0x00B3, 0, - 15, 0x33A4, 0x0063, 0x006D, 0x00B3, 0, - 15, 0x33A5, 0x006D, 0x00B3, 0, - 15, 0x33A6, 0x006B, 0x006D, 0x00B3, 0, - 15, 0x33A7, 0x006D, 0x2215, 0x0073, 0, - 15, 0x33A8, 0x006D, 0x2215, 0x0073, 0x00B2, 0, - 15, 0x33A9, 0x0050, 0x0061, 0, - 15, 0x33AA, 0x006B, 0x0050, 0x0061, 0, - 15, 0x33AB, 0x004D, 0x0050, 0x0061, 0, - 15, 0x33AC, 0x0047, 0x0050, 0x0061, 0, - 15, 0x33AD, 0x0072, 0x0061, 0x0064, 0, - 15, 0x33AE, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0, - 15, 0x33AF, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x00B2, 0, - 15, 0x33B0, 0x0070, 0x0073, 0, - 15, 0x33B1, 0x006E, 0x0073, 0, - 15, 0x33B2, 0x03BC, 0x0073, 0, - 15, 0x33B3, 0x006D, 0x0073, 0, - 15, 0x33B4, 0x0070, 0x0056, 0, - 15, 0x33B5, 0x006E, 0x0056, 0, - 15, 0x33B6, 0x03BC, 0x0056, 0, - 15, 0x33B7, 0x006D, 0x0056, 0, - 15, 0x33B8, 0x006B, 0x0056, 0, - 15, 0x33B9, 0x004D, 0x0056, 0, - 15, 0x33BA, 0x0070, 0x0057, 0, - 15, 0x33BB, 0x006E, 0x0057, 0, - 15, 0x33BC, 0x03BC, 0x0057, 0, - 15, 0x33BD, 0x006D, 0x0057, 0, - 15, 0x33BE, 0x006B, 0x0057, 0, - 15, 0x33BF, 0x004D, 0x0057, 0, - 15, 0x33C0, 0x006B, 0x03A9, 0, - 15, 0x33C1, 0x004D, 0x03A9, 0, - 15, 0x33C2, 0x0061, 0x002E, 0x006D, 0x002E, 0, - 15, 0x33C3, 0x0042, 0x0071, 0, - 15, 0x33C4, 0x0063, 0x0063, 0, - 15, 0x33C5, 0x0063, 0x0064, 0, - 15, 0x33C6, 0x0043, 0x2215, 0x006B, 0x0067, 0, - 15, 0x33C7, 0x0043, 0x006F, 0x002E, 0, - 15, 0x33C8, 0x0064, 0x0042, 0, - 15, 0x33C9, 0x0047, 0x0079, 0, - 15, 0x33CA, 0x0068, 0x0061, 0, - 15, 0x33CB, 0x0048, 0x0050, 0, - 15, 0x33CC, 0x0069, 0x006E, 0, - 15, 0x33CD, 0x004B, 0x004B, 0, - 15, 0x33CE, 0x004B, 0x004D, 0, - 15, 0x33CF, 0x006B, 0x0074, 0, - 15, 0x33D0, 0x006C, 0x006D, 0, - 15, 0x33D1, 0x006C, 0x006E, 0, - 15, 0x33D2, 0x006C, 0x006F, 0x0067, 0, - 15, 0x33D3, 0x006C, 0x0078, 0, - 15, 0x33D4, 0x006D, 0x0062, 0, - 15, 0x33D5, 0x006D, 0x0069, 0x006C, 0, - 15, 0x33D6, 0x006D, 0x006F, 0x006C, 0, - 15, 0x33D7, 0x0050, 0x0048, 0, - 15, 0x33D8, 0x0070, 0x002E, 0x006D, 0x002E, 0, - 15, 0x33D9, 0x0050, 0x0050, 0x004D, 0, - 15, 0x33DA, 0x0050, 0x0052, 0, - 15, 0x33DB, 0x0073, 0x0072, 0, - 15, 0x33DC, 0x0053, 0x0076, 0, - 15, 0x33DD, 0x0057, 0x0062, 0, - 16, 0x33E0, 0x0031, 0x65E5, 0, - 16, 0x33E1, 0x0032, 0x65E5, 0, - 16, 0x33E2, 0x0033, 0x65E5, 0, - 16, 0x33E3, 0x0034, 0x65E5, 0, - 16, 0x33E4, 0x0035, 0x65E5, 0, - 16, 0x33E5, 0x0036, 0x65E5, 0, - 16, 0x33E6, 0x0037, 0x65E5, 0, - 16, 0x33E7, 0x0038, 0x65E5, 0, - 16, 0x33E8, 0x0039, 0x65E5, 0, - 16, 0x33E9, 0x0031, 0x0030, 0x65E5, 0, - 16, 0x33EA, 0x0031, 0x0031, 0x65E5, 0, - 16, 0x33EB, 0x0031, 0x0032, 0x65E5, 0, - 16, 0x33EC, 0x0031, 0x0033, 0x65E5, 0, - 16, 0x33ED, 0x0031, 0x0034, 0x65E5, 0, - 16, 0x33EE, 0x0031, 0x0035, 0x65E5, 0, - 16, 0x33EF, 0x0031, 0x0036, 0x65E5, 0, - 16, 0x33F0, 0x0031, 0x0037, 0x65E5, 0, - 16, 0x33F1, 0x0031, 0x0038, 0x65E5, 0, - 16, 0x33F2, 0x0031, 0x0039, 0x65E5, 0, - 16, 0x33F3, 0x0032, 0x0030, 0x65E5, 0, - 16, 0x33F4, 0x0032, 0x0031, 0x65E5, 0, - 16, 0x33F5, 0x0032, 0x0032, 0x65E5, 0, - 16, 0x33F6, 0x0032, 0x0033, 0x65E5, 0, - 16, 0x33F7, 0x0032, 0x0034, 0x65E5, 0, - 16, 0x33F8, 0x0032, 0x0035, 0x65E5, 0, - 16, 0x33F9, 0x0032, 0x0036, 0x65E5, 0, - 16, 0x33FA, 0x0032, 0x0037, 0x65E5, 0, - 16, 0x33FB, 0x0032, 0x0038, 0x65E5, 0, - 16, 0x33FC, 0x0032, 0x0039, 0x65E5, 0, - 16, 0x33FD, 0x0033, 0x0030, 0x65E5, 0, - 16, 0x33FE, 0x0033, 0x0031, 0x65E5, 0, - 1, 0xF900, 0x8C48, 0, - 1, 0xF901, 0x66F4, 0, - 1, 0xF902, 0x8ECA, 0, - 1, 0xF903, 0x8CC8, 0, - 1, 0xF904, 0x6ED1, 0, - 1, 0xF905, 0x4E32, 0, - 1, 0xF906, 0x53E5, 0, - 1, 0xF907, 0x9F9C, 0, - 1, 0xF908, 0x9F9C, 0, - 1, 0xF909, 0x5951, 0, - 1, 0xF90A, 0x91D1, 0, - 1, 0xF90B, 0x5587, 0, - 1, 0xF90C, 0x5948, 0, - 1, 0xF90D, 0x61F6, 0, - 1, 0xF90E, 0x7669, 0, - 1, 0xF90F, 0x7F85, 0, - 1, 0xF910, 0x863F, 0, - 1, 0xF911, 0x87BA, 0, - 1, 0xF912, 0x88F8, 0, - 1, 0xF913, 0x908F, 0, - 1, 0xF914, 0x6A02, 0, - 1, 0xF915, 0x6D1B, 0, - 1, 0xF916, 0x70D9, 0, - 1, 0xF917, 0x73DE, 0, - 1, 0xF918, 0x843D, 0, - 1, 0xF919, 0x916A, 0, - 1, 0xF91A, 0x99F1, 0, - 1, 0xF91B, 0x4E82, 0, - 1, 0xF91C, 0x5375, 0, - 1, 0xF91D, 0x6B04, 0, - 1, 0xF91E, 0x721B, 0, - 1, 0xF91F, 0x862D, 0, - 1, 0xF920, 0x9E1E, 0, - 1, 0xF921, 0x5D50, 0, - 1, 0xF922, 0x6FEB, 0, - 1, 0xF923, 0x85CD, 0, - 1, 0xF924, 0x8964, 0, - 1, 0xF925, 0x62C9, 0, - 1, 0xF926, 0x81D8, 0, - 1, 0xF927, 0x881F, 0, - 1, 0xF928, 0x5ECA, 0, - 1, 0xF929, 0x6717, 0, - 1, 0xF92A, 0x6D6A, 0, - 1, 0xF92B, 0x72FC, 0, - 1, 0xF92C, 0x90CE, 0, - 1, 0xF92D, 0x4F86, 0, - 1, 0xF92E, 0x51B7, 0, - 1, 0xF92F, 0x52DE, 0, - 1, 0xF930, 0x64C4, 0, - 1, 0xF931, 0x6AD3, 0, - 1, 0xF932, 0x7210, 0, - 1, 0xF933, 0x76E7, 0, - 1, 0xF934, 0x8001, 0, - 1, 0xF935, 0x8606, 0, - 1, 0xF936, 0x865C, 0, - 1, 0xF937, 0x8DEF, 0, - 1, 0xF938, 0x9732, 0, - 1, 0xF939, 0x9B6F, 0, - 1, 0xF93A, 0x9DFA, 0, - 1, 0xF93B, 0x788C, 0, - 1, 0xF93C, 0x797F, 0, - 1, 0xF93D, 0x7DA0, 0, - 1, 0xF93E, 0x83C9, 0, - 1, 0xF93F, 0x9304, 0, - 1, 0xF940, 0x9E7F, 0, - 1, 0xF941, 0x8AD6, 0, - 1, 0xF942, 0x58DF, 0, - 1, 0xF943, 0x5F04, 0, - 1, 0xF944, 0x7C60, 0, - 1, 0xF945, 0x807E, 0, - 1, 0xF946, 0x7262, 0, - 1, 0xF947, 0x78CA, 0, - 1, 0xF948, 0x8CC2, 0, - 1, 0xF949, 0x96F7, 0, - 1, 0xF94A, 0x58D8, 0, - 1, 0xF94B, 0x5C62, 0, - 1, 0xF94C, 0x6A13, 0, - 1, 0xF94D, 0x6DDA, 0, - 1, 0xF94E, 0x6F0F, 0, - 1, 0xF94F, 0x7D2F, 0, - 1, 0xF950, 0x7E37, 0, - 1, 0xF951, 0x964B, 0, - 1, 0xF952, 0x52D2, 0, - 1, 0xF953, 0x808B, 0, - 1, 0xF954, 0x51DC, 0, - 1, 0xF955, 0x51CC, 0, - 1, 0xF956, 0x7A1C, 0, - 1, 0xF957, 0x7DBE, 0, - 1, 0xF958, 0x83F1, 0, - 1, 0xF959, 0x9675, 0, - 1, 0xF95A, 0x8B80, 0, - 1, 0xF95B, 0x62CF, 0, - 1, 0xF95C, 0x6A02, 0, - 1, 0xF95D, 0x8AFE, 0, - 1, 0xF95E, 0x4E39, 0, - 1, 0xF95F, 0x5BE7, 0, - 1, 0xF960, 0x6012, 0, - 1, 0xF961, 0x7387, 0, - 1, 0xF962, 0x7570, 0, - 1, 0xF963, 0x5317, 0, - 1, 0xF964, 0x78FB, 0, - 1, 0xF965, 0x4FBF, 0, - 1, 0xF966, 0x5FA9, 0, - 1, 0xF967, 0x4E0D, 0, - 1, 0xF968, 0x6CCC, 0, - 1, 0xF969, 0x6578, 0, - 1, 0xF96A, 0x7D22, 0, - 1, 0xF96B, 0x53C3, 0, - 1, 0xF96C, 0x585E, 0, - 1, 0xF96D, 0x7701, 0, - 1, 0xF96E, 0x8449, 0, - 1, 0xF96F, 0x8AAA, 0, - 1, 0xF970, 0x6BBA, 0, - 1, 0xF971, 0x8FB0, 0, - 1, 0xF972, 0x6C88, 0, - 1, 0xF973, 0x62FE, 0, - 1, 0xF974, 0x82E5, 0, - 1, 0xF975, 0x63A0, 0, - 1, 0xF976, 0x7565, 0, - 1, 0xF977, 0x4EAE, 0, - 1, 0xF978, 0x5169, 0, - 1, 0xF979, 0x51C9, 0, - 1, 0xF97A, 0x6881, 0, - 1, 0xF97B, 0x7CE7, 0, - 1, 0xF97C, 0x826F, 0, - 1, 0xF97D, 0x8AD2, 0, - 1, 0xF97E, 0x91CF, 0, - 1, 0xF97F, 0x52F5, 0, - 1, 0xF980, 0x5442, 0, - 1, 0xF981, 0x5973, 0, - 1, 0xF982, 0x5EEC, 0, - 1, 0xF983, 0x65C5, 0, - 1, 0xF984, 0x6FFE, 0, - 1, 0xF985, 0x792A, 0, - 1, 0xF986, 0x95AD, 0, - 1, 0xF987, 0x9A6A, 0, - 1, 0xF988, 0x9E97, 0, - 1, 0xF989, 0x9ECE, 0, - 1, 0xF98A, 0x529B, 0, - 1, 0xF98B, 0x66C6, 0, - 1, 0xF98C, 0x6B77, 0, - 1, 0xF98D, 0x8F62, 0, - 1, 0xF98E, 0x5E74, 0, - 1, 0xF98F, 0x6190, 0, - 1, 0xF990, 0x6200, 0, - 1, 0xF991, 0x649A, 0, - 1, 0xF992, 0x6F23, 0, - 1, 0xF993, 0x7149, 0, - 1, 0xF994, 0x7489, 0, - 1, 0xF995, 0x79CA, 0, - 1, 0xF996, 0x7DF4, 0, - 1, 0xF997, 0x806F, 0, - 1, 0xF998, 0x8F26, 0, - 1, 0xF999, 0x84EE, 0, - 1, 0xF99A, 0x9023, 0, - 1, 0xF99B, 0x934A, 0, - 1, 0xF99C, 0x5217, 0, - 1, 0xF99D, 0x52A3, 0, - 1, 0xF99E, 0x54BD, 0, - 1, 0xF99F, 0x70C8, 0, - 1, 0xF9A0, 0x88C2, 0, - 1, 0xF9A1, 0x8AAA, 0, - 1, 0xF9A2, 0x5EC9, 0, - 1, 0xF9A3, 0x5FF5, 0, - 1, 0xF9A4, 0x637B, 0, - 1, 0xF9A5, 0x6BAE, 0, - 1, 0xF9A6, 0x7C3E, 0, - 1, 0xF9A7, 0x7375, 0, - 1, 0xF9A8, 0x4EE4, 0, - 1, 0xF9A9, 0x56F9, 0, - 1, 0xF9AA, 0x5BE7, 0, - 1, 0xF9AB, 0x5DBA, 0, - 1, 0xF9AC, 0x601C, 0, - 1, 0xF9AD, 0x73B2, 0, - 1, 0xF9AE, 0x7469, 0, - 1, 0xF9AF, 0x7F9A, 0, - 1, 0xF9B0, 0x8046, 0, - 1, 0xF9B1, 0x9234, 0, - 1, 0xF9B2, 0x96F6, 0, - 1, 0xF9B3, 0x9748, 0, - 1, 0xF9B4, 0x9818, 0, - 1, 0xF9B5, 0x4F8B, 0, - 1, 0xF9B6, 0x79AE, 0, - 1, 0xF9B7, 0x91B4, 0, - 1, 0xF9B8, 0x96B8, 0, - 1, 0xF9B9, 0x60E1, 0, - 1, 0xF9BA, 0x4E86, 0, - 1, 0xF9BB, 0x50DA, 0, - 1, 0xF9BC, 0x5BEE, 0, - 1, 0xF9BD, 0x5C3F, 0, - 1, 0xF9BE, 0x6599, 0, - 1, 0xF9BF, 0x6A02, 0, - 1, 0xF9C0, 0x71CE, 0, - 1, 0xF9C1, 0x7642, 0, - 1, 0xF9C2, 0x84FC, 0, - 1, 0xF9C3, 0x907C, 0, - 1, 0xF9C4, 0x9F8D, 0, - 1, 0xF9C5, 0x6688, 0, - 1, 0xF9C6, 0x962E, 0, - 1, 0xF9C7, 0x5289, 0, - 1, 0xF9C8, 0x677B, 0, - 1, 0xF9C9, 0x67F3, 0, - 1, 0xF9CA, 0x6D41, 0, - 1, 0xF9CB, 0x6E9C, 0, - 1, 0xF9CC, 0x7409, 0, - 1, 0xF9CD, 0x7559, 0, - 1, 0xF9CE, 0x786B, 0, - 1, 0xF9CF, 0x7D10, 0, - 1, 0xF9D0, 0x985E, 0, - 1, 0xF9D1, 0x516D, 0, - 1, 0xF9D2, 0x622E, 0, - 1, 0xF9D3, 0x9678, 0, - 1, 0xF9D4, 0x502B, 0, - 1, 0xF9D5, 0x5D19, 0, - 1, 0xF9D6, 0x6DEA, 0, - 1, 0xF9D7, 0x8F2A, 0, - 1, 0xF9D8, 0x5F8B, 0, - 1, 0xF9D9, 0x6144, 0, - 1, 0xF9DA, 0x6817, 0, - 1, 0xF9DB, 0x7387, 0, - 1, 0xF9DC, 0x9686, 0, - 1, 0xF9DD, 0x5229, 0, - 1, 0xF9DE, 0x540F, 0, - 1, 0xF9DF, 0x5C65, 0, - 1, 0xF9E0, 0x6613, 0, - 1, 0xF9E1, 0x674E, 0, - 1, 0xF9E2, 0x68A8, 0, - 1, 0xF9E3, 0x6CE5, 0, - 1, 0xF9E4, 0x7406, 0, - 1, 0xF9E5, 0x75E2, 0, - 1, 0xF9E6, 0x7F79, 0, - 1, 0xF9E7, 0x88CF, 0, - 1, 0xF9E8, 0x88E1, 0, - 1, 0xF9E9, 0x91CC, 0, - 1, 0xF9EA, 0x96E2, 0, - 1, 0xF9EB, 0x533F, 0, - 1, 0xF9EC, 0x6EBA, 0, - 1, 0xF9ED, 0x541D, 0, - 1, 0xF9EE, 0x71D0, 0, - 1, 0xF9EF, 0x7498, 0, - 1, 0xF9F0, 0x85FA, 0, - 1, 0xF9F1, 0x96A3, 0, - 1, 0xF9F2, 0x9C57, 0, - 1, 0xF9F3, 0x9E9F, 0, - 1, 0xF9F4, 0x6797, 0, - 1, 0xF9F5, 0x6DCB, 0, - 1, 0xF9F6, 0x81E8, 0, - 1, 0xF9F7, 0x7ACB, 0, - 1, 0xF9F8, 0x7B20, 0, - 1, 0xF9F9, 0x7C92, 0, - 1, 0xF9FA, 0x72C0, 0, - 1, 0xF9FB, 0x7099, 0, - 1, 0xF9FC, 0x8B58, 0, - 1, 0xF9FD, 0x4EC0, 0, - 1, 0xF9FE, 0x8336, 0, - 1, 0xF9FF, 0x523A, 0, - 1, 0xFA00, 0x5207, 0, - 1, 0xFA01, 0x5EA6, 0, - 1, 0xFA02, 0x62D3, 0, - 1, 0xFA03, 0x7CD6, 0, - 1, 0xFA04, 0x5B85, 0, - 1, 0xFA05, 0x6D1E, 0, - 1, 0xFA06, 0x66B4, 0, - 1, 0xFA07, 0x8F3B, 0, - 1, 0xFA08, 0x884C, 0, - 1, 0xFA09, 0x964D, 0, - 1, 0xFA0A, 0x898B, 0, - 1, 0xFA0B, 0x5ED3, 0, - 1, 0xFA0C, 0x5140, 0, - 1, 0xFA0D, 0x55C0, 0, - 1, 0xFA10, 0x585A, 0, - 1, 0xFA12, 0x6674, 0, - 1, 0xFA15, 0x51DE, 0, - 1, 0xFA16, 0x732A, 0, - 1, 0xFA17, 0x76CA, 0, - 1, 0xFA18, 0x793C, 0, - 1, 0xFA19, 0x795E, 0, - 1, 0xFA1A, 0x7965, 0, - 1, 0xFA1B, 0x798F, 0, - 1, 0xFA1C, 0x9756, 0, - 1, 0xFA1D, 0x7CBE, 0, - 1, 0xFA1E, 0x7FBD, 0, - 1, 0xFA20, 0x8612, 0, - 1, 0xFA22, 0x8AF8, 0, - 1, 0xFA25, 0x9038, 0, - 1, 0xFA26, 0x90FD, 0, - 1, 0xFA2A, 0x98EF, 0, - 1, 0xFA2B, 0x98FC, 0, - 1, 0xFA2C, 0x9928, 0, - 1, 0xFA2D, 0x9DB4, 0, - 1, 0xFA30, 0x4FAE, 0, - 1, 0xFA31, 0x50E7, 0, - 1, 0xFA32, 0x514D, 0, - 1, 0xFA33, 0x52C9, 0, - 1, 0xFA34, 0x52E4, 0, - 1, 0xFA35, 0x5351, 0, - 1, 0xFA36, 0x559D, 0, - 1, 0xFA37, 0x5606, 0, - 1, 0xFA38, 0x5668, 0, - 1, 0xFA39, 0x5840, 0, - 1, 0xFA3A, 0x58A8, 0, - 1, 0xFA3B, 0x5C64, 0, - 1, 0xFA3C, 0x5C6E, 0, - 1, 0xFA3D, 0x6094, 0, - 1, 0xFA3E, 0x6168, 0, - 1, 0xFA3F, 0x618E, 0, - 1, 0xFA40, 0x61F2, 0, - 1, 0xFA41, 0x654F, 0, - 1, 0xFA42, 0x65E2, 0, - 1, 0xFA43, 0x6691, 0, - 1, 0xFA44, 0x6885, 0, - 1, 0xFA45, 0x6D77, 0, - 1, 0xFA46, 0x6E1A, 0, - 1, 0xFA47, 0x6F22, 0, - 1, 0xFA48, 0x716E, 0, - 1, 0xFA49, 0x722B, 0, - 1, 0xFA4A, 0x7422, 0, - 1, 0xFA4B, 0x7891, 0, - 1, 0xFA4C, 0x793E, 0, - 1, 0xFA4D, 0x7949, 0, - 1, 0xFA4E, 0x7948, 0, - 1, 0xFA4F, 0x7950, 0, - 1, 0xFA50, 0x7956, 0, - 1, 0xFA51, 0x795D, 0, - 1, 0xFA52, 0x798D, 0, - 1, 0xFA53, 0x798E, 0, - 1, 0xFA54, 0x7A40, 0, - 1, 0xFA55, 0x7A81, 0, - 1, 0xFA56, 0x7BC0, 0, - 1, 0xFA57, 0x7DF4, 0, - 1, 0xFA58, 0x7E09, 0, - 1, 0xFA59, 0x7E41, 0, - 1, 0xFA5A, 0x7F72, 0, - 1, 0xFA5B, 0x8005, 0, - 1, 0xFA5C, 0x81ED, 0, - 1, 0xFA5D, 0x8279, 0, - 1, 0xFA5E, 0x8279, 0, - 1, 0xFA5F, 0x8457, 0, - 1, 0xFA60, 0x8910, 0, - 1, 0xFA61, 0x8996, 0, - 1, 0xFA62, 0x8B01, 0, - 1, 0xFA63, 0x8B39, 0, - 1, 0xFA64, 0x8CD3, 0, - 1, 0xFA65, 0x8D08, 0, - 1, 0xFA66, 0x8FB6, 0, - 1, 0xFA67, 0x9038, 0, - 1, 0xFA68, 0x96E3, 0, - 1, 0xFA69, 0x97FF, 0, - 1, 0xFA6A, 0x983B, 0, - 16, 0xFB00, 0x0066, 0x0066, 0, - 16, 0xFB01, 0x0066, 0x0069, 0, - 16, 0xFB02, 0x0066, 0x006C, 0, - 16, 0xFB03, 0x0066, 0x0066, 0x0069, 0, - 16, 0xFB04, 0x0066, 0x0066, 0x006C, 0, - 16, 0xFB05, 0x017F, 0x0074, 0, - 16, 0xFB06, 0x0073, 0x0074, 0, - 16, 0xFB13, 0x0574, 0x0576, 0, - 16, 0xFB14, 0x0574, 0x0565, 0, - 16, 0xFB15, 0x0574, 0x056B, 0, - 16, 0xFB16, 0x057E, 0x0576, 0, - 16, 0xFB17, 0x0574, 0x056D, 0, - 1, 0xFB1D, 0x05D9, 0x05B4, 0, - 1, 0xFB1F, 0x05F2, 0x05B7, 0, - 2, 0xFB20, 0x05E2, 0, - 2, 0xFB21, 0x05D0, 0, - 2, 0xFB22, 0x05D3, 0, - 2, 0xFB23, 0x05D4, 0, - 2, 0xFB24, 0x05DB, 0, - 2, 0xFB25, 0x05DC, 0, - 2, 0xFB26, 0x05DD, 0, - 2, 0xFB27, 0x05E8, 0, - 2, 0xFB28, 0x05EA, 0, - 2, 0xFB29, 0x002B, 0, - 1, 0xFB2A, 0x05E9, 0x05C1, 0, - 1, 0xFB2B, 0x05E9, 0x05C2, 0, - 1, 0xFB2C, 0xFB49, 0x05C1, 0, - 1, 0xFB2D, 0xFB49, 0x05C2, 0, - 1, 0xFB2E, 0x05D0, 0x05B7, 0, - 1, 0xFB2F, 0x05D0, 0x05B8, 0, - 1, 0xFB30, 0x05D0, 0x05BC, 0, - 1, 0xFB31, 0x05D1, 0x05BC, 0, - 1, 0xFB32, 0x05D2, 0x05BC, 0, - 1, 0xFB33, 0x05D3, 0x05BC, 0, - 1, 0xFB34, 0x05D4, 0x05BC, 0, - 1, 0xFB35, 0x05D5, 0x05BC, 0, - 1, 0xFB36, 0x05D6, 0x05BC, 0, - 1, 0xFB38, 0x05D8, 0x05BC, 0, - 1, 0xFB39, 0x05D9, 0x05BC, 0, - 1, 0xFB3A, 0x05DA, 0x05BC, 0, - 1, 0xFB3B, 0x05DB, 0x05BC, 0, - 1, 0xFB3C, 0x05DC, 0x05BC, 0, - 1, 0xFB3E, 0x05DE, 0x05BC, 0, - 1, 0xFB40, 0x05E0, 0x05BC, 0, - 1, 0xFB41, 0x05E1, 0x05BC, 0, - 1, 0xFB43, 0x05E3, 0x05BC, 0, - 1, 0xFB44, 0x05E4, 0x05BC, 0, - 1, 0xFB46, 0x05E6, 0x05BC, 0, - 1, 0xFB47, 0x05E7, 0x05BC, 0, - 1, 0xFB48, 0x05E8, 0x05BC, 0, - 1, 0xFB49, 0x05E9, 0x05BC, 0, - 1, 0xFB4A, 0x05EA, 0x05BC, 0, - 1, 0xFB4B, 0x05D5, 0x05B9, 0, - 1, 0xFB4C, 0x05D1, 0x05BF, 0, - 1, 0xFB4D, 0x05DB, 0x05BF, 0, - 1, 0xFB4E, 0x05E4, 0x05BF, 0, - 16, 0xFB4F, 0x05D0, 0x05DC, 0, - 7, 0xFB50, 0x0671, 0, - 6, 0xFB51, 0x0671, 0, - 7, 0xFB52, 0x067B, 0, - 6, 0xFB53, 0x067B, 0, - 4, 0xFB54, 0x067B, 0, - 5, 0xFB55, 0x067B, 0, - 7, 0xFB56, 0x067E, 0, - 6, 0xFB57, 0x067E, 0, - 4, 0xFB58, 0x067E, 0, - 5, 0xFB59, 0x067E, 0, - 7, 0xFB5A, 0x0680, 0, - 6, 0xFB5B, 0x0680, 0, - 4, 0xFB5C, 0x0680, 0, - 5, 0xFB5D, 0x0680, 0, - 7, 0xFB5E, 0x067A, 0, - 6, 0xFB5F, 0x067A, 0, - 4, 0xFB60, 0x067A, 0, - 5, 0xFB61, 0x067A, 0, - 7, 0xFB62, 0x067F, 0, - 6, 0xFB63, 0x067F, 0, - 4, 0xFB64, 0x067F, 0, - 5, 0xFB65, 0x067F, 0, - 7, 0xFB66, 0x0679, 0, - 6, 0xFB67, 0x0679, 0, - 4, 0xFB68, 0x0679, 0, - 5, 0xFB69, 0x0679, 0, - 7, 0xFB6A, 0x06A4, 0, - 6, 0xFB6B, 0x06A4, 0, - 4, 0xFB6C, 0x06A4, 0, - 5, 0xFB6D, 0x06A4, 0, - 7, 0xFB6E, 0x06A6, 0, - 6, 0xFB6F, 0x06A6, 0, - 4, 0xFB70, 0x06A6, 0, - 5, 0xFB71, 0x06A6, 0, - 7, 0xFB72, 0x0684, 0, - 6, 0xFB73, 0x0684, 0, - 4, 0xFB74, 0x0684, 0, - 5, 0xFB75, 0x0684, 0, - 7, 0xFB76, 0x0683, 0, - 6, 0xFB77, 0x0683, 0, - 4, 0xFB78, 0x0683, 0, - 5, 0xFB79, 0x0683, 0, - 7, 0xFB7A, 0x0686, 0, - 6, 0xFB7B, 0x0686, 0, - 4, 0xFB7C, 0x0686, 0, - 5, 0xFB7D, 0x0686, 0, - 7, 0xFB7E, 0x0687, 0, - 6, 0xFB7F, 0x0687, 0, - 4, 0xFB80, 0x0687, 0, - 5, 0xFB81, 0x0687, 0, - 7, 0xFB82, 0x068D, 0, - 6, 0xFB83, 0x068D, 0, - 7, 0xFB84, 0x068C, 0, - 6, 0xFB85, 0x068C, 0, - 7, 0xFB86, 0x068E, 0, - 6, 0xFB87, 0x068E, 0, - 7, 0xFB88, 0x0688, 0, - 6, 0xFB89, 0x0688, 0, - 7, 0xFB8A, 0x0698, 0, - 6, 0xFB8B, 0x0698, 0, - 7, 0xFB8C, 0x0691, 0, - 6, 0xFB8D, 0x0691, 0, - 7, 0xFB8E, 0x06A9, 0, - 6, 0xFB8F, 0x06A9, 0, - 4, 0xFB90, 0x06A9, 0, - 5, 0xFB91, 0x06A9, 0, - 7, 0xFB92, 0x06AF, 0, - 6, 0xFB93, 0x06AF, 0, - 4, 0xFB94, 0x06AF, 0, - 5, 0xFB95, 0x06AF, 0, - 7, 0xFB96, 0x06B3, 0, - 6, 0xFB97, 0x06B3, 0, - 4, 0xFB98, 0x06B3, 0, - 5, 0xFB99, 0x06B3, 0, - 7, 0xFB9A, 0x06B1, 0, - 6, 0xFB9B, 0x06B1, 0, - 4, 0xFB9C, 0x06B1, 0, - 5, 0xFB9D, 0x06B1, 0, - 7, 0xFB9E, 0x06BA, 0, - 6, 0xFB9F, 0x06BA, 0, - 7, 0xFBA0, 0x06BB, 0, - 6, 0xFBA1, 0x06BB, 0, - 4, 0xFBA2, 0x06BB, 0, - 5, 0xFBA3, 0x06BB, 0, - 7, 0xFBA4, 0x06C0, 0, - 6, 0xFBA5, 0x06C0, 0, - 7, 0xFBA6, 0x06C1, 0, - 6, 0xFBA7, 0x06C1, 0, - 4, 0xFBA8, 0x06C1, 0, - 5, 0xFBA9, 0x06C1, 0, - 7, 0xFBAA, 0x06BE, 0, - 6, 0xFBAB, 0x06BE, 0, - 4, 0xFBAC, 0x06BE, 0, - 5, 0xFBAD, 0x06BE, 0, - 7, 0xFBAE, 0x06D2, 0, - 6, 0xFBAF, 0x06D2, 0, - 7, 0xFBB0, 0x06D3, 0, - 6, 0xFBB1, 0x06D3, 0, - 7, 0xFBD3, 0x06AD, 0, - 6, 0xFBD4, 0x06AD, 0, - 4, 0xFBD5, 0x06AD, 0, - 5, 0xFBD6, 0x06AD, 0, - 7, 0xFBD7, 0x06C7, 0, - 6, 0xFBD8, 0x06C7, 0, - 7, 0xFBD9, 0x06C6, 0, - 6, 0xFBDA, 0x06C6, 0, - 7, 0xFBDB, 0x06C8, 0, - 6, 0xFBDC, 0x06C8, 0, - 7, 0xFBDD, 0x0677, 0, - 7, 0xFBDE, 0x06CB, 0, - 6, 0xFBDF, 0x06CB, 0, - 7, 0xFBE0, 0x06C5, 0, - 6, 0xFBE1, 0x06C5, 0, - 7, 0xFBE2, 0x06C9, 0, - 6, 0xFBE3, 0x06C9, 0, - 7, 0xFBE4, 0x06D0, 0, - 6, 0xFBE5, 0x06D0, 0, - 4, 0xFBE6, 0x06D0, 0, - 5, 0xFBE7, 0x06D0, 0, - 4, 0xFBE8, 0x0649, 0, - 5, 0xFBE9, 0x0649, 0, - 7, 0xFBEA, 0x0626, 0x0627, 0, - 6, 0xFBEB, 0x0626, 0x0627, 0, - 7, 0xFBEC, 0x0626, 0x06D5, 0, - 6, 0xFBED, 0x0626, 0x06D5, 0, - 7, 0xFBEE, 0x0626, 0x0648, 0, - 6, 0xFBEF, 0x0626, 0x0648, 0, - 7, 0xFBF0, 0x0626, 0x06C7, 0, - 6, 0xFBF1, 0x0626, 0x06C7, 0, - 7, 0xFBF2, 0x0626, 0x06C6, 0, - 6, 0xFBF3, 0x0626, 0x06C6, 0, - 7, 0xFBF4, 0x0626, 0x06C8, 0, - 6, 0xFBF5, 0x0626, 0x06C8, 0, - 7, 0xFBF6, 0x0626, 0x06D0, 0, - 6, 0xFBF7, 0x0626, 0x06D0, 0, - 4, 0xFBF8, 0x0626, 0x06D0, 0, - 7, 0xFBF9, 0x0626, 0x0649, 0, - 6, 0xFBFA, 0x0626, 0x0649, 0, - 4, 0xFBFB, 0x0626, 0x0649, 0, - 7, 0xFBFC, 0x06CC, 0, - 6, 0xFBFD, 0x06CC, 0, - 4, 0xFBFE, 0x06CC, 0, - 5, 0xFBFF, 0x06CC, 0, - 7, 0xFC00, 0x0626, 0x062C, 0, - 7, 0xFC01, 0x0626, 0x062D, 0, - 7, 0xFC02, 0x0626, 0x0645, 0, - 7, 0xFC03, 0x0626, 0x0649, 0, - 7, 0xFC04, 0x0626, 0x064A, 0, - 7, 0xFC05, 0x0628, 0x062C, 0, - 7, 0xFC06, 0x0628, 0x062D, 0, - 7, 0xFC07, 0x0628, 0x062E, 0, - 7, 0xFC08, 0x0628, 0x0645, 0, - 7, 0xFC09, 0x0628, 0x0649, 0, - 7, 0xFC0A, 0x0628, 0x064A, 0, - 7, 0xFC0B, 0x062A, 0x062C, 0, - 7, 0xFC0C, 0x062A, 0x062D, 0, - 7, 0xFC0D, 0x062A, 0x062E, 0, - 7, 0xFC0E, 0x062A, 0x0645, 0, - 7, 0xFC0F, 0x062A, 0x0649, 0, - 7, 0xFC10, 0x062A, 0x064A, 0, - 7, 0xFC11, 0x062B, 0x062C, 0, - 7, 0xFC12, 0x062B, 0x0645, 0, - 7, 0xFC13, 0x062B, 0x0649, 0, - 7, 0xFC14, 0x062B, 0x064A, 0, - 7, 0xFC15, 0x062C, 0x062D, 0, - 7, 0xFC16, 0x062C, 0x0645, 0, - 7, 0xFC17, 0x062D, 0x062C, 0, - 7, 0xFC18, 0x062D, 0x0645, 0, - 7, 0xFC19, 0x062E, 0x062C, 0, - 7, 0xFC1A, 0x062E, 0x062D, 0, - 7, 0xFC1B, 0x062E, 0x0645, 0, - 7, 0xFC1C, 0x0633, 0x062C, 0, - 7, 0xFC1D, 0x0633, 0x062D, 0, - 7, 0xFC1E, 0x0633, 0x062E, 0, - 7, 0xFC1F, 0x0633, 0x0645, 0, - 7, 0xFC20, 0x0635, 0x062D, 0, - 7, 0xFC21, 0x0635, 0x0645, 0, - 7, 0xFC22, 0x0636, 0x062C, 0, - 7, 0xFC23, 0x0636, 0x062D, 0, - 7, 0xFC24, 0x0636, 0x062E, 0, - 7, 0xFC25, 0x0636, 0x0645, 0, - 7, 0xFC26, 0x0637, 0x062D, 0, - 7, 0xFC27, 0x0637, 0x0645, 0, - 7, 0xFC28, 0x0638, 0x0645, 0, - 7, 0xFC29, 0x0639, 0x062C, 0, - 7, 0xFC2A, 0x0639, 0x0645, 0, - 7, 0xFC2B, 0x063A, 0x062C, 0, - 7, 0xFC2C, 0x063A, 0x0645, 0, - 7, 0xFC2D, 0x0641, 0x062C, 0, - 7, 0xFC2E, 0x0641, 0x062D, 0, - 7, 0xFC2F, 0x0641, 0x062E, 0, - 7, 0xFC30, 0x0641, 0x0645, 0, - 7, 0xFC31, 0x0641, 0x0649, 0, - 7, 0xFC32, 0x0641, 0x064A, 0, - 7, 0xFC33, 0x0642, 0x062D, 0, - 7, 0xFC34, 0x0642, 0x0645, 0, - 7, 0xFC35, 0x0642, 0x0649, 0, - 7, 0xFC36, 0x0642, 0x064A, 0, - 7, 0xFC37, 0x0643, 0x0627, 0, - 7, 0xFC38, 0x0643, 0x062C, 0, - 7, 0xFC39, 0x0643, 0x062D, 0, - 7, 0xFC3A, 0x0643, 0x062E, 0, - 7, 0xFC3B, 0x0643, 0x0644, 0, - 7, 0xFC3C, 0x0643, 0x0645, 0, - 7, 0xFC3D, 0x0643, 0x0649, 0, - 7, 0xFC3E, 0x0643, 0x064A, 0, - 7, 0xFC3F, 0x0644, 0x062C, 0, - 7, 0xFC40, 0x0644, 0x062D, 0, - 7, 0xFC41, 0x0644, 0x062E, 0, - 7, 0xFC42, 0x0644, 0x0645, 0, - 7, 0xFC43, 0x0644, 0x0649, 0, - 7, 0xFC44, 0x0644, 0x064A, 0, - 7, 0xFC45, 0x0645, 0x062C, 0, - 7, 0xFC46, 0x0645, 0x062D, 0, - 7, 0xFC47, 0x0645, 0x062E, 0, - 7, 0xFC48, 0x0645, 0x0645, 0, - 7, 0xFC49, 0x0645, 0x0649, 0, - 7, 0xFC4A, 0x0645, 0x064A, 0, - 7, 0xFC4B, 0x0646, 0x062C, 0, - 7, 0xFC4C, 0x0646, 0x062D, 0, - 7, 0xFC4D, 0x0646, 0x062E, 0, - 7, 0xFC4E, 0x0646, 0x0645, 0, - 7, 0xFC4F, 0x0646, 0x0649, 0, - 7, 0xFC50, 0x0646, 0x064A, 0, - 7, 0xFC51, 0x0647, 0x062C, 0, - 7, 0xFC52, 0x0647, 0x0645, 0, - 7, 0xFC53, 0x0647, 0x0649, 0, - 7, 0xFC54, 0x0647, 0x064A, 0, - 7, 0xFC55, 0x064A, 0x062C, 0, - 7, 0xFC56, 0x064A, 0x062D, 0, - 7, 0xFC57, 0x064A, 0x062E, 0, - 7, 0xFC58, 0x064A, 0x0645, 0, - 7, 0xFC59, 0x064A, 0x0649, 0, - 7, 0xFC5A, 0x064A, 0x064A, 0, - 7, 0xFC5B, 0x0630, 0x0670, 0, - 7, 0xFC5C, 0x0631, 0x0670, 0, - 7, 0xFC5D, 0x0649, 0x0670, 0, - 7, 0xFC5E, 0x0020, 0x064C, 0x0651, 0, - 7, 0xFC5F, 0x0020, 0x064D, 0x0651, 0, - 7, 0xFC60, 0x0020, 0x064E, 0x0651, 0, - 7, 0xFC61, 0x0020, 0x064F, 0x0651, 0, - 7, 0xFC62, 0x0020, 0x0650, 0x0651, 0, - 7, 0xFC63, 0x0020, 0x0651, 0x0670, 0, - 6, 0xFC64, 0x0626, 0x0631, 0, - 6, 0xFC65, 0x0626, 0x0632, 0, - 6, 0xFC66, 0x0626, 0x0645, 0, - 6, 0xFC67, 0x0626, 0x0646, 0, - 6, 0xFC68, 0x0626, 0x0649, 0, - 6, 0xFC69, 0x0626, 0x064A, 0, - 6, 0xFC6A, 0x0628, 0x0631, 0, - 6, 0xFC6B, 0x0628, 0x0632, 0, - 6, 0xFC6C, 0x0628, 0x0645, 0, - 6, 0xFC6D, 0x0628, 0x0646, 0, - 6, 0xFC6E, 0x0628, 0x0649, 0, - 6, 0xFC6F, 0x0628, 0x064A, 0, - 6, 0xFC70, 0x062A, 0x0631, 0, - 6, 0xFC71, 0x062A, 0x0632, 0, - 6, 0xFC72, 0x062A, 0x0645, 0, - 6, 0xFC73, 0x062A, 0x0646, 0, - 6, 0xFC74, 0x062A, 0x0649, 0, - 6, 0xFC75, 0x062A, 0x064A, 0, - 6, 0xFC76, 0x062B, 0x0631, 0, - 6, 0xFC77, 0x062B, 0x0632, 0, - 6, 0xFC78, 0x062B, 0x0645, 0, - 6, 0xFC79, 0x062B, 0x0646, 0, - 6, 0xFC7A, 0x062B, 0x0649, 0, - 6, 0xFC7B, 0x062B, 0x064A, 0, - 6, 0xFC7C, 0x0641, 0x0649, 0, - 6, 0xFC7D, 0x0641, 0x064A, 0, - 6, 0xFC7E, 0x0642, 0x0649, 0, - 6, 0xFC7F, 0x0642, 0x064A, 0, - 6, 0xFC80, 0x0643, 0x0627, 0, - 6, 0xFC81, 0x0643, 0x0644, 0, - 6, 0xFC82, 0x0643, 0x0645, 0, - 6, 0xFC83, 0x0643, 0x0649, 0, - 6, 0xFC84, 0x0643, 0x064A, 0, - 6, 0xFC85, 0x0644, 0x0645, 0, - 6, 0xFC86, 0x0644, 0x0649, 0, - 6, 0xFC87, 0x0644, 0x064A, 0, - 6, 0xFC88, 0x0645, 0x0627, 0, - 6, 0xFC89, 0x0645, 0x0645, 0, - 6, 0xFC8A, 0x0646, 0x0631, 0, - 6, 0xFC8B, 0x0646, 0x0632, 0, - 6, 0xFC8C, 0x0646, 0x0645, 0, - 6, 0xFC8D, 0x0646, 0x0646, 0, - 6, 0xFC8E, 0x0646, 0x0649, 0, - 6, 0xFC8F, 0x0646, 0x064A, 0, - 6, 0xFC90, 0x0649, 0x0670, 0, - 6, 0xFC91, 0x064A, 0x0631, 0, - 6, 0xFC92, 0x064A, 0x0632, 0, - 6, 0xFC93, 0x064A, 0x0645, 0, - 6, 0xFC94, 0x064A, 0x0646, 0, - 6, 0xFC95, 0x064A, 0x0649, 0, - 6, 0xFC96, 0x064A, 0x064A, 0, - 4, 0xFC97, 0x0626, 0x062C, 0, - 4, 0xFC98, 0x0626, 0x062D, 0, - 4, 0xFC99, 0x0626, 0x062E, 0, - 4, 0xFC9A, 0x0626, 0x0645, 0, - 4, 0xFC9B, 0x0626, 0x0647, 0, - 4, 0xFC9C, 0x0628, 0x062C, 0, - 4, 0xFC9D, 0x0628, 0x062D, 0, - 4, 0xFC9E, 0x0628, 0x062E, 0, - 4, 0xFC9F, 0x0628, 0x0645, 0, - 4, 0xFCA0, 0x0628, 0x0647, 0, - 4, 0xFCA1, 0x062A, 0x062C, 0, - 4, 0xFCA2, 0x062A, 0x062D, 0, - 4, 0xFCA3, 0x062A, 0x062E, 0, - 4, 0xFCA4, 0x062A, 0x0645, 0, - 4, 0xFCA5, 0x062A, 0x0647, 0, - 4, 0xFCA6, 0x062B, 0x0645, 0, - 4, 0xFCA7, 0x062C, 0x062D, 0, - 4, 0xFCA8, 0x062C, 0x0645, 0, - 4, 0xFCA9, 0x062D, 0x062C, 0, - 4, 0xFCAA, 0x062D, 0x0645, 0, - 4, 0xFCAB, 0x062E, 0x062C, 0, - 4, 0xFCAC, 0x062E, 0x0645, 0, - 4, 0xFCAD, 0x0633, 0x062C, 0, - 4, 0xFCAE, 0x0633, 0x062D, 0, - 4, 0xFCAF, 0x0633, 0x062E, 0, - 4, 0xFCB0, 0x0633, 0x0645, 0, - 4, 0xFCB1, 0x0635, 0x062D, 0, - 4, 0xFCB2, 0x0635, 0x062E, 0, - 4, 0xFCB3, 0x0635, 0x0645, 0, - 4, 0xFCB4, 0x0636, 0x062C, 0, - 4, 0xFCB5, 0x0636, 0x062D, 0, - 4, 0xFCB6, 0x0636, 0x062E, 0, - 4, 0xFCB7, 0x0636, 0x0645, 0, - 4, 0xFCB8, 0x0637, 0x062D, 0, - 4, 0xFCB9, 0x0638, 0x0645, 0, - 4, 0xFCBA, 0x0639, 0x062C, 0, - 4, 0xFCBB, 0x0639, 0x0645, 0, - 4, 0xFCBC, 0x063A, 0x062C, 0, - 4, 0xFCBD, 0x063A, 0x0645, 0, - 4, 0xFCBE, 0x0641, 0x062C, 0, - 4, 0xFCBF, 0x0641, 0x062D, 0, - 4, 0xFCC0, 0x0641, 0x062E, 0, - 4, 0xFCC1, 0x0641, 0x0645, 0, - 4, 0xFCC2, 0x0642, 0x062D, 0, - 4, 0xFCC3, 0x0642, 0x0645, 0, - 4, 0xFCC4, 0x0643, 0x062C, 0, - 4, 0xFCC5, 0x0643, 0x062D, 0, - 4, 0xFCC6, 0x0643, 0x062E, 0, - 4, 0xFCC7, 0x0643, 0x0644, 0, - 4, 0xFCC8, 0x0643, 0x0645, 0, - 4, 0xFCC9, 0x0644, 0x062C, 0, - 4, 0xFCCA, 0x0644, 0x062D, 0, - 4, 0xFCCB, 0x0644, 0x062E, 0, - 4, 0xFCCC, 0x0644, 0x0645, 0, - 4, 0xFCCD, 0x0644, 0x0647, 0, - 4, 0xFCCE, 0x0645, 0x062C, 0, - 4, 0xFCCF, 0x0645, 0x062D, 0, - 4, 0xFCD0, 0x0645, 0x062E, 0, - 4, 0xFCD1, 0x0645, 0x0645, 0, - 4, 0xFCD2, 0x0646, 0x062C, 0, - 4, 0xFCD3, 0x0646, 0x062D, 0, - 4, 0xFCD4, 0x0646, 0x062E, 0, - 4, 0xFCD5, 0x0646, 0x0645, 0, - 4, 0xFCD6, 0x0646, 0x0647, 0, - 4, 0xFCD7, 0x0647, 0x062C, 0, - 4, 0xFCD8, 0x0647, 0x0645, 0, - 4, 0xFCD9, 0x0647, 0x0670, 0, - 4, 0xFCDA, 0x064A, 0x062C, 0, - 4, 0xFCDB, 0x064A, 0x062D, 0, - 4, 0xFCDC, 0x064A, 0x062E, 0, - 4, 0xFCDD, 0x064A, 0x0645, 0, - 4, 0xFCDE, 0x064A, 0x0647, 0, - 5, 0xFCDF, 0x0626, 0x0645, 0, - 5, 0xFCE0, 0x0626, 0x0647, 0, - 5, 0xFCE1, 0x0628, 0x0645, 0, - 5, 0xFCE2, 0x0628, 0x0647, 0, - 5, 0xFCE3, 0x062A, 0x0645, 0, - 5, 0xFCE4, 0x062A, 0x0647, 0, - 5, 0xFCE5, 0x062B, 0x0645, 0, - 5, 0xFCE6, 0x062B, 0x0647, 0, - 5, 0xFCE7, 0x0633, 0x0645, 0, - 5, 0xFCE8, 0x0633, 0x0647, 0, - 5, 0xFCE9, 0x0634, 0x0645, 0, - 5, 0xFCEA, 0x0634, 0x0647, 0, - 5, 0xFCEB, 0x0643, 0x0644, 0, - 5, 0xFCEC, 0x0643, 0x0645, 0, - 5, 0xFCED, 0x0644, 0x0645, 0, - 5, 0xFCEE, 0x0646, 0x0645, 0, - 5, 0xFCEF, 0x0646, 0x0647, 0, - 5, 0xFCF0, 0x064A, 0x0645, 0, - 5, 0xFCF1, 0x064A, 0x0647, 0, - 5, 0xFCF2, 0x0640, 0x064E, 0x0651, 0, - 5, 0xFCF3, 0x0640, 0x064F, 0x0651, 0, - 5, 0xFCF4, 0x0640, 0x0650, 0x0651, 0, - 7, 0xFCF5, 0x0637, 0x0649, 0, - 7, 0xFCF6, 0x0637, 0x064A, 0, - 7, 0xFCF7, 0x0639, 0x0649, 0, - 7, 0xFCF8, 0x0639, 0x064A, 0, - 7, 0xFCF9, 0x063A, 0x0649, 0, - 7, 0xFCFA, 0x063A, 0x064A, 0, - 7, 0xFCFB, 0x0633, 0x0649, 0, - 7, 0xFCFC, 0x0633, 0x064A, 0, - 7, 0xFCFD, 0x0634, 0x0649, 0, - 7, 0xFCFE, 0x0634, 0x064A, 0, - 7, 0xFCFF, 0x062D, 0x0649, 0, - 7, 0xFD00, 0x062D, 0x064A, 0, - 7, 0xFD01, 0x062C, 0x0649, 0, - 7, 0xFD02, 0x062C, 0x064A, 0, - 7, 0xFD03, 0x062E, 0x0649, 0, - 7, 0xFD04, 0x062E, 0x064A, 0, - 7, 0xFD05, 0x0635, 0x0649, 0, - 7, 0xFD06, 0x0635, 0x064A, 0, - 7, 0xFD07, 0x0636, 0x0649, 0, - 7, 0xFD08, 0x0636, 0x064A, 0, - 7, 0xFD09, 0x0634, 0x062C, 0, - 7, 0xFD0A, 0x0634, 0x062D, 0, - 7, 0xFD0B, 0x0634, 0x062E, 0, - 7, 0xFD0C, 0x0634, 0x0645, 0, - 7, 0xFD0D, 0x0634, 0x0631, 0, - 7, 0xFD0E, 0x0633, 0x0631, 0, - 7, 0xFD0F, 0x0635, 0x0631, 0, - 7, 0xFD10, 0x0636, 0x0631, 0, - 6, 0xFD11, 0x0637, 0x0649, 0, - 6, 0xFD12, 0x0637, 0x064A, 0, - 6, 0xFD13, 0x0639, 0x0649, 0, - 6, 0xFD14, 0x0639, 0x064A, 0, - 6, 0xFD15, 0x063A, 0x0649, 0, - 6, 0xFD16, 0x063A, 0x064A, 0, - 6, 0xFD17, 0x0633, 0x0649, 0, - 6, 0xFD18, 0x0633, 0x064A, 0, - 6, 0xFD19, 0x0634, 0x0649, 0, - 6, 0xFD1A, 0x0634, 0x064A, 0, - 6, 0xFD1B, 0x062D, 0x0649, 0, - 6, 0xFD1C, 0x062D, 0x064A, 0, - 6, 0xFD1D, 0x062C, 0x0649, 0, - 6, 0xFD1E, 0x062C, 0x064A, 0, - 6, 0xFD1F, 0x062E, 0x0649, 0, - 6, 0xFD20, 0x062E, 0x064A, 0, - 6, 0xFD21, 0x0635, 0x0649, 0, - 6, 0xFD22, 0x0635, 0x064A, 0, - 6, 0xFD23, 0x0636, 0x0649, 0, - 6, 0xFD24, 0x0636, 0x064A, 0, - 6, 0xFD25, 0x0634, 0x062C, 0, - 6, 0xFD26, 0x0634, 0x062D, 0, - 6, 0xFD27, 0x0634, 0x062E, 0, - 6, 0xFD28, 0x0634, 0x0645, 0, - 6, 0xFD29, 0x0634, 0x0631, 0, - 6, 0xFD2A, 0x0633, 0x0631, 0, - 6, 0xFD2B, 0x0635, 0x0631, 0, - 6, 0xFD2C, 0x0636, 0x0631, 0, - 4, 0xFD2D, 0x0634, 0x062C, 0, - 4, 0xFD2E, 0x0634, 0x062D, 0, - 4, 0xFD2F, 0x0634, 0x062E, 0, - 4, 0xFD30, 0x0634, 0x0645, 0, - 4, 0xFD31, 0x0633, 0x0647, 0, - 4, 0xFD32, 0x0634, 0x0647, 0, - 4, 0xFD33, 0x0637, 0x0645, 0, - 5, 0xFD34, 0x0633, 0x062C, 0, - 5, 0xFD35, 0x0633, 0x062D, 0, - 5, 0xFD36, 0x0633, 0x062E, 0, - 5, 0xFD37, 0x0634, 0x062C, 0, - 5, 0xFD38, 0x0634, 0x062D, 0, - 5, 0xFD39, 0x0634, 0x062E, 0, - 5, 0xFD3A, 0x0637, 0x0645, 0, - 5, 0xFD3B, 0x0638, 0x0645, 0, - 6, 0xFD3C, 0x0627, 0x064B, 0, - 7, 0xFD3D, 0x0627, 0x064B, 0, - 4, 0xFD50, 0x062A, 0x062C, 0x0645, 0, - 6, 0xFD51, 0x062A, 0x062D, 0x062C, 0, - 4, 0xFD52, 0x062A, 0x062D, 0x062C, 0, - 4, 0xFD53, 0x062A, 0x062D, 0x0645, 0, - 4, 0xFD54, 0x062A, 0x062E, 0x0645, 0, - 4, 0xFD55, 0x062A, 0x0645, 0x062C, 0, - 4, 0xFD56, 0x062A, 0x0645, 0x062D, 0, - 4, 0xFD57, 0x062A, 0x0645, 0x062E, 0, - 6, 0xFD58, 0x062C, 0x0645, 0x062D, 0, - 4, 0xFD59, 0x062C, 0x0645, 0x062D, 0, - 6, 0xFD5A, 0x062D, 0x0645, 0x064A, 0, - 6, 0xFD5B, 0x062D, 0x0645, 0x0649, 0, - 4, 0xFD5C, 0x0633, 0x062D, 0x062C, 0, - 4, 0xFD5D, 0x0633, 0x062C, 0x062D, 0, - 6, 0xFD5E, 0x0633, 0x062C, 0x0649, 0, - 6, 0xFD5F, 0x0633, 0x0645, 0x062D, 0, - 4, 0xFD60, 0x0633, 0x0645, 0x062D, 0, - 4, 0xFD61, 0x0633, 0x0645, 0x062C, 0, - 6, 0xFD62, 0x0633, 0x0645, 0x0645, 0, - 4, 0xFD63, 0x0633, 0x0645, 0x0645, 0, - 6, 0xFD64, 0x0635, 0x062D, 0x062D, 0, - 4, 0xFD65, 0x0635, 0x062D, 0x062D, 0, - 6, 0xFD66, 0x0635, 0x0645, 0x0645, 0, - 6, 0xFD67, 0x0634, 0x062D, 0x0645, 0, - 4, 0xFD68, 0x0634, 0x062D, 0x0645, 0, - 6, 0xFD69, 0x0634, 0x062C, 0x064A, 0, - 6, 0xFD6A, 0x0634, 0x0645, 0x062E, 0, - 4, 0xFD6B, 0x0634, 0x0645, 0x062E, 0, - 6, 0xFD6C, 0x0634, 0x0645, 0x0645, 0, - 4, 0xFD6D, 0x0634, 0x0645, 0x0645, 0, - 6, 0xFD6E, 0x0636, 0x062D, 0x0649, 0, - 6, 0xFD6F, 0x0636, 0x062E, 0x0645, 0, - 4, 0xFD70, 0x0636, 0x062E, 0x0645, 0, - 6, 0xFD71, 0x0637, 0x0645, 0x062D, 0, - 4, 0xFD72, 0x0637, 0x0645, 0x062D, 0, - 4, 0xFD73, 0x0637, 0x0645, 0x0645, 0, - 6, 0xFD74, 0x0637, 0x0645, 0x064A, 0, - 6, 0xFD75, 0x0639, 0x062C, 0x0645, 0, - 6, 0xFD76, 0x0639, 0x0645, 0x0645, 0, - 4, 0xFD77, 0x0639, 0x0645, 0x0645, 0, - 6, 0xFD78, 0x0639, 0x0645, 0x0649, 0, - 6, 0xFD79, 0x063A, 0x0645, 0x0645, 0, - 6, 0xFD7A, 0x063A, 0x0645, 0x064A, 0, - 6, 0xFD7B, 0x063A, 0x0645, 0x0649, 0, - 6, 0xFD7C, 0x0641, 0x062E, 0x0645, 0, - 4, 0xFD7D, 0x0641, 0x062E, 0x0645, 0, - 6, 0xFD7E, 0x0642, 0x0645, 0x062D, 0, - 6, 0xFD7F, 0x0642, 0x0645, 0x0645, 0, - 6, 0xFD80, 0x0644, 0x062D, 0x0645, 0, - 6, 0xFD81, 0x0644, 0x062D, 0x064A, 0, - 6, 0xFD82, 0x0644, 0x062D, 0x0649, 0, - 4, 0xFD83, 0x0644, 0x062C, 0x062C, 0, - 6, 0xFD84, 0x0644, 0x062C, 0x062C, 0, - 6, 0xFD85, 0x0644, 0x062E, 0x0645, 0, - 4, 0xFD86, 0x0644, 0x062E, 0x0645, 0, - 6, 0xFD87, 0x0644, 0x0645, 0x062D, 0, - 4, 0xFD88, 0x0644, 0x0645, 0x062D, 0, - 4, 0xFD89, 0x0645, 0x062D, 0x062C, 0, - 4, 0xFD8A, 0x0645, 0x062D, 0x0645, 0, - 6, 0xFD8B, 0x0645, 0x062D, 0x064A, 0, - 4, 0xFD8C, 0x0645, 0x062C, 0x062D, 0, - 4, 0xFD8D, 0x0645, 0x062C, 0x0645, 0, - 4, 0xFD8E, 0x0645, 0x062E, 0x062C, 0, - 4, 0xFD8F, 0x0645, 0x062E, 0x0645, 0, - 4, 0xFD92, 0x0645, 0x062C, 0x062E, 0, - 4, 0xFD93, 0x0647, 0x0645, 0x062C, 0, - 4, 0xFD94, 0x0647, 0x0645, 0x0645, 0, - 4, 0xFD95, 0x0646, 0x062D, 0x0645, 0, - 6, 0xFD96, 0x0646, 0x062D, 0x0649, 0, - 6, 0xFD97, 0x0646, 0x062C, 0x0645, 0, - 4, 0xFD98, 0x0646, 0x062C, 0x0645, 0, - 6, 0xFD99, 0x0646, 0x062C, 0x0649, 0, - 6, 0xFD9A, 0x0646, 0x0645, 0x064A, 0, - 6, 0xFD9B, 0x0646, 0x0645, 0x0649, 0, - 6, 0xFD9C, 0x064A, 0x0645, 0x0645, 0, - 4, 0xFD9D, 0x064A, 0x0645, 0x0645, 0, - 6, 0xFD9E, 0x0628, 0x062E, 0x064A, 0, - 6, 0xFD9F, 0x062A, 0x062C, 0x064A, 0, - 6, 0xFDA0, 0x062A, 0x062C, 0x0649, 0, - 6, 0xFDA1, 0x062A, 0x062E, 0x064A, 0, - 6, 0xFDA2, 0x062A, 0x062E, 0x0649, 0, - 6, 0xFDA3, 0x062A, 0x0645, 0x064A, 0, - 6, 0xFDA4, 0x062A, 0x0645, 0x0649, 0, - 6, 0xFDA5, 0x062C, 0x0645, 0x064A, 0, - 6, 0xFDA6, 0x062C, 0x062D, 0x0649, 0, - 6, 0xFDA7, 0x062C, 0x0645, 0x0649, 0, - 6, 0xFDA8, 0x0633, 0x062E, 0x0649, 0, - 6, 0xFDA9, 0x0635, 0x062D, 0x064A, 0, - 6, 0xFDAA, 0x0634, 0x062D, 0x064A, 0, - 6, 0xFDAB, 0x0636, 0x062D, 0x064A, 0, - 6, 0xFDAC, 0x0644, 0x062C, 0x064A, 0, - 6, 0xFDAD, 0x0644, 0x0645, 0x064A, 0, - 6, 0xFDAE, 0x064A, 0x062D, 0x064A, 0, - 6, 0xFDAF, 0x064A, 0x062C, 0x064A, 0, - 6, 0xFDB0, 0x064A, 0x0645, 0x064A, 0, - 6, 0xFDB1, 0x0645, 0x0645, 0x064A, 0, - 6, 0xFDB2, 0x0642, 0x0645, 0x064A, 0, - 6, 0xFDB3, 0x0646, 0x062D, 0x064A, 0, - 4, 0xFDB4, 0x0642, 0x0645, 0x062D, 0, - 4, 0xFDB5, 0x0644, 0x062D, 0x0645, 0, - 6, 0xFDB6, 0x0639, 0x0645, 0x064A, 0, - 6, 0xFDB7, 0x0643, 0x0645, 0x064A, 0, - 4, 0xFDB8, 0x0646, 0x062C, 0x062D, 0, - 6, 0xFDB9, 0x0645, 0x062E, 0x064A, 0, - 4, 0xFDBA, 0x0644, 0x062C, 0x0645, 0, - 6, 0xFDBB, 0x0643, 0x0645, 0x0645, 0, - 6, 0xFDBC, 0x0644, 0x062C, 0x0645, 0, - 6, 0xFDBD, 0x0646, 0x062C, 0x062D, 0, - 6, 0xFDBE, 0x062C, 0x062D, 0x064A, 0, - 6, 0xFDBF, 0x062D, 0x062C, 0x064A, 0, - 6, 0xFDC0, 0x0645, 0x062C, 0x064A, 0, - 6, 0xFDC1, 0x0641, 0x0645, 0x064A, 0, - 6, 0xFDC2, 0x0628, 0x062D, 0x064A, 0, - 4, 0xFDC3, 0x0643, 0x0645, 0x0645, 0, - 4, 0xFDC4, 0x0639, 0x062C, 0x0645, 0, - 4, 0xFDC5, 0x0635, 0x0645, 0x0645, 0, - 6, 0xFDC6, 0x0633, 0x062E, 0x064A, 0, - 6, 0xFDC7, 0x0646, 0x062C, 0x064A, 0, - 7, 0xFDF0, 0x0635, 0x0644, 0x06D2, 0, - 7, 0xFDF1, 0x0642, 0x0644, 0x06D2, 0, - 7, 0xFDF2, 0x0627, 0x0644, 0x0644, 0x0647, 0, - 7, 0xFDF3, 0x0627, 0x0643, 0x0628, 0x0631, 0, - 7, 0xFDF4, 0x0645, 0x062D, 0x0645, 0x062F, 0, - 7, 0xFDF5, 0x0635, 0x0644, 0x0639, 0x0645, 0, - 7, 0xFDF6, 0x0631, 0x0633, 0x0648, 0x0644, 0, - 7, 0xFDF7, 0x0639, 0x0644, 0x064A, 0x0647, 0, - 7, 0xFDF8, 0x0648, 0x0633, 0x0644, 0x0645, 0, - 7, 0xFDF9, 0x0635, 0x0644, 0x0649, 0, - 7, 0xFDFA, 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645, 0, - 7, 0xFDFB, 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647, 0, - 7, 0xFDFC, 0x0631, 0x06CC, 0x0627, 0x0644, 0, - 11, 0xFE30, 0x2025, 0, - 11, 0xFE31, 0x2014, 0, - 11, 0xFE32, 0x2013, 0, - 11, 0xFE33, 0x005F, 0, - 11, 0xFE34, 0x005F, 0, - 11, 0xFE35, 0x0028, 0, - 11, 0xFE36, 0x0029, 0, - 11, 0xFE37, 0x007B, 0, - 11, 0xFE38, 0x007D, 0, - 11, 0xFE39, 0x3014, 0, - 11, 0xFE3A, 0x3015, 0, - 11, 0xFE3B, 0x3010, 0, - 11, 0xFE3C, 0x3011, 0, - 11, 0xFE3D, 0x300A, 0, - 11, 0xFE3E, 0x300B, 0, - 11, 0xFE3F, 0x3008, 0, - 11, 0xFE40, 0x3009, 0, - 11, 0xFE41, 0x300C, 0, - 11, 0xFE42, 0x300D, 0, - 11, 0xFE43, 0x300E, 0, - 11, 0xFE44, 0x300F, 0, - 16, 0xFE49, 0x203E, 0, - 16, 0xFE4A, 0x203E, 0, - 16, 0xFE4B, 0x203E, 0, - 16, 0xFE4C, 0x203E, 0, - 16, 0xFE4D, 0x005F, 0, - 16, 0xFE4E, 0x005F, 0, - 16, 0xFE4F, 0x005F, 0, - 14, 0xFE50, 0x002C, 0, - 14, 0xFE51, 0x3001, 0, - 14, 0xFE52, 0x002E, 0, - 14, 0xFE54, 0x003B, 0, - 14, 0xFE55, 0x003A, 0, - 14, 0xFE56, 0x003F, 0, - 14, 0xFE57, 0x0021, 0, - 14, 0xFE58, 0x2014, 0, - 14, 0xFE59, 0x0028, 0, - 14, 0xFE5A, 0x0029, 0, - 14, 0xFE5B, 0x007B, 0, - 14, 0xFE5C, 0x007D, 0, - 14, 0xFE5D, 0x3014, 0, - 14, 0xFE5E, 0x3015, 0, - 14, 0xFE5F, 0x0023, 0, - 14, 0xFE60, 0x0026, 0, - 14, 0xFE61, 0x002A, 0, - 14, 0xFE62, 0x002B, 0, - 14, 0xFE63, 0x002D, 0, - 14, 0xFE64, 0x003C, 0, - 14, 0xFE65, 0x003E, 0, - 14, 0xFE66, 0x003D, 0, - 14, 0xFE68, 0x005C, 0, - 14, 0xFE69, 0x0024, 0, - 14, 0xFE6A, 0x0025, 0, - 14, 0xFE6B, 0x0040, 0, - 7, 0xFE70, 0x0020, 0x064B, 0, - 5, 0xFE71, 0x0640, 0x064B, 0, - 7, 0xFE72, 0x0020, 0x064C, 0, - 7, 0xFE74, 0x0020, 0x064D, 0, - 7, 0xFE76, 0x0020, 0x064E, 0, - 5, 0xFE77, 0x0640, 0x064E, 0, - 7, 0xFE78, 0x0020, 0x064F, 0, - 5, 0xFE79, 0x0640, 0x064F, 0, - 7, 0xFE7A, 0x0020, 0x0650, 0, - 5, 0xFE7B, 0x0640, 0x0650, 0, - 7, 0xFE7C, 0x0020, 0x0651, 0, - 5, 0xFE7D, 0x0640, 0x0651, 0, - 7, 0xFE7E, 0x0020, 0x0652, 0, - 5, 0xFE7F, 0x0640, 0x0652, 0, - 7, 0xFE80, 0x0621, 0, - 7, 0xFE81, 0x0622, 0, - 6, 0xFE82, 0x0622, 0, - 7, 0xFE83, 0x0623, 0, - 6, 0xFE84, 0x0623, 0, - 7, 0xFE85, 0x0624, 0, - 6, 0xFE86, 0x0624, 0, - 7, 0xFE87, 0x0625, 0, - 6, 0xFE88, 0x0625, 0, - 7, 0xFE89, 0x0626, 0, - 6, 0xFE8A, 0x0626, 0, - 4, 0xFE8B, 0x0626, 0, - 5, 0xFE8C, 0x0626, 0, - 7, 0xFE8D, 0x0627, 0, - 6, 0xFE8E, 0x0627, 0, - 7, 0xFE8F, 0x0628, 0, - 6, 0xFE90, 0x0628, 0, - 4, 0xFE91, 0x0628, 0, - 5, 0xFE92, 0x0628, 0, - 7, 0xFE93, 0x0629, 0, - 6, 0xFE94, 0x0629, 0, - 7, 0xFE95, 0x062A, 0, - 6, 0xFE96, 0x062A, 0, - 4, 0xFE97, 0x062A, 0, - 5, 0xFE98, 0x062A, 0, - 7, 0xFE99, 0x062B, 0, - 6, 0xFE9A, 0x062B, 0, - 4, 0xFE9B, 0x062B, 0, - 5, 0xFE9C, 0x062B, 0, - 7, 0xFE9D, 0x062C, 0, - 6, 0xFE9E, 0x062C, 0, - 4, 0xFE9F, 0x062C, 0, - 5, 0xFEA0, 0x062C, 0, - 7, 0xFEA1, 0x062D, 0, - 6, 0xFEA2, 0x062D, 0, - 4, 0xFEA3, 0x062D, 0, - 5, 0xFEA4, 0x062D, 0, - 7, 0xFEA5, 0x062E, 0, - 6, 0xFEA6, 0x062E, 0, - 4, 0xFEA7, 0x062E, 0, - 5, 0xFEA8, 0x062E, 0, - 7, 0xFEA9, 0x062F, 0, - 6, 0xFEAA, 0x062F, 0, - 7, 0xFEAB, 0x0630, 0, - 6, 0xFEAC, 0x0630, 0, - 7, 0xFEAD, 0x0631, 0, - 6, 0xFEAE, 0x0631, 0, - 7, 0xFEAF, 0x0632, 0, - 6, 0xFEB0, 0x0632, 0, - 7, 0xFEB1, 0x0633, 0, - 6, 0xFEB2, 0x0633, 0, - 4, 0xFEB3, 0x0633, 0, - 5, 0xFEB4, 0x0633, 0, - 7, 0xFEB5, 0x0634, 0, - 6, 0xFEB6, 0x0634, 0, - 4, 0xFEB7, 0x0634, 0, - 5, 0xFEB8, 0x0634, 0, - 7, 0xFEB9, 0x0635, 0, - 6, 0xFEBA, 0x0635, 0, - 4, 0xFEBB, 0x0635, 0, - 5, 0xFEBC, 0x0635, 0, - 7, 0xFEBD, 0x0636, 0, - 6, 0xFEBE, 0x0636, 0, - 4, 0xFEBF, 0x0636, 0, - 5, 0xFEC0, 0x0636, 0, - 7, 0xFEC1, 0x0637, 0, - 6, 0xFEC2, 0x0637, 0, - 4, 0xFEC3, 0x0637, 0, - 5, 0xFEC4, 0x0637, 0, - 7, 0xFEC5, 0x0638, 0, - 6, 0xFEC6, 0x0638, 0, - 4, 0xFEC7, 0x0638, 0, - 5, 0xFEC8, 0x0638, 0, - 7, 0xFEC9, 0x0639, 0, - 6, 0xFECA, 0x0639, 0, - 4, 0xFECB, 0x0639, 0, - 5, 0xFECC, 0x0639, 0, - 7, 0xFECD, 0x063A, 0, - 6, 0xFECE, 0x063A, 0, - 4, 0xFECF, 0x063A, 0, - 5, 0xFED0, 0x063A, 0, - 7, 0xFED1, 0x0641, 0, - 6, 0xFED2, 0x0641, 0, - 4, 0xFED3, 0x0641, 0, - 5, 0xFED4, 0x0641, 0, - 7, 0xFED5, 0x0642, 0, - 6, 0xFED6, 0x0642, 0, - 4, 0xFED7, 0x0642, 0, - 5, 0xFED8, 0x0642, 0, - 7, 0xFED9, 0x0643, 0, - 6, 0xFEDA, 0x0643, 0, - 4, 0xFEDB, 0x0643, 0, - 5, 0xFEDC, 0x0643, 0, - 7, 0xFEDD, 0x0644, 0, - 6, 0xFEDE, 0x0644, 0, - 4, 0xFEDF, 0x0644, 0, - 5, 0xFEE0, 0x0644, 0, - 7, 0xFEE1, 0x0645, 0, - 6, 0xFEE2, 0x0645, 0, - 4, 0xFEE3, 0x0645, 0, - 5, 0xFEE4, 0x0645, 0, - 7, 0xFEE5, 0x0646, 0, - 6, 0xFEE6, 0x0646, 0, - 4, 0xFEE7, 0x0646, 0, - 5, 0xFEE8, 0x0646, 0, - 7, 0xFEE9, 0x0647, 0, - 6, 0xFEEA, 0x0647, 0, - 4, 0xFEEB, 0x0647, 0, - 5, 0xFEEC, 0x0647, 0, - 7, 0xFEED, 0x0648, 0, - 6, 0xFEEE, 0x0648, 0, - 7, 0xFEEF, 0x0649, 0, - 6, 0xFEF0, 0x0649, 0, - 7, 0xFEF1, 0x064A, 0, - 6, 0xFEF2, 0x064A, 0, - 4, 0xFEF3, 0x064A, 0, - 5, 0xFEF4, 0x064A, 0, - 7, 0xFEF5, 0x0644, 0x0622, 0, - 6, 0xFEF6, 0x0644, 0x0622, 0, - 7, 0xFEF7, 0x0644, 0x0623, 0, - 6, 0xFEF8, 0x0644, 0x0623, 0, - 7, 0xFEF9, 0x0644, 0x0625, 0, - 6, 0xFEFA, 0x0644, 0x0625, 0, - 7, 0xFEFB, 0x0644, 0x0627, 0, - 6, 0xFEFC, 0x0644, 0x0627, 0, - 12, 0xFF01, 0x0021, 0, - 12, 0xFF02, 0x0022, 0, - 12, 0xFF03, 0x0023, 0, - 12, 0xFF04, 0x0024, 0, - 12, 0xFF05, 0x0025, 0, - 12, 0xFF06, 0x0026, 0, - 12, 0xFF07, 0x0027, 0, - 12, 0xFF08, 0x0028, 0, - 12, 0xFF09, 0x0029, 0, - 12, 0xFF0A, 0x002A, 0, - 12, 0xFF0B, 0x002B, 0, - 12, 0xFF0C, 0x002C, 0, - 12, 0xFF0D, 0x002D, 0, - 12, 0xFF0E, 0x002E, 0, - 12, 0xFF0F, 0x002F, 0, - 12, 0xFF10, 0x0030, 0, - 12, 0xFF11, 0x0031, 0, - 12, 0xFF12, 0x0032, 0, - 12, 0xFF13, 0x0033, 0, - 12, 0xFF14, 0x0034, 0, - 12, 0xFF15, 0x0035, 0, - 12, 0xFF16, 0x0036, 0, - 12, 0xFF17, 0x0037, 0, - 12, 0xFF18, 0x0038, 0, - 12, 0xFF19, 0x0039, 0, - 12, 0xFF1A, 0x003A, 0, - 12, 0xFF1B, 0x003B, 0, - 12, 0xFF1C, 0x003C, 0, - 12, 0xFF1D, 0x003D, 0, - 12, 0xFF1E, 0x003E, 0, - 12, 0xFF1F, 0x003F, 0, - 12, 0xFF20, 0x0040, 0, - 12, 0xFF21, 0x0041, 0, - 12, 0xFF22, 0x0042, 0, - 12, 0xFF23, 0x0043, 0, - 12, 0xFF24, 0x0044, 0, - 12, 0xFF25, 0x0045, 0, - 12, 0xFF26, 0x0046, 0, - 12, 0xFF27, 0x0047, 0, - 12, 0xFF28, 0x0048, 0, - 12, 0xFF29, 0x0049, 0, - 12, 0xFF2A, 0x004A, 0, - 12, 0xFF2B, 0x004B, 0, - 12, 0xFF2C, 0x004C, 0, - 12, 0xFF2D, 0x004D, 0, - 12, 0xFF2E, 0x004E, 0, - 12, 0xFF2F, 0x004F, 0, - 12, 0xFF30, 0x0050, 0, - 12, 0xFF31, 0x0051, 0, - 12, 0xFF32, 0x0052, 0, - 12, 0xFF33, 0x0053, 0, - 12, 0xFF34, 0x0054, 0, - 12, 0xFF35, 0x0055, 0, - 12, 0xFF36, 0x0056, 0, - 12, 0xFF37, 0x0057, 0, - 12, 0xFF38, 0x0058, 0, - 12, 0xFF39, 0x0059, 0, - 12, 0xFF3A, 0x005A, 0, - 12, 0xFF3B, 0x005B, 0, - 12, 0xFF3C, 0x005C, 0, - 12, 0xFF3D, 0x005D, 0, - 12, 0xFF3E, 0x005E, 0, - 12, 0xFF3F, 0x005F, 0, - 12, 0xFF40, 0x0060, 0, - 12, 0xFF41, 0x0061, 0, - 12, 0xFF42, 0x0062, 0, - 12, 0xFF43, 0x0063, 0, - 12, 0xFF44, 0x0064, 0, - 12, 0xFF45, 0x0065, 0, - 12, 0xFF46, 0x0066, 0, - 12, 0xFF47, 0x0067, 0, - 12, 0xFF48, 0x0068, 0, - 12, 0xFF49, 0x0069, 0, - 12, 0xFF4A, 0x006A, 0, - 12, 0xFF4B, 0x006B, 0, - 12, 0xFF4C, 0x006C, 0, - 12, 0xFF4D, 0x006D, 0, - 12, 0xFF4E, 0x006E, 0, - 12, 0xFF4F, 0x006F, 0, - 12, 0xFF50, 0x0070, 0, - 12, 0xFF51, 0x0071, 0, - 12, 0xFF52, 0x0072, 0, - 12, 0xFF53, 0x0073, 0, - 12, 0xFF54, 0x0074, 0, - 12, 0xFF55, 0x0075, 0, - 12, 0xFF56, 0x0076, 0, - 12, 0xFF57, 0x0077, 0, - 12, 0xFF58, 0x0078, 0, - 12, 0xFF59, 0x0079, 0, - 12, 0xFF5A, 0x007A, 0, - 12, 0xFF5B, 0x007B, 0, - 12, 0xFF5C, 0x007C, 0, - 12, 0xFF5D, 0x007D, 0, - 12, 0xFF5E, 0x007E, 0, - 12, 0xFF5F, 0x2985, 0, - 12, 0xFF60, 0x2986, 0, - 13, 0xFF61, 0x3002, 0, - 13, 0xFF62, 0x300C, 0, - 13, 0xFF63, 0x300D, 0, - 13, 0xFF64, 0x3001, 0, - 13, 0xFF65, 0x30FB, 0, - 13, 0xFF66, 0x30F2, 0, - 13, 0xFF67, 0x30A1, 0, - 13, 0xFF68, 0x30A3, 0, - 13, 0xFF69, 0x30A5, 0, - 13, 0xFF6A, 0x30A7, 0, - 13, 0xFF6B, 0x30A9, 0, - 13, 0xFF6C, 0x30E3, 0, - 13, 0xFF6D, 0x30E5, 0, - 13, 0xFF6E, 0x30E7, 0, - 13, 0xFF6F, 0x30C3, 0, - 13, 0xFF70, 0x30FC, 0, - 13, 0xFF71, 0x30A2, 0, - 13, 0xFF72, 0x30A4, 0, - 13, 0xFF73, 0x30A6, 0, - 13, 0xFF74, 0x30A8, 0, - 13, 0xFF75, 0x30AA, 0, - 13, 0xFF76, 0x30AB, 0, - 13, 0xFF77, 0x30AD, 0, - 13, 0xFF78, 0x30AF, 0, - 13, 0xFF79, 0x30B1, 0, - 13, 0xFF7A, 0x30B3, 0, - 13, 0xFF7B, 0x30B5, 0, - 13, 0xFF7C, 0x30B7, 0, - 13, 0xFF7D, 0x30B9, 0, - 13, 0xFF7E, 0x30BB, 0, - 13, 0xFF7F, 0x30BD, 0, - 13, 0xFF80, 0x30BF, 0, - 13, 0xFF81, 0x30C1, 0, - 13, 0xFF82, 0x30C4, 0, - 13, 0xFF83, 0x30C6, 0, - 13, 0xFF84, 0x30C8, 0, - 13, 0xFF85, 0x30CA, 0, - 13, 0xFF86, 0x30CB, 0, - 13, 0xFF87, 0x30CC, 0, - 13, 0xFF88, 0x30CD, 0, - 13, 0xFF89, 0x30CE, 0, - 13, 0xFF8A, 0x30CF, 0, - 13, 0xFF8B, 0x30D2, 0, - 13, 0xFF8C, 0x30D5, 0, - 13, 0xFF8D, 0x30D8, 0, - 13, 0xFF8E, 0x30DB, 0, - 13, 0xFF8F, 0x30DE, 0, - 13, 0xFF90, 0x30DF, 0, - 13, 0xFF91, 0x30E0, 0, - 13, 0xFF92, 0x30E1, 0, - 13, 0xFF93, 0x30E2, 0, - 13, 0xFF94, 0x30E4, 0, - 13, 0xFF95, 0x30E6, 0, - 13, 0xFF96, 0x30E8, 0, - 13, 0xFF97, 0x30E9, 0, - 13, 0xFF98, 0x30EA, 0, - 13, 0xFF99, 0x30EB, 0, - 13, 0xFF9A, 0x30EC, 0, - 13, 0xFF9B, 0x30ED, 0, - 13, 0xFF9C, 0x30EF, 0, - 13, 0xFF9D, 0x30F3, 0, - 13, 0xFF9E, 0x3099, 0, - 13, 0xFF9F, 0x309A, 0, - 13, 0xFFA0, 0x3164, 0, - 13, 0xFFA1, 0x3131, 0, - 13, 0xFFA2, 0x3132, 0, - 13, 0xFFA3, 0x3133, 0, - 13, 0xFFA4, 0x3134, 0, - 13, 0xFFA5, 0x3135, 0, - 13, 0xFFA6, 0x3136, 0, - 13, 0xFFA7, 0x3137, 0, - 13, 0xFFA8, 0x3138, 0, - 13, 0xFFA9, 0x3139, 0, - 13, 0xFFAA, 0x313A, 0, - 13, 0xFFAB, 0x313B, 0, - 13, 0xFFAC, 0x313C, 0, - 13, 0xFFAD, 0x313D, 0, - 13, 0xFFAE, 0x313E, 0, - 13, 0xFFAF, 0x313F, 0, - 13, 0xFFB0, 0x3140, 0, - 13, 0xFFB1, 0x3141, 0, - 13, 0xFFB2, 0x3142, 0, - 13, 0xFFB3, 0x3143, 0, - 13, 0xFFB4, 0x3144, 0, - 13, 0xFFB5, 0x3145, 0, - 13, 0xFFB6, 0x3146, 0, - 13, 0xFFB7, 0x3147, 0, - 13, 0xFFB8, 0x3148, 0, - 13, 0xFFB9, 0x3149, 0, - 13, 0xFFBA, 0x314A, 0, - 13, 0xFFBB, 0x314B, 0, - 13, 0xFFBC, 0x314C, 0, - 13, 0xFFBD, 0x314D, 0, - 13, 0xFFBE, 0x314E, 0, - 13, 0xFFC2, 0x314F, 0, - 13, 0xFFC3, 0x3150, 0, - 13, 0xFFC4, 0x3151, 0, - 13, 0xFFC5, 0x3152, 0, - 13, 0xFFC6, 0x3153, 0, - 13, 0xFFC7, 0x3154, 0, - 13, 0xFFCA, 0x3155, 0, - 13, 0xFFCB, 0x3156, 0, - 13, 0xFFCC, 0x3157, 0, - 13, 0xFFCD, 0x3158, 0, - 13, 0xFFCE, 0x3159, 0, - 13, 0xFFCF, 0x315A, 0, - 13, 0xFFD2, 0x315B, 0, - 13, 0xFFD3, 0x315C, 0, - 13, 0xFFD4, 0x315D, 0, - 13, 0xFFD5, 0x315E, 0, - 13, 0xFFD6, 0x315F, 0, - 13, 0xFFD7, 0x3160, 0, - 13, 0xFFDA, 0x3161, 0, - 13, 0xFFDB, 0x3162, 0, - 13, 0xFFDC, 0x3163, 0, - 12, 0xFFE0, 0x00A2, 0, - 12, 0xFFE1, 0x00A3, 0, - 12, 0xFFE2, 0x00AC, 0, - 12, 0xFFE3, 0x00AF, 0, - 12, 0xFFE4, 0x00A6, 0, - 12, 0xFFE5, 0x00A5, 0, - 12, 0xFFE6, 0x20A9, 0, - 13, 0xFFE8, 0x2502, 0, - 13, 0xFFE9, 0x2190, 0, - 13, 0xFFEA, 0x2191, 0, - 13, 0xFFEB, 0x2192, 0, - 13, 0xFFEC, 0x2193, 0, - 13, 0xFFED, 0x25A0, 0, - 13, 0xFFEE, 0x25CB, 0, - -}; - -const TQ_UINT16 TQUnicodeTables::decomposition_info[] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 17, 18, - 19, 20, 21, 22, 23, 8, 8, 8, - 8, 8, 24, 8, 8, 8, 25, 26, - 27, 28, 29, 30, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 31, 32, 33, 34, 35, 36, 37, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 10, 0, 0, 0, 0, 14, - 0, 0, 19, 23, 27, 32, 0, 0, - 36, 41, 45, 0, 49, 55, 61, 0, - 67, 72, 77, 82, 87, 92, 0, 97, - 102, 107, 112, 117, 122, 127, 132, 137, - 0, 142, 147, 152, 157, 162, 167, 0, - 0, 172, 177, 182, 187, 192, 0, 0, - 197, 202, 207, 212, 217, 222, 0, 227, - 232, 237, 242, 247, 252, 257, 262, 267, - 0, 272, 277, 282, 287, 292, 297, 0, - 0, 302, 307, 312, 317, 322, 0, 327, - - 332, 337, 342, 347, 352, 357, 362, 367, - 372, 377, 382, 387, 392, 397, 402, 407, - 0, 0, 412, 417, 422, 427, 432, 437, - 442, 447, 452, 457, 462, 467, 472, 477, - 482, 487, 492, 497, 502, 507, 0, 0, - 512, 517, 522, 527, 532, 537, 542, 547, - 552, 0, 557, 562, 567, 572, 577, 582, - 0, 587, 592, 597, 602, 607, 612, 617, - 622, 0, 0, 627, 632, 637, 642, 647, - 652, 657, 0, 0, 662, 667, 672, 677, - 682, 687, 0, 0, 692, 697, 702, 707, - 712, 717, 722, 727, 732, 737, 742, 747, - 752, 757, 762, 767, 772, 777, 0, 0, - 782, 787, 792, 797, 802, 807, 812, 817, - 822, 827, 832, 837, 842, 847, 852, 857, - 862, 867, 872, 877, 882, 887, 892, 897, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 901, 906, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 911, - 916, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 921, 926, 931, 936, - 941, 946, 951, 956, 961, 966, 971, 976, - 981, 986, 991, 996, 1001, 1006, 1011, 1016, - 1021, 1026, 1031, 1036, 1041, 0, 1046, 1051, - 1056, 1061, 1066, 1071, 0, 0, 1076, 1081, - 1086, 1091, 1096, 1101, 1106, 1111, 1116, 1121, - 1126, 1131, 1136, 1141, 1146, 1151, 0, 0, - 1156, 1161, 1166, 1171, 1176, 1181, 1186, 1191, - - 1196, 1201, 1206, 1211, 1216, 1221, 1226, 1231, - 1236, 1241, 1246, 1251, 1256, 1261, 1266, 1271, - 1276, 1281, 1286, 1291, 1296, 1301, 1306, 1311, - 1316, 1321, 1326, 1331, 0, 0, 1336, 1341, - 0, 0, 0, 0, 0, 0, 1346, 1351, - 1356, 1361, 1366, 1371, 1376, 1381, 1386, 1391, - 1396, 1401, 1406, 1411, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1416, 1420, 1424, 1428, 1432, 1436, 1440, 1444, - 1448, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1452, 1457, 1462, 1467, 1472, 1477, 0, 0, - 1482, 1486, 1490, 1494, 1498, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1502, 1506, 0, 1510, 1514, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1519, 0, 0, 0, - 0, 0, 1523, 0, 0, 0, 1528, 0, - 0, 0, 0, 0, 1532, 1537, 1542, 1547, - 1551, 1556, 1561, 0, 1566, 0, 1571, 1576, - 1581, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1586, 1591, 1596, 1601, 1606, 1611, - 1616, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1621, 1626, 1631, 1636, 1641, 0, - 1646, 1650, 1654, 1658, 1663, 1668, 1672, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1676, 1680, 0, 0, 1684, 1688, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 1692, 1697, 0, 1702, 0, 0, 0, 1707, - 0, 0, 0, 0, 1712, 1717, 1722, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1727, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1732, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1737, 1742, 0, 1747, 0, 0, 0, 1752, - 0, 0, 0, 0, 1757, 1762, 1767, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1772, 1777, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1782, 1787, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1792, 1797, 1802, 1807, 0, 0, 1812, 1817, - 0, 0, 1822, 1827, 1832, 1837, 1842, 1847, - 0, 0, 1852, 1857, 1862, 1867, 1872, 1877, - 0, 0, 1882, 1887, 1892, 1897, 1902, 1907, - 1912, 1917, 1922, 1927, 1932, 1937, 0, 0, - 1942, 1947, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1952, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1957, 1962, 1967, 1972, 1977, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1982, 1987, 1992, - 1997, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2002, 0, 2007, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2012, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2017, 0, 0, 0, 0, 0, 0, - 0, 2022, 0, 0, 2027, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2032, 2037, 2042, 2047, 2052, 2057, 2062, 2067, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2072, 2077, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2082, 2087, 0, 2092, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2097, 0, 0, 2102, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2107, 2112, 2117, 0, 0, 2122, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2127, 0, 0, 2132, 2137, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2142, 2147, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2152, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2157, 2162, 2167, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2172, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2177, 0, 0, 0, 0, 0, 0, 2182, - 2187, 0, 2192, 2197, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2202, 2207, 2212, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2217, 0, 2222, 2227, 2232, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2237, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2242, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2247, 2252, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2257, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2261, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2266, 0, 0, - 0, 0, 2271, 0, 0, 0, 0, 2276, - 0, 0, 0, 0, 2281, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2286, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2291, 0, 2296, 2301, 2306, - 2311, 2316, 0, 0, 0, 0, 0, 0, - 0, 2321, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2326, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2331, 0, 0, - 0, 0, 2336, 0, 0, 0, 0, 2341, - 0, 0, 0, 0, 2346, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2351, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2356, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 2361, 2366, 2371, 2376, 2381, 2386, 2391, 2396, - 2401, 2406, 2411, 2416, 2421, 2426, 2431, 2436, - 2441, 2446, 2451, 2456, 2461, 2466, 2471, 2476, - 2481, 2486, 2491, 2496, 2501, 2506, 2511, 2516, - 2521, 2526, 2531, 2536, 2541, 2546, 2551, 2556, - 2561, 2566, 2571, 2576, 2581, 2586, 2591, 2596, - 2601, 2606, 2611, 2616, 2621, 2626, 2631, 2636, - 2641, 2646, 2651, 2656, 2661, 2666, 2671, 2676, - 2681, 2686, 2691, 2696, 2701, 2706, 2711, 2716, - 2721, 2726, 2731, 2736, 2741, 2746, 2751, 2756, - 2761, 2766, 2771, 2776, 2781, 2786, 2791, 2796, - 2801, 2806, 2811, 2816, 2821, 2826, 2831, 2836, - 2841, 2846, 2851, 2856, 2861, 2866, 2871, 2876, - 2881, 2886, 2891, 2896, 2901, 2906, 2911, 2916, - 2921, 2926, 2931, 2936, 2941, 2946, 2951, 2956, - 2961, 2966, 2971, 2976, 2981, 2986, 2991, 2996, - 3001, 3006, 3011, 3016, 3021, 3026, 3031, 3036, - 3041, 3046, 3051, 3056, 3061, 3066, 3071, 3076, - 3081, 3086, 3091, 3096, 3101, 3106, 3111, 3116, - 3121, 3126, 3131, 3136, 0, 0, 0, 0, - 3141, 3146, 3151, 3156, 3161, 3166, 3171, 3176, - 3181, 3186, 3191, 3196, 3201, 3206, 3211, 3216, - 3221, 3226, 3231, 3236, 3241, 3246, 3251, 3256, - 3261, 3266, 3271, 3276, 3281, 3286, 3291, 3296, - 3301, 3306, 3311, 3316, 3321, 3326, 3331, 3336, - 3341, 3346, 3351, 3356, 3361, 3366, 3371, 3376, - 3381, 3386, 3391, 3396, 3401, 3406, 3411, 3416, - 3421, 3426, 3431, 3436, 3441, 3446, 3451, 3456, - 3461, 3466, 3471, 3476, 3481, 3486, 3491, 3496, - 3501, 3506, 3511, 3516, 3521, 3526, 3531, 3536, - 3541, 3546, 3551, 3556, 3561, 3566, 3571, 3576, - 3581, 3586, 0, 0, 0, 0, 0, 0, - - 3591, 3596, 3601, 3606, 3611, 3616, 3621, 3626, - 3631, 3636, 3641, 3646, 3651, 3656, 3661, 3666, - 3671, 3676, 3681, 3686, 3691, 3696, 0, 0, - 3701, 3706, 3711, 3716, 3721, 3726, 0, 0, - 3731, 3736, 3741, 3746, 3751, 3756, 3761, 3766, - 3771, 3776, 3781, 3786, 3791, 3796, 3801, 3806, - 3811, 3816, 3821, 3826, 3831, 3836, 3841, 3846, - 3851, 3856, 3861, 3866, 3871, 3876, 3881, 3886, - 3891, 3896, 3901, 3906, 3911, 3916, 0, 0, - 3921, 3926, 3931, 3936, 3941, 3946, 0, 0, - 3951, 3956, 3961, 3966, 3971, 3976, 3981, 3986, - 0, 3991, 0, 3996, 0, 4001, 0, 4006, - 4011, 4016, 4021, 4026, 4031, 4036, 4041, 4046, - 4051, 4056, 4061, 4066, 4071, 4076, 4081, 4086, - 4091, 4096, 4100, 4105, 4109, 4114, 4118, 4123, - 4127, 4132, 4136, 4141, 4145, 4150, 0, 0, - 4154, 4159, 4164, 4169, 4174, 4179, 4184, 4189, - 4194, 4199, 4204, 4209, 4214, 4219, 4224, 4229, - 4234, 4239, 4244, 4249, 4254, 4259, 4264, 4269, - 4274, 4279, 4284, 4289, 4294, 4299, 4304, 4309, - 4314, 4319, 4324, 4329, 4334, 4339, 4344, 4349, - 4354, 4359, 4364, 4369, 4374, 4379, 4384, 4389, - 4394, 4399, 4404, 4409, 4414, 0, 4419, 4424, - 4429, 4434, 4439, 4444, 4448, 4453, 4458, 4462, - 4467, 4472, 4477, 4482, 4487, 0, 4492, 4497, - 4502, 4507, 4511, 4516, 4520, 4525, 4530, 4535, - 4540, 4545, 4550, 4555, 0, 0, 4559, 4564, - 4569, 4574, 4579, 4584, 0, 4588, 4593, 4598, - 4603, 4608, 4613, 4618, 4622, 4627, 4632, 4637, - 4642, 4647, 4652, 4657, 4661, 4666, 4671, 4675, - 0, 0, 4679, 4684, 4689, 0, 4694, 4699, - 4704, 4709, 4713, 4718, 4722, 4727, 4731, 0, - - 4736, 4740, 4744, 4748, 4752, 4756, 4760, 4764, - 4768, 4772, 4776, 0, 0, 0, 0, 0, - 0, 4780, 0, 0, 0, 0, 0, 4784, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4789, 4793, 4798, 0, - 0, 0, 0, 0, 0, 0, 0, 4804, - 0, 0, 0, 4808, 4813, 0, 4819, 4824, - 0, 0, 0, 0, 4830, 0, 4835, 0, - 0, 0, 0, 0, 0, 0, 0, 4840, - 4845, 4850, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4855, - 0, 0, 0, 0, 0, 0, 0, 4862, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4866, 4870, 0, 0, 4874, 4878, 4882, 4886, - 4890, 4894, 4898, 4902, 4906, 4910, 4914, 4918, - 4922, 4926, 4930, 4934, 4938, 4942, 4946, 4950, - 4954, 4958, 4962, 4966, 4970, 4974, 4978, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4982, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 4987, 4993, 4999, 5003, 0, 5008, 5014, 5020, - 0, 5024, 5029, 5033, 5037, 5041, 5045, 5049, - 5053, 5057, 5061, 5065, 0, 5069, 5073, 0, - 0, 5078, 5082, 5086, 5090, 5094, 0, 0, - 5098, 5103, 5109, 0, 5114, 0, 5118, 0, - 5122, 0, 5126, 5130, 5134, 5138, 0, 5142, - 5146, 5150, 0, 5154, 5158, 5162, 5166, 5170, - 5174, 5178, 0, 0, 0, 5182, 5186, 5190, - 5194, 0, 0, 0, 0, 5198, 5202, 5206, - 5210, 5214, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 5218, 5224, 5230, 5236, 5242, - 5248, 5254, 5260, 5266, 5272, 5278, 5284, 5290, - 5295, 5299, 5304, 5310, 5315, 5319, 5324, 5330, - 5337, 5342, 5346, 5351, 5357, 5361, 5365, 5369, - 5373, 5377, 5382, 5388, 5393, 5397, 5402, 5408, - 5415, 5420, 5424, 5429, 5435, 5439, 5443, 5447, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 5451, 5456, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 5461, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5466, 5471, 5476, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 5481, 0, 0, 0, - 0, 5486, 0, 0, 5491, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 5496, 0, 5501, 0, - 0, 0, 0, 0, 5506, 5511, 0, 5517, - 5522, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5528, 0, 0, 5533, 0, 0, 5538, - 0, 5543, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5548, 0, 5553, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 5558, 5563, 5568, - 5573, 5578, 0, 0, 5583, 5588, 0, 0, - 5593, 5598, 0, 0, 0, 0, 0, 0, - 5603, 5608, 0, 0, 5613, 5618, 0, 0, - 5623, 5628, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 5633, 5638, 5643, 5648, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5653, 5658, 5663, 5668, 0, 0, 0, 0, - 0, 0, 5673, 5678, 5683, 5688, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5693, 5697, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5701, 5705, 5709, 5713, 5717, 5721, 5725, 5729, - 5733, 5737, 5742, 5747, 5752, 5757, 5762, 5767, - 5772, 5777, 5782, 5787, 5792, 5798, 5804, 5810, - 5816, 5822, 5828, 5834, 5840, 5846, 5853, 5860, - 5867, 5874, 5881, 5888, 5895, 5902, 5909, 5916, - 5923, 5928, 5933, 5938, 5943, 5948, 5953, 5958, - 5963, 5968, 5974, 5980, 5986, 5992, 5998, 6004, - 6010, 6016, 6022, 6028, 6034, 6040, 6046, 6052, - 6058, 6064, 6070, 6076, 6082, 6088, 6094, 6100, - 6106, 6112, 6118, 6124, 6130, 6136, 6142, 6148, - 6154, 6160, 6166, 6172, 6178, 6184, 6190, 6194, - 6198, 6202, 6206, 6210, 6214, 6218, 6222, 6226, - 6230, 6234, 6238, 6242, 6246, 6250, 6254, 6258, - 6262, 6266, 6270, 6274, 6278, 6282, 6286, 6290, - 6294, 6298, 6302, 6306, 6310, 6314, 6318, 6322, - 6326, 6330, 6334, 6338, 6342, 6346, 6350, 6354, - 6358, 6362, 6366, 6370, 6374, 6378, 6382, 6386, - 6390, 6394, 6398, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6402, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6409, 6415, 6420, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6426, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 6431, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 6435, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 6439, 6443, 6447, 6451, 6455, 6459, 6463, 6467, - 6471, 6475, 6479, 6483, 6487, 6491, 6495, 6499, - 6503, 6507, 6511, 6515, 6519, 6523, 6527, 6531, - 6535, 6539, 6543, 6547, 6551, 6555, 6559, 6563, - 6567, 6571, 6575, 6579, 6583, 6587, 6591, 6595, - 6599, 6603, 6607, 6611, 6615, 6619, 6623, 6627, - 6631, 6635, 6639, 6643, 6647, 6651, 6655, 6659, - 6663, 6667, 6671, 6675, 6679, 6683, 6687, 6691, - 6695, 6699, 6703, 6707, 6711, 6715, 6719, 6723, - 6727, 6731, 6735, 6739, 6743, 6747, 6751, 6755, - 6759, 6763, 6767, 6771, 6775, 6779, 6783, 6787, - 6791, 6795, 6799, 6803, 6807, 6811, 6815, 6819, - 6823, 6827, 6831, 6835, 6839, 6843, 6847, 6851, - 6855, 6859, 6863, 6867, 6871, 6875, 6879, 6883, - 6887, 6891, 6895, 6899, 6903, 6907, 6911, 6915, - 6919, 6923, 6927, 6931, 6935, 6939, 6943, 6947, - 6951, 6955, 6959, 6963, 6967, 6971, 6975, 6979, - 6983, 6987, 6991, 6995, 6999, 7003, 7007, 7011, - 7015, 7019, 7023, 7027, 7031, 7035, 7039, 7043, - 7047, 7051, 7055, 7059, 7063, 7067, 7071, 7075, - 7079, 7083, 7087, 7091, 7095, 7099, 7103, 7107, - 7111, 7115, 7119, 7123, 7127, 7131, 7135, 7139, - 7143, 7147, 7151, 7155, 7159, 7163, 7167, 7171, - 7175, 7179, 7183, 7187, 7191, 7195, 7199, 7203, - 7207, 7211, 7215, 7219, 7223, 7227, 7231, 7235, - 7239, 7243, 7247, 7251, 7255, 7259, 7263, 7267, - 7271, 7275, 7279, 7283, 7287, 7291, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 7295, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 7299, 0, - 7303, 7307, 7311, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7315, 0, 7320, 0, - 7325, 0, 7330, 0, 7335, 0, 7340, 0, - 7345, 0, 7350, 0, 7355, 0, 7360, 0, - 7365, 0, 7370, 0, 0, 7375, 0, 7380, - 0, 7385, 0, 0, 0, 0, 0, 0, - 7390, 7395, 0, 7400, 7405, 0, 7410, 7415, - 0, 7420, 7425, 0, 7430, 7435, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7440, 0, 0, 0, - 0, 0, 0, 7445, 7450, 0, 7455, 7460, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7465, 0, 7470, 0, - 7475, 0, 7480, 0, 7485, 0, 7490, 0, - 7495, 0, 7500, 0, 7505, 0, 7510, 0, - 7515, 0, 7520, 0, 0, 7525, 0, 7530, - 0, 7535, 0, 0, 0, 0, 0, 0, - 7540, 7545, 0, 7550, 7555, 0, 7560, 7565, - 0, 7570, 7575, 0, 7580, 7585, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7590, 0, 0, 7595, - 7600, 7605, 7610, 0, 0, 0, 7615, 7620, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7625, 7629, 7633, 7637, 7641, 7645, 7649, - 7653, 7657, 7661, 7665, 7669, 7673, 7677, 7681, - 7685, 7689, 7693, 7697, 7701, 7705, 7709, 7713, - 7717, 7721, 7725, 7729, 7733, 7737, 7741, 7745, - 7749, 7753, 7757, 7761, 7765, 7769, 7773, 7777, - 7781, 7785, 7789, 7793, 7797, 7801, 7805, 7809, - 7813, 7817, 7821, 7825, 7829, 7833, 7837, 7841, - 7845, 7849, 7853, 7857, 7861, 7865, 7869, 7873, - 7877, 7881, 7885, 7889, 7893, 7897, 7901, 7905, - 7909, 7913, 7917, 7921, 7925, 7929, 7933, 7937, - 7941, 7945, 7949, 7953, 7957, 7961, 7965, 7969, - 7973, 7977, 7981, 7985, 7989, 7993, 7997, 0, - 0, 0, 8001, 8005, 8009, 8013, 8017, 8021, - 8025, 8029, 8033, 8037, 8041, 8045, 8049, 8053, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 8057, 8063, 8069, 8075, 8081, 8087, 8093, 8099, - 8105, 8111, 8117, 8123, 8129, 8135, 8141, 8148, - 8155, 8162, 8169, 8176, 8183, 8190, 8197, 8204, - 8211, 8218, 8225, 8232, 8239, 0, 0, 0, - 8246, 8252, 8258, 8264, 8270, 8276, 8282, 8288, - 8294, 8300, 8306, 8312, 8318, 8324, 8330, 8336, - 8342, 8348, 8354, 8360, 8366, 8372, 8378, 8384, - 8390, 8396, 8402, 8408, 8414, 8420, 8426, 8432, - 8438, 8444, 8450, 8456, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 8462, 8467, 8472, 8477, 8482, 8487, 8492, - 8497, 8502, 8507, 8512, 8517, 8522, 8527, 8532, - 8537, 8541, 8545, 8549, 8553, 8557, 8561, 8565, - 8569, 8573, 8577, 8581, 8585, 8589, 8593, 8598, - 8603, 8608, 8613, 8618, 8623, 8628, 8633, 8638, - 8643, 8648, 8653, 8658, 0, 0, 0, 0, - 8663, 8667, 8671, 8675, 8679, 8683, 8687, 8691, - 8695, 8699, 8703, 8707, 8711, 8715, 8719, 8723, - 8727, 8731, 8735, 8739, 8743, 8747, 8751, 8755, - 8759, 8763, 8767, 8771, 8775, 8779, 8783, 8787, - 8791, 8795, 8799, 8803, 8807, 8811, 8815, 8819, - 8823, 8827, 8831, 8835, 8839, 8843, 8847, 8851, - 8855, 8859, 8864, 8869, 8874, 8879, 8884, 8889, - 8894, 8899, 8904, 8909, 8914, 8919, 8924, 8929, - 8934, 8939, 8944, 8949, 8954, 8959, 8964, 8969, - 8974, 8979, 8985, 8991, 0, 0, 0, 0, - 8997, 9001, 9005, 9009, 9013, 9017, 9021, 9025, - 9029, 9033, 9037, 9041, 9045, 9049, 9053, 9057, - 9061, 9065, 9069, 9073, 9077, 9081, 9085, 9089, - 9093, 9097, 9101, 9105, 9109, 9113, 9117, 9121, - 9125, 9129, 9133, 9137, 9141, 9145, 9149, 9153, - 9157, 9161, 9165, 9169, 9173, 9177, 9181, 0, - - 9185, 9192, 9199, 9206, 9212, 9219, 9225, 9231, - 9239, 9246, 9252, 9258, 9264, 9271, 9278, 9284, - 9290, 9295, 9301, 9308, 9315, 9320, 9328, 9337, - 9345, 9351, 9359, 9367, 9374, 9380, 9386, 9392, - 9399, 9407, 9414, 9420, 9426, 9432, 9437, 9442, - 9447, 9452, 9458, 9464, 9472, 9478, 9485, 9493, - 9499, 9504, 9509, 9517, 9524, 9532, 9538, 9546, - 9551, 9557, 9563, 9569, 9575, 9581, 9588, 9594, - 9599, 9605, 9611, 9617, 9624, 9630, 9636, 9642, - 9650, 9657, 9662, 9670, 9675, 9682, 9689, 9695, - 9701, 9707, 9714, 9719, 9725, 9732, 9737, 9745, - 9751, 9756, 9761, 9766, 9771, 9776, 9781, 9786, - 9791, 9796, 9801, 9807, 9813, 9819, 9825, 9831, - 9837, 9843, 9849, 9855, 9861, 9867, 9873, 9879, - 9885, 9891, 9897, 9902, 9907, 9913, 9918, 0, - 0, 0, 0, 9923, 9928, 9933, 9938, 9943, - 9950, 9955, 9960, 9965, 9970, 9975, 9980, 9985, - 9990, 9996, 10003, 10008, 10013, 10018, 10023, 10028, - 10033, 10038, 10044, 10050, 10056, 10062, 10067, 10072, - 10077, 10082, 10087, 10092, 10097, 10102, 10107, 10112, - 10118, 10124, 10129, 10135, 10141, 10147, 10152, 10158, - 10164, 10171, 10176, 10182, 10188, 10194, 10200, 10208, - 10217, 10222, 10227, 10232, 10237, 10242, 10247, 10252, - 10257, 10262, 10267, 10272, 10277, 10282, 10287, 10292, - 10297, 10302, 10307, 10314, 10319, 10324, 10329, 10336, - 10342, 10347, 10352, 10357, 10362, 10367, 10372, 10377, - 10382, 10387, 10392, 10398, 10403, 10408, 10414, 10420, - 10425, 10432, 10438, 10443, 10448, 10453, 0, 0, - 10458, 10463, 10468, 10473, 10478, 10483, 10488, 10493, - 10498, 10503, 10509, 10515, 10521, 10527, 10533, 10539, - 10545, 10551, 10557, 10563, 10569, 10575, 10581, 10587, - 10593, 10599, 10605, 10611, 10617, 10623, 10629, 0, - - 10635, 10639, 10643, 10647, 10651, 10655, 10659, 10663, - 10667, 10671, 10675, 10679, 10683, 10687, 10691, 10695, - 10699, 10703, 10707, 10711, 10715, 10719, 10723, 10727, - 10731, 10735, 10739, 10743, 10747, 10751, 10755, 10759, - 10763, 10767, 10771, 10775, 10779, 10783, 10787, 10791, - 10795, 10799, 10803, 10807, 10811, 10815, 10819, 10823, - 10827, 10831, 10835, 10839, 10843, 10847, 10851, 10855, - 10859, 10863, 10867, 10871, 10875, 10879, 10883, 10887, - 10891, 10895, 10899, 10903, 10907, 10911, 10915, 10919, - 10923, 10927, 10931, 10935, 10939, 10943, 10947, 10951, - 10955, 10959, 10963, 10967, 10971, 10975, 10979, 10983, - 10987, 10991, 10995, 10999, 11003, 11007, 11011, 11015, - 11019, 11023, 11027, 11031, 11035, 11039, 11043, 11047, - 11051, 11055, 11059, 11063, 11067, 11071, 11075, 11079, - 11083, 11087, 11091, 11095, 11099, 11103, 11107, 11111, - 11115, 11119, 11123, 11127, 11131, 11135, 11139, 11143, - 11147, 11151, 11155, 11159, 11163, 11167, 11171, 11175, - 11179, 11183, 11187, 11191, 11195, 11199, 11203, 11207, - 11211, 11215, 11219, 11223, 11227, 11231, 11235, 11239, - 11243, 11247, 11251, 11255, 11259, 11263, 11267, 11271, - 11275, 11279, 11283, 11287, 11291, 11295, 11299, 11303, - 11307, 11311, 11315, 11319, 11323, 11327, 11331, 11335, - 11339, 11343, 11347, 11351, 11355, 11359, 11363, 11367, - 11371, 11375, 11379, 11383, 11387, 11391, 11395, 11399, - 11403, 11407, 11411, 11415, 11419, 11423, 11427, 11431, - 11435, 11439, 11443, 11447, 11451, 11455, 11459, 11463, - 11467, 11471, 11475, 11479, 11483, 11487, 11491, 11495, - 11499, 11503, 11507, 11511, 11515, 11519, 11523, 11527, - 11531, 11535, 11539, 11543, 11547, 11551, 11555, 11559, - 11563, 11567, 11571, 11575, 11579, 11583, 11587, 11591, - 11595, 11599, 11603, 11607, 11611, 11615, 11619, 11623, - 11627, 11631, 11635, 11639, 11643, 11647, 11651, 11655, - - 11659, 11663, 11667, 11671, 11675, 11679, 11683, 11687, - 11691, 11695, 11699, 11703, 11707, 11711, 0, 0, - 11715, 0, 11719, 0, 0, 11723, 11727, 11731, - 11735, 11739, 11743, 11747, 11751, 11755, 11759, 0, - 11763, 0, 11767, 0, 0, 11771, 11775, 0, - 0, 0, 11779, 11783, 11787, 11791, 0, 0, - 11795, 11799, 11803, 11807, 11811, 11815, 11819, 11823, - 11827, 11831, 11835, 11839, 11843, 11847, 11851, 11855, - 11859, 11863, 11867, 11871, 11875, 11879, 11883, 11887, - 11891, 11895, 11899, 11903, 11907, 11911, 11915, 11919, - 11923, 11927, 11931, 11935, 11939, 11943, 11947, 11951, - 11955, 11959, 11963, 11967, 11971, 11975, 11979, 11983, - 11987, 11991, 11995, 11999, 12003, 12007, 12011, 12015, - 12019, 12023, 12027, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 12031, 12036, 12041, 12046, 12052, 12058, 12063, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 12068, 12073, 12078, 12083, 12088, - 0, 0, 0, 0, 0, 12093, 0, 12098, - 12103, 12107, 12111, 12115, 12119, 12123, 12127, 12131, - 12135, 12139, 12143, 12148, 12153, 12158, 12163, 12168, - 12173, 12178, 12183, 12188, 12193, 12198, 12203, 0, - 12208, 12213, 12218, 12223, 12228, 0, 12233, 0, - 12238, 12243, 0, 12248, 12253, 0, 12258, 12263, - 12268, 12273, 12278, 12283, 12288, 12293, 12298, 12303, - 12308, 12312, 12316, 12320, 12324, 12328, 12332, 12336, - 12340, 12344, 12348, 12352, 12356, 12360, 12364, 12368, - 12372, 12376, 12380, 12384, 12388, 12392, 12396, 12400, - 12404, 12408, 12412, 12416, 12420, 12424, 12428, 12432, - 12436, 12440, 12444, 12448, 12452, 12456, 12460, 12464, - 12468, 12472, 12476, 12480, 12484, 12488, 12492, 12496, - 12500, 12504, 12508, 12512, 12516, 12520, 12524, 12528, - 12532, 12536, 12540, 12544, 12548, 12552, 12556, 12560, - 12564, 12568, 12572, 12576, 12580, 12584, 12588, 12592, - 12596, 12600, 12604, 12608, 12612, 12616, 12620, 12624, - 12628, 12632, 12636, 12640, 12644, 12648, 12652, 12656, - 12660, 12664, 12668, 12672, 12676, 12680, 12684, 12688, - 12692, 12696, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 12700, 12704, 12708, 12712, 12716, - 12720, 12724, 12728, 12732, 12736, 12740, 12744, 12748, - 12752, 12756, 12760, 12764, 12768, 12772, 12776, 12780, - 12784, 12788, 12792, 12797, 12802, 12807, 12812, 12817, - 12822, 12827, 12832, 12837, 12842, 12847, 12852, 12857, - 12862, 12867, 12872, 12877, 12882, 12886, 12890, 12894, - - 12898, 12903, 12908, 12913, 12918, 12923, 12928, 12933, - 12938, 12943, 12948, 12953, 12958, 12963, 12968, 12973, - 12978, 12983, 12988, 12993, 12998, 13003, 13008, 13013, - 13018, 13023, 13028, 13033, 13038, 13043, 13048, 13053, - 13058, 13063, 13068, 13073, 13078, 13083, 13088, 13093, - 13098, 13103, 13108, 13113, 13118, 13123, 13128, 13133, - 13138, 13143, 13148, 13153, 13158, 13163, 13168, 13173, - 13178, 13183, 13188, 13193, 13198, 13203, 13208, 13213, - 13218, 13223, 13228, 13233, 13238, 13243, 13248, 13253, - 13258, 13263, 13268, 13273, 13278, 13283, 13288, 13293, - 13298, 13303, 13308, 13313, 13318, 13323, 13328, 13333, - 13338, 13343, 13348, 13353, 13358, 13363, 13368, 13374, - 13380, 13386, 13392, 13398, 13404, 13409, 13414, 13419, - 13424, 13429, 13434, 13439, 13444, 13449, 13454, 13459, - 13464, 13469, 13474, 13479, 13484, 13489, 13494, 13499, - 13504, 13509, 13514, 13519, 13524, 13529, 13534, 13539, - 13544, 13549, 13554, 13559, 13564, 13569, 13574, 13579, - 13584, 13589, 13594, 13599, 13604, 13609, 13614, 13619, - 13624, 13629, 13634, 13639, 13644, 13649, 13654, 13659, - 13664, 13669, 13674, 13679, 13684, 13689, 13694, 13699, - 13704, 13709, 13714, 13719, 13724, 13729, 13734, 13739, - 13744, 13749, 13754, 13759, 13764, 13769, 13774, 13779, - 13784, 13789, 13794, 13799, 13804, 13809, 13814, 13819, - 13824, 13829, 13834, 13839, 13844, 13849, 13854, 13859, - 13864, 13869, 13874, 13879, 13884, 13889, 13894, 13899, - 13904, 13909, 13914, 13919, 13924, 13929, 13934, 13939, - 13944, 13949, 13954, 13959, 13964, 13969, 13974, 13979, - 13984, 13989, 13994, 13999, 14004, 14009, 14014, 14019, - 14024, 14029, 14034, 14039, 14044, 14049, 14054, 14059, - 14064, 14069, 14074, 14079, 14084, 14089, 14094, 14099, - 14104, 14109, 14114, 14120, 14126, 14132, 14137, 14142, - 14147, 14152, 14157, 14162, 14167, 14172, 14177, 14182, - - 14187, 14192, 14197, 14202, 14207, 14212, 14217, 14222, - 14227, 14232, 14237, 14242, 14247, 14252, 14257, 14262, - 14267, 14272, 14277, 14282, 14287, 14292, 14297, 14302, - 14307, 14312, 14317, 14322, 14327, 14332, 14337, 14342, - 14347, 14352, 14357, 14362, 14367, 14372, 14377, 14382, - 14387, 14392, 14397, 14402, 14407, 14412, 14417, 14422, - 14427, 14432, 14437, 14442, 14447, 14452, 14457, 14462, - 14467, 14472, 14477, 14482, 14487, 14492, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 14497, 14503, 14509, 14515, 14521, 14527, 14533, 14539, - 14545, 14551, 14557, 14563, 14569, 14575, 14581, 14587, - 14593, 14599, 14605, 14611, 14617, 14623, 14629, 14635, - 14641, 14647, 14653, 14659, 14665, 14671, 14677, 14683, - 14689, 14695, 14701, 14707, 14713, 14719, 14725, 14731, - 14737, 14743, 14749, 14755, 14761, 14767, 14773, 14779, - 14785, 14791, 14797, 14803, 14809, 14815, 14821, 14827, - 14833, 14839, 14845, 14851, 14857, 14863, 14869, 14875, - 0, 0, 14881, 14887, 14893, 14899, 14905, 14911, - 14917, 14923, 14929, 14935, 14941, 14947, 14953, 14959, - 14965, 14971, 14977, 14983, 14989, 14995, 15001, 15007, - 15013, 15019, 15025, 15031, 15037, 15043, 15049, 15055, - 15061, 15067, 15073, 15079, 15085, 15091, 15097, 15103, - 15109, 15115, 15121, 15127, 15133, 15139, 15145, 15151, - 15157, 15163, 15169, 15175, 15181, 15187, 15193, 15199, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 15205, 15211, 15217, 15224, 15231, 15238, 15245, 15252, - 15259, 15266, 15272, 15293, 15304, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 15311, 15315, 15319, 15323, 15327, 15331, 15335, 15339, - 15343, 15347, 15351, 15355, 15359, 15363, 15367, 15371, - 15375, 15379, 15383, 15387, 15391, 0, 0, 0, - 0, 15395, 15399, 15403, 15407, 15411, 15415, 15419, - 15423, 15427, 15431, 0, 15435, 15439, 15443, 15447, - 15451, 15455, 15459, 15463, 15467, 15471, 15475, 15479, - 15483, 15487, 15491, 15495, 15499, 15503, 15507, 0, - 15511, 15515, 15519, 15523, 0, 0, 0, 0, - 15527, 15532, 15537, 0, 15542, 0, 15547, 15552, - 15557, 15562, 15567, 15572, 15577, 15582, 15587, 15592, - 15597, 15601, 15605, 15609, 15613, 15617, 15621, 15625, - 15629, 15633, 15637, 15641, 15645, 15649, 15653, 15657, - 15661, 15665, 15669, 15673, 15677, 15681, 15685, 15689, - 15693, 15697, 15701, 15705, 15709, 15713, 15717, 15721, - 15725, 15729, 15733, 15737, 15741, 15745, 15749, 15753, - 15757, 15761, 15765, 15769, 15773, 15777, 15781, 15785, - 15789, 15793, 15797, 15801, 15805, 15809, 15813, 15817, - 15821, 15825, 15829, 15833, 15837, 15841, 15845, 15849, - 15853, 15857, 15861, 15865, 15869, 15873, 15877, 15881, - 15885, 15889, 15893, 15897, 15901, 15905, 15909, 15913, - 15917, 15921, 15925, 15929, 15933, 15937, 15941, 15945, - 15949, 15953, 15957, 15961, 15965, 15969, 15973, 15977, - 15981, 15985, 15989, 15993, 15997, 16001, 16005, 16009, - 16013, 16017, 16021, 16025, 16029, 16033, 16037, 16041, - 16045, 16049, 16053, 16057, 16061, 16065, 16070, 16075, - 16080, 16085, 16090, 16095, 16100, 0, 0, 0, - - 0, 16105, 16109, 16113, 16117, 16121, 16125, 16129, - 16133, 16137, 16141, 16145, 16149, 16153, 16157, 16161, - 16165, 16169, 16173, 16177, 16181, 16185, 16189, 16193, - 16197, 16201, 16205, 16209, 16213, 16217, 16221, 16225, - 16229, 16233, 16237, 16241, 16245, 16249, 16253, 16257, - 16261, 16265, 16269, 16273, 16277, 16281, 16285, 16289, - 16293, 16297, 16301, 16305, 16309, 16313, 16317, 16321, - 16325, 16329, 16333, 16337, 16341, 16345, 16349, 16353, - 16357, 16361, 16365, 16369, 16373, 16377, 16381, 16385, - 16389, 16393, 16397, 16401, 16405, 16409, 16413, 16417, - 16421, 16425, 16429, 16433, 16437, 16441, 16445, 16449, - 16453, 16457, 16461, 16465, 16469, 16473, 16477, 16481, - 16485, 16489, 16493, 16497, 16501, 16505, 16509, 16513, - 16517, 16521, 16525, 16529, 16533, 16537, 16541, 16545, - 16549, 16553, 16557, 16561, 16565, 16569, 16573, 16577, - 16581, 16585, 16589, 16593, 16597, 16601, 16605, 16609, - 16613, 16617, 16621, 16625, 16629, 16633, 16637, 16641, - 16645, 16649, 16653, 16657, 16661, 16665, 16669, 16673, - 16677, 16681, 16685, 16689, 16693, 16697, 16701, 16705, - 16709, 16713, 16717, 16721, 16725, 16729, 16733, 16737, - 16741, 16745, 16749, 16753, 16757, 16761, 16765, 16769, - 16773, 16777, 16781, 16785, 16789, 16793, 16797, 16801, - 16805, 16809, 16813, 16817, 16821, 16825, 16829, 16833, - 16837, 16841, 16845, 16849, 16853, 16857, 16861, 0, - 0, 0, 16865, 16869, 16873, 16877, 16881, 16885, - 0, 0, 16889, 16893, 16897, 16901, 16905, 16909, - 0, 0, 16913, 16917, 16921, 16925, 16929, 16933, - 0, 0, 16937, 16941, 16945, 0, 0, 0, - 16949, 16953, 16957, 16961, 16965, 16969, 16973, 0, - 16977, 16981, 16985, 16989, 16993, 16997, 17001, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -// 67544 bytes - -const TQ_UINT16 TQUnicodeTables::ligature_map[] = { - 0, - 5563, 0, - 5548, 0, - 5568, 0, - 67, 72, 77, 82, 87, 92, 332, 342, 352, 966, 1196, 1206, 1346, 2361, 3141, 3151, 0, - 2371, 2381, 2391, 0, - 97, 362, 372, 382, 392, 0, - 402, 2411, 2421, 2431, 2441, 2451, 0, - 102, 107, 112, 117, 412, 422, 432, 442, 452, 1216, 1226, 1356, 2481, 2491, 3261, 3271, 3281, 0, - 2511, 0, - 462, 472, 482, 492, 1076, 1146, 2521, 0, - 502, 1336, 2531, 2541, 2551, 2561, 2571, 0, - 122, 127, 132, 137, 512, 522, 532, 542, 552, 976, 1236, 1246, 2581, 3341, 3351, 0, - 567, 0, - 577, 1086, 2601, 2611, 2621, 0, - 587, 597, 607, 2631, 2651, 2661, 0, - 2671, 2681, 2691, 0, - 142, 627, 637, 647, 1156, 2701, 2711, 2721, 2731, 0, - 147, 152, 157, 162, 167, 662, 672, 682, 901, 986, 1096, 1256, 1266, 1386, 3361, 3371, 0, - 2781, 2791, 0, - 692, 702, 712, 1276, 1286, 2801, 2811, 2831, 0, - 722, 732, 742, 752, 1316, 2841, 2851, 0, - 762, 772, 1326, 2891, 2901, 2911, 2921, 0, - 172, 177, 182, 187, 782, 792, 802, 812, 822, 832, 911, 996, 1296, 1306, 2931, 2941, 2951, 3481, 3491, 0, - 2981, 2991, 0, - 842, 3001, 3011, 3021, 3031, 3041, 0, - 3051, 3061, 0, - 192, 852, 862, 1406, 3071, 3551, 3561, 3571, 3581, 0, - 867, 877, 887, 3081, 3091, 3101, 0, - 197, 202, 207, 212, 217, 222, 337, 347, 357, 971, 1201, 1211, 1351, 2366, 3146, 3156, 0, - 2376, 2386, 2396, 0, - 227, 367, 377, 387, 397, 0, - 407, 2416, 2426, 2436, 2446, 2456, 0, - 232, 237, 242, 247, 417, 427, 437, 447, 457, 1221, 1231, 1361, 2486, 2496, 3266, 3276, 3286, 0, - 2516, 0, - 467, 477, 487, 497, 1081, 1151, 2526, 0, - 507, 1341, 2536, 2546, 2556, 2566, 2576, 3111, 0, - 252, 257, 262, 267, 517, 527, 537, 547, 981, 1241, 1251, 2586, 3346, 3356, 0, - 572, 1126, 0, - 582, 1091, 2606, 2616, 2626, 0, - 592, 602, 612, 2636, 2656, 2666, 0, - 2676, 2686, 2696, 0, - 272, 632, 642, 652, 1161, 2706, 2716, 2726, 2736, 0, - 277, 282, 287, 292, 297, 667, 677, 687, 906, 991, 1101, 1261, 1271, 1391, 3366, 3376, 0, - 2786, 2796, 0, - 697, 707, 717, 1281, 1291, 2806, 2816, 2836, 0, - 727, 737, 747, 757, 1321, 2846, 2856, 0, - 767, 777, 1331, 2896, 2906, 2916, 2926, 3116, 0, - 302, 307, 312, 317, 787, 797, 807, 817, 827, 837, 916, 1001, 1301, 1311, 2936, 2946, 2956, 3486, 3496, 0, - 2986, 2996, 0, - 847, 3006, 3016, 3026, 3036, 3046, 3121, 0, - 3056, 3066, 0, - 322, 327, 857, 1411, 3076, 3126, 3556, 3566, 3576, 3586, 0, - 872, 882, 892, 3086, 3096, 3106, 0, - 1537, 4472, 4666, 0, - 3161, 3171, 3181, 3191, 0, - 1046, 0, - 1166, 0, - 1066, 1176, 0, - 2401, 0, - 3291, 3301, 3311, 3321, 0, - 2591, 0, - 3381, 3391, 3401, 3411, 0, - 1376, 2741, 2751, 0, - 1366, 0, - 1186, 0, - 1006, 1016, 1026, 1036, 0, - 3166, 3176, 3186, 3196, 0, - 1051, 0, - 1171, 0, - 1071, 1181, 0, - 2406, 0, - 3296, 3306, 3316, 3326, 0, - 2596, 0, - 3386, 3396, 3406, 3416, 0, - 1381, 2746, 2756, 0, - 1371, 0, - 1191, 0, - 1011, 1021, 1031, 1041, 0, - 3211, 3221, 3231, 3241, 0, - 3216, 3226, 3236, 3246, 0, - 2461, 2471, 0, - 2466, 2476, 0, - 2761, 2771, 0, - 2766, 2776, 0, - 2861, 0, - 2866, 0, - 2871, 0, - 2876, 0, - 2961, 0, - 2966, 0, - 2971, 0, - 2976, 0, - 3136, 0, - 3431, 3441, 3451, 3461, 3471, 0, - 3436, 3446, 3456, 3466, 3476, 0, - 3501, 3511, 3521, 3531, 3541, 0, - 3506, 3516, 3526, 3536, 3546, 0, - 1116, 0, - 1106, 0, - 1111, 0, - 1056, 0, - 1061, 0, - 2501, 0, - 2506, 0, - 1396, 0, - 1401, 0, - 1121, 0, - 1514, 0, - 1542, 3631, 3636, 4429, 4434, 4439, 4448, 0, - 1551, 3701, 3706, 4502, 0, - 1556, 3771, 3776, 4511, 4520, 0, - 1561, 1586, 3851, 3856, 4569, 4574, 4579, 0, - 1566, 3921, 3926, 4704, 0, - 4661, 0, - 1571, 1591, 3991, 4642, 4647, 4652, 0, - 1576, 4051, 4056, 4713, 4722, 0, - 4414, 0, - 4487, 0, - 1596, 3591, 3596, 4091, 4394, 4399, 4409, 4419, 0, - 1601, 3671, 3676, 4100, 0, - 1606, 3731, 3736, 4109, 4482, 4492, 0, - 1611, 1621, 3811, 3816, 4118, 4540, 4545, 4559, 0, - 1631, 3891, 3896, 4127, 0, - 4622, 4627, 0, - 1626, 1636, 3951, 3956, 4136, 4603, 4608, 4632, 0, - 1641, 4011, 4016, 4145, 4684, 4694, 0, - 1581, 4550, 4564, 0, - 1616, 4613, 4637, 0, - 4689, 0, - 1658, 1663, 0, - 1707, 0, - 1792, 1802, 0, - 1702, 0, - 1692, 1697, 1812, 0, - 1782, 1832, 0, - 1842, 0, - 1717, 1727, 1852, 1862, 0, - 1712, 0, - 1872, 0, - 1722, 1902, 1912, 1922, 0, - 1932, 0, - 1942, 0, - 1892, 0, - 1797, 1807, 0, - 1747, 0, - 1737, 1742, 1817, 0, - 1787, 1837, 0, - 1847, 0, - 1732, 1762, 1857, 1867, 0, - 1757, 0, - 1877, 0, - 1767, 1907, 1917, 1927, 0, - 1937, 0, - 1947, 0, - 1897, 0, - 1752, 0, - 1772, 0, - 1777, 0, - 1822, 0, - 1827, 0, - 1882, 0, - 1887, 0, - 12163, 12168, 12173, 0, - 12178, 12288, 0, - 12183, 0, - 12188, 0, - 12193, 0, - 12198, 12283, 0, - 12203, 0, - 12208, 0, - 12093, 12213, 0, - 12218, 0, - 12223, 12293, 0, - 12228, 0, - 12233, 0, - 12238, 0, - 12243, 0, - 12248, 0, - 12253, 12298, 0, - 12258, 0, - 12263, 0, - 12268, 0, - 12143, 12148, 12273, 0, - 12278, 0, - 12098, 0, - 1957, 1962, 1972, 0, - 1967, 0, - 1977, 0, - 2007, 0, - 2012, 0, - 2002, 0, - 2032, 0, - 2037, 0, - 2042, 0, - 2047, 0, - 2052, 0, - 2057, 0, - 2017, 0, - 2062, 0, - 2067, 0, - 2022, 0, - 2027, 0, - 2082, 0, - 2087, 0, - 2092, 0, - 2072, 2077, 0, - 2107, 0, - 2112, 0, - 2117, 0, - 2122, 0, - 2097, 0, - 2102, 0, - 2142, 0, - 2147, 0, - 2127, 2132, 2137, 0, - 2152, 0, - 2157, 2167, 0, - 2162, 0, - 2172, 0, - 2177, 0, - 2182, 2187, 2192, 0, - 2197, 0, - 2202, 2212, 0, - 2207, 0, - 2217, 2222, 2232, 0, - 2227, 0, - 2286, 0, - 2261, 0, - 2266, 0, - 2271, 0, - 2276, 0, - 2281, 0, - 2291, 2296, 2321, 0, - 2351, 0, - 2326, 0, - 2331, 0, - 2336, 0, - 2341, 0, - 2346, 0, - 2301, 0, - 2311, 0, - 2356, 0, - 2641, 0, - 2646, 0, - 2821, 0, - 2826, 0, - 2881, 0, - 2886, 0, - 3201, 3251, 0, - 3206, 3256, 0, - 3331, 0, - 3336, 0, - 3421, 0, - 3426, 0, - 3601, 3611, 3621, 4154, 0, - 3606, 3616, 3626, 4159, 0, - 4164, 0, - 4169, 0, - 4174, 0, - 4179, 0, - 4184, 0, - 4189, 0, - 3641, 3651, 3661, 4194, 0, - 3646, 3656, 3666, 4199, 0, - 4204, 0, - 4209, 0, - 4214, 0, - 4219, 0, - 4224, 0, - 4229, 0, - 3681, 3691, 0, - 3686, 3696, 0, - 3711, 3721, 0, - 3716, 3726, 0, - 3741, 3751, 3761, 4234, 0, - 3746, 3756, 3766, 4239, 0, - 4244, 0, - 4249, 0, - 4254, 0, - 4259, 0, - 4264, 0, - 4269, 0, - 3781, 3791, 3801, 4274, 0, - 3786, 3796, 3806, 4279, 0, - 4284, 0, - 4289, 0, - 4294, 0, - 4299, 0, - 4304, 0, - 4309, 0, - 3821, 3831, 3841, 0, - 3826, 3836, 3846, 0, - 3861, 3871, 3881, 0, - 3866, 3876, 3886, 0, - 3901, 3911, 0, - 3906, 3916, 0, - 3931, 3941, 0, - 3936, 3946, 0, - 3961, 3971, 3981, 0, - 3966, 3976, 3986, 0, - 3996, 4001, 4006, 0, - 4021, 4031, 4041, 4314, 0, - 4026, 4036, 4046, 4319, 0, - 4324, 0, - 4329, 0, - 4334, 0, - 4339, 0, - 4344, 0, - 4349, 0, - 4061, 4071, 4081, 4354, 0, - 4066, 4076, 4086, 4359, 0, - 4364, 0, - 4369, 0, - 4374, 0, - 4379, 0, - 4384, 0, - 4389, 0, - 4404, 0, - 4477, 0, - 4679, 0, - 4424, 0, - 4525, 4530, 4535, 0, - 4497, 0, - 4699, 0, - 4588, 4593, 4598, 0, - 5451, 0, - 5456, 0, - 5461, 0, - 5466, 0, - 5476, 0, - 5471, 0, - 5481, 0, - 5486, 0, - 5491, 0, - 5496, 0, - 5501, 0, - 5528, 0, - 5533, 0, - 5538, 0, - 5543, 0, - 5558, 0, - 5553, 0, - 5573, 0, - 5578, 0, - 5583, 0, - 5588, 0, - 5593, 0, - 5598, 0, - 5603, 0, - 5608, 0, - 5653, 0, - 5658, 0, - 5613, 0, - 5618, 0, - 5623, 0, - 5628, 0, - 5663, 0, - 5668, 0, - 5633, 0, - 5638, 0, - 5643, 0, - 5648, 0, - 5673, 0, - 5678, 0, - 5683, 0, - 5688, 0, - 6426, 0, - 7440, 0, - 7315, 0, - 7320, 0, - 7325, 0, - 7330, 0, - 7335, 0, - 7340, 0, - 7345, 0, - 7350, 0, - 7355, 0, - 7360, 0, - 7365, 0, - 7370, 0, - 7375, 0, - 7380, 0, - 7385, 0, - 7390, 7395, 0, - 7400, 7405, 0, - 7410, 7415, 0, - 7420, 7425, 0, - 7430, 7435, 0, - 7455, 0, - 7590, 0, - 7465, 0, - 7470, 0, - 7475, 0, - 7480, 0, - 7485, 0, - 7490, 0, - 7495, 0, - 7500, 0, - 7505, 0, - 7510, 0, - 7515, 0, - 7520, 0, - 7525, 0, - 7530, 0, - 7535, 0, - 7540, 7545, 0, - 7550, 7555, 0, - 7560, 7565, 0, - 7570, 7575, 0, - 7580, 7585, 0, - 7595, 0, - 7600, 0, - 7605, 0, - 7610, 0, - 7615, 0, - 12153, 12158, 0, - -}; - -const TQ_UINT16 TQUnicodeTables::ligature_info[] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 8, 9, 10, 11, 12, 13, 8, 14, - 15, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 16, 17, - 8, 18, 19, 8, 8, 8, 8, 8, - 8, 8, 20, 8, 8, 8, 8, 8, - 21, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 22, 8, 8, 8, 8, - - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 3, 5, 0, - 0, 7, 24, 28, 34, 41, 59, 61, - 69, 77, 93, 95, 101, 108, 112, 122, - 139, 0, 142, 151, 159, 167, 187, 190, - 197, 200, 210, 0, 0, 0, 0, 0, - 0, 217, 234, 238, 244, 251, 269, 271, - 279, 288, 303, 306, 312, 319, 323, 333, - 350, 0, 353, 362, 370, 379, 399, 402, - 410, 413, 424, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 431, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 435, 0, 440, 442, 444, 447, - 0, 0, 449, 0, 0, 0, 0, 454, - 0, 0, 0, 0, 456, 461, 465, 0, - 467, 0, 0, 0, 469, 0, 0, 0, - 0, 0, 474, 0, 479, 481, 483, 486, - 0, 0, 488, 0, 0, 0, 0, 493, - 0, 0, 0, 0, 495, 500, 504, 0, - 506, 0, 0, 0, 508, 0, 0, 0, - - 0, 0, 513, 518, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 523, 526, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 529, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 535, 537, 0, 0, 0, 0, - 539, 541, 0, 0, 0, 0, 0, 0, - 543, 545, 547, 549, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 551, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 553, 559, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 565, - 571, 0, 0, 0, 0, 0, 0, 577, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 579, 581, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 583, 585, - 587, 589, 0, 0, 0, 0, 591, 593, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 595, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 597, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 599, 0, 0, 0, 607, 0, 612, - 0, 618, 0, 0, 0, 0, 0, 626, - 0, 631, 0, 0, 0, 633, 0, 0, - 0, 640, 0, 0, 646, 0, 648, 0, - 0, 650, 0, 0, 0, 659, 0, 664, - 0, 671, 0, 0, 0, 0, 0, 680, - 0, 685, 0, 0, 0, 688, 0, 0, - 0, 697, 704, 708, 0, 0, 712, 0, - 0, 0, 714, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 717, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 719, 0, 0, 722, 0, 724, 728, 731, - 733, 0, 738, 0, 0, 0, 740, 0, - 0, 0, 0, 742, 0, 0, 0, 747, - 0, 0, 0, 749, 0, 751, 0, 0, - 753, 0, 0, 756, 0, 758, 762, 765, - 767, 0, 772, 0, 0, 0, 774, 0, - 0, 0, 0, 776, 0, 0, 0, 781, - 0, 0, 0, 783, 0, 785, 0, 0, - 0, 0, 0, 0, 0, 0, 787, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 789, 791, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 793, 795, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 797, 799, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 801, 805, 808, 810, 812, 814, 817, 0, - 819, 821, 824, 826, 829, 0, 831, 0, - 833, 835, 0, 837, 839, 0, 842, 844, - 846, 848, 852, 0, 0, 0, 0, 0, - 0, 0, 854, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 856, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 860, 0, 862, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 864, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 866, 0, 0, 868, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 870, 872, 874, - 0, 0, 0, 0, 876, 0, 0, 0, - 0, 878, 880, 0, 0, 0, 0, 0, - 882, 0, 0, 884, 0, 0, 0, 886, - 888, 0, 0, 890, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 892, 894, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 896, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 898, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 901, 903, - 0, 0, 0, 0, 905, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 907, 0, 0, 0, 0, - 0, 0, 909, 0, 0, 0, 0, 0, - 911, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 913, 915, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 917, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 921, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 923, 926, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 928, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 930, - 0, 0, 0, 0, 0, 0, 932, 0, - 0, 0, 936, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 938, 941, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 943, 0, 0, 947, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 949, 0, 951, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 953, 0, 0, 0, - 0, 955, 0, 0, 0, 0, 957, 0, - 0, 0, 0, 959, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 961, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 965, 0, 967, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 969, 0, 0, 0, - 0, 971, 0, 0, 0, 0, 973, 0, - 0, 0, 0, 975, 0, 0, 0, 0, - 0, 0, 977, 979, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 981, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 983, 985, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 987, 989, 0, 0, 0, 0, - 0, 0, 991, 993, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 995, 998, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1001, 1003, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1005, 1007, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 1009, 1014, 1019, 1021, 1023, 1025, 1027, 1029, - 1031, 1036, 1041, 1043, 1045, 1047, 1049, 1051, - 1053, 1056, 0, 0, 0, 0, 0, 0, - 1059, 1062, 0, 0, 0, 0, 0, 0, - 1065, 1070, 1075, 1077, 1079, 1081, 1083, 1085, - 1087, 1092, 1097, 1099, 1101, 1103, 1105, 1107, - 1109, 1113, 0, 0, 0, 0, 0, 0, - 1117, 1121, 0, 0, 0, 0, 0, 0, - 1125, 1128, 0, 0, 0, 0, 0, 0, - 1131, 1134, 0, 0, 0, 0, 0, 0, - 1137, 1141, 0, 0, 0, 0, 0, 0, - 0, 1145, 0, 0, 0, 0, 0, 0, - 1149, 1154, 1159, 1161, 1163, 1165, 1167, 1169, - 1171, 1176, 1181, 1183, 1185, 1187, 1189, 1191, - 1193, 0, 0, 0, 1195, 0, 0, 0, - 0, 0, 0, 0, 1197, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1199, 0, - 0, 0, 0, 0, 0, 0, 0, 1201, - 0, 0, 0, 0, 0, 0, 1205, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1207, 0, - 0, 0, 0, 0, 0, 0, 1209, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1213, 0, 1215, 0, 1217, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1219, 0, 1221, 0, 1223, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 1225, 0, 0, 0, 0, - 1227, 0, 0, 1229, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1231, 0, 1233, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1235, 0, 0, 0, - 0, 0, 0, 1237, 0, 1239, 0, 0, - 1241, 0, 0, 0, 0, 1243, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1245, 0, 0, 1247, 1249, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1251, 1253, 0, 0, 1255, 1257, - 0, 0, 1259, 1261, 1263, 1265, 0, 0, - 0, 0, 1267, 1269, 0, 0, 1271, 1273, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1275, 1277, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1279, 0, 0, 0, 0, 0, - 1281, 1283, 0, 1285, 0, 0, 0, 0, - 0, 0, 1287, 1289, 1291, 1293, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1295, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1297, 0, - 0, 0, 0, 1299, 0, 1301, 0, 1303, - 0, 1305, 0, 1307, 0, 1309, 0, 1311, - 0, 1313, 0, 1315, 0, 1317, 0, 1319, - 0, 1321, 0, 0, 1323, 0, 1325, 0, - 1327, 0, 0, 0, 0, 0, 0, 1329, - 0, 0, 1332, 0, 0, 1335, 0, 0, - 1338, 0, 0, 1341, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1344, 0, 0, - 0, 0, 0, 0, 0, 0, 1346, 0, - 0, 0, 0, 1348, 0, 1350, 0, 1352, - 0, 1354, 0, 1356, 0, 1358, 0, 1360, - 0, 1362, 0, 1364, 0, 1366, 0, 1368, - 0, 1370, 0, 0, 1372, 0, 1374, 0, - 1376, 0, 0, 0, 0, 0, 0, 1378, - 0, 0, 1381, 0, 0, 1384, 0, 0, - 1387, 0, 0, 1390, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1393, - 1395, 1397, 1399, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1401, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1403, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -// 14586 bytes - -const TQ_UINT8 TQUnicodeTables::direction_info[] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 2, 9, 10, 11, 12, 13, 14, 15, - 16, 2, 2, 2, 2, 2, 17, 18, - 19, 2, 2, 2, 2, 2, 2, 20, - 21, 22, 23, 24, 25, 26, 27, 28, - 26, 29, 30, 2, 2, 2, 31, 32, - 33, 2, 34, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 35, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 36, 37, 38, 39, 40, - - - 18, 18, 18, 18, 18, 18, 18, 18, - 18, 8, 7, 8, 9, 7, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 7, 7, 7, 8, - 9, 10, 10, 4, 4, 4, 10, 10, - 138, 138, 10, 4, 6, 4, 6, 3, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 6, 10, 138, 10, 138, 10, - 10, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 138, 10, 138, 10, 10, - 10, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 138, 10, 138, 10, 18, - 18, 18, 18, 18, 18, 7, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, - 6, 10, 4, 4, 4, 4, 10, 10, - 10, 10, 0, 138, 10, 10, 10, 10, - 4, 4, 2, 2, 10, 0, 10, 10, - 10, 2, 0, 138, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 10, 10, 0, 0, 0, 0, 0, - 0, 0, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 0, 0, 0, 0, 10, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 10, 0, - 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 17, 17, 17, 17, 0, - 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 10, 0, 0, 0, 0, 0, - 0, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 0, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 0, 17, 17, 17, 1, 17, - 1, 17, 17, 1, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 13, 0, 0, 0, 13, - 0, 13, 77, 77, 77, 77, 45, 77, - 45, 77, 45, 45, 45, 45, 45, 77, - 77, 77, 77, 45, 45, 45, 45, 45, - 45, 45, 45, 0, 0, 0, 0, 0, - 109, 45, 45, 45, 45, 45, 45, 45, - 77, 45, 45, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 4, 5, 5, 13, 45, 45, - 17, 77, 77, 77, 13, 77, 77, 77, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 77, 45, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 45, 77, 45, 77, - 45, 45, 77, 77, 13, 77, 17, 17, - 17, 17, 17, 17, 17, 13, 17, 17, - 17, 17, 17, 17, 17, 13, 13, 17, - 17, 10, 17, 17, 17, 17, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 45, 45, 45, 13, 13, 0, - - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 0, 18, - 77, 17, 45, 45, 45, 77, 77, 77, - 77, 77, 45, 45, 45, 45, 77, 45, - 45, 45, 45, 45, 45, 45, 45, 45, - 77, 45, 77, 45, 77, 0, 0, 0, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 13, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 17, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, - 0, 17, 17, 17, 17, 17, 17, 17, - 17, 0, 0, 0, 0, 17, 0, 0, - 0, 17, 17, 17, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, - 0, 17, 17, 17, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, - 0, 17, 17, 0, 0, 0, 0, 17, - 17, 0, 0, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, - 0, 17, 17, 17, 17, 17, 0, 17, - 17, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 17, - 0, 17, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 17, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 17, 17, - 17, 0, 0, 0, 0, 0, 17, 17, - 17, 0, 17, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 17, 17, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, - 0, 0, 0, 0, 0, 0, 17, 0, - 0, 0, 0, 0, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 17, 0, 17, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 0, 0, 17, 17, 17, 17, - 17, 17, 17, 0, 0, 0, 0, 4, - 0, 0, 0, 0, 0, 0, 0, 17, - 17, 17, 17, 17, 17, 17, 17, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 0, 0, 17, 17, 17, 17, - 17, 17, 0, 17, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 17, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 0, 17, - 0, 17, 10, 10, 10, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 0, - 17, 17, 17, 17, 17, 0, 17, 17, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 17, 17, 17, 17, 17, 17, - 0, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 17, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 17, 17, - 17, 0, 17, 0, 0, 0, 17, 17, - 0, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 10, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 17, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, - 17, 17, 17, 17, 17, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 17, 0, - 0, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 4, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 17, 17, 17, 18, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 0, 10, - 10, 10, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 10, 0, - - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 18, 18, 114, 0, 1, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 9, 7, 11, 14, 16, 12, 15, 9, - 4, 4, 4, 4, 4, 10, 10, 10, - 10, 138, 138, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 138, 138, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 0, 0, 0, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 9, - 18, 18, 18, 18, 0, 0, 0, 0, - 0, 0, 18, 18, 18, 18, 18, 18, - 2, 0, 0, 0, 2, 2, 2, 2, - 2, 2, 4, 4, 10, 138, 138, 0, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 4, 4, 10, 138, 138, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 10, 10, 0, 10, 10, 10, 10, 0, - 10, 10, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 10, 0, 10, 10, - 10, 0, 0, 0, 0, 0, 10, 10, - 10, 10, 10, 10, 0, 10, 0, 10, - 0, 10, 0, 0, 0, 0, 4, 0, - 0, 0, 10, 0, 0, 0, 0, 0, - 0, 0, 10, 0, 0, 0, 0, 0, - 138, 10, 10, 10, 10, 0, 0, 0, - 0, 0, 10, 10, 0, 0, 0, 0, - 0, 0, 0, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - - 10, 138, 138, 138, 138, 10, 10, 10, - 138, 138, 138, 138, 138, 138, 10, 10, - 10, 138, 4, 4, 10, 138, 138, 10, - 10, 10, 138, 138, 138, 138, 10, 138, - 138, 138, 138, 10, 138, 10, 138, 10, - 10, 10, 10, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 10, 10, 10, 10, - 10, 138, 10, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 10, 10, 10, - 10, 10, 138, 138, 138, 138, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 138, - 138, 10, 138, 10, 138, 138, 138, 138, - 138, 138, 138, 138, 10, 10, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 10, 10, 138, - 138, 138, 138, 10, 10, 10, 10, 10, - 138, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 138, 138, 10, 10, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 10, 10, 10, 10, 10, 138, 138, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 138, 138, 138, 138, 138, 10, 10, - 138, 138, 10, 10, 10, 10, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 10, 10, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - - 10, 10, 10, 10, 10, 10, 10, 10, - 138, 138, 138, 138, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 138, 138, 10, 10, 10, 10, 10, 10, - 10, 138, 138, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 0, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 0, 0, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 10, 10, 10, 10, 0, 10, 10, - 10, 10, 0, 0, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 0, 10, 0, 10, - 10, 10, 10, 0, 0, 0, 10, 0, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 10, 10, 10, 10, 10, 10, 10, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 138, 138, 138, 138, 10, - 10, 10, 10, 10, 138, 138, 138, 10, - 10, 10, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 10, 10, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 10, 10, 10, 10, 10, 10, 10, 10, - 138, 10, 10, 10, 10, 10, 10, 10, - 138, 138, 138, 138, 138, 138, 10, 10, - 10, 138, 10, 10, 10, 10, 138, 138, - 138, 138, 138, 10, 138, 138, 10, 10, - 138, 138, 138, 138, 138, 10, 10, 10, - 10, 138, 10, 138, 138, 138, 10, 10, - 138, 138, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 138, 138, 138, 138, - 138, 138, 10, 10, 138, 138, 10, 10, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 10, 138, 138, - 138, 138, 10, 10, 138, 10, 138, 10, - 10, 138, 10, 138, 138, 138, 138, 10, - 10, 10, 10, 10, 138, 138, 10, 10, - 10, 10, 10, 10, 138, 138, 138, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 138, - 138, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 138, 138, 10, 10, - 10, 10, 138, 138, 138, 138, 10, 138, - 138, 10, 10, 138, 138, 10, 10, 10, - 10, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 10, 10, 138, 138, - 138, 138, 138, 138, 138, 138, 10, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 138, 138, 138, 10, - 10, 10, 10, 10, 138, 10, 138, 10, - 10, 10, 138, 138, 138, 138, 138, 10, - 10, 10, 10, 10, 138, 138, 138, 10, - 10, 10, 10, 138, 10, 10, 10, 138, - 138, 138, 138, 138, 10, 138, 10, 10, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 0, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 0, 0, 0, 0, - - 9, 10, 10, 10, 10, 0, 0, 0, - 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 10, 10, 138, 138, 138, 138, - 138, 138, 138, 138, 10, 10, 10, 10, - 10, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 17, 17, 17, 17, 17, 17, - 10, 0, 0, 0, 0, 0, 10, 10, - 0, 0, 0, 0, 0, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 17, 10, 10, 0, 0, 0, - 10, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 17, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 4, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 1, 0, 1, 0, - 1, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 0, 0, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 0, 0, 0, - - 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 17, 17, 17, 17, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 10, 10, 10, 10, 10, 10, 10, - 6, 10, 6, 0, 10, 6, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 4, - 10, 10, 4, 4, 10, 10, 10, 0, - 10, 4, 4, 10, 0, 0, 0, 0, - 13, 13, 13, 13, 13, 0, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 0, 0, 18, - - 0, 10, 10, 4, 4, 4, 10, 10, - 138, 138, 10, 4, 6, 4, 6, 3, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 6, 10, 138, 10, 138, 10, - 10, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 138, 10, 138, 10, 10, - 10, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 138, 10, 138, 10, 138, - 138, 10, 138, 138, 10, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4, 4, 10, 10, 10, 4, 4, 0, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 18, 18, 18, 10, 10, 0, 0, -}; - -// 25082 bytes - -const TQ_UINT8 TQUnicodeTables::combining_info[] = { - 1, 1, 1, 2, 3, 4, 5, 6, - 1, 7, 8, 9, 10, 11, 12, 13, - 14, 1, 1, 1, 1, 1, 1, 15, - 16, 1, 1, 1, 1, 1, 1, 1, - 17, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 18, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 19, 1, 1, 20, 1, - - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 230, 230, 230, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 232, 220, 220, - 220, 220, 232, 216, 220, 220, 220, 220, - 220, 202, 202, 220, 220, 220, 220, 202, - 202, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 1, 1, 1, 1, - 1, 220, 220, 220, 220, 230, 230, 230, - 230, 230, 230, 230, 230, 240, 230, 220, - 220, 220, 230, 230, 230, 220, 220, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 234, 234, 233, 230, 230, 230, 230, 230, - 230, 230, 230, 230, 230, 230, 230, 230, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 230, 230, 230, 230, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 220, 230, 230, 230, 230, 220, 230, - 230, 230, 222, 220, 230, 230, 230, 230, - 230, 230, 0, 220, 220, 220, 220, 220, - 230, 230, 220, 230, 230, 222, 228, 230, - 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 0, 20, 21, 22, 0, 23, - 0, 24, 25, 0, 230, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 27, 28, 29, 30, 31, - 32, 33, 34, 230, 230, 220, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 35, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 230, 230, - 230, 230, 230, 230, 230, 0, 0, 230, - 230, 230, 230, 220, 230, 0, 0, 230, - 230, 0, 220, 230, 230, 220, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 36, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 230, 220, 230, 230, 220, 230, 230, 220, - 220, 220, 230, 220, 220, 230, 220, 230, - 230, 230, 220, 230, 220, 230, 220, 230, - 220, 230, 230, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 230, 220, 230, 230, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 84, 91, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 103, 103, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 107, 107, 107, 107, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 118, 118, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 122, 122, 122, 122, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 220, 220, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 220, 0, 220, - 0, 216, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 129, 130, 0, 132, 0, 0, 0, - 0, 0, 130, 130, 130, 130, 0, 0, - 130, 0, 230, 230, 9, 0, 230, 230, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 220, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 7, - 0, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 228, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 230, 230, 1, 1, 230, 230, 230, 230, - 1, 1, 1, 230, 230, 0, 0, 0, - 0, 230, 0, 0, 0, 1, 1, 230, - 220, 230, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 218, 228, 232, 222, 224, 224, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 8, 8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 26, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 230, 230, 230, 230, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -// 30458 bytes - -const TQ_UINT16 TQUnicodeTables::case_info[] = { - 1, 2, 3, 4, 5, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 7, 8, - 0, 9, 0, 0, 10, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 11, - - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0, - 0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x39c, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x1e9e, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x178, - - 0x101, 0x100, 0x103, 0x102, 0x105, 0x104, 0x107, 0x106, - 0x109, 0x108, 0x10b, 0x10a, 0x10d, 0x10c, 0x10f, 0x10e, - 0x111, 0x110, 0x113, 0x112, 0x115, 0x114, 0x117, 0x116, - 0x119, 0x118, 0x11b, 0x11a, 0x11d, 0x11c, 0x11f, 0x11e, - 0x121, 0x120, 0x123, 0x122, 0x125, 0x124, 0x127, 0x126, - 0x129, 0x128, 0x12b, 0x12a, 0x12d, 0x12c, 0x12f, 0x12e, - 0x69, 0x49, 0x133, 0x132, 0x135, 0x134, 0x137, 0x136, - 0, 0x13a, 0x139, 0x13c, 0x13b, 0x13e, 0x13d, 0x140, - 0x13f, 0x142, 0x141, 0x144, 0x143, 0x146, 0x145, 0x148, - 0x147, 0, 0x14b, 0x14a, 0x14d, 0x14c, 0x14f, 0x14e, - 0x151, 0x150, 0x153, 0x152, 0x155, 0x154, 0x157, 0x156, - 0x159, 0x158, 0x15b, 0x15a, 0x15d, 0x15c, 0x15f, 0x15e, - 0x161, 0x160, 0x163, 0x162, 0x165, 0x164, 0x167, 0x166, - 0x169, 0x168, 0x16b, 0x16a, 0x16d, 0x16c, 0x16f, 0x16e, - 0x171, 0x170, 0x173, 0x172, 0x175, 0x174, 0x177, 0x176, - 0xff, 0x17a, 0x179, 0x17c, 0x17b, 0x17e, 0x17d, 0x53, - 0, 0x253, 0x183, 0x182, 0x185, 0x184, 0x254, 0x188, - 0x187, 0x256, 0x257, 0x18c, 0x18b, 0, 0x1dd, 0x259, - 0x25b, 0x192, 0x191, 0x260, 0x263, 0x1f6, 0x269, 0x268, - 0x199, 0x198, 0, 0, 0x26f, 0x272, 0x220, 0x275, - 0x1a1, 0x1a0, 0x1a3, 0x1a2, 0x1a5, 0x1a4, 0x280, 0x1a8, - 0x1a7, 0x283, 0, 0, 0x1ad, 0x1ac, 0x288, 0x1b0, - 0x1af, 0x28a, 0x28b, 0x1b4, 0x1b3, 0x1b6, 0x1b5, 0x292, - 0x1b9, 0x1b8, 0, 0, 0x1bd, 0x1bc, 0, 0x1f7, - 0, 0, 0, 0, 0x1c6, 0x1c4, 0x1c4, 0x1c9, - 0x1c7, 0x1c7, 0x1cc, 0x1ca, 0x1ca, 0x1ce, 0x1cd, 0x1d0, - 0x1cf, 0x1d2, 0x1d1, 0x1d4, 0x1d3, 0x1d6, 0x1d5, 0x1d8, - 0x1d7, 0x1da, 0x1d9, 0x1dc, 0x1db, 0x18e, 0x1df, 0x1de, - 0x1e1, 0x1e0, 0x1e3, 0x1e2, 0x1e5, 0x1e4, 0x1e7, 0x1e6, - 0x1e9, 0x1e8, 0x1eb, 0x1ea, 0x1ed, 0x1ec, 0x1ef, 0x1ee, - 0, 0x1f3, 0x1f1, 0x1f1, 0x1f5, 0x1f4, 0x195, 0x1bf, - 0x1f9, 0x1f8, 0x1fb, 0x1fa, 0x1fd, 0x1fc, 0x1ff, 0x1fe, - - 0x201, 0x200, 0x203, 0x202, 0x205, 0x204, 0x207, 0x206, - 0x209, 0x208, 0x20b, 0x20a, 0x20d, 0x20c, 0x20f, 0x20e, - 0x211, 0x210, 0x213, 0x212, 0x215, 0x214, 0x217, 0x216, - 0x219, 0x218, 0x21b, 0x21a, 0x21d, 0x21c, 0x21f, 0x21e, - 0x19e, 0, 0x223, 0x222, 0x225, 0x224, 0x227, 0x226, - 0x229, 0x228, 0x22b, 0x22a, 0x22d, 0x22c, 0x22f, 0x22e, - 0x231, 0x230, 0x233, 0x232, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x242, 0x241, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x181, 0x186, 0, 0x189, 0x18a, - 0, 0x18f, 0, 0x190, 0, 0, 0, 0, - 0x193, 0, 0, 0x194, 0, 0, 0, 0, - 0x197, 0x196, 0, 0, 0, 0, 0, 0x19c, - 0, 0, 0x19d, 0, 0, 0x19f, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x1a6, 0, 0, 0x1a9, 0, 0, 0, 0, - 0x1ae, 0, 0x1b1, 0x1b2, 0, 0, 0, 0, - 0, 0, 0x1b7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x399, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3ac, 0, - 0x3ad, 0x3ae, 0x3af, 0, 0x3cc, 0, 0x3cd, 0x3ce, - 0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, - 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf, - 0x3c0, 0x3c1, 0, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, - 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x386, 0x388, 0x389, 0x38a, - 0, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, - 0x398, 0x399, 0x39a, 0x39b, 0x39c, 0x39d, 0x39e, 0x39f, - 0x3a0, 0x3a1, 0x3a3, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, - 0x3a8, 0x3a9, 0x3aa, 0x3ab, 0x38c, 0x38e, 0x38f, 0, - 0x392, 0x398, 0, 0, 0, 0x3a6, 0x3a0, 0, - 0x3d9, 0x3d8, 0x3db, 0x3da, 0x3dd, 0x3dc, 0x3df, 0x3de, - 0x3e1, 0x3e0, 0x3e3, 0x3e2, 0x3e5, 0x3e4, 0x3e7, 0x3e6, - 0x3e9, 0x3e8, 0x3eb, 0x3ea, 0x3ed, 0x3ec, 0x3ef, 0x3ee, - 0x39a, 0x3a1, 0x3f9, 0, 0x3b8, 0x395, 0, 0, - 0, 0x3f2, 0x3fb, 0x3fa, 0, 0, 0, 0, - - 0x450, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, - 0x458, 0x459, 0x45a, 0x45b, 0x45c, 0x45d, 0x45e, 0x45f, - 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, - 0x438, 0x439, 0x43a, 0x43b, 0x43c, 0x43d, 0x43e, 0x43f, - 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, - 0x448, 0x449, 0x44a, 0x44b, 0x44c, 0x44d, 0x44e, 0x44f, - 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, - 0x418, 0x419, 0x41a, 0x41b, 0x41c, 0x41d, 0x41e, 0x41f, - 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, - 0x428, 0x429, 0x42a, 0x42b, 0x42c, 0x42d, 0x42e, 0x42f, - 0x400, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, - 0x408, 0x409, 0x40a, 0x40b, 0x40c, 0x40d, 0x40e, 0x40f, - 0x461, 0x460, 0x463, 0x462, 0x465, 0x464, 0x467, 0x466, - 0x469, 0x468, 0x46b, 0x46a, 0x46d, 0x46c, 0x46f, 0x46e, - 0x471, 0x470, 0x473, 0x472, 0x475, 0x474, 0x477, 0x476, - 0x479, 0x478, 0x47b, 0x47a, 0x47d, 0x47c, 0x47f, 0x47e, - 0x481, 0x480, 0, 0, 0, 0, 0, 0, - 0, 0, 0x48b, 0x48a, 0x48d, 0x48c, 0x48f, 0x48e, - 0x491, 0x490, 0x493, 0x492, 0x495, 0x494, 0x497, 0x496, - 0x499, 0x498, 0x49b, 0x49a, 0x49d, 0x49c, 0x49f, 0x49e, - 0x4a1, 0x4a0, 0x4a3, 0x4a2, 0x4a5, 0x4a4, 0x4a7, 0x4a6, - 0x4a9, 0x4a8, 0x4ab, 0x4aa, 0x4ad, 0x4ac, 0x4af, 0x4ae, - 0x4b1, 0x4b0, 0x4b3, 0x4b2, 0x4b5, 0x4b4, 0x4b7, 0x4b6, - 0x4b9, 0x4b8, 0x4bb, 0x4ba, 0x4bd, 0x4bc, 0x4bf, 0x4be, - 0, 0x4c2, 0x4c1, 0x4c4, 0x4c3, 0x4c6, 0x4c5, 0x4c8, - 0x4c7, 0x4ca, 0x4c9, 0x4cc, 0x4cb, 0x4ce, 0x4cd, 0, - 0x4d1, 0x4d0, 0x4d3, 0x4d2, 0x4d5, 0x4d4, 0x4d7, 0x4d6, - 0x4d9, 0x4d8, 0x4db, 0x4da, 0x4dd, 0x4dc, 0x4df, 0x4de, - 0x4e1, 0x4e0, 0x4e3, 0x4e2, 0x4e5, 0x4e4, 0x4e7, 0x4e6, - 0x4e9, 0x4e8, 0x4eb, 0x4ea, 0x4ed, 0x4ec, 0x4ef, 0x4ee, - 0x4f1, 0x4f0, 0x4f3, 0x4f2, 0x4f5, 0x4f4, 0, 0, - 0x4f9, 0x4f8, 0, 0, 0, 0, 0, 0, - - 0x501, 0x500, 0x503, 0x502, 0x505, 0x504, 0x507, 0x506, - 0x509, 0x508, 0x50b, 0x50a, 0x50d, 0x50c, 0x50f, 0x50e, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x561, 0x562, 0x563, 0x564, 0x565, 0x566, 0x567, - 0x568, 0x569, 0x56a, 0x56b, 0x56c, 0x56d, 0x56e, 0x56f, - 0x570, 0x571, 0x572, 0x573, 0x574, 0x575, 0x576, 0x577, - 0x578, 0x579, 0x57a, 0x57b, 0x57c, 0x57d, 0x57e, 0x57f, - 0x580, 0x581, 0x582, 0x583, 0x584, 0x585, 0x586, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x531, 0x532, 0x533, 0x534, 0x535, 0x536, 0x537, - 0x538, 0x539, 0x53a, 0x53b, 0x53c, 0x53d, 0x53e, 0x53f, - 0x540, 0x541, 0x542, 0x543, 0x544, 0x545, 0x546, 0x547, - 0x548, 0x549, 0x54a, 0x54b, 0x54c, 0x54d, 0x54e, 0x54f, - 0x550, 0x551, 0x552, 0x553, 0x554, 0x555, 0x556, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0x1e01, 0x1e00, 0x1e03, 0x1e02, 0x1e05, 0x1e04, 0x1e07, 0x1e06, - 0x1e09, 0x1e08, 0x1e0b, 0x1e0a, 0x1e0d, 0x1e0c, 0x1e0f, 0x1e0e, - 0x1e11, 0x1e10, 0x1e13, 0x1e12, 0x1e15, 0x1e14, 0x1e17, 0x1e16, - 0x1e19, 0x1e18, 0x1e1b, 0x1e1a, 0x1e1d, 0x1e1c, 0x1e1f, 0x1e1e, - 0x1e21, 0x1e20, 0x1e23, 0x1e22, 0x1e25, 0x1e24, 0x1e27, 0x1e26, - 0x1e29, 0x1e28, 0x1e2b, 0x1e2a, 0x1e2d, 0x1e2c, 0x1e2f, 0x1e2e, - 0x1e31, 0x1e30, 0x1e33, 0x1e32, 0x1e35, 0x1e34, 0x1e37, 0x1e36, - 0x1e39, 0x1e38, 0x1e3b, 0x1e3a, 0x1e3d, 0x1e3c, 0x1e3f, 0x1e3e, - 0x1e41, 0x1e40, 0x1e43, 0x1e42, 0x1e45, 0x1e44, 0x1e47, 0x1e46, - 0x1e49, 0x1e48, 0x1e4b, 0x1e4a, 0x1e4d, 0x1e4c, 0x1e4f, 0x1e4e, - 0x1e51, 0x1e50, 0x1e53, 0x1e52, 0x1e55, 0x1e54, 0x1e57, 0x1e56, - 0x1e59, 0x1e58, 0x1e5b, 0x1e5a, 0x1e5d, 0x1e5c, 0x1e5f, 0x1e5e, - 0x1e61, 0x1e60, 0x1e63, 0x1e62, 0x1e65, 0x1e64, 0x1e67, 0x1e66, - 0x1e69, 0x1e68, 0x1e6b, 0x1e6a, 0x1e6d, 0x1e6c, 0x1e6f, 0x1e6e, - 0x1e71, 0x1e70, 0x1e73, 0x1e72, 0x1e75, 0x1e74, 0x1e77, 0x1e76, - 0x1e79, 0x1e78, 0x1e7b, 0x1e7a, 0x1e7d, 0x1e7c, 0x1e7f, 0x1e7e, - 0x1e81, 0x1e80, 0x1e83, 0x1e82, 0x1e85, 0x1e84, 0x1e87, 0x1e86, - 0x1e89, 0x1e88, 0x1e8b, 0x1e8a, 0x1e8d, 0x1e8c, 0x1e8f, 0x1e8e, - 0x1e91, 0x1e90, 0x1e93, 0x1e92, 0x1e95, 0x1e94, 0, 0, - 0, 0, 0, 0x1e60, 0, 0, 0xdf, 0, - 0x1ea1, 0x1ea0, 0x1ea3, 0x1ea2, 0x1ea5, 0x1ea4, 0x1ea7, 0x1ea6, - 0x1ea9, 0x1ea8, 0x1eab, 0x1eaa, 0x1ead, 0x1eac, 0x1eaf, 0x1eae, - 0x1eb1, 0x1eb0, 0x1eb3, 0x1eb2, 0x1eb5, 0x1eb4, 0x1eb7, 0x1eb6, - 0x1eb9, 0x1eb8, 0x1ebb, 0x1eba, 0x1ebd, 0x1ebc, 0x1ebf, 0x1ebe, - 0x1ec1, 0x1ec0, 0x1ec3, 0x1ec2, 0x1ec5, 0x1ec4, 0x1ec7, 0x1ec6, - 0x1ec9, 0x1ec8, 0x1ecb, 0x1eca, 0x1ecd, 0x1ecc, 0x1ecf, 0x1ece, - 0x1ed1, 0x1ed0, 0x1ed3, 0x1ed2, 0x1ed5, 0x1ed4, 0x1ed7, 0x1ed6, - 0x1ed9, 0x1ed8, 0x1edb, 0x1eda, 0x1edd, 0x1edc, 0x1edf, 0x1ede, - 0x1ee1, 0x1ee0, 0x1ee3, 0x1ee2, 0x1ee5, 0x1ee4, 0x1ee7, 0x1ee6, - 0x1ee9, 0x1ee8, 0x1eeb, 0x1eea, 0x1eed, 0x1eec, 0x1eef, 0x1eee, - 0x1ef1, 0x1ef0, 0x1ef3, 0x1ef2, 0x1ef5, 0x1ef4, 0x1ef7, 0x1ef6, - 0x1ef9, 0x1ef8, 0, 0, 0, 0, 0, 0, - - 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, - 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, - 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0, 0, - 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0, 0, - 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, - 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, - 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, - 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, - 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0, 0, - 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0, 0, - 0, 0x1f59, 0, 0x1f5b, 0, 0x1f5d, 0, 0x1f5f, - 0, 0x1f51, 0, 0x1f53, 0, 0x1f55, 0, 0x1f57, - 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, - 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, - 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, - 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0, 0, - 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, - 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, - 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, - 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, - 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf, - 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, - 0x1fb8, 0x1fb9, 0, 0x1fbc, 0, 0, 0, 0, - 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0, 0x399, 0, - 0, 0, 0, 0x1fcc, 0, 0, 0, 0, - 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0, 0, 0, - 0x1fd8, 0x1fd9, 0, 0, 0, 0, 0, 0, - 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0, 0, 0, 0, - 0x1fe8, 0x1fe9, 0, 0, 0, 0x1fec, 0, 0, - 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0, 0, 0, - 0, 0, 0, 0x1ffc, 0, 0, 0, 0, - 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3c9, 0, - 0, 0, 0x6b, 0xe5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, - 0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x24d0, 0x24d1, - 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, - 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, - 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, - 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd, - 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5, - 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd, - 0x24ce, 0x24cf, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, - 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, - 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, - 0xff58, 0xff59, 0xff5a, 0, 0, 0, 0, 0, - 0, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, - 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, - 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, - 0xff38, 0xff39, 0xff3a, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -// 36602 bytes - -const TQ_INT8 TQUnicodeTables::decimal_info[] = { - 1, 0, 0, 0, 0, 0, 2, 0, - 0, 3, 3, 4, 3, 5, 6, 7, - 8, 0, 0, 9, 0, 0, 0, 10, - 11, 0, 0, 0, 0, 0, 0, 0, - 12, 0, 0, 0, 13, 0, 0, 14, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 11, - - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2, 3, -1, -1, -1, -1, - -1, 1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, - 2, 3, 4, 5, 6, 7, 8, 9, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, - 2, 3, 4, 5, 6, 7, 8, 9, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, - 2, 3, 4, 5, 6, 7, 8, 9, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1, - 2, 3, 4, 5, 6, 7, 8, 9, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, - 2, 3, 4, 5, 6, 7, 8, 9, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 0, -1, -1, -1, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 2, 3, 4, 5, 6, 7, 8, - 9, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 1, 2, 3, 4, - 5, 6, 7, 8, 9, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 1, 2, 3, 4, 5, 6, 7, 8, - 9, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 0, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1, 2, 3, - 4, 5, 6, 7, 8, 9, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1, 2, - 3, 4, 5, 6, 7, 8, 9, -1, - 1, 2, 3, 4, 5, 6, 7, 8, - 9, -1, 1, 2, 3, 4, 5, 6, - 7, 8, 9, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -}; -// 40698 bytes - -#endif - -#ifdef TQT_NO_UNICODETABLES - -const TQ_UINT8 TQUnicodeTables::latin1_line_break_info[] = { - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 15, 23, 19, 21, 22, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 26, 5, 2, 11, 8, 9, 11, 2, - 0, 1, 11, 8, 7, 14, 7, 6, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 7, 7, 11, 11, 11, 5, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 0, 8, 1, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 0, 15, 1, 11, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 3, 11, 9, 8, 8, 8, 11, 11, - 11, 11, 11, 2, 11, 15, 11, 11, - 9, 8, 11, 11, 16, 11, 11, 11, - 11, 11, 11, 2, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, -}; - -#else - -const TQ_UINT8 TQUnicodeTables::line_break_info[] = { - 1, 2, 3, 4, 5, 6, 7, 8, - 2, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 2, 18, 2, 2, 19, 20, - 21, 2, 2, 2, 2, 2, 2, 2, - 22, 23, 24, 25, 2, 2, 2, 26, - 2, 27, 2, 2, 2, 2, 28, 29, - 30, 31, 32, 33, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 35, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 36, - 34, 34, 34, 34, 37, 2, 2, 2, - 2, 2, 2, 2, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 34, - 34, 34, 34, 34, 34, 34, 34, 38, - 39, 39, 39, 39, 39, 39, 39, 39, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 34, 40, 41, 2, 42, 43, 44, - - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 15, 23, 19, 21, 22, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 26, 5, 2, 11, 8, 9, 11, 2, - 0, 1, 11, 8, 7, 14, 7, 6, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 7, 7, 11, 11, 11, 5, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 0, 8, 1, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 0, 15, 1, 11, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 3, 11, 9, 8, 8, 8, 11, 11, - 11, 11, 11, 2, 11, 15, 11, 11, - 9, 8, 11, 11, 16, 11, 11, 11, - 11, 11, 11, 2, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 16, 11, 11, 11, 16, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 19, 19, 19, 19, 11, - 19, 19, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 7, 15, 11, 11, 11, 11, 11, - 11, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 11, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 11, 19, 19, 19, 11, 19, - 11, 19, 19, 11, 19, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - 19, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 11, 11, 19, - 19, 11, 19, 19, 19, 19, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 19, - 11, 19, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 19, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 19, 11, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 11, 11, - 11, 19, 19, 19, 19, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 19, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 19, 11, 19, 19, - 19, 19, 19, 19, 19, 11, 11, 19, - 19, 11, 11, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 8, 8, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 19, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 19, 11, 19, 19, - 19, 19, 19, 11, 11, 11, 11, 19, - 19, 11, 11, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 19, 19, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 19, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 19, 11, 19, 19, - 19, 19, 19, 19, 19, 19, 11, 19, - 19, 19, 11, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 19, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 19, 11, 19, 19, - 19, 19, 19, 19, 11, 11, 11, 19, - 19, 11, 11, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 19, 19, 19, 11, 11, 11, 19, 19, - 19, 11, 19, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 19, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 19, 19, 19, 19, 19, 11, 19, 19, - 19, 11, 19, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 19, 19, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 19, 19, 19, 19, 19, 11, 19, 19, - 19, 11, 19, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 19, 19, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 19, - 19, 19, 19, 19, 11, 11, 19, 19, - 19, 11, 19, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 11, 11, 11, 11, 19, - 19, 19, 19, 19, 19, 11, 19, 11, - 19, 19, 19, 19, 19, 19, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 19, 20, 20, 19, 19, 19, 19, - 19, 19, 19, 11, 11, 11, 11, 8, - 20, 20, 20, 20, 20, 20, 20, 19, - 19, 19, 19, 19, 19, 19, 19, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 4, 4, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 20, 20, 11, 20, 11, 11, 20, - 20, 11, 20, 11, 11, 20, 11, 11, - 11, 11, 11, 11, 20, 20, 20, 20, - 11, 20, 20, 20, 20, 20, 20, 20, - 11, 20, 20, 20, 11, 20, 11, 20, - 11, 11, 20, 20, 11, 20, 20, 20, - 20, 19, 20, 20, 19, 19, 19, 19, - 19, 19, 11, 19, 19, 20, 11, 11, - 20, 20, 20, 20, 20, 11, 20, 11, - 19, 19, 19, 19, 19, 19, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 20, 20, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 15, 3, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 19, 19, 11, 11, 11, 11, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 19, 11, 19, - 11, 19, 0, 1, 0, 1, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 11, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 19, 19, 19, 19, 19, 19, 19, 19, - 11, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 11, 20, 20, 20, 20, 20, - 11, 20, 20, 11, 19, 19, 19, 19, - 19, 19, 19, 11, 11, 11, 19, 19, - 19, 19, 11, 11, 11, 11, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - 20, 20, 20, 20, 20, 20, 19, 19, - 19, 19, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 11, 11, 11, 11, 11, 12, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 11, 11, 11, 11, 11, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 15, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 15, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 0, 1, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 19, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 19, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 4, 15, 4, 4, - 4, 4, 4, 8, 11, 11, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 16, 11, - 11, 11, 11, 19, 19, 19, 19, 11, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 19, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 15, 15, 15, 15, 15, 15, 15, 3, - 15, 15, 15, 18, 19, 19, 19, 19, - 15, 3, 15, 15, 17, 11, 11, 11, - 2, 2, 0, 2, 2, 2, 0, 2, - 11, 11, 11, 11, 13, 13, 13, 15, - 21, 21, 19, 19, 19, 19, 19, 3, - 9, 9, 9, 9, 9, 9, 9, 9, - 11, 2, 2, 11, 4, 11, 11, 11, - 11, 11, 11, 11, 4, 0, 1, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 15, - 3, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 19, 19, 19, 19, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 0, 1, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 0, 1, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 8, 8, 8, 8, 8, 8, 8, 9, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 9, 11, 11, 11, 11, - 11, 9, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 8, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 9, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 8, 8, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 0, 1, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 0, 1, 2, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 2, 2, 2, 2, 11, - 11, 11, 5, 5, 11, 11, 11, 11, - 0, 1, 0, 1, 0, 1, 0, 1, - 0, 1, 0, 1, 0, 1, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 0, 1, - 0, 1, 0, 1, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 0, 1, 0, 1, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 0, 1, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 11, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, - - 12, 1, 1, 12, 12, 4, 12, 12, - 0, 1, 0, 1, 0, 1, 0, 1, - 0, 1, 12, 12, 0, 1, 0, 1, - 0, 1, 0, 1, 4, 0, 1, 1, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 19, 19, 19, 19, 19, 19, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 4, 4, 12, 12, 12, - 11, 4, 12, 4, 12, 4, 12, 4, - 12, 4, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 4, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 4, 12, 4, 12, 4, - 12, 12, 12, 12, 12, 12, 4, 12, - 12, 12, 12, 12, 12, 4, 4, 11, - 11, 19, 19, 4, 4, 4, 4, 12, - 4, 4, 12, 4, 12, 4, 12, 4, - 12, 4, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 4, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 4, 12, 4, 12, 4, - 12, 12, 12, 12, 12, 12, 4, 12, - 12, 12, 12, 12, 12, 4, 4, 12, - 12, 12, 12, 4, 12, 4, 12, 12, - - 11, 11, 11, 11, 11, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 11, 11, 11, - 11, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, - - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 19, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 0, 1, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 9, 11, 11, 11, - - 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 19, 19, 19, 19, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 12, 12, 11, - 11, 12, 12, 12, 12, 12, 12, 12, - 1, 12, 1, 11, 4, 4, 5, 5, - 12, 0, 1, 0, 1, 0, 1, 12, - 12, 12, 12, 12, 12, 12, 12, 11, - 12, 8, 9, 12, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 3, - - 11, 5, 12, 12, 8, 9, 12, 12, - 0, 1, 12, 12, 1, 12, 1, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 4, 4, 12, 12, 12, 5, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 0, 12, 1, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 0, 12, 1, 12, 0, - 1, 1, 0, 1, 1, 4, 11, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 4, 4, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 9, 8, 12, 12, 12, 8, 8, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, - 11, 19, 19, 19, 25, 11, 11, 11, -}; -// 52474 bytes - -#endif - -// END OF GENERATED DATA - - - -#ifndef TQT_NO_UNICODETABLES -const TQ_UINT16 TQUnicodeTables::symmetricPairs[] = { - 0x0028, 0x0029, 0x003C, 0x003E, 0x005B, 0x005D, 0x007B, 0x007D, - 0x00AB, 0x00BB, 0x2039, 0x203A, 0x2045, 0x2046, 0x207D, 0x207E, - 0x208D, 0x208E, 0x2208, 0x220B, 0x2209, 0x220C, 0x220A, 0x220D, - 0x2215, 0x29F5, 0x223C, 0x223D, 0x2243, 0x22CD, 0x2252, 0x2253, - 0x2254, 0x2255, 0x2264, 0x2265, 0x2266, 0x2267, 0x2268, 0x2269, - 0x226A, 0x226B, 0x226E, 0x226F, 0x2270, 0x2271, 0x2272, 0x2273, - 0x2274, 0x2275, 0x2276, 0x2277, 0x2278, 0x2279, 0x227A, 0x227B, - 0x227C, 0x227D, 0x227E, 0x227F, 0x2280, 0x2281, 0x2282, 0x2283, - 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289, 0x228A, 0x228B, - 0x228F, 0x2290, 0x2291, 0x2292, 0x2298, 0x29B8, 0x22A2, 0x22A3, - 0x22A6, 0x2ADE, 0x22A8, 0x2AE4, 0x22A9, 0x2AE3, 0x22AB, 0x2AE5, - 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x22B4, 0x22B5, 0x22B6, 0x22B7, - 0x22C9, 0x22CA, 0x22CB, 0x22CC, 0x22D0, 0x22D1, 0x22D6, 0x22D7, - 0x22D8, 0x22D9, 0x22DA, 0x22DB, 0x22DC, 0x22DD, 0x22DE, 0x22DF, - 0x22E0, 0x22E1, 0x22E2, 0x22E3, 0x22E4, 0x22E5, 0x22E6, 0x22E7, - 0x22E8, 0x22E9, 0x22EA, 0x22EB, 0x22EC, 0x22ED, 0x22F0, 0x22F1, - 0x22F2, 0x22FA, 0x22F3, 0x22FB, 0x22F4, 0x22FC, 0x22F6, 0x22FD, - 0x22F7, 0x22FE, 0x2308, 0x2309, 0x230A, 0x230B, 0x2329, 0x232A, - 0x2768, 0x2769, 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, - 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x27D5, 0x27D6, - 0x27DD, 0x27DE, 0x27E2, 0x27E3, 0x27E4, 0x27E5, 0x27E6, 0x27E7, - 0x27E8, 0x27E9, 0x27EA, 0x27EB, 0x2983, 0x2984, 0x2985, 0x2986, - 0x2987, 0x2988, 0x2989, 0x298A, 0x298B, 0x298C, 0x298D, 0x2990, - 0x298E, 0x298F, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, - 0x2997, 0x2998, 0x29C0, 0x29C1, 0x29C4, 0x29C5, 0x29CF, 0x29D0, - 0x29D1, 0x29D2, 0x29D4, 0x29D5, 0x29D8, 0x29D9, 0x29DA, 0x29DB, - 0x29F8, 0x29F9, 0x29FC, 0x29FD, 0x2A2B, 0x2A2C, 0x2A34, 0x2A35, - 0x2A3C, 0x2A3D, 0x2A64, 0x2A65, 0x2A79, 0x2A7A, 0x2A7D, 0x2A7E, - 0x2A7F, 0x2A80, 0x2A81, 0x2A82, 0x2A83, 0x2A84, 0x2A8B, 0x2A8C, - 0x2A91, 0x2A92, 0x2A93, 0x2A94, 0x2A95, 0x2A96, 0x2A97, 0x2A98, - 0x2A99, 0x2A9A, 0x2A9B, 0x2A9C, 0x2AA1, 0x2AA2, 0x2AA6, 0x2AA7, - 0x2AA8, 0x2AA9, 0x2AAA, 0x2AAB, 0x2AAC, 0x2AAD, 0x2AAF, 0x2AB0, - 0x2AB3, 0x2AB4, 0x2ABB, 0x2ABC, 0x2ABD, 0x2ABE, 0x2ABF, 0x2AC0, - 0x2AC1, 0x2AC2, 0x2AC3, 0x2AC4, 0x2AC5, 0x2AC6, 0x2ACD, 0x2ACE, - 0x2ACF, 0x2AD0, 0x2AD1, 0x2AD2, 0x2AD3, 0x2AD4, 0x2AD5, 0x2AD6, - 0x2AEC, 0x2AED, 0x2AF7, 0x2AF8, 0x2AF9, 0x2AFA, 0x3008, 0x3009, - 0x300A, 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3010, 0x3011, - 0x3014, 0x3015, 0x3016, 0x3017, 0x3018, 0x3019, 0x301A, 0x301B, - 0xFF08, 0xFF09, 0xFF1C, 0xFF1E, 0xFF3B, 0xFF3D, 0xFF5B, 0xFF5D, - 0xFF5F, 0xFF60, 0xFF62, 0xFF63, -}; - -// ### shouldn't this be const? -const int TQUnicodeTables::symmetricPairsSize = - sizeof(symmetricPairs)/sizeof(symmetricPairs[0]); - -#else - -/* - only include info for the first unicode range (latin1) when building - without unicode tables. -*/ -const TQ_UINT8 TQUnicodeTables::unicode_info[] = { - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 7, 26, 26, 26, 28, 26, 26, 26, - 22, 23, 26, 27, 26, 21, 26, 26, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 26, 26, 27, 27, 27, 26, - 26, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 22, 26, 23, 29, 20, - 29, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 22, 27, 23, 27, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 7, 26, 28, 28, 28, 28, 30, 30, - 29, 30, 16, 24, 27, 21, 30, 29, - 30, 27, 6, 6, 29, 16, 30, 26, - 29, 6, 16, 25, 6, 6, 6, 26, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 27, - 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 27, - 16, 16, 16, 16, 16, 16, 16, 16 -}; - -#endif - -/* - * ---------------------------------------------------------------------- - * End of unicode tables - * ---------------------------------------------------------------------- - */ - -enum Script { - // European Alphabetic Scripts - Latin, - Greek, - Cyrillic, - Armenian, - Georgian, - Runic, - Ogham, - SpacingModifiers, - CombiningMarks, - - // Middle Eastern Scripts - Hebrew, - Arabic, - Syriac, - Thaana, - - // South and Southeast Asian Scripts - Devanagari, - Bengali, - Gurmukhi, - Gujarati, - Oriya, - Tamil, - Telugu, - Kannada, - Malayalam, - Sinhala, - Thai, - Lao, - Tibetan, - Myanmar, - Khmer, - - // East Asian Scripts - Han, - Hiragana, - Katakana, - Hangul, - Bopomofo, - Yi, - - // Additional Scripts - Ethiopic, - Cherokee, - CanadianAboriginal, - Mongolian, - - // Symbols - CurrencySymbols, - LetterlikeSymbols, - NumberForms, - MathematicalOperators, - TechnicalSymbols, - GeometricSymbols, - MiscellaneousSymbols, - EnclosedAndSquare, - Braille, - - Unicode, - - // some scripts added in Unicode 3.2 - Tagalog, - Hanunoo, - Buhid, - Tagbanwa, - - KatakanaHalfWidth, // from JIS X 0201 - - // from Unicode 4.0 - Limbu, - TaiLe, - - // End - NScripts, - UnknownScript = NScripts -}; - -// copied form tqfont.h, as we can't include it in tools. Do not modify without -// changing the script enum in tqfont.h aswell. -const unsigned char TQUnicodeTables::otherScripts [128] = { -#define SCRIPTS_02 0 - 0xaf, Latin, 0xff, SpacingModifiers, // row 0x02, index 0 -#define SCRIPTS_03 4 - 0x6f, CombiningMarks, 0xff, Greek, // row 0x03, index 4 -#define SCRIPTS_05 8 - 0x2f, Cyrillic, 0x8f, Armenian, 0xff, Hebrew, // row 0x05, index 8 -#define SCRIPTS_07 14 - 0x4f, Syriac, 0x7f, Unicode, 0xbf, Thaana, - 0xff, Unicode, // row 0x07, index 14 -#define SCRIPTS_10 22 - 0x9f, Myanmar, 0xff, Georgian, // row 0x10, index 20 -#define SCRIPTS_13 26 - 0x7f, Ethiopic, 0x9f, Unicode, 0xff, Cherokee, // row 0x13, index 24 -#define SCRIPTS_16 32 - 0x7f, CanadianAboriginal, 0x9f, Ogham, - 0xff, Runic, // row 0x16 index 30 -#define SCRIPTS_17 38 - 0x1f, Tagalog, 0x3f, Hanunoo, 0x5f, Buhid, - 0x7f, Tagbanwa, 0xff, Khmer, // row 0x17, index 36 -#define SCRIPTS_18 48 - 0xaf, Mongolian, 0xff, Unicode, // row 0x18, index 46 -#define SCRIPTS_19 52 - 0x4f, Limbu, 0x7f, TaiLe, 0xdf, Unicode, 0xff, Khmer, -#define SCRIPTS_20 60 - 0x0a, Unicode, 0x0d, UnknownScript, 0x6f, Unicode, 0x9f, NumberForms, - 0xab, CurrencySymbols, 0xac, Latin, - 0xcf, CurrencySymbols, 0xff, CombiningMarks, // row 0x20, index 50 -#define SCRIPTS_21 76 - 0x4f, LetterlikeSymbols, 0x8f, NumberForms, - 0xff, MathematicalOperators, // row 0x21, index 62 -#define SCRIPTS_24 82 - 0x5f, TechnicalSymbols, 0xff, EnclosedAndSquare, // row 0x24, index 68 -#define SCRIPTS_2e 86 - 0x7f, Unicode, 0xff, Han, // row 0x2e, index 72 -#define SCRIPTS_30 90 - 0x3f, Han, 0x9f, Hiragana, 0xff, Katakana, // row 0x30, index 76 -#define SCRIPTS_31 96 - 0x2f, Bopomofo, 0x8f, Hangul, 0x9f, Han, - 0xff, Unicode, // row 0x31, index 82 -#define SCRIPTS_fb 104 - 0x06, Latin, 0x1c, Unicode, 0x4f, Hebrew, - 0xff, Arabic, // row 0xfb, index 90 -#define SCRIPTS_fe 112 - 0x1f, Unicode, 0x2f, CombiningMarks, 0x6f, Han, - 0xff, Arabic, // row 0xfe, index 98 -#define SCRIPTS_ff 120 - 0x60, Han, // row 0xff, index 106 - 0x9f, KatakanaHalfWidth, 0xef, Han, 0xff, Unicode -}; - -// (uc-0x0900)>>7 -const unsigned char TQUnicodeTables::indicScripts [] = -{ - Devanagari, Bengali, - Gurmukhi, Gujarati, - Oriya, Tamil, - Telugu, Kannada, - Malayalam, Sinhala, - Thai, Lao -}; - - -// 0x80 + x: x is the offset into the otherScripts table -const unsigned char TQUnicodeTables::scriptTable[256] = -{ - Latin, Latin, 0x80+SCRIPTS_02, 0x80+SCRIPTS_03, - Cyrillic, 0x80+SCRIPTS_05, Arabic, 0x80+SCRIPTS_07, - Unicode, SCRIPTS_INDIC, SCRIPTS_INDIC, SCRIPTS_INDIC, - SCRIPTS_INDIC, SCRIPTS_INDIC, SCRIPTS_INDIC, Tibetan, - - 0x80+SCRIPTS_10, Hangul, Ethiopic, 0x80+SCRIPTS_13, - CanadianAboriginal, CanadianAboriginal, 0x80+SCRIPTS_16, 0x80+SCRIPTS_17, - 0x80+SCRIPTS_18, 0x80+SCRIPTS_19, Unicode, Unicode, - Unicode, Unicode, Latin, Greek, - - 0x80+SCRIPTS_20, 0x80+SCRIPTS_21, MathematicalOperators, TechnicalSymbols, - 0x80+SCRIPTS_24, GeometricSymbols, MiscellaneousSymbols, MiscellaneousSymbols, - Braille, Unicode, Unicode, Unicode, - Unicode, Unicode, 0x80+SCRIPTS_2e, Han, - - 0x80+SCRIPTS_30, 0x80+SCRIPTS_31, EnclosedAndSquare, EnclosedAndSquare, - Han, Han, Han, Han, - Han, Han, Han, Han, - Han, Han, Han, Han, - - Han, Han, Han, Han, Han, Han, Han, Han, - Han, Han, Han, Han, Han, Han, Han, Han, - - Han, Han, Han, Han, Han, Han, Han, Han, - Han, Han, Han, Han, Han, Han, Han, Han, - - Han, Han, Han, Han, Han, Han, Han, Han, - Han, Han, Han, Han, Han, Han, Han, Han, - - Han, Han, Han, Han, Han, Han, Han, Han, - Han, Han, Han, Han, Han, Han, Han, Han, - - - Han, Han, Han, Han, Han, Han, Han, Han, - Han, Han, Han, Han, Han, Han, Han, Han, - - Han, Han, Han, Han, Han, Han, Han, Han, - Han, Han, Han, Han, Han, Han, Han, Han, - - Yi, Yi, Yi, Yi, Yi, Unicode, Unicode, Unicode, - Unicode, Unicode, Unicode, Unicode, Hangul, Hangul, Hangul, Hangul, - - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - - Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, - Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, - - Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, - Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, - - Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, - Unicode, Han, Han, 0x80+SCRIPTS_fb, Arabic, Arabic, 0x80+SCRIPTS_fe, 0x80+SCRIPTS_ff -}; - diff --git a/src/tools/qunicodetables_p.h b/src/tools/qunicodetables_p.h deleted file mode 100644 index 18045f470..000000000 --- a/src/tools/qunicodetables_p.h +++ /dev/null @@ -1,266 +0,0 @@ -/**************************************************************************** -** -** ??? -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the widgets module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQUNICODETABLES_P_H -#define TQUNICODETABLES_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of internal files. This header file may change from version to version -// without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqstring.h" -#endif // QT_H - -#ifdef TQT_NO_UNICODETABLES -# include -#endif - -class TQUnicodeTables { -public: - static const TQ_UINT8 unicode_info[]; -#ifndef TQT_NO_UNICODETABLES - static const TQ_UINT16 decomposition_map[]; - static const TQ_UINT16 decomposition_info[]; - static const TQ_UINT16 ligature_map[]; - static const TQ_UINT16 ligature_info[]; - static const TQ_UINT8 direction_info[]; - static const TQ_UINT8 combining_info[]; - static const TQ_UINT16 case_info[]; - static const TQ_INT8 decimal_info[]; - static const TQ_UINT16 symmetricPairs[]; - static const int symmetricPairsSize; - static const TQ_UINT8 line_break_info[]; -#else - static const TQ_UINT8 latin1_line_break_info[]; -#endif - static const unsigned char otherScripts[]; - static const unsigned char indicScripts[]; - static const unsigned char scriptTable[]; - enum { SCRIPTS_INDIC = 0x7e }; - - // see http://www.unicode.org/reports/tr14/tr14-13.html - // we don't use the XX and AI properties and map them to AL instead. - enum LineBreakClass { - LineBreak_OP, LineBreak_CL, LineBreak_QU, LineBreak_GL, LineBreak_NS, - LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR, LineBreak_PO, - LineBreak_NU, LineBreak_AL, LineBreak_ID, LineBreak_IN, LineBreak_HY, - LineBreak_BA, LineBreak_BB, LineBreak_B2, LineBreak_ZW, LineBreak_CM, - LineBreak_SA, LineBreak_BK, LineBreak_CR, LineBreak_LF, LineBreak_SG, - LineBreak_CB, LineBreak_SP - }; -}; - - -inline TQChar::Category category( const TQChar &c ) -{ -#ifdef TQT_NO_UNICODETABLES - if ( c.unicode() > 0xff ) return TQChar::Letter_Uppercase; //######## - return (TQChar::Category)TQUnicodeTables::unicode_info[c.unicode()]; -#else - int uc = ((int)TQUnicodeTables::unicode_info[c.row()]) << 8; - uc += c.cell(); - return (TQChar::Category)TQUnicodeTables::unicode_info[uc]; -#endif // TQT_NO_UNICODETABLES -} - -inline TQChar lower( const TQChar &c ) -{ -#ifndef TQT_NO_UNICODETABLES - int row = c.row(); - int cell = c.cell(); - int ci = TQUnicodeTables::case_info[row]; - int uc = ((int)TQUnicodeTables::unicode_info[c.row()]) << 8; - uc += c.cell(); - if (TQUnicodeTables::unicode_info[uc] != TQChar::Letter_Uppercase || !ci) - return c; - TQ_UINT16 lower = TQUnicodeTables::case_info[(ci<<8)+cell]; - return lower ? TQChar(lower) : c; -#else - if ( c.row() ) - return c; - return TQChar( tolower((uchar) c.latin1()) ); -#endif -} - -inline TQChar upper( const TQChar &c ) -{ -#ifndef TQT_NO_UNICODETABLES - int row = c.row(); - int cell = c.cell(); - int ci = TQUnicodeTables::case_info[row]; - int uc = ((int)TQUnicodeTables::unicode_info[c.row()]) << 8; - uc += c.cell(); - if (TQUnicodeTables::unicode_info[uc] != TQChar::Letter_Lowercase || !ci) - return c; - TQ_UINT16 upper = TQUnicodeTables::case_info[(ci<<8)+cell]; - return upper ? TQChar(upper) : c; -#else - if ( c.row() ) - return c; - return TQChar( toupper((uchar) c.latin1()) ); -#endif -} - -inline TQChar::Direction direction( const TQChar &c ) -{ -#ifndef TQT_NO_UNICODETABLES - int pos = TQUnicodeTables::direction_info[c.row()]; - return (TQChar::Direction) (TQUnicodeTables::direction_info[(pos<<8)+c.cell()] & 0x1f); -#else - Q_UNUSED(c); - return TQChar::DirL; -#endif -} - -inline bool mirrored( const TQChar &c ) -{ -#ifndef TQT_NO_UNICODETABLES - int pos = TQUnicodeTables::direction_info[c.row()]; - return TQUnicodeTables::direction_info[(pos<<8)+c.cell()] > 128; -#else - Q_UNUSED(c); - return FALSE; -#endif -} - - -inline TQChar mirroredChar( const TQChar &ch ) -{ -#ifndef TQT_NO_UNICODETABLES - if(!::mirrored( ch )) - return ch; - - int i; - int c = ch.unicode(); - for (i = 0; i < TQUnicodeTables::symmetricPairsSize; i ++) { - if (TQUnicodeTables::symmetricPairs[i] == c) - return TQUnicodeTables::symmetricPairs[(i%2) ? (i-1) : (i+1)]; - } -#endif - return ch; -} - -inline TQChar::Joining joining( const TQChar &ch ) -{ -#ifndef TQT_NO_UNICODETABLES - int pos = TQUnicodeTables::direction_info[ch.row()]; - return (TQChar::Joining) ((TQUnicodeTables::direction_info[(pos<<8)+ch.cell()] >> 5) &0x3); -#else - Q_UNUSED(ch); - return TQChar::OtherJoining; -#endif -} - -inline bool isMark( const TQChar &ch ) -{ - TQChar::Category c = ::category( ch ); - return c >= TQChar::Mark_NonSpacing && c <= TQChar::Mark_Enclosing; -} - -inline unsigned char combiningClass( const TQChar &ch ) -{ -#ifndef TQT_NO_UNICODETABLES - const int pos = TQUnicodeTables::combining_info[ch.row()]; - return TQUnicodeTables::combining_info[(pos<<8) + ch.cell()]; -#else - Q_UNUSED(ch); - return 0; -#endif -} - -inline bool isSpace( const TQChar &ch ) -{ - if( ch.unicode() >= 9 && ch.unicode() <=13 ) return TRUE; - TQChar::Category c = ::category( ch ); - return c >= TQChar::Separator_Space && c <= TQChar::Separator_Paragraph; -} - -inline int lineBreakClass( const TQChar &ch ) -{ -#ifdef TQT_NO_UNICODETABLES - return ch.row() ? TQUnicodeTables::LineBreak_AL - : TQUnicodeTables::latin1_line_break_info[ch.cell()]; -#else - int pos = ((int)TQUnicodeTables::line_break_info[ch.row()] << 8) + ch.cell(); - return TQUnicodeTables::line_break_info[pos]; -#endif -} - -inline int scriptForChar( ushort uc ) -{ - unsigned char script = TQUnicodeTables::scriptTable[(uc>>8)]; - if ( script >= TQUnicodeTables::SCRIPTS_INDIC ) { - if ( script == TQUnicodeTables::SCRIPTS_INDIC ) { - script = TQUnicodeTables::indicScripts[ (uc-0x0900)>>7 ]; - } else { - // 0x80 + SCRIPTS_xx - unsigned char index = script-0x80; - unsigned char cell = uc &0xff; - while( TQUnicodeTables::otherScripts[index++] < cell ) - index++; - script = TQUnicodeTables::otherScripts[index]; - } - } - return script; -} - -#ifdef TQ_WS_X11 -#define SCRIPT_FOR_CHAR( script, c ) \ -do { \ - unsigned short _uc = (c).unicode(); \ - if ( _uc < 0x100 ) { \ - script = TQFont::Latin; \ - } else { \ - script = (TQFont::Script)scriptForChar( _uc ); \ - } \ -} while( FALSE ) -#else -#define SCRIPT_FOR_CHAR( script, c ) \ - script = (TQFont::Script)scriptForChar( (c).unicode() ) -#endif - -#endif diff --git a/src/tools/tqcom_p.h b/src/tools/tqcom_p.h new file mode 100644 index 000000000..9ff7ece64 --- /dev/null +++ b/src/tools/tqcom_p.h @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** ... +** +** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQCOM_P_H +#define TQCOM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of a number of TQt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqstringlist.h" +#include "tquuid.h" +#endif // QT_H + +#if __GNUC__ - 0 > 3 +#pragma GCC system_header +#endif + +#ifndef TQT_NO_COMPONENT + +class TQObject; +struct TQUInterfaceDescription; +struct TQUObject; + +#define TQRESULT unsigned long +#define TQS_OK (TQRESULT)0x00000000 +#define TQS_FALSE (TQRESULT)0x00000001 + +#define TQE_NOTIMPL (TQRESULT)0x80000001 +#define TQE_OUTOFMEMORY (TQRESULT)0x80000002 +#define TQE_INVALIDARG (TQRESULT)0x80000003 +#define TQE_NOINTERFACE (TQRESULT)0x80000004 +#define TQE_NOCOMPONENT (TQRESULT)0x80000005 + + +// {1D8518CD-E8F5-4366-99E8-879FD7E482DE} +#ifndef IID_QUnknown +#define IID_QUnknown TQUuid(0x1d8518cd, 0xe8f5, 0x4366, 0x99, 0xe8, 0x87, 0x9f, 0xd7, 0xe4, 0x82, 0xde) +#endif + +struct TQ_EXPORT TQUnknownInterface +{ + virtual TQRESULT queryInterface( const TQUuid&, TQUnknownInterface** ) = 0; + virtual ulong addRef() = 0; + virtual ulong release() = 0; +}; + +// {FBAC965E-A441-413F-935E-CDF582573FAB} +#ifndef IID_QDispatch +#define IID_QDispatch TQUuid( 0xfbac965e, 0xa441, 0x413f, 0x93, 0x5e, 0xcd, 0xf5, 0x82, 0x57, 0x3f, 0xab) +#endif + +// the dispatch interface that inherits the unknown interface.. It is +// used to explore interfaces during runtime and to do dynamic calls. +struct TQ_EXPORT TQDispatchInterface : public TQUnknownInterface +{ + // returns the interface description of this dispatch interface. + virtual const TQUInterfaceDescription* interfaceDescription() const = 0; + + // returns the event description of this dispatch interface. + virtual const TQUInterfaceDescription* eventsDescription() const = 0; + + // invokes method id with parameters V*. Returns some sort of + // exception code. + virtual TQRESULT invoke( int id, TQUObject* o ) = 0; + + // installs listener as event listener + virtual void installListener( TQDispatchInterface* listener ) = 0; + + // remove listener as event listener + virtual void removeListener( TQDispatchInterface* listener ) = 0; +}; + +template +class TQInterfacePtr +{ +public: + TQInterfacePtr():iface(0){} + + TQInterfacePtr( T* i) { + if ( (iface = i) ) + iface->addRef(); + } + + TQInterfacePtr(const TQInterfacePtr &p) { + if ( (iface = p.iface) ) + iface->addRef(); + } + + ~TQInterfacePtr() { + if ( iface ) + iface->release(); + } + + TQInterfacePtr &operator=(const TQInterfacePtr &p) { + if ( iface != p.iface ) { + if ( iface ) + iface->release(); + if ( (iface = p.iface) ) + iface->addRef(); + } + return *this; + } + + TQInterfacePtr &operator=(T* i) { + if (iface != i ) { + if ( iface ) + iface->release(); + if ( (iface = i) ) + iface->addRef(); + } + return *this; + } + + bool operator==( const TQInterfacePtr &p ) const { return iface == p.iface; } + + bool operator!= ( const TQInterfacePtr& p ) const { return !( *this == p ); } + + bool isNull() const { return !iface; } + + T* operator->() const { return iface; } + + T& operator*() const { return *iface; } + + operator T*() const { return iface; } + + TQUnknownInterface** operator &() const { + if( iface ) + iface->release(); + return (TQUnknownInterface**)&iface; + } + + T** operator &() { + if ( iface ) + iface->release(); + return &iface; + } + +private: + T* iface; +}; + +// {10A1501B-4C5F-4914-95DD-C400486CF900} +#ifndef IID_QObject +#define IID_QObject TQUuid( 0x10a1501b, 0x4c5f, 0x4914, 0x95, 0xdd, 0xc4, 0x00, 0x48, 0x6c, 0xf9, 0x00) +#endif + +struct TQ_EXPORT TQObjectInterface +{ + virtual TQObject* qObject() = 0; +}; + +// {5F3968A5-F451-45b1-96FB-061AD98F926E} +#ifndef IID_QComponentInformation +#define IID_QComponentInformation TQUuid(0x5f3968a5, 0xf451, 0x45b1, 0x96, 0xfb, 0x6, 0x1a, 0xd9, 0x8f, 0x92, 0x6e) +#endif + +struct TQ_EXPORT TQComponentInformationInterface : public TQUnknownInterface +{ + virtual TQString name() const = 0; + virtual TQString description() const = 0; + virtual TQString author() const = 0; + virtual TQString version() const = 0; +}; + +// {6CAA771B-17BB-4988-9E78-BA5CDDAAC31E} +#ifndef IID_QComponentFactory +#define IID_QComponentFactory TQUuid( 0x6caa771b, 0x17bb, 0x4988, 0x9e, 0x78, 0xba, 0x5c, 0xdd, 0xaa, 0xc3, 0x1e) +#endif + +struct TQ_EXPORT TQComponentFactoryInterface : public TQUnknownInterface +{ + virtual TQRESULT createInstance( const TQUuid &cid, const TQUuid &iid, TQUnknownInterface** instance, TQUnknownInterface *outer ) = 0; +}; + +// {D16111D4-E1E7-4C47-8599-24483DAE2E07} +#ifndef IID_QLibrary +#define IID_QLibrary TQUuid( 0xd16111d4, 0xe1e7, 0x4c47, 0x85, 0x99, 0x24, 0x48, 0x3d, 0xae, 0x2e, 0x07) +#endif + +struct TQ_EXPORT TQLibraryInterface : public TQUnknownInterface +{ + virtual bool init() = 0; + virtual void cleanup() = 0; + virtual bool canUnload() const = 0; +}; + +// {3F8FDC44-3015-4f3e-B6D6-E4AAAABDEAAD} +#ifndef IID_QFeatureList +#define IID_QFeatureList TQUuid(0x3f8fdc44, 0x3015, 0x4f3e, 0xb6, 0xd6, 0xe4, 0xaa, 0xaa, 0xbd, 0xea, 0xad) +#endif + +struct TQ_EXPORT TQFeatureListInterface : public TQUnknownInterface +{ + virtual TQStringList featureList() const = 0; +}; + +// {B5FEB5DE-E0CD-4E37-B0EB-8A812499A0C1} +#ifndef IID_QComponentRegistration +#define IID_QComponentRegistration TQUuid( 0xb5feb5de, 0xe0cd, 0x4e37, 0xb0, 0xeb, 0x8a, 0x81, 0x24, 0x99, 0xa0, 0xc1) +#endif + +struct TQ_EXPORT TQComponentRegistrationInterface : public TQUnknownInterface +{ + virtual bool registerComponents( const TQString &filepath ) const = 0; + virtual bool unregisterComponents() const = 0; +}; + +// internal class that wraps an initialized ulong +struct TQ_EXPORT TQtULong +{ + TQtULong() : ref( 0 ) { } + operator unsigned long () const { return ref; } + unsigned long& operator++() { return ++ref; } + unsigned long operator++( int ) { return ref++; } + unsigned long& operator--() { return --ref; } + unsigned long operator--( int ) { return ref--; } + + unsigned long ref; +}; +// default implementation of ref counting. A variable "ulong ref" has to be a member + + +#define TQ_REFCOUNT \ +private: \ + TQtULong qtrefcount; \ +public: \ + ulong addRef() {return qtrefcount++;} \ + ulong release() {if(!--qtrefcount){delete this;return 0;}return qtrefcount;} + +#ifndef Q_EXPORT_COMPONENT +#if defined(TQT_THREAD_SUPPORT) +#define QT_THREADED_BUILD 1 +#define Q_UCM_FLAGS_STRING "11" +#else +#define QT_THREADED_BUILD 0 +#define Q_UCM_FLAGS_STRING "01" +#endif + +#ifndef TQ_EXTERN_C +#ifdef __cplusplus +#define TQ_EXTERN_C extern "C" +#else +#define TQ_EXTERN_C extern +#endif +#endif + +// this is duplicated at Q_PLUGIN_VERIFICATION_DATA in tqgplugin.h +// NOTE: if you change pattern, you MUST change the pattern in +// tqcomlibrary.cpp as well. changing the pattern will break all +// backwards compatibility as well (no old plugins will be loaded). +#ifndef Q_UCM_VERIFICATION_DATA +# define Q_UCM_VERIFICATION_DATA \ + static const char *qt_ucm_verification_data = \ + "pattern=" "QT_UCM_VERIFICATION_DATA" "\n" \ + "version=" TQT_VERSION_STR "\n" \ + "flags=" Q_UCM_FLAGS_STRING "\n" \ + "buildkey=" TQT_BUILD_KEY "\0"; +#endif // Q_UCM_VERIFICATION_DATA + +// This macro expands to the default implementation of ucm_instantiate. +#ifndef Q_CREATE_INSTANCE +# define Q_CREATE_INSTANCE( IMPLEMENTATION ) \ + IMPLEMENTATION *i = new IMPLEMENTATION; \ + TQUnknownInterface* iface = 0; \ + i->queryInterface( IID_QUnknown, &iface ); \ + return iface; +#endif // Q_CREATE_INSTANCE + +# ifdef TQ_WS_WIN +# ifdef Q_CC_BOR +# define Q_EXPORT_COMPONENT() \ + Q_UCM_VERIFICATION_DATA \ + TQ_EXTERN_C __declspec(dllexport) \ + const char * __stdcall qt_ucm_query_verification_data() \ + { return qt_ucm_verification_data; } \ + TQ_EXTERN_C TQ_EXPORT __declspec(dllexport) TQUnknownInterface* \ + __stdcall ucm_instantiate() +# else +# define Q_EXPORT_COMPONENT() \ + Q_UCM_VERIFICATION_DATA \ + TQ_EXTERN_C __declspec(dllexport) \ + const char *qt_ucm_query_verification_data() \ + { return qt_ucm_verification_data; } \ + TQ_EXTERN_C TQ_EXPORT __declspec(dllexport) TQUnknownInterface* ucm_instantiate() +# endif +# else +# define Q_EXPORT_COMPONENT() \ + Q_UCM_VERIFICATION_DATA \ + TQ_EXTERN_C \ + const char *qt_ucm_query_verification_data() \ + { return qt_ucm_verification_data; } \ + TQ_EXTERN_C TQ_EXPORT TQUnknownInterface* ucm_instantiate() +# endif +# define Q_EXPORT_INTERFACE() Q_EXPORT_COMPONENT() +#endif + +#endif //TQT_NO_COMPONENT + +#endif //TQCOM_P_H diff --git a/src/tools/tqcomlibrary.cpp b/src/tools/tqcomlibrary.cpp new file mode 100644 index 000000000..5c2510130 --- /dev/null +++ b/src/tools/tqcomlibrary.cpp @@ -0,0 +1,538 @@ +/**************************************************************************** +** +** Implementation of TQComLibrary class +** +** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqcomlibrary_p.h" + +#ifndef TQT_NO_COMPONENT +#include +#include +#include +#include +#include +#ifndef NO_ERRNO_H +#include +#endif // NO_ERROR_H + +#ifdef TQT_THREAD_SUPPORT +# include "tqmutexpool_p.h" +#endif // TQT_THREAD_SUPPORT + +#ifndef QT_DEBUG_COMPONENT +# if defined(QT_DEBUG) +# define QT_DEBUG_COMPONENT 1 +# endif +#endif + + +TQComLibrary::TQComLibrary( const TQString &filename ) + : TQLibrary( filename ), entry( 0 ), libiface( 0 ), qt_version( 0 ) +{ +} + +TQComLibrary::~TQComLibrary() +{ + if ( autoUnload() ) + unload(); + if ( libiface ) + libiface->release(); + if ( entry ) + entry->release(); +} + +bool TQComLibrary::unload() +{ + int refs = entry ? entry->release() : 0; + entry = 0; + if (refs || !libiface) + return FALSE; + + libiface->cleanup(); + if ( !libiface->canUnload() ) + return FALSE; + libiface->release(); + libiface = 0; + + return TQLibrary::unload(); +} + +static bool qt_verify( const TQString& library, uint version, uint flags, + const TQCString &key, bool warn ) +{ + uint our_flags = 1; +#if defined(TQT_THREAD_SUPPORT) + our_flags |= 2; +#endif + + if ( (flags & 1) == 0 ) { + if ( warn ) + tqWarning( "Conflict in %s:\n" + " Plugin cannot be queried successfully!", + (const char*) TQFile::encodeName(library) ); + } else if ( ( version > TQT_VERSION ) || + ( ( TQT_VERSION & 0xff0000 ) > ( version & 0xff0000 ) ) ) { + if ( warn ) + tqWarning( "Conflict in %s:\n" + " Plugin uses incompatible TQt library (%d.%d.%d)!", + (const char*) TQFile::encodeName(library), + (version&0xff0000) >> 16, (version&0xff00) >> 8, version&0xff ); + } else if ( (flags & 2) != (our_flags & 2) ) { + if ( warn ) + tqWarning( "Conflict in %s:\n" + " Plugin uses %s TQt library!", + (const char*) TQFile::encodeName(library), + (flags & 2) ? "multi threaded" : "single threaded" ); + } else if ( key != TQT_BUILD_KEY ) { + if ( warn ) + tqWarning( "Conflict in %s:\n" + " Plugin uses incompatible TQt library!\n" + " expected build key \"%s\", got \"%s\".", + (const char*) TQFile::encodeName(library), + TQT_BUILD_KEY, + key.isEmpty() ? "" : (const char *) key ); + } else { + return TRUE; + } + return FALSE; +} + +struct qt_token_info +{ + qt_token_info( const char *f, const ulong fc ) + : fields( f ), field_count( fc ), results( fc ), lengths( fc ) + { + results.fill( 0 ); + lengths.fill( 0 ); + } + + const char *fields; + const ulong field_count; + + TQMemArray results; + TQMemArray lengths; +}; + +/* + return values: + 1 parse ok + 0 eos + -1 parse error +*/ +static int qt_tokenize( const char *s, ulong s_len, ulong *advance, + const qt_token_info &token_info ) +{ + ulong pos = 0, field = 0, fieldlen = 0; + char current; + int ret = -1; + *advance = 0; + for (;;) { + current = s[ pos ]; + + // next char + ++pos; + ++fieldlen; + ++*advance; + + if ( ! current || pos == s_len + 1 ) { + // save result + token_info.results[ (int)field ] = s; + token_info.lengths[ (int)field ] = fieldlen - 1; + + // end of string + ret = 0; + break; + } + + if ( current == token_info.fields[ field ] ) { + // save result + token_info.results[ (int)field ] = s; + token_info.lengths[ (int)field ] = fieldlen - 1; + + // end of field + fieldlen = 0; + ++field; + if ( field == token_info.field_count - 1 ) { + // parse ok + ret = 1; + } + if ( field == token_info.field_count ) { + // done parsing + break; + } + + // reset string and its length + s = s + pos; + s_len -= pos; + pos = 0; + } + } + + return ret; +} + +/* + returns TRUE if the string s was correctly parsed, FALSE otherwise. +*/ +static bool qt_parse_pattern( const char *s, uint *version, uint *flags, + TQCString *key ) +{ + bool ret = TRUE; + + qt_token_info pinfo("=\n", 2); + int parse; + ulong at = 0, advance, parselen = tqstrlen( s ); + do { + parse = qt_tokenize( s + at, parselen, &advance, pinfo ); + if ( parse == -1 ) { + ret = FALSE; + break; + } + + at += advance; + parselen -= advance; + + if ( tqstrncmp( "version", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { + // parse version string + qt_token_info pinfo2("..-", 3); + if ( qt_tokenize( pinfo.results[ 1 ], pinfo.lengths[ 1 ], + &advance, pinfo2 ) != -1 ) { + TQCString m( pinfo2.results[ 0 ], pinfo2.lengths[ 0 ] + 1 ); + TQCString n( pinfo2.results[ 1 ], pinfo2.lengths[ 1 ] + 1 ); + TQCString p( pinfo2.results[ 2 ], pinfo2.lengths[ 2 ] + 1 ); + *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt(); + } else { + ret = FALSE; + break; + } + } else if ( tqstrncmp( "flags", pinfo.results[ 0 ], pinfo.lengths[ 0 ] ) == 0 ) { + // parse flags string + char ch; + *flags = 0; + ulong p = 0, c = 0, bit = 0; + while ( p < pinfo.lengths[ 1 ] ) { + ch = pinfo.results[ 1 ][ p ]; + bit = pinfo.lengths[ 1 ] - p - 1; + c = 1 << bit; + if ( ch == '1' ) { + *flags |= c; + } else if ( ch != '0' ) { + ret = FALSE; + break; + } + ++p; + } + } else if ( tqstrncmp( "buildkey", pinfo.results[ 0 ], + pinfo.lengths[ 0 ] ) == 0 ){ + // save buildkey + *key = TQCString( pinfo.results[ 1 ], pinfo.lengths[ 1 ] + 1 ); + } + } while ( parse == 1 && parselen > 0 ); + + return ret; +} + +#if defined(Q_OS_UNIX) + +#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) +# define USE_MMAP +# include +# include +#endif // Q_OS_FREEBSD || Q_OS_LINUX + +static long qt_find_pattern( const char *s, ulong s_len, + const char *pattern, ulong p_len ) +{ + /* + this uses the same algorithm as TQString::findRev... + + we search from the end of the file because on the supported + systems, the read-only data/text segments are placed at the end + of the file. HOWEVER, when building with debugging enabled, all + the debug symbols are placed AFTER the data/text segments. + + what does this mean? when building in release mode, the search + is fast because the data we are looking for is at the end of the + file... when building in debug mode, the search is slower + because we have to skip over all the debugging symbols first + */ + + if ( ! s || ! pattern || p_len > s_len ) return -1; + ulong i, hs = 0, hp = 0, delta = s_len - p_len; + + for (i = 0; i < p_len; ++i ) { + hs += s[delta + i]; + hp += pattern[i]; + } + i = delta; + for (;;) { + if ( hs == hp && tqstrncmp( s + i, pattern, p_len ) == 0 ) + return i; + if ( i == 0 ) + break; + --i; + hs -= s[i + p_len]; + hs += s[i]; + } + + return -1; +} + +/* + This opens the specified library, mmaps it into memory, and searches + for the QT_UCM_VERIFICATION_DATA. The advantage of this approach is that + we can get the verification data without have to actually load the library. + This lets us detect mismatches more safely. + + Returns FALSE if version/flags/key information is not present, or if the + information could not be read. + Returns TRUE if version/flags/key information is present and succesfully read. +*/ +static bool qt_unix_query( const TQString &library, uint *version, uint *flags, + TQCString *key ) +{ + TQFile file( library ); + if (! file.open( IO_ReadOnly ) ) { + tqWarning( "%s: %s", (const char*) TQFile::encodeName(library), + strerror( errno ) ); + return FALSE; + } + + TQByteArray data; + char *filedata = 0; + ulong fdlen = 0; + +#ifdef USE_MMAP + char *mapaddr = 0; + size_t maplen = file.size(); + mapaddr = (char *) mmap( mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0 ); + if ( mapaddr != MAP_FAILED ) { + // mmap succeeded + filedata = mapaddr; + fdlen = maplen; + } else { + // mmap failed + tqWarning( "mmap: %s", strerror( errno ) ); +#endif // USE_MMAP + // try reading the data into memory instead + data = file.readAll(); + filedata = data.data(); + fdlen = data.size(); +#ifdef USE_MMAP + } +#endif // USE_MMAP + + // verify that the pattern is present in the plugin + const char *pattern = "pattern=QT_UCM_VERIFICATION_DATA"; + const ulong plen = tqstrlen( pattern ); + long pos = qt_find_pattern( filedata, fdlen, pattern, plen ); + + bool ret = FALSE; + if ( pos >= 0 ) { + ret = qt_parse_pattern( filedata + pos, version, flags, key ); + } + +#ifdef USE_MMAP + if ( mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0 ) { + tqWarning( "munmap: %s", strerror( errno ) ); + } +#endif // USE_MMAP + + file.close(); + return ret; +} + +#endif // Q_OS_UNIX + + +static TQSettings *cache = 0; +static TQSingleCleanupHandler cleanup_cache; + +void TQComLibrary::createInstanceInternal() +{ + if ( library().isEmpty() ) + return; + + TQFileInfo fileinfo( library() ); + TQString lastModified = fileinfo.lastModified().toString(TQt::ISODate); + TQString regkey = TQString("/TQt Plugins %1.%2/%3") + .arg( ( TQT_VERSION & 0xff0000 ) >> 16 ) + .arg( ( TQT_VERSION & 0xff00 ) >> 8 ) + .arg( library() ); + TQStringList reg; + uint flags = 0; + TQCString key; + bool query_done = FALSE; + bool warn_mismatch = TRUE; + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &cache ) : 0 ); +#endif // TQT_THREAD_SUPPORT + + if ( ! cache ) { + cache = new TQSettings; + cache->insertSearchPath( TQSettings::Windows, "/Trolltech" ); + cleanup_cache.set( &cache ); + } + + reg = cache->readListEntry( regkey ); + if ( reg.count() == 4 ) { + // check timestamp + if ( lastModified == reg[3] ) { + qt_version = reg[0].toUInt(0, 16); + flags = reg[1].toUInt(0, 16); + key = reg[2].latin1(); + + query_done = TRUE; + warn_mismatch = FALSE; + } + } + +#if defined(Q_OS_UNIX) + if ( ! query_done ) { + // get the query information directly from the plugin without loading + if ( qt_unix_query( library(), &qt_version, &flags, &key ) ) { + // info read succesfully from library + query_done = TRUE; + } + } +#else // !Q_OS_UNIX + if ( ! query_done ) { + // get the query information by loading the plugin + if ( !isLoaded() ) { + Q_ASSERT( entry == 0 ); + if ( !load() ) + return; + } + +# ifdef Q_CC_BOR + typedef const char * __stdcall (*UCMQueryVerificationDataProc)(); +# else + typedef const char * (*UCMQueryVerificationDataProc)(); +# endif + UCMQueryVerificationDataProc ucmQueryVerificationdataProc; + ucmQueryVerificationdataProc = + (UCMQueryVerificationDataProc) resolve( "qt_ucm_query_verification_data" ); + + if ( !ucmQueryVerificationdataProc || + !qt_parse_pattern( ucmQueryVerificationdataProc(), + &qt_version, &flags, &key ) ) { + qt_version = flags = 0; + key = "unknown"; + } else { + query_done = TRUE; + } + } +#endif // Q_OS_UNIX + + TQStringList queried; + queried << TQString::number( qt_version,16 ) + << TQString::number( flags, 16 ) + << key + << lastModified; + + if ( queried != reg ) { + cache->writeEntry( regkey, queried ); + // delete the cache, which forces the settings to be written + delete cache; + cache = 0; + } + + if ( ! query_done ) { + if ( warn_mismatch ) { + tqWarning( "Conflict in %s:\n Plugin cannot be queried successfully!", + (const char*) TQFile::encodeName( library() ) ); + } + unload(); + return; + } + + if ( ! qt_verify( library(), qt_version, flags, key, warn_mismatch ) ) { + unload(); + return; + } else if ( !isLoaded() ) { + Q_ASSERT( entry == 0 ); + if ( !load() ) + return; + } + +#ifdef Q_CC_BOR + typedef TQUnknownInterface* __stdcall (*UCMInstanceProc)(); +#else + typedef TQUnknownInterface* (*UCMInstanceProc)(); +#endif + UCMInstanceProc ucmInstanceProc; + ucmInstanceProc = (UCMInstanceProc) resolve( "ucm_instantiate" ); +#if defined(QT_DEBUG_COMPONENT) + if ( !ucmInstanceProc ) + tqWarning( "%s: Not a UCOM library.", (const char*) TQFile::encodeName(library()) ); +#endif + entry = ucmInstanceProc ? ucmInstanceProc() : 0; + + if ( entry ) { + if ( entry->queryInterface( IID_QLibrary, (TQUnknownInterface**)&libiface ) == TQS_OK ) { + if ( libiface && !libiface->init() ) { + libiface->release(); + libiface = 0; + unload(); + return; + } + } + } else { +#if defined(QT_DEBUG_COMPONENT) + tqWarning( "%s: No exported component provided.", (const char*) TQFile::encodeName(library()) ); +#endif + unload(); + } +} + +TQRESULT TQComLibrary::queryInterface( const TQUuid& request, TQUnknownInterface** iface ) +{ + if ( !entry ) + createInstanceInternal(); + return entry ? entry->queryInterface( request, iface ) : TQE_NOCOMPONENT; +} + +uint TQComLibrary::qtVersion() +{ + if ( !entry ) + createInstanceInternal(); + return entry ? qt_version : 0; +} + + +#endif // TQT_NO_COMPONENT diff --git a/src/tools/tqcomlibrary_p.h b/src/tools/tqcomlibrary_p.h new file mode 100644 index 000000000..e803a236c --- /dev/null +++ b/src/tools/tqcomlibrary_p.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Definition of TQComLibrary class +** +** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQCOMLIBRARY_P_H +#define TQCOMLIBRARY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of a number of TQt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqcom_p.h" +#include "tqlibrary.h" +#endif // QT_H + +#ifndef TQT_NO_COMPONENT + +class TQ_EXPORT TQComLibrary : public TQLibrary +{ +public: + TQComLibrary( const TQString &filename ); + ~TQComLibrary(); + + bool unload(); + TQRESULT queryInterface( const TQUuid &iid, TQUnknownInterface **iface ); + uint qtVersion(); + +private: + void createInstanceInternal(); + + TQUnknownInterface *entry; + TQLibraryInterface *libiface; + uint qt_version; + +}; + +#endif //TQT_NO_COMPONENT + +#endif diff --git a/src/tools/tqcomponentfactory.cpp b/src/tools/tqcomponentfactory.cpp index 6bac4b618..3b05e94de 100644 --- a/src/tools/tqcomponentfactory.cpp +++ b/src/tools/tqcomponentfactory.cpp @@ -42,7 +42,7 @@ #ifndef TQT_NO_COMPONENT #include "tqsettings.h" -#include +#include #include "tqdir.h" #include "ntqapplication.h" diff --git a/src/tools/tqcomponentfactory_p.h b/src/tools/tqcomponentfactory_p.h index 89399152f..ea45d7455 100644 --- a/src/tools/tqcomponentfactory_p.h +++ b/src/tools/tqcomponentfactory_p.h @@ -42,7 +42,7 @@ #define TQCOMPONENTFACTORY_P_H #ifndef QT_H -#include "qcom_p.h" +#include "tqcom_p.h" #endif // QT_H // diff --git a/src/tools/tqcriticalsection_p.cpp b/src/tools/tqcriticalsection_p.cpp new file mode 100644 index 000000000..a6203b0c8 --- /dev/null +++ b/src/tools/tqcriticalsection_p.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Implementation of TQCriticalSection class +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#if defined(TQT_THREAD_SUPPORT) + +#include "qt_windows.h" + +#include + +class TQCriticalSectionPrivate +{ +public: + TQCriticalSectionPrivate() {} + + CRITICAL_SECTION section; +}; + + +TQCriticalSection::TQCriticalSection() +{ + d = new TQCriticalSectionPrivate; + InitializeCriticalSection( &d->section ); +} + +TQCriticalSection::~TQCriticalSection() +{ + DeleteCriticalSection( &d->section ); + delete d; +} + +void TQCriticalSection::enter() +{ + EnterCriticalSection( &d->section ); +} + +void TQCriticalSection::leave() +{ + LeaveCriticalSection( &d->section ); +} + +#endif diff --git a/src/tools/tqcriticalsection_p.h b/src/tools/tqcriticalsection_p.h new file mode 100644 index 000000000..330e141e1 --- /dev/null +++ b/src/tools/tqcriticalsection_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Definition of TQCriticalSection class +** +** Copyright (C) 2001-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQCRITICALSECTION_P_H +#define TQCRITICALSECTION_P_H + +#ifndef QT_H +#endif // QT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of TQt Remote Control. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +// + +#if defined(TQT_THREAD_SUPPORT) + +#if defined(TQ_WS_WIN) + +/* + TQCriticalSection +*/ + +class TQCriticalSectionPrivate; + +class TQCriticalSection +{ +public: + TQCriticalSection(); + ~TQCriticalSection(); + void enter(); + void leave(); + +private: + TQCriticalSectionPrivate *d; +}; + +#endif + +#endif + +#endif diff --git a/src/tools/tqgpluginmanager.cpp b/src/tools/tqgpluginmanager.cpp index d53e4f5f5..94b5a6435 100644 --- a/src/tools/tqgpluginmanager.cpp +++ b/src/tools/tqgpluginmanager.cpp @@ -38,7 +38,7 @@ #include "tqgpluginmanager_p.h" #ifndef TQT_NO_COMPONENT -#include "qcomlibrary_p.h" +#include "tqcomlibrary_p.h" #include "tqmap.h" #include "tqdir.h" @@ -205,7 +205,7 @@ static int similarity( const TQString& s1, const TQString& s2 ) } /*! - \class TQPluginManager qpluginmanager.h + \class TQPluginManager tqpluginmanager.h \reentrant \brief The TQPluginManager class provides basic functions to access a certain kind of functionality in libraries. \ingroup componentmodel diff --git a/src/tools/tqgpluginmanager_p.h b/src/tools/tqgpluginmanager_p.h index 946fe3bc4..123936627 100644 --- a/src/tools/tqgpluginmanager_p.h +++ b/src/tools/tqgpluginmanager_p.h @@ -44,7 +44,7 @@ #include "tqlibrary.h" #include "tquuid.h" #include "tqstringlist.h" -#include "qcom_p.h" +#include "tqcom_p.h" #endif // QT_H // diff --git a/src/tools/tqpluginmanager_p.h b/src/tools/tqpluginmanager_p.h new file mode 100644 index 000000000..4e42eed0f --- /dev/null +++ b/src/tools/tqpluginmanager_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Definition of TQPluginManager class +** +** Created : 000101 +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQPLUGINMANAGER_P_H +#define TQPLUGINMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of a number of TQt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqgpluginmanager_p.h" +#endif // QT_H + +#ifndef TQT_NO_COMPONENT + +template +class TQPluginManager : public TQGPluginManager +{ +public: + TQPluginManager( const TQUuid& id, const TQStringList& paths = TQString::null, const TQString &suffix = TQString::null, bool cs = TRUE ) + : TQGPluginManager( id, paths, suffix, cs ) {} + TQRESULT queryInterface(const TQString& feature, Type** iface) const + { + return queryUnknownInterface( feature, (TQUnknownInterface**)iface ); + } +}; + +#endif //TQT_NO_COMPONENT + +#endif //TQPLUGINMANAGER_P_H diff --git a/src/tools/tqstring.cpp b/src/tools/tqstring.cpp index 5247289df..318f1aa77 100644 --- a/src/tools/tqstring.cpp +++ b/src/tools/tqstring.cpp @@ -59,7 +59,7 @@ #include "tqlocale.h" #include "tqlocale_p.h" -#include "qunicodetables_p.h" +#include "tqunicodetables_p.h" #include #include #include diff --git a/src/tools/tqucom.cpp b/src/tools/tqucom.cpp new file mode 100644 index 000000000..3ab50a7a9 --- /dev/null +++ b/src/tools/tqucom.cpp @@ -0,0 +1,573 @@ +/**************************************************************************** +** +** Implementation of the TQUcom classes +** +** Created : 990101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "private/tqucom_p.h" +#include "private/tqucomextra_p.h" + +#include "tqvariant.h" + +#include + +// Standard types + +// {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} +const TQUuid TID_QUType_Null( 0xde56510e, 0x4e9f, 0x4b76, 0xa3, 0xc2, 0xd1, 0xe2, 0xef, 0x42, 0xf1, 0xac ); +const TQUuid *TQUType_Null::uuid() const { return &TID_QUType_Null; } +const char *TQUType_Null::desc() const { return "null"; } +bool TQUType_Null::canConvertFrom( TQUObject *, TQUType * ) { return FALSE; } +bool TQUType_Null::canConvertTo( TQUObject *, TQUType * ) { return FALSE; } +bool TQUType_Null::convertFrom( TQUObject *, TQUType * ) { return FALSE; } +bool TQUType_Null::convertTo( TQUObject *, TQUType * ) { return FALSE; } +void TQUType_Null::clear( TQUObject *) {} +int TQUType_Null::serializeTo( TQUObject *, TQUBuffer * ) { return 0; } +int TQUType_Null::serializeFrom( TQUObject *, TQUBuffer * ) { return 0; } +TQUType_Null static_QUType_Null; + + +// {7EE17B08-5419-47e2-9776-8EEA112DCAEC} +const TQUuid TID_QUType_enum( 0x7ee17b08, 0x5419, 0x47e2, 0x97, 0x76, 0x8e, 0xea, 0x11, 0x2d, 0xca, 0xec ); +TQUType_enum static_QUType_enum; +const TQUuid *TQUType_enum::uuid() const { return &TID_QUType_enum; } +const char *TQUType_enum::desc() const { return "enum"; } +void TQUType_enum::set( TQUObject *o, int v ) +{ + o->payload.i = v; + o->type = this; +} + +bool TQUType_enum::canConvertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool TQUType_enum::canConvertTo( TQUObject * /*o*/, TQUType *t ) +{ + return isEqual( t, &static_QUType_int ); +} + +bool TQUType_enum::convertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) // ## todo unsigned int? + ; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool TQUType_enum::convertTo( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) { + o->type = &static_QUType_int; + return TRUE; + } + return FALSE; +} + +int TQUType_enum::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_enum::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {8AC26448-5AB4-49eb-968C-8F30AB13D732} +const TQUuid TID_QUType_ptr( 0x8ac26448, 0x5ab4, 0x49eb, 0x96, 0x8c, 0x8f, 0x30, 0xab, 0x13, 0xd7, 0x32 ); +TQUType_ptr static_QUType_ptr; +const TQUuid *TQUType_ptr::uuid() const { return &TID_QUType_ptr; } +const char *TQUType_ptr::desc() const { return "ptr"; } + +void TQUType_ptr::set( TQUObject *o, const void* v ) +{ + o->payload.ptr = (void*) v; + o->type = this; +} + +bool TQUType_ptr::canConvertFrom( TQUObject *o, TQUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool TQUType_ptr::canConvertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +bool TQUType_ptr::convertFrom( TQUObject *o, TQUType *t ) +{ + return t->convertTo( o, this ); +} + +bool TQUType_ptr::convertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +int TQUType_ptr::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_ptr::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {97A2594D-6496-4402-A11E-55AEF2D4D25C} +const TQUuid TID_QUType_iface( 0x97a2594d, 0x6496, 0x4402, 0xa1, 0x1e, 0x55, 0xae, 0xf2, 0xd4, 0xd2, 0x5c ); +TQUType_iface static_QUType_iface; +const TQUuid *TQUType_iface::uuid() const { return &TID_QUType_iface; } +const char *TQUType_iface::desc() const { return "UnknownInterface"; } + +void TQUType_iface::set( TQUObject *o, TQUnknownInterface* iface ) +{ + o->payload.iface = iface; + o->type = this; +} + +bool TQUType_iface::canConvertFrom( TQUObject *o, TQUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool TQUType_iface::canConvertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +bool TQUType_iface::convertFrom( TQUObject *o, TQUType *t ) +{ + return t->convertTo( o, this ); +} + +bool TQUType_iface::convertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +int TQUType_iface::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_iface::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} +const TQUuid TID_QUType_idisp( 0x2f358164, 0xe28f, 0x4bf4, 0x9f, 0xa9, 0x4e, 0xc, 0xdc, 0xab, 0xa5, 0xb ); +TQUType_idisp static_QUType_idisp; +const TQUuid *TQUType_idisp::uuid() const { return &TID_QUType_idisp; } +const char *TQUType_idisp::desc() const { return "DispatchInterface"; } + +void TQUType_idisp::set( TQUObject *o, TQDispatchInterface* idisp ) +{ + o->payload.idisp = idisp; + o->type = this; +} + +bool TQUType_idisp::canConvertFrom( TQUObject *o, TQUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool TQUType_idisp::canConvertTo( TQUObject * /*o*/, TQUType *t ) +{ + return isEqual( t, &static_QUType_iface ); +} + +bool TQUType_idisp::convertFrom( TQUObject *o, TQUType *t ) +{ + return t->convertTo( o, this ); +} + +bool TQUType_idisp::convertTo( TQUObject *o, TQUType *t ) +{ +#ifndef TQT_NO_COMPONENT + if ( isEqual( t, &static_QUType_iface ) ) { + o->payload.iface = (TQUnknownInterface*)o->payload.idisp; + o->type = &static_QUType_iface; + return TRUE; + } +#endif + return FALSE; +} + +int TQUType_idisp::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_idisp::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {CA42115D-13D0-456c-82B5-FC10187F313E} +const TQUuid TID_QUType_bool( 0xca42115d, 0x13d0, 0x456c, 0x82, 0xb5, 0xfc, 0x10, 0x18, 0x7f, 0x31, 0x3e ); +TQUType_bool static_QUType_bool; +const TQUuid *TQUType_bool::uuid() const { return &TID_QUType_bool; } +const char *TQUType_bool::desc() const { return "bool"; } + +void TQUType_bool::set( TQUObject *o, bool v ) +{ + o->payload.b = v; + o->type = this; +} + +bool TQUType_bool::canConvertFrom( TQUObject *o, TQUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool TQUType_bool::canConvertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +bool TQUType_bool::convertFrom( TQUObject *o, TQUType *t ) +{ + return t->convertTo( o, this ); +} + +bool TQUType_bool::convertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +int TQUType_bool::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_bool::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} +const TQUuid TID_QUType_int( 0x53c1f3be, 0x73c3, 0x4c7d, 0x9e, 0x5, 0xcc, 0xf0, 0x9e, 0xb6, 0x76, 0xb5 ); +TQUType_int static_QUType_int; +const TQUuid *TQUType_int::uuid() const { return &TID_QUType_int; } +const char *TQUType_int::desc() const { return "int"; } + +void TQUType_int::set( TQUObject *o, int v ) +{ + o->payload.i = v; + o->type = this; +} + +bool TQUType_int::canConvertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_double ) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool TQUType_int::canConvertTo( TQUObject * /*o*/, TQUType *t ) +{ + return isEqual( t, &static_QUType_double ); +} + +bool TQUType_int::convertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_double ) ) + o->payload.i = (long)o->payload.d; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool TQUType_int::convertTo( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = (double)o->payload.i; + o->type = &static_QUType_double; + } else + return FALSE; + return TRUE; +} + +int TQUType_int::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_int::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {2D0974E5-0BA6-4ec2-8837-C198972CB48C} +const TQUuid TID_QUType_double( 0x2d0974e5, 0xba6, 0x4ec2, 0x88, 0x37, 0xc1, 0x98, 0x97, 0x2c, 0xb4, 0x8c ); +TQUType_double static_QUType_double; +const TQUuid *TQUType_double::uuid() const { return &TID_QUType_double; } +const char *TQUType_double::desc() const {return "double"; } + +void TQUType_double::set( TQUObject *o, double v ) +{ + o->payload.d = v; + o->type = this; +} + +bool TQUType_double::canConvertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool TQUType_double::canConvertTo( TQUObject * /*o*/, TQUType *t ) +{ + return isEqual( t, &static_QUType_int ); +} + +bool TQUType_double::convertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) + o->payload.d = (double)o->payload.i; + else + return t->convertTo( o, this ); + + o->type = this; + return TRUE; +} + +bool TQUType_double::convertTo( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_int ) ) { + o->payload.i = (int) o->payload.d; + o->type = &static_QUType_int; + } else if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = (double) o->payload.f; + o->type = &static_QUType_double; + } else + return FALSE; + return TRUE; +} + +int TQUType_double::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_double::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +// {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} +const TQUuid TID_QUType_charstar( 0xefcdd1d4, 0x77a3, 0x4b8e, 0x8d, 0x46, 0xdc, 0x14, 0xb8, 0xd3, 0x93, 0xe9 ); +TQUType_charstar static_QUType_charstar; +const TQUuid *TQUType_charstar::uuid() const { return &TID_QUType_charstar; } +const char *TQUType_charstar::desc() const { return "char*"; } + +void TQUType_charstar::set( TQUObject *o, const char* v, bool take ) +{ + if ( take ) { + if ( v ) { + o->payload.charstar.ptr = new char[ strlen(v) + 1 ]; + strcpy( o->payload.charstar.ptr, v ); + } else { + o->payload.charstar.ptr = 0; + } + o->payload.charstar.owner = TRUE; + } else { + o->payload.charstar.ptr = (char*) v; + o->payload.charstar.owner = FALSE; + } + o->type = this; +} + +bool TQUType_charstar::canConvertFrom( TQUObject *o, TQUType *t ) +{ + return t->canConvertTo( o, this ); +} + +bool TQUType_charstar::canConvertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +bool TQUType_charstar::convertFrom( TQUObject *o, TQUType *t ) +{ + return t->convertTo( o, this ); +} + +bool TQUType_charstar::convertTo( TQUObject *, TQUType * ) +{ + return FALSE; +} + +void TQUType_charstar::clear( TQUObject *o ) +{ + if ( o->payload.charstar.owner ) + delete [] o->payload.charstar.ptr; + o->payload.charstar.ptr = 0; +} + +int TQUType_charstar::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_charstar::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + + +// TQt specific types + +// {44C2A547-01E7-4e56-8559-35AF9D2F42B7} +const TQUuid TID_QUType_TQString( 0x44c2a547, 0x1e7, 0x4e56, 0x85, 0x59, 0x35, 0xaf, 0x9d, 0x2f, 0x42, 0xb7 ); +TQUType_TQString static_QUType_TQString; +const TQUuid *TQUType_TQString::uuid() const { return &TID_QUType_TQString; } +const char *TQUType_TQString::desc() const { return "TQString"; } + +void TQUType_TQString::set( TQUObject *o, const TQString& v ) +{ + o->payload.ptr = new TQString( v ); + o->type = this; +} + +bool TQUType_TQString::canConvertFrom( TQUObject *o, TQUType *t ) +{ + if ( isEqual( t, &static_QUType_charstar ) || + isEqual( t, &static_QUType_double ) || + isEqual( t, &static_QUType_int ) ) + return TRUE; + + return t->canConvertTo( o, this ); +} + +bool TQUType_TQString::canConvertTo( TQUObject * /*o*/, TQUType *t ) +{ + return isEqual( t, &static_QUType_charstar ) || + isEqual( t, &static_QUType_int ) || + isEqual( t, &static_QUType_double ); +} + +bool TQUType_TQString::convertFrom( TQUObject *o, TQUType *t ) +{ + TQString *str = 0; + if ( isEqual( t, &static_QUType_charstar ) ) + str = new TQString( o->payload.charstar.ptr ); + else if ( isEqual( t, &static_QUType_double ) ) + str = new TQString( TQString::number( o->payload.d ) ); + else if ( isEqual( t, &static_QUType_int ) ) + str = new TQString( TQString::number( o->payload.i ) ); + else + return t->convertTo( o, this ); + + o->type->clear( o ); + o->payload.ptr = str; + o->type = this; + return TRUE; +} + +bool TQUType_TQString::convertTo( TQUObject *o, TQUType *t ) +{ + TQString *str = (TQString *)o->payload.ptr; + if ( isEqual( t, &static_QUType_charstar ) ) { + o->payload.charstar.ptr = tqstrdup( str->local8Bit().data() ); + o->payload.charstar.owner = TRUE; + o->type = &static_QUType_charstar; + } else if ( isEqual( t, &static_QUType_int ) ) { + o->payload.l = str->toLong(); + o->type = &static_QUType_int; + } else if ( isEqual( t, &static_QUType_double ) ) { + o->payload.d = str->toDouble(); + o->type = &static_QUType_double; + } else { + return FALSE; + } + delete str; + return TRUE; +} + +int TQUType_TQString::serializeTo( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +int TQUType_TQString::serializeFrom( TQUObject *, TQUBuffer * ) +{ + return 0; +} + +void TQUType_TQString::clear( TQUObject *o ) +{ + delete (TQString*)o->payload.ptr; + o->payload.ptr = 0; +} + +TQUObject* TQUObject::deepCopy(TQUObject* newLocation) { + TQUObject* ret; + if (newLocation) { + ret = new(newLocation) TQUObject(*this); + } + else { + ret = new TQUObject(*this); + } + // Any type that has a clear() method must be copied here! + if (*(type->uuid()) == TID_QUType_charstar) { + static_QUType_charstar.set( ret, (const char *)static_QUType_charstar.get(this), true ); + } + if (*(type->uuid()) == TID_QUType_TQString) { + static_QUType_TQString.set( ret, (TQString)static_QUType_TQString.get(this) ); + } + if (*(type->uuid()) == TID_QUType_TQVariant) { + static_QUType_TQVariant.set( ret, (TQVariant)static_QUType_TQVariant.get(this) ); + } + return ret; +} diff --git a/src/tools/tqucom_p.h b/src/tools/tqucom_p.h new file mode 100644 index 000000000..761d5cee4 --- /dev/null +++ b/src/tools/tqucom_p.h @@ -0,0 +1,472 @@ +/**************************************************************************** +** +** Definition of the TQUcom interfaces +** +** Created : 990101 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQUCOM_P_H +#define TQUCOM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of a number of TQt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqstring.h" +#include "tquuid.h" +#endif // QT_H + +#ifdef check +#undef check +#endif + +#if __GNUC__ - 0 > 3 +#pragma GCC system_header +#endif + +struct TQUObject; +struct TQUInterfaceDescription; +struct TQUnknownInterface; +struct TQDispatchInterface; + + +struct TQ_EXPORT TQUBuffer +{ + virtual long read( char *data, ulong maxlen ) = 0; + virtual long write( const char *data, ulong len ) = 0; +}; + + +// A type for a TQUObject +struct TQ_EXPORT TQUType +{ + virtual const TQUuid *uuid() const = 0; + virtual const char *desc() const = 0; + + + virtual bool canConvertFrom( TQUObject *, TQUType * ) = 0; + // virtual private, only called by canConvertFrom + virtual bool canConvertTo( TQUObject *, TQUType * ) = 0; + + + virtual bool convertFrom( TQUObject *, TQUType * ) = 0; + // virtual private, only called by convertFrom + virtual bool convertTo( TQUObject *, TQUType * ) = 0; + + virtual void clear( TQUObject * ) = 0; + + virtual int serializeTo( TQUObject *, TQUBuffer * ) = 0; + virtual int serializeFrom( TQUObject *, TQUBuffer * ) = 0; + + static bool isEqual( const TQUType *t1, const TQUType *t2 ); + static bool check( TQUObject* o, TQUType* t ); +}; + + +// {DE56510E-4E9F-4b76-A3C2-D1E2EF42F1AC} +extern TQ_EXPORT const TQUuid TID_QUType_Null; +struct TQ_EXPORT TQUType_Null : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ); + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_Null static_QUType_Null; + + +// The magic TQUObject +struct TQ_EXPORT TQUObject +{ +public: // scary MSVC bug makes this necessary + TQUObject() : type( &static_QUType_Null ), isLastObject(false) {} + ~TQUObject() { type->clear( this ); } + + TQUType *type; + + // the unavoidable union + union + { + bool b; + + char c; + short s; + int i; + long l; + + unsigned char uc; + unsigned short us; + unsigned int ui; + unsigned long ul; + + float f; + double d; + + char byte[16]; + + struct { + char* data; + unsigned long size; + } bytearray; + + void* ptr; + + struct { + void *ptr; + bool owner; + } voidstar; + + struct { + char *ptr; + bool owner; + } charstar; + + struct { + char *ptr; + bool owner; + } utf8; + + struct { + char *ptr; + bool owner; + } local8bit; + + TQUnknownInterface* iface; + TQDispatchInterface* idisp; + + } payload; + + TQUObject* deepCopy(TQUObject*); + bool isLastObject; +}; + + +// A parameter description describes one method parameters. A +// parameter has a name, a type and a flag describing whether it's an +// in parameter, an out parameter, or both ways +struct TQ_EXPORT TQUParameter +{ + const char* name; + TQUType *type; + const void* typeExtra; //Usually 0, UEnum* for TQUType_enum, const char* for TQUType_ptr, int* for TQUType_varptr + enum { In = 1, Out = 2, InOut = In | Out }; + int inOut; +}; + +// A method description describes one method. A method has a name and +// an array of parameters. +struct TQ_EXPORT TQUMethod +{ + const char* name; + int count; + const TQUParameter* parameters; +}; + +// A Property description. Not used yet in the example. +struct TQ_EXPORT TQUProperty +{ + const char* name; + TQUType* type; + const void* typeExtra; //type dependend. Usually 0, but UEnum for TQUTypeenum or const char* for TQUTypeptr + + int set; // -1 undefined + int get; // -1 undefined + + int designable; // -1 FALSE, -2 TRUE, else method + int stored; // -1 FALSE, -2 TRUE, else method +}; + +// An interface description describes one interface, that is all its +// methods and properties. +struct TQ_EXPORT TQUInterfaceDescription +{ + int methodCount; + const TQUMethod* methods; + int propertyCount; + const TQUProperty* properties; +}; + + +// A component description describe one component, that is its name, +// vendor, release, info, its component uuid and all its interface +// uuids. +struct TQ_EXPORT TQUComponentDescription +{ + const char* name; + const char* vendor; + const char* release; + const char* info; + TQUuid cid; + int count; + const TQUuid* interfaces; +}; + + +// A component server description describe one component server, that +// is its name, vendor, release, info and the descriptions of all +// components it can instantiate. +struct TQ_EXPORT TQUComponentServerDescription +{ + const char* name; + const char* vendor; + const char* release; + const char* info; + int count; + const TQUComponentDescription* components; +}; + + + +struct TQ_EXPORT TQUEnumItem // - a name/value pair +{ + const char *key; + int value; +}; + +struct TQ_EXPORT TQUEnum +{ + const char *name; // - enumerator name + unsigned int count; // - number of values + const TQUEnumItem *items; // - the name/value pairs + bool set; // whether enum has to be treated as a set +}; + +inline bool TQUType::isEqual( const TQUType *t1, const TQUType *t2 ) { + return t1 == t2 || t1->uuid() == t2->uuid() || + *(t1->uuid()) == *(t2->uuid()); +} + +inline bool TQUType::check( TQUObject* o, TQUType* t ) { + return isEqual( o->type, t ) || t->convertFrom( o, o->type ); +} + + + +// {7EE17B08-5419-47e2-9776-8EEA112DCAEC} +extern TQ_EXPORT const TQUuid TID_QUType_enum; +struct TQ_EXPORT TQUType_enum : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, int ); + int &get( TQUObject * o ) { return o->payload.i; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_enum static_QUType_enum; + + +// {8AC26448-5AB4-49eb-968C-8F30AB13D732} +extern TQ_EXPORT const TQUuid TID_QUType_ptr; +struct TQ_EXPORT TQUType_ptr : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, const void* ); + void* &get( TQUObject * o ) { return o->payload.ptr; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_ptr static_QUType_ptr; + +// {97A2594D-6496-4402-A11E-55AEF2D4D25C} +extern TQ_EXPORT const TQUuid TID_QUType_iface; +struct TQ_EXPORT TQUType_iface : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, TQUnknownInterface* ); + TQUnknownInterface* &get( TQUObject *o ){ return o->payload.iface; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_iface static_QUType_iface; + +// {2F358164-E28F-4bf4-9FA9-4E0CDCABA50B} +extern TQ_EXPORT const TQUuid TID_QUType_idisp; +struct TQ_EXPORT TQUType_idisp : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, TQDispatchInterface* ); + TQDispatchInterface* &get( TQUObject *o ){ return o->payload.idisp; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_idisp static_QUType_idisp; + +// {CA42115D-13D0-456c-82B5-FC10187F313E} +extern TQ_EXPORT const TQUuid TID_QUType_bool; +struct TQ_EXPORT TQUType_bool : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, bool ); + bool &get( TQUObject *o ) { return o->payload.b; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_bool static_QUType_bool; + +// {53C1F3BE-73C3-4c7d-9E05-CCF09EB676B5} +extern TQ_EXPORT const TQUuid TID_QUType_int; +struct TQ_EXPORT TQUType_int : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, int ); + int &get( TQUObject *o ) { return o->payload.i; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_int static_QUType_int; + + +// {2D0974E5-0BA6-4ec2-8837-C198972CB48C} +extern TQ_EXPORT const TQUuid TID_QUType_double; +struct TQ_EXPORT TQUType_double : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, double ); + double &get( TQUObject *o ) { return o->payload.d; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ) {} + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); +}; +extern TQ_EXPORT TQUType_double static_QUType_double; + + +// {EFCDD1D4-77A3-4b8e-8D46-DC14B8D393E9} +extern TQ_EXPORT const TQUuid TID_QUType_charstar; +struct TQ_EXPORT TQUType_charstar : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, const char*, bool take = FALSE ); + char* get( TQUObject *o ){ return o->payload.charstar.ptr; } + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ); + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); + +}; +extern TQ_EXPORT TQUType_charstar static_QUType_charstar; + +// {44C2A547-01E7-4e56-8559-35AF9D2F42B7} +extern const TQUuid TID_QUType_TQString; + +struct TQ_EXPORT TQUType_TQString : public TQUType +{ + const TQUuid *uuid() const; + const char *desc() const; + + void set( TQUObject *, const TQString & ); + TQString &get( TQUObject * o ) { return *(TQString*)o->payload.ptr; } + + bool canConvertFrom( TQUObject *, TQUType * ); + bool canConvertTo( TQUObject *, TQUType * ); + bool convertFrom( TQUObject *, TQUType * ); + bool convertTo( TQUObject *, TQUType * ); + void clear( TQUObject * ); + int serializeTo( TQUObject *, TQUBuffer * ); + int serializeFrom( TQUObject *, TQUBuffer * ); + +}; +extern TQ_EXPORT TQUType_TQString static_QUType_TQString; + + +#endif // TQUCOM_P_H diff --git a/src/tools/tqunicodetables.cpp b/src/tools/tqunicodetables.cpp new file mode 100644 index 000000000..ee3ed918b --- /dev/null +++ b/src/tools/tqunicodetables.cpp @@ -0,0 +1,13257 @@ +/**************************************************************************** +** +** ??? +** +** Copyright (C) 2002-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqunicodetables_p.h" + +/* ------------------------------------------------------------------------- + * unicode information + * these tables are generated from the unicode reference file + * ftp://ftp.unicode.org/Public/3.2-Update/UnicodeData.txt + * + * Lars + * ------------------------------------------------------------------------- + */ + +/* ------------------------------------------------------------------------- +2021-04-12 + +Data between + +// START OF GENERATED DATA +and +// END OF GENERATED DATA + +regenerated by adding new character data to UnicodeData-3.2.0.txt[*] +with unedited ArabicShaping-3.2.0.txt and LineBreak-3.2.0.txt +and using perl-5.10 + +[*] https://unicode.org/Public/3.2-Update/ + * ------------------------------------------------------------------------- + */ + +/* Perl script to generate (run perl -x tools/tqunicodetables.cpp) + +#!perl + +sub numberize +{ + my(%r, $n, $id); + for $id ( @_ ) { + $i = $id; + $i="" if $i eq "EMPTY"; + $r{$i}=$n++; + } + return %r; +} + + +sub readUnicodeDataLine { + $code = shift @_; + for $n (qw{ + name category combining_class bidi_category + character_decomposition decimal_digit_value digit_value + numeric_value mirrored oldname comment + uppercase lowercase titlecase}) + { + $id = shift @_; + $codes = "${n}_code"; + if ( defined %$codes && defined $$codes{$id} ) { + $id = $$codes{$id}; + } + ${$n}{$code}=$id; + } + $decomp = $character_decomposition{$code}; + if ( length $decomp == 0 ) { + $decomp = ""; + } + if (substr($decomp, 0, 1) ne '<') { + $decomp = " " . $decomp; + } + @_ = split(" ", $decomp); + $tag = shift @_; + $tag = $character_decomposition_tag{$tag}; + $decomp = join( ", 0x", @_ ); + $decomp = "0x".$decomp; + $decomposition{$code} = $decomp; + $decomposition_tag{$code} = $tag; + $decomposition_pos{$code} = $position; + $len = scalar(@_); + $decomposition_len{$code} = $len; + +# we use canonical decompositions longer than 1 char +# we exlude Arabic ligatures from the table + if($len > 1 and $tag == 1) { +# ligature to add... + $start = shift @_; + $ligature{$start} = $ligature{$start}." ".$code; + } + +# adjust position + if($len != 0) { + $position += $len + 3; + } +} + + +# Code to integer mappings... +# +%category_code = numberize(qw{ + EMPTY + Mn Mc Me + Nd Nl No + Zs Zl Zp + Cc Cf Cs Co Cn + + Lu Ll Lt Lm Lo + Pc Pd Ps Pe Pi Pf Po + Sm Sc Sk So +}); +%bidi_category_code = numberize(qw{ + L R EN ES ET AN CS B S WS ON LRE LRO AL RLE RLO PDF NSM BN}); +%character_decomposition_tag = numberize(qw{ + + + +}); +%mirrored_code = numberize(qw{N Y}); + +%joining_code = numberize(qw{U D R C}); + +# we map AI and XX to AL for now, as we can't handle them any better +%line_break_code = numberize(qw{OP CL QU GL NS EX SY + IS PR PO NU AL ID IN HY + BA BB B2 + ZW CM + SA + BK CR LF SG CB SP +}); + +# Read data into hashes... +# +open IN, "UnicodeData-3.2.0.txt"; +$position = 1; +while () { + @fields = split /;/; + if ( length($fields[0]) < 5 ) { + if ( $fields[1] =~ /, First>/ ) { + $codeRangeBegin = $fields[0]; + } elsif ( $fields[1] =~ /, Last>/ ) { + for ( $i=hex($codeRangeBegin); $i<=hex($fields[0]); $i+=1 ) { + @fields2 = @fields; + $fields2[0] = sprintf "%lX", $i; + readUnicodeDataLine @fields2; + } + } else { + readUnicodeDataLine @fields; + } + } +} + +open IN2, "ArabicShaping-3.2.0.txt"; +$position = 1; +while () { + @fields = split /;/; + $code = shift @fields; + $dummy = shift @fields; + $join = shift @fields; + $join =~ s/ //g; + $join = $joining_code{$join}; + $joining{$code}=$join; +} + +open IN3, "LineBreak-3.2.0.txt"; +$position = 1; +while () { + @fields = split /;/; + $code = shift @fields; + $break = shift @fields; + if (length($break) > 0) { + chomp $break; + $break =~ s/ .*$//; + + $from = $code; + $to = $code; + if ( length($code) > 5 ) { + $from =~ s,\.\..*,,; + $to =~ s/......//; +# print "$from..$to = $break\n"; + } + if($break eq "AI") { + $break = "AL"; + } + if($break eq "XX") { + $break = "AL"; + } + for ( $i=hex($from); $i<=hex($to); $i+=1 ) { + $breaks{sprintf("%04X",$i)}=$line_break_code{$break}; + } + } +} + +# Build pages... +# +$rowtable_txt = ""; +$row_txt = ""; +$pos = 1; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $category{$code}; + $info = 0 if !defined $info; + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $row{$txt}; + if ( !defined $therow ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $row{$txt}=$therow; + $pos += 1; + $size += 256; + } + $rowtable_txt .= "\n " if $row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +print "// START OF GENERATED DATA\n\n"; +print "#ifndef TQT_NO_UNICODETABLES\n\n"; + +# Print pages... +# + +print "const TQ_UINT8 TQUnicodeTables::unicode_info[] = {"; +print $rowtable_txt; +$size += 256; +print "\n\n"; +print $row_txt; +print "};\n\n"; +print "// $size bytes\n\n"; + +# Build decomposition tables +# +$rowtable_txt = ""; +$row_txt = ""; +$table_txt = + "const TQ_UINT16 TQUnicodeTables::decomposition_map[] = {\n 0,\n"; +$pos = 1; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $txt .= "\n " if $cell%8 == 0; + if( $decomposition_tag{$code} != 0 ) { + $txt .= " $decomposition_pos{$code},"; + $table_txt .= " $decomposition_tag{$code},"; + $table_txt .= " 0x$code,"; + $table_txt .= " $decomposition{$code}, 0,\n"; + $size += 2 * $decomposition_len{$code} + 6; + } else { + $txt .= " 0,"; + } + } + $therow = $row{$txt}; + if ( !defined $therow ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $row{$txt}=$therow; + $pos += 1; + $size += 512; + } + $rowtable_txt .= "\n " if $row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print decomposition tables +# +print "$table_txt\n};\n\n"; + +print "const TQ_UINT16 TQUnicodeTables::decomposition_info[] = {"; +print "$rowtable_txt\n"; +$size += 512; +print $row_txt; +print "};\n\n"; +print "// $size bytes\n\n"; + + +# build ligature tables +# +$size = 0; +$position = 1; +$pos = 1; +$rowtable_txt = ""; +$row_txt = ""; +$table_txt = + "const TQ_UINT16 TQUnicodeTables::ligature_map[] = {\n 0,\n"; +for $lig_row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$lig_row,$cell); + $txt .= "\n " if $cell%8 == 0; + if( defined $ligature{$code} ) { + $txt .= " $position,"; + @ligature = split(" ", $ligature{$code}); +# we need to sort ligatures according to their length. +# long ones have to come first! + @ligature_sort = sort { $decomposition_len{$b} <=> $decomposition_len{$a} } @ligature; +# now replace each code by its position in +# the decomposition map. + undef(@lig_pos); + for $n (@ligature_sort) { + push(@lig_pos, $decomposition_pos{$n}); + } +# debug info + if( 0 ) { + print "ligatures: $ligature{$code}\n"; + $sort = join(" ", @ligature_sort); + print "sorted : $sort\n"; + } + $lig = join(", ", @lig_pos); + $table_txt .= " $lig, 0,\n"; + $size += 2 * scalar(@ligature) + 2; + $position += scalar(@ligature) + 1; + } else { + $txt .= " 0,"; + } + } + $therow = $lig_row{$txt}; + if ( !defined $therow ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $lig_row{$txt}=$therow; + $pos += 1; + $size += 512; + } + $rowtable_txt .= "\n " if $lig_row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print ligature tables +# +print "$table_txt\n};\n\n"; +print "const TQ_UINT16 TQUnicodeTables::ligature_info[] = {"; +print "$rowtable_txt\n\n"; +$size+=512; +print $row_txt; +print "};\n\n"; +print "// $size bytes\n\n"; + + + +# Build direction/joining/mirrored pages... +# +$rowtable_txt = ""; +$row_txt = ""; +$pos = 1; +for $dir_row ( 0..255 ) { + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$dir_row,$cell); + $dir = $bidi_category{$code}; + $dir = 0 if !defined $dir; + $join = $joining{$code}; + $join = 0 if !defined $join; + $mirr = $mirrored{$code}; + $mirr = 0 if !defined $mirr; + $info = $dir + 32*$join + 128*$mirr; + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $dir_row{$txt}; + if ( !defined $therow ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $dir_row{$txt}=$therow; + $pos += 1; + $size+=256; + } + $rowtable_txt .= "\n " if $dir_row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print pages... +# +print "const TQ_UINT8 TQUnicodeTables::direction_info[] = {"; +print "$rowtable_txt\n\n"; +$size+=256; +print $row_txt; +print "};\n\n"; +print "// $size bytes\n\n"; + +# Build table of combining classes +# +$rowtable_txt = ""; +$row_txt = ""; +$pos = 1; +for $combining_row ( 0..255 ) { + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$combining_row,$cell); + $info = $combining_class{$code}; + $info = 0 if !defined $info; + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $combining_row{$txt}; + if ( !defined $therow ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $combining_row{$txt}=$therow; + $pos += 1; + $size += 256; + } + $rowtable_txt .= "\n " if $combining_row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print pages... +# +print "const TQ_UINT8 TQUnicodeTables::combining_info[] = {"; +print "$rowtable_txt\n\n"; +$size+=256; +print $row_txt; +print "};\n\n"; +print "// $size bytes\n\n"; + +# Build case info +# +$rowtable_txt = ""; +$row_txt = ""; +$pos = 1; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $uppercase{$code}; + if ( length( $info ) eq 0 ) { + $info = $lowercase{$code}; + } + $info =~ s/^0+//; + if ( length( $info ) eq 0 ) { + $info = "0"; + } else { + $info = "0x".lc($info); + } + if ( length( $info ) ne 1 ) { + $nonzero = 1; + } + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $case_row{$txt}; + if ( !defined $therow && $nonzero ne 0 ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $case_row{$txt}=$therow; + $pos += 1; + $size += 512; + } + $rowtable_txt .= "\n " if $row%8 == 0; + if ( $nonzero ne 0 ) { + $rowtable_txt .= "$therow, "; + } else { + $rowtable_txt .= "0, "; + } +} + +# Print pages... +# +print "const TQ_UINT16 TQUnicodeTables::case_info[] = {"; +print "$rowtable_txt\n\n"; +$size+=512; +print $row_txt; +print "};\n"; +print "// $size bytes\n\n"; + +# Build decimal info +# +$rowtable_txt = ""; +$row_txt = ""; +$pos = 1; +for $row ( 0..255 ) { + $nonzero=0; + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $digit_value{$code}; + if ( length( $info ) eq 0 ) { + $info = -1; + } else { + $nonzero = 1; + } + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $decimal_row{$txt}; + if ( !defined $therow && $nonzero ne 0 ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $decimal_row{$txt}=$therow; + $pos += 1; + $size += 256; + } + $rowtable_txt .= "\n " if $row%8 == 0; + if ( $nonzero ne 0 ) { + $rowtable_txt .= "$therow, "; + } else { + $rowtable_txt .= "0, "; + } +} + +# Print pages... +# +print "const TQ_INT8 TQUnicodeTables::decimal_info[] = {"; +print "$rowtable_txt\n\n"; +$size+=512; +print $row_txt; +print "};\n"; +print "// $size bytes\n\n"; + + +# Build line break info +# +$rowtable_txt = ""; +$row_txt = ""; +$pos = 1; +for $row ( 0..255 ) { + $txt = ""; + for $cell ( 0..255 ) { + $code = sprintf("%02X%02X",$row,$cell); + $info = $breaks{$code}; + if ( length( $info ) eq 0 ) { + $info = $line_break_code{"AL"}; + } + $txt .= "\n " if $cell%8 == 0; + $txt .= "$info, "; + } + $therow = $lb_row{$txt}; + if ( !defined $therow ) { + $therow = sprintf("%d",$pos); + $row_txt = $row_txt."$txt\n"; + $lb_row{$txt}=$therow; + $pos += 1; + $size += 256; + } + $rowtable_txt .= "\n " if $row%8 == 0; + $rowtable_txt .= "$therow, "; +} + +# Print pages... +# +print "const TQ_UINT8 TQUnicodeTables::line_break_info[] = {"; +print "$rowtable_txt\n\n"; +$size+=512; +print $row_txt; +print "};\n"; +print "// $size bytes\n\n"; + + + +print "#endif\n\n"; +print "// END OF GENERATED DATA\n\n"; + + +__END__ + +*/ + +// START OF GENERATED DATA + +#ifndef TQT_NO_UNICODETABLES + +const TQ_UINT8 TQUnicodeTables::unicode_info[] = { + 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, 9, 9, 9, 9, 9, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 30, 9, 9, 9, 38, 39, + 40, 41, 42, 43, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 44, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 45, + 22, 22, 22, 22, 46, 9, 9, 9, + 9, 9, 9, 9, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 47, + 48, 48, 48, 48, 48, 48, 48, 48, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 22, 50, 51, 22, 52, 53, 54, + + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 7, 26, 26, 26, 28, 26, 26, 26, + 22, 23, 26, 27, 26, 21, 26, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 27, 27, 27, 26, + 26, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 26, 23, 29, 20, + 29, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 27, 23, 27, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 7, 26, 28, 28, 28, 28, 30, 30, + 29, 30, 16, 24, 27, 21, 30, 29, + 30, 27, 6, 6, 29, 16, 30, 26, + 29, 6, 16, 25, 6, 6, 6, 26, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 27, + 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 27, + 16, 16, 16, 16, 16, 16, 16, 16, + + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 16, 15, 16, 15, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 15, 16, 15, + 16, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 15, 16, 15, 16, 15, 16, 16, + 16, 15, 15, 16, 15, 16, 15, 15, + 16, 15, 15, 15, 16, 16, 15, 15, + 15, 15, 16, 15, 15, 16, 15, 15, + 15, 16, 16, 16, 15, 15, 16, 15, + 15, 16, 15, 16, 15, 16, 15, 15, + 16, 15, 16, 16, 15, 16, 15, 15, + 16, 15, 15, 15, 16, 15, 16, 15, + 15, 16, 16, 19, 15, 16, 16, 16, + 19, 19, 19, 19, 15, 17, 16, 15, + 17, 16, 15, 17, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 16, 15, 17, 16, 15, 16, 15, 15, + 15, 16, 15, 16, 15, 16, 15, 16, + + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 0, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 16, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 29, 29, 18, 18, 18, 18, 18, + 18, 18, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 18, 18, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 18, 18, 18, 18, 18, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 18, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 29, 29, 0, 0, + 0, 0, 18, 0, 0, 0, 26, 0, + 0, 0, 0, 0, 29, 29, 15, 26, + 15, 15, 15, 0, 15, 0, 15, 15, + 16, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 0, + 16, 16, 15, 15, 15, 16, 16, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 16, 16, 16, 16, 15, 16, 27, 0, + 0, 15, 15, 16, 0, 0, 0, 0, + + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 30, 1, 1, 1, 1, 0, + 3, 3, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 15, 16, 15, 16, 15, 16, 15, + 16, 15, 16, 15, 16, 15, 16, 0, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 0, 0, + 15, 16, 0, 0, 0, 0, 0, 0, + + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, + 0, 18, 26, 26, 26, 26, 26, 26, + 0, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 0, 26, 21, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 26, 1, + 26, 1, 1, 26, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 19, 19, 19, 26, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 26, 0, 0, 0, 26, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 26, 26, 19, 19, + 1, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 26, 19, 1, 1, + 1, 1, 1, 1, 1, 11, 3, 1, + 1, 1, 1, 1, 1, 18, 18, 1, + 1, 30, 1, 1, 1, 1, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 19, 19, 19, 30, 30, 0, + + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 0, 11, + 19, 1, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 1, 1, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 1, 19, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 1, 0, 0, + 19, 1, 1, 1, 1, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 1, 26, 26, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 19, + 19, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 0, 0, 0, 19, 19, + 19, 19, 0, 0, 1, 0, 2, 2, + 2, 1, 1, 1, 1, 0, 0, 2, + 2, 0, 0, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 19, 19, 0, 19, + 19, 19, 1, 1, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 19, 19, 28, 28, 6, 6, 6, 6, + 6, 6, 30, 0, 0, 0, 0, 0, + + 0, 0, 1, 0, 0, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 19, + 19, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 19, 19, 0, + 19, 19, 0, 0, 1, 0, 2, 2, + 2, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 19, 19, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 19, 19, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 0, 19, + 19, 19, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 19, 19, 19, + 19, 19, 0, 0, 1, 19, 2, 2, + 2, 1, 1, 1, 1, 1, 0, 1, + 1, 2, 0, 2, 2, 1, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 1, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 19, + 19, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 0, 0, 19, 19, + 19, 19, 0, 0, 1, 19, 2, 1, + 2, 1, 1, 1, 0, 0, 0, 2, + 2, 0, 0, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, + 0, 0, 0, 0, 19, 19, 0, 19, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 30, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 19, 0, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 0, 0, + 0, 19, 19, 0, 19, 0, 19, 19, + 0, 0, 0, 19, 19, 0, 0, 0, + 19, 19, 19, 0, 0, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 19, + 19, 19, 0, 0, 0, 0, 2, 2, + 1, 2, 2, 0, 0, 0, 2, 2, + 2, 0, 2, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 6, 6, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 2, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 1, 1, + 1, 2, 2, 2, 2, 0, 1, 1, + 1, 0, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 2, 1, + 2, 2, 2, 2, 2, 0, 1, 2, + 2, 0, 2, 2, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 19, 0, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 2, 2, + 2, 1, 1, 1, 0, 0, 2, 2, + 2, 0, 2, 2, 2, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 0, 0, 0, 0, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 1, 0, 0, 0, 0, 2, + 2, 2, 1, 1, 1, 0, 1, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 1, 19, 19, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 28, + 19, 19, 19, 19, 19, 19, 18, 1, + 1, 1, 1, 1, 1, 1, 1, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 19, 19, 0, 19, 0, 0, 19, + 19, 0, 19, 0, 0, 19, 0, 0, + 0, 0, 0, 0, 19, 19, 19, 19, + 0, 19, 19, 19, 19, 19, 19, 19, + 0, 19, 19, 19, 0, 19, 0, 19, + 0, 0, 19, 19, 0, 19, 19, 19, + 19, 1, 19, 19, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 19, 0, 0, + 19, 19, 19, 19, 19, 0, 18, 0, + 1, 1, 1, 1, 1, 1, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 19, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 19, 30, 30, 30, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 30, 30, 30, 30, 30, + 1, 1, 30, 30, 30, 30, 30, 30, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 30, 1, 30, 1, + 30, 1, 22, 23, 22, 23, 2, 2, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 1, 26, 1, 1, + 19, 19, 19, 19, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 30, 30, + 30, 30, 30, 30, 30, 30, 1, 30, + 30, 30, 30, 30, 30, 0, 0, 30, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 19, 19, 19, 19, 19, + 0, 19, 19, 0, 2, 1, 1, 1, + 1, 2, 1, 0, 0, 0, 1, 1, + 2, 1, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 26, 26, 26, 26, + 19, 19, 19, 19, 19, 19, 2, 2, + 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 0, 0, 26, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 0, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 0, 26, 26, 26, 26, 26, 26, 26, + 26, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 26, 26, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 22, 23, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 26, 26, 26, 5, 5, + 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 19, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 1, 1, 26, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 0, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 26, 26, 26, 18, + 26, 26, 26, 28, 19, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 26, 26, 26, 26, 26, 26, 21, 26, + 26, 26, 26, 1, 1, 1, 11, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 16, 16, + 16, 16, 16, 16, 0, 0, 15, 0, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 15, 16, 15, 16, 15, 16, + 15, 16, 0, 0, 0, 0, 0, 0, + + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 0, 15, 0, 15, 0, 15, 0, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 16, 16, 16, 16, 0, 16, 16, + 15, 15, 15, 15, 17, 29, 16, 29, + 29, 29, 16, 16, 16, 0, 16, 16, + 15, 15, 15, 15, 17, 29, 29, 29, + 16, 16, 16, 16, 0, 0, 16, 16, + 15, 15, 15, 15, 0, 29, 29, 29, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 15, 29, 29, 29, + 0, 0, 16, 16, 16, 0, 16, 16, + 15, 15, 15, 15, 17, 29, 29, 0, + + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 11, 11, 11, 11, + 21, 21, 21, 21, 21, 21, 26, 26, + 24, 25, 22, 24, 24, 25, 22, 24, + 26, 26, 26, 26, 26, 26, 26, 26, + 8, 9, 11, 11, 11, 11, 11, 7, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 24, 25, 26, 26, 26, 26, 20, + 20, 26, 26, 26, 27, 22, 23, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 27, 0, 0, 0, 0, 26, + 0, 0, 0, 0, 0, 0, 0, 7, + 11, 11, 11, 11, 0, 0, 0, 0, + 0, 0, 11, 11, 11, 11, 11, 11, + 6, 16, 0, 0, 6, 6, 6, 6, + 6, 6, 27, 27, 27, 22, 23, 16, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 27, 27, 27, 22, 23, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 3, + 3, 1, 3, 3, 3, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 30, 30, 15, 30, 30, 30, 30, 15, + 30, 30, 16, 15, 15, 15, 16, 16, + 15, 15, 15, 16, 30, 15, 30, 30, + 30, 15, 15, 15, 15, 15, 30, 30, + 30, 30, 30, 30, 15, 30, 15, 30, + 15, 30, 15, 15, 15, 15, 30, 16, + 15, 15, 30, 15, 16, 19, 19, 19, + 19, 16, 30, 0, 0, 16, 15, 15, + 27, 27, 27, 27, 27, 15, 16, 16, + 16, 16, 30, 27, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 30, 30, 30, + 30, 30, 27, 27, 30, 30, 30, 30, + 27, 30, 30, 27, 30, 30, 27, 30, + 30, 30, 30, 30, 30, 30, 27, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 27, 27, + 30, 30, 27, 30, 27, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + + 30, 30, 30, 30, 30, 30, 30, 30, + 27, 27, 27, 27, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 27, 27, 30, 30, 30, 30, 30, 30, + 30, 22, 23, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 27, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 22, 23, 26, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 27, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 27, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 27, 27, 27, 27, 27, 27, 27, 27, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 30, 30, + 0, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 27, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 30, 30, 30, 30, 0, 30, 30, + 30, 30, 0, 0, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 0, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 30, 0, 30, + 30, 30, 30, 0, 0, 0, 30, 0, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 30, 30, 30, 30, 30, 30, 30, + 22, 23, 22, 23, 22, 23, 22, 23, + 22, 23, 22, 23, 22, 23, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 30, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 0, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 22, 23, + 22, 23, 22, 23, 0, 0, 0, 0, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 22, 23, 22, 23, 22, + 23, 22, 23, 22, 23, 22, 23, 22, + 23, 22, 23, 22, 23, 22, 23, 22, + 23, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 22, 23, 22, 23, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 22, 23, 27, 27, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 0, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + + 7, 26, 26, 26, 30, 18, 19, 5, + 22, 23, 22, 23, 22, 23, 22, 23, + 22, 23, 30, 30, 22, 23, 22, 23, + 22, 23, 22, 23, 21, 22, 23, 23, + 30, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 1, 1, 1, 1, 1, 1, + 21, 18, 18, 18, 18, 18, 30, 30, + 5, 5, 5, 18, 19, 26, 30, 30, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 1, 1, 29, 29, 18, 18, 19, + 21, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 20, 18, 18, 18, 19, + + 0, 0, 0, 0, 0, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 0, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 30, 30, 6, 6, 6, 6, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 30, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 0, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 0, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 16, 16, 16, 16, 16, 16, 16, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 16, 16, 16, 16, + 0, 0, 0, 0, 0, 19, 1, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 27, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 19, 19, 19, 19, 19, 0, 19, 0, + 19, 19, 0, 19, 19, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 22, 23, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 28, 0, 0, 0, + + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 26, 21, 21, 20, 20, 22, 23, 22, + 23, 22, 23, 22, 23, 22, 23, 22, + 23, 22, 23, 22, 23, 26, 26, 0, + 0, 26, 26, 26, 26, 20, 20, 20, + 26, 26, 26, 0, 26, 26, 26, 26, + 21, 22, 23, 22, 23, 22, 23, 26, + 26, 26, 27, 21, 27, 27, 27, 0, + 26, 28, 26, 26, 0, 0, 0, 0, + 19, 19, 19, 19, 19, 0, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 0, 0, 11, + + 0, 26, 26, 26, 28, 26, 26, 26, + 22, 23, 26, 27, 26, 21, 26, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 27, 27, 27, 26, + 26, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 26, 23, 29, 20, + 29, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 27, 23, 27, 22, + 23, 26, 22, 23, 26, 20, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 18, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 18, 18, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 0, + 0, 0, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 19, 19, 19, + 0, 0, 19, 19, 19, 0, 0, 0, + 28, 28, 27, 29, 30, 28, 28, 0, + 30, 27, 27, 27, 27, 30, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 11, 11, 30, 30, 0, 0, +}; + +// 14080 bytes + +const TQ_UINT16 TQUnicodeTables::decomposition_map[] = { + 0, + 3, 0x00A0, 0x0020, 0, + 16, 0x00A8, 0x0020, 0x0308, 0, + 9, 0x00AA, 0x0061, 0, + 16, 0x00AF, 0x0020, 0x0304, 0, + 9, 0x00B2, 0x0032, 0, + 9, 0x00B3, 0x0033, 0, + 16, 0x00B4, 0x0020, 0x0301, 0, + 16, 0x00B5, 0x03BC, 0, + 16, 0x00B8, 0x0020, 0x0327, 0, + 9, 0x00B9, 0x0031, 0, + 9, 0x00BA, 0x006F, 0, + 17, 0x00BC, 0x0031, 0x2044, 0x0034, 0, + 17, 0x00BD, 0x0031, 0x2044, 0x0032, 0, + 17, 0x00BE, 0x0033, 0x2044, 0x0034, 0, + 1, 0x00C0, 0x0041, 0x0300, 0, + 1, 0x00C1, 0x0041, 0x0301, 0, + 1, 0x00C2, 0x0041, 0x0302, 0, + 1, 0x00C3, 0x0041, 0x0303, 0, + 1, 0x00C4, 0x0041, 0x0308, 0, + 1, 0x00C5, 0x0041, 0x030A, 0, + 1, 0x00C7, 0x0043, 0x0327, 0, + 1, 0x00C8, 0x0045, 0x0300, 0, + 1, 0x00C9, 0x0045, 0x0301, 0, + 1, 0x00CA, 0x0045, 0x0302, 0, + 1, 0x00CB, 0x0045, 0x0308, 0, + 1, 0x00CC, 0x0049, 0x0300, 0, + 1, 0x00CD, 0x0049, 0x0301, 0, + 1, 0x00CE, 0x0049, 0x0302, 0, + 1, 0x00CF, 0x0049, 0x0308, 0, + 1, 0x00D1, 0x004E, 0x0303, 0, + 1, 0x00D2, 0x004F, 0x0300, 0, + 1, 0x00D3, 0x004F, 0x0301, 0, + 1, 0x00D4, 0x004F, 0x0302, 0, + 1, 0x00D5, 0x004F, 0x0303, 0, + 1, 0x00D6, 0x004F, 0x0308, 0, + 1, 0x00D9, 0x0055, 0x0300, 0, + 1, 0x00DA, 0x0055, 0x0301, 0, + 1, 0x00DB, 0x0055, 0x0302, 0, + 1, 0x00DC, 0x0055, 0x0308, 0, + 1, 0x00DD, 0x0059, 0x0301, 0, + 1, 0x00E0, 0x0061, 0x0300, 0, + 1, 0x00E1, 0x0061, 0x0301, 0, + 1, 0x00E2, 0x0061, 0x0302, 0, + 1, 0x00E3, 0x0061, 0x0303, 0, + 1, 0x00E4, 0x0061, 0x0308, 0, + 1, 0x00E5, 0x0061, 0x030A, 0, + 1, 0x00E7, 0x0063, 0x0327, 0, + 1, 0x00E8, 0x0065, 0x0300, 0, + 1, 0x00E9, 0x0065, 0x0301, 0, + 1, 0x00EA, 0x0065, 0x0302, 0, + 1, 0x00EB, 0x0065, 0x0308, 0, + 1, 0x00EC, 0x0069, 0x0300, 0, + 1, 0x00ED, 0x0069, 0x0301, 0, + 1, 0x00EE, 0x0069, 0x0302, 0, + 1, 0x00EF, 0x0069, 0x0308, 0, + 1, 0x00F1, 0x006E, 0x0303, 0, + 1, 0x00F2, 0x006F, 0x0300, 0, + 1, 0x00F3, 0x006F, 0x0301, 0, + 1, 0x00F4, 0x006F, 0x0302, 0, + 1, 0x00F5, 0x006F, 0x0303, 0, + 1, 0x00F6, 0x006F, 0x0308, 0, + 1, 0x00F9, 0x0075, 0x0300, 0, + 1, 0x00FA, 0x0075, 0x0301, 0, + 1, 0x00FB, 0x0075, 0x0302, 0, + 1, 0x00FC, 0x0075, 0x0308, 0, + 1, 0x00FD, 0x0079, 0x0301, 0, + 1, 0x00FF, 0x0079, 0x0308, 0, + 1, 0x0100, 0x0041, 0x0304, 0, + 1, 0x0101, 0x0061, 0x0304, 0, + 1, 0x0102, 0x0041, 0x0306, 0, + 1, 0x0103, 0x0061, 0x0306, 0, + 1, 0x0104, 0x0041, 0x0328, 0, + 1, 0x0105, 0x0061, 0x0328, 0, + 1, 0x0106, 0x0043, 0x0301, 0, + 1, 0x0107, 0x0063, 0x0301, 0, + 1, 0x0108, 0x0043, 0x0302, 0, + 1, 0x0109, 0x0063, 0x0302, 0, + 1, 0x010A, 0x0043, 0x0307, 0, + 1, 0x010B, 0x0063, 0x0307, 0, + 1, 0x010C, 0x0043, 0x030C, 0, + 1, 0x010D, 0x0063, 0x030C, 0, + 1, 0x010E, 0x0044, 0x030C, 0, + 1, 0x010F, 0x0064, 0x030C, 0, + 1, 0x0112, 0x0045, 0x0304, 0, + 1, 0x0113, 0x0065, 0x0304, 0, + 1, 0x0114, 0x0045, 0x0306, 0, + 1, 0x0115, 0x0065, 0x0306, 0, + 1, 0x0116, 0x0045, 0x0307, 0, + 1, 0x0117, 0x0065, 0x0307, 0, + 1, 0x0118, 0x0045, 0x0328, 0, + 1, 0x0119, 0x0065, 0x0328, 0, + 1, 0x011A, 0x0045, 0x030C, 0, + 1, 0x011B, 0x0065, 0x030C, 0, + 1, 0x011C, 0x0047, 0x0302, 0, + 1, 0x011D, 0x0067, 0x0302, 0, + 1, 0x011E, 0x0047, 0x0306, 0, + 1, 0x011F, 0x0067, 0x0306, 0, + 1, 0x0120, 0x0047, 0x0307, 0, + 1, 0x0121, 0x0067, 0x0307, 0, + 1, 0x0122, 0x0047, 0x0327, 0, + 1, 0x0123, 0x0067, 0x0327, 0, + 1, 0x0124, 0x0048, 0x0302, 0, + 1, 0x0125, 0x0068, 0x0302, 0, + 1, 0x0128, 0x0049, 0x0303, 0, + 1, 0x0129, 0x0069, 0x0303, 0, + 1, 0x012A, 0x0049, 0x0304, 0, + 1, 0x012B, 0x0069, 0x0304, 0, + 1, 0x012C, 0x0049, 0x0306, 0, + 1, 0x012D, 0x0069, 0x0306, 0, + 1, 0x012E, 0x0049, 0x0328, 0, + 1, 0x012F, 0x0069, 0x0328, 0, + 1, 0x0130, 0x0049, 0x0307, 0, + 16, 0x0132, 0x0049, 0x004A, 0, + 16, 0x0133, 0x0069, 0x006A, 0, + 1, 0x0134, 0x004A, 0x0302, 0, + 1, 0x0135, 0x006A, 0x0302, 0, + 1, 0x0136, 0x004B, 0x0327, 0, + 1, 0x0137, 0x006B, 0x0327, 0, + 1, 0x0139, 0x004C, 0x0301, 0, + 1, 0x013A, 0x006C, 0x0301, 0, + 1, 0x013B, 0x004C, 0x0327, 0, + 1, 0x013C, 0x006C, 0x0327, 0, + 1, 0x013D, 0x004C, 0x030C, 0, + 1, 0x013E, 0x006C, 0x030C, 0, + 16, 0x013F, 0x004C, 0x00B7, 0, + 16, 0x0140, 0x006C, 0x00B7, 0, + 1, 0x0143, 0x004E, 0x0301, 0, + 1, 0x0144, 0x006E, 0x0301, 0, + 1, 0x0145, 0x004E, 0x0327, 0, + 1, 0x0146, 0x006E, 0x0327, 0, + 1, 0x0147, 0x004E, 0x030C, 0, + 1, 0x0148, 0x006E, 0x030C, 0, + 16, 0x0149, 0x02BC, 0x006E, 0, + 1, 0x014C, 0x004F, 0x0304, 0, + 1, 0x014D, 0x006F, 0x0304, 0, + 1, 0x014E, 0x004F, 0x0306, 0, + 1, 0x014F, 0x006F, 0x0306, 0, + 1, 0x0150, 0x004F, 0x030B, 0, + 1, 0x0151, 0x006F, 0x030B, 0, + 1, 0x0154, 0x0052, 0x0301, 0, + 1, 0x0155, 0x0072, 0x0301, 0, + 1, 0x0156, 0x0052, 0x0327, 0, + 1, 0x0157, 0x0072, 0x0327, 0, + 1, 0x0158, 0x0052, 0x030C, 0, + 1, 0x0159, 0x0072, 0x030C, 0, + 1, 0x015A, 0x0053, 0x0301, 0, + 1, 0x015B, 0x0073, 0x0301, 0, + 1, 0x015C, 0x0053, 0x0302, 0, + 1, 0x015D, 0x0073, 0x0302, 0, + 1, 0x015E, 0x0053, 0x0327, 0, + 1, 0x015F, 0x0073, 0x0327, 0, + 1, 0x0160, 0x0053, 0x030C, 0, + 1, 0x0161, 0x0073, 0x030C, 0, + 1, 0x0162, 0x0054, 0x0327, 0, + 1, 0x0163, 0x0074, 0x0327, 0, + 1, 0x0164, 0x0054, 0x030C, 0, + 1, 0x0165, 0x0074, 0x030C, 0, + 1, 0x0168, 0x0055, 0x0303, 0, + 1, 0x0169, 0x0075, 0x0303, 0, + 1, 0x016A, 0x0055, 0x0304, 0, + 1, 0x016B, 0x0075, 0x0304, 0, + 1, 0x016C, 0x0055, 0x0306, 0, + 1, 0x016D, 0x0075, 0x0306, 0, + 1, 0x016E, 0x0055, 0x030A, 0, + 1, 0x016F, 0x0075, 0x030A, 0, + 1, 0x0170, 0x0055, 0x030B, 0, + 1, 0x0171, 0x0075, 0x030B, 0, + 1, 0x0172, 0x0055, 0x0328, 0, + 1, 0x0173, 0x0075, 0x0328, 0, + 1, 0x0174, 0x0057, 0x0302, 0, + 1, 0x0175, 0x0077, 0x0302, 0, + 1, 0x0176, 0x0059, 0x0302, 0, + 1, 0x0177, 0x0079, 0x0302, 0, + 1, 0x0178, 0x0059, 0x0308, 0, + 1, 0x0179, 0x005A, 0x0301, 0, + 1, 0x017A, 0x007A, 0x0301, 0, + 1, 0x017B, 0x005A, 0x0307, 0, + 1, 0x017C, 0x007A, 0x0307, 0, + 1, 0x017D, 0x005A, 0x030C, 0, + 1, 0x017E, 0x007A, 0x030C, 0, + 16, 0x017F, 0x0073, 0, + 1, 0x01A0, 0x004F, 0x031B, 0, + 1, 0x01A1, 0x006F, 0x031B, 0, + 1, 0x01AF, 0x0055, 0x031B, 0, + 1, 0x01B0, 0x0075, 0x031B, 0, + 16, 0x01C4, 0x0044, 0x017D, 0, + 16, 0x01C5, 0x0044, 0x017E, 0, + 16, 0x01C6, 0x0064, 0x017E, 0, + 16, 0x01C7, 0x004C, 0x004A, 0, + 16, 0x01C8, 0x004C, 0x006A, 0, + 16, 0x01C9, 0x006C, 0x006A, 0, + 16, 0x01CA, 0x004E, 0x004A, 0, + 16, 0x01CB, 0x004E, 0x006A, 0, + 16, 0x01CC, 0x006E, 0x006A, 0, + 1, 0x01CD, 0x0041, 0x030C, 0, + 1, 0x01CE, 0x0061, 0x030C, 0, + 1, 0x01CF, 0x0049, 0x030C, 0, + 1, 0x01D0, 0x0069, 0x030C, 0, + 1, 0x01D1, 0x004F, 0x030C, 0, + 1, 0x01D2, 0x006F, 0x030C, 0, + 1, 0x01D3, 0x0055, 0x030C, 0, + 1, 0x01D4, 0x0075, 0x030C, 0, + 1, 0x01D5, 0x00DC, 0x0304, 0, + 1, 0x01D6, 0x00FC, 0x0304, 0, + 1, 0x01D7, 0x00DC, 0x0301, 0, + 1, 0x01D8, 0x00FC, 0x0301, 0, + 1, 0x01D9, 0x00DC, 0x030C, 0, + 1, 0x01DA, 0x00FC, 0x030C, 0, + 1, 0x01DB, 0x00DC, 0x0300, 0, + 1, 0x01DC, 0x00FC, 0x0300, 0, + 1, 0x01DE, 0x00C4, 0x0304, 0, + 1, 0x01DF, 0x00E4, 0x0304, 0, + 1, 0x01E0, 0x0226, 0x0304, 0, + 1, 0x01E1, 0x0227, 0x0304, 0, + 1, 0x01E2, 0x00C6, 0x0304, 0, + 1, 0x01E3, 0x00E6, 0x0304, 0, + 1, 0x01E6, 0x0047, 0x030C, 0, + 1, 0x01E7, 0x0067, 0x030C, 0, + 1, 0x01E8, 0x004B, 0x030C, 0, + 1, 0x01E9, 0x006B, 0x030C, 0, + 1, 0x01EA, 0x004F, 0x0328, 0, + 1, 0x01EB, 0x006F, 0x0328, 0, + 1, 0x01EC, 0x01EA, 0x0304, 0, + 1, 0x01ED, 0x01EB, 0x0304, 0, + 1, 0x01EE, 0x01B7, 0x030C, 0, + 1, 0x01EF, 0x0292, 0x030C, 0, + 1, 0x01F0, 0x006A, 0x030C, 0, + 16, 0x01F1, 0x0044, 0x005A, 0, + 16, 0x01F2, 0x0044, 0x007A, 0, + 16, 0x01F3, 0x0064, 0x007A, 0, + 1, 0x01F4, 0x0047, 0x0301, 0, + 1, 0x01F5, 0x0067, 0x0301, 0, + 1, 0x01F8, 0x004E, 0x0300, 0, + 1, 0x01F9, 0x006E, 0x0300, 0, + 1, 0x01FA, 0x00C5, 0x0301, 0, + 1, 0x01FB, 0x00E5, 0x0301, 0, + 1, 0x01FC, 0x00C6, 0x0301, 0, + 1, 0x01FD, 0x00E6, 0x0301, 0, + 1, 0x01FE, 0x00D8, 0x0301, 0, + 1, 0x01FF, 0x00F8, 0x0301, 0, + 1, 0x0200, 0x0041, 0x030F, 0, + 1, 0x0201, 0x0061, 0x030F, 0, + 1, 0x0202, 0x0041, 0x0311, 0, + 1, 0x0203, 0x0061, 0x0311, 0, + 1, 0x0204, 0x0045, 0x030F, 0, + 1, 0x0205, 0x0065, 0x030F, 0, + 1, 0x0206, 0x0045, 0x0311, 0, + 1, 0x0207, 0x0065, 0x0311, 0, + 1, 0x0208, 0x0049, 0x030F, 0, + 1, 0x0209, 0x0069, 0x030F, 0, + 1, 0x020A, 0x0049, 0x0311, 0, + 1, 0x020B, 0x0069, 0x0311, 0, + 1, 0x020C, 0x004F, 0x030F, 0, + 1, 0x020D, 0x006F, 0x030F, 0, + 1, 0x020E, 0x004F, 0x0311, 0, + 1, 0x020F, 0x006F, 0x0311, 0, + 1, 0x0210, 0x0052, 0x030F, 0, + 1, 0x0211, 0x0072, 0x030F, 0, + 1, 0x0212, 0x0052, 0x0311, 0, + 1, 0x0213, 0x0072, 0x0311, 0, + 1, 0x0214, 0x0055, 0x030F, 0, + 1, 0x0215, 0x0075, 0x030F, 0, + 1, 0x0216, 0x0055, 0x0311, 0, + 1, 0x0217, 0x0075, 0x0311, 0, + 1, 0x0218, 0x0053, 0x0326, 0, + 1, 0x0219, 0x0073, 0x0326, 0, + 1, 0x021A, 0x0054, 0x0326, 0, + 1, 0x021B, 0x0074, 0x0326, 0, + 1, 0x021E, 0x0048, 0x030C, 0, + 1, 0x021F, 0x0068, 0x030C, 0, + 1, 0x0226, 0x0041, 0x0307, 0, + 1, 0x0227, 0x0061, 0x0307, 0, + 1, 0x0228, 0x0045, 0x0327, 0, + 1, 0x0229, 0x0065, 0x0327, 0, + 1, 0x022A, 0x00D6, 0x0304, 0, + 1, 0x022B, 0x00F6, 0x0304, 0, + 1, 0x022C, 0x00D5, 0x0304, 0, + 1, 0x022D, 0x00F5, 0x0304, 0, + 1, 0x022E, 0x004F, 0x0307, 0, + 1, 0x022F, 0x006F, 0x0307, 0, + 1, 0x0230, 0x022E, 0x0304, 0, + 1, 0x0231, 0x022F, 0x0304, 0, + 1, 0x0232, 0x0059, 0x0304, 0, + 1, 0x0233, 0x0079, 0x0304, 0, + 9, 0x02B0, 0x0068, 0, + 9, 0x02B1, 0x0266, 0, + 9, 0x02B2, 0x006A, 0, + 9, 0x02B3, 0x0072, 0, + 9, 0x02B4, 0x0279, 0, + 9, 0x02B5, 0x027B, 0, + 9, 0x02B6, 0x0281, 0, + 9, 0x02B7, 0x0077, 0, + 9, 0x02B8, 0x0079, 0, + 16, 0x02D8, 0x0020, 0x0306, 0, + 16, 0x02D9, 0x0020, 0x0307, 0, + 16, 0x02DA, 0x0020, 0x030A, 0, + 16, 0x02DB, 0x0020, 0x0328, 0, + 16, 0x02DC, 0x0020, 0x0303, 0, + 16, 0x02DD, 0x0020, 0x030B, 0, + 9, 0x02E0, 0x0263, 0, + 9, 0x02E1, 0x006C, 0, + 9, 0x02E2, 0x0073, 0, + 9, 0x02E3, 0x0078, 0, + 9, 0x02E4, 0x0295, 0, + 1, 0x0340, 0x0300, 0, + 1, 0x0341, 0x0301, 0, + 1, 0x0343, 0x0313, 0, + 1, 0x0344, 0x0308, 0x0301, 0, + 1, 0x0374, 0x02B9, 0, + 16, 0x037A, 0x0020, 0x0345, 0, + 1, 0x037E, 0x003B, 0, + 16, 0x0384, 0x0020, 0x0301, 0, + 1, 0x0385, 0x00A8, 0x0301, 0, + 1, 0x0386, 0x0391, 0x0301, 0, + 1, 0x0387, 0x00B7, 0, + 1, 0x0388, 0x0395, 0x0301, 0, + 1, 0x0389, 0x0397, 0x0301, 0, + 1, 0x038A, 0x0399, 0x0301, 0, + 1, 0x038C, 0x039F, 0x0301, 0, + 1, 0x038E, 0x03A5, 0x0301, 0, + 1, 0x038F, 0x03A9, 0x0301, 0, + 1, 0x0390, 0x03CA, 0x0301, 0, + 1, 0x03AA, 0x0399, 0x0308, 0, + 1, 0x03AB, 0x03A5, 0x0308, 0, + 1, 0x03AC, 0x03B1, 0x0301, 0, + 1, 0x03AD, 0x03B5, 0x0301, 0, + 1, 0x03AE, 0x03B7, 0x0301, 0, + 1, 0x03AF, 0x03B9, 0x0301, 0, + 1, 0x03B0, 0x03CB, 0x0301, 0, + 1, 0x03CA, 0x03B9, 0x0308, 0, + 1, 0x03CB, 0x03C5, 0x0308, 0, + 1, 0x03CC, 0x03BF, 0x0301, 0, + 1, 0x03CD, 0x03C5, 0x0301, 0, + 1, 0x03CE, 0x03C9, 0x0301, 0, + 16, 0x03D0, 0x03B2, 0, + 16, 0x03D1, 0x03B8, 0, + 16, 0x03D2, 0x03A5, 0, + 1, 0x03D3, 0x03D2, 0x0301, 0, + 1, 0x03D4, 0x03D2, 0x0308, 0, + 16, 0x03D5, 0x03C6, 0, + 16, 0x03D6, 0x03C0, 0, + 16, 0x03F0, 0x03BA, 0, + 16, 0x03F1, 0x03C1, 0, + 16, 0x03F4, 0x0398, 0, + 16, 0x03F5, 0x03B5, 0, + 1, 0x0400, 0x0415, 0x0300, 0, + 1, 0x0401, 0x0415, 0x0308, 0, + 1, 0x0403, 0x0413, 0x0301, 0, + 1, 0x0407, 0x0406, 0x0308, 0, + 1, 0x040C, 0x041A, 0x0301, 0, + 1, 0x040D, 0x0418, 0x0300, 0, + 1, 0x040E, 0x0423, 0x0306, 0, + 1, 0x0419, 0x0418, 0x0306, 0, + 1, 0x0439, 0x0438, 0x0306, 0, + 1, 0x0450, 0x0435, 0x0300, 0, + 1, 0x0451, 0x0435, 0x0308, 0, + 1, 0x0453, 0x0433, 0x0301, 0, + 1, 0x0457, 0x0456, 0x0308, 0, + 1, 0x045C, 0x043A, 0x0301, 0, + 1, 0x045D, 0x0438, 0x0300, 0, + 1, 0x045E, 0x0443, 0x0306, 0, + 1, 0x0476, 0x0474, 0x030F, 0, + 1, 0x0477, 0x0475, 0x030F, 0, + 1, 0x04C1, 0x0416, 0x0306, 0, + 1, 0x04C2, 0x0436, 0x0306, 0, + 1, 0x04D0, 0x0410, 0x0306, 0, + 1, 0x04D1, 0x0430, 0x0306, 0, + 1, 0x04D2, 0x0410, 0x0308, 0, + 1, 0x04D3, 0x0430, 0x0308, 0, + 1, 0x04D6, 0x0415, 0x0306, 0, + 1, 0x04D7, 0x0435, 0x0306, 0, + 1, 0x04DA, 0x04D8, 0x0308, 0, + 1, 0x04DB, 0x04D9, 0x0308, 0, + 1, 0x04DC, 0x0416, 0x0308, 0, + 1, 0x04DD, 0x0436, 0x0308, 0, + 1, 0x04DE, 0x0417, 0x0308, 0, + 1, 0x04DF, 0x0437, 0x0308, 0, + 1, 0x04E2, 0x0418, 0x0304, 0, + 1, 0x04E3, 0x0438, 0x0304, 0, + 1, 0x04E4, 0x0418, 0x0308, 0, + 1, 0x04E5, 0x0438, 0x0308, 0, + 1, 0x04E6, 0x041E, 0x0308, 0, + 1, 0x04E7, 0x043E, 0x0308, 0, + 1, 0x04EA, 0x04E8, 0x0308, 0, + 1, 0x04EB, 0x04E9, 0x0308, 0, + 1, 0x04EC, 0x042D, 0x0308, 0, + 1, 0x04ED, 0x044D, 0x0308, 0, + 1, 0x04EE, 0x0423, 0x0304, 0, + 1, 0x04EF, 0x0443, 0x0304, 0, + 1, 0x04F0, 0x0423, 0x0308, 0, + 1, 0x04F1, 0x0443, 0x0308, 0, + 1, 0x04F2, 0x0423, 0x030B, 0, + 1, 0x04F3, 0x0443, 0x030B, 0, + 1, 0x04F4, 0x0427, 0x0308, 0, + 1, 0x04F5, 0x0447, 0x0308, 0, + 1, 0x04F8, 0x042B, 0x0308, 0, + 1, 0x04F9, 0x044B, 0x0308, 0, + 16, 0x0587, 0x0565, 0x0582, 0, + 1, 0x0622, 0x0627, 0x0653, 0, + 1, 0x0623, 0x0627, 0x0654, 0, + 1, 0x0624, 0x0648, 0x0654, 0, + 1, 0x0625, 0x0627, 0x0655, 0, + 1, 0x0626, 0x064A, 0x0654, 0, + 16, 0x0675, 0x0627, 0x0674, 0, + 16, 0x0676, 0x0648, 0x0674, 0, + 16, 0x0677, 0x06C7, 0x0674, 0, + 16, 0x0678, 0x064A, 0x0674, 0, + 1, 0x06C0, 0x06D5, 0x0654, 0, + 1, 0x06C2, 0x06C1, 0x0654, 0, + 1, 0x06D3, 0x06D2, 0x0654, 0, + 1, 0x0929, 0x0928, 0x093C, 0, + 1, 0x0931, 0x0930, 0x093C, 0, + 1, 0x0934, 0x0933, 0x093C, 0, + 1, 0x0958, 0x0915, 0x093C, 0, + 1, 0x0959, 0x0916, 0x093C, 0, + 1, 0x095A, 0x0917, 0x093C, 0, + 1, 0x095B, 0x091C, 0x093C, 0, + 1, 0x095C, 0x0921, 0x093C, 0, + 1, 0x095D, 0x0922, 0x093C, 0, + 1, 0x095E, 0x092B, 0x093C, 0, + 1, 0x095F, 0x092F, 0x093C, 0, + 1, 0x09CB, 0x09C7, 0x09BE, 0, + 1, 0x09CC, 0x09C7, 0x09D7, 0, + 1, 0x09DC, 0x09A1, 0x09BC, 0, + 1, 0x09DD, 0x09A2, 0x09BC, 0, + 1, 0x09DF, 0x09AF, 0x09BC, 0, + 1, 0x0A33, 0x0A32, 0x0A3C, 0, + 1, 0x0A36, 0x0A38, 0x0A3C, 0, + 1, 0x0A59, 0x0A16, 0x0A3C, 0, + 1, 0x0A5A, 0x0A17, 0x0A3C, 0, + 1, 0x0A5B, 0x0A1C, 0x0A3C, 0, + 1, 0x0A5E, 0x0A2B, 0x0A3C, 0, + 1, 0x0B48, 0x0B47, 0x0B56, 0, + 1, 0x0B4B, 0x0B47, 0x0B3E, 0, + 1, 0x0B4C, 0x0B47, 0x0B57, 0, + 1, 0x0B5C, 0x0B21, 0x0B3C, 0, + 1, 0x0B5D, 0x0B22, 0x0B3C, 0, + 1, 0x0B94, 0x0B92, 0x0BD7, 0, + 1, 0x0BCA, 0x0BC6, 0x0BBE, 0, + 1, 0x0BCB, 0x0BC7, 0x0BBE, 0, + 1, 0x0BCC, 0x0BC6, 0x0BD7, 0, + 1, 0x0C48, 0x0C46, 0x0C56, 0, + 1, 0x0CC0, 0x0CBF, 0x0CD5, 0, + 1, 0x0CC7, 0x0CC6, 0x0CD5, 0, + 1, 0x0CC8, 0x0CC6, 0x0CD6, 0, + 1, 0x0CCA, 0x0CC6, 0x0CC2, 0, + 1, 0x0CCB, 0x0CCA, 0x0CD5, 0, + 1, 0x0D4A, 0x0D46, 0x0D3E, 0, + 1, 0x0D4B, 0x0D47, 0x0D3E, 0, + 1, 0x0D4C, 0x0D46, 0x0D57, 0, + 1, 0x0DDA, 0x0DD9, 0x0DCA, 0, + 1, 0x0DDC, 0x0DD9, 0x0DCF, 0, + 1, 0x0DDD, 0x0DDC, 0x0DCA, 0, + 1, 0x0DDE, 0x0DD9, 0x0DDF, 0, + 16, 0x0E33, 0x0E4D, 0x0E32, 0, + 16, 0x0EB3, 0x0ECD, 0x0EB2, 0, + 16, 0x0EDC, 0x0EAB, 0x0E99, 0, + 16, 0x0EDD, 0x0EAB, 0x0EA1, 0, + 3, 0x0F0C, 0x0F0B, 0, + 1, 0x0F43, 0x0F42, 0x0FB7, 0, + 1, 0x0F4D, 0x0F4C, 0x0FB7, 0, + 1, 0x0F52, 0x0F51, 0x0FB7, 0, + 1, 0x0F57, 0x0F56, 0x0FB7, 0, + 1, 0x0F5C, 0x0F5B, 0x0FB7, 0, + 1, 0x0F69, 0x0F40, 0x0FB5, 0, + 1, 0x0F73, 0x0F71, 0x0F72, 0, + 1, 0x0F75, 0x0F71, 0x0F74, 0, + 1, 0x0F76, 0x0FB2, 0x0F80, 0, + 16, 0x0F77, 0x0FB2, 0x0F81, 0, + 1, 0x0F78, 0x0FB3, 0x0F80, 0, + 16, 0x0F79, 0x0FB3, 0x0F81, 0, + 1, 0x0F81, 0x0F71, 0x0F80, 0, + 1, 0x0F93, 0x0F92, 0x0FB7, 0, + 1, 0x0F9D, 0x0F9C, 0x0FB7, 0, + 1, 0x0FA2, 0x0FA1, 0x0FB7, 0, + 1, 0x0FA7, 0x0FA6, 0x0FB7, 0, + 1, 0x0FAC, 0x0FAB, 0x0FB7, 0, + 1, 0x0FB9, 0x0F90, 0x0FB5, 0, + 1, 0x1026, 0x1025, 0x102E, 0, + 1, 0x1E00, 0x0041, 0x0325, 0, + 1, 0x1E01, 0x0061, 0x0325, 0, + 1, 0x1E02, 0x0042, 0x0307, 0, + 1, 0x1E03, 0x0062, 0x0307, 0, + 1, 0x1E04, 0x0042, 0x0323, 0, + 1, 0x1E05, 0x0062, 0x0323, 0, + 1, 0x1E06, 0x0042, 0x0331, 0, + 1, 0x1E07, 0x0062, 0x0331, 0, + 1, 0x1E08, 0x00C7, 0x0301, 0, + 1, 0x1E09, 0x00E7, 0x0301, 0, + 1, 0x1E0A, 0x0044, 0x0307, 0, + 1, 0x1E0B, 0x0064, 0x0307, 0, + 1, 0x1E0C, 0x0044, 0x0323, 0, + 1, 0x1E0D, 0x0064, 0x0323, 0, + 1, 0x1E0E, 0x0044, 0x0331, 0, + 1, 0x1E0F, 0x0064, 0x0331, 0, + 1, 0x1E10, 0x0044, 0x0327, 0, + 1, 0x1E11, 0x0064, 0x0327, 0, + 1, 0x1E12, 0x0044, 0x032D, 0, + 1, 0x1E13, 0x0064, 0x032D, 0, + 1, 0x1E14, 0x0112, 0x0300, 0, + 1, 0x1E15, 0x0113, 0x0300, 0, + 1, 0x1E16, 0x0112, 0x0301, 0, + 1, 0x1E17, 0x0113, 0x0301, 0, + 1, 0x1E18, 0x0045, 0x032D, 0, + 1, 0x1E19, 0x0065, 0x032D, 0, + 1, 0x1E1A, 0x0045, 0x0330, 0, + 1, 0x1E1B, 0x0065, 0x0330, 0, + 1, 0x1E1C, 0x0228, 0x0306, 0, + 1, 0x1E1D, 0x0229, 0x0306, 0, + 1, 0x1E1E, 0x0046, 0x0307, 0, + 1, 0x1E1F, 0x0066, 0x0307, 0, + 1, 0x1E20, 0x0047, 0x0304, 0, + 1, 0x1E21, 0x0067, 0x0304, 0, + 1, 0x1E22, 0x0048, 0x0307, 0, + 1, 0x1E23, 0x0068, 0x0307, 0, + 1, 0x1E24, 0x0048, 0x0323, 0, + 1, 0x1E25, 0x0068, 0x0323, 0, + 1, 0x1E26, 0x0048, 0x0308, 0, + 1, 0x1E27, 0x0068, 0x0308, 0, + 1, 0x1E28, 0x0048, 0x0327, 0, + 1, 0x1E29, 0x0068, 0x0327, 0, + 1, 0x1E2A, 0x0048, 0x032E, 0, + 1, 0x1E2B, 0x0068, 0x032E, 0, + 1, 0x1E2C, 0x0049, 0x0330, 0, + 1, 0x1E2D, 0x0069, 0x0330, 0, + 1, 0x1E2E, 0x00CF, 0x0301, 0, + 1, 0x1E2F, 0x00EF, 0x0301, 0, + 1, 0x1E30, 0x004B, 0x0301, 0, + 1, 0x1E31, 0x006B, 0x0301, 0, + 1, 0x1E32, 0x004B, 0x0323, 0, + 1, 0x1E33, 0x006B, 0x0323, 0, + 1, 0x1E34, 0x004B, 0x0331, 0, + 1, 0x1E35, 0x006B, 0x0331, 0, + 1, 0x1E36, 0x004C, 0x0323, 0, + 1, 0x1E37, 0x006C, 0x0323, 0, + 1, 0x1E38, 0x1E36, 0x0304, 0, + 1, 0x1E39, 0x1E37, 0x0304, 0, + 1, 0x1E3A, 0x004C, 0x0331, 0, + 1, 0x1E3B, 0x006C, 0x0331, 0, + 1, 0x1E3C, 0x004C, 0x032D, 0, + 1, 0x1E3D, 0x006C, 0x032D, 0, + 1, 0x1E3E, 0x004D, 0x0301, 0, + 1, 0x1E3F, 0x006D, 0x0301, 0, + 1, 0x1E40, 0x004D, 0x0307, 0, + 1, 0x1E41, 0x006D, 0x0307, 0, + 1, 0x1E42, 0x004D, 0x0323, 0, + 1, 0x1E43, 0x006D, 0x0323, 0, + 1, 0x1E44, 0x004E, 0x0307, 0, + 1, 0x1E45, 0x006E, 0x0307, 0, + 1, 0x1E46, 0x004E, 0x0323, 0, + 1, 0x1E47, 0x006E, 0x0323, 0, + 1, 0x1E48, 0x004E, 0x0331, 0, + 1, 0x1E49, 0x006E, 0x0331, 0, + 1, 0x1E4A, 0x004E, 0x032D, 0, + 1, 0x1E4B, 0x006E, 0x032D, 0, + 1, 0x1E4C, 0x00D5, 0x0301, 0, + 1, 0x1E4D, 0x00F5, 0x0301, 0, + 1, 0x1E4E, 0x00D5, 0x0308, 0, + 1, 0x1E4F, 0x00F5, 0x0308, 0, + 1, 0x1E50, 0x014C, 0x0300, 0, + 1, 0x1E51, 0x014D, 0x0300, 0, + 1, 0x1E52, 0x014C, 0x0301, 0, + 1, 0x1E53, 0x014D, 0x0301, 0, + 1, 0x1E54, 0x0050, 0x0301, 0, + 1, 0x1E55, 0x0070, 0x0301, 0, + 1, 0x1E56, 0x0050, 0x0307, 0, + 1, 0x1E57, 0x0070, 0x0307, 0, + 1, 0x1E58, 0x0052, 0x0307, 0, + 1, 0x1E59, 0x0072, 0x0307, 0, + 1, 0x1E5A, 0x0052, 0x0323, 0, + 1, 0x1E5B, 0x0072, 0x0323, 0, + 1, 0x1E5C, 0x1E5A, 0x0304, 0, + 1, 0x1E5D, 0x1E5B, 0x0304, 0, + 1, 0x1E5E, 0x0052, 0x0331, 0, + 1, 0x1E5F, 0x0072, 0x0331, 0, + 1, 0x1E60, 0x0053, 0x0307, 0, + 1, 0x1E61, 0x0073, 0x0307, 0, + 1, 0x1E62, 0x0053, 0x0323, 0, + 1, 0x1E63, 0x0073, 0x0323, 0, + 1, 0x1E64, 0x015A, 0x0307, 0, + 1, 0x1E65, 0x015B, 0x0307, 0, + 1, 0x1E66, 0x0160, 0x0307, 0, + 1, 0x1E67, 0x0161, 0x0307, 0, + 1, 0x1E68, 0x1E62, 0x0307, 0, + 1, 0x1E69, 0x1E63, 0x0307, 0, + 1, 0x1E6A, 0x0054, 0x0307, 0, + 1, 0x1E6B, 0x0074, 0x0307, 0, + 1, 0x1E6C, 0x0054, 0x0323, 0, + 1, 0x1E6D, 0x0074, 0x0323, 0, + 1, 0x1E6E, 0x0054, 0x0331, 0, + 1, 0x1E6F, 0x0074, 0x0331, 0, + 1, 0x1E70, 0x0054, 0x032D, 0, + 1, 0x1E71, 0x0074, 0x032D, 0, + 1, 0x1E72, 0x0055, 0x0324, 0, + 1, 0x1E73, 0x0075, 0x0324, 0, + 1, 0x1E74, 0x0055, 0x0330, 0, + 1, 0x1E75, 0x0075, 0x0330, 0, + 1, 0x1E76, 0x0055, 0x032D, 0, + 1, 0x1E77, 0x0075, 0x032D, 0, + 1, 0x1E78, 0x0168, 0x0301, 0, + 1, 0x1E79, 0x0169, 0x0301, 0, + 1, 0x1E7A, 0x016A, 0x0308, 0, + 1, 0x1E7B, 0x016B, 0x0308, 0, + 1, 0x1E7C, 0x0056, 0x0303, 0, + 1, 0x1E7D, 0x0076, 0x0303, 0, + 1, 0x1E7E, 0x0056, 0x0323, 0, + 1, 0x1E7F, 0x0076, 0x0323, 0, + 1, 0x1E80, 0x0057, 0x0300, 0, + 1, 0x1E81, 0x0077, 0x0300, 0, + 1, 0x1E82, 0x0057, 0x0301, 0, + 1, 0x1E83, 0x0077, 0x0301, 0, + 1, 0x1E84, 0x0057, 0x0308, 0, + 1, 0x1E85, 0x0077, 0x0308, 0, + 1, 0x1E86, 0x0057, 0x0307, 0, + 1, 0x1E87, 0x0077, 0x0307, 0, + 1, 0x1E88, 0x0057, 0x0323, 0, + 1, 0x1E89, 0x0077, 0x0323, 0, + 1, 0x1E8A, 0x0058, 0x0307, 0, + 1, 0x1E8B, 0x0078, 0x0307, 0, + 1, 0x1E8C, 0x0058, 0x0308, 0, + 1, 0x1E8D, 0x0078, 0x0308, 0, + 1, 0x1E8E, 0x0059, 0x0307, 0, + 1, 0x1E8F, 0x0079, 0x0307, 0, + 1, 0x1E90, 0x005A, 0x0302, 0, + 1, 0x1E91, 0x007A, 0x0302, 0, + 1, 0x1E92, 0x005A, 0x0323, 0, + 1, 0x1E93, 0x007A, 0x0323, 0, + 1, 0x1E94, 0x005A, 0x0331, 0, + 1, 0x1E95, 0x007A, 0x0331, 0, + 1, 0x1E96, 0x0068, 0x0331, 0, + 1, 0x1E97, 0x0074, 0x0308, 0, + 1, 0x1E98, 0x0077, 0x030A, 0, + 1, 0x1E99, 0x0079, 0x030A, 0, + 16, 0x1E9A, 0x0061, 0x02BE, 0, + 1, 0x1E9B, 0x017F, 0x0307, 0, + 1, 0x1EA0, 0x0041, 0x0323, 0, + 1, 0x1EA1, 0x0061, 0x0323, 0, + 1, 0x1EA2, 0x0041, 0x0309, 0, + 1, 0x1EA3, 0x0061, 0x0309, 0, + 1, 0x1EA4, 0x00C2, 0x0301, 0, + 1, 0x1EA5, 0x00E2, 0x0301, 0, + 1, 0x1EA6, 0x00C2, 0x0300, 0, + 1, 0x1EA7, 0x00E2, 0x0300, 0, + 1, 0x1EA8, 0x00C2, 0x0309, 0, + 1, 0x1EA9, 0x00E2, 0x0309, 0, + 1, 0x1EAA, 0x00C2, 0x0303, 0, + 1, 0x1EAB, 0x00E2, 0x0303, 0, + 1, 0x1EAC, 0x1EA0, 0x0302, 0, + 1, 0x1EAD, 0x1EA1, 0x0302, 0, + 1, 0x1EAE, 0x0102, 0x0301, 0, + 1, 0x1EAF, 0x0103, 0x0301, 0, + 1, 0x1EB0, 0x0102, 0x0300, 0, + 1, 0x1EB1, 0x0103, 0x0300, 0, + 1, 0x1EB2, 0x0102, 0x0309, 0, + 1, 0x1EB3, 0x0103, 0x0309, 0, + 1, 0x1EB4, 0x0102, 0x0303, 0, + 1, 0x1EB5, 0x0103, 0x0303, 0, + 1, 0x1EB6, 0x1EA0, 0x0306, 0, + 1, 0x1EB7, 0x1EA1, 0x0306, 0, + 1, 0x1EB8, 0x0045, 0x0323, 0, + 1, 0x1EB9, 0x0065, 0x0323, 0, + 1, 0x1EBA, 0x0045, 0x0309, 0, + 1, 0x1EBB, 0x0065, 0x0309, 0, + 1, 0x1EBC, 0x0045, 0x0303, 0, + 1, 0x1EBD, 0x0065, 0x0303, 0, + 1, 0x1EBE, 0x00CA, 0x0301, 0, + 1, 0x1EBF, 0x00EA, 0x0301, 0, + 1, 0x1EC0, 0x00CA, 0x0300, 0, + 1, 0x1EC1, 0x00EA, 0x0300, 0, + 1, 0x1EC2, 0x00CA, 0x0309, 0, + 1, 0x1EC3, 0x00EA, 0x0309, 0, + 1, 0x1EC4, 0x00CA, 0x0303, 0, + 1, 0x1EC5, 0x00EA, 0x0303, 0, + 1, 0x1EC6, 0x1EB8, 0x0302, 0, + 1, 0x1EC7, 0x1EB9, 0x0302, 0, + 1, 0x1EC8, 0x0049, 0x0309, 0, + 1, 0x1EC9, 0x0069, 0x0309, 0, + 1, 0x1ECA, 0x0049, 0x0323, 0, + 1, 0x1ECB, 0x0069, 0x0323, 0, + 1, 0x1ECC, 0x004F, 0x0323, 0, + 1, 0x1ECD, 0x006F, 0x0323, 0, + 1, 0x1ECE, 0x004F, 0x0309, 0, + 1, 0x1ECF, 0x006F, 0x0309, 0, + 1, 0x1ED0, 0x00D4, 0x0301, 0, + 1, 0x1ED1, 0x00F4, 0x0301, 0, + 1, 0x1ED2, 0x00D4, 0x0300, 0, + 1, 0x1ED3, 0x00F4, 0x0300, 0, + 1, 0x1ED4, 0x00D4, 0x0309, 0, + 1, 0x1ED5, 0x00F4, 0x0309, 0, + 1, 0x1ED6, 0x00D4, 0x0303, 0, + 1, 0x1ED7, 0x00F4, 0x0303, 0, + 1, 0x1ED8, 0x1ECC, 0x0302, 0, + 1, 0x1ED9, 0x1ECD, 0x0302, 0, + 1, 0x1EDA, 0x01A0, 0x0301, 0, + 1, 0x1EDB, 0x01A1, 0x0301, 0, + 1, 0x1EDC, 0x01A0, 0x0300, 0, + 1, 0x1EDD, 0x01A1, 0x0300, 0, + 1, 0x1EDE, 0x01A0, 0x0309, 0, + 1, 0x1EDF, 0x01A1, 0x0309, 0, + 1, 0x1EE0, 0x01A0, 0x0303, 0, + 1, 0x1EE1, 0x01A1, 0x0303, 0, + 1, 0x1EE2, 0x01A0, 0x0323, 0, + 1, 0x1EE3, 0x01A1, 0x0323, 0, + 1, 0x1EE4, 0x0055, 0x0323, 0, + 1, 0x1EE5, 0x0075, 0x0323, 0, + 1, 0x1EE6, 0x0055, 0x0309, 0, + 1, 0x1EE7, 0x0075, 0x0309, 0, + 1, 0x1EE8, 0x01AF, 0x0301, 0, + 1, 0x1EE9, 0x01B0, 0x0301, 0, + 1, 0x1EEA, 0x01AF, 0x0300, 0, + 1, 0x1EEB, 0x01B0, 0x0300, 0, + 1, 0x1EEC, 0x01AF, 0x0309, 0, + 1, 0x1EED, 0x01B0, 0x0309, 0, + 1, 0x1EEE, 0x01AF, 0x0303, 0, + 1, 0x1EEF, 0x01B0, 0x0303, 0, + 1, 0x1EF0, 0x01AF, 0x0323, 0, + 1, 0x1EF1, 0x01B0, 0x0323, 0, + 1, 0x1EF2, 0x0059, 0x0300, 0, + 1, 0x1EF3, 0x0079, 0x0300, 0, + 1, 0x1EF4, 0x0059, 0x0323, 0, + 1, 0x1EF5, 0x0079, 0x0323, 0, + 1, 0x1EF6, 0x0059, 0x0309, 0, + 1, 0x1EF7, 0x0079, 0x0309, 0, + 1, 0x1EF8, 0x0059, 0x0303, 0, + 1, 0x1EF9, 0x0079, 0x0303, 0, + 1, 0x1F00, 0x03B1, 0x0313, 0, + 1, 0x1F01, 0x03B1, 0x0314, 0, + 1, 0x1F02, 0x1F00, 0x0300, 0, + 1, 0x1F03, 0x1F01, 0x0300, 0, + 1, 0x1F04, 0x1F00, 0x0301, 0, + 1, 0x1F05, 0x1F01, 0x0301, 0, + 1, 0x1F06, 0x1F00, 0x0342, 0, + 1, 0x1F07, 0x1F01, 0x0342, 0, + 1, 0x1F08, 0x0391, 0x0313, 0, + 1, 0x1F09, 0x0391, 0x0314, 0, + 1, 0x1F0A, 0x1F08, 0x0300, 0, + 1, 0x1F0B, 0x1F09, 0x0300, 0, + 1, 0x1F0C, 0x1F08, 0x0301, 0, + 1, 0x1F0D, 0x1F09, 0x0301, 0, + 1, 0x1F0E, 0x1F08, 0x0342, 0, + 1, 0x1F0F, 0x1F09, 0x0342, 0, + 1, 0x1F10, 0x03B5, 0x0313, 0, + 1, 0x1F11, 0x03B5, 0x0314, 0, + 1, 0x1F12, 0x1F10, 0x0300, 0, + 1, 0x1F13, 0x1F11, 0x0300, 0, + 1, 0x1F14, 0x1F10, 0x0301, 0, + 1, 0x1F15, 0x1F11, 0x0301, 0, + 1, 0x1F18, 0x0395, 0x0313, 0, + 1, 0x1F19, 0x0395, 0x0314, 0, + 1, 0x1F1A, 0x1F18, 0x0300, 0, + 1, 0x1F1B, 0x1F19, 0x0300, 0, + 1, 0x1F1C, 0x1F18, 0x0301, 0, + 1, 0x1F1D, 0x1F19, 0x0301, 0, + 1, 0x1F20, 0x03B7, 0x0313, 0, + 1, 0x1F21, 0x03B7, 0x0314, 0, + 1, 0x1F22, 0x1F20, 0x0300, 0, + 1, 0x1F23, 0x1F21, 0x0300, 0, + 1, 0x1F24, 0x1F20, 0x0301, 0, + 1, 0x1F25, 0x1F21, 0x0301, 0, + 1, 0x1F26, 0x1F20, 0x0342, 0, + 1, 0x1F27, 0x1F21, 0x0342, 0, + 1, 0x1F28, 0x0397, 0x0313, 0, + 1, 0x1F29, 0x0397, 0x0314, 0, + 1, 0x1F2A, 0x1F28, 0x0300, 0, + 1, 0x1F2B, 0x1F29, 0x0300, 0, + 1, 0x1F2C, 0x1F28, 0x0301, 0, + 1, 0x1F2D, 0x1F29, 0x0301, 0, + 1, 0x1F2E, 0x1F28, 0x0342, 0, + 1, 0x1F2F, 0x1F29, 0x0342, 0, + 1, 0x1F30, 0x03B9, 0x0313, 0, + 1, 0x1F31, 0x03B9, 0x0314, 0, + 1, 0x1F32, 0x1F30, 0x0300, 0, + 1, 0x1F33, 0x1F31, 0x0300, 0, + 1, 0x1F34, 0x1F30, 0x0301, 0, + 1, 0x1F35, 0x1F31, 0x0301, 0, + 1, 0x1F36, 0x1F30, 0x0342, 0, + 1, 0x1F37, 0x1F31, 0x0342, 0, + 1, 0x1F38, 0x0399, 0x0313, 0, + 1, 0x1F39, 0x0399, 0x0314, 0, + 1, 0x1F3A, 0x1F38, 0x0300, 0, + 1, 0x1F3B, 0x1F39, 0x0300, 0, + 1, 0x1F3C, 0x1F38, 0x0301, 0, + 1, 0x1F3D, 0x1F39, 0x0301, 0, + 1, 0x1F3E, 0x1F38, 0x0342, 0, + 1, 0x1F3F, 0x1F39, 0x0342, 0, + 1, 0x1F40, 0x03BF, 0x0313, 0, + 1, 0x1F41, 0x03BF, 0x0314, 0, + 1, 0x1F42, 0x1F40, 0x0300, 0, + 1, 0x1F43, 0x1F41, 0x0300, 0, + 1, 0x1F44, 0x1F40, 0x0301, 0, + 1, 0x1F45, 0x1F41, 0x0301, 0, + 1, 0x1F48, 0x039F, 0x0313, 0, + 1, 0x1F49, 0x039F, 0x0314, 0, + 1, 0x1F4A, 0x1F48, 0x0300, 0, + 1, 0x1F4B, 0x1F49, 0x0300, 0, + 1, 0x1F4C, 0x1F48, 0x0301, 0, + 1, 0x1F4D, 0x1F49, 0x0301, 0, + 1, 0x1F50, 0x03C5, 0x0313, 0, + 1, 0x1F51, 0x03C5, 0x0314, 0, + 1, 0x1F52, 0x1F50, 0x0300, 0, + 1, 0x1F53, 0x1F51, 0x0300, 0, + 1, 0x1F54, 0x1F50, 0x0301, 0, + 1, 0x1F55, 0x1F51, 0x0301, 0, + 1, 0x1F56, 0x1F50, 0x0342, 0, + 1, 0x1F57, 0x1F51, 0x0342, 0, + 1, 0x1F59, 0x03A5, 0x0314, 0, + 1, 0x1F5B, 0x1F59, 0x0300, 0, + 1, 0x1F5D, 0x1F59, 0x0301, 0, + 1, 0x1F5F, 0x1F59, 0x0342, 0, + 1, 0x1F60, 0x03C9, 0x0313, 0, + 1, 0x1F61, 0x03C9, 0x0314, 0, + 1, 0x1F62, 0x1F60, 0x0300, 0, + 1, 0x1F63, 0x1F61, 0x0300, 0, + 1, 0x1F64, 0x1F60, 0x0301, 0, + 1, 0x1F65, 0x1F61, 0x0301, 0, + 1, 0x1F66, 0x1F60, 0x0342, 0, + 1, 0x1F67, 0x1F61, 0x0342, 0, + 1, 0x1F68, 0x03A9, 0x0313, 0, + 1, 0x1F69, 0x03A9, 0x0314, 0, + 1, 0x1F6A, 0x1F68, 0x0300, 0, + 1, 0x1F6B, 0x1F69, 0x0300, 0, + 1, 0x1F6C, 0x1F68, 0x0301, 0, + 1, 0x1F6D, 0x1F69, 0x0301, 0, + 1, 0x1F6E, 0x1F68, 0x0342, 0, + 1, 0x1F6F, 0x1F69, 0x0342, 0, + 1, 0x1F70, 0x03B1, 0x0300, 0, + 1, 0x1F71, 0x03AC, 0, + 1, 0x1F72, 0x03B5, 0x0300, 0, + 1, 0x1F73, 0x03AD, 0, + 1, 0x1F74, 0x03B7, 0x0300, 0, + 1, 0x1F75, 0x03AE, 0, + 1, 0x1F76, 0x03B9, 0x0300, 0, + 1, 0x1F77, 0x03AF, 0, + 1, 0x1F78, 0x03BF, 0x0300, 0, + 1, 0x1F79, 0x03CC, 0, + 1, 0x1F7A, 0x03C5, 0x0300, 0, + 1, 0x1F7B, 0x03CD, 0, + 1, 0x1F7C, 0x03C9, 0x0300, 0, + 1, 0x1F7D, 0x03CE, 0, + 1, 0x1F80, 0x1F00, 0x0345, 0, + 1, 0x1F81, 0x1F01, 0x0345, 0, + 1, 0x1F82, 0x1F02, 0x0345, 0, + 1, 0x1F83, 0x1F03, 0x0345, 0, + 1, 0x1F84, 0x1F04, 0x0345, 0, + 1, 0x1F85, 0x1F05, 0x0345, 0, + 1, 0x1F86, 0x1F06, 0x0345, 0, + 1, 0x1F87, 0x1F07, 0x0345, 0, + 1, 0x1F88, 0x1F08, 0x0345, 0, + 1, 0x1F89, 0x1F09, 0x0345, 0, + 1, 0x1F8A, 0x1F0A, 0x0345, 0, + 1, 0x1F8B, 0x1F0B, 0x0345, 0, + 1, 0x1F8C, 0x1F0C, 0x0345, 0, + 1, 0x1F8D, 0x1F0D, 0x0345, 0, + 1, 0x1F8E, 0x1F0E, 0x0345, 0, + 1, 0x1F8F, 0x1F0F, 0x0345, 0, + 1, 0x1F90, 0x1F20, 0x0345, 0, + 1, 0x1F91, 0x1F21, 0x0345, 0, + 1, 0x1F92, 0x1F22, 0x0345, 0, + 1, 0x1F93, 0x1F23, 0x0345, 0, + 1, 0x1F94, 0x1F24, 0x0345, 0, + 1, 0x1F95, 0x1F25, 0x0345, 0, + 1, 0x1F96, 0x1F26, 0x0345, 0, + 1, 0x1F97, 0x1F27, 0x0345, 0, + 1, 0x1F98, 0x1F28, 0x0345, 0, + 1, 0x1F99, 0x1F29, 0x0345, 0, + 1, 0x1F9A, 0x1F2A, 0x0345, 0, + 1, 0x1F9B, 0x1F2B, 0x0345, 0, + 1, 0x1F9C, 0x1F2C, 0x0345, 0, + 1, 0x1F9D, 0x1F2D, 0x0345, 0, + 1, 0x1F9E, 0x1F2E, 0x0345, 0, + 1, 0x1F9F, 0x1F2F, 0x0345, 0, + 1, 0x1FA0, 0x1F60, 0x0345, 0, + 1, 0x1FA1, 0x1F61, 0x0345, 0, + 1, 0x1FA2, 0x1F62, 0x0345, 0, + 1, 0x1FA3, 0x1F63, 0x0345, 0, + 1, 0x1FA4, 0x1F64, 0x0345, 0, + 1, 0x1FA5, 0x1F65, 0x0345, 0, + 1, 0x1FA6, 0x1F66, 0x0345, 0, + 1, 0x1FA7, 0x1F67, 0x0345, 0, + 1, 0x1FA8, 0x1F68, 0x0345, 0, + 1, 0x1FA9, 0x1F69, 0x0345, 0, + 1, 0x1FAA, 0x1F6A, 0x0345, 0, + 1, 0x1FAB, 0x1F6B, 0x0345, 0, + 1, 0x1FAC, 0x1F6C, 0x0345, 0, + 1, 0x1FAD, 0x1F6D, 0x0345, 0, + 1, 0x1FAE, 0x1F6E, 0x0345, 0, + 1, 0x1FAF, 0x1F6F, 0x0345, 0, + 1, 0x1FB0, 0x03B1, 0x0306, 0, + 1, 0x1FB1, 0x03B1, 0x0304, 0, + 1, 0x1FB2, 0x1F70, 0x0345, 0, + 1, 0x1FB3, 0x03B1, 0x0345, 0, + 1, 0x1FB4, 0x03AC, 0x0345, 0, + 1, 0x1FB6, 0x03B1, 0x0342, 0, + 1, 0x1FB7, 0x1FB6, 0x0345, 0, + 1, 0x1FB8, 0x0391, 0x0306, 0, + 1, 0x1FB9, 0x0391, 0x0304, 0, + 1, 0x1FBA, 0x0391, 0x0300, 0, + 1, 0x1FBB, 0x0386, 0, + 1, 0x1FBC, 0x0391, 0x0345, 0, + 16, 0x1FBD, 0x0020, 0x0313, 0, + 1, 0x1FBE, 0x03B9, 0, + 16, 0x1FBF, 0x0020, 0x0313, 0, + 16, 0x1FC0, 0x0020, 0x0342, 0, + 1, 0x1FC1, 0x00A8, 0x0342, 0, + 1, 0x1FC2, 0x1F74, 0x0345, 0, + 1, 0x1FC3, 0x03B7, 0x0345, 0, + 1, 0x1FC4, 0x03AE, 0x0345, 0, + 1, 0x1FC6, 0x03B7, 0x0342, 0, + 1, 0x1FC7, 0x1FC6, 0x0345, 0, + 1, 0x1FC8, 0x0395, 0x0300, 0, + 1, 0x1FC9, 0x0388, 0, + 1, 0x1FCA, 0x0397, 0x0300, 0, + 1, 0x1FCB, 0x0389, 0, + 1, 0x1FCC, 0x0397, 0x0345, 0, + 1, 0x1FCD, 0x1FBF, 0x0300, 0, + 1, 0x1FCE, 0x1FBF, 0x0301, 0, + 1, 0x1FCF, 0x1FBF, 0x0342, 0, + 1, 0x1FD0, 0x03B9, 0x0306, 0, + 1, 0x1FD1, 0x03B9, 0x0304, 0, + 1, 0x1FD2, 0x03CA, 0x0300, 0, + 1, 0x1FD3, 0x0390, 0, + 1, 0x1FD6, 0x03B9, 0x0342, 0, + 1, 0x1FD7, 0x03CA, 0x0342, 0, + 1, 0x1FD8, 0x0399, 0x0306, 0, + 1, 0x1FD9, 0x0399, 0x0304, 0, + 1, 0x1FDA, 0x0399, 0x0300, 0, + 1, 0x1FDB, 0x038A, 0, + 1, 0x1FDD, 0x1FFE, 0x0300, 0, + 1, 0x1FDE, 0x1FFE, 0x0301, 0, + 1, 0x1FDF, 0x1FFE, 0x0342, 0, + 1, 0x1FE0, 0x03C5, 0x0306, 0, + 1, 0x1FE1, 0x03C5, 0x0304, 0, + 1, 0x1FE2, 0x03CB, 0x0300, 0, + 1, 0x1FE3, 0x03B0, 0, + 1, 0x1FE4, 0x03C1, 0x0313, 0, + 1, 0x1FE5, 0x03C1, 0x0314, 0, + 1, 0x1FE6, 0x03C5, 0x0342, 0, + 1, 0x1FE7, 0x03CB, 0x0342, 0, + 1, 0x1FE8, 0x03A5, 0x0306, 0, + 1, 0x1FE9, 0x03A5, 0x0304, 0, + 1, 0x1FEA, 0x03A5, 0x0300, 0, + 1, 0x1FEB, 0x038E, 0, + 1, 0x1FEC, 0x03A1, 0x0314, 0, + 1, 0x1FED, 0x00A8, 0x0300, 0, + 1, 0x1FEE, 0x0385, 0, + 1, 0x1FEF, 0x0060, 0, + 1, 0x1FF2, 0x1F7C, 0x0345, 0, + 1, 0x1FF3, 0x03C9, 0x0345, 0, + 1, 0x1FF4, 0x03CE, 0x0345, 0, + 1, 0x1FF6, 0x03C9, 0x0342, 0, + 1, 0x1FF7, 0x1FF6, 0x0345, 0, + 1, 0x1FF8, 0x039F, 0x0300, 0, + 1, 0x1FF9, 0x038C, 0, + 1, 0x1FFA, 0x03A9, 0x0300, 0, + 1, 0x1FFB, 0x038F, 0, + 1, 0x1FFC, 0x03A9, 0x0345, 0, + 1, 0x1FFD, 0x00B4, 0, + 16, 0x1FFE, 0x0020, 0x0314, 0, + 1, 0x2000, 0x2002, 0, + 1, 0x2001, 0x2003, 0, + 16, 0x2002, 0x0020, 0, + 16, 0x2003, 0x0020, 0, + 16, 0x2004, 0x0020, 0, + 16, 0x2005, 0x0020, 0, + 16, 0x2006, 0x0020, 0, + 3, 0x2007, 0x0020, 0, + 16, 0x2008, 0x0020, 0, + 16, 0x2009, 0x0020, 0, + 16, 0x200A, 0x0020, 0, + 3, 0x2011, 0x2010, 0, + 16, 0x2017, 0x0020, 0x0333, 0, + 16, 0x2024, 0x002E, 0, + 16, 0x2025, 0x002E, 0x002E, 0, + 16, 0x2026, 0x002E, 0x002E, 0x002E, 0, + 3, 0x202F, 0x0020, 0, + 16, 0x2033, 0x2032, 0x2032, 0, + 16, 0x2034, 0x2032, 0x2032, 0x2032, 0, + 16, 0x2036, 0x2035, 0x2035, 0, + 16, 0x2037, 0x2035, 0x2035, 0x2035, 0, + 16, 0x203C, 0x0021, 0x0021, 0, + 16, 0x203E, 0x0020, 0x0305, 0, + 16, 0x2047, 0x003F, 0x003F, 0, + 16, 0x2048, 0x003F, 0x0021, 0, + 16, 0x2049, 0x0021, 0x003F, 0, + 16, 0x2057, 0x2032, 0x2032, 0x2032, 0x2032, 0, + 16, 0x205F, 0x0020, 0, + 9, 0x2070, 0x0030, 0, + 9, 0x2071, 0x0069, 0, + 9, 0x2074, 0x0034, 0, + 9, 0x2075, 0x0035, 0, + 9, 0x2076, 0x0036, 0, + 9, 0x2077, 0x0037, 0, + 9, 0x2078, 0x0038, 0, + 9, 0x2079, 0x0039, 0, + 9, 0x207A, 0x002B, 0, + 9, 0x207B, 0x2212, 0, + 9, 0x207C, 0x003D, 0, + 9, 0x207D, 0x0028, 0, + 9, 0x207E, 0x0029, 0, + 9, 0x207F, 0x006E, 0, + 10, 0x2080, 0x0030, 0, + 10, 0x2081, 0x0031, 0, + 10, 0x2082, 0x0032, 0, + 10, 0x2083, 0x0033, 0, + 10, 0x2084, 0x0034, 0, + 10, 0x2085, 0x0035, 0, + 10, 0x2086, 0x0036, 0, + 10, 0x2087, 0x0037, 0, + 10, 0x2088, 0x0038, 0, + 10, 0x2089, 0x0039, 0, + 10, 0x208A, 0x002B, 0, + 10, 0x208B, 0x2212, 0, + 10, 0x208C, 0x003D, 0, + 10, 0x208D, 0x0028, 0, + 10, 0x208E, 0x0029, 0, + 16, 0x20A8, 0x0052, 0x0073, 0, + 16, 0x2100, 0x0061, 0x002F, 0x0063, 0, + 16, 0x2101, 0x0061, 0x002F, 0x0073, 0, + 2, 0x2102, 0x0043, 0, + 16, 0x2103, 0x00B0, 0x0043, 0, + 16, 0x2105, 0x0063, 0x002F, 0x006F, 0, + 16, 0x2106, 0x0063, 0x002F, 0x0075, 0, + 16, 0x2107, 0x0190, 0, + 16, 0x2109, 0x00B0, 0x0046, 0, + 2, 0x210A, 0x0067, 0, + 2, 0x210B, 0x0048, 0, + 2, 0x210C, 0x0048, 0, + 2, 0x210D, 0x0048, 0, + 2, 0x210E, 0x0068, 0, + 2, 0x210F, 0x0127, 0, + 2, 0x2110, 0x0049, 0, + 2, 0x2111, 0x0049, 0, + 2, 0x2112, 0x004C, 0, + 2, 0x2113, 0x006C, 0, + 2, 0x2115, 0x004E, 0, + 16, 0x2116, 0x004E, 0x006F, 0, + 2, 0x2119, 0x0050, 0, + 2, 0x211A, 0x0051, 0, + 2, 0x211B, 0x0052, 0, + 2, 0x211C, 0x0052, 0, + 2, 0x211D, 0x0052, 0, + 9, 0x2120, 0x0053, 0x004D, 0, + 16, 0x2121, 0x0054, 0x0045, 0x004C, 0, + 9, 0x2122, 0x0054, 0x004D, 0, + 2, 0x2124, 0x005A, 0, + 1, 0x2126, 0x03A9, 0, + 2, 0x2128, 0x005A, 0, + 1, 0x212A, 0x004B, 0, + 1, 0x212B, 0x00C5, 0, + 2, 0x212C, 0x0042, 0, + 2, 0x212D, 0x0043, 0, + 2, 0x212F, 0x0065, 0, + 2, 0x2130, 0x0045, 0, + 2, 0x2131, 0x0046, 0, + 2, 0x2133, 0x004D, 0, + 2, 0x2134, 0x006F, 0, + 16, 0x2135, 0x05D0, 0, + 16, 0x2136, 0x05D1, 0, + 16, 0x2137, 0x05D2, 0, + 16, 0x2138, 0x05D3, 0, + 2, 0x2139, 0x0069, 0, + 2, 0x213D, 0x03B3, 0, + 2, 0x213E, 0x0393, 0, + 2, 0x213F, 0x03A0, 0, + 2, 0x2140, 0x2211, 0, + 2, 0x2145, 0x0044, 0, + 2, 0x2146, 0x0064, 0, + 2, 0x2147, 0x0065, 0, + 2, 0x2148, 0x0069, 0, + 2, 0x2149, 0x006A, 0, + 17, 0x2153, 0x0031, 0x2044, 0x0033, 0, + 17, 0x2154, 0x0032, 0x2044, 0x0033, 0, + 17, 0x2155, 0x0031, 0x2044, 0x0035, 0, + 17, 0x2156, 0x0032, 0x2044, 0x0035, 0, + 17, 0x2157, 0x0033, 0x2044, 0x0035, 0, + 17, 0x2158, 0x0034, 0x2044, 0x0035, 0, + 17, 0x2159, 0x0031, 0x2044, 0x0036, 0, + 17, 0x215A, 0x0035, 0x2044, 0x0036, 0, + 17, 0x215B, 0x0031, 0x2044, 0x0038, 0, + 17, 0x215C, 0x0033, 0x2044, 0x0038, 0, + 17, 0x215D, 0x0035, 0x2044, 0x0038, 0, + 17, 0x215E, 0x0037, 0x2044, 0x0038, 0, + 17, 0x215F, 0x0031, 0x2044, 0, + 16, 0x2160, 0x0049, 0, + 16, 0x2161, 0x0049, 0x0049, 0, + 16, 0x2162, 0x0049, 0x0049, 0x0049, 0, + 16, 0x2163, 0x0049, 0x0056, 0, + 16, 0x2164, 0x0056, 0, + 16, 0x2165, 0x0056, 0x0049, 0, + 16, 0x2166, 0x0056, 0x0049, 0x0049, 0, + 16, 0x2167, 0x0056, 0x0049, 0x0049, 0x0049, 0, + 16, 0x2168, 0x0049, 0x0058, 0, + 16, 0x2169, 0x0058, 0, + 16, 0x216A, 0x0058, 0x0049, 0, + 16, 0x216B, 0x0058, 0x0049, 0x0049, 0, + 16, 0x216C, 0x004C, 0, + 16, 0x216D, 0x0043, 0, + 16, 0x216E, 0x0044, 0, + 16, 0x216F, 0x004D, 0, + 16, 0x2170, 0x0069, 0, + 16, 0x2171, 0x0069, 0x0069, 0, + 16, 0x2172, 0x0069, 0x0069, 0x0069, 0, + 16, 0x2173, 0x0069, 0x0076, 0, + 16, 0x2174, 0x0076, 0, + 16, 0x2175, 0x0076, 0x0069, 0, + 16, 0x2176, 0x0076, 0x0069, 0x0069, 0, + 16, 0x2177, 0x0076, 0x0069, 0x0069, 0x0069, 0, + 16, 0x2178, 0x0069, 0x0078, 0, + 16, 0x2179, 0x0078, 0, + 16, 0x217A, 0x0078, 0x0069, 0, + 16, 0x217B, 0x0078, 0x0069, 0x0069, 0, + 16, 0x217C, 0x006C, 0, + 16, 0x217D, 0x0063, 0, + 16, 0x217E, 0x0064, 0, + 16, 0x217F, 0x006D, 0, + 1, 0x219A, 0x2190, 0x0338, 0, + 1, 0x219B, 0x2192, 0x0338, 0, + 1, 0x21AE, 0x2194, 0x0338, 0, + 1, 0x21CD, 0x21D0, 0x0338, 0, + 1, 0x21CE, 0x21D4, 0x0338, 0, + 1, 0x21CF, 0x21D2, 0x0338, 0, + 1, 0x2204, 0x2203, 0x0338, 0, + 1, 0x2209, 0x2208, 0x0338, 0, + 1, 0x220C, 0x220B, 0x0338, 0, + 1, 0x2224, 0x2223, 0x0338, 0, + 1, 0x2226, 0x2225, 0x0338, 0, + 16, 0x222C, 0x222B, 0x222B, 0, + 16, 0x222D, 0x222B, 0x222B, 0x222B, 0, + 16, 0x222F, 0x222E, 0x222E, 0, + 16, 0x2230, 0x222E, 0x222E, 0x222E, 0, + 1, 0x2241, 0x223C, 0x0338, 0, + 1, 0x2244, 0x2243, 0x0338, 0, + 1, 0x2247, 0x2245, 0x0338, 0, + 1, 0x2249, 0x2248, 0x0338, 0, + 1, 0x2260, 0x003D, 0x0338, 0, + 1, 0x2262, 0x2261, 0x0338, 0, + 1, 0x226D, 0x224D, 0x0338, 0, + 1, 0x226E, 0x003C, 0x0338, 0, + 1, 0x226F, 0x003E, 0x0338, 0, + 1, 0x2270, 0x2264, 0x0338, 0, + 1, 0x2271, 0x2265, 0x0338, 0, + 1, 0x2274, 0x2272, 0x0338, 0, + 1, 0x2275, 0x2273, 0x0338, 0, + 1, 0x2278, 0x2276, 0x0338, 0, + 1, 0x2279, 0x2277, 0x0338, 0, + 1, 0x2280, 0x227A, 0x0338, 0, + 1, 0x2281, 0x227B, 0x0338, 0, + 1, 0x2284, 0x2282, 0x0338, 0, + 1, 0x2285, 0x2283, 0x0338, 0, + 1, 0x2288, 0x2286, 0x0338, 0, + 1, 0x2289, 0x2287, 0x0338, 0, + 1, 0x22AC, 0x22A2, 0x0338, 0, + 1, 0x22AD, 0x22A8, 0x0338, 0, + 1, 0x22AE, 0x22A9, 0x0338, 0, + 1, 0x22AF, 0x22AB, 0x0338, 0, + 1, 0x22E0, 0x227C, 0x0338, 0, + 1, 0x22E1, 0x227D, 0x0338, 0, + 1, 0x22E2, 0x2291, 0x0338, 0, + 1, 0x22E3, 0x2292, 0x0338, 0, + 1, 0x22EA, 0x22B2, 0x0338, 0, + 1, 0x22EB, 0x22B3, 0x0338, 0, + 1, 0x22EC, 0x22B4, 0x0338, 0, + 1, 0x22ED, 0x22B5, 0x0338, 0, + 1, 0x2329, 0x3008, 0, + 1, 0x232A, 0x3009, 0, + 8, 0x2460, 0x0031, 0, + 8, 0x2461, 0x0032, 0, + 8, 0x2462, 0x0033, 0, + 8, 0x2463, 0x0034, 0, + 8, 0x2464, 0x0035, 0, + 8, 0x2465, 0x0036, 0, + 8, 0x2466, 0x0037, 0, + 8, 0x2467, 0x0038, 0, + 8, 0x2468, 0x0039, 0, + 8, 0x2469, 0x0031, 0x0030, 0, + 8, 0x246A, 0x0031, 0x0031, 0, + 8, 0x246B, 0x0031, 0x0032, 0, + 8, 0x246C, 0x0031, 0x0033, 0, + 8, 0x246D, 0x0031, 0x0034, 0, + 8, 0x246E, 0x0031, 0x0035, 0, + 8, 0x246F, 0x0031, 0x0036, 0, + 8, 0x2470, 0x0031, 0x0037, 0, + 8, 0x2471, 0x0031, 0x0038, 0, + 8, 0x2472, 0x0031, 0x0039, 0, + 8, 0x2473, 0x0032, 0x0030, 0, + 16, 0x2474, 0x0028, 0x0031, 0x0029, 0, + 16, 0x2475, 0x0028, 0x0032, 0x0029, 0, + 16, 0x2476, 0x0028, 0x0033, 0x0029, 0, + 16, 0x2477, 0x0028, 0x0034, 0x0029, 0, + 16, 0x2478, 0x0028, 0x0035, 0x0029, 0, + 16, 0x2479, 0x0028, 0x0036, 0x0029, 0, + 16, 0x247A, 0x0028, 0x0037, 0x0029, 0, + 16, 0x247B, 0x0028, 0x0038, 0x0029, 0, + 16, 0x247C, 0x0028, 0x0039, 0x0029, 0, + 16, 0x247D, 0x0028, 0x0031, 0x0030, 0x0029, 0, + 16, 0x247E, 0x0028, 0x0031, 0x0031, 0x0029, 0, + 16, 0x247F, 0x0028, 0x0031, 0x0032, 0x0029, 0, + 16, 0x2480, 0x0028, 0x0031, 0x0033, 0x0029, 0, + 16, 0x2481, 0x0028, 0x0031, 0x0034, 0x0029, 0, + 16, 0x2482, 0x0028, 0x0031, 0x0035, 0x0029, 0, + 16, 0x2483, 0x0028, 0x0031, 0x0036, 0x0029, 0, + 16, 0x2484, 0x0028, 0x0031, 0x0037, 0x0029, 0, + 16, 0x2485, 0x0028, 0x0031, 0x0038, 0x0029, 0, + 16, 0x2486, 0x0028, 0x0031, 0x0039, 0x0029, 0, + 16, 0x2487, 0x0028, 0x0032, 0x0030, 0x0029, 0, + 16, 0x2488, 0x0031, 0x002E, 0, + 16, 0x2489, 0x0032, 0x002E, 0, + 16, 0x248A, 0x0033, 0x002E, 0, + 16, 0x248B, 0x0034, 0x002E, 0, + 16, 0x248C, 0x0035, 0x002E, 0, + 16, 0x248D, 0x0036, 0x002E, 0, + 16, 0x248E, 0x0037, 0x002E, 0, + 16, 0x248F, 0x0038, 0x002E, 0, + 16, 0x2490, 0x0039, 0x002E, 0, + 16, 0x2491, 0x0031, 0x0030, 0x002E, 0, + 16, 0x2492, 0x0031, 0x0031, 0x002E, 0, + 16, 0x2493, 0x0031, 0x0032, 0x002E, 0, + 16, 0x2494, 0x0031, 0x0033, 0x002E, 0, + 16, 0x2495, 0x0031, 0x0034, 0x002E, 0, + 16, 0x2496, 0x0031, 0x0035, 0x002E, 0, + 16, 0x2497, 0x0031, 0x0036, 0x002E, 0, + 16, 0x2498, 0x0031, 0x0037, 0x002E, 0, + 16, 0x2499, 0x0031, 0x0038, 0x002E, 0, + 16, 0x249A, 0x0031, 0x0039, 0x002E, 0, + 16, 0x249B, 0x0032, 0x0030, 0x002E, 0, + 16, 0x249C, 0x0028, 0x0061, 0x0029, 0, + 16, 0x249D, 0x0028, 0x0062, 0x0029, 0, + 16, 0x249E, 0x0028, 0x0063, 0x0029, 0, + 16, 0x249F, 0x0028, 0x0064, 0x0029, 0, + 16, 0x24A0, 0x0028, 0x0065, 0x0029, 0, + 16, 0x24A1, 0x0028, 0x0066, 0x0029, 0, + 16, 0x24A2, 0x0028, 0x0067, 0x0029, 0, + 16, 0x24A3, 0x0028, 0x0068, 0x0029, 0, + 16, 0x24A4, 0x0028, 0x0069, 0x0029, 0, + 16, 0x24A5, 0x0028, 0x006A, 0x0029, 0, + 16, 0x24A6, 0x0028, 0x006B, 0x0029, 0, + 16, 0x24A7, 0x0028, 0x006C, 0x0029, 0, + 16, 0x24A8, 0x0028, 0x006D, 0x0029, 0, + 16, 0x24A9, 0x0028, 0x006E, 0x0029, 0, + 16, 0x24AA, 0x0028, 0x006F, 0x0029, 0, + 16, 0x24AB, 0x0028, 0x0070, 0x0029, 0, + 16, 0x24AC, 0x0028, 0x0071, 0x0029, 0, + 16, 0x24AD, 0x0028, 0x0072, 0x0029, 0, + 16, 0x24AE, 0x0028, 0x0073, 0x0029, 0, + 16, 0x24AF, 0x0028, 0x0074, 0x0029, 0, + 16, 0x24B0, 0x0028, 0x0075, 0x0029, 0, + 16, 0x24B1, 0x0028, 0x0076, 0x0029, 0, + 16, 0x24B2, 0x0028, 0x0077, 0x0029, 0, + 16, 0x24B3, 0x0028, 0x0078, 0x0029, 0, + 16, 0x24B4, 0x0028, 0x0079, 0x0029, 0, + 16, 0x24B5, 0x0028, 0x007A, 0x0029, 0, + 8, 0x24B6, 0x0041, 0, + 8, 0x24B7, 0x0042, 0, + 8, 0x24B8, 0x0043, 0, + 8, 0x24B9, 0x0044, 0, + 8, 0x24BA, 0x0045, 0, + 8, 0x24BB, 0x0046, 0, + 8, 0x24BC, 0x0047, 0, + 8, 0x24BD, 0x0048, 0, + 8, 0x24BE, 0x0049, 0, + 8, 0x24BF, 0x004A, 0, + 8, 0x24C0, 0x004B, 0, + 8, 0x24C1, 0x004C, 0, + 8, 0x24C2, 0x004D, 0, + 8, 0x24C3, 0x004E, 0, + 8, 0x24C4, 0x004F, 0, + 8, 0x24C5, 0x0050, 0, + 8, 0x24C6, 0x0051, 0, + 8, 0x24C7, 0x0052, 0, + 8, 0x24C8, 0x0053, 0, + 8, 0x24C9, 0x0054, 0, + 8, 0x24CA, 0x0055, 0, + 8, 0x24CB, 0x0056, 0, + 8, 0x24CC, 0x0057, 0, + 8, 0x24CD, 0x0058, 0, + 8, 0x24CE, 0x0059, 0, + 8, 0x24CF, 0x005A, 0, + 8, 0x24D0, 0x0061, 0, + 8, 0x24D1, 0x0062, 0, + 8, 0x24D2, 0x0063, 0, + 8, 0x24D3, 0x0064, 0, + 8, 0x24D4, 0x0065, 0, + 8, 0x24D5, 0x0066, 0, + 8, 0x24D6, 0x0067, 0, + 8, 0x24D7, 0x0068, 0, + 8, 0x24D8, 0x0069, 0, + 8, 0x24D9, 0x006A, 0, + 8, 0x24DA, 0x006B, 0, + 8, 0x24DB, 0x006C, 0, + 8, 0x24DC, 0x006D, 0, + 8, 0x24DD, 0x006E, 0, + 8, 0x24DE, 0x006F, 0, + 8, 0x24DF, 0x0070, 0, + 8, 0x24E0, 0x0071, 0, + 8, 0x24E1, 0x0072, 0, + 8, 0x24E2, 0x0073, 0, + 8, 0x24E3, 0x0074, 0, + 8, 0x24E4, 0x0075, 0, + 8, 0x24E5, 0x0076, 0, + 8, 0x24E6, 0x0077, 0, + 8, 0x24E7, 0x0078, 0, + 8, 0x24E8, 0x0079, 0, + 8, 0x24E9, 0x007A, 0, + 8, 0x24EA, 0x0030, 0, + 16, 0x2A0C, 0x222B, 0x222B, 0x222B, 0x222B, 0, + 16, 0x2A74, 0x003A, 0x003A, 0x003D, 0, + 16, 0x2A75, 0x003D, 0x003D, 0, + 16, 0x2A76, 0x003D, 0x003D, 0x003D, 0, + 1, 0x2ADC, 0x2ADD, 0x0338, 0, + 16, 0x2E9F, 0x6BCD, 0, + 16, 0x2EF3, 0x9F9F, 0, + 16, 0x2F00, 0x4E00, 0, + 16, 0x2F01, 0x4E28, 0, + 16, 0x2F02, 0x4E36, 0, + 16, 0x2F03, 0x4E3F, 0, + 16, 0x2F04, 0x4E59, 0, + 16, 0x2F05, 0x4E85, 0, + 16, 0x2F06, 0x4E8C, 0, + 16, 0x2F07, 0x4EA0, 0, + 16, 0x2F08, 0x4EBA, 0, + 16, 0x2F09, 0x513F, 0, + 16, 0x2F0A, 0x5165, 0, + 16, 0x2F0B, 0x516B, 0, + 16, 0x2F0C, 0x5182, 0, + 16, 0x2F0D, 0x5196, 0, + 16, 0x2F0E, 0x51AB, 0, + 16, 0x2F0F, 0x51E0, 0, + 16, 0x2F10, 0x51F5, 0, + 16, 0x2F11, 0x5200, 0, + 16, 0x2F12, 0x529B, 0, + 16, 0x2F13, 0x52F9, 0, + 16, 0x2F14, 0x5315, 0, + 16, 0x2F15, 0x531A, 0, + 16, 0x2F16, 0x5338, 0, + 16, 0x2F17, 0x5341, 0, + 16, 0x2F18, 0x535C, 0, + 16, 0x2F19, 0x5369, 0, + 16, 0x2F1A, 0x5382, 0, + 16, 0x2F1B, 0x53B6, 0, + 16, 0x2F1C, 0x53C8, 0, + 16, 0x2F1D, 0x53E3, 0, + 16, 0x2F1E, 0x56D7, 0, + 16, 0x2F1F, 0x571F, 0, + 16, 0x2F20, 0x58EB, 0, + 16, 0x2F21, 0x5902, 0, + 16, 0x2F22, 0x590A, 0, + 16, 0x2F23, 0x5915, 0, + 16, 0x2F24, 0x5927, 0, + 16, 0x2F25, 0x5973, 0, + 16, 0x2F26, 0x5B50, 0, + 16, 0x2F27, 0x5B80, 0, + 16, 0x2F28, 0x5BF8, 0, + 16, 0x2F29, 0x5C0F, 0, + 16, 0x2F2A, 0x5C22, 0, + 16, 0x2F2B, 0x5C38, 0, + 16, 0x2F2C, 0x5C6E, 0, + 16, 0x2F2D, 0x5C71, 0, + 16, 0x2F2E, 0x5DDB, 0, + 16, 0x2F2F, 0x5DE5, 0, + 16, 0x2F30, 0x5DF1, 0, + 16, 0x2F31, 0x5DFE, 0, + 16, 0x2F32, 0x5E72, 0, + 16, 0x2F33, 0x5E7A, 0, + 16, 0x2F34, 0x5E7F, 0, + 16, 0x2F35, 0x5EF4, 0, + 16, 0x2F36, 0x5EFE, 0, + 16, 0x2F37, 0x5F0B, 0, + 16, 0x2F38, 0x5F13, 0, + 16, 0x2F39, 0x5F50, 0, + 16, 0x2F3A, 0x5F61, 0, + 16, 0x2F3B, 0x5F73, 0, + 16, 0x2F3C, 0x5FC3, 0, + 16, 0x2F3D, 0x6208, 0, + 16, 0x2F3E, 0x6236, 0, + 16, 0x2F3F, 0x624B, 0, + 16, 0x2F40, 0x652F, 0, + 16, 0x2F41, 0x6534, 0, + 16, 0x2F42, 0x6587, 0, + 16, 0x2F43, 0x6597, 0, + 16, 0x2F44, 0x65A4, 0, + 16, 0x2F45, 0x65B9, 0, + 16, 0x2F46, 0x65E0, 0, + 16, 0x2F47, 0x65E5, 0, + 16, 0x2F48, 0x66F0, 0, + 16, 0x2F49, 0x6708, 0, + 16, 0x2F4A, 0x6728, 0, + 16, 0x2F4B, 0x6B20, 0, + 16, 0x2F4C, 0x6B62, 0, + 16, 0x2F4D, 0x6B79, 0, + 16, 0x2F4E, 0x6BB3, 0, + 16, 0x2F4F, 0x6BCB, 0, + 16, 0x2F50, 0x6BD4, 0, + 16, 0x2F51, 0x6BDB, 0, + 16, 0x2F52, 0x6C0F, 0, + 16, 0x2F53, 0x6C14, 0, + 16, 0x2F54, 0x6C34, 0, + 16, 0x2F55, 0x706B, 0, + 16, 0x2F56, 0x722A, 0, + 16, 0x2F57, 0x7236, 0, + 16, 0x2F58, 0x723B, 0, + 16, 0x2F59, 0x723F, 0, + 16, 0x2F5A, 0x7247, 0, + 16, 0x2F5B, 0x7259, 0, + 16, 0x2F5C, 0x725B, 0, + 16, 0x2F5D, 0x72AC, 0, + 16, 0x2F5E, 0x7384, 0, + 16, 0x2F5F, 0x7389, 0, + 16, 0x2F60, 0x74DC, 0, + 16, 0x2F61, 0x74E6, 0, + 16, 0x2F62, 0x7518, 0, + 16, 0x2F63, 0x751F, 0, + 16, 0x2F64, 0x7528, 0, + 16, 0x2F65, 0x7530, 0, + 16, 0x2F66, 0x758B, 0, + 16, 0x2F67, 0x7592, 0, + 16, 0x2F68, 0x7676, 0, + 16, 0x2F69, 0x767D, 0, + 16, 0x2F6A, 0x76AE, 0, + 16, 0x2F6B, 0x76BF, 0, + 16, 0x2F6C, 0x76EE, 0, + 16, 0x2F6D, 0x77DB, 0, + 16, 0x2F6E, 0x77E2, 0, + 16, 0x2F6F, 0x77F3, 0, + 16, 0x2F70, 0x793A, 0, + 16, 0x2F71, 0x79B8, 0, + 16, 0x2F72, 0x79BE, 0, + 16, 0x2F73, 0x7A74, 0, + 16, 0x2F74, 0x7ACB, 0, + 16, 0x2F75, 0x7AF9, 0, + 16, 0x2F76, 0x7C73, 0, + 16, 0x2F77, 0x7CF8, 0, + 16, 0x2F78, 0x7F36, 0, + 16, 0x2F79, 0x7F51, 0, + 16, 0x2F7A, 0x7F8A, 0, + 16, 0x2F7B, 0x7FBD, 0, + 16, 0x2F7C, 0x8001, 0, + 16, 0x2F7D, 0x800C, 0, + 16, 0x2F7E, 0x8012, 0, + 16, 0x2F7F, 0x8033, 0, + 16, 0x2F80, 0x807F, 0, + 16, 0x2F81, 0x8089, 0, + 16, 0x2F82, 0x81E3, 0, + 16, 0x2F83, 0x81EA, 0, + 16, 0x2F84, 0x81F3, 0, + 16, 0x2F85, 0x81FC, 0, + 16, 0x2F86, 0x820C, 0, + 16, 0x2F87, 0x821B, 0, + 16, 0x2F88, 0x821F, 0, + 16, 0x2F89, 0x826E, 0, + 16, 0x2F8A, 0x8272, 0, + 16, 0x2F8B, 0x8278, 0, + 16, 0x2F8C, 0x864D, 0, + 16, 0x2F8D, 0x866B, 0, + 16, 0x2F8E, 0x8840, 0, + 16, 0x2F8F, 0x884C, 0, + 16, 0x2F90, 0x8863, 0, + 16, 0x2F91, 0x897E, 0, + 16, 0x2F92, 0x898B, 0, + 16, 0x2F93, 0x89D2, 0, + 16, 0x2F94, 0x8A00, 0, + 16, 0x2F95, 0x8C37, 0, + 16, 0x2F96, 0x8C46, 0, + 16, 0x2F97, 0x8C55, 0, + 16, 0x2F98, 0x8C78, 0, + 16, 0x2F99, 0x8C9D, 0, + 16, 0x2F9A, 0x8D64, 0, + 16, 0x2F9B, 0x8D70, 0, + 16, 0x2F9C, 0x8DB3, 0, + 16, 0x2F9D, 0x8EAB, 0, + 16, 0x2F9E, 0x8ECA, 0, + 16, 0x2F9F, 0x8F9B, 0, + 16, 0x2FA0, 0x8FB0, 0, + 16, 0x2FA1, 0x8FB5, 0, + 16, 0x2FA2, 0x9091, 0, + 16, 0x2FA3, 0x9149, 0, + 16, 0x2FA4, 0x91C6, 0, + 16, 0x2FA5, 0x91CC, 0, + 16, 0x2FA6, 0x91D1, 0, + 16, 0x2FA7, 0x9577, 0, + 16, 0x2FA8, 0x9580, 0, + 16, 0x2FA9, 0x961C, 0, + 16, 0x2FAA, 0x96B6, 0, + 16, 0x2FAB, 0x96B9, 0, + 16, 0x2FAC, 0x96E8, 0, + 16, 0x2FAD, 0x9751, 0, + 16, 0x2FAE, 0x975E, 0, + 16, 0x2FAF, 0x9762, 0, + 16, 0x2FB0, 0x9769, 0, + 16, 0x2FB1, 0x97CB, 0, + 16, 0x2FB2, 0x97ED, 0, + 16, 0x2FB3, 0x97F3, 0, + 16, 0x2FB4, 0x9801, 0, + 16, 0x2FB5, 0x98A8, 0, + 16, 0x2FB6, 0x98DB, 0, + 16, 0x2FB7, 0x98DF, 0, + 16, 0x2FB8, 0x9996, 0, + 16, 0x2FB9, 0x9999, 0, + 16, 0x2FBA, 0x99AC, 0, + 16, 0x2FBB, 0x9AA8, 0, + 16, 0x2FBC, 0x9AD8, 0, + 16, 0x2FBD, 0x9ADF, 0, + 16, 0x2FBE, 0x9B25, 0, + 16, 0x2FBF, 0x9B2F, 0, + 16, 0x2FC0, 0x9B32, 0, + 16, 0x2FC1, 0x9B3C, 0, + 16, 0x2FC2, 0x9B5A, 0, + 16, 0x2FC3, 0x9CE5, 0, + 16, 0x2FC4, 0x9E75, 0, + 16, 0x2FC5, 0x9E7F, 0, + 16, 0x2FC6, 0x9EA5, 0, + 16, 0x2FC7, 0x9EBB, 0, + 16, 0x2FC8, 0x9EC3, 0, + 16, 0x2FC9, 0x9ECD, 0, + 16, 0x2FCA, 0x9ED1, 0, + 16, 0x2FCB, 0x9EF9, 0, + 16, 0x2FCC, 0x9EFD, 0, + 16, 0x2FCD, 0x9F0E, 0, + 16, 0x2FCE, 0x9F13, 0, + 16, 0x2FCF, 0x9F20, 0, + 16, 0x2FD0, 0x9F3B, 0, + 16, 0x2FD1, 0x9F4A, 0, + 16, 0x2FD2, 0x9F52, 0, + 16, 0x2FD3, 0x9F8D, 0, + 16, 0x2FD4, 0x9F9C, 0, + 16, 0x2FD5, 0x9FA0, 0, + 12, 0x3000, 0x0020, 0, + 16, 0x3036, 0x3012, 0, + 16, 0x3038, 0x5341, 0, + 16, 0x3039, 0x5344, 0, + 16, 0x303A, 0x5345, 0, + 1, 0x304C, 0x304B, 0x3099, 0, + 1, 0x304E, 0x304D, 0x3099, 0, + 1, 0x3050, 0x304F, 0x3099, 0, + 1, 0x3052, 0x3051, 0x3099, 0, + 1, 0x3054, 0x3053, 0x3099, 0, + 1, 0x3056, 0x3055, 0x3099, 0, + 1, 0x3058, 0x3057, 0x3099, 0, + 1, 0x305A, 0x3059, 0x3099, 0, + 1, 0x305C, 0x305B, 0x3099, 0, + 1, 0x305E, 0x305D, 0x3099, 0, + 1, 0x3060, 0x305F, 0x3099, 0, + 1, 0x3062, 0x3061, 0x3099, 0, + 1, 0x3065, 0x3064, 0x3099, 0, + 1, 0x3067, 0x3066, 0x3099, 0, + 1, 0x3069, 0x3068, 0x3099, 0, + 1, 0x3070, 0x306F, 0x3099, 0, + 1, 0x3071, 0x306F, 0x309A, 0, + 1, 0x3073, 0x3072, 0x3099, 0, + 1, 0x3074, 0x3072, 0x309A, 0, + 1, 0x3076, 0x3075, 0x3099, 0, + 1, 0x3077, 0x3075, 0x309A, 0, + 1, 0x3079, 0x3078, 0x3099, 0, + 1, 0x307A, 0x3078, 0x309A, 0, + 1, 0x307C, 0x307B, 0x3099, 0, + 1, 0x307D, 0x307B, 0x309A, 0, + 1, 0x3094, 0x3046, 0x3099, 0, + 16, 0x309B, 0x0020, 0x3099, 0, + 16, 0x309C, 0x0020, 0x309A, 0, + 1, 0x309E, 0x309D, 0x3099, 0, + 11, 0x309F, 0x3088, 0x308A, 0, + 1, 0x30AC, 0x30AB, 0x3099, 0, + 1, 0x30AE, 0x30AD, 0x3099, 0, + 1, 0x30B0, 0x30AF, 0x3099, 0, + 1, 0x30B2, 0x30B1, 0x3099, 0, + 1, 0x30B4, 0x30B3, 0x3099, 0, + 1, 0x30B6, 0x30B5, 0x3099, 0, + 1, 0x30B8, 0x30B7, 0x3099, 0, + 1, 0x30BA, 0x30B9, 0x3099, 0, + 1, 0x30BC, 0x30BB, 0x3099, 0, + 1, 0x30BE, 0x30BD, 0x3099, 0, + 1, 0x30C0, 0x30BF, 0x3099, 0, + 1, 0x30C2, 0x30C1, 0x3099, 0, + 1, 0x30C5, 0x30C4, 0x3099, 0, + 1, 0x30C7, 0x30C6, 0x3099, 0, + 1, 0x30C9, 0x30C8, 0x3099, 0, + 1, 0x30D0, 0x30CF, 0x3099, 0, + 1, 0x30D1, 0x30CF, 0x309A, 0, + 1, 0x30D3, 0x30D2, 0x3099, 0, + 1, 0x30D4, 0x30D2, 0x309A, 0, + 1, 0x30D6, 0x30D5, 0x3099, 0, + 1, 0x30D7, 0x30D5, 0x309A, 0, + 1, 0x30D9, 0x30D8, 0x3099, 0, + 1, 0x30DA, 0x30D8, 0x309A, 0, + 1, 0x30DC, 0x30DB, 0x3099, 0, + 1, 0x30DD, 0x30DB, 0x309A, 0, + 1, 0x30F4, 0x30A6, 0x3099, 0, + 1, 0x30F7, 0x30EF, 0x3099, 0, + 1, 0x30F8, 0x30F0, 0x3099, 0, + 1, 0x30F9, 0x30F1, 0x3099, 0, + 1, 0x30FA, 0x30F2, 0x3099, 0, + 1, 0x30FE, 0x30FD, 0x3099, 0, + 11, 0x30FF, 0x30B3, 0x30C8, 0, + 16, 0x3131, 0x1100, 0, + 16, 0x3132, 0x1101, 0, + 16, 0x3133, 0x11AA, 0, + 16, 0x3134, 0x1102, 0, + 16, 0x3135, 0x11AC, 0, + 16, 0x3136, 0x11AD, 0, + 16, 0x3137, 0x1103, 0, + 16, 0x3138, 0x1104, 0, + 16, 0x3139, 0x1105, 0, + 16, 0x313A, 0x11B0, 0, + 16, 0x313B, 0x11B1, 0, + 16, 0x313C, 0x11B2, 0, + 16, 0x313D, 0x11B3, 0, + 16, 0x313E, 0x11B4, 0, + 16, 0x313F, 0x11B5, 0, + 16, 0x3140, 0x111A, 0, + 16, 0x3141, 0x1106, 0, + 16, 0x3142, 0x1107, 0, + 16, 0x3143, 0x1108, 0, + 16, 0x3144, 0x1121, 0, + 16, 0x3145, 0x1109, 0, + 16, 0x3146, 0x110A, 0, + 16, 0x3147, 0x110B, 0, + 16, 0x3148, 0x110C, 0, + 16, 0x3149, 0x110D, 0, + 16, 0x314A, 0x110E, 0, + 16, 0x314B, 0x110F, 0, + 16, 0x314C, 0x1110, 0, + 16, 0x314D, 0x1111, 0, + 16, 0x314E, 0x1112, 0, + 16, 0x314F, 0x1161, 0, + 16, 0x3150, 0x1162, 0, + 16, 0x3151, 0x1163, 0, + 16, 0x3152, 0x1164, 0, + 16, 0x3153, 0x1165, 0, + 16, 0x3154, 0x1166, 0, + 16, 0x3155, 0x1167, 0, + 16, 0x3156, 0x1168, 0, + 16, 0x3157, 0x1169, 0, + 16, 0x3158, 0x116A, 0, + 16, 0x3159, 0x116B, 0, + 16, 0x315A, 0x116C, 0, + 16, 0x315B, 0x116D, 0, + 16, 0x315C, 0x116E, 0, + 16, 0x315D, 0x116F, 0, + 16, 0x315E, 0x1170, 0, + 16, 0x315F, 0x1171, 0, + 16, 0x3160, 0x1172, 0, + 16, 0x3161, 0x1173, 0, + 16, 0x3162, 0x1174, 0, + 16, 0x3163, 0x1175, 0, + 16, 0x3164, 0x1160, 0, + 16, 0x3165, 0x1114, 0, + 16, 0x3166, 0x1115, 0, + 16, 0x3167, 0x11C7, 0, + 16, 0x3168, 0x11C8, 0, + 16, 0x3169, 0x11CC, 0, + 16, 0x316A, 0x11CE, 0, + 16, 0x316B, 0x11D3, 0, + 16, 0x316C, 0x11D7, 0, + 16, 0x316D, 0x11D9, 0, + 16, 0x316E, 0x111C, 0, + 16, 0x316F, 0x11DD, 0, + 16, 0x3170, 0x11DF, 0, + 16, 0x3171, 0x111D, 0, + 16, 0x3172, 0x111E, 0, + 16, 0x3173, 0x1120, 0, + 16, 0x3174, 0x1122, 0, + 16, 0x3175, 0x1123, 0, + 16, 0x3176, 0x1127, 0, + 16, 0x3177, 0x1129, 0, + 16, 0x3178, 0x112B, 0, + 16, 0x3179, 0x112C, 0, + 16, 0x317A, 0x112D, 0, + 16, 0x317B, 0x112E, 0, + 16, 0x317C, 0x112F, 0, + 16, 0x317D, 0x1132, 0, + 16, 0x317E, 0x1136, 0, + 16, 0x317F, 0x1140, 0, + 16, 0x3180, 0x1147, 0, + 16, 0x3181, 0x114C, 0, + 16, 0x3182, 0x11F1, 0, + 16, 0x3183, 0x11F2, 0, + 16, 0x3184, 0x1157, 0, + 16, 0x3185, 0x1158, 0, + 16, 0x3186, 0x1159, 0, + 16, 0x3187, 0x1184, 0, + 16, 0x3188, 0x1185, 0, + 16, 0x3189, 0x1188, 0, + 16, 0x318A, 0x1191, 0, + 16, 0x318B, 0x1192, 0, + 16, 0x318C, 0x1194, 0, + 16, 0x318D, 0x119E, 0, + 16, 0x318E, 0x11A1, 0, + 9, 0x3192, 0x4E00, 0, + 9, 0x3193, 0x4E8C, 0, + 9, 0x3194, 0x4E09, 0, + 9, 0x3195, 0x56DB, 0, + 9, 0x3196, 0x4E0A, 0, + 9, 0x3197, 0x4E2D, 0, + 9, 0x3198, 0x4E0B, 0, + 9, 0x3199, 0x7532, 0, + 9, 0x319A, 0x4E59, 0, + 9, 0x319B, 0x4E19, 0, + 9, 0x319C, 0x4E01, 0, + 9, 0x319D, 0x5929, 0, + 9, 0x319E, 0x5730, 0, + 9, 0x319F, 0x4EBA, 0, + 16, 0x3200, 0x0028, 0x1100, 0x0029, 0, + 16, 0x3201, 0x0028, 0x1102, 0x0029, 0, + 16, 0x3202, 0x0028, 0x1103, 0x0029, 0, + 16, 0x3203, 0x0028, 0x1105, 0x0029, 0, + 16, 0x3204, 0x0028, 0x1106, 0x0029, 0, + 16, 0x3205, 0x0028, 0x1107, 0x0029, 0, + 16, 0x3206, 0x0028, 0x1109, 0x0029, 0, + 16, 0x3207, 0x0028, 0x110B, 0x0029, 0, + 16, 0x3208, 0x0028, 0x110C, 0x0029, 0, + 16, 0x3209, 0x0028, 0x110E, 0x0029, 0, + 16, 0x320A, 0x0028, 0x110F, 0x0029, 0, + 16, 0x320B, 0x0028, 0x1110, 0x0029, 0, + 16, 0x320C, 0x0028, 0x1111, 0x0029, 0, + 16, 0x320D, 0x0028, 0x1112, 0x0029, 0, + 16, 0x320E, 0x0028, 0x1100, 0x1161, 0x0029, 0, + 16, 0x320F, 0x0028, 0x1102, 0x1161, 0x0029, 0, + 16, 0x3210, 0x0028, 0x1103, 0x1161, 0x0029, 0, + 16, 0x3211, 0x0028, 0x1105, 0x1161, 0x0029, 0, + 16, 0x3212, 0x0028, 0x1106, 0x1161, 0x0029, 0, + 16, 0x3213, 0x0028, 0x1107, 0x1161, 0x0029, 0, + 16, 0x3214, 0x0028, 0x1109, 0x1161, 0x0029, 0, + 16, 0x3215, 0x0028, 0x110B, 0x1161, 0x0029, 0, + 16, 0x3216, 0x0028, 0x110C, 0x1161, 0x0029, 0, + 16, 0x3217, 0x0028, 0x110E, 0x1161, 0x0029, 0, + 16, 0x3218, 0x0028, 0x110F, 0x1161, 0x0029, 0, + 16, 0x3219, 0x0028, 0x1110, 0x1161, 0x0029, 0, + 16, 0x321A, 0x0028, 0x1111, 0x1161, 0x0029, 0, + 16, 0x321B, 0x0028, 0x1112, 0x1161, 0x0029, 0, + 16, 0x321C, 0x0028, 0x110C, 0x116E, 0x0029, 0, + 16, 0x3220, 0x0028, 0x4E00, 0x0029, 0, + 16, 0x3221, 0x0028, 0x4E8C, 0x0029, 0, + 16, 0x3222, 0x0028, 0x4E09, 0x0029, 0, + 16, 0x3223, 0x0028, 0x56DB, 0x0029, 0, + 16, 0x3224, 0x0028, 0x4E94, 0x0029, 0, + 16, 0x3225, 0x0028, 0x516D, 0x0029, 0, + 16, 0x3226, 0x0028, 0x4E03, 0x0029, 0, + 16, 0x3227, 0x0028, 0x516B, 0x0029, 0, + 16, 0x3228, 0x0028, 0x4E5D, 0x0029, 0, + 16, 0x3229, 0x0028, 0x5341, 0x0029, 0, + 16, 0x322A, 0x0028, 0x6708, 0x0029, 0, + 16, 0x322B, 0x0028, 0x706B, 0x0029, 0, + 16, 0x322C, 0x0028, 0x6C34, 0x0029, 0, + 16, 0x322D, 0x0028, 0x6728, 0x0029, 0, + 16, 0x322E, 0x0028, 0x91D1, 0x0029, 0, + 16, 0x322F, 0x0028, 0x571F, 0x0029, 0, + 16, 0x3230, 0x0028, 0x65E5, 0x0029, 0, + 16, 0x3231, 0x0028, 0x682A, 0x0029, 0, + 16, 0x3232, 0x0028, 0x6709, 0x0029, 0, + 16, 0x3233, 0x0028, 0x793E, 0x0029, 0, + 16, 0x3234, 0x0028, 0x540D, 0x0029, 0, + 16, 0x3235, 0x0028, 0x7279, 0x0029, 0, + 16, 0x3236, 0x0028, 0x8CA1, 0x0029, 0, + 16, 0x3237, 0x0028, 0x795D, 0x0029, 0, + 16, 0x3238, 0x0028, 0x52B4, 0x0029, 0, + 16, 0x3239, 0x0028, 0x4EE3, 0x0029, 0, + 16, 0x323A, 0x0028, 0x547C, 0x0029, 0, + 16, 0x323B, 0x0028, 0x5B66, 0x0029, 0, + 16, 0x323C, 0x0028, 0x76E3, 0x0029, 0, + 16, 0x323D, 0x0028, 0x4F01, 0x0029, 0, + 16, 0x323E, 0x0028, 0x8CC7, 0x0029, 0, + 16, 0x323F, 0x0028, 0x5354, 0x0029, 0, + 16, 0x3240, 0x0028, 0x796D, 0x0029, 0, + 16, 0x3241, 0x0028, 0x4F11, 0x0029, 0, + 16, 0x3242, 0x0028, 0x81EA, 0x0029, 0, + 16, 0x3243, 0x0028, 0x81F3, 0x0029, 0, + 8, 0x3251, 0x0032, 0x0031, 0, + 8, 0x3252, 0x0032, 0x0032, 0, + 8, 0x3253, 0x0032, 0x0033, 0, + 8, 0x3254, 0x0032, 0x0034, 0, + 8, 0x3255, 0x0032, 0x0035, 0, + 8, 0x3256, 0x0032, 0x0036, 0, + 8, 0x3257, 0x0032, 0x0037, 0, + 8, 0x3258, 0x0032, 0x0038, 0, + 8, 0x3259, 0x0032, 0x0039, 0, + 8, 0x325A, 0x0033, 0x0030, 0, + 8, 0x325B, 0x0033, 0x0031, 0, + 8, 0x325C, 0x0033, 0x0032, 0, + 8, 0x325D, 0x0033, 0x0033, 0, + 8, 0x325E, 0x0033, 0x0034, 0, + 8, 0x325F, 0x0033, 0x0035, 0, + 8, 0x3260, 0x1100, 0, + 8, 0x3261, 0x1102, 0, + 8, 0x3262, 0x1103, 0, + 8, 0x3263, 0x1105, 0, + 8, 0x3264, 0x1106, 0, + 8, 0x3265, 0x1107, 0, + 8, 0x3266, 0x1109, 0, + 8, 0x3267, 0x110B, 0, + 8, 0x3268, 0x110C, 0, + 8, 0x3269, 0x110E, 0, + 8, 0x326A, 0x110F, 0, + 8, 0x326B, 0x1110, 0, + 8, 0x326C, 0x1111, 0, + 8, 0x326D, 0x1112, 0, + 8, 0x326E, 0x1100, 0x1161, 0, + 8, 0x326F, 0x1102, 0x1161, 0, + 8, 0x3270, 0x1103, 0x1161, 0, + 8, 0x3271, 0x1105, 0x1161, 0, + 8, 0x3272, 0x1106, 0x1161, 0, + 8, 0x3273, 0x1107, 0x1161, 0, + 8, 0x3274, 0x1109, 0x1161, 0, + 8, 0x3275, 0x110B, 0x1161, 0, + 8, 0x3276, 0x110C, 0x1161, 0, + 8, 0x3277, 0x110E, 0x1161, 0, + 8, 0x3278, 0x110F, 0x1161, 0, + 8, 0x3279, 0x1110, 0x1161, 0, + 8, 0x327A, 0x1111, 0x1161, 0, + 8, 0x327B, 0x1112, 0x1161, 0, + 8, 0x3280, 0x4E00, 0, + 8, 0x3281, 0x4E8C, 0, + 8, 0x3282, 0x4E09, 0, + 8, 0x3283, 0x56DB, 0, + 8, 0x3284, 0x4E94, 0, + 8, 0x3285, 0x516D, 0, + 8, 0x3286, 0x4E03, 0, + 8, 0x3287, 0x516B, 0, + 8, 0x3288, 0x4E5D, 0, + 8, 0x3289, 0x5341, 0, + 8, 0x328A, 0x6708, 0, + 8, 0x328B, 0x706B, 0, + 8, 0x328C, 0x6C34, 0, + 8, 0x328D, 0x6728, 0, + 8, 0x328E, 0x91D1, 0, + 8, 0x328F, 0x571F, 0, + 8, 0x3290, 0x65E5, 0, + 8, 0x3291, 0x682A, 0, + 8, 0x3292, 0x6709, 0, + 8, 0x3293, 0x793E, 0, + 8, 0x3294, 0x540D, 0, + 8, 0x3295, 0x7279, 0, + 8, 0x3296, 0x8CA1, 0, + 8, 0x3297, 0x795D, 0, + 8, 0x3298, 0x52B4, 0, + 8, 0x3299, 0x79D8, 0, + 8, 0x329A, 0x7537, 0, + 8, 0x329B, 0x5973, 0, + 8, 0x329C, 0x9069, 0, + 8, 0x329D, 0x512A, 0, + 8, 0x329E, 0x5370, 0, + 8, 0x329F, 0x6CE8, 0, + 8, 0x32A0, 0x9805, 0, + 8, 0x32A1, 0x4F11, 0, + 8, 0x32A2, 0x5199, 0, + 8, 0x32A3, 0x6B63, 0, + 8, 0x32A4, 0x4E0A, 0, + 8, 0x32A5, 0x4E2D, 0, + 8, 0x32A6, 0x4E0B, 0, + 8, 0x32A7, 0x5DE6, 0, + 8, 0x32A8, 0x53F3, 0, + 8, 0x32A9, 0x533B, 0, + 8, 0x32AA, 0x5B97, 0, + 8, 0x32AB, 0x5B66, 0, + 8, 0x32AC, 0x76E3, 0, + 8, 0x32AD, 0x4F01, 0, + 8, 0x32AE, 0x8CC7, 0, + 8, 0x32AF, 0x5354, 0, + 8, 0x32B0, 0x591C, 0, + 8, 0x32B1, 0x0033, 0x0036, 0, + 8, 0x32B2, 0x0033, 0x0037, 0, + 8, 0x32B3, 0x0033, 0x0038, 0, + 8, 0x32B4, 0x0033, 0x0039, 0, + 8, 0x32B5, 0x0034, 0x0030, 0, + 8, 0x32B6, 0x0034, 0x0031, 0, + 8, 0x32B7, 0x0034, 0x0032, 0, + 8, 0x32B8, 0x0034, 0x0033, 0, + 8, 0x32B9, 0x0034, 0x0034, 0, + 8, 0x32BA, 0x0034, 0x0035, 0, + 8, 0x32BB, 0x0034, 0x0036, 0, + 8, 0x32BC, 0x0034, 0x0037, 0, + 8, 0x32BD, 0x0034, 0x0038, 0, + 8, 0x32BE, 0x0034, 0x0039, 0, + 8, 0x32BF, 0x0035, 0x0030, 0, + 16, 0x32C0, 0x0031, 0x6708, 0, + 16, 0x32C1, 0x0032, 0x6708, 0, + 16, 0x32C2, 0x0033, 0x6708, 0, + 16, 0x32C3, 0x0034, 0x6708, 0, + 16, 0x32C4, 0x0035, 0x6708, 0, + 16, 0x32C5, 0x0036, 0x6708, 0, + 16, 0x32C6, 0x0037, 0x6708, 0, + 16, 0x32C7, 0x0038, 0x6708, 0, + 16, 0x32C8, 0x0039, 0x6708, 0, + 16, 0x32C9, 0x0031, 0x0030, 0x6708, 0, + 16, 0x32CA, 0x0031, 0x0031, 0x6708, 0, + 16, 0x32CB, 0x0031, 0x0032, 0x6708, 0, + 8, 0x32D0, 0x30A2, 0, + 8, 0x32D1, 0x30A4, 0, + 8, 0x32D2, 0x30A6, 0, + 8, 0x32D3, 0x30A8, 0, + 8, 0x32D4, 0x30AA, 0, + 8, 0x32D5, 0x30AB, 0, + 8, 0x32D6, 0x30AD, 0, + 8, 0x32D7, 0x30AF, 0, + 8, 0x32D8, 0x30B1, 0, + 8, 0x32D9, 0x30B3, 0, + 8, 0x32DA, 0x30B5, 0, + 8, 0x32DB, 0x30B7, 0, + 8, 0x32DC, 0x30B9, 0, + 8, 0x32DD, 0x30BB, 0, + 8, 0x32DE, 0x30BD, 0, + 8, 0x32DF, 0x30BF, 0, + 8, 0x32E0, 0x30C1, 0, + 8, 0x32E1, 0x30C4, 0, + 8, 0x32E2, 0x30C6, 0, + 8, 0x32E3, 0x30C8, 0, + 8, 0x32E4, 0x30CA, 0, + 8, 0x32E5, 0x30CB, 0, + 8, 0x32E6, 0x30CC, 0, + 8, 0x32E7, 0x30CD, 0, + 8, 0x32E8, 0x30CE, 0, + 8, 0x32E9, 0x30CF, 0, + 8, 0x32EA, 0x30D2, 0, + 8, 0x32EB, 0x30D5, 0, + 8, 0x32EC, 0x30D8, 0, + 8, 0x32ED, 0x30DB, 0, + 8, 0x32EE, 0x30DE, 0, + 8, 0x32EF, 0x30DF, 0, + 8, 0x32F0, 0x30E0, 0, + 8, 0x32F1, 0x30E1, 0, + 8, 0x32F2, 0x30E2, 0, + 8, 0x32F3, 0x30E4, 0, + 8, 0x32F4, 0x30E6, 0, + 8, 0x32F5, 0x30E8, 0, + 8, 0x32F6, 0x30E9, 0, + 8, 0x32F7, 0x30EA, 0, + 8, 0x32F8, 0x30EB, 0, + 8, 0x32F9, 0x30EC, 0, + 8, 0x32FA, 0x30ED, 0, + 8, 0x32FB, 0x30EF, 0, + 8, 0x32FC, 0x30F0, 0, + 8, 0x32FD, 0x30F1, 0, + 8, 0x32FE, 0x30F2, 0, + 15, 0x3300, 0x30A2, 0x30D1, 0x30FC, 0x30C8, 0, + 15, 0x3301, 0x30A2, 0x30EB, 0x30D5, 0x30A1, 0, + 15, 0x3302, 0x30A2, 0x30F3, 0x30DA, 0x30A2, 0, + 15, 0x3303, 0x30A2, 0x30FC, 0x30EB, 0, + 15, 0x3304, 0x30A4, 0x30CB, 0x30F3, 0x30B0, 0, + 15, 0x3305, 0x30A4, 0x30F3, 0x30C1, 0, + 15, 0x3306, 0x30A6, 0x30A9, 0x30F3, 0, + 15, 0x3307, 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9, 0, + 15, 0x3308, 0x30A8, 0x30FC, 0x30AB, 0x30FC, 0, + 15, 0x3309, 0x30AA, 0x30F3, 0x30B9, 0, + 15, 0x330A, 0x30AA, 0x30FC, 0x30E0, 0, + 15, 0x330B, 0x30AB, 0x30A4, 0x30EA, 0, + 15, 0x330C, 0x30AB, 0x30E9, 0x30C3, 0x30C8, 0, + 15, 0x330D, 0x30AB, 0x30ED, 0x30EA, 0x30FC, 0, + 15, 0x330E, 0x30AC, 0x30ED, 0x30F3, 0, + 15, 0x330F, 0x30AC, 0x30F3, 0x30DE, 0, + 15, 0x3310, 0x30AE, 0x30AC, 0, + 15, 0x3311, 0x30AE, 0x30CB, 0x30FC, 0, + 15, 0x3312, 0x30AD, 0x30E5, 0x30EA, 0x30FC, 0, + 15, 0x3313, 0x30AE, 0x30EB, 0x30C0, 0x30FC, 0, + 15, 0x3314, 0x30AD, 0x30ED, 0, + 15, 0x3315, 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0, 0, + 15, 0x3316, 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0, + 15, 0x3317, 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8, 0, + 15, 0x3318, 0x30B0, 0x30E9, 0x30E0, 0, + 15, 0x3319, 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3, 0, + 15, 0x331A, 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED, 0, + 15, 0x331B, 0x30AF, 0x30ED, 0x30FC, 0x30CD, 0, + 15, 0x331C, 0x30B1, 0x30FC, 0x30B9, 0, + 15, 0x331D, 0x30B3, 0x30EB, 0x30CA, 0, + 15, 0x331E, 0x30B3, 0x30FC, 0x30DD, 0, + 15, 0x331F, 0x30B5, 0x30A4, 0x30AF, 0x30EB, 0, + 15, 0x3320, 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0, 0, + 15, 0x3321, 0x30B7, 0x30EA, 0x30F3, 0x30B0, 0, + 15, 0x3322, 0x30BB, 0x30F3, 0x30C1, 0, + 15, 0x3323, 0x30BB, 0x30F3, 0x30C8, 0, + 15, 0x3324, 0x30C0, 0x30FC, 0x30B9, 0, + 15, 0x3325, 0x30C7, 0x30B7, 0, + 15, 0x3326, 0x30C9, 0x30EB, 0, + 15, 0x3327, 0x30C8, 0x30F3, 0, + 15, 0x3328, 0x30CA, 0x30CE, 0, + 15, 0x3329, 0x30CE, 0x30C3, 0x30C8, 0, + 15, 0x332A, 0x30CF, 0x30A4, 0x30C4, 0, + 15, 0x332B, 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8, 0, + 15, 0x332C, 0x30D1, 0x30FC, 0x30C4, 0, + 15, 0x332D, 0x30D0, 0x30FC, 0x30EC, 0x30EB, 0, + 15, 0x332E, 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB, 0, + 15, 0x332F, 0x30D4, 0x30AF, 0x30EB, 0, + 15, 0x3330, 0x30D4, 0x30B3, 0, + 15, 0x3331, 0x30D3, 0x30EB, 0, + 15, 0x3332, 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9, 0, + 15, 0x3333, 0x30D5, 0x30A3, 0x30FC, 0x30C8, 0, + 15, 0x3334, 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB, 0, + 15, 0x3335, 0x30D5, 0x30E9, 0x30F3, 0, + 15, 0x3336, 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB, 0, + 15, 0x3337, 0x30DA, 0x30BD, 0, + 15, 0x3338, 0x30DA, 0x30CB, 0x30D2, 0, + 15, 0x3339, 0x30D8, 0x30EB, 0x30C4, 0, + 15, 0x333A, 0x30DA, 0x30F3, 0x30B9, 0, + 15, 0x333B, 0x30DA, 0x30FC, 0x30B8, 0, + 15, 0x333C, 0x30D9, 0x30FC, 0x30BF, 0, + 15, 0x333D, 0x30DD, 0x30A4, 0x30F3, 0x30C8, 0, + 15, 0x333E, 0x30DC, 0x30EB, 0x30C8, 0, + 15, 0x333F, 0x30DB, 0x30F3, 0, + 15, 0x3340, 0x30DD, 0x30F3, 0x30C9, 0, + 15, 0x3341, 0x30DB, 0x30FC, 0x30EB, 0, + 15, 0x3342, 0x30DB, 0x30FC, 0x30F3, 0, + 15, 0x3343, 0x30DE, 0x30A4, 0x30AF, 0x30ED, 0, + 15, 0x3344, 0x30DE, 0x30A4, 0x30EB, 0, + 15, 0x3345, 0x30DE, 0x30C3, 0x30CF, 0, + 15, 0x3346, 0x30DE, 0x30EB, 0x30AF, 0, + 15, 0x3347, 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3, 0, + 15, 0x3348, 0x30DF, 0x30AF, 0x30ED, 0x30F3, 0, + 15, 0x3349, 0x30DF, 0x30EA, 0, + 15, 0x334A, 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB, 0, + 15, 0x334B, 0x30E1, 0x30AC, 0, + 15, 0x334C, 0x30E1, 0x30AC, 0x30C8, 0x30F3, 0, + 15, 0x334D, 0x30E1, 0x30FC, 0x30C8, 0x30EB, 0, + 15, 0x334E, 0x30E4, 0x30FC, 0x30C9, 0, + 15, 0x334F, 0x30E4, 0x30FC, 0x30EB, 0, + 15, 0x3350, 0x30E6, 0x30A2, 0x30F3, 0, + 15, 0x3351, 0x30EA, 0x30C3, 0x30C8, 0x30EB, 0, + 15, 0x3352, 0x30EA, 0x30E9, 0, + 15, 0x3353, 0x30EB, 0x30D4, 0x30FC, 0, + 15, 0x3354, 0x30EB, 0x30FC, 0x30D6, 0x30EB, 0, + 15, 0x3355, 0x30EC, 0x30E0, 0, + 15, 0x3356, 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3, 0, + 15, 0x3357, 0x30EF, 0x30C3, 0x30C8, 0, + 16, 0x3358, 0x0030, 0x70B9, 0, + 16, 0x3359, 0x0031, 0x70B9, 0, + 16, 0x335A, 0x0032, 0x70B9, 0, + 16, 0x335B, 0x0033, 0x70B9, 0, + 16, 0x335C, 0x0034, 0x70B9, 0, + 16, 0x335D, 0x0035, 0x70B9, 0, + 16, 0x335E, 0x0036, 0x70B9, 0, + 16, 0x335F, 0x0037, 0x70B9, 0, + 16, 0x3360, 0x0038, 0x70B9, 0, + 16, 0x3361, 0x0039, 0x70B9, 0, + 16, 0x3362, 0x0031, 0x0030, 0x70B9, 0, + 16, 0x3363, 0x0031, 0x0031, 0x70B9, 0, + 16, 0x3364, 0x0031, 0x0032, 0x70B9, 0, + 16, 0x3365, 0x0031, 0x0033, 0x70B9, 0, + 16, 0x3366, 0x0031, 0x0034, 0x70B9, 0, + 16, 0x3367, 0x0031, 0x0035, 0x70B9, 0, + 16, 0x3368, 0x0031, 0x0036, 0x70B9, 0, + 16, 0x3369, 0x0031, 0x0037, 0x70B9, 0, + 16, 0x336A, 0x0031, 0x0038, 0x70B9, 0, + 16, 0x336B, 0x0031, 0x0039, 0x70B9, 0, + 16, 0x336C, 0x0032, 0x0030, 0x70B9, 0, + 16, 0x336D, 0x0032, 0x0031, 0x70B9, 0, + 16, 0x336E, 0x0032, 0x0032, 0x70B9, 0, + 16, 0x336F, 0x0032, 0x0033, 0x70B9, 0, + 16, 0x3370, 0x0032, 0x0034, 0x70B9, 0, + 15, 0x3371, 0x0068, 0x0050, 0x0061, 0, + 15, 0x3372, 0x0064, 0x0061, 0, + 15, 0x3373, 0x0041, 0x0055, 0, + 15, 0x3374, 0x0062, 0x0061, 0x0072, 0, + 15, 0x3375, 0x006F, 0x0056, 0, + 15, 0x3376, 0x0070, 0x0063, 0, + 15, 0x337B, 0x5E73, 0x6210, 0, + 15, 0x337C, 0x662D, 0x548C, 0, + 15, 0x337D, 0x5927, 0x6B63, 0, + 15, 0x337E, 0x660E, 0x6CBB, 0, + 15, 0x337F, 0x682A, 0x5F0F, 0x4F1A, 0x793E, 0, + 15, 0x3380, 0x0070, 0x0041, 0, + 15, 0x3381, 0x006E, 0x0041, 0, + 15, 0x3382, 0x03BC, 0x0041, 0, + 15, 0x3383, 0x006D, 0x0041, 0, + 15, 0x3384, 0x006B, 0x0041, 0, + 15, 0x3385, 0x004B, 0x0042, 0, + 15, 0x3386, 0x004D, 0x0042, 0, + 15, 0x3387, 0x0047, 0x0042, 0, + 15, 0x3388, 0x0063, 0x0061, 0x006C, 0, + 15, 0x3389, 0x006B, 0x0063, 0x0061, 0x006C, 0, + 15, 0x338A, 0x0070, 0x0046, 0, + 15, 0x338B, 0x006E, 0x0046, 0, + 15, 0x338C, 0x03BC, 0x0046, 0, + 15, 0x338D, 0x03BC, 0x0067, 0, + 15, 0x338E, 0x006D, 0x0067, 0, + 15, 0x338F, 0x006B, 0x0067, 0, + 15, 0x3390, 0x0048, 0x007A, 0, + 15, 0x3391, 0x006B, 0x0048, 0x007A, 0, + 15, 0x3392, 0x004D, 0x0048, 0x007A, 0, + 15, 0x3393, 0x0047, 0x0048, 0x007A, 0, + 15, 0x3394, 0x0054, 0x0048, 0x007A, 0, + 15, 0x3395, 0x03BC, 0x2113, 0, + 15, 0x3396, 0x006D, 0x2113, 0, + 15, 0x3397, 0x0064, 0x2113, 0, + 15, 0x3398, 0x006B, 0x2113, 0, + 15, 0x3399, 0x0066, 0x006D, 0, + 15, 0x339A, 0x006E, 0x006D, 0, + 15, 0x339B, 0x03BC, 0x006D, 0, + 15, 0x339C, 0x006D, 0x006D, 0, + 15, 0x339D, 0x0063, 0x006D, 0, + 15, 0x339E, 0x006B, 0x006D, 0, + 15, 0x339F, 0x006D, 0x006D, 0x00B2, 0, + 15, 0x33A0, 0x0063, 0x006D, 0x00B2, 0, + 15, 0x33A1, 0x006D, 0x00B2, 0, + 15, 0x33A2, 0x006B, 0x006D, 0x00B2, 0, + 15, 0x33A3, 0x006D, 0x006D, 0x00B3, 0, + 15, 0x33A4, 0x0063, 0x006D, 0x00B3, 0, + 15, 0x33A5, 0x006D, 0x00B3, 0, + 15, 0x33A6, 0x006B, 0x006D, 0x00B3, 0, + 15, 0x33A7, 0x006D, 0x2215, 0x0073, 0, + 15, 0x33A8, 0x006D, 0x2215, 0x0073, 0x00B2, 0, + 15, 0x33A9, 0x0050, 0x0061, 0, + 15, 0x33AA, 0x006B, 0x0050, 0x0061, 0, + 15, 0x33AB, 0x004D, 0x0050, 0x0061, 0, + 15, 0x33AC, 0x0047, 0x0050, 0x0061, 0, + 15, 0x33AD, 0x0072, 0x0061, 0x0064, 0, + 15, 0x33AE, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0, + 15, 0x33AF, 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x00B2, 0, + 15, 0x33B0, 0x0070, 0x0073, 0, + 15, 0x33B1, 0x006E, 0x0073, 0, + 15, 0x33B2, 0x03BC, 0x0073, 0, + 15, 0x33B3, 0x006D, 0x0073, 0, + 15, 0x33B4, 0x0070, 0x0056, 0, + 15, 0x33B5, 0x006E, 0x0056, 0, + 15, 0x33B6, 0x03BC, 0x0056, 0, + 15, 0x33B7, 0x006D, 0x0056, 0, + 15, 0x33B8, 0x006B, 0x0056, 0, + 15, 0x33B9, 0x004D, 0x0056, 0, + 15, 0x33BA, 0x0070, 0x0057, 0, + 15, 0x33BB, 0x006E, 0x0057, 0, + 15, 0x33BC, 0x03BC, 0x0057, 0, + 15, 0x33BD, 0x006D, 0x0057, 0, + 15, 0x33BE, 0x006B, 0x0057, 0, + 15, 0x33BF, 0x004D, 0x0057, 0, + 15, 0x33C0, 0x006B, 0x03A9, 0, + 15, 0x33C1, 0x004D, 0x03A9, 0, + 15, 0x33C2, 0x0061, 0x002E, 0x006D, 0x002E, 0, + 15, 0x33C3, 0x0042, 0x0071, 0, + 15, 0x33C4, 0x0063, 0x0063, 0, + 15, 0x33C5, 0x0063, 0x0064, 0, + 15, 0x33C6, 0x0043, 0x2215, 0x006B, 0x0067, 0, + 15, 0x33C7, 0x0043, 0x006F, 0x002E, 0, + 15, 0x33C8, 0x0064, 0x0042, 0, + 15, 0x33C9, 0x0047, 0x0079, 0, + 15, 0x33CA, 0x0068, 0x0061, 0, + 15, 0x33CB, 0x0048, 0x0050, 0, + 15, 0x33CC, 0x0069, 0x006E, 0, + 15, 0x33CD, 0x004B, 0x004B, 0, + 15, 0x33CE, 0x004B, 0x004D, 0, + 15, 0x33CF, 0x006B, 0x0074, 0, + 15, 0x33D0, 0x006C, 0x006D, 0, + 15, 0x33D1, 0x006C, 0x006E, 0, + 15, 0x33D2, 0x006C, 0x006F, 0x0067, 0, + 15, 0x33D3, 0x006C, 0x0078, 0, + 15, 0x33D4, 0x006D, 0x0062, 0, + 15, 0x33D5, 0x006D, 0x0069, 0x006C, 0, + 15, 0x33D6, 0x006D, 0x006F, 0x006C, 0, + 15, 0x33D7, 0x0050, 0x0048, 0, + 15, 0x33D8, 0x0070, 0x002E, 0x006D, 0x002E, 0, + 15, 0x33D9, 0x0050, 0x0050, 0x004D, 0, + 15, 0x33DA, 0x0050, 0x0052, 0, + 15, 0x33DB, 0x0073, 0x0072, 0, + 15, 0x33DC, 0x0053, 0x0076, 0, + 15, 0x33DD, 0x0057, 0x0062, 0, + 16, 0x33E0, 0x0031, 0x65E5, 0, + 16, 0x33E1, 0x0032, 0x65E5, 0, + 16, 0x33E2, 0x0033, 0x65E5, 0, + 16, 0x33E3, 0x0034, 0x65E5, 0, + 16, 0x33E4, 0x0035, 0x65E5, 0, + 16, 0x33E5, 0x0036, 0x65E5, 0, + 16, 0x33E6, 0x0037, 0x65E5, 0, + 16, 0x33E7, 0x0038, 0x65E5, 0, + 16, 0x33E8, 0x0039, 0x65E5, 0, + 16, 0x33E9, 0x0031, 0x0030, 0x65E5, 0, + 16, 0x33EA, 0x0031, 0x0031, 0x65E5, 0, + 16, 0x33EB, 0x0031, 0x0032, 0x65E5, 0, + 16, 0x33EC, 0x0031, 0x0033, 0x65E5, 0, + 16, 0x33ED, 0x0031, 0x0034, 0x65E5, 0, + 16, 0x33EE, 0x0031, 0x0035, 0x65E5, 0, + 16, 0x33EF, 0x0031, 0x0036, 0x65E5, 0, + 16, 0x33F0, 0x0031, 0x0037, 0x65E5, 0, + 16, 0x33F1, 0x0031, 0x0038, 0x65E5, 0, + 16, 0x33F2, 0x0031, 0x0039, 0x65E5, 0, + 16, 0x33F3, 0x0032, 0x0030, 0x65E5, 0, + 16, 0x33F4, 0x0032, 0x0031, 0x65E5, 0, + 16, 0x33F5, 0x0032, 0x0032, 0x65E5, 0, + 16, 0x33F6, 0x0032, 0x0033, 0x65E5, 0, + 16, 0x33F7, 0x0032, 0x0034, 0x65E5, 0, + 16, 0x33F8, 0x0032, 0x0035, 0x65E5, 0, + 16, 0x33F9, 0x0032, 0x0036, 0x65E5, 0, + 16, 0x33FA, 0x0032, 0x0037, 0x65E5, 0, + 16, 0x33FB, 0x0032, 0x0038, 0x65E5, 0, + 16, 0x33FC, 0x0032, 0x0039, 0x65E5, 0, + 16, 0x33FD, 0x0033, 0x0030, 0x65E5, 0, + 16, 0x33FE, 0x0033, 0x0031, 0x65E5, 0, + 1, 0xF900, 0x8C48, 0, + 1, 0xF901, 0x66F4, 0, + 1, 0xF902, 0x8ECA, 0, + 1, 0xF903, 0x8CC8, 0, + 1, 0xF904, 0x6ED1, 0, + 1, 0xF905, 0x4E32, 0, + 1, 0xF906, 0x53E5, 0, + 1, 0xF907, 0x9F9C, 0, + 1, 0xF908, 0x9F9C, 0, + 1, 0xF909, 0x5951, 0, + 1, 0xF90A, 0x91D1, 0, + 1, 0xF90B, 0x5587, 0, + 1, 0xF90C, 0x5948, 0, + 1, 0xF90D, 0x61F6, 0, + 1, 0xF90E, 0x7669, 0, + 1, 0xF90F, 0x7F85, 0, + 1, 0xF910, 0x863F, 0, + 1, 0xF911, 0x87BA, 0, + 1, 0xF912, 0x88F8, 0, + 1, 0xF913, 0x908F, 0, + 1, 0xF914, 0x6A02, 0, + 1, 0xF915, 0x6D1B, 0, + 1, 0xF916, 0x70D9, 0, + 1, 0xF917, 0x73DE, 0, + 1, 0xF918, 0x843D, 0, + 1, 0xF919, 0x916A, 0, + 1, 0xF91A, 0x99F1, 0, + 1, 0xF91B, 0x4E82, 0, + 1, 0xF91C, 0x5375, 0, + 1, 0xF91D, 0x6B04, 0, + 1, 0xF91E, 0x721B, 0, + 1, 0xF91F, 0x862D, 0, + 1, 0xF920, 0x9E1E, 0, + 1, 0xF921, 0x5D50, 0, + 1, 0xF922, 0x6FEB, 0, + 1, 0xF923, 0x85CD, 0, + 1, 0xF924, 0x8964, 0, + 1, 0xF925, 0x62C9, 0, + 1, 0xF926, 0x81D8, 0, + 1, 0xF927, 0x881F, 0, + 1, 0xF928, 0x5ECA, 0, + 1, 0xF929, 0x6717, 0, + 1, 0xF92A, 0x6D6A, 0, + 1, 0xF92B, 0x72FC, 0, + 1, 0xF92C, 0x90CE, 0, + 1, 0xF92D, 0x4F86, 0, + 1, 0xF92E, 0x51B7, 0, + 1, 0xF92F, 0x52DE, 0, + 1, 0xF930, 0x64C4, 0, + 1, 0xF931, 0x6AD3, 0, + 1, 0xF932, 0x7210, 0, + 1, 0xF933, 0x76E7, 0, + 1, 0xF934, 0x8001, 0, + 1, 0xF935, 0x8606, 0, + 1, 0xF936, 0x865C, 0, + 1, 0xF937, 0x8DEF, 0, + 1, 0xF938, 0x9732, 0, + 1, 0xF939, 0x9B6F, 0, + 1, 0xF93A, 0x9DFA, 0, + 1, 0xF93B, 0x788C, 0, + 1, 0xF93C, 0x797F, 0, + 1, 0xF93D, 0x7DA0, 0, + 1, 0xF93E, 0x83C9, 0, + 1, 0xF93F, 0x9304, 0, + 1, 0xF940, 0x9E7F, 0, + 1, 0xF941, 0x8AD6, 0, + 1, 0xF942, 0x58DF, 0, + 1, 0xF943, 0x5F04, 0, + 1, 0xF944, 0x7C60, 0, + 1, 0xF945, 0x807E, 0, + 1, 0xF946, 0x7262, 0, + 1, 0xF947, 0x78CA, 0, + 1, 0xF948, 0x8CC2, 0, + 1, 0xF949, 0x96F7, 0, + 1, 0xF94A, 0x58D8, 0, + 1, 0xF94B, 0x5C62, 0, + 1, 0xF94C, 0x6A13, 0, + 1, 0xF94D, 0x6DDA, 0, + 1, 0xF94E, 0x6F0F, 0, + 1, 0xF94F, 0x7D2F, 0, + 1, 0xF950, 0x7E37, 0, + 1, 0xF951, 0x964B, 0, + 1, 0xF952, 0x52D2, 0, + 1, 0xF953, 0x808B, 0, + 1, 0xF954, 0x51DC, 0, + 1, 0xF955, 0x51CC, 0, + 1, 0xF956, 0x7A1C, 0, + 1, 0xF957, 0x7DBE, 0, + 1, 0xF958, 0x83F1, 0, + 1, 0xF959, 0x9675, 0, + 1, 0xF95A, 0x8B80, 0, + 1, 0xF95B, 0x62CF, 0, + 1, 0xF95C, 0x6A02, 0, + 1, 0xF95D, 0x8AFE, 0, + 1, 0xF95E, 0x4E39, 0, + 1, 0xF95F, 0x5BE7, 0, + 1, 0xF960, 0x6012, 0, + 1, 0xF961, 0x7387, 0, + 1, 0xF962, 0x7570, 0, + 1, 0xF963, 0x5317, 0, + 1, 0xF964, 0x78FB, 0, + 1, 0xF965, 0x4FBF, 0, + 1, 0xF966, 0x5FA9, 0, + 1, 0xF967, 0x4E0D, 0, + 1, 0xF968, 0x6CCC, 0, + 1, 0xF969, 0x6578, 0, + 1, 0xF96A, 0x7D22, 0, + 1, 0xF96B, 0x53C3, 0, + 1, 0xF96C, 0x585E, 0, + 1, 0xF96D, 0x7701, 0, + 1, 0xF96E, 0x8449, 0, + 1, 0xF96F, 0x8AAA, 0, + 1, 0xF970, 0x6BBA, 0, + 1, 0xF971, 0x8FB0, 0, + 1, 0xF972, 0x6C88, 0, + 1, 0xF973, 0x62FE, 0, + 1, 0xF974, 0x82E5, 0, + 1, 0xF975, 0x63A0, 0, + 1, 0xF976, 0x7565, 0, + 1, 0xF977, 0x4EAE, 0, + 1, 0xF978, 0x5169, 0, + 1, 0xF979, 0x51C9, 0, + 1, 0xF97A, 0x6881, 0, + 1, 0xF97B, 0x7CE7, 0, + 1, 0xF97C, 0x826F, 0, + 1, 0xF97D, 0x8AD2, 0, + 1, 0xF97E, 0x91CF, 0, + 1, 0xF97F, 0x52F5, 0, + 1, 0xF980, 0x5442, 0, + 1, 0xF981, 0x5973, 0, + 1, 0xF982, 0x5EEC, 0, + 1, 0xF983, 0x65C5, 0, + 1, 0xF984, 0x6FFE, 0, + 1, 0xF985, 0x792A, 0, + 1, 0xF986, 0x95AD, 0, + 1, 0xF987, 0x9A6A, 0, + 1, 0xF988, 0x9E97, 0, + 1, 0xF989, 0x9ECE, 0, + 1, 0xF98A, 0x529B, 0, + 1, 0xF98B, 0x66C6, 0, + 1, 0xF98C, 0x6B77, 0, + 1, 0xF98D, 0x8F62, 0, + 1, 0xF98E, 0x5E74, 0, + 1, 0xF98F, 0x6190, 0, + 1, 0xF990, 0x6200, 0, + 1, 0xF991, 0x649A, 0, + 1, 0xF992, 0x6F23, 0, + 1, 0xF993, 0x7149, 0, + 1, 0xF994, 0x7489, 0, + 1, 0xF995, 0x79CA, 0, + 1, 0xF996, 0x7DF4, 0, + 1, 0xF997, 0x806F, 0, + 1, 0xF998, 0x8F26, 0, + 1, 0xF999, 0x84EE, 0, + 1, 0xF99A, 0x9023, 0, + 1, 0xF99B, 0x934A, 0, + 1, 0xF99C, 0x5217, 0, + 1, 0xF99D, 0x52A3, 0, + 1, 0xF99E, 0x54BD, 0, + 1, 0xF99F, 0x70C8, 0, + 1, 0xF9A0, 0x88C2, 0, + 1, 0xF9A1, 0x8AAA, 0, + 1, 0xF9A2, 0x5EC9, 0, + 1, 0xF9A3, 0x5FF5, 0, + 1, 0xF9A4, 0x637B, 0, + 1, 0xF9A5, 0x6BAE, 0, + 1, 0xF9A6, 0x7C3E, 0, + 1, 0xF9A7, 0x7375, 0, + 1, 0xF9A8, 0x4EE4, 0, + 1, 0xF9A9, 0x56F9, 0, + 1, 0xF9AA, 0x5BE7, 0, + 1, 0xF9AB, 0x5DBA, 0, + 1, 0xF9AC, 0x601C, 0, + 1, 0xF9AD, 0x73B2, 0, + 1, 0xF9AE, 0x7469, 0, + 1, 0xF9AF, 0x7F9A, 0, + 1, 0xF9B0, 0x8046, 0, + 1, 0xF9B1, 0x9234, 0, + 1, 0xF9B2, 0x96F6, 0, + 1, 0xF9B3, 0x9748, 0, + 1, 0xF9B4, 0x9818, 0, + 1, 0xF9B5, 0x4F8B, 0, + 1, 0xF9B6, 0x79AE, 0, + 1, 0xF9B7, 0x91B4, 0, + 1, 0xF9B8, 0x96B8, 0, + 1, 0xF9B9, 0x60E1, 0, + 1, 0xF9BA, 0x4E86, 0, + 1, 0xF9BB, 0x50DA, 0, + 1, 0xF9BC, 0x5BEE, 0, + 1, 0xF9BD, 0x5C3F, 0, + 1, 0xF9BE, 0x6599, 0, + 1, 0xF9BF, 0x6A02, 0, + 1, 0xF9C0, 0x71CE, 0, + 1, 0xF9C1, 0x7642, 0, + 1, 0xF9C2, 0x84FC, 0, + 1, 0xF9C3, 0x907C, 0, + 1, 0xF9C4, 0x9F8D, 0, + 1, 0xF9C5, 0x6688, 0, + 1, 0xF9C6, 0x962E, 0, + 1, 0xF9C7, 0x5289, 0, + 1, 0xF9C8, 0x677B, 0, + 1, 0xF9C9, 0x67F3, 0, + 1, 0xF9CA, 0x6D41, 0, + 1, 0xF9CB, 0x6E9C, 0, + 1, 0xF9CC, 0x7409, 0, + 1, 0xF9CD, 0x7559, 0, + 1, 0xF9CE, 0x786B, 0, + 1, 0xF9CF, 0x7D10, 0, + 1, 0xF9D0, 0x985E, 0, + 1, 0xF9D1, 0x516D, 0, + 1, 0xF9D2, 0x622E, 0, + 1, 0xF9D3, 0x9678, 0, + 1, 0xF9D4, 0x502B, 0, + 1, 0xF9D5, 0x5D19, 0, + 1, 0xF9D6, 0x6DEA, 0, + 1, 0xF9D7, 0x8F2A, 0, + 1, 0xF9D8, 0x5F8B, 0, + 1, 0xF9D9, 0x6144, 0, + 1, 0xF9DA, 0x6817, 0, + 1, 0xF9DB, 0x7387, 0, + 1, 0xF9DC, 0x9686, 0, + 1, 0xF9DD, 0x5229, 0, + 1, 0xF9DE, 0x540F, 0, + 1, 0xF9DF, 0x5C65, 0, + 1, 0xF9E0, 0x6613, 0, + 1, 0xF9E1, 0x674E, 0, + 1, 0xF9E2, 0x68A8, 0, + 1, 0xF9E3, 0x6CE5, 0, + 1, 0xF9E4, 0x7406, 0, + 1, 0xF9E5, 0x75E2, 0, + 1, 0xF9E6, 0x7F79, 0, + 1, 0xF9E7, 0x88CF, 0, + 1, 0xF9E8, 0x88E1, 0, + 1, 0xF9E9, 0x91CC, 0, + 1, 0xF9EA, 0x96E2, 0, + 1, 0xF9EB, 0x533F, 0, + 1, 0xF9EC, 0x6EBA, 0, + 1, 0xF9ED, 0x541D, 0, + 1, 0xF9EE, 0x71D0, 0, + 1, 0xF9EF, 0x7498, 0, + 1, 0xF9F0, 0x85FA, 0, + 1, 0xF9F1, 0x96A3, 0, + 1, 0xF9F2, 0x9C57, 0, + 1, 0xF9F3, 0x9E9F, 0, + 1, 0xF9F4, 0x6797, 0, + 1, 0xF9F5, 0x6DCB, 0, + 1, 0xF9F6, 0x81E8, 0, + 1, 0xF9F7, 0x7ACB, 0, + 1, 0xF9F8, 0x7B20, 0, + 1, 0xF9F9, 0x7C92, 0, + 1, 0xF9FA, 0x72C0, 0, + 1, 0xF9FB, 0x7099, 0, + 1, 0xF9FC, 0x8B58, 0, + 1, 0xF9FD, 0x4EC0, 0, + 1, 0xF9FE, 0x8336, 0, + 1, 0xF9FF, 0x523A, 0, + 1, 0xFA00, 0x5207, 0, + 1, 0xFA01, 0x5EA6, 0, + 1, 0xFA02, 0x62D3, 0, + 1, 0xFA03, 0x7CD6, 0, + 1, 0xFA04, 0x5B85, 0, + 1, 0xFA05, 0x6D1E, 0, + 1, 0xFA06, 0x66B4, 0, + 1, 0xFA07, 0x8F3B, 0, + 1, 0xFA08, 0x884C, 0, + 1, 0xFA09, 0x964D, 0, + 1, 0xFA0A, 0x898B, 0, + 1, 0xFA0B, 0x5ED3, 0, + 1, 0xFA0C, 0x5140, 0, + 1, 0xFA0D, 0x55C0, 0, + 1, 0xFA10, 0x585A, 0, + 1, 0xFA12, 0x6674, 0, + 1, 0xFA15, 0x51DE, 0, + 1, 0xFA16, 0x732A, 0, + 1, 0xFA17, 0x76CA, 0, + 1, 0xFA18, 0x793C, 0, + 1, 0xFA19, 0x795E, 0, + 1, 0xFA1A, 0x7965, 0, + 1, 0xFA1B, 0x798F, 0, + 1, 0xFA1C, 0x9756, 0, + 1, 0xFA1D, 0x7CBE, 0, + 1, 0xFA1E, 0x7FBD, 0, + 1, 0xFA20, 0x8612, 0, + 1, 0xFA22, 0x8AF8, 0, + 1, 0xFA25, 0x9038, 0, + 1, 0xFA26, 0x90FD, 0, + 1, 0xFA2A, 0x98EF, 0, + 1, 0xFA2B, 0x98FC, 0, + 1, 0xFA2C, 0x9928, 0, + 1, 0xFA2D, 0x9DB4, 0, + 1, 0xFA30, 0x4FAE, 0, + 1, 0xFA31, 0x50E7, 0, + 1, 0xFA32, 0x514D, 0, + 1, 0xFA33, 0x52C9, 0, + 1, 0xFA34, 0x52E4, 0, + 1, 0xFA35, 0x5351, 0, + 1, 0xFA36, 0x559D, 0, + 1, 0xFA37, 0x5606, 0, + 1, 0xFA38, 0x5668, 0, + 1, 0xFA39, 0x5840, 0, + 1, 0xFA3A, 0x58A8, 0, + 1, 0xFA3B, 0x5C64, 0, + 1, 0xFA3C, 0x5C6E, 0, + 1, 0xFA3D, 0x6094, 0, + 1, 0xFA3E, 0x6168, 0, + 1, 0xFA3F, 0x618E, 0, + 1, 0xFA40, 0x61F2, 0, + 1, 0xFA41, 0x654F, 0, + 1, 0xFA42, 0x65E2, 0, + 1, 0xFA43, 0x6691, 0, + 1, 0xFA44, 0x6885, 0, + 1, 0xFA45, 0x6D77, 0, + 1, 0xFA46, 0x6E1A, 0, + 1, 0xFA47, 0x6F22, 0, + 1, 0xFA48, 0x716E, 0, + 1, 0xFA49, 0x722B, 0, + 1, 0xFA4A, 0x7422, 0, + 1, 0xFA4B, 0x7891, 0, + 1, 0xFA4C, 0x793E, 0, + 1, 0xFA4D, 0x7949, 0, + 1, 0xFA4E, 0x7948, 0, + 1, 0xFA4F, 0x7950, 0, + 1, 0xFA50, 0x7956, 0, + 1, 0xFA51, 0x795D, 0, + 1, 0xFA52, 0x798D, 0, + 1, 0xFA53, 0x798E, 0, + 1, 0xFA54, 0x7A40, 0, + 1, 0xFA55, 0x7A81, 0, + 1, 0xFA56, 0x7BC0, 0, + 1, 0xFA57, 0x7DF4, 0, + 1, 0xFA58, 0x7E09, 0, + 1, 0xFA59, 0x7E41, 0, + 1, 0xFA5A, 0x7F72, 0, + 1, 0xFA5B, 0x8005, 0, + 1, 0xFA5C, 0x81ED, 0, + 1, 0xFA5D, 0x8279, 0, + 1, 0xFA5E, 0x8279, 0, + 1, 0xFA5F, 0x8457, 0, + 1, 0xFA60, 0x8910, 0, + 1, 0xFA61, 0x8996, 0, + 1, 0xFA62, 0x8B01, 0, + 1, 0xFA63, 0x8B39, 0, + 1, 0xFA64, 0x8CD3, 0, + 1, 0xFA65, 0x8D08, 0, + 1, 0xFA66, 0x8FB6, 0, + 1, 0xFA67, 0x9038, 0, + 1, 0xFA68, 0x96E3, 0, + 1, 0xFA69, 0x97FF, 0, + 1, 0xFA6A, 0x983B, 0, + 16, 0xFB00, 0x0066, 0x0066, 0, + 16, 0xFB01, 0x0066, 0x0069, 0, + 16, 0xFB02, 0x0066, 0x006C, 0, + 16, 0xFB03, 0x0066, 0x0066, 0x0069, 0, + 16, 0xFB04, 0x0066, 0x0066, 0x006C, 0, + 16, 0xFB05, 0x017F, 0x0074, 0, + 16, 0xFB06, 0x0073, 0x0074, 0, + 16, 0xFB13, 0x0574, 0x0576, 0, + 16, 0xFB14, 0x0574, 0x0565, 0, + 16, 0xFB15, 0x0574, 0x056B, 0, + 16, 0xFB16, 0x057E, 0x0576, 0, + 16, 0xFB17, 0x0574, 0x056D, 0, + 1, 0xFB1D, 0x05D9, 0x05B4, 0, + 1, 0xFB1F, 0x05F2, 0x05B7, 0, + 2, 0xFB20, 0x05E2, 0, + 2, 0xFB21, 0x05D0, 0, + 2, 0xFB22, 0x05D3, 0, + 2, 0xFB23, 0x05D4, 0, + 2, 0xFB24, 0x05DB, 0, + 2, 0xFB25, 0x05DC, 0, + 2, 0xFB26, 0x05DD, 0, + 2, 0xFB27, 0x05E8, 0, + 2, 0xFB28, 0x05EA, 0, + 2, 0xFB29, 0x002B, 0, + 1, 0xFB2A, 0x05E9, 0x05C1, 0, + 1, 0xFB2B, 0x05E9, 0x05C2, 0, + 1, 0xFB2C, 0xFB49, 0x05C1, 0, + 1, 0xFB2D, 0xFB49, 0x05C2, 0, + 1, 0xFB2E, 0x05D0, 0x05B7, 0, + 1, 0xFB2F, 0x05D0, 0x05B8, 0, + 1, 0xFB30, 0x05D0, 0x05BC, 0, + 1, 0xFB31, 0x05D1, 0x05BC, 0, + 1, 0xFB32, 0x05D2, 0x05BC, 0, + 1, 0xFB33, 0x05D3, 0x05BC, 0, + 1, 0xFB34, 0x05D4, 0x05BC, 0, + 1, 0xFB35, 0x05D5, 0x05BC, 0, + 1, 0xFB36, 0x05D6, 0x05BC, 0, + 1, 0xFB38, 0x05D8, 0x05BC, 0, + 1, 0xFB39, 0x05D9, 0x05BC, 0, + 1, 0xFB3A, 0x05DA, 0x05BC, 0, + 1, 0xFB3B, 0x05DB, 0x05BC, 0, + 1, 0xFB3C, 0x05DC, 0x05BC, 0, + 1, 0xFB3E, 0x05DE, 0x05BC, 0, + 1, 0xFB40, 0x05E0, 0x05BC, 0, + 1, 0xFB41, 0x05E1, 0x05BC, 0, + 1, 0xFB43, 0x05E3, 0x05BC, 0, + 1, 0xFB44, 0x05E4, 0x05BC, 0, + 1, 0xFB46, 0x05E6, 0x05BC, 0, + 1, 0xFB47, 0x05E7, 0x05BC, 0, + 1, 0xFB48, 0x05E8, 0x05BC, 0, + 1, 0xFB49, 0x05E9, 0x05BC, 0, + 1, 0xFB4A, 0x05EA, 0x05BC, 0, + 1, 0xFB4B, 0x05D5, 0x05B9, 0, + 1, 0xFB4C, 0x05D1, 0x05BF, 0, + 1, 0xFB4D, 0x05DB, 0x05BF, 0, + 1, 0xFB4E, 0x05E4, 0x05BF, 0, + 16, 0xFB4F, 0x05D0, 0x05DC, 0, + 7, 0xFB50, 0x0671, 0, + 6, 0xFB51, 0x0671, 0, + 7, 0xFB52, 0x067B, 0, + 6, 0xFB53, 0x067B, 0, + 4, 0xFB54, 0x067B, 0, + 5, 0xFB55, 0x067B, 0, + 7, 0xFB56, 0x067E, 0, + 6, 0xFB57, 0x067E, 0, + 4, 0xFB58, 0x067E, 0, + 5, 0xFB59, 0x067E, 0, + 7, 0xFB5A, 0x0680, 0, + 6, 0xFB5B, 0x0680, 0, + 4, 0xFB5C, 0x0680, 0, + 5, 0xFB5D, 0x0680, 0, + 7, 0xFB5E, 0x067A, 0, + 6, 0xFB5F, 0x067A, 0, + 4, 0xFB60, 0x067A, 0, + 5, 0xFB61, 0x067A, 0, + 7, 0xFB62, 0x067F, 0, + 6, 0xFB63, 0x067F, 0, + 4, 0xFB64, 0x067F, 0, + 5, 0xFB65, 0x067F, 0, + 7, 0xFB66, 0x0679, 0, + 6, 0xFB67, 0x0679, 0, + 4, 0xFB68, 0x0679, 0, + 5, 0xFB69, 0x0679, 0, + 7, 0xFB6A, 0x06A4, 0, + 6, 0xFB6B, 0x06A4, 0, + 4, 0xFB6C, 0x06A4, 0, + 5, 0xFB6D, 0x06A4, 0, + 7, 0xFB6E, 0x06A6, 0, + 6, 0xFB6F, 0x06A6, 0, + 4, 0xFB70, 0x06A6, 0, + 5, 0xFB71, 0x06A6, 0, + 7, 0xFB72, 0x0684, 0, + 6, 0xFB73, 0x0684, 0, + 4, 0xFB74, 0x0684, 0, + 5, 0xFB75, 0x0684, 0, + 7, 0xFB76, 0x0683, 0, + 6, 0xFB77, 0x0683, 0, + 4, 0xFB78, 0x0683, 0, + 5, 0xFB79, 0x0683, 0, + 7, 0xFB7A, 0x0686, 0, + 6, 0xFB7B, 0x0686, 0, + 4, 0xFB7C, 0x0686, 0, + 5, 0xFB7D, 0x0686, 0, + 7, 0xFB7E, 0x0687, 0, + 6, 0xFB7F, 0x0687, 0, + 4, 0xFB80, 0x0687, 0, + 5, 0xFB81, 0x0687, 0, + 7, 0xFB82, 0x068D, 0, + 6, 0xFB83, 0x068D, 0, + 7, 0xFB84, 0x068C, 0, + 6, 0xFB85, 0x068C, 0, + 7, 0xFB86, 0x068E, 0, + 6, 0xFB87, 0x068E, 0, + 7, 0xFB88, 0x0688, 0, + 6, 0xFB89, 0x0688, 0, + 7, 0xFB8A, 0x0698, 0, + 6, 0xFB8B, 0x0698, 0, + 7, 0xFB8C, 0x0691, 0, + 6, 0xFB8D, 0x0691, 0, + 7, 0xFB8E, 0x06A9, 0, + 6, 0xFB8F, 0x06A9, 0, + 4, 0xFB90, 0x06A9, 0, + 5, 0xFB91, 0x06A9, 0, + 7, 0xFB92, 0x06AF, 0, + 6, 0xFB93, 0x06AF, 0, + 4, 0xFB94, 0x06AF, 0, + 5, 0xFB95, 0x06AF, 0, + 7, 0xFB96, 0x06B3, 0, + 6, 0xFB97, 0x06B3, 0, + 4, 0xFB98, 0x06B3, 0, + 5, 0xFB99, 0x06B3, 0, + 7, 0xFB9A, 0x06B1, 0, + 6, 0xFB9B, 0x06B1, 0, + 4, 0xFB9C, 0x06B1, 0, + 5, 0xFB9D, 0x06B1, 0, + 7, 0xFB9E, 0x06BA, 0, + 6, 0xFB9F, 0x06BA, 0, + 7, 0xFBA0, 0x06BB, 0, + 6, 0xFBA1, 0x06BB, 0, + 4, 0xFBA2, 0x06BB, 0, + 5, 0xFBA3, 0x06BB, 0, + 7, 0xFBA4, 0x06C0, 0, + 6, 0xFBA5, 0x06C0, 0, + 7, 0xFBA6, 0x06C1, 0, + 6, 0xFBA7, 0x06C1, 0, + 4, 0xFBA8, 0x06C1, 0, + 5, 0xFBA9, 0x06C1, 0, + 7, 0xFBAA, 0x06BE, 0, + 6, 0xFBAB, 0x06BE, 0, + 4, 0xFBAC, 0x06BE, 0, + 5, 0xFBAD, 0x06BE, 0, + 7, 0xFBAE, 0x06D2, 0, + 6, 0xFBAF, 0x06D2, 0, + 7, 0xFBB0, 0x06D3, 0, + 6, 0xFBB1, 0x06D3, 0, + 7, 0xFBD3, 0x06AD, 0, + 6, 0xFBD4, 0x06AD, 0, + 4, 0xFBD5, 0x06AD, 0, + 5, 0xFBD6, 0x06AD, 0, + 7, 0xFBD7, 0x06C7, 0, + 6, 0xFBD8, 0x06C7, 0, + 7, 0xFBD9, 0x06C6, 0, + 6, 0xFBDA, 0x06C6, 0, + 7, 0xFBDB, 0x06C8, 0, + 6, 0xFBDC, 0x06C8, 0, + 7, 0xFBDD, 0x0677, 0, + 7, 0xFBDE, 0x06CB, 0, + 6, 0xFBDF, 0x06CB, 0, + 7, 0xFBE0, 0x06C5, 0, + 6, 0xFBE1, 0x06C5, 0, + 7, 0xFBE2, 0x06C9, 0, + 6, 0xFBE3, 0x06C9, 0, + 7, 0xFBE4, 0x06D0, 0, + 6, 0xFBE5, 0x06D0, 0, + 4, 0xFBE6, 0x06D0, 0, + 5, 0xFBE7, 0x06D0, 0, + 4, 0xFBE8, 0x0649, 0, + 5, 0xFBE9, 0x0649, 0, + 7, 0xFBEA, 0x0626, 0x0627, 0, + 6, 0xFBEB, 0x0626, 0x0627, 0, + 7, 0xFBEC, 0x0626, 0x06D5, 0, + 6, 0xFBED, 0x0626, 0x06D5, 0, + 7, 0xFBEE, 0x0626, 0x0648, 0, + 6, 0xFBEF, 0x0626, 0x0648, 0, + 7, 0xFBF0, 0x0626, 0x06C7, 0, + 6, 0xFBF1, 0x0626, 0x06C7, 0, + 7, 0xFBF2, 0x0626, 0x06C6, 0, + 6, 0xFBF3, 0x0626, 0x06C6, 0, + 7, 0xFBF4, 0x0626, 0x06C8, 0, + 6, 0xFBF5, 0x0626, 0x06C8, 0, + 7, 0xFBF6, 0x0626, 0x06D0, 0, + 6, 0xFBF7, 0x0626, 0x06D0, 0, + 4, 0xFBF8, 0x0626, 0x06D0, 0, + 7, 0xFBF9, 0x0626, 0x0649, 0, + 6, 0xFBFA, 0x0626, 0x0649, 0, + 4, 0xFBFB, 0x0626, 0x0649, 0, + 7, 0xFBFC, 0x06CC, 0, + 6, 0xFBFD, 0x06CC, 0, + 4, 0xFBFE, 0x06CC, 0, + 5, 0xFBFF, 0x06CC, 0, + 7, 0xFC00, 0x0626, 0x062C, 0, + 7, 0xFC01, 0x0626, 0x062D, 0, + 7, 0xFC02, 0x0626, 0x0645, 0, + 7, 0xFC03, 0x0626, 0x0649, 0, + 7, 0xFC04, 0x0626, 0x064A, 0, + 7, 0xFC05, 0x0628, 0x062C, 0, + 7, 0xFC06, 0x0628, 0x062D, 0, + 7, 0xFC07, 0x0628, 0x062E, 0, + 7, 0xFC08, 0x0628, 0x0645, 0, + 7, 0xFC09, 0x0628, 0x0649, 0, + 7, 0xFC0A, 0x0628, 0x064A, 0, + 7, 0xFC0B, 0x062A, 0x062C, 0, + 7, 0xFC0C, 0x062A, 0x062D, 0, + 7, 0xFC0D, 0x062A, 0x062E, 0, + 7, 0xFC0E, 0x062A, 0x0645, 0, + 7, 0xFC0F, 0x062A, 0x0649, 0, + 7, 0xFC10, 0x062A, 0x064A, 0, + 7, 0xFC11, 0x062B, 0x062C, 0, + 7, 0xFC12, 0x062B, 0x0645, 0, + 7, 0xFC13, 0x062B, 0x0649, 0, + 7, 0xFC14, 0x062B, 0x064A, 0, + 7, 0xFC15, 0x062C, 0x062D, 0, + 7, 0xFC16, 0x062C, 0x0645, 0, + 7, 0xFC17, 0x062D, 0x062C, 0, + 7, 0xFC18, 0x062D, 0x0645, 0, + 7, 0xFC19, 0x062E, 0x062C, 0, + 7, 0xFC1A, 0x062E, 0x062D, 0, + 7, 0xFC1B, 0x062E, 0x0645, 0, + 7, 0xFC1C, 0x0633, 0x062C, 0, + 7, 0xFC1D, 0x0633, 0x062D, 0, + 7, 0xFC1E, 0x0633, 0x062E, 0, + 7, 0xFC1F, 0x0633, 0x0645, 0, + 7, 0xFC20, 0x0635, 0x062D, 0, + 7, 0xFC21, 0x0635, 0x0645, 0, + 7, 0xFC22, 0x0636, 0x062C, 0, + 7, 0xFC23, 0x0636, 0x062D, 0, + 7, 0xFC24, 0x0636, 0x062E, 0, + 7, 0xFC25, 0x0636, 0x0645, 0, + 7, 0xFC26, 0x0637, 0x062D, 0, + 7, 0xFC27, 0x0637, 0x0645, 0, + 7, 0xFC28, 0x0638, 0x0645, 0, + 7, 0xFC29, 0x0639, 0x062C, 0, + 7, 0xFC2A, 0x0639, 0x0645, 0, + 7, 0xFC2B, 0x063A, 0x062C, 0, + 7, 0xFC2C, 0x063A, 0x0645, 0, + 7, 0xFC2D, 0x0641, 0x062C, 0, + 7, 0xFC2E, 0x0641, 0x062D, 0, + 7, 0xFC2F, 0x0641, 0x062E, 0, + 7, 0xFC30, 0x0641, 0x0645, 0, + 7, 0xFC31, 0x0641, 0x0649, 0, + 7, 0xFC32, 0x0641, 0x064A, 0, + 7, 0xFC33, 0x0642, 0x062D, 0, + 7, 0xFC34, 0x0642, 0x0645, 0, + 7, 0xFC35, 0x0642, 0x0649, 0, + 7, 0xFC36, 0x0642, 0x064A, 0, + 7, 0xFC37, 0x0643, 0x0627, 0, + 7, 0xFC38, 0x0643, 0x062C, 0, + 7, 0xFC39, 0x0643, 0x062D, 0, + 7, 0xFC3A, 0x0643, 0x062E, 0, + 7, 0xFC3B, 0x0643, 0x0644, 0, + 7, 0xFC3C, 0x0643, 0x0645, 0, + 7, 0xFC3D, 0x0643, 0x0649, 0, + 7, 0xFC3E, 0x0643, 0x064A, 0, + 7, 0xFC3F, 0x0644, 0x062C, 0, + 7, 0xFC40, 0x0644, 0x062D, 0, + 7, 0xFC41, 0x0644, 0x062E, 0, + 7, 0xFC42, 0x0644, 0x0645, 0, + 7, 0xFC43, 0x0644, 0x0649, 0, + 7, 0xFC44, 0x0644, 0x064A, 0, + 7, 0xFC45, 0x0645, 0x062C, 0, + 7, 0xFC46, 0x0645, 0x062D, 0, + 7, 0xFC47, 0x0645, 0x062E, 0, + 7, 0xFC48, 0x0645, 0x0645, 0, + 7, 0xFC49, 0x0645, 0x0649, 0, + 7, 0xFC4A, 0x0645, 0x064A, 0, + 7, 0xFC4B, 0x0646, 0x062C, 0, + 7, 0xFC4C, 0x0646, 0x062D, 0, + 7, 0xFC4D, 0x0646, 0x062E, 0, + 7, 0xFC4E, 0x0646, 0x0645, 0, + 7, 0xFC4F, 0x0646, 0x0649, 0, + 7, 0xFC50, 0x0646, 0x064A, 0, + 7, 0xFC51, 0x0647, 0x062C, 0, + 7, 0xFC52, 0x0647, 0x0645, 0, + 7, 0xFC53, 0x0647, 0x0649, 0, + 7, 0xFC54, 0x0647, 0x064A, 0, + 7, 0xFC55, 0x064A, 0x062C, 0, + 7, 0xFC56, 0x064A, 0x062D, 0, + 7, 0xFC57, 0x064A, 0x062E, 0, + 7, 0xFC58, 0x064A, 0x0645, 0, + 7, 0xFC59, 0x064A, 0x0649, 0, + 7, 0xFC5A, 0x064A, 0x064A, 0, + 7, 0xFC5B, 0x0630, 0x0670, 0, + 7, 0xFC5C, 0x0631, 0x0670, 0, + 7, 0xFC5D, 0x0649, 0x0670, 0, + 7, 0xFC5E, 0x0020, 0x064C, 0x0651, 0, + 7, 0xFC5F, 0x0020, 0x064D, 0x0651, 0, + 7, 0xFC60, 0x0020, 0x064E, 0x0651, 0, + 7, 0xFC61, 0x0020, 0x064F, 0x0651, 0, + 7, 0xFC62, 0x0020, 0x0650, 0x0651, 0, + 7, 0xFC63, 0x0020, 0x0651, 0x0670, 0, + 6, 0xFC64, 0x0626, 0x0631, 0, + 6, 0xFC65, 0x0626, 0x0632, 0, + 6, 0xFC66, 0x0626, 0x0645, 0, + 6, 0xFC67, 0x0626, 0x0646, 0, + 6, 0xFC68, 0x0626, 0x0649, 0, + 6, 0xFC69, 0x0626, 0x064A, 0, + 6, 0xFC6A, 0x0628, 0x0631, 0, + 6, 0xFC6B, 0x0628, 0x0632, 0, + 6, 0xFC6C, 0x0628, 0x0645, 0, + 6, 0xFC6D, 0x0628, 0x0646, 0, + 6, 0xFC6E, 0x0628, 0x0649, 0, + 6, 0xFC6F, 0x0628, 0x064A, 0, + 6, 0xFC70, 0x062A, 0x0631, 0, + 6, 0xFC71, 0x062A, 0x0632, 0, + 6, 0xFC72, 0x062A, 0x0645, 0, + 6, 0xFC73, 0x062A, 0x0646, 0, + 6, 0xFC74, 0x062A, 0x0649, 0, + 6, 0xFC75, 0x062A, 0x064A, 0, + 6, 0xFC76, 0x062B, 0x0631, 0, + 6, 0xFC77, 0x062B, 0x0632, 0, + 6, 0xFC78, 0x062B, 0x0645, 0, + 6, 0xFC79, 0x062B, 0x0646, 0, + 6, 0xFC7A, 0x062B, 0x0649, 0, + 6, 0xFC7B, 0x062B, 0x064A, 0, + 6, 0xFC7C, 0x0641, 0x0649, 0, + 6, 0xFC7D, 0x0641, 0x064A, 0, + 6, 0xFC7E, 0x0642, 0x0649, 0, + 6, 0xFC7F, 0x0642, 0x064A, 0, + 6, 0xFC80, 0x0643, 0x0627, 0, + 6, 0xFC81, 0x0643, 0x0644, 0, + 6, 0xFC82, 0x0643, 0x0645, 0, + 6, 0xFC83, 0x0643, 0x0649, 0, + 6, 0xFC84, 0x0643, 0x064A, 0, + 6, 0xFC85, 0x0644, 0x0645, 0, + 6, 0xFC86, 0x0644, 0x0649, 0, + 6, 0xFC87, 0x0644, 0x064A, 0, + 6, 0xFC88, 0x0645, 0x0627, 0, + 6, 0xFC89, 0x0645, 0x0645, 0, + 6, 0xFC8A, 0x0646, 0x0631, 0, + 6, 0xFC8B, 0x0646, 0x0632, 0, + 6, 0xFC8C, 0x0646, 0x0645, 0, + 6, 0xFC8D, 0x0646, 0x0646, 0, + 6, 0xFC8E, 0x0646, 0x0649, 0, + 6, 0xFC8F, 0x0646, 0x064A, 0, + 6, 0xFC90, 0x0649, 0x0670, 0, + 6, 0xFC91, 0x064A, 0x0631, 0, + 6, 0xFC92, 0x064A, 0x0632, 0, + 6, 0xFC93, 0x064A, 0x0645, 0, + 6, 0xFC94, 0x064A, 0x0646, 0, + 6, 0xFC95, 0x064A, 0x0649, 0, + 6, 0xFC96, 0x064A, 0x064A, 0, + 4, 0xFC97, 0x0626, 0x062C, 0, + 4, 0xFC98, 0x0626, 0x062D, 0, + 4, 0xFC99, 0x0626, 0x062E, 0, + 4, 0xFC9A, 0x0626, 0x0645, 0, + 4, 0xFC9B, 0x0626, 0x0647, 0, + 4, 0xFC9C, 0x0628, 0x062C, 0, + 4, 0xFC9D, 0x0628, 0x062D, 0, + 4, 0xFC9E, 0x0628, 0x062E, 0, + 4, 0xFC9F, 0x0628, 0x0645, 0, + 4, 0xFCA0, 0x0628, 0x0647, 0, + 4, 0xFCA1, 0x062A, 0x062C, 0, + 4, 0xFCA2, 0x062A, 0x062D, 0, + 4, 0xFCA3, 0x062A, 0x062E, 0, + 4, 0xFCA4, 0x062A, 0x0645, 0, + 4, 0xFCA5, 0x062A, 0x0647, 0, + 4, 0xFCA6, 0x062B, 0x0645, 0, + 4, 0xFCA7, 0x062C, 0x062D, 0, + 4, 0xFCA8, 0x062C, 0x0645, 0, + 4, 0xFCA9, 0x062D, 0x062C, 0, + 4, 0xFCAA, 0x062D, 0x0645, 0, + 4, 0xFCAB, 0x062E, 0x062C, 0, + 4, 0xFCAC, 0x062E, 0x0645, 0, + 4, 0xFCAD, 0x0633, 0x062C, 0, + 4, 0xFCAE, 0x0633, 0x062D, 0, + 4, 0xFCAF, 0x0633, 0x062E, 0, + 4, 0xFCB0, 0x0633, 0x0645, 0, + 4, 0xFCB1, 0x0635, 0x062D, 0, + 4, 0xFCB2, 0x0635, 0x062E, 0, + 4, 0xFCB3, 0x0635, 0x0645, 0, + 4, 0xFCB4, 0x0636, 0x062C, 0, + 4, 0xFCB5, 0x0636, 0x062D, 0, + 4, 0xFCB6, 0x0636, 0x062E, 0, + 4, 0xFCB7, 0x0636, 0x0645, 0, + 4, 0xFCB8, 0x0637, 0x062D, 0, + 4, 0xFCB9, 0x0638, 0x0645, 0, + 4, 0xFCBA, 0x0639, 0x062C, 0, + 4, 0xFCBB, 0x0639, 0x0645, 0, + 4, 0xFCBC, 0x063A, 0x062C, 0, + 4, 0xFCBD, 0x063A, 0x0645, 0, + 4, 0xFCBE, 0x0641, 0x062C, 0, + 4, 0xFCBF, 0x0641, 0x062D, 0, + 4, 0xFCC0, 0x0641, 0x062E, 0, + 4, 0xFCC1, 0x0641, 0x0645, 0, + 4, 0xFCC2, 0x0642, 0x062D, 0, + 4, 0xFCC3, 0x0642, 0x0645, 0, + 4, 0xFCC4, 0x0643, 0x062C, 0, + 4, 0xFCC5, 0x0643, 0x062D, 0, + 4, 0xFCC6, 0x0643, 0x062E, 0, + 4, 0xFCC7, 0x0643, 0x0644, 0, + 4, 0xFCC8, 0x0643, 0x0645, 0, + 4, 0xFCC9, 0x0644, 0x062C, 0, + 4, 0xFCCA, 0x0644, 0x062D, 0, + 4, 0xFCCB, 0x0644, 0x062E, 0, + 4, 0xFCCC, 0x0644, 0x0645, 0, + 4, 0xFCCD, 0x0644, 0x0647, 0, + 4, 0xFCCE, 0x0645, 0x062C, 0, + 4, 0xFCCF, 0x0645, 0x062D, 0, + 4, 0xFCD0, 0x0645, 0x062E, 0, + 4, 0xFCD1, 0x0645, 0x0645, 0, + 4, 0xFCD2, 0x0646, 0x062C, 0, + 4, 0xFCD3, 0x0646, 0x062D, 0, + 4, 0xFCD4, 0x0646, 0x062E, 0, + 4, 0xFCD5, 0x0646, 0x0645, 0, + 4, 0xFCD6, 0x0646, 0x0647, 0, + 4, 0xFCD7, 0x0647, 0x062C, 0, + 4, 0xFCD8, 0x0647, 0x0645, 0, + 4, 0xFCD9, 0x0647, 0x0670, 0, + 4, 0xFCDA, 0x064A, 0x062C, 0, + 4, 0xFCDB, 0x064A, 0x062D, 0, + 4, 0xFCDC, 0x064A, 0x062E, 0, + 4, 0xFCDD, 0x064A, 0x0645, 0, + 4, 0xFCDE, 0x064A, 0x0647, 0, + 5, 0xFCDF, 0x0626, 0x0645, 0, + 5, 0xFCE0, 0x0626, 0x0647, 0, + 5, 0xFCE1, 0x0628, 0x0645, 0, + 5, 0xFCE2, 0x0628, 0x0647, 0, + 5, 0xFCE3, 0x062A, 0x0645, 0, + 5, 0xFCE4, 0x062A, 0x0647, 0, + 5, 0xFCE5, 0x062B, 0x0645, 0, + 5, 0xFCE6, 0x062B, 0x0647, 0, + 5, 0xFCE7, 0x0633, 0x0645, 0, + 5, 0xFCE8, 0x0633, 0x0647, 0, + 5, 0xFCE9, 0x0634, 0x0645, 0, + 5, 0xFCEA, 0x0634, 0x0647, 0, + 5, 0xFCEB, 0x0643, 0x0644, 0, + 5, 0xFCEC, 0x0643, 0x0645, 0, + 5, 0xFCED, 0x0644, 0x0645, 0, + 5, 0xFCEE, 0x0646, 0x0645, 0, + 5, 0xFCEF, 0x0646, 0x0647, 0, + 5, 0xFCF0, 0x064A, 0x0645, 0, + 5, 0xFCF1, 0x064A, 0x0647, 0, + 5, 0xFCF2, 0x0640, 0x064E, 0x0651, 0, + 5, 0xFCF3, 0x0640, 0x064F, 0x0651, 0, + 5, 0xFCF4, 0x0640, 0x0650, 0x0651, 0, + 7, 0xFCF5, 0x0637, 0x0649, 0, + 7, 0xFCF6, 0x0637, 0x064A, 0, + 7, 0xFCF7, 0x0639, 0x0649, 0, + 7, 0xFCF8, 0x0639, 0x064A, 0, + 7, 0xFCF9, 0x063A, 0x0649, 0, + 7, 0xFCFA, 0x063A, 0x064A, 0, + 7, 0xFCFB, 0x0633, 0x0649, 0, + 7, 0xFCFC, 0x0633, 0x064A, 0, + 7, 0xFCFD, 0x0634, 0x0649, 0, + 7, 0xFCFE, 0x0634, 0x064A, 0, + 7, 0xFCFF, 0x062D, 0x0649, 0, + 7, 0xFD00, 0x062D, 0x064A, 0, + 7, 0xFD01, 0x062C, 0x0649, 0, + 7, 0xFD02, 0x062C, 0x064A, 0, + 7, 0xFD03, 0x062E, 0x0649, 0, + 7, 0xFD04, 0x062E, 0x064A, 0, + 7, 0xFD05, 0x0635, 0x0649, 0, + 7, 0xFD06, 0x0635, 0x064A, 0, + 7, 0xFD07, 0x0636, 0x0649, 0, + 7, 0xFD08, 0x0636, 0x064A, 0, + 7, 0xFD09, 0x0634, 0x062C, 0, + 7, 0xFD0A, 0x0634, 0x062D, 0, + 7, 0xFD0B, 0x0634, 0x062E, 0, + 7, 0xFD0C, 0x0634, 0x0645, 0, + 7, 0xFD0D, 0x0634, 0x0631, 0, + 7, 0xFD0E, 0x0633, 0x0631, 0, + 7, 0xFD0F, 0x0635, 0x0631, 0, + 7, 0xFD10, 0x0636, 0x0631, 0, + 6, 0xFD11, 0x0637, 0x0649, 0, + 6, 0xFD12, 0x0637, 0x064A, 0, + 6, 0xFD13, 0x0639, 0x0649, 0, + 6, 0xFD14, 0x0639, 0x064A, 0, + 6, 0xFD15, 0x063A, 0x0649, 0, + 6, 0xFD16, 0x063A, 0x064A, 0, + 6, 0xFD17, 0x0633, 0x0649, 0, + 6, 0xFD18, 0x0633, 0x064A, 0, + 6, 0xFD19, 0x0634, 0x0649, 0, + 6, 0xFD1A, 0x0634, 0x064A, 0, + 6, 0xFD1B, 0x062D, 0x0649, 0, + 6, 0xFD1C, 0x062D, 0x064A, 0, + 6, 0xFD1D, 0x062C, 0x0649, 0, + 6, 0xFD1E, 0x062C, 0x064A, 0, + 6, 0xFD1F, 0x062E, 0x0649, 0, + 6, 0xFD20, 0x062E, 0x064A, 0, + 6, 0xFD21, 0x0635, 0x0649, 0, + 6, 0xFD22, 0x0635, 0x064A, 0, + 6, 0xFD23, 0x0636, 0x0649, 0, + 6, 0xFD24, 0x0636, 0x064A, 0, + 6, 0xFD25, 0x0634, 0x062C, 0, + 6, 0xFD26, 0x0634, 0x062D, 0, + 6, 0xFD27, 0x0634, 0x062E, 0, + 6, 0xFD28, 0x0634, 0x0645, 0, + 6, 0xFD29, 0x0634, 0x0631, 0, + 6, 0xFD2A, 0x0633, 0x0631, 0, + 6, 0xFD2B, 0x0635, 0x0631, 0, + 6, 0xFD2C, 0x0636, 0x0631, 0, + 4, 0xFD2D, 0x0634, 0x062C, 0, + 4, 0xFD2E, 0x0634, 0x062D, 0, + 4, 0xFD2F, 0x0634, 0x062E, 0, + 4, 0xFD30, 0x0634, 0x0645, 0, + 4, 0xFD31, 0x0633, 0x0647, 0, + 4, 0xFD32, 0x0634, 0x0647, 0, + 4, 0xFD33, 0x0637, 0x0645, 0, + 5, 0xFD34, 0x0633, 0x062C, 0, + 5, 0xFD35, 0x0633, 0x062D, 0, + 5, 0xFD36, 0x0633, 0x062E, 0, + 5, 0xFD37, 0x0634, 0x062C, 0, + 5, 0xFD38, 0x0634, 0x062D, 0, + 5, 0xFD39, 0x0634, 0x062E, 0, + 5, 0xFD3A, 0x0637, 0x0645, 0, + 5, 0xFD3B, 0x0638, 0x0645, 0, + 6, 0xFD3C, 0x0627, 0x064B, 0, + 7, 0xFD3D, 0x0627, 0x064B, 0, + 4, 0xFD50, 0x062A, 0x062C, 0x0645, 0, + 6, 0xFD51, 0x062A, 0x062D, 0x062C, 0, + 4, 0xFD52, 0x062A, 0x062D, 0x062C, 0, + 4, 0xFD53, 0x062A, 0x062D, 0x0645, 0, + 4, 0xFD54, 0x062A, 0x062E, 0x0645, 0, + 4, 0xFD55, 0x062A, 0x0645, 0x062C, 0, + 4, 0xFD56, 0x062A, 0x0645, 0x062D, 0, + 4, 0xFD57, 0x062A, 0x0645, 0x062E, 0, + 6, 0xFD58, 0x062C, 0x0645, 0x062D, 0, + 4, 0xFD59, 0x062C, 0x0645, 0x062D, 0, + 6, 0xFD5A, 0x062D, 0x0645, 0x064A, 0, + 6, 0xFD5B, 0x062D, 0x0645, 0x0649, 0, + 4, 0xFD5C, 0x0633, 0x062D, 0x062C, 0, + 4, 0xFD5D, 0x0633, 0x062C, 0x062D, 0, + 6, 0xFD5E, 0x0633, 0x062C, 0x0649, 0, + 6, 0xFD5F, 0x0633, 0x0645, 0x062D, 0, + 4, 0xFD60, 0x0633, 0x0645, 0x062D, 0, + 4, 0xFD61, 0x0633, 0x0645, 0x062C, 0, + 6, 0xFD62, 0x0633, 0x0645, 0x0645, 0, + 4, 0xFD63, 0x0633, 0x0645, 0x0645, 0, + 6, 0xFD64, 0x0635, 0x062D, 0x062D, 0, + 4, 0xFD65, 0x0635, 0x062D, 0x062D, 0, + 6, 0xFD66, 0x0635, 0x0645, 0x0645, 0, + 6, 0xFD67, 0x0634, 0x062D, 0x0645, 0, + 4, 0xFD68, 0x0634, 0x062D, 0x0645, 0, + 6, 0xFD69, 0x0634, 0x062C, 0x064A, 0, + 6, 0xFD6A, 0x0634, 0x0645, 0x062E, 0, + 4, 0xFD6B, 0x0634, 0x0645, 0x062E, 0, + 6, 0xFD6C, 0x0634, 0x0645, 0x0645, 0, + 4, 0xFD6D, 0x0634, 0x0645, 0x0645, 0, + 6, 0xFD6E, 0x0636, 0x062D, 0x0649, 0, + 6, 0xFD6F, 0x0636, 0x062E, 0x0645, 0, + 4, 0xFD70, 0x0636, 0x062E, 0x0645, 0, + 6, 0xFD71, 0x0637, 0x0645, 0x062D, 0, + 4, 0xFD72, 0x0637, 0x0645, 0x062D, 0, + 4, 0xFD73, 0x0637, 0x0645, 0x0645, 0, + 6, 0xFD74, 0x0637, 0x0645, 0x064A, 0, + 6, 0xFD75, 0x0639, 0x062C, 0x0645, 0, + 6, 0xFD76, 0x0639, 0x0645, 0x0645, 0, + 4, 0xFD77, 0x0639, 0x0645, 0x0645, 0, + 6, 0xFD78, 0x0639, 0x0645, 0x0649, 0, + 6, 0xFD79, 0x063A, 0x0645, 0x0645, 0, + 6, 0xFD7A, 0x063A, 0x0645, 0x064A, 0, + 6, 0xFD7B, 0x063A, 0x0645, 0x0649, 0, + 6, 0xFD7C, 0x0641, 0x062E, 0x0645, 0, + 4, 0xFD7D, 0x0641, 0x062E, 0x0645, 0, + 6, 0xFD7E, 0x0642, 0x0645, 0x062D, 0, + 6, 0xFD7F, 0x0642, 0x0645, 0x0645, 0, + 6, 0xFD80, 0x0644, 0x062D, 0x0645, 0, + 6, 0xFD81, 0x0644, 0x062D, 0x064A, 0, + 6, 0xFD82, 0x0644, 0x062D, 0x0649, 0, + 4, 0xFD83, 0x0644, 0x062C, 0x062C, 0, + 6, 0xFD84, 0x0644, 0x062C, 0x062C, 0, + 6, 0xFD85, 0x0644, 0x062E, 0x0645, 0, + 4, 0xFD86, 0x0644, 0x062E, 0x0645, 0, + 6, 0xFD87, 0x0644, 0x0645, 0x062D, 0, + 4, 0xFD88, 0x0644, 0x0645, 0x062D, 0, + 4, 0xFD89, 0x0645, 0x062D, 0x062C, 0, + 4, 0xFD8A, 0x0645, 0x062D, 0x0645, 0, + 6, 0xFD8B, 0x0645, 0x062D, 0x064A, 0, + 4, 0xFD8C, 0x0645, 0x062C, 0x062D, 0, + 4, 0xFD8D, 0x0645, 0x062C, 0x0645, 0, + 4, 0xFD8E, 0x0645, 0x062E, 0x062C, 0, + 4, 0xFD8F, 0x0645, 0x062E, 0x0645, 0, + 4, 0xFD92, 0x0645, 0x062C, 0x062E, 0, + 4, 0xFD93, 0x0647, 0x0645, 0x062C, 0, + 4, 0xFD94, 0x0647, 0x0645, 0x0645, 0, + 4, 0xFD95, 0x0646, 0x062D, 0x0645, 0, + 6, 0xFD96, 0x0646, 0x062D, 0x0649, 0, + 6, 0xFD97, 0x0646, 0x062C, 0x0645, 0, + 4, 0xFD98, 0x0646, 0x062C, 0x0645, 0, + 6, 0xFD99, 0x0646, 0x062C, 0x0649, 0, + 6, 0xFD9A, 0x0646, 0x0645, 0x064A, 0, + 6, 0xFD9B, 0x0646, 0x0645, 0x0649, 0, + 6, 0xFD9C, 0x064A, 0x0645, 0x0645, 0, + 4, 0xFD9D, 0x064A, 0x0645, 0x0645, 0, + 6, 0xFD9E, 0x0628, 0x062E, 0x064A, 0, + 6, 0xFD9F, 0x062A, 0x062C, 0x064A, 0, + 6, 0xFDA0, 0x062A, 0x062C, 0x0649, 0, + 6, 0xFDA1, 0x062A, 0x062E, 0x064A, 0, + 6, 0xFDA2, 0x062A, 0x062E, 0x0649, 0, + 6, 0xFDA3, 0x062A, 0x0645, 0x064A, 0, + 6, 0xFDA4, 0x062A, 0x0645, 0x0649, 0, + 6, 0xFDA5, 0x062C, 0x0645, 0x064A, 0, + 6, 0xFDA6, 0x062C, 0x062D, 0x0649, 0, + 6, 0xFDA7, 0x062C, 0x0645, 0x0649, 0, + 6, 0xFDA8, 0x0633, 0x062E, 0x0649, 0, + 6, 0xFDA9, 0x0635, 0x062D, 0x064A, 0, + 6, 0xFDAA, 0x0634, 0x062D, 0x064A, 0, + 6, 0xFDAB, 0x0636, 0x062D, 0x064A, 0, + 6, 0xFDAC, 0x0644, 0x062C, 0x064A, 0, + 6, 0xFDAD, 0x0644, 0x0645, 0x064A, 0, + 6, 0xFDAE, 0x064A, 0x062D, 0x064A, 0, + 6, 0xFDAF, 0x064A, 0x062C, 0x064A, 0, + 6, 0xFDB0, 0x064A, 0x0645, 0x064A, 0, + 6, 0xFDB1, 0x0645, 0x0645, 0x064A, 0, + 6, 0xFDB2, 0x0642, 0x0645, 0x064A, 0, + 6, 0xFDB3, 0x0646, 0x062D, 0x064A, 0, + 4, 0xFDB4, 0x0642, 0x0645, 0x062D, 0, + 4, 0xFDB5, 0x0644, 0x062D, 0x0645, 0, + 6, 0xFDB6, 0x0639, 0x0645, 0x064A, 0, + 6, 0xFDB7, 0x0643, 0x0645, 0x064A, 0, + 4, 0xFDB8, 0x0646, 0x062C, 0x062D, 0, + 6, 0xFDB9, 0x0645, 0x062E, 0x064A, 0, + 4, 0xFDBA, 0x0644, 0x062C, 0x0645, 0, + 6, 0xFDBB, 0x0643, 0x0645, 0x0645, 0, + 6, 0xFDBC, 0x0644, 0x062C, 0x0645, 0, + 6, 0xFDBD, 0x0646, 0x062C, 0x062D, 0, + 6, 0xFDBE, 0x062C, 0x062D, 0x064A, 0, + 6, 0xFDBF, 0x062D, 0x062C, 0x064A, 0, + 6, 0xFDC0, 0x0645, 0x062C, 0x064A, 0, + 6, 0xFDC1, 0x0641, 0x0645, 0x064A, 0, + 6, 0xFDC2, 0x0628, 0x062D, 0x064A, 0, + 4, 0xFDC3, 0x0643, 0x0645, 0x0645, 0, + 4, 0xFDC4, 0x0639, 0x062C, 0x0645, 0, + 4, 0xFDC5, 0x0635, 0x0645, 0x0645, 0, + 6, 0xFDC6, 0x0633, 0x062E, 0x064A, 0, + 6, 0xFDC7, 0x0646, 0x062C, 0x064A, 0, + 7, 0xFDF0, 0x0635, 0x0644, 0x06D2, 0, + 7, 0xFDF1, 0x0642, 0x0644, 0x06D2, 0, + 7, 0xFDF2, 0x0627, 0x0644, 0x0644, 0x0647, 0, + 7, 0xFDF3, 0x0627, 0x0643, 0x0628, 0x0631, 0, + 7, 0xFDF4, 0x0645, 0x062D, 0x0645, 0x062F, 0, + 7, 0xFDF5, 0x0635, 0x0644, 0x0639, 0x0645, 0, + 7, 0xFDF6, 0x0631, 0x0633, 0x0648, 0x0644, 0, + 7, 0xFDF7, 0x0639, 0x0644, 0x064A, 0x0647, 0, + 7, 0xFDF8, 0x0648, 0x0633, 0x0644, 0x0645, 0, + 7, 0xFDF9, 0x0635, 0x0644, 0x0649, 0, + 7, 0xFDFA, 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645, 0, + 7, 0xFDFB, 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647, 0, + 7, 0xFDFC, 0x0631, 0x06CC, 0x0627, 0x0644, 0, + 11, 0xFE30, 0x2025, 0, + 11, 0xFE31, 0x2014, 0, + 11, 0xFE32, 0x2013, 0, + 11, 0xFE33, 0x005F, 0, + 11, 0xFE34, 0x005F, 0, + 11, 0xFE35, 0x0028, 0, + 11, 0xFE36, 0x0029, 0, + 11, 0xFE37, 0x007B, 0, + 11, 0xFE38, 0x007D, 0, + 11, 0xFE39, 0x3014, 0, + 11, 0xFE3A, 0x3015, 0, + 11, 0xFE3B, 0x3010, 0, + 11, 0xFE3C, 0x3011, 0, + 11, 0xFE3D, 0x300A, 0, + 11, 0xFE3E, 0x300B, 0, + 11, 0xFE3F, 0x3008, 0, + 11, 0xFE40, 0x3009, 0, + 11, 0xFE41, 0x300C, 0, + 11, 0xFE42, 0x300D, 0, + 11, 0xFE43, 0x300E, 0, + 11, 0xFE44, 0x300F, 0, + 16, 0xFE49, 0x203E, 0, + 16, 0xFE4A, 0x203E, 0, + 16, 0xFE4B, 0x203E, 0, + 16, 0xFE4C, 0x203E, 0, + 16, 0xFE4D, 0x005F, 0, + 16, 0xFE4E, 0x005F, 0, + 16, 0xFE4F, 0x005F, 0, + 14, 0xFE50, 0x002C, 0, + 14, 0xFE51, 0x3001, 0, + 14, 0xFE52, 0x002E, 0, + 14, 0xFE54, 0x003B, 0, + 14, 0xFE55, 0x003A, 0, + 14, 0xFE56, 0x003F, 0, + 14, 0xFE57, 0x0021, 0, + 14, 0xFE58, 0x2014, 0, + 14, 0xFE59, 0x0028, 0, + 14, 0xFE5A, 0x0029, 0, + 14, 0xFE5B, 0x007B, 0, + 14, 0xFE5C, 0x007D, 0, + 14, 0xFE5D, 0x3014, 0, + 14, 0xFE5E, 0x3015, 0, + 14, 0xFE5F, 0x0023, 0, + 14, 0xFE60, 0x0026, 0, + 14, 0xFE61, 0x002A, 0, + 14, 0xFE62, 0x002B, 0, + 14, 0xFE63, 0x002D, 0, + 14, 0xFE64, 0x003C, 0, + 14, 0xFE65, 0x003E, 0, + 14, 0xFE66, 0x003D, 0, + 14, 0xFE68, 0x005C, 0, + 14, 0xFE69, 0x0024, 0, + 14, 0xFE6A, 0x0025, 0, + 14, 0xFE6B, 0x0040, 0, + 7, 0xFE70, 0x0020, 0x064B, 0, + 5, 0xFE71, 0x0640, 0x064B, 0, + 7, 0xFE72, 0x0020, 0x064C, 0, + 7, 0xFE74, 0x0020, 0x064D, 0, + 7, 0xFE76, 0x0020, 0x064E, 0, + 5, 0xFE77, 0x0640, 0x064E, 0, + 7, 0xFE78, 0x0020, 0x064F, 0, + 5, 0xFE79, 0x0640, 0x064F, 0, + 7, 0xFE7A, 0x0020, 0x0650, 0, + 5, 0xFE7B, 0x0640, 0x0650, 0, + 7, 0xFE7C, 0x0020, 0x0651, 0, + 5, 0xFE7D, 0x0640, 0x0651, 0, + 7, 0xFE7E, 0x0020, 0x0652, 0, + 5, 0xFE7F, 0x0640, 0x0652, 0, + 7, 0xFE80, 0x0621, 0, + 7, 0xFE81, 0x0622, 0, + 6, 0xFE82, 0x0622, 0, + 7, 0xFE83, 0x0623, 0, + 6, 0xFE84, 0x0623, 0, + 7, 0xFE85, 0x0624, 0, + 6, 0xFE86, 0x0624, 0, + 7, 0xFE87, 0x0625, 0, + 6, 0xFE88, 0x0625, 0, + 7, 0xFE89, 0x0626, 0, + 6, 0xFE8A, 0x0626, 0, + 4, 0xFE8B, 0x0626, 0, + 5, 0xFE8C, 0x0626, 0, + 7, 0xFE8D, 0x0627, 0, + 6, 0xFE8E, 0x0627, 0, + 7, 0xFE8F, 0x0628, 0, + 6, 0xFE90, 0x0628, 0, + 4, 0xFE91, 0x0628, 0, + 5, 0xFE92, 0x0628, 0, + 7, 0xFE93, 0x0629, 0, + 6, 0xFE94, 0x0629, 0, + 7, 0xFE95, 0x062A, 0, + 6, 0xFE96, 0x062A, 0, + 4, 0xFE97, 0x062A, 0, + 5, 0xFE98, 0x062A, 0, + 7, 0xFE99, 0x062B, 0, + 6, 0xFE9A, 0x062B, 0, + 4, 0xFE9B, 0x062B, 0, + 5, 0xFE9C, 0x062B, 0, + 7, 0xFE9D, 0x062C, 0, + 6, 0xFE9E, 0x062C, 0, + 4, 0xFE9F, 0x062C, 0, + 5, 0xFEA0, 0x062C, 0, + 7, 0xFEA1, 0x062D, 0, + 6, 0xFEA2, 0x062D, 0, + 4, 0xFEA3, 0x062D, 0, + 5, 0xFEA4, 0x062D, 0, + 7, 0xFEA5, 0x062E, 0, + 6, 0xFEA6, 0x062E, 0, + 4, 0xFEA7, 0x062E, 0, + 5, 0xFEA8, 0x062E, 0, + 7, 0xFEA9, 0x062F, 0, + 6, 0xFEAA, 0x062F, 0, + 7, 0xFEAB, 0x0630, 0, + 6, 0xFEAC, 0x0630, 0, + 7, 0xFEAD, 0x0631, 0, + 6, 0xFEAE, 0x0631, 0, + 7, 0xFEAF, 0x0632, 0, + 6, 0xFEB0, 0x0632, 0, + 7, 0xFEB1, 0x0633, 0, + 6, 0xFEB2, 0x0633, 0, + 4, 0xFEB3, 0x0633, 0, + 5, 0xFEB4, 0x0633, 0, + 7, 0xFEB5, 0x0634, 0, + 6, 0xFEB6, 0x0634, 0, + 4, 0xFEB7, 0x0634, 0, + 5, 0xFEB8, 0x0634, 0, + 7, 0xFEB9, 0x0635, 0, + 6, 0xFEBA, 0x0635, 0, + 4, 0xFEBB, 0x0635, 0, + 5, 0xFEBC, 0x0635, 0, + 7, 0xFEBD, 0x0636, 0, + 6, 0xFEBE, 0x0636, 0, + 4, 0xFEBF, 0x0636, 0, + 5, 0xFEC0, 0x0636, 0, + 7, 0xFEC1, 0x0637, 0, + 6, 0xFEC2, 0x0637, 0, + 4, 0xFEC3, 0x0637, 0, + 5, 0xFEC4, 0x0637, 0, + 7, 0xFEC5, 0x0638, 0, + 6, 0xFEC6, 0x0638, 0, + 4, 0xFEC7, 0x0638, 0, + 5, 0xFEC8, 0x0638, 0, + 7, 0xFEC9, 0x0639, 0, + 6, 0xFECA, 0x0639, 0, + 4, 0xFECB, 0x0639, 0, + 5, 0xFECC, 0x0639, 0, + 7, 0xFECD, 0x063A, 0, + 6, 0xFECE, 0x063A, 0, + 4, 0xFECF, 0x063A, 0, + 5, 0xFED0, 0x063A, 0, + 7, 0xFED1, 0x0641, 0, + 6, 0xFED2, 0x0641, 0, + 4, 0xFED3, 0x0641, 0, + 5, 0xFED4, 0x0641, 0, + 7, 0xFED5, 0x0642, 0, + 6, 0xFED6, 0x0642, 0, + 4, 0xFED7, 0x0642, 0, + 5, 0xFED8, 0x0642, 0, + 7, 0xFED9, 0x0643, 0, + 6, 0xFEDA, 0x0643, 0, + 4, 0xFEDB, 0x0643, 0, + 5, 0xFEDC, 0x0643, 0, + 7, 0xFEDD, 0x0644, 0, + 6, 0xFEDE, 0x0644, 0, + 4, 0xFEDF, 0x0644, 0, + 5, 0xFEE0, 0x0644, 0, + 7, 0xFEE1, 0x0645, 0, + 6, 0xFEE2, 0x0645, 0, + 4, 0xFEE3, 0x0645, 0, + 5, 0xFEE4, 0x0645, 0, + 7, 0xFEE5, 0x0646, 0, + 6, 0xFEE6, 0x0646, 0, + 4, 0xFEE7, 0x0646, 0, + 5, 0xFEE8, 0x0646, 0, + 7, 0xFEE9, 0x0647, 0, + 6, 0xFEEA, 0x0647, 0, + 4, 0xFEEB, 0x0647, 0, + 5, 0xFEEC, 0x0647, 0, + 7, 0xFEED, 0x0648, 0, + 6, 0xFEEE, 0x0648, 0, + 7, 0xFEEF, 0x0649, 0, + 6, 0xFEF0, 0x0649, 0, + 7, 0xFEF1, 0x064A, 0, + 6, 0xFEF2, 0x064A, 0, + 4, 0xFEF3, 0x064A, 0, + 5, 0xFEF4, 0x064A, 0, + 7, 0xFEF5, 0x0644, 0x0622, 0, + 6, 0xFEF6, 0x0644, 0x0622, 0, + 7, 0xFEF7, 0x0644, 0x0623, 0, + 6, 0xFEF8, 0x0644, 0x0623, 0, + 7, 0xFEF9, 0x0644, 0x0625, 0, + 6, 0xFEFA, 0x0644, 0x0625, 0, + 7, 0xFEFB, 0x0644, 0x0627, 0, + 6, 0xFEFC, 0x0644, 0x0627, 0, + 12, 0xFF01, 0x0021, 0, + 12, 0xFF02, 0x0022, 0, + 12, 0xFF03, 0x0023, 0, + 12, 0xFF04, 0x0024, 0, + 12, 0xFF05, 0x0025, 0, + 12, 0xFF06, 0x0026, 0, + 12, 0xFF07, 0x0027, 0, + 12, 0xFF08, 0x0028, 0, + 12, 0xFF09, 0x0029, 0, + 12, 0xFF0A, 0x002A, 0, + 12, 0xFF0B, 0x002B, 0, + 12, 0xFF0C, 0x002C, 0, + 12, 0xFF0D, 0x002D, 0, + 12, 0xFF0E, 0x002E, 0, + 12, 0xFF0F, 0x002F, 0, + 12, 0xFF10, 0x0030, 0, + 12, 0xFF11, 0x0031, 0, + 12, 0xFF12, 0x0032, 0, + 12, 0xFF13, 0x0033, 0, + 12, 0xFF14, 0x0034, 0, + 12, 0xFF15, 0x0035, 0, + 12, 0xFF16, 0x0036, 0, + 12, 0xFF17, 0x0037, 0, + 12, 0xFF18, 0x0038, 0, + 12, 0xFF19, 0x0039, 0, + 12, 0xFF1A, 0x003A, 0, + 12, 0xFF1B, 0x003B, 0, + 12, 0xFF1C, 0x003C, 0, + 12, 0xFF1D, 0x003D, 0, + 12, 0xFF1E, 0x003E, 0, + 12, 0xFF1F, 0x003F, 0, + 12, 0xFF20, 0x0040, 0, + 12, 0xFF21, 0x0041, 0, + 12, 0xFF22, 0x0042, 0, + 12, 0xFF23, 0x0043, 0, + 12, 0xFF24, 0x0044, 0, + 12, 0xFF25, 0x0045, 0, + 12, 0xFF26, 0x0046, 0, + 12, 0xFF27, 0x0047, 0, + 12, 0xFF28, 0x0048, 0, + 12, 0xFF29, 0x0049, 0, + 12, 0xFF2A, 0x004A, 0, + 12, 0xFF2B, 0x004B, 0, + 12, 0xFF2C, 0x004C, 0, + 12, 0xFF2D, 0x004D, 0, + 12, 0xFF2E, 0x004E, 0, + 12, 0xFF2F, 0x004F, 0, + 12, 0xFF30, 0x0050, 0, + 12, 0xFF31, 0x0051, 0, + 12, 0xFF32, 0x0052, 0, + 12, 0xFF33, 0x0053, 0, + 12, 0xFF34, 0x0054, 0, + 12, 0xFF35, 0x0055, 0, + 12, 0xFF36, 0x0056, 0, + 12, 0xFF37, 0x0057, 0, + 12, 0xFF38, 0x0058, 0, + 12, 0xFF39, 0x0059, 0, + 12, 0xFF3A, 0x005A, 0, + 12, 0xFF3B, 0x005B, 0, + 12, 0xFF3C, 0x005C, 0, + 12, 0xFF3D, 0x005D, 0, + 12, 0xFF3E, 0x005E, 0, + 12, 0xFF3F, 0x005F, 0, + 12, 0xFF40, 0x0060, 0, + 12, 0xFF41, 0x0061, 0, + 12, 0xFF42, 0x0062, 0, + 12, 0xFF43, 0x0063, 0, + 12, 0xFF44, 0x0064, 0, + 12, 0xFF45, 0x0065, 0, + 12, 0xFF46, 0x0066, 0, + 12, 0xFF47, 0x0067, 0, + 12, 0xFF48, 0x0068, 0, + 12, 0xFF49, 0x0069, 0, + 12, 0xFF4A, 0x006A, 0, + 12, 0xFF4B, 0x006B, 0, + 12, 0xFF4C, 0x006C, 0, + 12, 0xFF4D, 0x006D, 0, + 12, 0xFF4E, 0x006E, 0, + 12, 0xFF4F, 0x006F, 0, + 12, 0xFF50, 0x0070, 0, + 12, 0xFF51, 0x0071, 0, + 12, 0xFF52, 0x0072, 0, + 12, 0xFF53, 0x0073, 0, + 12, 0xFF54, 0x0074, 0, + 12, 0xFF55, 0x0075, 0, + 12, 0xFF56, 0x0076, 0, + 12, 0xFF57, 0x0077, 0, + 12, 0xFF58, 0x0078, 0, + 12, 0xFF59, 0x0079, 0, + 12, 0xFF5A, 0x007A, 0, + 12, 0xFF5B, 0x007B, 0, + 12, 0xFF5C, 0x007C, 0, + 12, 0xFF5D, 0x007D, 0, + 12, 0xFF5E, 0x007E, 0, + 12, 0xFF5F, 0x2985, 0, + 12, 0xFF60, 0x2986, 0, + 13, 0xFF61, 0x3002, 0, + 13, 0xFF62, 0x300C, 0, + 13, 0xFF63, 0x300D, 0, + 13, 0xFF64, 0x3001, 0, + 13, 0xFF65, 0x30FB, 0, + 13, 0xFF66, 0x30F2, 0, + 13, 0xFF67, 0x30A1, 0, + 13, 0xFF68, 0x30A3, 0, + 13, 0xFF69, 0x30A5, 0, + 13, 0xFF6A, 0x30A7, 0, + 13, 0xFF6B, 0x30A9, 0, + 13, 0xFF6C, 0x30E3, 0, + 13, 0xFF6D, 0x30E5, 0, + 13, 0xFF6E, 0x30E7, 0, + 13, 0xFF6F, 0x30C3, 0, + 13, 0xFF70, 0x30FC, 0, + 13, 0xFF71, 0x30A2, 0, + 13, 0xFF72, 0x30A4, 0, + 13, 0xFF73, 0x30A6, 0, + 13, 0xFF74, 0x30A8, 0, + 13, 0xFF75, 0x30AA, 0, + 13, 0xFF76, 0x30AB, 0, + 13, 0xFF77, 0x30AD, 0, + 13, 0xFF78, 0x30AF, 0, + 13, 0xFF79, 0x30B1, 0, + 13, 0xFF7A, 0x30B3, 0, + 13, 0xFF7B, 0x30B5, 0, + 13, 0xFF7C, 0x30B7, 0, + 13, 0xFF7D, 0x30B9, 0, + 13, 0xFF7E, 0x30BB, 0, + 13, 0xFF7F, 0x30BD, 0, + 13, 0xFF80, 0x30BF, 0, + 13, 0xFF81, 0x30C1, 0, + 13, 0xFF82, 0x30C4, 0, + 13, 0xFF83, 0x30C6, 0, + 13, 0xFF84, 0x30C8, 0, + 13, 0xFF85, 0x30CA, 0, + 13, 0xFF86, 0x30CB, 0, + 13, 0xFF87, 0x30CC, 0, + 13, 0xFF88, 0x30CD, 0, + 13, 0xFF89, 0x30CE, 0, + 13, 0xFF8A, 0x30CF, 0, + 13, 0xFF8B, 0x30D2, 0, + 13, 0xFF8C, 0x30D5, 0, + 13, 0xFF8D, 0x30D8, 0, + 13, 0xFF8E, 0x30DB, 0, + 13, 0xFF8F, 0x30DE, 0, + 13, 0xFF90, 0x30DF, 0, + 13, 0xFF91, 0x30E0, 0, + 13, 0xFF92, 0x30E1, 0, + 13, 0xFF93, 0x30E2, 0, + 13, 0xFF94, 0x30E4, 0, + 13, 0xFF95, 0x30E6, 0, + 13, 0xFF96, 0x30E8, 0, + 13, 0xFF97, 0x30E9, 0, + 13, 0xFF98, 0x30EA, 0, + 13, 0xFF99, 0x30EB, 0, + 13, 0xFF9A, 0x30EC, 0, + 13, 0xFF9B, 0x30ED, 0, + 13, 0xFF9C, 0x30EF, 0, + 13, 0xFF9D, 0x30F3, 0, + 13, 0xFF9E, 0x3099, 0, + 13, 0xFF9F, 0x309A, 0, + 13, 0xFFA0, 0x3164, 0, + 13, 0xFFA1, 0x3131, 0, + 13, 0xFFA2, 0x3132, 0, + 13, 0xFFA3, 0x3133, 0, + 13, 0xFFA4, 0x3134, 0, + 13, 0xFFA5, 0x3135, 0, + 13, 0xFFA6, 0x3136, 0, + 13, 0xFFA7, 0x3137, 0, + 13, 0xFFA8, 0x3138, 0, + 13, 0xFFA9, 0x3139, 0, + 13, 0xFFAA, 0x313A, 0, + 13, 0xFFAB, 0x313B, 0, + 13, 0xFFAC, 0x313C, 0, + 13, 0xFFAD, 0x313D, 0, + 13, 0xFFAE, 0x313E, 0, + 13, 0xFFAF, 0x313F, 0, + 13, 0xFFB0, 0x3140, 0, + 13, 0xFFB1, 0x3141, 0, + 13, 0xFFB2, 0x3142, 0, + 13, 0xFFB3, 0x3143, 0, + 13, 0xFFB4, 0x3144, 0, + 13, 0xFFB5, 0x3145, 0, + 13, 0xFFB6, 0x3146, 0, + 13, 0xFFB7, 0x3147, 0, + 13, 0xFFB8, 0x3148, 0, + 13, 0xFFB9, 0x3149, 0, + 13, 0xFFBA, 0x314A, 0, + 13, 0xFFBB, 0x314B, 0, + 13, 0xFFBC, 0x314C, 0, + 13, 0xFFBD, 0x314D, 0, + 13, 0xFFBE, 0x314E, 0, + 13, 0xFFC2, 0x314F, 0, + 13, 0xFFC3, 0x3150, 0, + 13, 0xFFC4, 0x3151, 0, + 13, 0xFFC5, 0x3152, 0, + 13, 0xFFC6, 0x3153, 0, + 13, 0xFFC7, 0x3154, 0, + 13, 0xFFCA, 0x3155, 0, + 13, 0xFFCB, 0x3156, 0, + 13, 0xFFCC, 0x3157, 0, + 13, 0xFFCD, 0x3158, 0, + 13, 0xFFCE, 0x3159, 0, + 13, 0xFFCF, 0x315A, 0, + 13, 0xFFD2, 0x315B, 0, + 13, 0xFFD3, 0x315C, 0, + 13, 0xFFD4, 0x315D, 0, + 13, 0xFFD5, 0x315E, 0, + 13, 0xFFD6, 0x315F, 0, + 13, 0xFFD7, 0x3160, 0, + 13, 0xFFDA, 0x3161, 0, + 13, 0xFFDB, 0x3162, 0, + 13, 0xFFDC, 0x3163, 0, + 12, 0xFFE0, 0x00A2, 0, + 12, 0xFFE1, 0x00A3, 0, + 12, 0xFFE2, 0x00AC, 0, + 12, 0xFFE3, 0x00AF, 0, + 12, 0xFFE4, 0x00A6, 0, + 12, 0xFFE5, 0x00A5, 0, + 12, 0xFFE6, 0x20A9, 0, + 13, 0xFFE8, 0x2502, 0, + 13, 0xFFE9, 0x2190, 0, + 13, 0xFFEA, 0x2191, 0, + 13, 0xFFEB, 0x2192, 0, + 13, 0xFFEC, 0x2193, 0, + 13, 0xFFED, 0x25A0, 0, + 13, 0xFFEE, 0x25CB, 0, + +}; + +const TQ_UINT16 TQUnicodeTables::decomposition_info[] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 17, 18, + 19, 20, 21, 22, 23, 8, 8, 8, + 8, 8, 24, 8, 8, 8, 25, 26, + 27, 28, 29, 30, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 31, 32, 33, 34, 35, 36, 37, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 10, 0, 0, 0, 0, 14, + 0, 0, 19, 23, 27, 32, 0, 0, + 36, 41, 45, 0, 49, 55, 61, 0, + 67, 72, 77, 82, 87, 92, 0, 97, + 102, 107, 112, 117, 122, 127, 132, 137, + 0, 142, 147, 152, 157, 162, 167, 0, + 0, 172, 177, 182, 187, 192, 0, 0, + 197, 202, 207, 212, 217, 222, 0, 227, + 232, 237, 242, 247, 252, 257, 262, 267, + 0, 272, 277, 282, 287, 292, 297, 0, + 0, 302, 307, 312, 317, 322, 0, 327, + + 332, 337, 342, 347, 352, 357, 362, 367, + 372, 377, 382, 387, 392, 397, 402, 407, + 0, 0, 412, 417, 422, 427, 432, 437, + 442, 447, 452, 457, 462, 467, 472, 477, + 482, 487, 492, 497, 502, 507, 0, 0, + 512, 517, 522, 527, 532, 537, 542, 547, + 552, 0, 557, 562, 567, 572, 577, 582, + 0, 587, 592, 597, 602, 607, 612, 617, + 622, 0, 0, 627, 632, 637, 642, 647, + 652, 657, 0, 0, 662, 667, 672, 677, + 682, 687, 0, 0, 692, 697, 702, 707, + 712, 717, 722, 727, 732, 737, 742, 747, + 752, 757, 762, 767, 772, 777, 0, 0, + 782, 787, 792, 797, 802, 807, 812, 817, + 822, 827, 832, 837, 842, 847, 852, 857, + 862, 867, 872, 877, 882, 887, 892, 897, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 901, 906, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 911, + 916, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 921, 926, 931, 936, + 941, 946, 951, 956, 961, 966, 971, 976, + 981, 986, 991, 996, 1001, 1006, 1011, 1016, + 1021, 1026, 1031, 1036, 1041, 0, 1046, 1051, + 1056, 1061, 1066, 1071, 0, 0, 1076, 1081, + 1086, 1091, 1096, 1101, 1106, 1111, 1116, 1121, + 1126, 1131, 1136, 1141, 1146, 1151, 0, 0, + 1156, 1161, 1166, 1171, 1176, 1181, 1186, 1191, + + 1196, 1201, 1206, 1211, 1216, 1221, 1226, 1231, + 1236, 1241, 1246, 1251, 1256, 1261, 1266, 1271, + 1276, 1281, 1286, 1291, 1296, 1301, 1306, 1311, + 1316, 1321, 1326, 1331, 0, 0, 1336, 1341, + 0, 0, 0, 0, 0, 0, 1346, 1351, + 1356, 1361, 1366, 1371, 1376, 1381, 1386, 1391, + 1396, 1401, 1406, 1411, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1416, 1420, 1424, 1428, 1432, 1436, 1440, 1444, + 1448, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1452, 1457, 1462, 1467, 1472, 1477, 0, 0, + 1482, 1486, 1490, 1494, 1498, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1502, 1506, 0, 1510, 1514, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1519, 0, 0, 0, + 0, 0, 1523, 0, 0, 0, 1528, 0, + 0, 0, 0, 0, 1532, 1537, 1542, 1547, + 1551, 1556, 1561, 0, 1566, 0, 1571, 1576, + 1581, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1586, 1591, 1596, 1601, 1606, 1611, + 1616, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1621, 1626, 1631, 1636, 1641, 0, + 1646, 1650, 1654, 1658, 1663, 1668, 1672, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1676, 1680, 0, 0, 1684, 1688, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 1692, 1697, 0, 1702, 0, 0, 0, 1707, + 0, 0, 0, 0, 1712, 1717, 1722, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1727, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1732, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1737, 1742, 0, 1747, 0, 0, 0, 1752, + 0, 0, 0, 0, 1757, 1762, 1767, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1772, 1777, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1782, 1787, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1792, 1797, 1802, 1807, 0, 0, 1812, 1817, + 0, 0, 1822, 1827, 1832, 1837, 1842, 1847, + 0, 0, 1852, 1857, 1862, 1867, 1872, 1877, + 0, 0, 1882, 1887, 1892, 1897, 1902, 1907, + 1912, 1917, 1922, 1927, 1932, 1937, 0, 0, + 1942, 1947, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1952, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1957, 1962, 1967, 1972, 1977, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1982, 1987, 1992, + 1997, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2002, 0, 2007, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2012, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2017, 0, 0, 0, 0, 0, 0, + 0, 2022, 0, 0, 2027, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2032, 2037, 2042, 2047, 2052, 2057, 2062, 2067, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2072, 2077, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2082, 2087, 0, 2092, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2097, 0, 0, 2102, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2107, 2112, 2117, 0, 0, 2122, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2127, 0, 0, 2132, 2137, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2142, 2147, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2152, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2157, 2162, 2167, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2172, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2177, 0, 0, 0, 0, 0, 0, 2182, + 2187, 0, 2192, 2197, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2202, 2207, 2212, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2217, 0, 2222, 2227, 2232, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2237, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2242, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2247, 2252, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2257, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2261, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2266, 0, 0, + 0, 0, 2271, 0, 0, 0, 0, 2276, + 0, 0, 0, 0, 2281, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2286, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2291, 0, 2296, 2301, 2306, + 2311, 2316, 0, 0, 0, 0, 0, 0, + 0, 2321, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2326, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2331, 0, 0, + 0, 0, 2336, 0, 0, 0, 0, 2341, + 0, 0, 0, 0, 2346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2351, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2356, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 2361, 2366, 2371, 2376, 2381, 2386, 2391, 2396, + 2401, 2406, 2411, 2416, 2421, 2426, 2431, 2436, + 2441, 2446, 2451, 2456, 2461, 2466, 2471, 2476, + 2481, 2486, 2491, 2496, 2501, 2506, 2511, 2516, + 2521, 2526, 2531, 2536, 2541, 2546, 2551, 2556, + 2561, 2566, 2571, 2576, 2581, 2586, 2591, 2596, + 2601, 2606, 2611, 2616, 2621, 2626, 2631, 2636, + 2641, 2646, 2651, 2656, 2661, 2666, 2671, 2676, + 2681, 2686, 2691, 2696, 2701, 2706, 2711, 2716, + 2721, 2726, 2731, 2736, 2741, 2746, 2751, 2756, + 2761, 2766, 2771, 2776, 2781, 2786, 2791, 2796, + 2801, 2806, 2811, 2816, 2821, 2826, 2831, 2836, + 2841, 2846, 2851, 2856, 2861, 2866, 2871, 2876, + 2881, 2886, 2891, 2896, 2901, 2906, 2911, 2916, + 2921, 2926, 2931, 2936, 2941, 2946, 2951, 2956, + 2961, 2966, 2971, 2976, 2981, 2986, 2991, 2996, + 3001, 3006, 3011, 3016, 3021, 3026, 3031, 3036, + 3041, 3046, 3051, 3056, 3061, 3066, 3071, 3076, + 3081, 3086, 3091, 3096, 3101, 3106, 3111, 3116, + 3121, 3126, 3131, 3136, 0, 0, 0, 0, + 3141, 3146, 3151, 3156, 3161, 3166, 3171, 3176, + 3181, 3186, 3191, 3196, 3201, 3206, 3211, 3216, + 3221, 3226, 3231, 3236, 3241, 3246, 3251, 3256, + 3261, 3266, 3271, 3276, 3281, 3286, 3291, 3296, + 3301, 3306, 3311, 3316, 3321, 3326, 3331, 3336, + 3341, 3346, 3351, 3356, 3361, 3366, 3371, 3376, + 3381, 3386, 3391, 3396, 3401, 3406, 3411, 3416, + 3421, 3426, 3431, 3436, 3441, 3446, 3451, 3456, + 3461, 3466, 3471, 3476, 3481, 3486, 3491, 3496, + 3501, 3506, 3511, 3516, 3521, 3526, 3531, 3536, + 3541, 3546, 3551, 3556, 3561, 3566, 3571, 3576, + 3581, 3586, 0, 0, 0, 0, 0, 0, + + 3591, 3596, 3601, 3606, 3611, 3616, 3621, 3626, + 3631, 3636, 3641, 3646, 3651, 3656, 3661, 3666, + 3671, 3676, 3681, 3686, 3691, 3696, 0, 0, + 3701, 3706, 3711, 3716, 3721, 3726, 0, 0, + 3731, 3736, 3741, 3746, 3751, 3756, 3761, 3766, + 3771, 3776, 3781, 3786, 3791, 3796, 3801, 3806, + 3811, 3816, 3821, 3826, 3831, 3836, 3841, 3846, + 3851, 3856, 3861, 3866, 3871, 3876, 3881, 3886, + 3891, 3896, 3901, 3906, 3911, 3916, 0, 0, + 3921, 3926, 3931, 3936, 3941, 3946, 0, 0, + 3951, 3956, 3961, 3966, 3971, 3976, 3981, 3986, + 0, 3991, 0, 3996, 0, 4001, 0, 4006, + 4011, 4016, 4021, 4026, 4031, 4036, 4041, 4046, + 4051, 4056, 4061, 4066, 4071, 4076, 4081, 4086, + 4091, 4096, 4100, 4105, 4109, 4114, 4118, 4123, + 4127, 4132, 4136, 4141, 4145, 4150, 0, 0, + 4154, 4159, 4164, 4169, 4174, 4179, 4184, 4189, + 4194, 4199, 4204, 4209, 4214, 4219, 4224, 4229, + 4234, 4239, 4244, 4249, 4254, 4259, 4264, 4269, + 4274, 4279, 4284, 4289, 4294, 4299, 4304, 4309, + 4314, 4319, 4324, 4329, 4334, 4339, 4344, 4349, + 4354, 4359, 4364, 4369, 4374, 4379, 4384, 4389, + 4394, 4399, 4404, 4409, 4414, 0, 4419, 4424, + 4429, 4434, 4439, 4444, 4448, 4453, 4458, 4462, + 4467, 4472, 4477, 4482, 4487, 0, 4492, 4497, + 4502, 4507, 4511, 4516, 4520, 4525, 4530, 4535, + 4540, 4545, 4550, 4555, 0, 0, 4559, 4564, + 4569, 4574, 4579, 4584, 0, 4588, 4593, 4598, + 4603, 4608, 4613, 4618, 4622, 4627, 4632, 4637, + 4642, 4647, 4652, 4657, 4661, 4666, 4671, 4675, + 0, 0, 4679, 4684, 4689, 0, 4694, 4699, + 4704, 4709, 4713, 4718, 4722, 4727, 4731, 0, + + 4736, 4740, 4744, 4748, 4752, 4756, 4760, 4764, + 4768, 4772, 4776, 0, 0, 0, 0, 0, + 0, 4780, 0, 0, 0, 0, 0, 4784, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4789, 4793, 4798, 0, + 0, 0, 0, 0, 0, 0, 0, 4804, + 0, 0, 0, 4808, 4813, 0, 4819, 4824, + 0, 0, 0, 0, 4830, 0, 4835, 0, + 0, 0, 0, 0, 0, 0, 0, 4840, + 4845, 4850, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4855, + 0, 0, 0, 0, 0, 0, 0, 4862, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4866, 4870, 0, 0, 4874, 4878, 4882, 4886, + 4890, 4894, 4898, 4902, 4906, 4910, 4914, 4918, + 4922, 4926, 4930, 4934, 4938, 4942, 4946, 4950, + 4954, 4958, 4962, 4966, 4970, 4974, 4978, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4982, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 4987, 4993, 4999, 5003, 0, 5008, 5014, 5020, + 0, 5024, 5029, 5033, 5037, 5041, 5045, 5049, + 5053, 5057, 5061, 5065, 0, 5069, 5073, 0, + 0, 5078, 5082, 5086, 5090, 5094, 0, 0, + 5098, 5103, 5109, 0, 5114, 0, 5118, 0, + 5122, 0, 5126, 5130, 5134, 5138, 0, 5142, + 5146, 5150, 0, 5154, 5158, 5162, 5166, 5170, + 5174, 5178, 0, 0, 0, 5182, 5186, 5190, + 5194, 0, 0, 0, 0, 5198, 5202, 5206, + 5210, 5214, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5218, 5224, 5230, 5236, 5242, + 5248, 5254, 5260, 5266, 5272, 5278, 5284, 5290, + 5295, 5299, 5304, 5310, 5315, 5319, 5324, 5330, + 5337, 5342, 5346, 5351, 5357, 5361, 5365, 5369, + 5373, 5377, 5382, 5388, 5393, 5397, 5402, 5408, + 5415, 5420, 5424, 5429, 5435, 5439, 5443, 5447, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5451, 5456, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5461, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5466, 5471, 5476, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 5481, 0, 0, 0, + 0, 5486, 0, 0, 5491, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5496, 0, 5501, 0, + 0, 0, 0, 0, 5506, 5511, 0, 5517, + 5522, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5528, 0, 0, 5533, 0, 0, 5538, + 0, 5543, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5548, 0, 5553, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5558, 5563, 5568, + 5573, 5578, 0, 0, 5583, 5588, 0, 0, + 5593, 5598, 0, 0, 0, 0, 0, 0, + 5603, 5608, 0, 0, 5613, 5618, 0, 0, + 5623, 5628, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5633, 5638, 5643, 5648, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5653, 5658, 5663, 5668, 0, 0, 0, 0, + 0, 0, 5673, 5678, 5683, 5688, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5693, 5697, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5701, 5705, 5709, 5713, 5717, 5721, 5725, 5729, + 5733, 5737, 5742, 5747, 5752, 5757, 5762, 5767, + 5772, 5777, 5782, 5787, 5792, 5798, 5804, 5810, + 5816, 5822, 5828, 5834, 5840, 5846, 5853, 5860, + 5867, 5874, 5881, 5888, 5895, 5902, 5909, 5916, + 5923, 5928, 5933, 5938, 5943, 5948, 5953, 5958, + 5963, 5968, 5974, 5980, 5986, 5992, 5998, 6004, + 6010, 6016, 6022, 6028, 6034, 6040, 6046, 6052, + 6058, 6064, 6070, 6076, 6082, 6088, 6094, 6100, + 6106, 6112, 6118, 6124, 6130, 6136, 6142, 6148, + 6154, 6160, 6166, 6172, 6178, 6184, 6190, 6194, + 6198, 6202, 6206, 6210, 6214, 6218, 6222, 6226, + 6230, 6234, 6238, 6242, 6246, 6250, 6254, 6258, + 6262, 6266, 6270, 6274, 6278, 6282, 6286, 6290, + 6294, 6298, 6302, 6306, 6310, 6314, 6318, 6322, + 6326, 6330, 6334, 6338, 6342, 6346, 6350, 6354, + 6358, 6362, 6366, 6370, 6374, 6378, 6382, 6386, + 6390, 6394, 6398, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6402, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6409, 6415, 6420, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6426, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6431, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6435, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 6439, 6443, 6447, 6451, 6455, 6459, 6463, 6467, + 6471, 6475, 6479, 6483, 6487, 6491, 6495, 6499, + 6503, 6507, 6511, 6515, 6519, 6523, 6527, 6531, + 6535, 6539, 6543, 6547, 6551, 6555, 6559, 6563, + 6567, 6571, 6575, 6579, 6583, 6587, 6591, 6595, + 6599, 6603, 6607, 6611, 6615, 6619, 6623, 6627, + 6631, 6635, 6639, 6643, 6647, 6651, 6655, 6659, + 6663, 6667, 6671, 6675, 6679, 6683, 6687, 6691, + 6695, 6699, 6703, 6707, 6711, 6715, 6719, 6723, + 6727, 6731, 6735, 6739, 6743, 6747, 6751, 6755, + 6759, 6763, 6767, 6771, 6775, 6779, 6783, 6787, + 6791, 6795, 6799, 6803, 6807, 6811, 6815, 6819, + 6823, 6827, 6831, 6835, 6839, 6843, 6847, 6851, + 6855, 6859, 6863, 6867, 6871, 6875, 6879, 6883, + 6887, 6891, 6895, 6899, 6903, 6907, 6911, 6915, + 6919, 6923, 6927, 6931, 6935, 6939, 6943, 6947, + 6951, 6955, 6959, 6963, 6967, 6971, 6975, 6979, + 6983, 6987, 6991, 6995, 6999, 7003, 7007, 7011, + 7015, 7019, 7023, 7027, 7031, 7035, 7039, 7043, + 7047, 7051, 7055, 7059, 7063, 7067, 7071, 7075, + 7079, 7083, 7087, 7091, 7095, 7099, 7103, 7107, + 7111, 7115, 7119, 7123, 7127, 7131, 7135, 7139, + 7143, 7147, 7151, 7155, 7159, 7163, 7167, 7171, + 7175, 7179, 7183, 7187, 7191, 7195, 7199, 7203, + 7207, 7211, 7215, 7219, 7223, 7227, 7231, 7235, + 7239, 7243, 7247, 7251, 7255, 7259, 7263, 7267, + 7271, 7275, 7279, 7283, 7287, 7291, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 7295, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7299, 0, + 7303, 7307, 7311, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7315, 0, 7320, 0, + 7325, 0, 7330, 0, 7335, 0, 7340, 0, + 7345, 0, 7350, 0, 7355, 0, 7360, 0, + 7365, 0, 7370, 0, 0, 7375, 0, 7380, + 0, 7385, 0, 0, 0, 0, 0, 0, + 7390, 7395, 0, 7400, 7405, 0, 7410, 7415, + 0, 7420, 7425, 0, 7430, 7435, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7440, 0, 0, 0, + 0, 0, 0, 7445, 7450, 0, 7455, 7460, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7465, 0, 7470, 0, + 7475, 0, 7480, 0, 7485, 0, 7490, 0, + 7495, 0, 7500, 0, 7505, 0, 7510, 0, + 7515, 0, 7520, 0, 0, 7525, 0, 7530, + 0, 7535, 0, 0, 0, 0, 0, 0, + 7540, 7545, 0, 7550, 7555, 0, 7560, 7565, + 0, 7570, 7575, 0, 7580, 7585, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7590, 0, 0, 7595, + 7600, 7605, 7610, 0, 0, 0, 7615, 7620, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7625, 7629, 7633, 7637, 7641, 7645, 7649, + 7653, 7657, 7661, 7665, 7669, 7673, 7677, 7681, + 7685, 7689, 7693, 7697, 7701, 7705, 7709, 7713, + 7717, 7721, 7725, 7729, 7733, 7737, 7741, 7745, + 7749, 7753, 7757, 7761, 7765, 7769, 7773, 7777, + 7781, 7785, 7789, 7793, 7797, 7801, 7805, 7809, + 7813, 7817, 7821, 7825, 7829, 7833, 7837, 7841, + 7845, 7849, 7853, 7857, 7861, 7865, 7869, 7873, + 7877, 7881, 7885, 7889, 7893, 7897, 7901, 7905, + 7909, 7913, 7917, 7921, 7925, 7929, 7933, 7937, + 7941, 7945, 7949, 7953, 7957, 7961, 7965, 7969, + 7973, 7977, 7981, 7985, 7989, 7993, 7997, 0, + 0, 0, 8001, 8005, 8009, 8013, 8017, 8021, + 8025, 8029, 8033, 8037, 8041, 8045, 8049, 8053, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 8057, 8063, 8069, 8075, 8081, 8087, 8093, 8099, + 8105, 8111, 8117, 8123, 8129, 8135, 8141, 8148, + 8155, 8162, 8169, 8176, 8183, 8190, 8197, 8204, + 8211, 8218, 8225, 8232, 8239, 0, 0, 0, + 8246, 8252, 8258, 8264, 8270, 8276, 8282, 8288, + 8294, 8300, 8306, 8312, 8318, 8324, 8330, 8336, + 8342, 8348, 8354, 8360, 8366, 8372, 8378, 8384, + 8390, 8396, 8402, 8408, 8414, 8420, 8426, 8432, + 8438, 8444, 8450, 8456, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8462, 8467, 8472, 8477, 8482, 8487, 8492, + 8497, 8502, 8507, 8512, 8517, 8522, 8527, 8532, + 8537, 8541, 8545, 8549, 8553, 8557, 8561, 8565, + 8569, 8573, 8577, 8581, 8585, 8589, 8593, 8598, + 8603, 8608, 8613, 8618, 8623, 8628, 8633, 8638, + 8643, 8648, 8653, 8658, 0, 0, 0, 0, + 8663, 8667, 8671, 8675, 8679, 8683, 8687, 8691, + 8695, 8699, 8703, 8707, 8711, 8715, 8719, 8723, + 8727, 8731, 8735, 8739, 8743, 8747, 8751, 8755, + 8759, 8763, 8767, 8771, 8775, 8779, 8783, 8787, + 8791, 8795, 8799, 8803, 8807, 8811, 8815, 8819, + 8823, 8827, 8831, 8835, 8839, 8843, 8847, 8851, + 8855, 8859, 8864, 8869, 8874, 8879, 8884, 8889, + 8894, 8899, 8904, 8909, 8914, 8919, 8924, 8929, + 8934, 8939, 8944, 8949, 8954, 8959, 8964, 8969, + 8974, 8979, 8985, 8991, 0, 0, 0, 0, + 8997, 9001, 9005, 9009, 9013, 9017, 9021, 9025, + 9029, 9033, 9037, 9041, 9045, 9049, 9053, 9057, + 9061, 9065, 9069, 9073, 9077, 9081, 9085, 9089, + 9093, 9097, 9101, 9105, 9109, 9113, 9117, 9121, + 9125, 9129, 9133, 9137, 9141, 9145, 9149, 9153, + 9157, 9161, 9165, 9169, 9173, 9177, 9181, 0, + + 9185, 9192, 9199, 9206, 9212, 9219, 9225, 9231, + 9239, 9246, 9252, 9258, 9264, 9271, 9278, 9284, + 9290, 9295, 9301, 9308, 9315, 9320, 9328, 9337, + 9345, 9351, 9359, 9367, 9374, 9380, 9386, 9392, + 9399, 9407, 9414, 9420, 9426, 9432, 9437, 9442, + 9447, 9452, 9458, 9464, 9472, 9478, 9485, 9493, + 9499, 9504, 9509, 9517, 9524, 9532, 9538, 9546, + 9551, 9557, 9563, 9569, 9575, 9581, 9588, 9594, + 9599, 9605, 9611, 9617, 9624, 9630, 9636, 9642, + 9650, 9657, 9662, 9670, 9675, 9682, 9689, 9695, + 9701, 9707, 9714, 9719, 9725, 9732, 9737, 9745, + 9751, 9756, 9761, 9766, 9771, 9776, 9781, 9786, + 9791, 9796, 9801, 9807, 9813, 9819, 9825, 9831, + 9837, 9843, 9849, 9855, 9861, 9867, 9873, 9879, + 9885, 9891, 9897, 9902, 9907, 9913, 9918, 0, + 0, 0, 0, 9923, 9928, 9933, 9938, 9943, + 9950, 9955, 9960, 9965, 9970, 9975, 9980, 9985, + 9990, 9996, 10003, 10008, 10013, 10018, 10023, 10028, + 10033, 10038, 10044, 10050, 10056, 10062, 10067, 10072, + 10077, 10082, 10087, 10092, 10097, 10102, 10107, 10112, + 10118, 10124, 10129, 10135, 10141, 10147, 10152, 10158, + 10164, 10171, 10176, 10182, 10188, 10194, 10200, 10208, + 10217, 10222, 10227, 10232, 10237, 10242, 10247, 10252, + 10257, 10262, 10267, 10272, 10277, 10282, 10287, 10292, + 10297, 10302, 10307, 10314, 10319, 10324, 10329, 10336, + 10342, 10347, 10352, 10357, 10362, 10367, 10372, 10377, + 10382, 10387, 10392, 10398, 10403, 10408, 10414, 10420, + 10425, 10432, 10438, 10443, 10448, 10453, 0, 0, + 10458, 10463, 10468, 10473, 10478, 10483, 10488, 10493, + 10498, 10503, 10509, 10515, 10521, 10527, 10533, 10539, + 10545, 10551, 10557, 10563, 10569, 10575, 10581, 10587, + 10593, 10599, 10605, 10611, 10617, 10623, 10629, 0, + + 10635, 10639, 10643, 10647, 10651, 10655, 10659, 10663, + 10667, 10671, 10675, 10679, 10683, 10687, 10691, 10695, + 10699, 10703, 10707, 10711, 10715, 10719, 10723, 10727, + 10731, 10735, 10739, 10743, 10747, 10751, 10755, 10759, + 10763, 10767, 10771, 10775, 10779, 10783, 10787, 10791, + 10795, 10799, 10803, 10807, 10811, 10815, 10819, 10823, + 10827, 10831, 10835, 10839, 10843, 10847, 10851, 10855, + 10859, 10863, 10867, 10871, 10875, 10879, 10883, 10887, + 10891, 10895, 10899, 10903, 10907, 10911, 10915, 10919, + 10923, 10927, 10931, 10935, 10939, 10943, 10947, 10951, + 10955, 10959, 10963, 10967, 10971, 10975, 10979, 10983, + 10987, 10991, 10995, 10999, 11003, 11007, 11011, 11015, + 11019, 11023, 11027, 11031, 11035, 11039, 11043, 11047, + 11051, 11055, 11059, 11063, 11067, 11071, 11075, 11079, + 11083, 11087, 11091, 11095, 11099, 11103, 11107, 11111, + 11115, 11119, 11123, 11127, 11131, 11135, 11139, 11143, + 11147, 11151, 11155, 11159, 11163, 11167, 11171, 11175, + 11179, 11183, 11187, 11191, 11195, 11199, 11203, 11207, + 11211, 11215, 11219, 11223, 11227, 11231, 11235, 11239, + 11243, 11247, 11251, 11255, 11259, 11263, 11267, 11271, + 11275, 11279, 11283, 11287, 11291, 11295, 11299, 11303, + 11307, 11311, 11315, 11319, 11323, 11327, 11331, 11335, + 11339, 11343, 11347, 11351, 11355, 11359, 11363, 11367, + 11371, 11375, 11379, 11383, 11387, 11391, 11395, 11399, + 11403, 11407, 11411, 11415, 11419, 11423, 11427, 11431, + 11435, 11439, 11443, 11447, 11451, 11455, 11459, 11463, + 11467, 11471, 11475, 11479, 11483, 11487, 11491, 11495, + 11499, 11503, 11507, 11511, 11515, 11519, 11523, 11527, + 11531, 11535, 11539, 11543, 11547, 11551, 11555, 11559, + 11563, 11567, 11571, 11575, 11579, 11583, 11587, 11591, + 11595, 11599, 11603, 11607, 11611, 11615, 11619, 11623, + 11627, 11631, 11635, 11639, 11643, 11647, 11651, 11655, + + 11659, 11663, 11667, 11671, 11675, 11679, 11683, 11687, + 11691, 11695, 11699, 11703, 11707, 11711, 0, 0, + 11715, 0, 11719, 0, 0, 11723, 11727, 11731, + 11735, 11739, 11743, 11747, 11751, 11755, 11759, 0, + 11763, 0, 11767, 0, 0, 11771, 11775, 0, + 0, 0, 11779, 11783, 11787, 11791, 0, 0, + 11795, 11799, 11803, 11807, 11811, 11815, 11819, 11823, + 11827, 11831, 11835, 11839, 11843, 11847, 11851, 11855, + 11859, 11863, 11867, 11871, 11875, 11879, 11883, 11887, + 11891, 11895, 11899, 11903, 11907, 11911, 11915, 11919, + 11923, 11927, 11931, 11935, 11939, 11943, 11947, 11951, + 11955, 11959, 11963, 11967, 11971, 11975, 11979, 11983, + 11987, 11991, 11995, 11999, 12003, 12007, 12011, 12015, + 12019, 12023, 12027, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 12031, 12036, 12041, 12046, 12052, 12058, 12063, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12068, 12073, 12078, 12083, 12088, + 0, 0, 0, 0, 0, 12093, 0, 12098, + 12103, 12107, 12111, 12115, 12119, 12123, 12127, 12131, + 12135, 12139, 12143, 12148, 12153, 12158, 12163, 12168, + 12173, 12178, 12183, 12188, 12193, 12198, 12203, 0, + 12208, 12213, 12218, 12223, 12228, 0, 12233, 0, + 12238, 12243, 0, 12248, 12253, 0, 12258, 12263, + 12268, 12273, 12278, 12283, 12288, 12293, 12298, 12303, + 12308, 12312, 12316, 12320, 12324, 12328, 12332, 12336, + 12340, 12344, 12348, 12352, 12356, 12360, 12364, 12368, + 12372, 12376, 12380, 12384, 12388, 12392, 12396, 12400, + 12404, 12408, 12412, 12416, 12420, 12424, 12428, 12432, + 12436, 12440, 12444, 12448, 12452, 12456, 12460, 12464, + 12468, 12472, 12476, 12480, 12484, 12488, 12492, 12496, + 12500, 12504, 12508, 12512, 12516, 12520, 12524, 12528, + 12532, 12536, 12540, 12544, 12548, 12552, 12556, 12560, + 12564, 12568, 12572, 12576, 12580, 12584, 12588, 12592, + 12596, 12600, 12604, 12608, 12612, 12616, 12620, 12624, + 12628, 12632, 12636, 12640, 12644, 12648, 12652, 12656, + 12660, 12664, 12668, 12672, 12676, 12680, 12684, 12688, + 12692, 12696, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12700, 12704, 12708, 12712, 12716, + 12720, 12724, 12728, 12732, 12736, 12740, 12744, 12748, + 12752, 12756, 12760, 12764, 12768, 12772, 12776, 12780, + 12784, 12788, 12792, 12797, 12802, 12807, 12812, 12817, + 12822, 12827, 12832, 12837, 12842, 12847, 12852, 12857, + 12862, 12867, 12872, 12877, 12882, 12886, 12890, 12894, + + 12898, 12903, 12908, 12913, 12918, 12923, 12928, 12933, + 12938, 12943, 12948, 12953, 12958, 12963, 12968, 12973, + 12978, 12983, 12988, 12993, 12998, 13003, 13008, 13013, + 13018, 13023, 13028, 13033, 13038, 13043, 13048, 13053, + 13058, 13063, 13068, 13073, 13078, 13083, 13088, 13093, + 13098, 13103, 13108, 13113, 13118, 13123, 13128, 13133, + 13138, 13143, 13148, 13153, 13158, 13163, 13168, 13173, + 13178, 13183, 13188, 13193, 13198, 13203, 13208, 13213, + 13218, 13223, 13228, 13233, 13238, 13243, 13248, 13253, + 13258, 13263, 13268, 13273, 13278, 13283, 13288, 13293, + 13298, 13303, 13308, 13313, 13318, 13323, 13328, 13333, + 13338, 13343, 13348, 13353, 13358, 13363, 13368, 13374, + 13380, 13386, 13392, 13398, 13404, 13409, 13414, 13419, + 13424, 13429, 13434, 13439, 13444, 13449, 13454, 13459, + 13464, 13469, 13474, 13479, 13484, 13489, 13494, 13499, + 13504, 13509, 13514, 13519, 13524, 13529, 13534, 13539, + 13544, 13549, 13554, 13559, 13564, 13569, 13574, 13579, + 13584, 13589, 13594, 13599, 13604, 13609, 13614, 13619, + 13624, 13629, 13634, 13639, 13644, 13649, 13654, 13659, + 13664, 13669, 13674, 13679, 13684, 13689, 13694, 13699, + 13704, 13709, 13714, 13719, 13724, 13729, 13734, 13739, + 13744, 13749, 13754, 13759, 13764, 13769, 13774, 13779, + 13784, 13789, 13794, 13799, 13804, 13809, 13814, 13819, + 13824, 13829, 13834, 13839, 13844, 13849, 13854, 13859, + 13864, 13869, 13874, 13879, 13884, 13889, 13894, 13899, + 13904, 13909, 13914, 13919, 13924, 13929, 13934, 13939, + 13944, 13949, 13954, 13959, 13964, 13969, 13974, 13979, + 13984, 13989, 13994, 13999, 14004, 14009, 14014, 14019, + 14024, 14029, 14034, 14039, 14044, 14049, 14054, 14059, + 14064, 14069, 14074, 14079, 14084, 14089, 14094, 14099, + 14104, 14109, 14114, 14120, 14126, 14132, 14137, 14142, + 14147, 14152, 14157, 14162, 14167, 14172, 14177, 14182, + + 14187, 14192, 14197, 14202, 14207, 14212, 14217, 14222, + 14227, 14232, 14237, 14242, 14247, 14252, 14257, 14262, + 14267, 14272, 14277, 14282, 14287, 14292, 14297, 14302, + 14307, 14312, 14317, 14322, 14327, 14332, 14337, 14342, + 14347, 14352, 14357, 14362, 14367, 14372, 14377, 14382, + 14387, 14392, 14397, 14402, 14407, 14412, 14417, 14422, + 14427, 14432, 14437, 14442, 14447, 14452, 14457, 14462, + 14467, 14472, 14477, 14482, 14487, 14492, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14497, 14503, 14509, 14515, 14521, 14527, 14533, 14539, + 14545, 14551, 14557, 14563, 14569, 14575, 14581, 14587, + 14593, 14599, 14605, 14611, 14617, 14623, 14629, 14635, + 14641, 14647, 14653, 14659, 14665, 14671, 14677, 14683, + 14689, 14695, 14701, 14707, 14713, 14719, 14725, 14731, + 14737, 14743, 14749, 14755, 14761, 14767, 14773, 14779, + 14785, 14791, 14797, 14803, 14809, 14815, 14821, 14827, + 14833, 14839, 14845, 14851, 14857, 14863, 14869, 14875, + 0, 0, 14881, 14887, 14893, 14899, 14905, 14911, + 14917, 14923, 14929, 14935, 14941, 14947, 14953, 14959, + 14965, 14971, 14977, 14983, 14989, 14995, 15001, 15007, + 15013, 15019, 15025, 15031, 15037, 15043, 15049, 15055, + 15061, 15067, 15073, 15079, 15085, 15091, 15097, 15103, + 15109, 15115, 15121, 15127, 15133, 15139, 15145, 15151, + 15157, 15163, 15169, 15175, 15181, 15187, 15193, 15199, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15205, 15211, 15217, 15224, 15231, 15238, 15245, 15252, + 15259, 15266, 15272, 15293, 15304, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15311, 15315, 15319, 15323, 15327, 15331, 15335, 15339, + 15343, 15347, 15351, 15355, 15359, 15363, 15367, 15371, + 15375, 15379, 15383, 15387, 15391, 0, 0, 0, + 0, 15395, 15399, 15403, 15407, 15411, 15415, 15419, + 15423, 15427, 15431, 0, 15435, 15439, 15443, 15447, + 15451, 15455, 15459, 15463, 15467, 15471, 15475, 15479, + 15483, 15487, 15491, 15495, 15499, 15503, 15507, 0, + 15511, 15515, 15519, 15523, 0, 0, 0, 0, + 15527, 15532, 15537, 0, 15542, 0, 15547, 15552, + 15557, 15562, 15567, 15572, 15577, 15582, 15587, 15592, + 15597, 15601, 15605, 15609, 15613, 15617, 15621, 15625, + 15629, 15633, 15637, 15641, 15645, 15649, 15653, 15657, + 15661, 15665, 15669, 15673, 15677, 15681, 15685, 15689, + 15693, 15697, 15701, 15705, 15709, 15713, 15717, 15721, + 15725, 15729, 15733, 15737, 15741, 15745, 15749, 15753, + 15757, 15761, 15765, 15769, 15773, 15777, 15781, 15785, + 15789, 15793, 15797, 15801, 15805, 15809, 15813, 15817, + 15821, 15825, 15829, 15833, 15837, 15841, 15845, 15849, + 15853, 15857, 15861, 15865, 15869, 15873, 15877, 15881, + 15885, 15889, 15893, 15897, 15901, 15905, 15909, 15913, + 15917, 15921, 15925, 15929, 15933, 15937, 15941, 15945, + 15949, 15953, 15957, 15961, 15965, 15969, 15973, 15977, + 15981, 15985, 15989, 15993, 15997, 16001, 16005, 16009, + 16013, 16017, 16021, 16025, 16029, 16033, 16037, 16041, + 16045, 16049, 16053, 16057, 16061, 16065, 16070, 16075, + 16080, 16085, 16090, 16095, 16100, 0, 0, 0, + + 0, 16105, 16109, 16113, 16117, 16121, 16125, 16129, + 16133, 16137, 16141, 16145, 16149, 16153, 16157, 16161, + 16165, 16169, 16173, 16177, 16181, 16185, 16189, 16193, + 16197, 16201, 16205, 16209, 16213, 16217, 16221, 16225, + 16229, 16233, 16237, 16241, 16245, 16249, 16253, 16257, + 16261, 16265, 16269, 16273, 16277, 16281, 16285, 16289, + 16293, 16297, 16301, 16305, 16309, 16313, 16317, 16321, + 16325, 16329, 16333, 16337, 16341, 16345, 16349, 16353, + 16357, 16361, 16365, 16369, 16373, 16377, 16381, 16385, + 16389, 16393, 16397, 16401, 16405, 16409, 16413, 16417, + 16421, 16425, 16429, 16433, 16437, 16441, 16445, 16449, + 16453, 16457, 16461, 16465, 16469, 16473, 16477, 16481, + 16485, 16489, 16493, 16497, 16501, 16505, 16509, 16513, + 16517, 16521, 16525, 16529, 16533, 16537, 16541, 16545, + 16549, 16553, 16557, 16561, 16565, 16569, 16573, 16577, + 16581, 16585, 16589, 16593, 16597, 16601, 16605, 16609, + 16613, 16617, 16621, 16625, 16629, 16633, 16637, 16641, + 16645, 16649, 16653, 16657, 16661, 16665, 16669, 16673, + 16677, 16681, 16685, 16689, 16693, 16697, 16701, 16705, + 16709, 16713, 16717, 16721, 16725, 16729, 16733, 16737, + 16741, 16745, 16749, 16753, 16757, 16761, 16765, 16769, + 16773, 16777, 16781, 16785, 16789, 16793, 16797, 16801, + 16805, 16809, 16813, 16817, 16821, 16825, 16829, 16833, + 16837, 16841, 16845, 16849, 16853, 16857, 16861, 0, + 0, 0, 16865, 16869, 16873, 16877, 16881, 16885, + 0, 0, 16889, 16893, 16897, 16901, 16905, 16909, + 0, 0, 16913, 16917, 16921, 16925, 16929, 16933, + 0, 0, 16937, 16941, 16945, 0, 0, 0, + 16949, 16953, 16957, 16961, 16965, 16969, 16973, 0, + 16977, 16981, 16985, 16989, 16993, 16997, 17001, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +// 67544 bytes + +const TQ_UINT16 TQUnicodeTables::ligature_map[] = { + 0, + 5563, 0, + 5548, 0, + 5568, 0, + 67, 72, 77, 82, 87, 92, 332, 342, 352, 966, 1196, 1206, 1346, 2361, 3141, 3151, 0, + 2371, 2381, 2391, 0, + 97, 362, 372, 382, 392, 0, + 402, 2411, 2421, 2431, 2441, 2451, 0, + 102, 107, 112, 117, 412, 422, 432, 442, 452, 1216, 1226, 1356, 2481, 2491, 3261, 3271, 3281, 0, + 2511, 0, + 462, 472, 482, 492, 1076, 1146, 2521, 0, + 502, 1336, 2531, 2541, 2551, 2561, 2571, 0, + 122, 127, 132, 137, 512, 522, 532, 542, 552, 976, 1236, 1246, 2581, 3341, 3351, 0, + 567, 0, + 577, 1086, 2601, 2611, 2621, 0, + 587, 597, 607, 2631, 2651, 2661, 0, + 2671, 2681, 2691, 0, + 142, 627, 637, 647, 1156, 2701, 2711, 2721, 2731, 0, + 147, 152, 157, 162, 167, 662, 672, 682, 901, 986, 1096, 1256, 1266, 1386, 3361, 3371, 0, + 2781, 2791, 0, + 692, 702, 712, 1276, 1286, 2801, 2811, 2831, 0, + 722, 732, 742, 752, 1316, 2841, 2851, 0, + 762, 772, 1326, 2891, 2901, 2911, 2921, 0, + 172, 177, 182, 187, 782, 792, 802, 812, 822, 832, 911, 996, 1296, 1306, 2931, 2941, 2951, 3481, 3491, 0, + 2981, 2991, 0, + 842, 3001, 3011, 3021, 3031, 3041, 0, + 3051, 3061, 0, + 192, 852, 862, 1406, 3071, 3551, 3561, 3571, 3581, 0, + 867, 877, 887, 3081, 3091, 3101, 0, + 197, 202, 207, 212, 217, 222, 337, 347, 357, 971, 1201, 1211, 1351, 2366, 3146, 3156, 0, + 2376, 2386, 2396, 0, + 227, 367, 377, 387, 397, 0, + 407, 2416, 2426, 2436, 2446, 2456, 0, + 232, 237, 242, 247, 417, 427, 437, 447, 457, 1221, 1231, 1361, 2486, 2496, 3266, 3276, 3286, 0, + 2516, 0, + 467, 477, 487, 497, 1081, 1151, 2526, 0, + 507, 1341, 2536, 2546, 2556, 2566, 2576, 3111, 0, + 252, 257, 262, 267, 517, 527, 537, 547, 981, 1241, 1251, 2586, 3346, 3356, 0, + 572, 1126, 0, + 582, 1091, 2606, 2616, 2626, 0, + 592, 602, 612, 2636, 2656, 2666, 0, + 2676, 2686, 2696, 0, + 272, 632, 642, 652, 1161, 2706, 2716, 2726, 2736, 0, + 277, 282, 287, 292, 297, 667, 677, 687, 906, 991, 1101, 1261, 1271, 1391, 3366, 3376, 0, + 2786, 2796, 0, + 697, 707, 717, 1281, 1291, 2806, 2816, 2836, 0, + 727, 737, 747, 757, 1321, 2846, 2856, 0, + 767, 777, 1331, 2896, 2906, 2916, 2926, 3116, 0, + 302, 307, 312, 317, 787, 797, 807, 817, 827, 837, 916, 1001, 1301, 1311, 2936, 2946, 2956, 3486, 3496, 0, + 2986, 2996, 0, + 847, 3006, 3016, 3026, 3036, 3046, 3121, 0, + 3056, 3066, 0, + 322, 327, 857, 1411, 3076, 3126, 3556, 3566, 3576, 3586, 0, + 872, 882, 892, 3086, 3096, 3106, 0, + 1537, 4472, 4666, 0, + 3161, 3171, 3181, 3191, 0, + 1046, 0, + 1166, 0, + 1066, 1176, 0, + 2401, 0, + 3291, 3301, 3311, 3321, 0, + 2591, 0, + 3381, 3391, 3401, 3411, 0, + 1376, 2741, 2751, 0, + 1366, 0, + 1186, 0, + 1006, 1016, 1026, 1036, 0, + 3166, 3176, 3186, 3196, 0, + 1051, 0, + 1171, 0, + 1071, 1181, 0, + 2406, 0, + 3296, 3306, 3316, 3326, 0, + 2596, 0, + 3386, 3396, 3406, 3416, 0, + 1381, 2746, 2756, 0, + 1371, 0, + 1191, 0, + 1011, 1021, 1031, 1041, 0, + 3211, 3221, 3231, 3241, 0, + 3216, 3226, 3236, 3246, 0, + 2461, 2471, 0, + 2466, 2476, 0, + 2761, 2771, 0, + 2766, 2776, 0, + 2861, 0, + 2866, 0, + 2871, 0, + 2876, 0, + 2961, 0, + 2966, 0, + 2971, 0, + 2976, 0, + 3136, 0, + 3431, 3441, 3451, 3461, 3471, 0, + 3436, 3446, 3456, 3466, 3476, 0, + 3501, 3511, 3521, 3531, 3541, 0, + 3506, 3516, 3526, 3536, 3546, 0, + 1116, 0, + 1106, 0, + 1111, 0, + 1056, 0, + 1061, 0, + 2501, 0, + 2506, 0, + 1396, 0, + 1401, 0, + 1121, 0, + 1514, 0, + 1542, 3631, 3636, 4429, 4434, 4439, 4448, 0, + 1551, 3701, 3706, 4502, 0, + 1556, 3771, 3776, 4511, 4520, 0, + 1561, 1586, 3851, 3856, 4569, 4574, 4579, 0, + 1566, 3921, 3926, 4704, 0, + 4661, 0, + 1571, 1591, 3991, 4642, 4647, 4652, 0, + 1576, 4051, 4056, 4713, 4722, 0, + 4414, 0, + 4487, 0, + 1596, 3591, 3596, 4091, 4394, 4399, 4409, 4419, 0, + 1601, 3671, 3676, 4100, 0, + 1606, 3731, 3736, 4109, 4482, 4492, 0, + 1611, 1621, 3811, 3816, 4118, 4540, 4545, 4559, 0, + 1631, 3891, 3896, 4127, 0, + 4622, 4627, 0, + 1626, 1636, 3951, 3956, 4136, 4603, 4608, 4632, 0, + 1641, 4011, 4016, 4145, 4684, 4694, 0, + 1581, 4550, 4564, 0, + 1616, 4613, 4637, 0, + 4689, 0, + 1658, 1663, 0, + 1707, 0, + 1792, 1802, 0, + 1702, 0, + 1692, 1697, 1812, 0, + 1782, 1832, 0, + 1842, 0, + 1717, 1727, 1852, 1862, 0, + 1712, 0, + 1872, 0, + 1722, 1902, 1912, 1922, 0, + 1932, 0, + 1942, 0, + 1892, 0, + 1797, 1807, 0, + 1747, 0, + 1737, 1742, 1817, 0, + 1787, 1837, 0, + 1847, 0, + 1732, 1762, 1857, 1867, 0, + 1757, 0, + 1877, 0, + 1767, 1907, 1917, 1927, 0, + 1937, 0, + 1947, 0, + 1897, 0, + 1752, 0, + 1772, 0, + 1777, 0, + 1822, 0, + 1827, 0, + 1882, 0, + 1887, 0, + 12163, 12168, 12173, 0, + 12178, 12288, 0, + 12183, 0, + 12188, 0, + 12193, 0, + 12198, 12283, 0, + 12203, 0, + 12208, 0, + 12093, 12213, 0, + 12218, 0, + 12223, 12293, 0, + 12228, 0, + 12233, 0, + 12238, 0, + 12243, 0, + 12248, 0, + 12253, 12298, 0, + 12258, 0, + 12263, 0, + 12268, 0, + 12143, 12148, 12273, 0, + 12278, 0, + 12098, 0, + 1957, 1962, 1972, 0, + 1967, 0, + 1977, 0, + 2007, 0, + 2012, 0, + 2002, 0, + 2032, 0, + 2037, 0, + 2042, 0, + 2047, 0, + 2052, 0, + 2057, 0, + 2017, 0, + 2062, 0, + 2067, 0, + 2022, 0, + 2027, 0, + 2082, 0, + 2087, 0, + 2092, 0, + 2072, 2077, 0, + 2107, 0, + 2112, 0, + 2117, 0, + 2122, 0, + 2097, 0, + 2102, 0, + 2142, 0, + 2147, 0, + 2127, 2132, 2137, 0, + 2152, 0, + 2157, 2167, 0, + 2162, 0, + 2172, 0, + 2177, 0, + 2182, 2187, 2192, 0, + 2197, 0, + 2202, 2212, 0, + 2207, 0, + 2217, 2222, 2232, 0, + 2227, 0, + 2286, 0, + 2261, 0, + 2266, 0, + 2271, 0, + 2276, 0, + 2281, 0, + 2291, 2296, 2321, 0, + 2351, 0, + 2326, 0, + 2331, 0, + 2336, 0, + 2341, 0, + 2346, 0, + 2301, 0, + 2311, 0, + 2356, 0, + 2641, 0, + 2646, 0, + 2821, 0, + 2826, 0, + 2881, 0, + 2886, 0, + 3201, 3251, 0, + 3206, 3256, 0, + 3331, 0, + 3336, 0, + 3421, 0, + 3426, 0, + 3601, 3611, 3621, 4154, 0, + 3606, 3616, 3626, 4159, 0, + 4164, 0, + 4169, 0, + 4174, 0, + 4179, 0, + 4184, 0, + 4189, 0, + 3641, 3651, 3661, 4194, 0, + 3646, 3656, 3666, 4199, 0, + 4204, 0, + 4209, 0, + 4214, 0, + 4219, 0, + 4224, 0, + 4229, 0, + 3681, 3691, 0, + 3686, 3696, 0, + 3711, 3721, 0, + 3716, 3726, 0, + 3741, 3751, 3761, 4234, 0, + 3746, 3756, 3766, 4239, 0, + 4244, 0, + 4249, 0, + 4254, 0, + 4259, 0, + 4264, 0, + 4269, 0, + 3781, 3791, 3801, 4274, 0, + 3786, 3796, 3806, 4279, 0, + 4284, 0, + 4289, 0, + 4294, 0, + 4299, 0, + 4304, 0, + 4309, 0, + 3821, 3831, 3841, 0, + 3826, 3836, 3846, 0, + 3861, 3871, 3881, 0, + 3866, 3876, 3886, 0, + 3901, 3911, 0, + 3906, 3916, 0, + 3931, 3941, 0, + 3936, 3946, 0, + 3961, 3971, 3981, 0, + 3966, 3976, 3986, 0, + 3996, 4001, 4006, 0, + 4021, 4031, 4041, 4314, 0, + 4026, 4036, 4046, 4319, 0, + 4324, 0, + 4329, 0, + 4334, 0, + 4339, 0, + 4344, 0, + 4349, 0, + 4061, 4071, 4081, 4354, 0, + 4066, 4076, 4086, 4359, 0, + 4364, 0, + 4369, 0, + 4374, 0, + 4379, 0, + 4384, 0, + 4389, 0, + 4404, 0, + 4477, 0, + 4679, 0, + 4424, 0, + 4525, 4530, 4535, 0, + 4497, 0, + 4699, 0, + 4588, 4593, 4598, 0, + 5451, 0, + 5456, 0, + 5461, 0, + 5466, 0, + 5476, 0, + 5471, 0, + 5481, 0, + 5486, 0, + 5491, 0, + 5496, 0, + 5501, 0, + 5528, 0, + 5533, 0, + 5538, 0, + 5543, 0, + 5558, 0, + 5553, 0, + 5573, 0, + 5578, 0, + 5583, 0, + 5588, 0, + 5593, 0, + 5598, 0, + 5603, 0, + 5608, 0, + 5653, 0, + 5658, 0, + 5613, 0, + 5618, 0, + 5623, 0, + 5628, 0, + 5663, 0, + 5668, 0, + 5633, 0, + 5638, 0, + 5643, 0, + 5648, 0, + 5673, 0, + 5678, 0, + 5683, 0, + 5688, 0, + 6426, 0, + 7440, 0, + 7315, 0, + 7320, 0, + 7325, 0, + 7330, 0, + 7335, 0, + 7340, 0, + 7345, 0, + 7350, 0, + 7355, 0, + 7360, 0, + 7365, 0, + 7370, 0, + 7375, 0, + 7380, 0, + 7385, 0, + 7390, 7395, 0, + 7400, 7405, 0, + 7410, 7415, 0, + 7420, 7425, 0, + 7430, 7435, 0, + 7455, 0, + 7590, 0, + 7465, 0, + 7470, 0, + 7475, 0, + 7480, 0, + 7485, 0, + 7490, 0, + 7495, 0, + 7500, 0, + 7505, 0, + 7510, 0, + 7515, 0, + 7520, 0, + 7525, 0, + 7530, 0, + 7535, 0, + 7540, 7545, 0, + 7550, 7555, 0, + 7560, 7565, 0, + 7570, 7575, 0, + 7580, 7585, 0, + 7595, 0, + 7600, 0, + 7605, 0, + 7610, 0, + 7615, 0, + 12153, 12158, 0, + +}; + +const TQ_UINT16 TQUnicodeTables::ligature_info[] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 8, 9, 10, 11, 12, 13, 8, 14, + 15, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 16, 17, + 8, 18, 19, 8, 8, 8, 8, 8, + 8, 8, 20, 8, 8, 8, 8, 8, + 21, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 22, 8, 8, 8, 8, + + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 3, 5, 0, + 0, 7, 24, 28, 34, 41, 59, 61, + 69, 77, 93, 95, 101, 108, 112, 122, + 139, 0, 142, 151, 159, 167, 187, 190, + 197, 200, 210, 0, 0, 0, 0, 0, + 0, 217, 234, 238, 244, 251, 269, 271, + 279, 288, 303, 306, 312, 319, 323, 333, + 350, 0, 353, 362, 370, 379, 399, 402, + 410, 413, 424, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 431, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 435, 0, 440, 442, 444, 447, + 0, 0, 449, 0, 0, 0, 0, 454, + 0, 0, 0, 0, 456, 461, 465, 0, + 467, 0, 0, 0, 469, 0, 0, 0, + 0, 0, 474, 0, 479, 481, 483, 486, + 0, 0, 488, 0, 0, 0, 0, 493, + 0, 0, 0, 0, 495, 500, 504, 0, + 506, 0, 0, 0, 508, 0, 0, 0, + + 0, 0, 513, 518, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 523, 526, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 529, 532, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 535, 537, 0, 0, 0, 0, + 539, 541, 0, 0, 0, 0, 0, 0, + 543, 545, 547, 549, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 551, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 553, 559, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 565, + 571, 0, 0, 0, 0, 0, 0, 577, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 579, 581, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 583, 585, + 587, 589, 0, 0, 0, 0, 591, 593, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 595, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 597, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 599, 0, 0, 0, 607, 0, 612, + 0, 618, 0, 0, 0, 0, 0, 626, + 0, 631, 0, 0, 0, 633, 0, 0, + 0, 640, 0, 0, 646, 0, 648, 0, + 0, 650, 0, 0, 0, 659, 0, 664, + 0, 671, 0, 0, 0, 0, 0, 680, + 0, 685, 0, 0, 0, 688, 0, 0, + 0, 697, 704, 708, 0, 0, 712, 0, + 0, 0, 714, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 717, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 719, 0, 0, 722, 0, 724, 728, 731, + 733, 0, 738, 0, 0, 0, 740, 0, + 0, 0, 0, 742, 0, 0, 0, 747, + 0, 0, 0, 749, 0, 751, 0, 0, + 753, 0, 0, 756, 0, 758, 762, 765, + 767, 0, 772, 0, 0, 0, 774, 0, + 0, 0, 0, 776, 0, 0, 0, 781, + 0, 0, 0, 783, 0, 785, 0, 0, + 0, 0, 0, 0, 0, 0, 787, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 789, 791, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 793, 795, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 797, 799, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 801, 805, 808, 810, 812, 814, 817, 0, + 819, 821, 824, 826, 829, 0, 831, 0, + 833, 835, 0, 837, 839, 0, 842, 844, + 846, 848, 852, 0, 0, 0, 0, 0, + 0, 0, 854, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 856, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 860, 0, 862, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 864, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 866, 0, 0, 868, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 870, 872, 874, + 0, 0, 0, 0, 876, 0, 0, 0, + 0, 878, 880, 0, 0, 0, 0, 0, + 882, 0, 0, 884, 0, 0, 0, 886, + 888, 0, 0, 890, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 892, 894, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 896, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 898, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 901, 903, + 0, 0, 0, 0, 905, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 907, 0, 0, 0, 0, + 0, 0, 909, 0, 0, 0, 0, 0, + 911, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 913, 915, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 917, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 921, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 923, 926, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 928, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 930, + 0, 0, 0, 0, 0, 0, 932, 0, + 0, 0, 936, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 938, 941, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 943, 0, 0, 947, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 949, 0, 951, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 953, 0, 0, 0, + 0, 955, 0, 0, 0, 0, 957, 0, + 0, 0, 0, 959, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 961, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 965, 0, 967, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 969, 0, 0, 0, + 0, 971, 0, 0, 0, 0, 973, 0, + 0, 0, 0, 975, 0, 0, 0, 0, + 0, 0, 977, 979, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 981, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 983, 985, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 987, 989, 0, 0, 0, 0, + 0, 0, 991, 993, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 995, 998, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1001, 1003, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1005, 1007, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 1009, 1014, 1019, 1021, 1023, 1025, 1027, 1029, + 1031, 1036, 1041, 1043, 1045, 1047, 1049, 1051, + 1053, 1056, 0, 0, 0, 0, 0, 0, + 1059, 1062, 0, 0, 0, 0, 0, 0, + 1065, 1070, 1075, 1077, 1079, 1081, 1083, 1085, + 1087, 1092, 1097, 1099, 1101, 1103, 1105, 1107, + 1109, 1113, 0, 0, 0, 0, 0, 0, + 1117, 1121, 0, 0, 0, 0, 0, 0, + 1125, 1128, 0, 0, 0, 0, 0, 0, + 1131, 1134, 0, 0, 0, 0, 0, 0, + 1137, 1141, 0, 0, 0, 0, 0, 0, + 0, 1145, 0, 0, 0, 0, 0, 0, + 1149, 1154, 1159, 1161, 1163, 1165, 1167, 1169, + 1171, 1176, 1181, 1183, 1185, 1187, 1189, 1191, + 1193, 0, 0, 0, 1195, 0, 0, 0, + 0, 0, 0, 0, 1197, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1199, 0, + 0, 0, 0, 0, 0, 0, 0, 1201, + 0, 0, 0, 0, 0, 0, 1205, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1207, 0, + 0, 0, 0, 0, 0, 0, 1209, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1213, 0, 1215, 0, 1217, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1219, 0, 1221, 0, 1223, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 1225, 0, 0, 0, 0, + 1227, 0, 0, 1229, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1231, 0, 1233, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1235, 0, 0, 0, + 0, 0, 0, 1237, 0, 1239, 0, 0, + 1241, 0, 0, 0, 0, 1243, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1245, 0, 0, 1247, 1249, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1251, 1253, 0, 0, 1255, 1257, + 0, 0, 1259, 1261, 1263, 1265, 0, 0, + 0, 0, 1267, 1269, 0, 0, 1271, 1273, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1275, 1277, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1279, 0, 0, 0, 0, 0, + 1281, 1283, 0, 1285, 0, 0, 0, 0, + 0, 0, 1287, 1289, 1291, 1293, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1295, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1297, 0, + 0, 0, 0, 1299, 0, 1301, 0, 1303, + 0, 1305, 0, 1307, 0, 1309, 0, 1311, + 0, 1313, 0, 1315, 0, 1317, 0, 1319, + 0, 1321, 0, 0, 1323, 0, 1325, 0, + 1327, 0, 0, 0, 0, 0, 0, 1329, + 0, 0, 1332, 0, 0, 1335, 0, 0, + 1338, 0, 0, 1341, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1344, 0, 0, + 0, 0, 0, 0, 0, 0, 1346, 0, + 0, 0, 0, 1348, 0, 1350, 0, 1352, + 0, 1354, 0, 1356, 0, 1358, 0, 1360, + 0, 1362, 0, 1364, 0, 1366, 0, 1368, + 0, 1370, 0, 0, 1372, 0, 1374, 0, + 1376, 0, 0, 0, 0, 0, 0, 1378, + 0, 0, 1381, 0, 0, 1384, 0, 0, + 1387, 0, 0, 1390, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1393, + 1395, 1397, 1399, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1401, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1403, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +// 14586 bytes + +const TQ_UINT8 TQUnicodeTables::direction_info[] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 2, 9, 10, 11, 12, 13, 14, 15, + 16, 2, 2, 2, 2, 2, 17, 18, + 19, 2, 2, 2, 2, 2, 2, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 26, 29, 30, 2, 2, 2, 31, 32, + 33, 2, 34, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 35, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 36, 37, 38, 39, 40, + + + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 8, 7, 8, 9, 7, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 7, 7, 7, 8, + 9, 10, 10, 4, 4, 4, 10, 10, + 138, 138, 10, 4, 6, 4, 6, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 6, 10, 138, 10, 138, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 18, + 18, 18, 18, 18, 18, 7, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 6, 10, 4, 4, 4, 4, 10, 10, + 10, 10, 0, 138, 10, 10, 10, 10, + 4, 4, 2, 2, 10, 0, 10, 10, + 10, 2, 0, 138, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 10, 10, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17, 17, 17, 17, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 17, 1, 17, + 1, 17, 17, 1, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 0, 0, 0, 13, + 0, 13, 77, 77, 77, 77, 45, 77, + 45, 77, 45, 45, 45, 45, 45, 77, + 77, 77, 77, 45, 45, 45, 45, 45, + 45, 45, 45, 0, 0, 0, 0, 0, + 109, 45, 45, 45, 45, 45, 45, 45, + 77, 45, 45, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 4, 5, 5, 13, 45, 45, + 17, 77, 77, 77, 13, 77, 77, 77, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 77, 45, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 45, 77, 45, 77, + 45, 45, 77, 77, 13, 77, 17, 17, + 17, 17, 17, 17, 17, 13, 17, 17, + 17, 17, 17, 17, 17, 13, 13, 17, + 17, 10, 17, 17, 17, 17, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 45, 45, 45, 13, 13, 0, + + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 0, 18, + 77, 17, 45, 45, 45, 77, 77, 77, + 77, 77, 45, 45, 45, 45, 77, 45, + 45, 45, 45, 45, 45, 45, 45, 45, + 77, 45, 77, 45, 77, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 0, 0, 0, 0, 17, 0, 0, + 0, 17, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 0, 0, 0, 0, 17, + 17, 0, 0, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 0, 17, + 17, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 17, + 0, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 17, + 17, 0, 0, 0, 0, 0, 17, 17, + 17, 0, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 17, + 17, 17, 17, 17, 17, 17, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 17, 17, 17, 17, + 17, 17, 0, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 0, 17, + 0, 17, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 0, + 17, 17, 17, 17, 17, 0, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17, 17, 17, + 17, 0, 17, 0, 0, 0, 17, 17, + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, + 17, 17, 17, 17, 17, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 17, 0, + 0, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 17, 17, 17, 18, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 10, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 10, 0, + + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 18, 18, 114, 0, 1, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 9, 7, 11, 14, 16, 12, 15, 9, + 4, 4, 4, 4, 4, 10, 10, 10, + 10, 138, 138, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 138, 138, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 9, + 18, 18, 18, 18, 0, 0, 0, 0, + 0, 0, 18, 18, 18, 18, 18, 18, + 2, 0, 0, 0, 2, 2, 2, 2, + 2, 2, 4, 4, 10, 138, 138, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 4, 4, 10, 138, 138, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 10, 10, 0, 10, 10, 10, 10, 0, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, 10, 10, + 10, 0, 0, 0, 0, 0, 10, 10, + 10, 10, 10, 10, 0, 10, 0, 10, + 0, 10, 0, 0, 0, 0, 4, 0, + 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, + 138, 10, 10, 10, 10, 0, 0, 0, + 0, 0, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 138, 138, 138, 138, 10, 10, 10, + 138, 138, 138, 138, 138, 138, 10, 10, + 10, 138, 4, 4, 10, 138, 138, 10, + 10, 10, 138, 138, 138, 138, 10, 138, + 138, 138, 138, 10, 138, 10, 138, 10, + 10, 10, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 10, 10, + 10, 138, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 10, 10, 10, + 10, 10, 138, 138, 138, 138, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 138, + 138, 10, 138, 10, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 10, 10, 138, + 138, 138, 138, 10, 10, 10, 10, 10, + 138, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 138, 138, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 10, 10, 10, 10, 10, 138, 138, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 138, 138, 138, 138, 138, 10, 10, + 138, 138, 10, 10, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 10, 10, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + + 10, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 138, 138, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 10, 10, 10, 10, 10, 10, + 10, 138, 138, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 10, 10, 10, 10, 0, 10, 10, + 10, 10, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 10, 0, 10, + 10, 10, 10, 0, 0, 0, 10, 0, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 138, 138, 10, + 10, 10, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 10, 10, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 10, 10, 10, 10, 10, 10, 10, 10, + 138, 10, 10, 10, 10, 10, 10, 10, + 138, 138, 138, 138, 138, 138, 10, 10, + 10, 138, 10, 10, 10, 10, 138, 138, + 138, 138, 138, 10, 138, 138, 10, 10, + 138, 138, 138, 138, 138, 10, 10, 10, + 10, 138, 10, 138, 138, 138, 10, 10, + 138, 138, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 138, 138, 138, 138, + 138, 138, 10, 10, 138, 138, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 10, 138, 138, + 138, 138, 10, 10, 138, 10, 138, 10, + 10, 138, 10, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 138, 10, 10, + 10, 10, 10, 10, 138, 138, 138, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 138, + 138, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 138, 138, 10, 10, + 10, 10, 138, 138, 138, 138, 10, 138, + 138, 10, 10, 138, 138, 10, 10, 10, + 10, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 138, 138, + 138, 138, 138, 138, 138, 138, 10, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 10, 138, 10, + 10, 10, 138, 138, 138, 138, 138, 10, + 10, 10, 10, 10, 138, 138, 138, 10, + 10, 10, 10, 138, 10, 10, 10, 138, + 138, 138, 138, 138, 10, 138, 10, 10, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 0, 0, 0, 0, + + 9, 10, 10, 10, 10, 0, 0, 0, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 10, 10, 138, 138, 138, 138, + 138, 138, 138, 138, 10, 10, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 17, 17, 17, 17, 17, + 10, 0, 0, 0, 0, 0, 10, 10, + 0, 0, 0, 0, 0, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 17, 10, 10, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 17, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 0, + 1, 1, 0, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 10, 10, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 0, + + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 17, 17, 17, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 10, 10, 10, 10, 10, 10, 10, + 6, 10, 6, 0, 10, 6, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 4, + 10, 10, 4, 4, 10, 10, 10, 0, + 10, 4, 4, 10, 0, 0, 0, 0, + 13, 13, 13, 13, 13, 0, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 18, + + 0, 10, 10, 4, 4, 4, 10, 10, + 138, 138, 10, 4, 6, 4, 6, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 6, 10, 138, 10, 138, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 10, + 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 138, 10, 138, 10, 138, + 138, 10, 138, 138, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 10, 10, 10, 4, 4, 0, + 10, 10, 10, 10, 10, 10, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 18, 18, 10, 10, 0, 0, +}; + +// 25082 bytes + +const TQ_UINT8 TQUnicodeTables::combining_info[] = { + 1, 1, 1, 2, 3, 4, 5, 6, + 1, 7, 8, 9, 10, 11, 12, 13, + 14, 1, 1, 1, 1, 1, 1, 15, + 16, 1, 1, 1, 1, 1, 1, 1, + 17, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 18, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 19, 1, 1, 20, 1, + + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 232, 220, 220, + 220, 220, 232, 216, 220, 220, 220, 220, + 220, 202, 202, 220, 220, 220, 220, 202, + 202, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 1, 1, 1, 1, + 1, 220, 220, 220, 220, 230, 230, 230, + 230, 230, 230, 230, 230, 240, 230, 220, + 220, 220, 230, 230, 230, 220, 220, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 234, 234, 233, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 230, 230, 230, 230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 220, 230, 230, 230, 230, 220, 230, + 230, 230, 222, 220, 230, 230, 230, 230, + 230, 230, 0, 220, 220, 220, 220, 220, + 230, 230, 220, 230, 230, 222, 228, 230, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 0, 20, 21, 22, 0, 23, + 0, 24, 25, 0, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 27, 28, 29, 30, 31, + 32, 33, 34, 230, 230, 220, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 230, 230, + 230, 230, 230, 230, 230, 0, 0, 230, + 230, 230, 230, 220, 230, 0, 0, 230, + 230, 0, 220, 230, 230, 220, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 36, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 230, 220, 230, 230, 220, 230, 230, 220, + 220, 220, 230, 220, 220, 230, 220, 230, + 230, 230, 220, 230, 220, 230, 220, 230, + 220, 230, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 230, 220, 230, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 84, 91, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 103, 103, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 107, 107, 107, 107, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 118, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 122, 122, 122, 122, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 220, 220, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 220, 0, 220, + 0, 216, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 129, 130, 0, 132, 0, 0, 0, + 0, 0, 130, 130, 130, 130, 0, 0, + 130, 0, 230, 230, 9, 0, 230, 230, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 220, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, + 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 228, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 230, 230, 1, 1, 230, 230, 230, 230, + 1, 1, 1, 230, 230, 0, 0, 0, + 0, 230, 0, 0, 0, 1, 1, 230, + 220, 230, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 218, 228, 232, 222, 224, 224, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 230, 230, 230, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +// 30458 bytes + +const TQ_UINT16 TQUnicodeTables::case_info[] = { + 1, 2, 3, 4, 5, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 8, + 0, 9, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, + + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0, + 0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x39c, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x1e9e, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x178, + + 0x101, 0x100, 0x103, 0x102, 0x105, 0x104, 0x107, 0x106, + 0x109, 0x108, 0x10b, 0x10a, 0x10d, 0x10c, 0x10f, 0x10e, + 0x111, 0x110, 0x113, 0x112, 0x115, 0x114, 0x117, 0x116, + 0x119, 0x118, 0x11b, 0x11a, 0x11d, 0x11c, 0x11f, 0x11e, + 0x121, 0x120, 0x123, 0x122, 0x125, 0x124, 0x127, 0x126, + 0x129, 0x128, 0x12b, 0x12a, 0x12d, 0x12c, 0x12f, 0x12e, + 0x69, 0x49, 0x133, 0x132, 0x135, 0x134, 0x137, 0x136, + 0, 0x13a, 0x139, 0x13c, 0x13b, 0x13e, 0x13d, 0x140, + 0x13f, 0x142, 0x141, 0x144, 0x143, 0x146, 0x145, 0x148, + 0x147, 0, 0x14b, 0x14a, 0x14d, 0x14c, 0x14f, 0x14e, + 0x151, 0x150, 0x153, 0x152, 0x155, 0x154, 0x157, 0x156, + 0x159, 0x158, 0x15b, 0x15a, 0x15d, 0x15c, 0x15f, 0x15e, + 0x161, 0x160, 0x163, 0x162, 0x165, 0x164, 0x167, 0x166, + 0x169, 0x168, 0x16b, 0x16a, 0x16d, 0x16c, 0x16f, 0x16e, + 0x171, 0x170, 0x173, 0x172, 0x175, 0x174, 0x177, 0x176, + 0xff, 0x17a, 0x179, 0x17c, 0x17b, 0x17e, 0x17d, 0x53, + 0, 0x253, 0x183, 0x182, 0x185, 0x184, 0x254, 0x188, + 0x187, 0x256, 0x257, 0x18c, 0x18b, 0, 0x1dd, 0x259, + 0x25b, 0x192, 0x191, 0x260, 0x263, 0x1f6, 0x269, 0x268, + 0x199, 0x198, 0, 0, 0x26f, 0x272, 0x220, 0x275, + 0x1a1, 0x1a0, 0x1a3, 0x1a2, 0x1a5, 0x1a4, 0x280, 0x1a8, + 0x1a7, 0x283, 0, 0, 0x1ad, 0x1ac, 0x288, 0x1b0, + 0x1af, 0x28a, 0x28b, 0x1b4, 0x1b3, 0x1b6, 0x1b5, 0x292, + 0x1b9, 0x1b8, 0, 0, 0x1bd, 0x1bc, 0, 0x1f7, + 0, 0, 0, 0, 0x1c6, 0x1c4, 0x1c4, 0x1c9, + 0x1c7, 0x1c7, 0x1cc, 0x1ca, 0x1ca, 0x1ce, 0x1cd, 0x1d0, + 0x1cf, 0x1d2, 0x1d1, 0x1d4, 0x1d3, 0x1d6, 0x1d5, 0x1d8, + 0x1d7, 0x1da, 0x1d9, 0x1dc, 0x1db, 0x18e, 0x1df, 0x1de, + 0x1e1, 0x1e0, 0x1e3, 0x1e2, 0x1e5, 0x1e4, 0x1e7, 0x1e6, + 0x1e9, 0x1e8, 0x1eb, 0x1ea, 0x1ed, 0x1ec, 0x1ef, 0x1ee, + 0, 0x1f3, 0x1f1, 0x1f1, 0x1f5, 0x1f4, 0x195, 0x1bf, + 0x1f9, 0x1f8, 0x1fb, 0x1fa, 0x1fd, 0x1fc, 0x1ff, 0x1fe, + + 0x201, 0x200, 0x203, 0x202, 0x205, 0x204, 0x207, 0x206, + 0x209, 0x208, 0x20b, 0x20a, 0x20d, 0x20c, 0x20f, 0x20e, + 0x211, 0x210, 0x213, 0x212, 0x215, 0x214, 0x217, 0x216, + 0x219, 0x218, 0x21b, 0x21a, 0x21d, 0x21c, 0x21f, 0x21e, + 0x19e, 0, 0x223, 0x222, 0x225, 0x224, 0x227, 0x226, + 0x229, 0x228, 0x22b, 0x22a, 0x22d, 0x22c, 0x22f, 0x22e, + 0x231, 0x230, 0x233, 0x232, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x242, 0x241, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x181, 0x186, 0, 0x189, 0x18a, + 0, 0x18f, 0, 0x190, 0, 0, 0, 0, + 0x193, 0, 0, 0x194, 0, 0, 0, 0, + 0x197, 0x196, 0, 0, 0, 0, 0, 0x19c, + 0, 0, 0x19d, 0, 0, 0x19f, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x1a6, 0, 0, 0x1a9, 0, 0, 0, 0, + 0x1ae, 0, 0x1b1, 0x1b2, 0, 0, 0, 0, + 0, 0, 0x1b7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0x399, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x3ac, 0, + 0x3ad, 0x3ae, 0x3af, 0, 0x3cc, 0, 0x3cd, 0x3ce, + 0, 0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, + 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bc, 0x3bd, 0x3be, 0x3bf, + 0x3c0, 0x3c1, 0, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, + 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x386, 0x388, 0x389, 0x38a, + 0, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, + 0x398, 0x399, 0x39a, 0x39b, 0x39c, 0x39d, 0x39e, 0x39f, + 0x3a0, 0x3a1, 0x3a3, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, + 0x3a8, 0x3a9, 0x3aa, 0x3ab, 0x38c, 0x38e, 0x38f, 0, + 0x392, 0x398, 0, 0, 0, 0x3a6, 0x3a0, 0, + 0x3d9, 0x3d8, 0x3db, 0x3da, 0x3dd, 0x3dc, 0x3df, 0x3de, + 0x3e1, 0x3e0, 0x3e3, 0x3e2, 0x3e5, 0x3e4, 0x3e7, 0x3e6, + 0x3e9, 0x3e8, 0x3eb, 0x3ea, 0x3ed, 0x3ec, 0x3ef, 0x3ee, + 0x39a, 0x3a1, 0x3f9, 0, 0x3b8, 0x395, 0, 0, + 0, 0x3f2, 0x3fb, 0x3fa, 0, 0, 0, 0, + + 0x450, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, + 0x458, 0x459, 0x45a, 0x45b, 0x45c, 0x45d, 0x45e, 0x45f, + 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, + 0x438, 0x439, 0x43a, 0x43b, 0x43c, 0x43d, 0x43e, 0x43f, + 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, + 0x448, 0x449, 0x44a, 0x44b, 0x44c, 0x44d, 0x44e, 0x44f, + 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, + 0x418, 0x419, 0x41a, 0x41b, 0x41c, 0x41d, 0x41e, 0x41f, + 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, + 0x428, 0x429, 0x42a, 0x42b, 0x42c, 0x42d, 0x42e, 0x42f, + 0x400, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, + 0x408, 0x409, 0x40a, 0x40b, 0x40c, 0x40d, 0x40e, 0x40f, + 0x461, 0x460, 0x463, 0x462, 0x465, 0x464, 0x467, 0x466, + 0x469, 0x468, 0x46b, 0x46a, 0x46d, 0x46c, 0x46f, 0x46e, + 0x471, 0x470, 0x473, 0x472, 0x475, 0x474, 0x477, 0x476, + 0x479, 0x478, 0x47b, 0x47a, 0x47d, 0x47c, 0x47f, 0x47e, + 0x481, 0x480, 0, 0, 0, 0, 0, 0, + 0, 0, 0x48b, 0x48a, 0x48d, 0x48c, 0x48f, 0x48e, + 0x491, 0x490, 0x493, 0x492, 0x495, 0x494, 0x497, 0x496, + 0x499, 0x498, 0x49b, 0x49a, 0x49d, 0x49c, 0x49f, 0x49e, + 0x4a1, 0x4a0, 0x4a3, 0x4a2, 0x4a5, 0x4a4, 0x4a7, 0x4a6, + 0x4a9, 0x4a8, 0x4ab, 0x4aa, 0x4ad, 0x4ac, 0x4af, 0x4ae, + 0x4b1, 0x4b0, 0x4b3, 0x4b2, 0x4b5, 0x4b4, 0x4b7, 0x4b6, + 0x4b9, 0x4b8, 0x4bb, 0x4ba, 0x4bd, 0x4bc, 0x4bf, 0x4be, + 0, 0x4c2, 0x4c1, 0x4c4, 0x4c3, 0x4c6, 0x4c5, 0x4c8, + 0x4c7, 0x4ca, 0x4c9, 0x4cc, 0x4cb, 0x4ce, 0x4cd, 0, + 0x4d1, 0x4d0, 0x4d3, 0x4d2, 0x4d5, 0x4d4, 0x4d7, 0x4d6, + 0x4d9, 0x4d8, 0x4db, 0x4da, 0x4dd, 0x4dc, 0x4df, 0x4de, + 0x4e1, 0x4e0, 0x4e3, 0x4e2, 0x4e5, 0x4e4, 0x4e7, 0x4e6, + 0x4e9, 0x4e8, 0x4eb, 0x4ea, 0x4ed, 0x4ec, 0x4ef, 0x4ee, + 0x4f1, 0x4f0, 0x4f3, 0x4f2, 0x4f5, 0x4f4, 0, 0, + 0x4f9, 0x4f8, 0, 0, 0, 0, 0, 0, + + 0x501, 0x500, 0x503, 0x502, 0x505, 0x504, 0x507, 0x506, + 0x509, 0x508, 0x50b, 0x50a, 0x50d, 0x50c, 0x50f, 0x50e, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x561, 0x562, 0x563, 0x564, 0x565, 0x566, 0x567, + 0x568, 0x569, 0x56a, 0x56b, 0x56c, 0x56d, 0x56e, 0x56f, + 0x570, 0x571, 0x572, 0x573, 0x574, 0x575, 0x576, 0x577, + 0x578, 0x579, 0x57a, 0x57b, 0x57c, 0x57d, 0x57e, 0x57f, + 0x580, 0x581, 0x582, 0x583, 0x584, 0x585, 0x586, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x531, 0x532, 0x533, 0x534, 0x535, 0x536, 0x537, + 0x538, 0x539, 0x53a, 0x53b, 0x53c, 0x53d, 0x53e, 0x53f, + 0x540, 0x541, 0x542, 0x543, 0x544, 0x545, 0x546, 0x547, + 0x548, 0x549, 0x54a, 0x54b, 0x54c, 0x54d, 0x54e, 0x54f, + 0x550, 0x551, 0x552, 0x553, 0x554, 0x555, 0x556, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0x1e01, 0x1e00, 0x1e03, 0x1e02, 0x1e05, 0x1e04, 0x1e07, 0x1e06, + 0x1e09, 0x1e08, 0x1e0b, 0x1e0a, 0x1e0d, 0x1e0c, 0x1e0f, 0x1e0e, + 0x1e11, 0x1e10, 0x1e13, 0x1e12, 0x1e15, 0x1e14, 0x1e17, 0x1e16, + 0x1e19, 0x1e18, 0x1e1b, 0x1e1a, 0x1e1d, 0x1e1c, 0x1e1f, 0x1e1e, + 0x1e21, 0x1e20, 0x1e23, 0x1e22, 0x1e25, 0x1e24, 0x1e27, 0x1e26, + 0x1e29, 0x1e28, 0x1e2b, 0x1e2a, 0x1e2d, 0x1e2c, 0x1e2f, 0x1e2e, + 0x1e31, 0x1e30, 0x1e33, 0x1e32, 0x1e35, 0x1e34, 0x1e37, 0x1e36, + 0x1e39, 0x1e38, 0x1e3b, 0x1e3a, 0x1e3d, 0x1e3c, 0x1e3f, 0x1e3e, + 0x1e41, 0x1e40, 0x1e43, 0x1e42, 0x1e45, 0x1e44, 0x1e47, 0x1e46, + 0x1e49, 0x1e48, 0x1e4b, 0x1e4a, 0x1e4d, 0x1e4c, 0x1e4f, 0x1e4e, + 0x1e51, 0x1e50, 0x1e53, 0x1e52, 0x1e55, 0x1e54, 0x1e57, 0x1e56, + 0x1e59, 0x1e58, 0x1e5b, 0x1e5a, 0x1e5d, 0x1e5c, 0x1e5f, 0x1e5e, + 0x1e61, 0x1e60, 0x1e63, 0x1e62, 0x1e65, 0x1e64, 0x1e67, 0x1e66, + 0x1e69, 0x1e68, 0x1e6b, 0x1e6a, 0x1e6d, 0x1e6c, 0x1e6f, 0x1e6e, + 0x1e71, 0x1e70, 0x1e73, 0x1e72, 0x1e75, 0x1e74, 0x1e77, 0x1e76, + 0x1e79, 0x1e78, 0x1e7b, 0x1e7a, 0x1e7d, 0x1e7c, 0x1e7f, 0x1e7e, + 0x1e81, 0x1e80, 0x1e83, 0x1e82, 0x1e85, 0x1e84, 0x1e87, 0x1e86, + 0x1e89, 0x1e88, 0x1e8b, 0x1e8a, 0x1e8d, 0x1e8c, 0x1e8f, 0x1e8e, + 0x1e91, 0x1e90, 0x1e93, 0x1e92, 0x1e95, 0x1e94, 0, 0, + 0, 0, 0, 0x1e60, 0, 0, 0xdf, 0, + 0x1ea1, 0x1ea0, 0x1ea3, 0x1ea2, 0x1ea5, 0x1ea4, 0x1ea7, 0x1ea6, + 0x1ea9, 0x1ea8, 0x1eab, 0x1eaa, 0x1ead, 0x1eac, 0x1eaf, 0x1eae, + 0x1eb1, 0x1eb0, 0x1eb3, 0x1eb2, 0x1eb5, 0x1eb4, 0x1eb7, 0x1eb6, + 0x1eb9, 0x1eb8, 0x1ebb, 0x1eba, 0x1ebd, 0x1ebc, 0x1ebf, 0x1ebe, + 0x1ec1, 0x1ec0, 0x1ec3, 0x1ec2, 0x1ec5, 0x1ec4, 0x1ec7, 0x1ec6, + 0x1ec9, 0x1ec8, 0x1ecb, 0x1eca, 0x1ecd, 0x1ecc, 0x1ecf, 0x1ece, + 0x1ed1, 0x1ed0, 0x1ed3, 0x1ed2, 0x1ed5, 0x1ed4, 0x1ed7, 0x1ed6, + 0x1ed9, 0x1ed8, 0x1edb, 0x1eda, 0x1edd, 0x1edc, 0x1edf, 0x1ede, + 0x1ee1, 0x1ee0, 0x1ee3, 0x1ee2, 0x1ee5, 0x1ee4, 0x1ee7, 0x1ee6, + 0x1ee9, 0x1ee8, 0x1eeb, 0x1eea, 0x1eed, 0x1eec, 0x1eef, 0x1eee, + 0x1ef1, 0x1ef0, 0x1ef3, 0x1ef2, 0x1ef5, 0x1ef4, 0x1ef7, 0x1ef6, + 0x1ef9, 0x1ef8, 0, 0, 0, 0, 0, 0, + + 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, + 0x1f00, 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, + 0x1f18, 0x1f19, 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0, 0, + 0x1f10, 0x1f11, 0x1f12, 0x1f13, 0x1f14, 0x1f15, 0, 0, + 0x1f28, 0x1f29, 0x1f2a, 0x1f2b, 0x1f2c, 0x1f2d, 0x1f2e, 0x1f2f, + 0x1f20, 0x1f21, 0x1f22, 0x1f23, 0x1f24, 0x1f25, 0x1f26, 0x1f27, + 0x1f38, 0x1f39, 0x1f3a, 0x1f3b, 0x1f3c, 0x1f3d, 0x1f3e, 0x1f3f, + 0x1f30, 0x1f31, 0x1f32, 0x1f33, 0x1f34, 0x1f35, 0x1f36, 0x1f37, + 0x1f48, 0x1f49, 0x1f4a, 0x1f4b, 0x1f4c, 0x1f4d, 0, 0, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0, 0, + 0, 0x1f59, 0, 0x1f5b, 0, 0x1f5d, 0, 0x1f5f, + 0, 0x1f51, 0, 0x1f53, 0, 0x1f55, 0, 0x1f57, + 0x1f68, 0x1f69, 0x1f6a, 0x1f6b, 0x1f6c, 0x1f6d, 0x1f6e, 0x1f6f, + 0x1f60, 0x1f61, 0x1f62, 0x1f63, 0x1f64, 0x1f65, 0x1f66, 0x1f67, + 0x1fba, 0x1fbb, 0x1fc8, 0x1fc9, 0x1fca, 0x1fcb, 0x1fda, 0x1fdb, + 0x1ff8, 0x1ff9, 0x1fea, 0x1feb, 0x1ffa, 0x1ffb, 0, 0, + 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fb8, 0x1fb9, 0, 0x1fbc, 0, 0, 0, 0, + 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, 0x1fb3, 0, 0x399, 0, + 0, 0, 0, 0x1fcc, 0, 0, 0, 0, + 0x1f72, 0x1f73, 0x1f74, 0x1f75, 0x1fc3, 0, 0, 0, + 0x1fd8, 0x1fd9, 0, 0, 0, 0, 0, 0, + 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, 0, 0, 0, 0, + 0x1fe8, 0x1fe9, 0, 0, 0, 0x1fec, 0, 0, + 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, 0x1fe5, 0, 0, 0, + 0, 0, 0, 0x1ffc, 0, 0, 0, 0, + 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, 0x1ff3, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x3c9, 0, + 0, 0, 0x6b, 0xe5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217a, 0x217b, 0x217c, 0x217d, 0x217e, 0x217f, + 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, + 0x2168, 0x2169, 0x216a, 0x216b, 0x216c, 0x216d, 0x216e, 0x216f, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x24d0, 0x24d1, + 0x24d2, 0x24d3, 0x24d4, 0x24d5, 0x24d6, 0x24d7, 0x24d8, 0x24d9, + 0x24da, 0x24db, 0x24dc, 0x24dd, 0x24de, 0x24df, 0x24e0, 0x24e1, + 0x24e2, 0x24e3, 0x24e4, 0x24e5, 0x24e6, 0x24e7, 0x24e8, 0x24e9, + 0x24b6, 0x24b7, 0x24b8, 0x24b9, 0x24ba, 0x24bb, 0x24bc, 0x24bd, + 0x24be, 0x24bf, 0x24c0, 0x24c1, 0x24c2, 0x24c3, 0x24c4, 0x24c5, + 0x24c6, 0x24c7, 0x24c8, 0x24c9, 0x24ca, 0x24cb, 0x24cc, 0x24cd, + 0x24ce, 0x24cf, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, + 0xff48, 0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, + 0xff50, 0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, + 0xff58, 0xff59, 0xff5a, 0, 0, 0, 0, 0, + 0, 0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, + 0xff28, 0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, + 0xff30, 0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, + 0xff38, 0xff39, 0xff3a, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; +// 36602 bytes + +const TQ_INT8 TQUnicodeTables::decimal_info[] = { + 1, 0, 0, 0, 0, 0, 2, 0, + 0, 3, 3, 4, 3, 5, 6, 7, + 8, 0, 0, 9, 0, 0, 0, 10, + 11, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 13, 0, 0, 14, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, + + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 2, 3, -1, -1, -1, -1, + -1, 1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1, 2, 3, 4, + 5, 6, 7, 8, 9, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 1, 2, 3, + 4, 5, 6, 7, 8, 9, -1, -1, + + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 1, 2, + 3, 4, 5, 6, 7, 8, 9, -1, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, -1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; +// 40698 bytes + +#endif + +#ifdef TQT_NO_UNICODETABLES + +const TQ_UINT8 TQUnicodeTables::latin1_line_break_info[] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 15, 23, 19, 21, 22, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 26, 5, 2, 11, 8, 9, 11, 2, + 0, 1, 11, 8, 7, 14, 7, 6, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 7, 7, 11, 11, 11, 5, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 8, 1, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 15, 1, 11, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 3, 11, 9, 8, 8, 8, 11, 11, + 11, 11, 11, 2, 11, 15, 11, 11, + 9, 8, 11, 11, 16, 11, 11, 11, + 11, 11, 11, 2, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, +}; + +#else + +const TQ_UINT8 TQUnicodeTables::line_break_info[] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 2, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 2, 18, 2, 2, 19, 20, + 21, 2, 2, 2, 2, 2, 2, 2, + 22, 23, 24, 25, 2, 2, 2, 26, + 2, 27, 2, 2, 2, 2, 28, 29, + 30, 31, 32, 33, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 35, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 36, + 34, 34, 34, 34, 37, 2, 2, 2, + 2, 2, 2, 2, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 38, + 39, 39, 39, 39, 39, 39, 39, 39, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 34, 40, 41, 2, 42, 43, 44, + + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 15, 23, 19, 21, 22, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 26, 5, 2, 11, 8, 9, 11, 2, + 0, 1, 11, 8, 7, 14, 7, 6, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 7, 7, 11, 11, 11, 5, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 8, 1, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 15, 1, 11, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 3, 11, 9, 8, 8, 8, 11, 11, + 11, 11, 11, 2, 11, 15, 11, 11, + 9, 8, 11, 11, 16, 11, 11, 11, + 11, 11, 11, 2, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 16, 11, 11, 11, 16, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 19, 19, 19, 19, 11, + 19, 19, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 7, 15, 11, 11, 11, 11, 11, + 11, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 11, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 11, 19, 19, 19, 11, 19, + 11, 19, 19, 11, 19, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 19, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 11, 11, 19, + 19, 11, 19, 19, 19, 19, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 19, + 11, 19, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 19, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 19, 11, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 11, 11, + 11, 19, 19, 19, 19, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 19, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 19, 11, 19, 19, + 19, 19, 19, 19, 19, 11, 11, 19, + 19, 11, 11, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 8, 8, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 19, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 19, 11, 19, 19, + 19, 19, 19, 11, 11, 11, 11, 19, + 19, 11, 11, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 19, 19, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 19, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 19, 11, 19, 19, + 19, 19, 19, 19, 19, 19, 11, 19, + 19, 19, 11, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 19, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 19, 11, 19, 19, + 19, 19, 19, 19, 11, 11, 11, 19, + 19, 11, 11, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 19, 19, 19, 11, 11, 11, 19, 19, + 19, 11, 19, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 19, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 19, 19, 19, 19, 19, 11, 19, 19, + 19, 11, 19, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 19, 19, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 19, 19, 19, 19, 19, 11, 19, 19, + 19, 11, 19, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 19, 19, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 19, + 19, 19, 19, 19, 11, 11, 19, 19, + 19, 11, 19, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 11, 11, 11, 11, 19, + 19, 19, 19, 19, 19, 11, 19, 11, + 19, 19, 19, 19, 19, 19, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 19, 20, 20, 19, 19, 19, 19, + 19, 19, 19, 11, 11, 11, 11, 8, + 20, 20, 20, 20, 20, 20, 20, 19, + 19, 19, 19, 19, 19, 19, 19, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 4, 4, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 20, 20, 11, 20, 11, 11, 20, + 20, 11, 20, 11, 11, 20, 11, 11, + 11, 11, 11, 11, 20, 20, 20, 20, + 11, 20, 20, 20, 20, 20, 20, 20, + 11, 20, 20, 20, 11, 20, 11, 20, + 11, 11, 20, 20, 11, 20, 20, 20, + 20, 19, 20, 20, 19, 19, 19, 19, + 19, 19, 11, 19, 19, 20, 11, 11, + 20, 20, 20, 20, 20, 11, 20, 11, + 19, 19, 19, 19, 19, 19, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 20, 20, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 15, 3, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 19, 19, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 19, 11, 19, + 11, 19, 0, 1, 0, 1, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 11, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 19, 19, 19, 19, 19, 19, 19, 19, + 11, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 11, 20, 20, 20, 20, 20, + 11, 20, 20, 11, 19, 19, 19, 19, + 19, 19, 19, 11, 11, 11, 19, 19, + 19, 19, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 20, 20, 20, 20, 20, 20, 19, 19, + 19, 19, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 11, 11, 11, 11, 11, 12, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 11, 11, 11, 11, 11, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 15, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 15, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 1, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 19, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 19, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 4, 15, 4, 4, + 4, 4, 4, 8, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 16, 11, + 11, 11, 11, 19, 19, 19, 19, 11, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 19, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 15, 15, 15, 15, 15, 15, 15, 3, + 15, 15, 15, 18, 19, 19, 19, 19, + 15, 3, 15, 15, 17, 11, 11, 11, + 2, 2, 0, 2, 2, 2, 0, 2, + 11, 11, 11, 11, 13, 13, 13, 15, + 21, 21, 19, 19, 19, 19, 19, 3, + 9, 9, 9, 9, 9, 9, 9, 9, + 11, 2, 2, 11, 4, 11, 11, 11, + 11, 11, 11, 11, 4, 0, 1, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 15, + 3, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 19, 19, 19, 19, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 1, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 0, 1, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 8, 8, 8, 8, 8, 8, 8, 9, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 9, 11, 11, 11, 11, + 11, 9, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 8, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 9, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 8, 8, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 0, 1, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 1, 2, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 2, 2, 2, 2, 11, + 11, 11, 5, 5, 11, 11, 11, 11, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 1, + 0, 1, 0, 1, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 0, 1, 0, 1, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 0, 1, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, + + 12, 1, 1, 12, 12, 4, 12, 12, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 12, 12, 0, 1, 0, 1, + 0, 1, 0, 1, 4, 0, 1, 1, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 19, 19, 19, 19, 19, 19, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 4, 4, 12, 12, 12, + 11, 4, 12, 4, 12, 4, 12, 4, + 12, 4, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 4, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 4, 12, 4, 12, 4, + 12, 12, 12, 12, 12, 12, 4, 12, + 12, 12, 12, 12, 12, 4, 4, 11, + 11, 19, 19, 4, 4, 4, 4, 12, + 4, 4, 12, 4, 12, 4, 12, 4, + 12, 4, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 4, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 4, 12, 4, 12, 4, + 12, 12, 12, 12, 12, 12, 4, 12, + 12, 12, 12, 12, 12, 4, 4, 12, + 12, 12, 12, 4, 12, 4, 12, 12, + + 11, 11, 11, 11, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, + + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 19, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 0, 1, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 9, 11, 11, 11, + + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 19, 19, 19, 19, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 12, 12, 11, + 11, 12, 12, 12, 12, 12, 12, 12, + 1, 12, 1, 11, 4, 4, 5, 5, + 12, 0, 1, 0, 1, 0, 1, 12, + 12, 12, 12, 12, 12, 12, 12, 11, + 12, 8, 9, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 3, + + 11, 5, 12, 12, 8, 9, 12, 12, + 0, 1, 12, 12, 1, 12, 1, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 4, 4, 12, 12, 12, 5, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 0, 12, 1, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 0, 12, 1, 12, 0, + 1, 1, 0, 1, 1, 4, 11, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 4, 4, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 9, 8, 12, 12, 12, 8, 8, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 19, 19, 19, 25, 11, 11, 11, +}; +// 52474 bytes + +#endif + +// END OF GENERATED DATA + + + +#ifndef TQT_NO_UNICODETABLES +const TQ_UINT16 TQUnicodeTables::symmetricPairs[] = { + 0x0028, 0x0029, 0x003C, 0x003E, 0x005B, 0x005D, 0x007B, 0x007D, + 0x00AB, 0x00BB, 0x2039, 0x203A, 0x2045, 0x2046, 0x207D, 0x207E, + 0x208D, 0x208E, 0x2208, 0x220B, 0x2209, 0x220C, 0x220A, 0x220D, + 0x2215, 0x29F5, 0x223C, 0x223D, 0x2243, 0x22CD, 0x2252, 0x2253, + 0x2254, 0x2255, 0x2264, 0x2265, 0x2266, 0x2267, 0x2268, 0x2269, + 0x226A, 0x226B, 0x226E, 0x226F, 0x2270, 0x2271, 0x2272, 0x2273, + 0x2274, 0x2275, 0x2276, 0x2277, 0x2278, 0x2279, 0x227A, 0x227B, + 0x227C, 0x227D, 0x227E, 0x227F, 0x2280, 0x2281, 0x2282, 0x2283, + 0x2284, 0x2285, 0x2286, 0x2287, 0x2288, 0x2289, 0x228A, 0x228B, + 0x228F, 0x2290, 0x2291, 0x2292, 0x2298, 0x29B8, 0x22A2, 0x22A3, + 0x22A6, 0x2ADE, 0x22A8, 0x2AE4, 0x22A9, 0x2AE3, 0x22AB, 0x2AE5, + 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x22B4, 0x22B5, 0x22B6, 0x22B7, + 0x22C9, 0x22CA, 0x22CB, 0x22CC, 0x22D0, 0x22D1, 0x22D6, 0x22D7, + 0x22D8, 0x22D9, 0x22DA, 0x22DB, 0x22DC, 0x22DD, 0x22DE, 0x22DF, + 0x22E0, 0x22E1, 0x22E2, 0x22E3, 0x22E4, 0x22E5, 0x22E6, 0x22E7, + 0x22E8, 0x22E9, 0x22EA, 0x22EB, 0x22EC, 0x22ED, 0x22F0, 0x22F1, + 0x22F2, 0x22FA, 0x22F3, 0x22FB, 0x22F4, 0x22FC, 0x22F6, 0x22FD, + 0x22F7, 0x22FE, 0x2308, 0x2309, 0x230A, 0x230B, 0x2329, 0x232A, + 0x2768, 0x2769, 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, + 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x27D5, 0x27D6, + 0x27DD, 0x27DE, 0x27E2, 0x27E3, 0x27E4, 0x27E5, 0x27E6, 0x27E7, + 0x27E8, 0x27E9, 0x27EA, 0x27EB, 0x2983, 0x2984, 0x2985, 0x2986, + 0x2987, 0x2988, 0x2989, 0x298A, 0x298B, 0x298C, 0x298D, 0x2990, + 0x298E, 0x298F, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, + 0x2997, 0x2998, 0x29C0, 0x29C1, 0x29C4, 0x29C5, 0x29CF, 0x29D0, + 0x29D1, 0x29D2, 0x29D4, 0x29D5, 0x29D8, 0x29D9, 0x29DA, 0x29DB, + 0x29F8, 0x29F9, 0x29FC, 0x29FD, 0x2A2B, 0x2A2C, 0x2A34, 0x2A35, + 0x2A3C, 0x2A3D, 0x2A64, 0x2A65, 0x2A79, 0x2A7A, 0x2A7D, 0x2A7E, + 0x2A7F, 0x2A80, 0x2A81, 0x2A82, 0x2A83, 0x2A84, 0x2A8B, 0x2A8C, + 0x2A91, 0x2A92, 0x2A93, 0x2A94, 0x2A95, 0x2A96, 0x2A97, 0x2A98, + 0x2A99, 0x2A9A, 0x2A9B, 0x2A9C, 0x2AA1, 0x2AA2, 0x2AA6, 0x2AA7, + 0x2AA8, 0x2AA9, 0x2AAA, 0x2AAB, 0x2AAC, 0x2AAD, 0x2AAF, 0x2AB0, + 0x2AB3, 0x2AB4, 0x2ABB, 0x2ABC, 0x2ABD, 0x2ABE, 0x2ABF, 0x2AC0, + 0x2AC1, 0x2AC2, 0x2AC3, 0x2AC4, 0x2AC5, 0x2AC6, 0x2ACD, 0x2ACE, + 0x2ACF, 0x2AD0, 0x2AD1, 0x2AD2, 0x2AD3, 0x2AD4, 0x2AD5, 0x2AD6, + 0x2AEC, 0x2AED, 0x2AF7, 0x2AF8, 0x2AF9, 0x2AFA, 0x3008, 0x3009, + 0x300A, 0x300B, 0x300C, 0x300D, 0x300E, 0x300F, 0x3010, 0x3011, + 0x3014, 0x3015, 0x3016, 0x3017, 0x3018, 0x3019, 0x301A, 0x301B, + 0xFF08, 0xFF09, 0xFF1C, 0xFF1E, 0xFF3B, 0xFF3D, 0xFF5B, 0xFF5D, + 0xFF5F, 0xFF60, 0xFF62, 0xFF63, +}; + +// ### shouldn't this be const? +const int TQUnicodeTables::symmetricPairsSize = + sizeof(symmetricPairs)/sizeof(symmetricPairs[0]); + +#else + +/* + only include info for the first unicode range (latin1) when building + without unicode tables. +*/ +const TQ_UINT8 TQUnicodeTables::unicode_info[] = { + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 7, 26, 26, 26, 28, 26, 26, 26, + 22, 23, 26, 27, 26, 21, 26, 26, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 26, 26, 27, 27, 27, 26, + 26, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 22, 26, 23, 29, 20, + 29, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 27, 23, 27, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 7, 26, 28, 28, 28, 28, 30, 30, + 29, 30, 16, 24, 27, 21, 30, 29, + 30, 27, 6, 6, 29, 16, 30, 26, + 29, 6, 16, 25, 6, 6, 6, 26, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 27, + 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 27, + 16, 16, 16, 16, 16, 16, 16, 16 +}; + +#endif + +/* + * ---------------------------------------------------------------------- + * End of unicode tables + * ---------------------------------------------------------------------- + */ + +enum Script { + // European Alphabetic Scripts + Latin, + Greek, + Cyrillic, + Armenian, + Georgian, + Runic, + Ogham, + SpacingModifiers, + CombiningMarks, + + // Middle Eastern Scripts + Hebrew, + Arabic, + Syriac, + Thaana, + + // South and Southeast Asian Scripts + Devanagari, + Bengali, + Gurmukhi, + Gujarati, + Oriya, + Tamil, + Telugu, + Kannada, + Malayalam, + Sinhala, + Thai, + Lao, + Tibetan, + Myanmar, + Khmer, + + // East Asian Scripts + Han, + Hiragana, + Katakana, + Hangul, + Bopomofo, + Yi, + + // Additional Scripts + Ethiopic, + Cherokee, + CanadianAboriginal, + Mongolian, + + // Symbols + CurrencySymbols, + LetterlikeSymbols, + NumberForms, + MathematicalOperators, + TechnicalSymbols, + GeometricSymbols, + MiscellaneousSymbols, + EnclosedAndSquare, + Braille, + + Unicode, + + // some scripts added in Unicode 3.2 + Tagalog, + Hanunoo, + Buhid, + Tagbanwa, + + KatakanaHalfWidth, // from JIS X 0201 + + // from Unicode 4.0 + Limbu, + TaiLe, + + // End + NScripts, + UnknownScript = NScripts +}; + +// copied form tqfont.h, as we can't include it in tools. Do not modify without +// changing the script enum in tqfont.h aswell. +const unsigned char TQUnicodeTables::otherScripts [128] = { +#define SCRIPTS_02 0 + 0xaf, Latin, 0xff, SpacingModifiers, // row 0x02, index 0 +#define SCRIPTS_03 4 + 0x6f, CombiningMarks, 0xff, Greek, // row 0x03, index 4 +#define SCRIPTS_05 8 + 0x2f, Cyrillic, 0x8f, Armenian, 0xff, Hebrew, // row 0x05, index 8 +#define SCRIPTS_07 14 + 0x4f, Syriac, 0x7f, Unicode, 0xbf, Thaana, + 0xff, Unicode, // row 0x07, index 14 +#define SCRIPTS_10 22 + 0x9f, Myanmar, 0xff, Georgian, // row 0x10, index 20 +#define SCRIPTS_13 26 + 0x7f, Ethiopic, 0x9f, Unicode, 0xff, Cherokee, // row 0x13, index 24 +#define SCRIPTS_16 32 + 0x7f, CanadianAboriginal, 0x9f, Ogham, + 0xff, Runic, // row 0x16 index 30 +#define SCRIPTS_17 38 + 0x1f, Tagalog, 0x3f, Hanunoo, 0x5f, Buhid, + 0x7f, Tagbanwa, 0xff, Khmer, // row 0x17, index 36 +#define SCRIPTS_18 48 + 0xaf, Mongolian, 0xff, Unicode, // row 0x18, index 46 +#define SCRIPTS_19 52 + 0x4f, Limbu, 0x7f, TaiLe, 0xdf, Unicode, 0xff, Khmer, +#define SCRIPTS_20 60 + 0x0a, Unicode, 0x0d, UnknownScript, 0x6f, Unicode, 0x9f, NumberForms, + 0xab, CurrencySymbols, 0xac, Latin, + 0xcf, CurrencySymbols, 0xff, CombiningMarks, // row 0x20, index 50 +#define SCRIPTS_21 76 + 0x4f, LetterlikeSymbols, 0x8f, NumberForms, + 0xff, MathematicalOperators, // row 0x21, index 62 +#define SCRIPTS_24 82 + 0x5f, TechnicalSymbols, 0xff, EnclosedAndSquare, // row 0x24, index 68 +#define SCRIPTS_2e 86 + 0x7f, Unicode, 0xff, Han, // row 0x2e, index 72 +#define SCRIPTS_30 90 + 0x3f, Han, 0x9f, Hiragana, 0xff, Katakana, // row 0x30, index 76 +#define SCRIPTS_31 96 + 0x2f, Bopomofo, 0x8f, Hangul, 0x9f, Han, + 0xff, Unicode, // row 0x31, index 82 +#define SCRIPTS_fb 104 + 0x06, Latin, 0x1c, Unicode, 0x4f, Hebrew, + 0xff, Arabic, // row 0xfb, index 90 +#define SCRIPTS_fe 112 + 0x1f, Unicode, 0x2f, CombiningMarks, 0x6f, Han, + 0xff, Arabic, // row 0xfe, index 98 +#define SCRIPTS_ff 120 + 0x60, Han, // row 0xff, index 106 + 0x9f, KatakanaHalfWidth, 0xef, Han, 0xff, Unicode +}; + +// (uc-0x0900)>>7 +const unsigned char TQUnicodeTables::indicScripts [] = +{ + Devanagari, Bengali, + Gurmukhi, Gujarati, + Oriya, Tamil, + Telugu, Kannada, + Malayalam, Sinhala, + Thai, Lao +}; + + +// 0x80 + x: x is the offset into the otherScripts table +const unsigned char TQUnicodeTables::scriptTable[256] = +{ + Latin, Latin, 0x80+SCRIPTS_02, 0x80+SCRIPTS_03, + Cyrillic, 0x80+SCRIPTS_05, Arabic, 0x80+SCRIPTS_07, + Unicode, SCRIPTS_INDIC, SCRIPTS_INDIC, SCRIPTS_INDIC, + SCRIPTS_INDIC, SCRIPTS_INDIC, SCRIPTS_INDIC, Tibetan, + + 0x80+SCRIPTS_10, Hangul, Ethiopic, 0x80+SCRIPTS_13, + CanadianAboriginal, CanadianAboriginal, 0x80+SCRIPTS_16, 0x80+SCRIPTS_17, + 0x80+SCRIPTS_18, 0x80+SCRIPTS_19, Unicode, Unicode, + Unicode, Unicode, Latin, Greek, + + 0x80+SCRIPTS_20, 0x80+SCRIPTS_21, MathematicalOperators, TechnicalSymbols, + 0x80+SCRIPTS_24, GeometricSymbols, MiscellaneousSymbols, MiscellaneousSymbols, + Braille, Unicode, Unicode, Unicode, + Unicode, Unicode, 0x80+SCRIPTS_2e, Han, + + 0x80+SCRIPTS_30, 0x80+SCRIPTS_31, EnclosedAndSquare, EnclosedAndSquare, + Han, Han, Han, Han, + Han, Han, Han, Han, + Han, Han, Han, Han, + + Han, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Han, Han, Han, Han, Han, Han, + + Han, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Han, Han, Han, Han, Han, Han, + + Han, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Han, Han, Han, Han, Han, Han, + + Han, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Han, Han, Han, Han, Han, Han, + + + Han, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Han, Han, Han, Han, Han, Han, + + Han, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Han, Han, Han, Han, Han, Han, + + Yi, Yi, Yi, Yi, Yi, Unicode, Unicode, Unicode, + Unicode, Unicode, Unicode, Unicode, Hangul, Hangul, Hangul, Hangul, + + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, + + Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, + Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, + + Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, + Unicode, Han, Han, 0x80+SCRIPTS_fb, Arabic, Arabic, 0x80+SCRIPTS_fe, 0x80+SCRIPTS_ff +}; + diff --git a/src/tools/tqunicodetables_p.h b/src/tools/tqunicodetables_p.h new file mode 100644 index 000000000..18045f470 --- /dev/null +++ b/src/tools/tqunicodetables_p.h @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** ??? +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the widgets module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQUNICODETABLES_P_H +#define TQUNICODETABLES_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqstring.h" +#endif // QT_H + +#ifdef TQT_NO_UNICODETABLES +# include +#endif + +class TQUnicodeTables { +public: + static const TQ_UINT8 unicode_info[]; +#ifndef TQT_NO_UNICODETABLES + static const TQ_UINT16 decomposition_map[]; + static const TQ_UINT16 decomposition_info[]; + static const TQ_UINT16 ligature_map[]; + static const TQ_UINT16 ligature_info[]; + static const TQ_UINT8 direction_info[]; + static const TQ_UINT8 combining_info[]; + static const TQ_UINT16 case_info[]; + static const TQ_INT8 decimal_info[]; + static const TQ_UINT16 symmetricPairs[]; + static const int symmetricPairsSize; + static const TQ_UINT8 line_break_info[]; +#else + static const TQ_UINT8 latin1_line_break_info[]; +#endif + static const unsigned char otherScripts[]; + static const unsigned char indicScripts[]; + static const unsigned char scriptTable[]; + enum { SCRIPTS_INDIC = 0x7e }; + + // see http://www.unicode.org/reports/tr14/tr14-13.html + // we don't use the XX and AI properties and map them to AL instead. + enum LineBreakClass { + LineBreak_OP, LineBreak_CL, LineBreak_QU, LineBreak_GL, LineBreak_NS, + LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR, LineBreak_PO, + LineBreak_NU, LineBreak_AL, LineBreak_ID, LineBreak_IN, LineBreak_HY, + LineBreak_BA, LineBreak_BB, LineBreak_B2, LineBreak_ZW, LineBreak_CM, + LineBreak_SA, LineBreak_BK, LineBreak_CR, LineBreak_LF, LineBreak_SG, + LineBreak_CB, LineBreak_SP + }; +}; + + +inline TQChar::Category category( const TQChar &c ) +{ +#ifdef TQT_NO_UNICODETABLES + if ( c.unicode() > 0xff ) return TQChar::Letter_Uppercase; //######## + return (TQChar::Category)TQUnicodeTables::unicode_info[c.unicode()]; +#else + int uc = ((int)TQUnicodeTables::unicode_info[c.row()]) << 8; + uc += c.cell(); + return (TQChar::Category)TQUnicodeTables::unicode_info[uc]; +#endif // TQT_NO_UNICODETABLES +} + +inline TQChar lower( const TQChar &c ) +{ +#ifndef TQT_NO_UNICODETABLES + int row = c.row(); + int cell = c.cell(); + int ci = TQUnicodeTables::case_info[row]; + int uc = ((int)TQUnicodeTables::unicode_info[c.row()]) << 8; + uc += c.cell(); + if (TQUnicodeTables::unicode_info[uc] != TQChar::Letter_Uppercase || !ci) + return c; + TQ_UINT16 lower = TQUnicodeTables::case_info[(ci<<8)+cell]; + return lower ? TQChar(lower) : c; +#else + if ( c.row() ) + return c; + return TQChar( tolower((uchar) c.latin1()) ); +#endif +} + +inline TQChar upper( const TQChar &c ) +{ +#ifndef TQT_NO_UNICODETABLES + int row = c.row(); + int cell = c.cell(); + int ci = TQUnicodeTables::case_info[row]; + int uc = ((int)TQUnicodeTables::unicode_info[c.row()]) << 8; + uc += c.cell(); + if (TQUnicodeTables::unicode_info[uc] != TQChar::Letter_Lowercase || !ci) + return c; + TQ_UINT16 upper = TQUnicodeTables::case_info[(ci<<8)+cell]; + return upper ? TQChar(upper) : c; +#else + if ( c.row() ) + return c; + return TQChar( toupper((uchar) c.latin1()) ); +#endif +} + +inline TQChar::Direction direction( const TQChar &c ) +{ +#ifndef TQT_NO_UNICODETABLES + int pos = TQUnicodeTables::direction_info[c.row()]; + return (TQChar::Direction) (TQUnicodeTables::direction_info[(pos<<8)+c.cell()] & 0x1f); +#else + Q_UNUSED(c); + return TQChar::DirL; +#endif +} + +inline bool mirrored( const TQChar &c ) +{ +#ifndef TQT_NO_UNICODETABLES + int pos = TQUnicodeTables::direction_info[c.row()]; + return TQUnicodeTables::direction_info[(pos<<8)+c.cell()] > 128; +#else + Q_UNUSED(c); + return FALSE; +#endif +} + + +inline TQChar mirroredChar( const TQChar &ch ) +{ +#ifndef TQT_NO_UNICODETABLES + if(!::mirrored( ch )) + return ch; + + int i; + int c = ch.unicode(); + for (i = 0; i < TQUnicodeTables::symmetricPairsSize; i ++) { + if (TQUnicodeTables::symmetricPairs[i] == c) + return TQUnicodeTables::symmetricPairs[(i%2) ? (i-1) : (i+1)]; + } +#endif + return ch; +} + +inline TQChar::Joining joining( const TQChar &ch ) +{ +#ifndef TQT_NO_UNICODETABLES + int pos = TQUnicodeTables::direction_info[ch.row()]; + return (TQChar::Joining) ((TQUnicodeTables::direction_info[(pos<<8)+ch.cell()] >> 5) &0x3); +#else + Q_UNUSED(ch); + return TQChar::OtherJoining; +#endif +} + +inline bool isMark( const TQChar &ch ) +{ + TQChar::Category c = ::category( ch ); + return c >= TQChar::Mark_NonSpacing && c <= TQChar::Mark_Enclosing; +} + +inline unsigned char combiningClass( const TQChar &ch ) +{ +#ifndef TQT_NO_UNICODETABLES + const int pos = TQUnicodeTables::combining_info[ch.row()]; + return TQUnicodeTables::combining_info[(pos<<8) + ch.cell()]; +#else + Q_UNUSED(ch); + return 0; +#endif +} + +inline bool isSpace( const TQChar &ch ) +{ + if( ch.unicode() >= 9 && ch.unicode() <=13 ) return TRUE; + TQChar::Category c = ::category( ch ); + return c >= TQChar::Separator_Space && c <= TQChar::Separator_Paragraph; +} + +inline int lineBreakClass( const TQChar &ch ) +{ +#ifdef TQT_NO_UNICODETABLES + return ch.row() ? TQUnicodeTables::LineBreak_AL + : TQUnicodeTables::latin1_line_break_info[ch.cell()]; +#else + int pos = ((int)TQUnicodeTables::line_break_info[ch.row()] << 8) + ch.cell(); + return TQUnicodeTables::line_break_info[pos]; +#endif +} + +inline int scriptForChar( ushort uc ) +{ + unsigned char script = TQUnicodeTables::scriptTable[(uc>>8)]; + if ( script >= TQUnicodeTables::SCRIPTS_INDIC ) { + if ( script == TQUnicodeTables::SCRIPTS_INDIC ) { + script = TQUnicodeTables::indicScripts[ (uc-0x0900)>>7 ]; + } else { + // 0x80 + SCRIPTS_xx + unsigned char index = script-0x80; + unsigned char cell = uc &0xff; + while( TQUnicodeTables::otherScripts[index++] < cell ) + index++; + script = TQUnicodeTables::otherScripts[index]; + } + } + return script; +} + +#ifdef TQ_WS_X11 +#define SCRIPT_FOR_CHAR( script, c ) \ +do { \ + unsigned short _uc = (c).unicode(); \ + if ( _uc < 0x100 ) { \ + script = TQFont::Latin; \ + } else { \ + script = (TQFont::Script)scriptForChar( _uc ); \ + } \ +} while( FALSE ) +#else +#define SCRIPT_FOR_CHAR( script, c ) \ + script = (TQFont::Script)scriptForChar( (c).unicode() ) +#endif + +#endif diff --git a/src/widgets/qeffects.cpp b/src/widgets/qeffects.cpp deleted file mode 100644 index 5fce0e854..000000000 --- a/src/widgets/qeffects.cpp +++ /dev/null @@ -1,675 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQEffects functions -** -** Created : 000621 -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the widgets module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "ntqapplication.h" -#ifndef TQT_NO_EFFECTS -#include "tqwidget.h" -#include "qeffects_p.h" -#include "tqpixmap.h" -#include "tqimage.h" -#include "tqtimer.h" -#include "tqdatetime.h" -#include "tqguardedptr.h" -#include "tqscrollview.h" - -/* - Internal class to get access to protected TQWidget-members -*/ - -class TQAccessWidget : public TQWidget -{ - friend class TQAlphaWidget; - friend class TQRollEffect; -public: - TQAccessWidget( TQWidget* parent=0, const char* name=0, WFlags f = 0 ) - : TQWidget( parent, name, f ) {} -}; - -/* - Internal class TQAlphaWidget. - - The TQAlphaWidget is shown while the animation lasts - and displays the pixmap resulting from the alpha blending. -*/ - -class TQAlphaWidget: public TQWidget, private TQEffects -{ - TQ_OBJECT -public: - TQAlphaWidget( TQWidget* w, WFlags f = 0 ); - - void run( int time ); - -protected: - void paintEvent( TQPaintEvent* e ); - void closeEvent( TQCloseEvent* ); - bool eventFilter( TQObject* o, TQEvent* e ); - void alphaBlend(); - -protected slots: - void render(); - -private: - TQPixmap pm; - double alpha; - TQImage back; - TQImage front; - TQImage mixed; - TQGuardedPtr widget; - int duration; - int elapsed; - bool showWidget; - TQTimer anim; - TQTime checkTime; -}; - -static TQAlphaWidget* q_blend = 0; - -/* - Constructs a TQAlphaWidget. -*/ -TQAlphaWidget::TQAlphaWidget( TQWidget* w, WFlags f ) - : TQWidget( TQApplication::desktop()->screen(TQApplication::desktop()->screenNumber(w)), - "qt internal alpha effect widget", f ) -{ -#if 1 //ndef TQ_WS_WIN - setEnabled( FALSE ); -#endif - - pm.setOptimization( TQPixmap::BestOptim ); - setBackgroundMode( NoBackground ); - widget = (TQAccessWidget*)w; - alpha = 0; -} - -/* - \reimp -*/ -void TQAlphaWidget::paintEvent( TQPaintEvent* ) -{ - bitBlt( this, TQPoint(0,0), &pm ); -} - -/* - Starts the alphablending animation. - The animation will take about \a time ms -*/ -void TQAlphaWidget::run( int time ) -{ - duration = time; - - if ( duration < 0 ) - duration = 150; - - if ( !widget ) - return; - - elapsed = 0; - checkTime.start(); - - showWidget = TRUE; - tqApp->installEventFilter( this ); - - widget->setWState( WState_Visible ); - - move( widget->geometry().x(),widget->geometry().y() ); - resize( widget->size().width(), widget->size().height() ); - - front = TQImage( widget->size(), 32 ); - front = TQPixmap::grabWidget( widget ); - - back = TQImage( widget->size(), 32 ); - back = TQPixmap::grabWindow( TQApplication::desktop()->winId(), - widget->geometry().x(), widget->geometry().y(), - widget->geometry().width(), widget->geometry().height() ); - - if ( !back.isNull() && checkTime.elapsed() < duration / 2 ) { - mixed = back.copy(); - pm = mixed; - show(); - setEnabled(FALSE); - - connect( &anim, TQ_SIGNAL(timeout()), this, TQ_SLOT(render())); - anim.start( 1 ); - } else { - duration = 0; - render(); - } -} - -/* - \reimp -*/ -bool TQAlphaWidget::eventFilter( TQObject* o, TQEvent* e ) -{ - switch ( e->type() ) { - case TQEvent::Move: - if ( o != widget ) - break; - move( widget->geometry().x(),widget->geometry().y() ); - update(); - break; - case TQEvent::Hide: - case TQEvent::Close: - if ( o != widget ) - break; - case TQEvent::MouseButtonPress: -#ifndef TQT_NO_SCROLLVIEW - if ( ::tqt_cast(o) ) - break; -#endif - case TQEvent::MouseButtonDblClick: - setEnabled(TRUE); - showWidget = FALSE; - render(); - break; - case TQEvent::KeyPress: - { - TQKeyEvent *ke = (TQKeyEvent*)e; - if ( ke->key() == Key_Escape ) - showWidget = FALSE; - else - duration = 0; - render(); - break; - } - default: - break; - } - return TQWidget::eventFilter( o, e ); -} - -/* - \reimp -*/ -void TQAlphaWidget::closeEvent( TQCloseEvent *e ) -{ - e->accept(); - if ( !q_blend ) - return; - - showWidget = FALSE; - render(); - - TQWidget::closeEvent( e ); -} - -/* - Render alphablending for the time elapsed. - - Show the blended widget and free all allocated source - if the blending is finished. -*/ -void TQAlphaWidget::render() -{ - int tempel = checkTime.elapsed(); - if ( elapsed >= tempel ) - elapsed++; - else - elapsed = tempel; - - if ( duration != 0 ) - alpha = tempel / double(duration); - else - alpha = 1; - if ( alpha >= 1 || !showWidget) { - anim.stop(); - tqApp->removeEventFilter( this ); - - if ( widget ) { - if ( !showWidget ) { -#ifdef TQ_WS_WIN - setEnabled(TRUE); - setFocus(); -#endif - widget->hide(); - widget->setWState( WState_ForceHide ); - widget->clearWState( WState_Visible ); - } else if ( duration ) { - BackgroundMode bgm = widget->backgroundMode(); - TQColor erc = widget->eraseColor(); - const TQPixmap *erp = widget->erasePixmap(); - - widget->clearWState( WState_Visible ); - widget->setBackgroundMode( NoBackground ); - widget->show(); - if ( bgm != FixedColor && bgm != FixedPixmap ) { - widget->clearWState( WState_Visible ); // prevent update in setBackgroundMode - widget->setBackgroundMode( bgm ); - widget->setWState( WState_Visible ); - } - if ( erc.isValid() ) { - widget->setEraseColor( erc ); - } else if ( erp ) { - widget->setErasePixmap( *erp ); - } - } else { - widget->clearWState( WState_Visible ); - widget->show(); - } - } - q_blend = 0; - deleteLater(); - } else { - if (widget) - widget->clearWState( WState_ForceHide ); - alphaBlend(); - pm = mixed; - repaint( FALSE ); - } -} - -/* - Calculate an alphablended image. -*/ -void TQAlphaWidget::alphaBlend() -{ - const double ia = 1-alpha; - const int sw = front.width(); - const int sh = front.height(); - switch( front.depth() ) { - case 32: - { - TQ_UINT32** md = (TQ_UINT32**)mixed.jumpTable(); - TQ_UINT32** bd = (TQ_UINT32**)back.jumpTable(); - TQ_UINT32** fd = (TQ_UINT32**)front.jumpTable(); - - for (int sy = 0; sy < sh; sy++ ) { - TQ_UINT32* bl = ((TQ_UINT32*)bd[sy]); - TQ_UINT32* fl = ((TQ_UINT32*)fd[sy]); - for (int sx = 0; sx < sw; sx++ ) { - TQ_UINT32 bp = bl[sx]; - TQ_UINT32 fp = fl[sx]; - - ((TQ_UINT32*)(md[sy]))[sx] = tqRgb(int (tqRed(bp)*ia + tqRed(fp)*alpha), - int (tqGreen(bp)*ia + tqGreen(fp)*alpha), - int (tqBlue(bp)*ia + tqBlue(fp)*alpha) ); - } - } - } - default: - break; - } -} - -/* - Internal class TQRollEffect - - The TQRollEffect widget is shown while the animation lasts - and displays a scrolling pixmap. -*/ - -class TQRollEffect : public TQWidget, private TQEffects -{ - TQ_OBJECT -public: - TQRollEffect( TQWidget* w, WFlags f, DirFlags orient ); - - void run( int time ); - -protected: - void paintEvent( TQPaintEvent* ); - bool eventFilter( TQObject*, TQEvent* ); - void closeEvent( TQCloseEvent* ); - -private slots: - void scroll(); - -private: - TQGuardedPtr widget; - - int currentHeight; - int currentWidth; - int totalHeight; - int totalWidth; - - int duration; - int elapsed; - bool done; - bool showWidget; - int orientation; - - TQTimer anim; - TQTime checkTime; - - TQPixmap pm; -}; - -static TQRollEffect* q_roll = 0; - -/* - Construct a TQRollEffect widget. -*/ -TQRollEffect::TQRollEffect( TQWidget* w, WFlags f, DirFlags orient ) - : TQWidget( TQApplication::desktop()->screen(TQApplication::desktop()->screenNumber(w)), - "qt internal roll effect widget", f ), orientation(orient) -{ -#if 1 //ndef TQ_WS_WIN - setEnabled( FALSE ); -#endif - widget = (TQAccessWidget*) w; - Q_ASSERT( widget ); - - setBackgroundMode( NoBackground ); - - if ( widget->testWState( WState_Resized ) ) { - totalWidth = widget->width(); - totalHeight = widget->height(); - } else { - totalWidth = widget->sizeHint().width(); - totalHeight = widget->sizeHint().height(); - } - - currentHeight = totalHeight; - currentWidth = totalWidth; - - if ( orientation & (RightScroll|LeftScroll) ) - currentWidth = 0; - if ( orientation & (DownScroll|UpScroll) ) - currentHeight = 0; - - pm.setOptimization( TQPixmap::BestOptim ); - pm = TQPixmap::grabWidget( widget ); -} - -/* - \reimp -*/ -void TQRollEffect::paintEvent( TQPaintEvent* ) -{ - int x = orientation & RightScroll ? TQMIN(0, currentWidth - totalWidth) : 0; - int y = orientation & DownScroll ? TQMIN(0, currentHeight - totalHeight) : 0; - - bitBlt( this, x, y, &pm, - 0, 0, pm.width(), pm.height(), CopyROP, TRUE ); -} - -/* - \reimp -*/ -bool TQRollEffect::eventFilter( TQObject* o, TQEvent* e ) -{ - switch ( e->type() ) { - case TQEvent::Move: - if ( o != widget ) - break; - move( widget->geometry().x(),widget->geometry().y() ); - update(); - break; - case TQEvent::Hide: - case TQEvent::Close: - if ( o != widget || done ) - break; - setEnabled(TRUE); - showWidget = FALSE; - done = TRUE; - scroll(); - break; - case TQEvent::MouseButtonPress: -#ifndef TQT_NO_SCROLLVIEW - if ( ::tqt_cast(o) ) - break; -#endif - case TQEvent::MouseButtonDblClick: - if ( done ) - break; - setEnabled(TRUE); - showWidget = FALSE; - done = TRUE; - scroll(); - break; - case TQEvent::KeyPress: - { - TQKeyEvent *ke = (TQKeyEvent*)e; - if ( ke->key() == Key_Escape ) - showWidget = FALSE; - done = TRUE; - scroll(); - break; - } - default: - break; - } - return TQWidget::eventFilter( o, e ); -} - -/* - \reimp -*/ -void TQRollEffect::closeEvent( TQCloseEvent *e ) -{ - e->accept(); - if ( done ) - return; - - showWidget = FALSE; - done = TRUE; - scroll(); - - TQWidget::closeEvent( e ); -} - -/* - Start the animation. - - The animation will take about \a time ms, or is - calculated if \a time is negative -*/ -void TQRollEffect::run( int time ) -{ - if ( !widget ) - return; - - duration = time; - elapsed = 0; - - if ( duration < 0 ) { - int dist = 0; - if ( orientation & (RightScroll|LeftScroll) ) - dist += totalWidth - currentWidth; - if ( orientation & (DownScroll|UpScroll) ) - dist += totalHeight - currentHeight; - duration = TQMIN( TQMAX( dist/3, 50 ), 120 ); - } - - connect( &anim, TQ_SIGNAL(timeout()), this, TQ_SLOT(scroll())); - - widget->setWState( WState_Visible ); - - move( widget->geometry().x(),widget->geometry().y() ); - resize( TQMIN( currentWidth, totalWidth ), TQMIN( currentHeight, totalHeight ) ); - - show(); - setEnabled(FALSE); - - tqApp->installEventFilter( this ); - - showWidget = TRUE; - done = FALSE; - anim.start( 1 ); - checkTime.start(); -} - -/* - Roll according to the time elapsed. -*/ -void TQRollEffect::scroll() -{ - if ( !done && widget) { - widget->clearWState( WState_ForceHide ); - int tempel = checkTime.elapsed(); - if ( elapsed >= tempel ) - elapsed++; - else - elapsed = tempel; - - if ( currentWidth != totalWidth ) { - currentWidth = totalWidth * (elapsed/duration) - + ( 2 * totalWidth * (elapsed%duration) + duration ) - / ( 2 * duration ); - // equiv. to int( (totalWidth*elapsed) / duration + 0.5 ) - done = (currentWidth >= totalWidth); - } - if ( currentHeight != totalHeight ) { - currentHeight = totalHeight * (elapsed/duration) - + ( 2 * totalHeight * (elapsed%duration) + duration ) - / ( 2 * duration ); - // equiv. to int( (totalHeight*elapsed) / duration + 0.5 ) - done = (currentHeight >= totalHeight); - } - done = ( currentHeight >= totalHeight ) && - ( currentWidth >= totalWidth ); - - int w = totalWidth; - int h = totalHeight; - int x = widget->geometry().x(); - int y = widget->geometry().y(); - - if ( orientation & RightScroll || orientation & LeftScroll ) - w = TQMIN( currentWidth, totalWidth ); - if ( orientation & DownScroll || orientation & UpScroll ) - h = TQMIN( currentHeight, totalHeight ); - - setUpdatesEnabled( FALSE ); - if ( orientation & UpScroll ) - y = widget->geometry().y() + TQMAX( 0, totalHeight - currentHeight ); - if ( orientation & LeftScroll ) - x = widget->geometry().x() + TQMAX( 0, totalWidth - currentWidth ); - if ( orientation & UpScroll || orientation & LeftScroll ) - move( x, y ); - - resize( w, h ); - setUpdatesEnabled( TRUE ); - repaint( FALSE ); - } - if ( done ) { - anim.stop(); - tqApp->removeEventFilter( this ); - if ( widget ) { - if ( !showWidget ) { -#ifdef TQ_WS_WIN - setEnabled(TRUE); - setFocus(); -#endif - widget->hide(); - widget->setWState( WState_ForceHide ); - widget->clearWState( WState_Visible ); - } else { - BackgroundMode bgm = widget->backgroundMode(); - TQColor erc = widget->eraseColor(); - const TQPixmap *erp = widget->erasePixmap(); - - widget->clearWState( WState_Visible ); - widget->setBackgroundMode( NoBackground ); - widget->show(); - if ( bgm != FixedColor && bgm != FixedPixmap ) { - widget->clearWState( WState_Visible ); // prevent update in setBackgroundMode - widget->setBackgroundMode( bgm ); - widget->setWState( WState_Visible ); - } - if ( erc.isValid() ) { - widget->setEraseColor( erc ); - } else if ( erp ) { - widget->setErasePixmap( *erp ); - } - } - } - q_roll = 0; - deleteLater(); - } -} - -/* - Delete this after timeout -*/ - -#include "qeffects.moc" - -/*! - Scroll widget \a w in \a time ms. \a orient may be 1 (vertical), 2 - (horizontal) or 3 (diagonal). -*/ -void qScrollEffect( TQWidget* w, TQEffects::DirFlags orient, int time ) -{ - if ( q_roll ) { - delete q_roll; - q_roll = 0; - } - - tqApp->sendPostedEvents( w, TQEvent::Move ); - tqApp->sendPostedEvents( w, TQEvent::Resize ); -#ifdef TQ_WS_X11 - uint flags = TQt::WStyle_Customize | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop - | (w->isPopup() ? TQt::WType_Popup : (TQt::WX11BypassWM | TQt::WStyle_Tool)); -#else - uint flags = TQt::WStyle_Customize | TQt::WType_Popup | TQt::WX11BypassWM | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop; -#endif - - // those can popups - they would steal the focus, but are disabled - q_roll = new TQRollEffect( w, flags, orient ); - q_roll->run( time ); -} - -/*! - Fade in widget \a w in \a time ms. -*/ -void qFadeEffect( TQWidget* w, int time ) -{ - if ( q_blend ) { - delete q_blend; - q_blend = 0; - } - - tqApp->sendPostedEvents( w, TQEvent::Move ); - tqApp->sendPostedEvents( w, TQEvent::Resize ); - -#ifdef TQ_WS_X11 - uint flags = TQt::WStyle_Customize | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop - | (w->isPopup() ? TQt::WType_Popup : (TQt::WX11BypassWM | TQt::WStyle_Tool)); -#else - uint flags = TQt::WStyle_Customize | TQt::WType_Popup | TQt::WX11BypassWM | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop; -#endif - - // those can popups - they would steal the focus, but are disabled - q_blend = new TQAlphaWidget( w, flags ); - - q_blend->run( time ); -} -#endif //TQT_NO_EFFECTS diff --git a/src/widgets/qeffects_p.h b/src/widgets/qeffects_p.h deleted file mode 100644 index 4d9845c01..000000000 --- a/src/widgets/qeffects_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Definition of TQEffects functions -** -** Created : 000621 -** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the widgets module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQEFFECTS_P_H -#define TQEFFECTS_P_H - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of qeffects.cpp, tqcombobox.cpp, tqpopupmenu.cpp and tqtooltip.cpp. -// This header file may change from version to version without notice, -// or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqnamespace.h" -#endif // QT_H - -#ifndef TQT_NO_EFFECTS -class TQWidget; - -struct TQEffects -{ - enum Direction { - LeftScroll = 0x0001, - RightScroll = 0x0002, - UpScroll = 0x0004, - DownScroll = 0x0008 - }; - - typedef uint DirFlags; -}; - -extern void TQ_EXPORT qScrollEffect( TQWidget*, TQEffects::DirFlags dir = TQEffects::DownScroll, int time = -1 ); -extern void TQ_EXPORT qFadeEffect( TQWidget*, int time = -1 ); -#endif // TQT_NO_EFFECTS - -#endif // TQEFFECTS_P_H diff --git a/src/widgets/qt_widgets.pri b/src/widgets/qt_widgets.pri index 9cb2f4b55..489279278 100644 --- a/src/widgets/qt_widgets.pri +++ b/src/widgets/qt_widgets.pri @@ -46,7 +46,7 @@ widgets { $$WIDGETS_H/tqsyntaxhighlighter.h \ $$WIDGETS_P/tqsyntaxhighlighter_p.h \ $$WIDGETS_H/tqtabwidget.h \ - $$WIDGETS_P/qtitlebar_p.h \ + $$WIDGETS_P/tqtitlebar_p.h \ $$WIDGETS_H/tqtoolbar.h \ $$WIDGETS_H/tqtoolbox.h \ $$WIDGETS_H/tqtoolbutton.h \ @@ -108,7 +108,7 @@ widgets { $$WIDGETS_CPP/tqsyntaxhighlighter.cpp \ $$WIDGETS_CPP/tqtabbar.cpp \ $$WIDGETS_CPP/tqtabwidget.cpp \ - $$WIDGETS_CPP/qtitlebar.cpp \ + $$WIDGETS_CPP/tqtitlebar.cpp \ $$WIDGETS_CPP/tqtoolbar.cpp \ $$WIDGETS_CPP/tqtoolbox.cpp \ $$WIDGETS_CPP/tqtoolbutton.cpp \ @@ -121,7 +121,7 @@ widgets { $$WIDGETS_CPP/tqwidgetstack.cpp \ $$WIDGETS_CPP/tqaction.cpp \ $$WIDGETS_CPP/tqdatetimeedit.cpp \ - $$WIDGETS_CPP/qeffects.cpp \ + $$WIDGETS_CPP/tqeffects.cpp \ $$WIDGETS_CPP/tqtextview.cpp \ $$WIDGETS_CPP/tqtextbrowser.cpp \ $$WIDGETS_CPP/tqtextedit.cpp \ diff --git a/src/widgets/qtitlebar.cpp b/src/widgets/qtitlebar.cpp deleted file mode 100644 index f0aa7bce8..000000000 --- a/src/widgets/qtitlebar.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/**************************************************************************** -** -** Implementation of some TQt private functions. -** -** Created : 001101 -** -** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the widgets module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qplatformdefs.h" - -#include "qtitlebar_p.h" - -#ifndef TQT_NO_TITLEBAR - -#include -#include "ntqapplication.h" -#include "tqstyle.h" -#include "tqdatetime.h" -#include "private/qapplication_p.h" -#include "tqtooltip.h" -#include "tqimage.h" -#include "tqtimer.h" -#include "tqpainter.h" -#include "tqstyle.h" -#include "private/qinternal_p.h" -#ifndef TQT_NO_WORKSPACE -#include "tqworkspace.h" -#endif -#if defined(TQ_WS_WIN) -#include "qt_windows.h" -#endif - -#ifndef TQT_NO_TOOLTIP -class TQTitleBarTip : public TQToolTip -{ -public: - TQTitleBarTip( TQWidget * parent ) : TQToolTip( parent ) { } - - void maybeTip( const TQPoint &pos ) - { - if ( !::tqt_cast(parentWidget()) ) - return; - TQTitleBar *t = (TQTitleBar *)parentWidget(); - - TQString tipstring; - TQStyle::SubControl ctrl = t->style().querySubControl(TQStyle::CC_TitleBar, t, pos); - TQSize controlSize = t->style().querySubControlMetrics(TQStyle::CC_TitleBar, t, ctrl).size(); - - TQWidget *window = t->window(); - if ( window ) { - switch(ctrl) { - case TQStyle::SC_TitleBarSysMenu: - if ( t->testWFlags( WStyle_SysMenu ) ) - tipstring = TQTitleBar::tr( "System Menu" ); - break; - - case TQStyle::SC_TitleBarShadeButton: - if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) ) - tipstring = TQTitleBar::tr( "Shade" ); - break; - - case TQStyle::SC_TitleBarUnshadeButton: - if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) ) - tipstring = TQTitleBar::tr( "Unshade" ); - break; - - case TQStyle::SC_TitleBarNormalButton: - case TQStyle::SC_TitleBarMinButton: - if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Minimize ) ) { - if( window->isMinimized() ) - tipstring = TQTitleBar::tr( "Normalize" ); - else - tipstring = TQTitleBar::tr( "Minimize" ); - } - break; - - case TQStyle::SC_TitleBarMaxButton: - if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Maximize ) ) - tipstring = TQTitleBar::tr( "Maximize" ); - break; - - case TQStyle::SC_TitleBarCloseButton: - if ( t->testWFlags( WStyle_SysMenu ) ) - tipstring = TQTitleBar::tr( "Close" ); - break; - - default: - break; - } - } -#ifndef TQT_NO_WIDGET_TOPEXTRA - if ( tipstring.isEmpty() ) { - if ( t->visibleText() != t->caption() ) - tipstring = t->caption(); - } -#endif - if(!tipstring.isEmpty()) - tip( TQRect(pos, controlSize), tipstring ); - } -}; -#endif - -class TQTitleBarPrivate -{ -public: - TQTitleBarPrivate() - : toolTip( 0 ), act( 0 ), window( 0 ), movable( 1 ), pressed( 0 ), autoraise(0) - { - } - - TQStyle::SCFlags buttonDown; - TQPoint moveOffset; - TQToolTip *toolTip; - bool act :1; - TQWidget* window; - bool movable :1; - bool pressed :1; - bool autoraise :1; - TQString cuttext; -#ifdef TQT_NO_WIDGET_TOPEXTRA - TQString cap; -#endif -}; - -TQTitleBar::TQTitleBar(TQWidget* w, TQWidget* parent, const char* name) - : TQWidget( parent, name, WStyle_Customize | WStyle_NoBorder | WNoAutoErase ) -{ - d = new TQTitleBarPrivate(); - -#ifndef TQT_NO_TOOLTIP - d->toolTip = new TQTitleBarTip( this ); -#endif - d->window = w; - d->buttonDown = TQStyle::SC_None; - d->act = 0; - if ( w ) { - setWFlags( ((TQTitleBar*)w)->getWFlags() | WNoAutoErase ); - if ( w->minimumSize() == w->maximumSize() ) - clearWFlags( WStyle_Maximize ); -#ifndef TQT_NO_WIDGET_TOPEXTRA - setCaption( w->caption() ); -#endif - } else { - setWFlags( WStyle_Customize | WNoAutoErase ); - } - - readColors(); - setSizePolicy( TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed ) ); - setMouseTracking(TRUE); -} - -TQTitleBar::~TQTitleBar() -{ -#ifndef TQT_NO_TOOLTIP - delete d->toolTip; -#endif - - delete d; - d = 0; -} - -#ifdef TQ_WS_WIN -extern TQRgb qt_colorref2qrgb(COLORREF col); -#endif - -void TQTitleBar::readColors() -{ - TQPalette pal = palette(); - - bool colorsInitialized = FALSE; - -#ifdef TQ_WS_WIN // ask system properties on windows -#ifndef SPI_GETGRADIENTCAPTIONS -#define SPI_GETGRADIENTCAPTIONS 0x1008 -#endif -#ifndef COLOR_GRADIENTACTIVECAPTION -#define COLOR_GRADIENTACTIVECAPTION 27 -#endif -#ifndef COLOR_GRADIENTINACTIVECAPTION -#define COLOR_GRADIENTINACTIVECAPTION 28 -#endif - if ( TQApplication::desktopSettingsAware() ) { - pal.setColor( TQPalette::Active, TQColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)) ); - pal.setColor( TQPalette::Inactive, TQColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)) ); - pal.setColor( TQPalette::Active, TQColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)) ); - pal.setColor( TQPalette::Inactive, TQColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)) ); - if ( qt_winver != TQt::WV_95 && qt_winver != WV_NT ) { - colorsInitialized = TRUE; - BOOL gradient; - QT_WA( { - SystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 ); - } , { - SystemParametersInfoA( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 ); - } ); - if ( gradient ) { - pal.setColor( TQPalette::Active, TQColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)) ); - pal.setColor( TQPalette::Inactive, TQColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)) ); - } else { - pal.setColor( TQPalette::Active, TQColorGroup::Base, palette().active().highlight() ); - pal.setColor( TQPalette::Inactive, TQColorGroup::Base, palette().inactive().highlight() ); - } - } - } -#endif // TQ_WS_WIN - if ( !colorsInitialized ) { - pal.setColor( TQPalette::Active, TQColorGroup::Highlight, palette().active().highlight() ); - pal.setColor( TQPalette::Active, TQColorGroup::Base, palette().active().highlight() ); - pal.setColor( TQPalette::Inactive, TQColorGroup::Highlight, palette().inactive().dark() ); - pal.setColor( TQPalette::Inactive, TQColorGroup::Base, palette().inactive().dark() ); - pal.setColor( TQPalette::Inactive, TQColorGroup::HighlightedText, palette().inactive().background() ); - } - - setPalette( pal ); - setActive( d->act ); -} - -void TQTitleBar::mousePressEvent( TQMouseEvent * e) -{ - if ( !d->act ) - emit doActivate(); - if ( e->button() == LeftButton ) { - d->pressed = TRUE; - TQStyle::SCFlags ctrl = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); - switch (ctrl) { - case TQStyle::SC_TitleBarSysMenu: - if ( testWFlags( WStyle_SysMenu ) && !testWFlags( WStyle_Tool ) ) { - d->buttonDown = TQStyle::SC_None; - static TQTime* t = 0; - static TQTitleBar* tc = 0; - if ( !t ) - t = new TQTime; - if ( tc != this || t->elapsed() > TQApplication::doubleClickInterval() ) { - emit showOperationMenu(); - t->start(); - tc = this; - } else { - tc = 0; - emit doClose(); - return; - } - } - break; - - case TQStyle::SC_TitleBarShadeButton: - case TQStyle::SC_TitleBarUnshadeButton: - if ( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) ) - d->buttonDown = ctrl; - break; - - case TQStyle::SC_TitleBarNormalButton: - if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) ) - d->buttonDown = ctrl; - break; - - case TQStyle::SC_TitleBarMinButton: - if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) ) - d->buttonDown = ctrl; - break; - - case TQStyle::SC_TitleBarMaxButton: - if ( testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) ) - d->buttonDown = ctrl; - break; - - case TQStyle::SC_TitleBarCloseButton: - if ( testWFlags( WStyle_SysMenu ) ) - d->buttonDown = ctrl; - break; - - case TQStyle::SC_TitleBarLabel: - d->buttonDown = ctrl; - d->moveOffset = mapToParent( e->pos() ); - break; - - default: - break; - } - repaint( FALSE ); - } else { - d->pressed = FALSE; - } -} - -void TQTitleBar::contextMenuEvent( TQContextMenuEvent *e ) -{ - TQStyle::SCFlags ctrl = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); - if( ctrl == TQStyle::SC_TitleBarLabel || ctrl == TQStyle::SC_TitleBarSysMenu ) - emit popupOperationMenu(e->globalPos()); - else - e->ignore(); -} - -void TQTitleBar::mouseReleaseEvent( TQMouseEvent * e) -{ - if ( e->button() == LeftButton && d->pressed) { - TQStyle::SCFlags ctrl = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); - - if (ctrl == d->buttonDown) { - switch(ctrl) { - case TQStyle::SC_TitleBarShadeButton: - case TQStyle::SC_TitleBarUnshadeButton: - if( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) ) - emit doShade(); - break; - - case TQStyle::SC_TitleBarNormalButton: - if( testWFlags( WStyle_MinMax ) && !testWFlags( WStyle_Tool ) ) - emit doNormal(); - break; - - case TQStyle::SC_TitleBarMinButton: - if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) ) - emit doMinimize(); - break; - - case TQStyle::SC_TitleBarMaxButton: - if( d->window && testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) ) { - if(d->window->isMaximized()) - emit doNormal(); - else - emit doMaximize(); - } - break; - - case TQStyle::SC_TitleBarCloseButton: - if( testWFlags( WStyle_SysMenu ) ) { - d->buttonDown = TQStyle::SC_None; - repaint(FALSE); - emit doClose(); - return; - } - break; - - default: - break; - } - } - d->buttonDown = TQStyle::SC_None; - repaint(FALSE); - d->pressed = FALSE; - } -} - -void TQTitleBar::mouseMoveEvent( TQMouseEvent * e) -{ - switch (d->buttonDown) { - case TQStyle::SC_None: - if(autoRaise()) - repaint( FALSE ); - break; - case TQStyle::SC_TitleBarSysMenu: - break; - case TQStyle::SC_TitleBarShadeButton: - case TQStyle::SC_TitleBarUnshadeButton: - case TQStyle::SC_TitleBarNormalButton: - case TQStyle::SC_TitleBarMinButton: - case TQStyle::SC_TitleBarMaxButton: - case TQStyle::SC_TitleBarCloseButton: - { - TQStyle::SCFlags last_ctrl = d->buttonDown; - d->buttonDown = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); - if( d->buttonDown != last_ctrl) - d->buttonDown = TQStyle::SC_None; - repaint(FALSE); - d->buttonDown = last_ctrl; - } - break; - - case TQStyle::SC_TitleBarLabel: - if ( d->buttonDown == TQStyle::SC_TitleBarLabel && d->movable && d->pressed ) { - if ( (d->moveOffset - mapToParent( e->pos() ) ).manhattanLength() >= 4 ) { - TQPoint p = mapFromGlobal(e->globalPos()); -#ifndef TQT_NO_WORKSPACE - if(d->window && d->window->parentWidget()->inherits("TQWorkspaceChild")) { - TQWorkspace *workspace = ::tqt_cast(d->window->parentWidget()->parentWidget()); - if(workspace) { - p = workspace->mapFromGlobal( e->globalPos() ); - if ( !workspace->rect().contains(p) ) { - if ( p.x() < 0 ) - p.rx() = 0; - if ( p.y() < 0 ) - p.ry() = 0; - if ( p.x() > workspace->width() ) - p.rx() = workspace->width(); - if ( p.y() > workspace->height() ) - p.ry() = workspace->height(); - } - } - } -#endif - TQPoint pp = p - d->moveOffset; - if (!parentWidget()->isMaximized()) - parentWidget()->move( pp ); - } - } else { - TQStyle::SCFlags last_ctrl = d->buttonDown; - d->buttonDown = TQStyle::SC_None; - if( d->buttonDown != last_ctrl) - repaint(FALSE); - } - break; - } -} - -void TQTitleBar::resizeEvent( TQResizeEvent *r) -{ - TQWidget::resizeEvent(r); - cutText(); -} - -void TQTitleBar::paintEvent(TQPaintEvent *) -{ - TQStyle::SCFlags ctrls = TQStyle::SC_TitleBarLabel; - if ( testWFlags( WStyle_SysMenu) ) { - if ( testWFlags( WStyle_Tool ) ) { - ctrls |= TQStyle::SC_TitleBarCloseButton; - if ( d->window && testWFlags( WStyle_MinMax ) ) { - if ( d->window->isMinimized() ) - ctrls |= TQStyle::SC_TitleBarUnshadeButton; - else - ctrls |= TQStyle::SC_TitleBarShadeButton; - } - } else { - ctrls |= TQStyle::SC_TitleBarSysMenu | TQStyle::SC_TitleBarCloseButton; - if ( d->window && testWFlags( WStyle_Minimize ) ) { - if( d->window && d->window->isMinimized() ) - ctrls |= TQStyle::SC_TitleBarNormalButton; - else - ctrls |= TQStyle::SC_TitleBarMinButton; - } - if ( d->window && testWFlags( WStyle_Maximize ) && !d->window->isMaximized() ) - ctrls |= TQStyle::SC_TitleBarMaxButton; - } - } - - TQStyle::SCFlags under_mouse = TQStyle::SC_None; - if( autoRaise() && hasMouse() ) { - TQPoint p(mapFromGlobal(TQCursor::pos())); - under_mouse = style().querySubControl(TQStyle::CC_TitleBar, this, p); - ctrls ^= under_mouse; - } - - TQSharedDoubleBuffer buffer( this, rect() ); - style().drawComplexControl(TQStyle::CC_TitleBar, buffer.painter(), this, rect(), - colorGroup(), - isEnabled() ? TQStyle::Style_Enabled : - TQStyle::Style_Default, ctrls, d->buttonDown); - if(under_mouse != TQStyle::SC_None) - style().drawComplexControl(TQStyle::CC_TitleBar, buffer.painter(), this, rect(), - colorGroup(), - TQStyle::Style_MouseOver | - (isEnabled() ? TQStyle::Style_Enabled : 0), - under_mouse, d->buttonDown); -} - -void TQTitleBar::mouseDoubleClickEvent( TQMouseEvent *e ) -{ - if ( e->button() != LeftButton ) - return; - - switch(style().querySubControl(TQStyle::CC_TitleBar, this, e->pos())) { - case TQStyle::SC_TitleBarLabel: - emit doubleClicked(); - break; - - case TQStyle::SC_TitleBarSysMenu: - if ( testWFlags( WStyle_SysMenu ) ) - emit doClose(); - break; - - default: - break; - } -} - -#ifdef TQT_NO_WIDGET_TOPEXTRA -// We provide one, since titlebar is useless otherwise. -TQString TQTitleBar::caption() const -{ - return d->cap; -} -#endif - -void TQTitleBar::cutText() -{ - TQFontMetrics fm( font() ); - - int maxw = style().querySubControlMetrics(TQStyle::CC_TitleBar, this, - TQStyle::SC_TitleBarLabel).width(); - if ( !d->window ) - maxw = width() - 20; - const TQString txt = caption(); - d->cuttext = txt; - if ( fm.width( txt + "m" ) > maxw ) { - int i = txt.length(); - int dotlength = fm.width( "..." ); - while ( i>0 && fm.width(txt.left( i )) + dotlength > maxw ) - i--; - if(i != (int)txt.length()) - d->cuttext = txt.left( i ) + "..."; - } -} - -void TQTitleBar::setCaption( const TQString& title ) -{ - if( caption() == title) - return; -#ifndef TQT_NO_WIDGET_TOPEXTRA - TQWidget::setCaption( title ); -#else - d->cap = title; -#endif - cutText(); - - update(); -} - - -void TQTitleBar::setIcon( const TQPixmap& icon ) -{ -#ifndef TQT_NO_WIDGET_TOPEXTRA -#ifndef TQT_NO_IMAGE_SMOOTHSCALE - TQRect menur = style().querySubControlMetrics(TQStyle::CC_TitleBar, this, - TQStyle::SC_TitleBarSysMenu); - - TQPixmap theIcon; - if (icon.width() > menur.width()) { - // try to keep something close to the same aspect - int aspect = (icon.height() * 100) / icon.width(); - int newh = (aspect * menur.width()) / 100; - theIcon.convertFromImage( icon.convertToImage().smoothScale(menur.width(), - newh) ); - } else if (icon.height() > menur.height()) { - // try to keep something close to the same aspect - int aspect = (icon.width() * 100) / icon.height(); - int neww = (aspect * menur.height()) / 100; - theIcon.convertFromImage( icon.convertToImage().smoothScale(neww, - menur.height()) ); - } else - theIcon = icon; - - TQWidget::setIcon( theIcon ); -#else - TQWidget::setIcon( icon ); -#endif - - update(); -#endif -} - -void TQTitleBar::leaveEvent( TQEvent * ) -{ - if(autoRaise() && !d->pressed) - repaint( FALSE ); -} - -void TQTitleBar::enterEvent( TQEvent * ) -{ - if(autoRaise() && !d->pressed) - repaint( FALSE ); - TQEvent e( TQEvent::Leave ); - TQApplication::sendEvent( parentWidget(), &e ); -} - -void TQTitleBar::setActive( bool active ) -{ - if ( d->act == active ) - return ; - - d->act = active; - update(); -} - -bool TQTitleBar::isActive() const -{ - return d->act; -} - -bool TQTitleBar::usesActiveColor() const -{ - return ( isActive() && isActiveWindow() ) || - ( !window() && topLevelWidget()->isActiveWindow() ); -} - -TQString TQTitleBar::visibleText() const -{ - return d->cuttext; -} - -TQWidget *TQTitleBar::window() const -{ - return d->window; -} - -bool TQTitleBar::event( TQEvent* e ) -{ - if ( e->type() == TQEvent::ApplicationPaletteChange ) { - readColors(); - return TRUE; - } else if ( e->type() == TQEvent::WindowActivate ) { - setActive( d->act ); - } else if ( e->type() == TQEvent::WindowDeactivate ) { - bool wasActive = d->act; - setActive( FALSE ); - d->act = wasActive; - } - - return TQWidget::event( e ); -} - -void TQTitleBar::setMovable(bool b) -{ - d->movable = b; -} - -bool TQTitleBar::isMovable() const -{ - return d->movable; -} - -void TQTitleBar::setAutoRaise(bool b) -{ - d->autoraise = b; -} - -bool TQTitleBar::autoRaise() const -{ - return d->autoraise; -} - -TQSize TQTitleBar::sizeHint() const -{ - constPolish(); - TQRect menur = style().querySubControlMetrics(TQStyle::CC_TitleBar, this, - TQStyle::SC_TitleBarSysMenu); - return TQSize( menur.width(), style().pixelMetric( TQStyle::PM_TitleBarHeight, this ) ); -} - -#endif //TQT_NO_TITLEBAR diff --git a/src/widgets/qtitlebar_p.h b/src/widgets/qtitlebar_p.h deleted file mode 100644 index e3d20023e..000000000 --- a/src/widgets/qtitlebar_p.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Definition of some TQt private functions. -** -** Created : 000101 -** -** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the widgets module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQTITLEBAR_P_H -#define TQTITLEBAR_P_H - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of tqworkspace.cpp and tqdockwindow.cpp. This header file may change -// from version to version without notice, or even be removed. -// -// We mean it. -// -// - - -#ifndef QT_H -#include "tqbutton.h" -#include "tqlabel.h" -#endif // QT_H - -#if !defined(TQT_NO_TITLEBAR) - -class TQToolTip; -class TQTitleBarPrivate; -class TQPixmap; - -class TQ_EXPORT TQTitleBar : public TQWidget -{ - TQ_OBJECT - TQ_PROPERTY( bool autoRaise READ autoRaise WRITE setAutoRaise ) - TQ_PROPERTY( bool movable READ isMovable WRITE setMovable ) - -public: - TQTitleBar (TQWidget* w, TQWidget* parent, const char* name=0); - ~TQTitleBar(); - - bool isActive() const; - bool usesActiveColor() const; - virtual TQString visibleText() const; - - bool isMovable() const; - void setMovable(bool); - - bool autoRaise() const; - void setAutoRaise(bool); - - TQWidget *window() const; - - TQSize sizeHint() const; - -#ifdef TQT_NO_WIDGET_TOPEXTRA - // We provide one, since titlebar is useless otherwise. - TQString caption() const; -#endif - -public slots: - void setActive( bool ); - void setCaption( const TQString& title ); - void setIcon( const TQPixmap& icon ); - -signals: - void doActivate(); - void doNormal(); - void doClose(); - void doMaximize(); - void doMinimize(); - void doShade(); - void showOperationMenu(); - void popupOperationMenu( const TQPoint& ); - void doubleClicked(); - -protected: - bool event( TQEvent *); - void resizeEvent( TQResizeEvent *); - void contextMenuEvent( TQContextMenuEvent * ); - void mousePressEvent( TQMouseEvent * ); - void mouseDoubleClickEvent( TQMouseEvent * ); - void mouseReleaseEvent( TQMouseEvent * ); - void mouseMoveEvent( TQMouseEvent * ); - void enterEvent( TQEvent *e ); - void leaveEvent( TQEvent *e ); - void paintEvent( TQPaintEvent *p ); - - virtual void cutText(); - -private: - void readColors(); - - TQTitleBarPrivate *d; -#if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= - TQTitleBar( const TQTitleBar & ); - TQTitleBar &operator=( const TQTitleBar & ); -#endif -}; - -#endif -#endif //TQTITLEBAR_P_H diff --git a/src/widgets/tqbutton.cpp b/src/widgets/tqbutton.cpp index 333ff6270..088f9cc6a 100644 --- a/src/widgets/tqbutton.cpp +++ b/src/widgets/tqbutton.cpp @@ -50,7 +50,7 @@ #include "tqpushbutton.h" #include "tqradiobutton.h" #include "tqguardedptr.h" -#include "../kernel/qinternal_p.h" +#include "../kernel/tqinternal_p.h" #if defined(QT_ACCESSIBILITY_SUPPORT) #include "tqaccessible.h" diff --git a/src/widgets/tqcombobox.cpp b/src/widgets/tqcombobox.cpp index cc97ffeda..1f0ff2e9d 100644 --- a/src/widgets/tqcombobox.cpp +++ b/src/widgets/tqcombobox.cpp @@ -50,7 +50,7 @@ #include "ntqapplication.h" #include "tqlineedit.h" #include "tqbitmap.h" -#include "qeffects_p.h" +#include "tqeffects_p.h" #include "tqstringlist.h" #include "tqcombobox.h" #include "tqstyle.h" diff --git a/src/widgets/tqdatetimeedit.cpp b/src/widgets/tqdatetimeedit.cpp index 6e32d3aaf..a01a14694 100644 --- a/src/widgets/tqdatetimeedit.cpp +++ b/src/widgets/tqdatetimeedit.cpp @@ -42,8 +42,8 @@ #ifndef TQT_NO_DATETIMEEDIT -#include "../kernel/qinternal_p.h" -#include "../kernel/qrichtext_p.h" +#include "../kernel/tqinternal_p.h" +#include "../kernel/tqrichtext_p.h" #include "tqrangecontrol.h" #include "ntqapplication.h" #include "tqpixmap.h" diff --git a/src/widgets/tqdockwindow.cpp b/src/widgets/tqdockwindow.cpp index 4bfe58a8a..e07a550af 100644 --- a/src/widgets/tqdockwindow.cpp +++ b/src/widgets/tqdockwindow.cpp @@ -44,7 +44,7 @@ #include "tqdesktopwidget.h" #include "tqdockarea.h" #include "tqwidgetresizehandler_p.h" -#include "qtitlebar_p.h" +#include "tqtitlebar_p.h" #include "tqpainter.h" #include "ntqapplication.h" #include "tqtoolbutton.h" diff --git a/src/widgets/tqeffects.cpp b/src/widgets/tqeffects.cpp new file mode 100644 index 000000000..792456119 --- /dev/null +++ b/src/widgets/tqeffects.cpp @@ -0,0 +1,675 @@ +/**************************************************************************** +** +** Implementation of TQEffects functions +** +** Created : 000621 +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the widgets module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "ntqapplication.h" +#ifndef TQT_NO_EFFECTS +#include "tqwidget.h" +#include "tqeffects_p.h" +#include "tqpixmap.h" +#include "tqimage.h" +#include "tqtimer.h" +#include "tqdatetime.h" +#include "tqguardedptr.h" +#include "tqscrollview.h" + +/* + Internal class to get access to protected TQWidget-members +*/ + +class TQAccessWidget : public TQWidget +{ + friend class TQAlphaWidget; + friend class TQRollEffect; +public: + TQAccessWidget( TQWidget* parent=0, const char* name=0, WFlags f = 0 ) + : TQWidget( parent, name, f ) {} +}; + +/* + Internal class TQAlphaWidget. + + The TQAlphaWidget is shown while the animation lasts + and displays the pixmap resulting from the alpha blending. +*/ + +class TQAlphaWidget: public TQWidget, private TQEffects +{ + TQ_OBJECT +public: + TQAlphaWidget( TQWidget* w, WFlags f = 0 ); + + void run( int time ); + +protected: + void paintEvent( TQPaintEvent* e ); + void closeEvent( TQCloseEvent* ); + bool eventFilter( TQObject* o, TQEvent* e ); + void alphaBlend(); + +protected slots: + void render(); + +private: + TQPixmap pm; + double alpha; + TQImage back; + TQImage front; + TQImage mixed; + TQGuardedPtr widget; + int duration; + int elapsed; + bool showWidget; + TQTimer anim; + TQTime checkTime; +}; + +static TQAlphaWidget* q_blend = 0; + +/* + Constructs a TQAlphaWidget. +*/ +TQAlphaWidget::TQAlphaWidget( TQWidget* w, WFlags f ) + : TQWidget( TQApplication::desktop()->screen(TQApplication::desktop()->screenNumber(w)), + "qt internal alpha effect widget", f ) +{ +#if 1 //ndef TQ_WS_WIN + setEnabled( FALSE ); +#endif + + pm.setOptimization( TQPixmap::BestOptim ); + setBackgroundMode( NoBackground ); + widget = (TQAccessWidget*)w; + alpha = 0; +} + +/* + \reimp +*/ +void TQAlphaWidget::paintEvent( TQPaintEvent* ) +{ + bitBlt( this, TQPoint(0,0), &pm ); +} + +/* + Starts the alphablending animation. + The animation will take about \a time ms +*/ +void TQAlphaWidget::run( int time ) +{ + duration = time; + + if ( duration < 0 ) + duration = 150; + + if ( !widget ) + return; + + elapsed = 0; + checkTime.start(); + + showWidget = TRUE; + tqApp->installEventFilter( this ); + + widget->setWState( WState_Visible ); + + move( widget->geometry().x(),widget->geometry().y() ); + resize( widget->size().width(), widget->size().height() ); + + front = TQImage( widget->size(), 32 ); + front = TQPixmap::grabWidget( widget ); + + back = TQImage( widget->size(), 32 ); + back = TQPixmap::grabWindow( TQApplication::desktop()->winId(), + widget->geometry().x(), widget->geometry().y(), + widget->geometry().width(), widget->geometry().height() ); + + if ( !back.isNull() && checkTime.elapsed() < duration / 2 ) { + mixed = back.copy(); + pm = mixed; + show(); + setEnabled(FALSE); + + connect( &anim, TQ_SIGNAL(timeout()), this, TQ_SLOT(render())); + anim.start( 1 ); + } else { + duration = 0; + render(); + } +} + +/* + \reimp +*/ +bool TQAlphaWidget::eventFilter( TQObject* o, TQEvent* e ) +{ + switch ( e->type() ) { + case TQEvent::Move: + if ( o != widget ) + break; + move( widget->geometry().x(),widget->geometry().y() ); + update(); + break; + case TQEvent::Hide: + case TQEvent::Close: + if ( o != widget ) + break; + case TQEvent::MouseButtonPress: +#ifndef TQT_NO_SCROLLVIEW + if ( ::tqt_cast(o) ) + break; +#endif + case TQEvent::MouseButtonDblClick: + setEnabled(TRUE); + showWidget = FALSE; + render(); + break; + case TQEvent::KeyPress: + { + TQKeyEvent *ke = (TQKeyEvent*)e; + if ( ke->key() == Key_Escape ) + showWidget = FALSE; + else + duration = 0; + render(); + break; + } + default: + break; + } + return TQWidget::eventFilter( o, e ); +} + +/* + \reimp +*/ +void TQAlphaWidget::closeEvent( TQCloseEvent *e ) +{ + e->accept(); + if ( !q_blend ) + return; + + showWidget = FALSE; + render(); + + TQWidget::closeEvent( e ); +} + +/* + Render alphablending for the time elapsed. + + Show the blended widget and free all allocated source + if the blending is finished. +*/ +void TQAlphaWidget::render() +{ + int tempel = checkTime.elapsed(); + if ( elapsed >= tempel ) + elapsed++; + else + elapsed = tempel; + + if ( duration != 0 ) + alpha = tempel / double(duration); + else + alpha = 1; + if ( alpha >= 1 || !showWidget) { + anim.stop(); + tqApp->removeEventFilter( this ); + + if ( widget ) { + if ( !showWidget ) { +#ifdef TQ_WS_WIN + setEnabled(TRUE); + setFocus(); +#endif + widget->hide(); + widget->setWState( WState_ForceHide ); + widget->clearWState( WState_Visible ); + } else if ( duration ) { + BackgroundMode bgm = widget->backgroundMode(); + TQColor erc = widget->eraseColor(); + const TQPixmap *erp = widget->erasePixmap(); + + widget->clearWState( WState_Visible ); + widget->setBackgroundMode( NoBackground ); + widget->show(); + if ( bgm != FixedColor && bgm != FixedPixmap ) { + widget->clearWState( WState_Visible ); // prevent update in setBackgroundMode + widget->setBackgroundMode( bgm ); + widget->setWState( WState_Visible ); + } + if ( erc.isValid() ) { + widget->setEraseColor( erc ); + } else if ( erp ) { + widget->setErasePixmap( *erp ); + } + } else { + widget->clearWState( WState_Visible ); + widget->show(); + } + } + q_blend = 0; + deleteLater(); + } else { + if (widget) + widget->clearWState( WState_ForceHide ); + alphaBlend(); + pm = mixed; + repaint( FALSE ); + } +} + +/* + Calculate an alphablended image. +*/ +void TQAlphaWidget::alphaBlend() +{ + const double ia = 1-alpha; + const int sw = front.width(); + const int sh = front.height(); + switch( front.depth() ) { + case 32: + { + TQ_UINT32** md = (TQ_UINT32**)mixed.jumpTable(); + TQ_UINT32** bd = (TQ_UINT32**)back.jumpTable(); + TQ_UINT32** fd = (TQ_UINT32**)front.jumpTable(); + + for (int sy = 0; sy < sh; sy++ ) { + TQ_UINT32* bl = ((TQ_UINT32*)bd[sy]); + TQ_UINT32* fl = ((TQ_UINT32*)fd[sy]); + for (int sx = 0; sx < sw; sx++ ) { + TQ_UINT32 bp = bl[sx]; + TQ_UINT32 fp = fl[sx]; + + ((TQ_UINT32*)(md[sy]))[sx] = tqRgb(int (tqRed(bp)*ia + tqRed(fp)*alpha), + int (tqGreen(bp)*ia + tqGreen(fp)*alpha), + int (tqBlue(bp)*ia + tqBlue(fp)*alpha) ); + } + } + } + default: + break; + } +} + +/* + Internal class TQRollEffect + + The TQRollEffect widget is shown while the animation lasts + and displays a scrolling pixmap. +*/ + +class TQRollEffect : public TQWidget, private TQEffects +{ + TQ_OBJECT +public: + TQRollEffect( TQWidget* w, WFlags f, DirFlags orient ); + + void run( int time ); + +protected: + void paintEvent( TQPaintEvent* ); + bool eventFilter( TQObject*, TQEvent* ); + void closeEvent( TQCloseEvent* ); + +private slots: + void scroll(); + +private: + TQGuardedPtr widget; + + int currentHeight; + int currentWidth; + int totalHeight; + int totalWidth; + + int duration; + int elapsed; + bool done; + bool showWidget; + int orientation; + + TQTimer anim; + TQTime checkTime; + + TQPixmap pm; +}; + +static TQRollEffect* q_roll = 0; + +/* + Construct a TQRollEffect widget. +*/ +TQRollEffect::TQRollEffect( TQWidget* w, WFlags f, DirFlags orient ) + : TQWidget( TQApplication::desktop()->screen(TQApplication::desktop()->screenNumber(w)), + "qt internal roll effect widget", f ), orientation(orient) +{ +#if 1 //ndef TQ_WS_WIN + setEnabled( FALSE ); +#endif + widget = (TQAccessWidget*) w; + Q_ASSERT( widget ); + + setBackgroundMode( NoBackground ); + + if ( widget->testWState( WState_Resized ) ) { + totalWidth = widget->width(); + totalHeight = widget->height(); + } else { + totalWidth = widget->sizeHint().width(); + totalHeight = widget->sizeHint().height(); + } + + currentHeight = totalHeight; + currentWidth = totalWidth; + + if ( orientation & (RightScroll|LeftScroll) ) + currentWidth = 0; + if ( orientation & (DownScroll|UpScroll) ) + currentHeight = 0; + + pm.setOptimization( TQPixmap::BestOptim ); + pm = TQPixmap::grabWidget( widget ); +} + +/* + \reimp +*/ +void TQRollEffect::paintEvent( TQPaintEvent* ) +{ + int x = orientation & RightScroll ? TQMIN(0, currentWidth - totalWidth) : 0; + int y = orientation & DownScroll ? TQMIN(0, currentHeight - totalHeight) : 0; + + bitBlt( this, x, y, &pm, + 0, 0, pm.width(), pm.height(), CopyROP, TRUE ); +} + +/* + \reimp +*/ +bool TQRollEffect::eventFilter( TQObject* o, TQEvent* e ) +{ + switch ( e->type() ) { + case TQEvent::Move: + if ( o != widget ) + break; + move( widget->geometry().x(),widget->geometry().y() ); + update(); + break; + case TQEvent::Hide: + case TQEvent::Close: + if ( o != widget || done ) + break; + setEnabled(TRUE); + showWidget = FALSE; + done = TRUE; + scroll(); + break; + case TQEvent::MouseButtonPress: +#ifndef TQT_NO_SCROLLVIEW + if ( ::tqt_cast(o) ) + break; +#endif + case TQEvent::MouseButtonDblClick: + if ( done ) + break; + setEnabled(TRUE); + showWidget = FALSE; + done = TRUE; + scroll(); + break; + case TQEvent::KeyPress: + { + TQKeyEvent *ke = (TQKeyEvent*)e; + if ( ke->key() == Key_Escape ) + showWidget = FALSE; + done = TRUE; + scroll(); + break; + } + default: + break; + } + return TQWidget::eventFilter( o, e ); +} + +/* + \reimp +*/ +void TQRollEffect::closeEvent( TQCloseEvent *e ) +{ + e->accept(); + if ( done ) + return; + + showWidget = FALSE; + done = TRUE; + scroll(); + + TQWidget::closeEvent( e ); +} + +/* + Start the animation. + + The animation will take about \a time ms, or is + calculated if \a time is negative +*/ +void TQRollEffect::run( int time ) +{ + if ( !widget ) + return; + + duration = time; + elapsed = 0; + + if ( duration < 0 ) { + int dist = 0; + if ( orientation & (RightScroll|LeftScroll) ) + dist += totalWidth - currentWidth; + if ( orientation & (DownScroll|UpScroll) ) + dist += totalHeight - currentHeight; + duration = TQMIN( TQMAX( dist/3, 50 ), 120 ); + } + + connect( &anim, TQ_SIGNAL(timeout()), this, TQ_SLOT(scroll())); + + widget->setWState( WState_Visible ); + + move( widget->geometry().x(),widget->geometry().y() ); + resize( TQMIN( currentWidth, totalWidth ), TQMIN( currentHeight, totalHeight ) ); + + show(); + setEnabled(FALSE); + + tqApp->installEventFilter( this ); + + showWidget = TRUE; + done = FALSE; + anim.start( 1 ); + checkTime.start(); +} + +/* + Roll according to the time elapsed. +*/ +void TQRollEffect::scroll() +{ + if ( !done && widget) { + widget->clearWState( WState_ForceHide ); + int tempel = checkTime.elapsed(); + if ( elapsed >= tempel ) + elapsed++; + else + elapsed = tempel; + + if ( currentWidth != totalWidth ) { + currentWidth = totalWidth * (elapsed/duration) + + ( 2 * totalWidth * (elapsed%duration) + duration ) + / ( 2 * duration ); + // equiv. to int( (totalWidth*elapsed) / duration + 0.5 ) + done = (currentWidth >= totalWidth); + } + if ( currentHeight != totalHeight ) { + currentHeight = totalHeight * (elapsed/duration) + + ( 2 * totalHeight * (elapsed%duration) + duration ) + / ( 2 * duration ); + // equiv. to int( (totalHeight*elapsed) / duration + 0.5 ) + done = (currentHeight >= totalHeight); + } + done = ( currentHeight >= totalHeight ) && + ( currentWidth >= totalWidth ); + + int w = totalWidth; + int h = totalHeight; + int x = widget->geometry().x(); + int y = widget->geometry().y(); + + if ( orientation & RightScroll || orientation & LeftScroll ) + w = TQMIN( currentWidth, totalWidth ); + if ( orientation & DownScroll || orientation & UpScroll ) + h = TQMIN( currentHeight, totalHeight ); + + setUpdatesEnabled( FALSE ); + if ( orientation & UpScroll ) + y = widget->geometry().y() + TQMAX( 0, totalHeight - currentHeight ); + if ( orientation & LeftScroll ) + x = widget->geometry().x() + TQMAX( 0, totalWidth - currentWidth ); + if ( orientation & UpScroll || orientation & LeftScroll ) + move( x, y ); + + resize( w, h ); + setUpdatesEnabled( TRUE ); + repaint( FALSE ); + } + if ( done ) { + anim.stop(); + tqApp->removeEventFilter( this ); + if ( widget ) { + if ( !showWidget ) { +#ifdef TQ_WS_WIN + setEnabled(TRUE); + setFocus(); +#endif + widget->hide(); + widget->setWState( WState_ForceHide ); + widget->clearWState( WState_Visible ); + } else { + BackgroundMode bgm = widget->backgroundMode(); + TQColor erc = widget->eraseColor(); + const TQPixmap *erp = widget->erasePixmap(); + + widget->clearWState( WState_Visible ); + widget->setBackgroundMode( NoBackground ); + widget->show(); + if ( bgm != FixedColor && bgm != FixedPixmap ) { + widget->clearWState( WState_Visible ); // prevent update in setBackgroundMode + widget->setBackgroundMode( bgm ); + widget->setWState( WState_Visible ); + } + if ( erc.isValid() ) { + widget->setEraseColor( erc ); + } else if ( erp ) { + widget->setErasePixmap( *erp ); + } + } + } + q_roll = 0; + deleteLater(); + } +} + +/* + Delete this after timeout +*/ + +#include "tqeffects.moc" + +/*! + Scroll widget \a w in \a time ms. \a orient may be 1 (vertical), 2 + (horizontal) or 3 (diagonal). +*/ +void qScrollEffect( TQWidget* w, TQEffects::DirFlags orient, int time ) +{ + if ( q_roll ) { + delete q_roll; + q_roll = 0; + } + + tqApp->sendPostedEvents( w, TQEvent::Move ); + tqApp->sendPostedEvents( w, TQEvent::Resize ); +#ifdef TQ_WS_X11 + uint flags = TQt::WStyle_Customize | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop + | (w->isPopup() ? TQt::WType_Popup : (TQt::WX11BypassWM | TQt::WStyle_Tool)); +#else + uint flags = TQt::WStyle_Customize | TQt::WType_Popup | TQt::WX11BypassWM | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop; +#endif + + // those can popups - they would steal the focus, but are disabled + q_roll = new TQRollEffect( w, flags, orient ); + q_roll->run( time ); +} + +/*! + Fade in widget \a w in \a time ms. +*/ +void qFadeEffect( TQWidget* w, int time ) +{ + if ( q_blend ) { + delete q_blend; + q_blend = 0; + } + + tqApp->sendPostedEvents( w, TQEvent::Move ); + tqApp->sendPostedEvents( w, TQEvent::Resize ); + +#ifdef TQ_WS_X11 + uint flags = TQt::WStyle_Customize | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop + | (w->isPopup() ? TQt::WType_Popup : (TQt::WX11BypassWM | TQt::WStyle_Tool)); +#else + uint flags = TQt::WStyle_Customize | TQt::WType_Popup | TQt::WX11BypassWM | TQt::WNoAutoErase | TQt::WStyle_StaysOnTop; +#endif + + // those can popups - they would steal the focus, but are disabled + q_blend = new TQAlphaWidget( w, flags ); + + q_blend->run( time ); +} +#endif //TQT_NO_EFFECTS diff --git a/src/widgets/tqeffects_p.h b/src/widgets/tqeffects_p.h new file mode 100644 index 000000000..6dad1b23f --- /dev/null +++ b/src/widgets/tqeffects_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Definition of TQEffects functions +** +** Created : 000621 +** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the widgets module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQEFFECTS_P_H +#define TQEFFECTS_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of tqeffects.cpp, tqcombobox.cpp, tqpopupmenu.cpp and tqtooltip.cpp. +// This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqnamespace.h" +#endif // QT_H + +#ifndef TQT_NO_EFFECTS +class TQWidget; + +struct TQEffects +{ + enum Direction { + LeftScroll = 0x0001, + RightScroll = 0x0002, + UpScroll = 0x0004, + DownScroll = 0x0008 + }; + + typedef uint DirFlags; +}; + +extern void TQ_EXPORT qScrollEffect( TQWidget*, TQEffects::DirFlags dir = TQEffects::DownScroll, int time = -1 ); +extern void TQ_EXPORT qFadeEffect( TQWidget*, int time = -1 ); +#endif // TQT_NO_EFFECTS + +#endif // TQEFFECTS_P_H diff --git a/src/widgets/tqiconview.cpp b/src/widgets/tqiconview.cpp index 35b144b81..7af1babc8 100644 --- a/src/widgets/tqiconview.cpp +++ b/src/widgets/tqiconview.cpp @@ -69,7 +69,7 @@ #include "tqptrdict.h" #include "tqstringlist.h" #include "tqcleanuphandler.h" -#include "private/qrichtext_p.h" +#include "private/tqrichtext_p.h" #include "tqstyle.h" #include diff --git a/src/widgets/tqlineedit.cpp b/src/widgets/tqlineedit.cpp index 150e7f1d6..46b1df641 100644 --- a/src/widgets/tqlineedit.cpp +++ b/src/widgets/tqlineedit.cpp @@ -60,7 +60,7 @@ #include "tqguardedptr.h" #include "tqstyle.h" #include "tqwhatsthis.h" -#include "../kernel/qinternal_p.h" +#include "../kernel/tqinternal_p.h" #include "private/tqtextlayout_p.h" #include "tqvaluevector.h" #if defined(Q_OS_LINUX) diff --git a/src/widgets/tqlistview.cpp b/src/widgets/tqlistview.cpp index 54473b6c5..477743c2a 100644 --- a/src/widgets/tqlistview.cpp +++ b/src/widgets/tqlistview.cpp @@ -63,7 +63,7 @@ #include "tqtooltip.h" #include "tqstyle.h" #include "tqstylesheet.h" -#include "../kernel/qinternal_p.h" +#include "../kernel/tqinternal_p.h" #if defined(QT_ACCESSIBILITY_SUPPORT) #include "tqaccessible.h" #endif diff --git a/src/widgets/tqmenubar.cpp b/src/widgets/tqmenubar.cpp index 8bedca7a4..8577bda56 100644 --- a/src/widgets/tqmenubar.cpp +++ b/src/widgets/tqmenubar.cpp @@ -52,7 +52,7 @@ #include "tqguardedptr.h" #include "tqlayout.h" #include "tqcleanuphandler.h" -#include "../kernel/qinternal_p.h" +#include "../kernel/tqinternal_p.h" #include "tqstyle.h" #include "tqtimer.h" #if defined(QT_ACCESSIBILITY_SUPPORT) diff --git a/src/widgets/tqmultilineedit.cpp b/src/widgets/tqmultilineedit.cpp index 8311291b3..1ee4b712e 100644 --- a/src/widgets/tqmultilineedit.cpp +++ b/src/widgets/tqmultilineedit.cpp @@ -51,7 +51,7 @@ #include "tqpopupmenu.h" #include "tqtimer.h" #include "tqdict.h" -#include "../kernel/qrichtext_p.h" +#include "../kernel/tqrichtext_p.h" /*! diff --git a/src/widgets/tqpopupmenu.cpp b/src/widgets/tqpopupmenu.cpp index 2e68598d6..e614a328c 100644 --- a/src/widgets/tqpopupmenu.cpp +++ b/src/widgets/tqpopupmenu.cpp @@ -51,7 +51,7 @@ #include "tqwhatsthis.h" #include "tqobjectlist.h" #include "tqguardedptr.h" -#include "qeffects_p.h" +#include "tqeffects_p.h" #include "tqcursor.h" #include "tqstyle.h" #include "tqtimer.h" diff --git a/src/widgets/tqprogressbar.cpp b/src/widgets/tqprogressbar.cpp index 7efa4ce48..2b3f5074a 100644 --- a/src/widgets/tqprogressbar.cpp +++ b/src/widgets/tqprogressbar.cpp @@ -45,7 +45,7 @@ #include "tqpixmap.h" #include "tqstyle.h" #include "tqwmatrix.h" -#include "../kernel/qinternal_p.h" +#include "../kernel/tqinternal_p.h" #if defined(QT_ACCESSIBILITY_SUPPORT) #include "tqaccessible.h" #endif diff --git a/src/widgets/tqsyntaxhighlighter.cpp b/src/widgets/tqsyntaxhighlighter.cpp index 223f7930c..f124b7ce2 100644 --- a/src/widgets/tqsyntaxhighlighter.cpp +++ b/src/widgets/tqsyntaxhighlighter.cpp @@ -42,7 +42,7 @@ #include "private/tqsyntaxhighlighter_p.h" #ifndef TQT_NO_SYNTAXHIGHLIGHTER -#include "../kernel/qrichtext_p.h" +#include "../kernel/tqrichtext_p.h" #include "tqtextedit.h" #include "tqtimer.h" diff --git a/src/widgets/tqsyntaxhighlighter_p.h b/src/widgets/tqsyntaxhighlighter_p.h index c4d7deabf..c72094f92 100644 --- a/src/widgets/tqsyntaxhighlighter_p.h +++ b/src/widgets/tqsyntaxhighlighter_p.h @@ -43,7 +43,7 @@ #ifndef TQT_NO_SYNTAXHIGHLIGHTER #include "tqsyntaxhighlighter.h" -#include "private/qrichtext_p.h" +#include "private/tqrichtext_p.h" class TQSyntaxHighlighterPrivate { diff --git a/src/widgets/tqtabbar.cpp b/src/widgets/tqtabbar.cpp index 7c9ebb2c4..cba1906c8 100644 --- a/src/widgets/tqtabbar.cpp +++ b/src/widgets/tqtabbar.cpp @@ -47,7 +47,7 @@ #include "tqpainter.h" #include "tqiconset.h" #include "tqcursor.h" -#include "../kernel/qinternal_p.h" +#include "../kernel/tqinternal_p.h" #if defined(QT_ACCESSIBILITY_SUPPORT) #include "tqaccessible.h" #endif diff --git a/src/widgets/tqtextbrowser.cpp b/src/widgets/tqtextbrowser.cpp index 69ae10d56..161757d19 100644 --- a/src/widgets/tqtextbrowser.cpp +++ b/src/widgets/tqtextbrowser.cpp @@ -40,7 +40,7 @@ #include "tqtextbrowser.h" #ifndef TQT_NO_TEXTBROWSER -#include "../kernel/qrichtext_p.h" +#include "../kernel/tqrichtext_p.h" #include "ntqapplication.h" #include "tqlayout.h" diff --git a/src/widgets/tqtextedit.cpp b/src/widgets/tqtextedit.cpp index 2c8bf3ba4..baddd23c5 100644 --- a/src/widgets/tqtextedit.cpp +++ b/src/widgets/tqtextedit.cpp @@ -47,7 +47,7 @@ #include "tqinputcontext.h" #endif -#include "../kernel/qrichtext_p.h" +#include "../kernel/tqrichtext_p.h" #include "tqpainter.h" #include "tqpen.h" #include "tqbrush.h" @@ -74,7 +74,7 @@ #include "tqptrstack.h" #include "tqmetaobject.h" #include "tqtextbrowser.h" -#include +#include #include "private/tqsyntaxhighlighter_p.h" #include diff --git a/src/widgets/tqtitlebar.cpp b/src/widgets/tqtitlebar.cpp new file mode 100644 index 000000000..83bb8c125 --- /dev/null +++ b/src/widgets/tqtitlebar.cpp @@ -0,0 +1,671 @@ +/**************************************************************************** +** +** Implementation of some TQt private functions. +** +** Created : 001101 +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the widgets module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qplatformdefs.h" + +#include "tqtitlebar_p.h" + +#ifndef TQT_NO_TITLEBAR + +#include +#include "ntqapplication.h" +#include "tqstyle.h" +#include "tqdatetime.h" +#include "private/qapplication_p.h" +#include "tqtooltip.h" +#include "tqimage.h" +#include "tqtimer.h" +#include "tqpainter.h" +#include "tqstyle.h" +#include "private/tqinternal_p.h" +#ifndef TQT_NO_WORKSPACE +#include "tqworkspace.h" +#endif +#if defined(TQ_WS_WIN) +#include "qt_windows.h" +#endif + +#ifndef TQT_NO_TOOLTIP +class TQTitleBarTip : public TQToolTip +{ +public: + TQTitleBarTip( TQWidget * parent ) : TQToolTip( parent ) { } + + void maybeTip( const TQPoint &pos ) + { + if ( !::tqt_cast(parentWidget()) ) + return; + TQTitleBar *t = (TQTitleBar *)parentWidget(); + + TQString tipstring; + TQStyle::SubControl ctrl = t->style().querySubControl(TQStyle::CC_TitleBar, t, pos); + TQSize controlSize = t->style().querySubControlMetrics(TQStyle::CC_TitleBar, t, ctrl).size(); + + TQWidget *window = t->window(); + if ( window ) { + switch(ctrl) { + case TQStyle::SC_TitleBarSysMenu: + if ( t->testWFlags( WStyle_SysMenu ) ) + tipstring = TQTitleBar::tr( "System Menu" ); + break; + + case TQStyle::SC_TitleBarShadeButton: + if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) ) + tipstring = TQTitleBar::tr( "Shade" ); + break; + + case TQStyle::SC_TitleBarUnshadeButton: + if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) ) + tipstring = TQTitleBar::tr( "Unshade" ); + break; + + case TQStyle::SC_TitleBarNormalButton: + case TQStyle::SC_TitleBarMinButton: + if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Minimize ) ) { + if( window->isMinimized() ) + tipstring = TQTitleBar::tr( "Normalize" ); + else + tipstring = TQTitleBar::tr( "Minimize" ); + } + break; + + case TQStyle::SC_TitleBarMaxButton: + if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Maximize ) ) + tipstring = TQTitleBar::tr( "Maximize" ); + break; + + case TQStyle::SC_TitleBarCloseButton: + if ( t->testWFlags( WStyle_SysMenu ) ) + tipstring = TQTitleBar::tr( "Close" ); + break; + + default: + break; + } + } +#ifndef TQT_NO_WIDGET_TOPEXTRA + if ( tipstring.isEmpty() ) { + if ( t->visibleText() != t->caption() ) + tipstring = t->caption(); + } +#endif + if(!tipstring.isEmpty()) + tip( TQRect(pos, controlSize), tipstring ); + } +}; +#endif + +class TQTitleBarPrivate +{ +public: + TQTitleBarPrivate() + : toolTip( 0 ), act( 0 ), window( 0 ), movable( 1 ), pressed( 0 ), autoraise(0) + { + } + + TQStyle::SCFlags buttonDown; + TQPoint moveOffset; + TQToolTip *toolTip; + bool act :1; + TQWidget* window; + bool movable :1; + bool pressed :1; + bool autoraise :1; + TQString cuttext; +#ifdef TQT_NO_WIDGET_TOPEXTRA + TQString cap; +#endif +}; + +TQTitleBar::TQTitleBar(TQWidget* w, TQWidget* parent, const char* name) + : TQWidget( parent, name, WStyle_Customize | WStyle_NoBorder | WNoAutoErase ) +{ + d = new TQTitleBarPrivate(); + +#ifndef TQT_NO_TOOLTIP + d->toolTip = new TQTitleBarTip( this ); +#endif + d->window = w; + d->buttonDown = TQStyle::SC_None; + d->act = 0; + if ( w ) { + setWFlags( ((TQTitleBar*)w)->getWFlags() | WNoAutoErase ); + if ( w->minimumSize() == w->maximumSize() ) + clearWFlags( WStyle_Maximize ); +#ifndef TQT_NO_WIDGET_TOPEXTRA + setCaption( w->caption() ); +#endif + } else { + setWFlags( WStyle_Customize | WNoAutoErase ); + } + + readColors(); + setSizePolicy( TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Fixed ) ); + setMouseTracking(TRUE); +} + +TQTitleBar::~TQTitleBar() +{ +#ifndef TQT_NO_TOOLTIP + delete d->toolTip; +#endif + + delete d; + d = 0; +} + +#ifdef TQ_WS_WIN +extern TQRgb qt_colorref2qrgb(COLORREF col); +#endif + +void TQTitleBar::readColors() +{ + TQPalette pal = palette(); + + bool colorsInitialized = FALSE; + +#ifdef TQ_WS_WIN // ask system properties on windows +#ifndef SPI_GETGRADIENTCAPTIONS +#define SPI_GETGRADIENTCAPTIONS 0x1008 +#endif +#ifndef COLOR_GRADIENTACTIVECAPTION +#define COLOR_GRADIENTACTIVECAPTION 27 +#endif +#ifndef COLOR_GRADIENTINACTIVECAPTION +#define COLOR_GRADIENTINACTIVECAPTION 28 +#endif + if ( TQApplication::desktopSettingsAware() ) { + pal.setColor( TQPalette::Active, TQColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)) ); + pal.setColor( TQPalette::Inactive, TQColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)) ); + pal.setColor( TQPalette::Active, TQColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)) ); + pal.setColor( TQPalette::Inactive, TQColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)) ); + if ( qt_winver != TQt::WV_95 && qt_winver != WV_NT ) { + colorsInitialized = TRUE; + BOOL gradient; + QT_WA( { + SystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 ); + } , { + SystemParametersInfoA( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 ); + } ); + if ( gradient ) { + pal.setColor( TQPalette::Active, TQColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)) ); + pal.setColor( TQPalette::Inactive, TQColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)) ); + } else { + pal.setColor( TQPalette::Active, TQColorGroup::Base, palette().active().highlight() ); + pal.setColor( TQPalette::Inactive, TQColorGroup::Base, palette().inactive().highlight() ); + } + } + } +#endif // TQ_WS_WIN + if ( !colorsInitialized ) { + pal.setColor( TQPalette::Active, TQColorGroup::Highlight, palette().active().highlight() ); + pal.setColor( TQPalette::Active, TQColorGroup::Base, palette().active().highlight() ); + pal.setColor( TQPalette::Inactive, TQColorGroup::Highlight, palette().inactive().dark() ); + pal.setColor( TQPalette::Inactive, TQColorGroup::Base, palette().inactive().dark() ); + pal.setColor( TQPalette::Inactive, TQColorGroup::HighlightedText, palette().inactive().background() ); + } + + setPalette( pal ); + setActive( d->act ); +} + +void TQTitleBar::mousePressEvent( TQMouseEvent * e) +{ + if ( !d->act ) + emit doActivate(); + if ( e->button() == LeftButton ) { + d->pressed = TRUE; + TQStyle::SCFlags ctrl = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); + switch (ctrl) { + case TQStyle::SC_TitleBarSysMenu: + if ( testWFlags( WStyle_SysMenu ) && !testWFlags( WStyle_Tool ) ) { + d->buttonDown = TQStyle::SC_None; + static TQTime* t = 0; + static TQTitleBar* tc = 0; + if ( !t ) + t = new TQTime; + if ( tc != this || t->elapsed() > TQApplication::doubleClickInterval() ) { + emit showOperationMenu(); + t->start(); + tc = this; + } else { + tc = 0; + emit doClose(); + return; + } + } + break; + + case TQStyle::SC_TitleBarShadeButton: + case TQStyle::SC_TitleBarUnshadeButton: + if ( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) ) + d->buttonDown = ctrl; + break; + + case TQStyle::SC_TitleBarNormalButton: + if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) ) + d->buttonDown = ctrl; + break; + + case TQStyle::SC_TitleBarMinButton: + if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) ) + d->buttonDown = ctrl; + break; + + case TQStyle::SC_TitleBarMaxButton: + if ( testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) ) + d->buttonDown = ctrl; + break; + + case TQStyle::SC_TitleBarCloseButton: + if ( testWFlags( WStyle_SysMenu ) ) + d->buttonDown = ctrl; + break; + + case TQStyle::SC_TitleBarLabel: + d->buttonDown = ctrl; + d->moveOffset = mapToParent( e->pos() ); + break; + + default: + break; + } + repaint( FALSE ); + } else { + d->pressed = FALSE; + } +} + +void TQTitleBar::contextMenuEvent( TQContextMenuEvent *e ) +{ + TQStyle::SCFlags ctrl = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); + if( ctrl == TQStyle::SC_TitleBarLabel || ctrl == TQStyle::SC_TitleBarSysMenu ) + emit popupOperationMenu(e->globalPos()); + else + e->ignore(); +} + +void TQTitleBar::mouseReleaseEvent( TQMouseEvent * e) +{ + if ( e->button() == LeftButton && d->pressed) { + TQStyle::SCFlags ctrl = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); + + if (ctrl == d->buttonDown) { + switch(ctrl) { + case TQStyle::SC_TitleBarShadeButton: + case TQStyle::SC_TitleBarUnshadeButton: + if( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) ) + emit doShade(); + break; + + case TQStyle::SC_TitleBarNormalButton: + if( testWFlags( WStyle_MinMax ) && !testWFlags( WStyle_Tool ) ) + emit doNormal(); + break; + + case TQStyle::SC_TitleBarMinButton: + if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) ) + emit doMinimize(); + break; + + case TQStyle::SC_TitleBarMaxButton: + if( d->window && testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) ) { + if(d->window->isMaximized()) + emit doNormal(); + else + emit doMaximize(); + } + break; + + case TQStyle::SC_TitleBarCloseButton: + if( testWFlags( WStyle_SysMenu ) ) { + d->buttonDown = TQStyle::SC_None; + repaint(FALSE); + emit doClose(); + return; + } + break; + + default: + break; + } + } + d->buttonDown = TQStyle::SC_None; + repaint(FALSE); + d->pressed = FALSE; + } +} + +void TQTitleBar::mouseMoveEvent( TQMouseEvent * e) +{ + switch (d->buttonDown) { + case TQStyle::SC_None: + if(autoRaise()) + repaint( FALSE ); + break; + case TQStyle::SC_TitleBarSysMenu: + break; + case TQStyle::SC_TitleBarShadeButton: + case TQStyle::SC_TitleBarUnshadeButton: + case TQStyle::SC_TitleBarNormalButton: + case TQStyle::SC_TitleBarMinButton: + case TQStyle::SC_TitleBarMaxButton: + case TQStyle::SC_TitleBarCloseButton: + { + TQStyle::SCFlags last_ctrl = d->buttonDown; + d->buttonDown = style().querySubControl(TQStyle::CC_TitleBar, this, e->pos()); + if( d->buttonDown != last_ctrl) + d->buttonDown = TQStyle::SC_None; + repaint(FALSE); + d->buttonDown = last_ctrl; + } + break; + + case TQStyle::SC_TitleBarLabel: + if ( d->buttonDown == TQStyle::SC_TitleBarLabel && d->movable && d->pressed ) { + if ( (d->moveOffset - mapToParent( e->pos() ) ).manhattanLength() >= 4 ) { + TQPoint p = mapFromGlobal(e->globalPos()); +#ifndef TQT_NO_WORKSPACE + if(d->window && d->window->parentWidget()->inherits("TQWorkspaceChild")) { + TQWorkspace *workspace = ::tqt_cast(d->window->parentWidget()->parentWidget()); + if(workspace) { + p = workspace->mapFromGlobal( e->globalPos() ); + if ( !workspace->rect().contains(p) ) { + if ( p.x() < 0 ) + p.rx() = 0; + if ( p.y() < 0 ) + p.ry() = 0; + if ( p.x() > workspace->width() ) + p.rx() = workspace->width(); + if ( p.y() > workspace->height() ) + p.ry() = workspace->height(); + } + } + } +#endif + TQPoint pp = p - d->moveOffset; + if (!parentWidget()->isMaximized()) + parentWidget()->move( pp ); + } + } else { + TQStyle::SCFlags last_ctrl = d->buttonDown; + d->buttonDown = TQStyle::SC_None; + if( d->buttonDown != last_ctrl) + repaint(FALSE); + } + break; + } +} + +void TQTitleBar::resizeEvent( TQResizeEvent *r) +{ + TQWidget::resizeEvent(r); + cutText(); +} + +void TQTitleBar::paintEvent(TQPaintEvent *) +{ + TQStyle::SCFlags ctrls = TQStyle::SC_TitleBarLabel; + if ( testWFlags( WStyle_SysMenu) ) { + if ( testWFlags( WStyle_Tool ) ) { + ctrls |= TQStyle::SC_TitleBarCloseButton; + if ( d->window && testWFlags( WStyle_MinMax ) ) { + if ( d->window->isMinimized() ) + ctrls |= TQStyle::SC_TitleBarUnshadeButton; + else + ctrls |= TQStyle::SC_TitleBarShadeButton; + } + } else { + ctrls |= TQStyle::SC_TitleBarSysMenu | TQStyle::SC_TitleBarCloseButton; + if ( d->window && testWFlags( WStyle_Minimize ) ) { + if( d->window && d->window->isMinimized() ) + ctrls |= TQStyle::SC_TitleBarNormalButton; + else + ctrls |= TQStyle::SC_TitleBarMinButton; + } + if ( d->window && testWFlags( WStyle_Maximize ) && !d->window->isMaximized() ) + ctrls |= TQStyle::SC_TitleBarMaxButton; + } + } + + TQStyle::SCFlags under_mouse = TQStyle::SC_None; + if( autoRaise() && hasMouse() ) { + TQPoint p(mapFromGlobal(TQCursor::pos())); + under_mouse = style().querySubControl(TQStyle::CC_TitleBar, this, p); + ctrls ^= under_mouse; + } + + TQSharedDoubleBuffer buffer( this, rect() ); + style().drawComplexControl(TQStyle::CC_TitleBar, buffer.painter(), this, rect(), + colorGroup(), + isEnabled() ? TQStyle::Style_Enabled : + TQStyle::Style_Default, ctrls, d->buttonDown); + if(under_mouse != TQStyle::SC_None) + style().drawComplexControl(TQStyle::CC_TitleBar, buffer.painter(), this, rect(), + colorGroup(), + TQStyle::Style_MouseOver | + (isEnabled() ? TQStyle::Style_Enabled : 0), + under_mouse, d->buttonDown); +} + +void TQTitleBar::mouseDoubleClickEvent( TQMouseEvent *e ) +{ + if ( e->button() != LeftButton ) + return; + + switch(style().querySubControl(TQStyle::CC_TitleBar, this, e->pos())) { + case TQStyle::SC_TitleBarLabel: + emit doubleClicked(); + break; + + case TQStyle::SC_TitleBarSysMenu: + if ( testWFlags( WStyle_SysMenu ) ) + emit doClose(); + break; + + default: + break; + } +} + +#ifdef TQT_NO_WIDGET_TOPEXTRA +// We provide one, since titlebar is useless otherwise. +TQString TQTitleBar::caption() const +{ + return d->cap; +} +#endif + +void TQTitleBar::cutText() +{ + TQFontMetrics fm( font() ); + + int maxw = style().querySubControlMetrics(TQStyle::CC_TitleBar, this, + TQStyle::SC_TitleBarLabel).width(); + if ( !d->window ) + maxw = width() - 20; + const TQString txt = caption(); + d->cuttext = txt; + if ( fm.width( txt + "m" ) > maxw ) { + int i = txt.length(); + int dotlength = fm.width( "..." ); + while ( i>0 && fm.width(txt.left( i )) + dotlength > maxw ) + i--; + if(i != (int)txt.length()) + d->cuttext = txt.left( i ) + "..."; + } +} + +void TQTitleBar::setCaption( const TQString& title ) +{ + if( caption() == title) + return; +#ifndef TQT_NO_WIDGET_TOPEXTRA + TQWidget::setCaption( title ); +#else + d->cap = title; +#endif + cutText(); + + update(); +} + + +void TQTitleBar::setIcon( const TQPixmap& icon ) +{ +#ifndef TQT_NO_WIDGET_TOPEXTRA +#ifndef TQT_NO_IMAGE_SMOOTHSCALE + TQRect menur = style().querySubControlMetrics(TQStyle::CC_TitleBar, this, + TQStyle::SC_TitleBarSysMenu); + + TQPixmap theIcon; + if (icon.width() > menur.width()) { + // try to keep something close to the same aspect + int aspect = (icon.height() * 100) / icon.width(); + int newh = (aspect * menur.width()) / 100; + theIcon.convertFromImage( icon.convertToImage().smoothScale(menur.width(), + newh) ); + } else if (icon.height() > menur.height()) { + // try to keep something close to the same aspect + int aspect = (icon.width() * 100) / icon.height(); + int neww = (aspect * menur.height()) / 100; + theIcon.convertFromImage( icon.convertToImage().smoothScale(neww, + menur.height()) ); + } else + theIcon = icon; + + TQWidget::setIcon( theIcon ); +#else + TQWidget::setIcon( icon ); +#endif + + update(); +#endif +} + +void TQTitleBar::leaveEvent( TQEvent * ) +{ + if(autoRaise() && !d->pressed) + repaint( FALSE ); +} + +void TQTitleBar::enterEvent( TQEvent * ) +{ + if(autoRaise() && !d->pressed) + repaint( FALSE ); + TQEvent e( TQEvent::Leave ); + TQApplication::sendEvent( parentWidget(), &e ); +} + +void TQTitleBar::setActive( bool active ) +{ + if ( d->act == active ) + return ; + + d->act = active; + update(); +} + +bool TQTitleBar::isActive() const +{ + return d->act; +} + +bool TQTitleBar::usesActiveColor() const +{ + return ( isActive() && isActiveWindow() ) || + ( !window() && topLevelWidget()->isActiveWindow() ); +} + +TQString TQTitleBar::visibleText() const +{ + return d->cuttext; +} + +TQWidget *TQTitleBar::window() const +{ + return d->window; +} + +bool TQTitleBar::event( TQEvent* e ) +{ + if ( e->type() == TQEvent::ApplicationPaletteChange ) { + readColors(); + return TRUE; + } else if ( e->type() == TQEvent::WindowActivate ) { + setActive( d->act ); + } else if ( e->type() == TQEvent::WindowDeactivate ) { + bool wasActive = d->act; + setActive( FALSE ); + d->act = wasActive; + } + + return TQWidget::event( e ); +} + +void TQTitleBar::setMovable(bool b) +{ + d->movable = b; +} + +bool TQTitleBar::isMovable() const +{ + return d->movable; +} + +void TQTitleBar::setAutoRaise(bool b) +{ + d->autoraise = b; +} + +bool TQTitleBar::autoRaise() const +{ + return d->autoraise; +} + +TQSize TQTitleBar::sizeHint() const +{ + constPolish(); + TQRect menur = style().querySubControlMetrics(TQStyle::CC_TitleBar, this, + TQStyle::SC_TitleBarSysMenu); + return TQSize( menur.width(), style().pixelMetric( TQStyle::PM_TitleBarHeight, this ) ); +} + +#endif //TQT_NO_TITLEBAR diff --git a/src/widgets/tqtitlebar_p.h b/src/widgets/tqtitlebar_p.h new file mode 100644 index 000000000..e3d20023e --- /dev/null +++ b/src/widgets/tqtitlebar_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Definition of some TQt private functions. +** +** Created : 000101 +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the widgets module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQTITLEBAR_P_H +#define TQTITLEBAR_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of tqworkspace.cpp and tqdockwindow.cpp. This header file may change +// from version to version without notice, or even be removed. +// +// We mean it. +// +// + + +#ifndef QT_H +#include "tqbutton.h" +#include "tqlabel.h" +#endif // QT_H + +#if !defined(TQT_NO_TITLEBAR) + +class TQToolTip; +class TQTitleBarPrivate; +class TQPixmap; + +class TQ_EXPORT TQTitleBar : public TQWidget +{ + TQ_OBJECT + TQ_PROPERTY( bool autoRaise READ autoRaise WRITE setAutoRaise ) + TQ_PROPERTY( bool movable READ isMovable WRITE setMovable ) + +public: + TQTitleBar (TQWidget* w, TQWidget* parent, const char* name=0); + ~TQTitleBar(); + + bool isActive() const; + bool usesActiveColor() const; + virtual TQString visibleText() const; + + bool isMovable() const; + void setMovable(bool); + + bool autoRaise() const; + void setAutoRaise(bool); + + TQWidget *window() const; + + TQSize sizeHint() const; + +#ifdef TQT_NO_WIDGET_TOPEXTRA + // We provide one, since titlebar is useless otherwise. + TQString caption() const; +#endif + +public slots: + void setActive( bool ); + void setCaption( const TQString& title ); + void setIcon( const TQPixmap& icon ); + +signals: + void doActivate(); + void doNormal(); + void doClose(); + void doMaximize(); + void doMinimize(); + void doShade(); + void showOperationMenu(); + void popupOperationMenu( const TQPoint& ); + void doubleClicked(); + +protected: + bool event( TQEvent *); + void resizeEvent( TQResizeEvent *); + void contextMenuEvent( TQContextMenuEvent * ); + void mousePressEvent( TQMouseEvent * ); + void mouseDoubleClickEvent( TQMouseEvent * ); + void mouseReleaseEvent( TQMouseEvent * ); + void mouseMoveEvent( TQMouseEvent * ); + void enterEvent( TQEvent *e ); + void leaveEvent( TQEvent *e ); + void paintEvent( TQPaintEvent *p ); + + virtual void cutText(); + +private: + void readColors(); + + TQTitleBarPrivate *d; +#if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= + TQTitleBar( const TQTitleBar & ); + TQTitleBar &operator=( const TQTitleBar & ); +#endif +}; + +#endif +#endif //TQTITLEBAR_P_H diff --git a/src/widgets/tqtooltip.cpp b/src/widgets/tqtooltip.cpp index ee0a097fe..e044be6ea 100644 --- a/src/widgets/tqtooltip.cpp +++ b/src/widgets/tqtooltip.cpp @@ -43,7 +43,7 @@ #include "ntqapplication.h" #include "tqguardedptr.h" #include "tqtimer.h" -#include "qeffects_p.h" +#include "tqeffects_p.h" static bool globally_enabled = TRUE; diff --git a/src/widgets/tqwidgetinterface_p.h b/src/widgets/tqwidgetinterface_p.h index 28986af38..81a158cc5 100644 --- a/src/widgets/tqwidgetinterface_p.h +++ b/src/widgets/tqwidgetinterface_p.h @@ -52,7 +52,7 @@ // #ifndef QT_H -#include +#include #include "tqiconset.h" #endif // QT_H diff --git a/src/workspace/tqworkspace.cpp b/src/workspace/tqworkspace.cpp index 2ab278119..1677b3a41 100644 --- a/src/workspace/tqworkspace.cpp +++ b/src/workspace/tqworkspace.cpp @@ -41,7 +41,7 @@ #include "tqworkspace.h" #ifndef TQT_NO_WORKSPACE #include "ntqapplication.h" -#include "../widgets/qtitlebar_p.h" +#include "../widgets/tqtitlebar_p.h" #include "tqobjectlist.h" #include "tqlayout.h" #include "tqtoolbutton.h" diff --git a/src/xml/qsvgdevice.cpp b/src/xml/qsvgdevice.cpp deleted file mode 100644 index e6dfb86a0..000000000 --- a/src/xml/qsvgdevice.cpp +++ /dev/null @@ -1,1591 +0,0 @@ -/**************************************************************************** -** -** Implementation of the TQSvgDevice class -** -** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the xml module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -*****************************************************************************/ - -#include - -#ifndef TQT_NO_SVG - -#include "tqpainter.h" -#include "tqpaintdevicemetrics.h" -#include "tqfile.h" -#include "tqmap.h" -#include "tqregexp.h" -#include "tqvaluelist.h" -#include "tqtextstream.h" -#include "tqimage.h" -#include "tqpixmap.h" - -#include - -const double deg2rad = 0.017453292519943295769; // pi/180 -const char piData[] = "version=\"1.0\" standalone=\"no\""; -const char publicId[] = "-//W3C//DTD SVG 20001102//EN"; -const char systemId[] = "http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd"; - -struct TQM_EXPORT_SVG ImgElement { - TQDomElement element; - TQImage image; - TQ_DUMMY_COMPARISON_OPERATOR( ImgElement ) -}; - -struct TQM_EXPORT_SVG PixElement { - TQDomElement element; - TQPixmap pixmap; - TQ_DUMMY_COMPARISON_OPERATOR( PixElement ) -}; - -struct TQSvgDeviceState { - int textx, texty; // current text position - int textalign; // text alignment - TQ_DUMMY_COMPARISON_OPERATOR( TQSvgDeviceState ) -}; - -typedef TQValueList ImageList; -typedef TQValueList PixmapList; -typedef TQValueList StateList; - -class TQSvgDevicePrivate { -public: - ImageList images; - PixmapList pixmaps; - StateList stack; - int currentClip; - - uint justRestored : 1; - - TQMap clipPathTable; -}; - -enum ElementType { - InvalidElement = 0, - AnchorElement, - CircleElement, - ClipElement, - CommentElement, - DescElement, - EllipseElement, - GroupElement, - ImageElement, - LineElement, - PolylineElement, - PolygonElement, - PathElement, - RectElement, - SvgElement, - TextElement, - TitleElement, - TSpanElement -}; - -typedef TQMap TQSvgTypeMap; -static TQSvgTypeMap *qSvgTypeMap=0; // element types -static TQMap *qSvgColMap=0; // recognized color keyword names - -/*! - \class TQSvgDevice qsvgdevice.h - \brief The TQSvgDevice class provides a paint device for SVG vector graphics. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup xml-tools - \module XML - \internal - - SVG is an XML vector graphics format. This class supports the - loading and saving of SVG files with load() and save(), and the - rendering of an SVG onto a TQPainter using play(). Use toString() - to put the SVG into a string. - - \sa TQPaintDevice TQPainter -*/ - -/*! - Creates a TQSvgDevice object. -*/ - -TQSvgDevice::TQSvgDevice() - : TQPaintDevice( TQInternal::ExternalDevice ), - pt( 0 ) -{ - d = new TQSvgDevicePrivate; - d->currentClip = 0; - d->justRestored = FALSE; -} - -/*! - Destroys the TQSvgDevice object and frees the resources it used. -*/ - -TQSvgDevice::~TQSvgDevice() -{ - delete qSvgTypeMap; qSvgTypeMap = 0; // static - delete qSvgColMap; qSvgColMap = 0; - delete d; -} - -/*! - Loads and parses a SVG from \a dev into the device. Returns TRUE - on success (i.e. loaded and parsed without error); otherwise - returns FALSE. -*/ - -bool TQSvgDevice::load( TQIODevice *dev ) -{ - return doc.setContent( dev ); -} - -/*! - Renders (replays) the SVG on the \a painter and returns TRUE if - successful (i.e. it is a valid SVG); otherwise returns FALSE. -*/ - -bool TQSvgDevice::play( TQPainter *painter ) -{ - if ( !painter ) { -#if defined(QT_CHECK_RANGE) - Q_ASSERT( painter ); -#endif - return FALSE; - } - pt = painter; - pt->setPen( TQt::NoPen ); // SVG default pen and brush - pt->setBrush( TQt::black ); - if ( doc.isNull() ) { - tqWarning( "TQSvgDevice::play: No SVG data set." ); - return FALSE; - } - - TQDomNode svg = doc.namedItem( "svg" ); - if ( svg.isNull() || !svg.isElement() ) { - tqWarning( "TQSvgDevice::play: Couldn't find any svg element." ); - return FALSE; - } - - // force transform to be activated in case our sequences - // are replayed later with a transformed painter - painter->setWorldXForm( TRUE ); - - TQDomNamedNodeMap attr = svg.attributes(); - int x = lenToInt( attr, "x" ); - int y = lenToInt( attr, "y" ); - brect.setX( x ); - brect.setY( y ); - TQString wstr = attr.contains( "width" ) - ? attr.namedItem( "width" ).nodeValue() : TQString( "100%" ); - TQString hstr = attr.contains( "height" ) - ? attr.namedItem( "height" ).nodeValue() : TQString( "100%" ); - double width = parseLen( wstr, 0, TRUE ); - double height = parseLen( hstr, 0, FALSE ); - // SVG doesn't respect x and y. But we want a proper bounding rect. - brect.setWidth( int(width) - x ); - brect.setHeight( int(height) - y ); - painter->setClipRect( brect, TQPainter::CoordPainter ); - - if ( attr.contains( "viewBox" ) ) { - TQRegExp re( TQString::fromLatin1("\\s*(\\S+)\\s*,?\\s*(\\S+)\\s*,?" - "\\s*(\\S+)\\s*,?\\s*(\\S+)\\s*") ); - if ( re.search( attr.namedItem( "viewBox" ).nodeValue() ) < 0 ) { - tqWarning( "TQSvgDevice::play: Invalid viewBox attribute."); - return FALSE; - } else { - double x = re.cap( 1 ).toDouble(); - double y = re.cap( 2 ).toDouble(); - double w = re.cap( 3 ).toDouble(); - double h = re.cap( 4 ).toDouble(); - if ( w < 0 || h < 0 ) { - tqWarning( "TQSvgDevice::play: Invalid viewBox dimension."); - return FALSE; - } else if ( w == 0 || h == 0 ) { - return TRUE; - } - painter->scale( width/w, height/h ); - painter->translate( -x, -y ); - } - } - - const struct ElementTable { - const char *name; - ElementType type; - } etab[] = { - { "a", AnchorElement }, - { "#comment", CommentElement }, - { "circle", CircleElement }, - { "clipPath", ClipElement }, - { "desc", DescElement }, - { "ellipse", EllipseElement }, - { "g", GroupElement }, - { "image", ImageElement }, - { "line", LineElement }, - { "polyline", PolylineElement }, - { "polygon", PolygonElement }, - { "path", PathElement }, - { "rect", RectElement }, - { "svg", SvgElement }, - { "text", TextElement }, - { "tspan", TSpanElement }, - { "title", TitleElement }, - { 0, InvalidElement } - }; - // initialize only once - if ( !qSvgTypeMap ) { - qSvgTypeMap = new TQSvgTypeMap; - const ElementTable *t = etab; - while ( t->name ) { - qSvgTypeMap->insert( t->name, t->type ); - t++; - } - } - - // initial state - TQSvgDeviceState st; - st.textx = st.texty = 0; - st.textalign = TQt::AlignLeft; - d->stack.append(st); - curr = &d->stack.last(); - // 'play' all elements recursively starting with 'svg' as root - bool b = play( svg ); - d->stack.remove( d->stack.begin() ); - return b; -} - -/*! - Returns the SVG as a single string of XML. -*/ -TQString TQSvgDevice::toString() const -{ - if ( doc.isNull() ) - return TQString(); - - return doc.toString(); -} - -/*! - Saves the SVG to \a fileName. -*/ - -bool TQSvgDevice::save( const TQString &fileName ) -{ - // guess svg id from fileName - TQString svgName = fileName.endsWith( ".svg" ) ? - fileName.left( fileName.length()-4 ) : fileName; - - // now we have the info about name and dimensions available - TQDomElement root = doc.documentElement(); - root.setAttribute( "id", svgName ); - // the standard doesn't take respect x and y. But we want a - // proper bounding rect. We make width and height bigger when - // writing out and subtract x and y when reading in. - root.setAttribute( "x", brect.x() ); - root.setAttribute( "y", brect.y() ); - root.setAttribute( "width", brect.width() + brect.x() ); - root.setAttribute( "height", brect.height() + brect.y() ); - - // ... and know how to name any image files to be written out - int icount = 0; - ImageList::Iterator iit = d->images.begin(); - for ( ; iit != d->images.end(); ++iit ) { - TQString href = TQString( "%1_%2.png" ).arg( svgName ).arg( icount ); - (*iit).image.save( href, "PNG" ); - (*iit).element.setAttribute( "xlink:href", href ); - icount++; - } - PixmapList::Iterator pit = d->pixmaps.begin(); - for ( ; pit != d->pixmaps.end(); ++pit ) { - TQString href = TQString( "%1_%2.png" ).arg( svgName ).arg( icount ); - (*pit).pixmap.save( href, "PNG" ); - (*pit).element.setAttribute( "xlink:href", href ); - icount++; - } - - TQFile f( fileName ); - if ( !f.open ( IO_WriteOnly ) ) - return FALSE; - TQTextStream s( &f ); - s.setEncoding( TQTextStream::UnicodeUTF8 ); - s << doc; - - return TRUE; -} - -/*! - \overload - - \a dev is the device to use for saving. -*/ - -bool TQSvgDevice::save( TQIODevice *dev ) -{ -#if defined(CHECK_RANGE) - if ( !d->images.isEmpty() || !d->pixmaps.isEmpty() ) - tqWarning( "TQSvgDevice::save: skipping external images" ); -#endif - - TQTextStream s( dev ); - s.setEncoding( TQTextStream::UnicodeUTF8 ); - s << doc; - - return TRUE; -} - -/*! - \fn TQRect TQSvgDevice::boundingRect() const - - Returns the bounding rectangle of the SVG. -*/ - -/*! - Sets the bounding rectangle of the SVG to rectangle \a r. -*/ - -void TQSvgDevice::setBoundingRect( const TQRect &r ) -{ - brect = r; -} - -/*! - Internal implementation of the virtual TQPaintDevice::metric() - function. - - \warning Use the TQPaintDeviceMetrics class instead. - - A TQSvgDevice has the following hard coded values: dpi=72, - numcolors=16777216 and depth=24. \a m is the metric to get. -*/ - -int TQSvgDevice::metric( int m ) const -{ - int val; - switch ( m ) { - case TQPaintDeviceMetrics::PdmWidth: - val = brect.width(); - break; - case TQPaintDeviceMetrics::PdmHeight: - val = brect.height(); - break; - case TQPaintDeviceMetrics::PdmWidthMM: - val = int(25.4/72.0*brect.width()); - break; - case TQPaintDeviceMetrics::PdmHeightMM: - val = int(25.4/72.0*brect.height()); - break; - case TQPaintDeviceMetrics::PdmDpiX: - val = 72; - break; - case TQPaintDeviceMetrics::PdmDpiY: - val = 72; - break; - case TQPaintDeviceMetrics::PdmNumColors: - val = 16777216; - break; - case TQPaintDeviceMetrics::PdmDepth: - val = 24; - break; - default: - val = 0; -#if defined(QT_CHECK_RANGE) - tqWarning( "TQSvgDevice::metric: Invalid metric command" ); -#endif - } - return val; -} - -/*! - \internal - - Records painter commands and stores them in the TQDomDocument doc. -*/ - -bool TQSvgDevice::cmd ( int c, TQPainter *painter, TQPDevCmdParam *p ) -{ - pt = painter; - - if ( c == PdcBegin ) { - TQDomImplementation domImpl; - TQDomDocumentType docType = domImpl.createDocumentType( "svg", - publicId, - systemId ); - doc = domImpl.createDocument( "http://www.w3.org/2000/svg", - "svg", docType ); - doc.insertBefore( doc.createProcessingInstruction( "xml", piData ), - doc.firstChild() ); - current = doc.documentElement(); - d->images.clear(); - d->pixmaps.clear(); - dirtyTransform = dirtyStyle = FALSE; // ### - return TRUE; - } else if ( c == PdcEnd ) { - return TRUE; - } - - TQDomElement e; - TQString str; - TQRect rect; - TQPointArray a; - int i, width, height, x, y; - switch ( c ) { - case PdcNOP: - break; - case PdcMoveTo: - curPt = *p[0].point; - break; - case PdcLineTo: - e = doc.createElement( "line" ); - e.setAttribute( "x1", curPt.x() ); - e.setAttribute( "y1", curPt.y() ); - e.setAttribute( "x2", p[0].point->x() ); - e.setAttribute( "y2", p[0].point->y() ); - break; - case PdcDrawPoint: - case PdcDrawLine: - e = doc.createElement( "line" ); - e.setAttribute( "x1", p[0].point->x() ); - e.setAttribute( "y1", p[0].point->y() ); - i = ( c == PdcDrawLine ) ? 1 : 0; - e.setAttribute( "x2", p[i].point->x() ); - e.setAttribute( "y2", p[i].point->y() ); - break; - case PdcDrawRect: - case PdcDrawRoundRect: - e = doc.createElement( "rect" ); - x = p[0].rect->x(); - y = p[0].rect->y(); - width = p[0].rect->width(); - height = p[0].rect->height(); - if ( width < 0 ) { - width = -width; - x -= width - 1; - } - if ( height < 0 ) { - height = -height; - y -= height - 1; - } - e.setAttribute( "x", x ); - e.setAttribute( "y", y ); - e.setAttribute( "width", width ); - e.setAttribute( "height", height ); - if ( c == PdcDrawRoundRect ) { - e.setAttribute( "rx", (p[1].ival*p[0].rect->width())/200 ); - e.setAttribute( "ry", (p[2].ival*p[0].rect->height())/200 ); - } - break; - case PdcDrawEllipse: - rect = *p[0].rect; - if ( rect.width() == rect.height() ) { - e = doc.createElement( "circle" ); - double cx = rect.x() + (rect.width() / 2.0); - double cy = rect.y() + (rect.height() / 2.0); - e.setAttribute( "cx", cx ); - e.setAttribute( "cy", cy ); - e.setAttribute( "r", cx - rect.x() ); - } else { - e = doc.createElement( "ellipse" ); - double cx = rect.x() + (rect.width() / 2.0); - double cy = rect.y() + (rect.height() / 2.0); - e.setAttribute( "cx", cx ); - e.setAttribute( "cy", cy ); - e.setAttribute( "rx", cx - rect.x() ); - e.setAttribute( "ry", cy - rect.y() ); - } - break; - case PdcDrawArc: - case PdcDrawPie: - case PdcDrawChord: { - rect = *p[0].rect; - double a = (double)p[1].ival / 16.0 * deg2rad; - double al = (double)p[2].ival / 16.0 * deg2rad; - double rx = rect.width() / 2.0; - double ry = rect.height() / 2.0; - double x0 = (double)rect.x() + rx; - double y0 = (double)rect.y() + ry; - double x1 = x0 + rx*cos(a); - double y1 = y0 - ry*sin(a); - double x2 = x0 + rx*cos(a+al); - double y2 = y0 - ry*sin(a+al); - int large = TQABS( al ) > ( 180.0 * deg2rad ) ? 1 : 0; - int sweep = al < 0.0 ? 1 : 0; - if ( c == PdcDrawPie ) - str = TQString( "M %1 %2 L %3 %4 " ).arg( x0 ).arg( y0 ) - .arg( x1 ).arg( y1 ); - else - str = TQString( "M %1 %2 " ).arg( x1 ).arg( y1 ); - str += TQString( "A %1 %2 %3 %4 %5 %6 %7" ) - .arg( rx ).arg( ry ).arg( a/deg2rad ). arg( large ).arg( sweep ) - .arg( x2 ).arg( y2 ); - if ( c != PdcDrawArc ) - str += "z"; - e = doc.createElement( "path" ); - e.setAttribute( "d", str ); - } - break; - case PdcDrawLineSegments: - { - a = *p[0].ptarr; - uint end = a.size() / 2; - for (uint i = 0; i < end; i++) { - e = doc.createElement( "line" ); - e.setAttribute( "x1", a[int(2*i)].x() ); - e.setAttribute( "y1", a[int(2*i)].y() ); - e.setAttribute( "x2", a[int(2*i+1)].x() ); - e.setAttribute( "y2", a[int(2*i+1)].y() ); - if ( i < end - 1 ) // The last one will be done at the end - appendChild( e, c ); - } - } - break; - case PdcDrawPolyline: - case PdcDrawPolygon: - { - a = *p[0].ptarr; - e = doc.createElement( ( c == PdcDrawPolyline ) ? - "polyline" : "polygon" ); - for (uint i = 0; i < a.size(); i++) { - TQString tmp; - tmp.sprintf( "%d %d ", a[ (int)i ].x(), a[ (int)i ].y() ); - str += tmp; - } - e.setAttribute( "points", str.stripWhiteSpace() ); - } - break; -#ifndef TQT_NO_BEZIER - case PdcDrawCubicBezier: - a = *p[0].ptarr; - e = doc.createElement( "path" ); - str.sprintf( "M %d %d C %d %d %d %d %d %d", a[0].x(), a[0].y(), - a[1].x(), a[1].y(), a[2].x(), a[2].y(), - a[3].x(), a[3].y() ); - e.setAttribute( "d", str ); - break; -#endif - case PdcDrawText2: - e = doc.createElement( "text" ); - if ( p[0].point->x() ) - e.setAttribute( "x", p[0].point->x() ); - if ( p[0].point->y() ) - e.setAttribute( "y", p[0].point->y() ); - e.appendChild( doc.createTextNode( *p[1].str ) ); - break; - case PdcDrawText2Formatted: { - e = doc.createElement( "text" ); - const TQRect *r = p[0].rect; - int tf = p[1].ival; - int x, y; - // horizontal text alignment - if ( ( tf & TQt::AlignHCenter ) != 0 ) { - x = r->x() + r->width() / 2; - e.setAttribute( "text-anchor", "middle" ); - } else if ( ( tf & TQt::AlignRight ) != 0 ) { - x = r->right(); - e.setAttribute( "text-anchor", "end" ); - } else { - x = r->x(); - } - // vertical text alignment - if ( ( tf & TQt::AlignVCenter ) != 0 ) - y = r->y() + ( r->height() + painter->fontMetrics().ascent() ) / 2; - else if ( ( tf & TQt::AlignBottom ) != 0 ) - y = r->bottom(); - else - y = r->y() + painter->fontMetrics().ascent(); - if ( x ) - e.setAttribute( "x", x ); - if ( y ) - e.setAttribute( "y", y ); - e.appendChild( doc.createTextNode( *p[2].str ) ); - } - break; - case PdcDrawPixmap: - case PdcDrawImage: - e = doc.createElement( "image" ); - e.setAttribute( "x", p[0].rect->x() ); - e.setAttribute( "y", p[0].rect->y() ); - e.setAttribute( "width", p[0].rect->width() ); - e.setAttribute( "height", p[0].rect->height() ); - if ( c == PdcDrawImage ) { - ImgElement ie; - ie.element = e; - ie.image = *p[1].image; - d->images.append( ie ); - } else { - PixElement pe; - pe.element = e; - pe.pixmap = *p[1].pixmap; - d->pixmaps.append( pe ); - } - // saving to disk and setting the xlink:href attribute will be - // done later in save() once we now the svg document name. - break; - case PdcSave: - e = doc.createElement( "g" ); - break; - case PdcRestore: - current = current.parentNode(); - dirtyTransform = !pt->worldMatrix().isIdentity(); - d->justRestored = TRUE; - // ### reset dirty flags - break; - case PdcSetBkColor: - case PdcSetBkMode: - case PdcSetROP: - case PdcSetBrushOrigin: - case PdcSetFont: - case PdcSetPen: - case PdcSetBrush: - dirtyStyle = TRUE; - break; - case PdcSetTabStops: - // ### - break; - case PdcSetTabArray: - // ### - break; - case PdcSetVXform: - case PdcSetWindow: - case PdcSetViewport: - case PdcSetWXform: - case PdcSetWMatrix: - case PdcSaveWMatrix: - case PdcRestoreWMatrix: - dirtyTransform = TRUE; - break; - case PdcSetClip: - // ### - break; - case PdcSetClipRegion: - { - // We skip the clip after restore, since restoring the clip is done automatically by - // the viewer as part of the tree structure. It doesn't hurt to write the region - // out, but it doubles the number of clipregions defined in the final svg. - if (d->justRestored) { - d->justRestored = FALSE; - return TRUE; - } - - TQMemArray rects = p[0].rgn->rects(); - if (rects.count() == 0) - return TRUE; - d->currentClip++; - e = doc.createElement( "clipPath" ); - e.setAttribute( "id", TQString("clip%1").arg(d->currentClip) ); - for (int i=0; i<(int)rects.count(); ++i) { - TQDomElement ce = doc.createElement("rect"); - ce.setAttribute( "x", rects.at(i).x() ); - ce.setAttribute( "y", rects.at(i).y() ); - ce.setAttribute( "width", rects.at(i).width() ); - ce.setAttribute( "height", rects.at(i).height() ); - e.appendChild(ce); - } - break; - } - default: -#if defined(CHECK_RANGE) - tqWarning( "TQSVGDevice::cmd: Invalid command %d", c ); -#endif - break; - } - - appendChild( e, c ); - - return TRUE; -} - -/*! - \internal - - Appends the child and applys any style and transformation. - -*/ - -void TQSvgDevice::appendChild( TQDomElement &e, int c ) -{ - if ( !e.isNull() ) { - current.appendChild( e ); - if ( c == PdcSave ) - current = e; - // ### optimize application of attributes utilizing - if ( c == PdcSetClipRegion ) { - TQDomElement ne; - ne = doc.createElement( "g" ); - ne.setAttribute( "style", TQString("clip-path:url(#clip%1)").arg(d->currentClip) ); - current.appendChild( ne ); - current = ne; - } else { - if ( dirtyStyle ) // only reset when entering - applyStyle( &e, c ); // or leaving a tag - if ( dirtyTransform && e.tagName() != "g" ) { - // same as above but not for tags - applyTransform( &e ); - if ( c == PdcSave ) - dirtyTransform = FALSE; - } - } - } -} - - -/*! - \internal - - Push the current drawing attributes on a stack. - - \sa restoreAttributes() -*/ - -void TQSvgDevice::saveAttributes() -{ - pt->save(); - // copy old state - TQSvgDeviceState st( *curr ); - d->stack.append( st ); - curr = &d->stack.last(); -} - -/*! - \internal - - Pop the current drawing attributes off the stack. - - \sa saveAttributes() -*/ - -void TQSvgDevice::restoreAttributes() -{ - pt->restore(); - Q_ASSERT( d->stack.count() > 1 ); - d->stack.remove( d->stack.fromLast() ); - curr = &d->stack.last(); -} - -/*! - \internal - - Evaluate \a node, drawing on \a p. Allows recursive calls. -*/ - -bool TQSvgDevice::play( const TQDomNode &node ) -{ - saveAttributes(); - - ElementType t = (*qSvgTypeMap)[ node.nodeName() ]; - - if ( t == LineElement && pt->pen().style() == TQt::NoPen ) { - TQPen p = pt->pen(); - p.setStyle( TQt::SolidLine ); - pt->setPen( p ); - } - TQDomNamedNodeMap attr = node.attributes(); - if ( attr.contains( "style" ) ) - setStyle( attr.namedItem( "style" ).nodeValue() ); - // ### might have to exclude more elements from transform - if ( t != SvgElement && attr.contains( "transform" ) ) - setTransform( attr.namedItem( "transform" ).nodeValue() ); - uint i = attr.length(); - if ( i > 0 ) { - TQPen pen = pt->pen(); - TQFont font = pt->font(); - while ( i-- ) { - TQDomNode n = attr.item( i ); - TQString a = n.nodeName(); - TQString val = n.nodeValue().lower().stripWhiteSpace(); - setStyleProperty( a, val, &pen, &font, &curr->textalign ); - } - pt->setPen( pen ); - pt->setFont( font ); - } - - int x1, y1, x2, y2, rx, ry, w, h; - double cx1, cy1, crx, cry; - switch ( t ) { - case CommentElement: - // ignore - break; - case RectElement: - rx = ry = 0; - x1 = lenToInt( attr, "x" ); - y1 = lenToInt( attr, "y" ); - w = lenToInt( attr, "width" ); - h = lenToInt( attr, "height" ); - if ( w == 0 || h == 0 ) // prevent div by zero below - break; - x2 = (int)attr.contains( "rx" ); // tiny abuse of x2 and y2 - y2 = (int)attr.contains( "ry" ); - if ( x2 ) - rx = lenToInt( attr, "rx" ); - if ( y2 ) - ry = lenToInt( attr, "ry" ); - if ( x2 && !y2 ) - ry = rx; - else if ( !x2 && y2 ) - rx = ry; - rx = int(200.0*double(rx)/double(w)); - ry = int(200.0*double(ry)/double(h)); - pt->drawRoundRect( x1, y1, w, h, rx, ry ); - break; - case CircleElement: - cx1 = lenToDouble( attr, "cx" ) + 0.5; - cy1 = lenToDouble( attr, "cy" ) + 0.5; - crx = lenToDouble( attr, "r" ); - pt->drawEllipse( (int)(cx1-crx), (int)(cy1-crx), (int)(2*crx), (int)(2*crx) ); - break; - case EllipseElement: - cx1 = lenToDouble( attr, "cx" ) + 0.5; - cy1 = lenToDouble( attr, "cy" ) + 0.5; - crx = lenToDouble( attr, "rx" ); - cry = lenToDouble( attr, "ry" ); - pt->drawEllipse( (int)(cx1-crx), (int)(cy1-cry), (int)(2*crx), (int)(2*cry) ); - break; - case LineElement: - { - x1 = lenToInt( attr, "x1" ); - x2 = lenToInt( attr, "x2" ); - y1 = lenToInt( attr, "y1" ); - y2 = lenToInt( attr, "y2" ); - TQPen p = pt->pen(); - w = p.width(); - p.setWidth( (unsigned int)(w * (TQABS(pt->worldMatrix().m11()) + TQABS(pt->worldMatrix().m22())) / 2) ); - pt->setPen( p ); - pt->drawLine( x1, y1, x2, y2 ); - p.setWidth( w ); - pt->setPen( p ); - } - break; - case PolylineElement: - case PolygonElement: - { - TQString pts = attr.namedItem( "points" ).nodeValue(); - pts = pts.simplifyWhiteSpace(); - TQStringList sl = TQStringList::split( TQRegExp( TQString::fromLatin1("[ ,]") ), pts ); - TQPointArray ptarr( (uint)sl.count() / 2); - for ( int i = 0; i < (int)sl.count() / 2; i++ ) { - double dx = sl[2*i].toDouble(); - double dy = sl[2*i+1].toDouble(); - ptarr.setPoint( i, int(dx), int(dy) ); - } - if ( t == PolylineElement ) { - if ( pt->brush().style() != TQt::NoBrush ) { - TQPen pn = pt->pen(); - pt->setPen( TQt::NoPen ); - pt->drawPolygon( ptarr ); - pt->setPen( pn ); - } - pt->drawPolyline( ptarr ); // ### closes when filled. bug ? - } else { - pt->drawPolygon( ptarr ); - } - } - break; - case SvgElement: - case GroupElement: - case AnchorElement: - { - TQDomNode child = node.firstChild(); - while ( !child.isNull() ) { - play( child ); - child = child.nextSibling(); - } - } - break; - case PathElement: - drawPath( attr.namedItem( "d" ).nodeValue() ); - break; - case TSpanElement: - case TextElement: - { - if ( attr.contains( "x" ) ) - curr->textx = lenToInt( attr, "x" ); - if ( attr.contains( "y" ) ) - curr->texty = lenToInt( attr, "y" ); - if ( t == TSpanElement ) { - curr->textx += lenToInt( attr, "dx" ); - curr->texty += lenToInt( attr, "dy" ); - } - // backup old colors - TQPen pn = pt->pen(); - TQColor pcolor = pn.color(); - TQColor bcolor = pt->brush().color(); - TQDomNode c = node.firstChild(); - while ( !c.isNull() ) { - if ( c.isText() ) { - // we have pen and brush reversed for text drawing - pn.setColor( bcolor ); - pt->setPen( pn ); - TQString text = c.toText().nodeValue(); - text = text.simplifyWhiteSpace(); // ### 'preserve' - w = pt->fontMetrics().width( text ); - if ( curr->textalign == TQt::AlignHCenter ) - curr->textx -= w / 2; - else if ( curr->textalign == TQt::AlignRight ) - curr->textx -= w; - pt->drawText( curr->textx, curr->texty, text ); - // restore pen - pn.setColor( pcolor ); - pt->setPen( pn ); - curr->textx += w; - } else if ( c.isElement() && - c.toElement().tagName() == "tspan" ) { - play( c ); - - } - c = c.nextSibling(); - } - if ( t == TSpanElement ) { - // move current text position in parent text element - StateList::Iterator it = --d->stack.fromLast(); - (*it).textx = curr->textx; - (*it).texty = curr->texty; - } - } - break; - case ImageElement: - { - x1 = lenToInt( attr, "x" ); - y1 = lenToInt( attr, "y" ); - w = lenToInt( attr, "width" ); - h = lenToInt( attr, "height" ); - TQString href = attr.namedItem( "xlink:href" ).nodeValue(); - // ### catch references to embedded .svg files - TQPixmap pix; - if ( !pix.load( href ) ) { - tqWarning( "TQSvgDevice::play: Couldn't load image %s", href.latin1() ); - break; - } - pt->drawPixmap( TQRect( x1, y1, w, h ), pix ); - } - break; - case DescElement: - case TitleElement: - // ignored for now - break; - case ClipElement: - { - TQDomNode child = node.firstChild(); - TQRegion region; - while (!child.isNull()) { - TQDomNamedNodeMap childAttr = child.attributes(); - if ( child.nodeName() == "rect" ) { - TQRect r; - r.setX(lenToInt( childAttr, "x" )); - r.setY(lenToInt( childAttr, "y" )); - r.setWidth(lenToInt( childAttr, "width" )); - r.setHeight(lenToInt( childAttr, "height" )); - region |= r; - } else if ( child.nodeName() == "ellipse" ) { - TQRect r; - int x = lenToInt( childAttr, "cx" ); - int y = lenToInt( childAttr, "cy" ); - int width = lenToInt( childAttr, "rx" ); - int height = lenToInt( childAttr, "ry" ); - r.setX( x - width ); - r.setY( y - height ); - r.setWidth( width * 2 ); - r.setHeight( height * 2 ); - TQRegion rgn( r, TQRegion::Ellipse ); - region |= rgn; - } - child = child.nextSibling(); - } - // Store the region in a named map so that it can be used when the - // group node is entered. - TQString idString = attr.namedItem("id").nodeValue(); - if (!idString.isEmpty()) - d->clipPathTable[idString] = region; - break; - } - case InvalidElement: - tqWarning( "TQSvgDevice::play: unknown element type %s", - node.nodeName().latin1() ); - break; - }; - - restoreAttributes(); - - return TRUE; -} - -/*! - \internal - - Parses a CSS2-compatible color specification. Either a keyword or - a numerical RGB specification like #ff00ff or rgb(255,0,50%). -*/ - -TQColor TQSvgDevice::parseColor( const TQString &col ) -{ - static const struct ColorTable { - const char *name; - const char *rgb; - } coltab[] = { - { "black", "#000000" }, - { "silver", "#c0c0c0" }, - { "gray", "#808080" }, - { "white", "#ffffff" }, - { "maroon", "#800000" }, - { "red", "#ff0000" }, - { "purple", "#800080" }, - { "fuchsia", "#ff00ff" }, - { "green", "#008000" }, - { "lime", "#00ff00" }, - { "olive", "#808000" }, - { "yellow", "#ffff00" }, - { "navy", "#000080" }, - { "blue", "#0000ff" }, - { "teal", "#008080" }, - { "aqua", "#00ffff" }, - // ### the latest spec has more - { 0, 0 } - }; - - // initialize color map on first use - if ( !qSvgColMap ) { - qSvgColMap = new TQMap; - const struct ColorTable *t = coltab; - while ( t->name ) { - qSvgColMap->insert( t->name, t->rgb ); - t++; - } - } - - // a keyword ? - if ( qSvgColMap->contains ( col ) ) - return TQColor( (*qSvgColMap)[ col ] ); - // in rgb(r,g,b) form ? - TQString c = col; - c.replace( TQRegExp( TQString::fromLatin1("\\s*") ), "" ); - TQRegExp reg( TQString::fromLatin1("^rgb\\((\\d+)(%?),(\\d+)(%?),(\\d+)(%?)\\)$") ); - if ( reg.search( c ) >= 0 ) { - int comp[3]; - for ( int i = 0; i < 3; i++ ) { - comp[ i ] = reg.cap( 2*i+1 ).toInt(); - if ( !reg.cap( 2*i+2 ).isEmpty() ) // percentage ? - comp[ i ] = int((double(255*comp[ i ])/100.0)); - } - return TQColor( comp[ 0 ], comp[ 1 ], comp[ 2 ] ); - } - - // check for predefined TQt color objects, #RRGGBB and #RGB - return TQColor( col ); -} - -/*! - \internal - - Parse a datatype consisting of a number followed by an - optional unit specifier. Can be used for type as - well. For relative units the value of \a horiz will determine - whether the horizontal or vertical dimension will be used. -*/ - -double TQSvgDevice::parseLen( const TQString &str, bool *ok, bool horiz ) const -{ - TQRegExp reg( TQString::fromLatin1("([+-]?\\d*\\.*\\d*[Ee]?[+-]?\\d*)(em|ex|px|%|pt|pc|cm|mm|in|)$") ); - if ( reg.search( str ) == -1 ) { - tqWarning( "TQSvgDevice::parseLen: couldn't parse %s ", str.latin1() ); - if ( ok ) - *ok = FALSE; - return 0.0; - } - - double dbl = reg.cap( 1 ).toDouble(); - TQString u = reg.cap( 2 ); - if ( !u.isEmpty() && u != "px" ) { - TQPaintDeviceMetrics m( pt->device() ); - if ( u == "em" ) { - TQFontInfo fi( pt->font() ); - dbl *= fi.pixelSize(); - } else if ( u == "ex" ) { - TQFontInfo fi( pt->font() ); - dbl *= 0.5 * fi.pixelSize(); - } else if ( u == "%" ) - dbl *= (horiz ? pt->window().width() : pt->window().height())/100.0; - else if ( u == "cm" ) - dbl *= m.logicalDpiX() / 2.54; - else if ( u == "mm" ) - dbl *= m.logicalDpiX() / 25.4; - else if ( u == "in" ) - dbl *= m.logicalDpiX(); - else if ( u == "pt" ) - dbl *= m.logicalDpiX() / 72.0; - else if ( u == "pc" ) - dbl *= m.logicalDpiX() / 6.0; - else - tqWarning( "TQSvgDevice::parseLen: Unknown unit %s", u.latin1() ); - } - if ( ok ) - *ok = TRUE; - return dbl; -} - -/*! - \internal - - Returns the length specified in attribute \a attr in \a map. If - the specified attribute doesn't exist or can't be parsed \a def is - returned. -*/ - -int TQSvgDevice::lenToInt( const TQDomNamedNodeMap &map, const TQString &attr, - int def ) const -{ - if ( map.contains( attr ) ) { - bool ok; - double dbl = parseLen( map.namedItem( attr ).nodeValue(), &ok ); - if ( ok ) - return tqRound( dbl ); - } - return def; -} - -double TQSvgDevice::lenToDouble( const TQDomNamedNodeMap &map, const TQString &attr, - int def ) const -{ - if ( map.contains( attr ) ) { - bool ok; - double d = parseLen( map.namedItem( attr ).nodeValue(), &ok ); - if ( ok ) - return d; - } - return def; -} - -void TQSvgDevice::setStyleProperty( const TQString &prop, const TQString &val, - TQPen *pen, TQFont *font, int *talign ) -{ - if ( prop == "stroke" ) { - if ( val == "none" ) { - pen->setStyle( TQt::NoPen ); - } else { - pen->setColor( parseColor( val )); - if ( pen->style() == TQt::NoPen ) - pen->setStyle( TQt::SolidLine ); - if ( pen->width() == 0 ) - pen->setWidth( 1 ); - } - } else if ( prop == "stroke-width" ) { - double w = parseLen( val ); - if ( w > 0.0001 ) - pen->setWidth( int(w) ); - else - pen->setStyle( TQt::NoPen ); - } else if ( prop == "stroke-linecap" ) { - if ( val == "butt" ) - pen->setCapStyle( TQt::FlatCap ); - else if ( val == "round" ) - pen->setCapStyle( TQt::RoundCap ); - else if ( val == "square" ) - pen->setCapStyle( TQt::SquareCap ); - } else if ( prop == "stroke-linejoin" ) { - if ( val == "miter" ) - pen->setJoinStyle( TQt::MiterJoin ); - else if ( val == "round" ) - pen->setJoinStyle( TQt::RoundJoin ); - else if ( val == "bevel" ) - pen->setJoinStyle( TQt::BevelJoin ); - } else if ( prop == "stroke-dasharray" ) { - if ( val == "18,6" ) - pen->setStyle( TQt::DashLine ); - else if ( val == "3" ) - pen->setStyle( TQt::DotLine ); - else if ( val == "9,6,3,6" ) - pen->setStyle( TQt::DashDotLine ); - else if ( val == "9,3,3" ) - pen->setStyle( TQt::DashDotDotLine ); - else - pen->setStyle( TQt::DotLine ); - } else if ( prop == "fill" ) { - if ( val == "none" ) - pt->setBrush( TQt::NoBrush ); - else - pt->setBrush( parseColor( val ) ); - } else if ( prop == "font-size" ) { - font->setPointSizeFloat( float(parseLen( val )) ); - } else if ( prop == "font-family" ) { - font->setFamily( val ); - } else if ( prop == "font-style" ) { - if ( val == "normal" ) - font->setItalic( FALSE ); - else if ( val == "italic" ) - font->setItalic( TRUE ); - else - tqWarning( "TQSvgDevice::setStyleProperty: unhandled " - "font-style: %s", val.latin1() ); - } else if ( prop == "font-weight" ) { - int w = font->weight(); - // no exact equivalents so we have to "round" a little bit - if ( val == "100" || val == "200" ) - w = TQFont::Light; - if ( val == "300" || val == "400" || val == "normal" ) - w = TQFont::Normal; - else if ( val == "500" || val == "600" ) - w = TQFont::DemiBold; - else if ( val == "700" || val == "bold" || val == "800" ) - w = TQFont::Bold; - else if ( val == "900" ) - w = TQFont::Black; - font->setWeight( w ); - } else if ( prop == "text-anchor" ) { - if ( val == "middle" ) - *talign = TQt::AlignHCenter; - else if ( val == "end" ) - *talign = TQt::AlignRight; - else - *talign = TQt::AlignLeft; - } else if ( prop == "clip-path" ) { - if (val.startsWith("url(#")) { - TQString clipName = val.mid(5, val.length() - 6); - if (!clipName.isEmpty()) { - TQRegion clipRegion = d->clipPathTable[clipName]; - if (!clipRegion.isEmpty()) - pt->setClipRegion(pt->clipRegion() & clipRegion, TQPainter::CoordPainter); - } - } - } -} - -void TQSvgDevice::setStyle( const TQString &s ) -{ - TQStringList rules = TQStringList::split( TQChar(';'), s ); - - TQPen pen = pt->pen(); - TQFont font = pt->font(); - - TQStringList::ConstIterator it = rules.begin(); - for ( ; it != rules.end(); it++ ) { - int col = (*it).find( ':' ); - if ( col > 0 ) { - TQString prop = (*it).left( col ).simplifyWhiteSpace(); - TQString val = (*it).right( (*it).length() - col - 1 ); - val = val.lower().stripWhiteSpace(); - setStyleProperty( prop, val, &pen, &font, &curr->textalign ); - } - } - - pt->setPen( pen ); - pt->setFont( font ); -} - -void TQSvgDevice::setTransform( const TQString &tr ) -{ - TQString t = tr.simplifyWhiteSpace(); - - TQRegExp reg( TQString::fromLatin1("\\s*([\\w]+)\\s*\\(([^\\(]*)\\)") ); - int index = 0; - while ( (index = reg.search(t, index)) >= 0 ) { - TQString command = reg.cap( 1 ); - TQString params = reg.cap( 2 ); - TQStringList plist = TQStringList::split( TQRegExp(TQString::fromLatin1("[,\\s]")), params ); - if ( command == "translate" ) { - double tx = 0, ty = 0; - tx = plist[0].toDouble(); - if ( plist.count() >= 2 ) - ty = plist[1].toDouble(); - pt->translate( tx, ty ); - } else if ( command == "rotate" ) { - pt->rotate( plist[0].toDouble() ); - } else if ( command == "scale" ) { - double sx, sy; - sx = sy = plist[0].toDouble(); - if ( plist.count() >= 2 ) - sy = plist[1].toDouble(); - pt->scale( sx, sy ); - } else if ( command == "matrix" && plist.count() >= 6 ) { - double m[ 6 ]; - for (int i = 0; i < 6; i++) - m[ i ] = plist[ i ].toDouble(); - TQWMatrix wm( m[ 0 ], m[ 1 ], m[ 2 ], - m[ 3 ], m[ 4 ], m[ 5 ] ); - pt->setWorldMatrix( wm, TRUE ); - } else if ( command == "skewX" ) { - pt->shear( 0.0, tan( plist[0].toDouble() * deg2rad ) ); - } else if ( command == "skewY" ) { - pt->shear( tan( plist[0].toDouble() * deg2rad ), 0.0 ); - } - - // move on to next command - index += reg.matchedLength(); - } -} - -void TQSvgDevice::drawPath( const TQString &data ) -{ - double x0 = 0, y0 = 0; // starting point - double x = 0, y = 0; // current point - double controlX = 0, controlY = 0; // last control point for curves - TQPointArray path( 500 ); // resulting path - TQValueList subIndex; // start indices for subpaths - TQPointArray quad( 4 ), bezier; // for curve calculations - int pcount = 0; // current point array index - uint idx = 0; // current data position - int mode = 0, lastMode = 0; // parser state - bool relative = FALSE; // e.g. 'h' vs. 'H' - TQString commands( "MZLHVCSTQTA" ); // recognized commands - int cmdArgs[] = { 2, 0, 2, 1, 1, 6, 4, 4, 2, 7 }; // no of arguments - TQRegExp reg( TQString::fromLatin1("\\s*,?\\s*([+-]?\\d*\\.?\\d*)") ); // floating point - - subIndex.append( 0 ); - // detect next command - while ( idx < data.length() ) { - TQChar ch = data[ (int)idx++ ]; - if ( ch.isSpace() ) - continue; - TQChar chUp = ch.upper(); - int cmd = commands.find( chUp ); - if ( cmd >= 0 ) { - // switch to new command mode - mode = cmd; - relative = ( ch != chUp ); // e.g. 'm' instead of 'M' - } else { - if ( mode && !ch.isLetter() ) { - cmd = mode; // continue in previous mode - idx--; - } else { - tqWarning( "TQSvgDevice::drawPath: Unknown command" ); - return; - } - } - - // read in the required number of arguments - const int maxArgs = 7; - double arg[ maxArgs ]; - int numArgs = cmdArgs[ cmd ]; - for ( int i = 0; i < numArgs; i++ ) { - int pos = reg.search( data, idx ); - if ( pos == -1 ) { - tqWarning( "TQSvgDevice::drawPath: Error parsing arguments" ); - return; - } - arg[ i ] = reg.cap( 1 ).toDouble(); - idx = pos + reg.matchedLength(); - }; - - // process command - double offsetX = relative ? x : 0; // correction offsets - double offsetY = relative ? y : 0; // for relative commands - switch ( mode ) { - case 0: // 'M' move to - if ( x != x0 || y != y0 ) - path.setPoint( pcount++, int(x0), int(y0) ); - x = x0 = arg[ 0 ] + offsetX; - y = y0 = arg[ 1 ] + offsetY; - subIndex.append( pcount ); - path.setPoint( pcount++, int(x0), int(y0) ); - mode = 2; // -> 'L' - break; - case 1: // 'Z' close path - path.setPoint( pcount++, int(x0), int(y0) ); - x = x0; - y = y0; - mode = 0; - break; - case 2: // 'L' line to - x = arg[ 0 ] + offsetX; - y = arg[ 1 ] + offsetY; - path.setPoint( pcount++, int(x), int(y) ); - break; - case 3: // 'H' horizontal line - x = arg[ 0 ] + offsetX; - path.setPoint( pcount++, int(x), int(y) ); - break; - case 4: // 'V' vertical line - y = arg[ 0 ] + offsetY; - path.setPoint( pcount++, int(x), int(y) ); - break; -#ifndef TQT_NO_BEZIER - case 5: // 'C' cubic bezier curveto - case 6: // 'S' smooth shorthand - case 7: // 'Q' quadratic bezier curves - case 8: { // 'T' smooth shorthand - quad.setPoint( 0, int(x), int(y) ); - // if possible, reflect last control point if smooth shorthand - if ( mode == 6 || mode == 8 ) { // smooth 'S' and 'T' - bool cont = mode == lastMode || - ( mode == 6 && lastMode == 5 ) || // 'S' and 'C' - ( mode == 8 && lastMode == 7 ); // 'T' and 'Q' - x = cont ? 2*x-controlX : x; - y = cont ? 2*y-controlY : y; - quad.setPoint( 1, int(x), int(y) ); - quad.setPoint( 2, int(x), int(y) ); - } - for ( int j = 0; j < numArgs/2; j++ ) { - x = arg[ 2*j ] + offsetX; - y = arg[ 2*j+1 ] + offsetY; - quad.setPoint( j+4-numArgs/2, int(x), int(y) ); - } - // remember last control point for next shorthand - controlX = quad[ 2 ].x(); - controlY = quad[ 2 ].y(); - // transform quadratic into cubic Bezier - if ( mode == 7 || mode == 8 ) { // cubic 'Q' and 'T' - int x31 = quad[0].x()+int(2.0*(quad[2].x()-quad[0].x())/3.0); - int y31 = quad[0].y()+int(2.0*(quad[2].y()-quad[0].y())/3.0); - int x32 = quad[2].x()+int(2.0*(quad[3].x()-quad[2].x())/3.0); - int y32 = quad[2].y()+int(2.0*(quad[3].y()-quad[2].y())/3.0); - quad.setPoint( 1, x31, y31 ); - quad.setPoint( 2, x32, y32 ); - } - // calculate points on curve - bezier = quad.cubicBezier(); - // reserve more space if needed - if ( bezier.size() > path.size() - pcount ) - path.resize( path.size() - pcount + bezier.size() ); - // copy - for ( int k = 0; k < (int)bezier.size(); k ++ ) - path.setPoint( pcount++, bezier[ k ] ); - break; - } -#endif // TQT_NO_BEZIER - case 9: // 'A' elliptical arc curve - // ### just a straight line - x = arg[ 5 ] + offsetX; - y = arg[ 6 ] + offsetY; - path.setPoint( pcount++, int(x), int(y) ); - break; - }; - lastMode = mode; - // array almost full ? expand for next loop - if ( pcount >= (int)path.size() - 4 ) - path.resize( 2 * path.size() ); - } - - subIndex.append( pcount ); // dummy marking the end - if ( pt->brush().style() != TQt::NoBrush ) { - // fill the area without stroke first - if ( x != x0 || y != y0 ) - path.setPoint( pcount++, int(x0), int(y0) ); - TQPen pen = pt->pen(); - pt->setPen( TQt::NoPen ); - pt->drawPolygon( path, FALSE, 0, pcount ); - pt->setPen( pen ); - } - // draw each subpath stroke seperately - TQValueListConstIterator it = subIndex.begin(); - int start = 0; - while ( it != subIndex.fromLast() ) { - int next = *++it; - // ### always joins ends if first and last point coincide. - // ### 'Z' can't have the desired effect - pt->drawPolyline( path, start, next-start ); - start = next; - } -} - -void TQSvgDevice::applyStyle( TQDomElement *e, int c ) const -{ - // ### do not write every attribute each time - TQColor pcol = pt->pen().color(); - TQColor bcol = pt->brush().color(); - TQString s; - if ( c == PdcDrawText2 || c == PdcDrawText2Formatted ) { - // TQPainter has a reversed understanding of pen/stroke vs. - // brush/fill for text - s += TQString( "fill:rgb(%1,%2,%3);" ) - .arg( pcol.red() ).arg( pcol.green() ).arg( pcol.blue() ); - s += TQString( "stroke-width:0;" ); - TQFont f = pt->font(); - TQFontInfo fi( f ); - s += TQString( "font-size:%1;" ).arg( fi.pointSize() ); - s += TQString( "font-style:%1;" ) - .arg( f.italic() ? "italic" : "normal" ); - // not a very scientific distribution - TQString fw; - if ( f.weight() <= TQFont::Light ) - fw = "100"; - else if ( f.weight() <= TQFont::Normal ) - fw = "400"; - else if ( f.weight() <= TQFont::DemiBold ) - fw = "600"; - else if ( f.weight() <= TQFont::Bold ) - fw = "700"; - else if ( f.weight() <= TQFont::Black ) - fw = "800"; - else - fw = "900"; - s += TQString( "font-weight:%1;" ).arg( fw ); - s += TQString( "font-family:%1;" ).arg( f.family() ); - } else { - s += TQString( "stroke:rgb(%1,%2,%3);" ) - .arg( pcol.red() ).arg( pcol.green() ).arg( pcol.blue() ); - double pw = pt->pen().width(); - if ( pw == 0 && pt->pen().style() != TQt::NoPen ) - pw = 0.9; - if ( c == PdcDrawLine ) - pw /= (TQABS(pt->worldMatrix().m11()) + TQABS(pt->worldMatrix().m22())) / 2.0; - s += TQString( "stroke-width:%1;" ).arg( pw ); - if ( pt->pen().style() == TQt::DashLine ) - s+= TQString( "stroke-dasharray:18,6;" ); - else if ( pt->pen().style() == TQt::DotLine ) - s+= TQString( "stroke-dasharray:3;" ); - else if ( pt->pen().style() == TQt::DashDotLine ) - s+= TQString( "stroke-dasharray:9,6,3,6;" ); - else if ( pt->pen().style() == TQt::DashDotDotLine ) - s+= TQString( "stroke-dasharray:9,3,3;" ); - if ( pt->brush().style() == TQt::NoBrush || c == PdcDrawPolyline || - c == PdcDrawCubicBezier ) - s += "fill:none;"; // TQt polylines use no brush, neither do Beziers - else - s += TQString( "fill:rgb(%1,%2,%3);" ) - .arg( bcol.red() ).arg( bcol.green() ).arg( bcol.blue() ); - } - e->setAttribute( "style", s ); -} - -void TQSvgDevice::applyTransform( TQDomElement *e ) const -{ - TQWMatrix m = pt->worldMatrix(); - - TQString s; - bool rot = ( m.m11() != 1.0 || m.m12() != 0.0 || - m.m21() != 0.0 || m.m22() != 1.0 ); - if ( !rot && ( m.dx() != 0.0 || m.dy() != 0.0 ) ) - s = TQString( "translate(%1,%2)" ).arg( m.dx() ).arg( m.dy() ); - else if ( rot ) { - if ( m.m12() == 0.0 && m.m21() == 0.0 && - m.dx() == 0.0 && m.dy() == 0.0 ) - s = TQString( "scale(%1,%2)" ).arg( m.m11() ).arg( m.m22() ); - else - s = TQString( "matrix(%1,%2,%3,%4,%5,%6)" ) - .arg( m.m11() ).arg( m.m12() ) - .arg( m.m21() ).arg( m.m22() ) - .arg( m.dx() ).arg( m.dy() ); - } - else - return; - - e->setAttribute( "transform", s ); -} - -#endif // TQT_NO_SVG diff --git a/src/xml/qsvgdevice_p.h b/src/xml/qsvgdevice_p.h deleted file mode 100644 index ffdec75fd..000000000 --- a/src/xml/qsvgdevice_p.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Definition of the TQSvgDevice class -** -** Created : 001024 -** -** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the xml module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -*****************************************************************************/ - -#ifndef TQSVGDEVICE_P_H -#define TQSVGDEVICE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of the TQPicture class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// -// - -#ifndef QT_H -#include "tqpaintdevice.h" -#include "tqrect.h" -#include "tqdom.h" -#endif // QT_H - -#if !defined(TQT_MODULE_XML) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_XML ) -#define TQM_EXPORT_SVG -#else -#define TQM_EXPORT_SVG TQ_EXPORT -#endif - -#ifndef TQT_NO_SVG - -class TQPainter; -class TQDomNode; -class TQDomNamedNodeMap; -struct TQSvgDeviceState; -class TQSvgDevicePrivate; - -class TQM_EXPORT_SVG TQSvgDevice : public TQPaintDevice -{ -public: - TQSvgDevice(); - ~TQSvgDevice(); - - bool play( TQPainter *p ); - - TQString toString() const; - - bool load( TQIODevice *dev ); - bool save( TQIODevice *dev ); - bool save( const TQString &fileName ); - - TQRect boundingRect() const; - void setBoundingRect( const TQRect &r ); - -protected: - virtual bool cmd ( int, TQPainter*, TQPDevCmdParam* ); - virtual int metric( int ) const; - -private: - // reading - bool play( const TQDomNode &node ); - void saveAttributes(); - void restoreAttributes(); - TQColor parseColor( const TQString &col ); - double parseLen( const TQString &str, bool *ok=0, bool horiz=TRUE ) const; - int lenToInt( const TQDomNamedNodeMap &map, const TQString &attr, - int def=0 ) const; - double lenToDouble( const TQDomNamedNodeMap &map, const TQString &attr, - int def=0 ) const; - void setStyleProperty( const TQString &prop, const TQString &val, - TQPen *pen, TQFont *font, int *talign ); - void setStyle( const TQString &s ); - void setTransform( const TQString &tr ); - void drawPath( const TQString &data ); - - // writing - void appendChild( TQDomElement &e, int c ); - void applyStyle( TQDomElement *e, int c ) const; - void applyTransform( TQDomElement *e ) const; - - // reading - TQRect brect; // bounding rectangle - TQDomDocument doc; // document tree - TQDomNode current; - TQPoint curPt; - TQSvgDeviceState *curr; - TQPainter *pt; // used by play() et al - - // writing - bool dirtyTransform, dirtyStyle; - - TQSvgDevicePrivate *d; -}; - -inline TQRect TQSvgDevice::boundingRect() const -{ - return brect; -} - -#endif // TQT_NO_SVG - -#endif // TQSVGDEVICE_P_H diff --git a/src/xml/qt_xml.pri b/src/xml/qt_xml.pri index 82fb0c4e0..9adf04487 100644 --- a/src/xml/qt_xml.pri +++ b/src/xml/qt_xml.pri @@ -1,8 +1,8 @@ # TQt xml module xml { - HEADERS += $$XML_H/tqxml.h $$XML_H/tqdom.h $$XML_CPP/qsvgdevice_p.h - SOURCES += $$XML_CPP/tqxml.cpp $$XML_CPP/tqdom.cpp $$XML_CPP/qsvgdevice.cpp + HEADERS += $$XML_H/tqxml.h $$XML_H/tqdom.h $$XML_CPP/tqsvgdevice_p.h + SOURCES += $$XML_CPP/tqxml.cpp $$XML_CPP/tqdom.cpp $$XML_CPP/tqsvgdevice.cpp win32-borland { QMAKE_CFLAGS_WARN_ON += -w-use QMAKE_CXXFLAGS_WARN_ON += -w-use diff --git a/src/xml/tqsvgdevice.cpp b/src/xml/tqsvgdevice.cpp new file mode 100644 index 000000000..1b92d8d6e --- /dev/null +++ b/src/xml/tqsvgdevice.cpp @@ -0,0 +1,1591 @@ +/**************************************************************************** +** +** Implementation of the TQSvgDevice class +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the xml module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +*****************************************************************************/ + +#include + +#ifndef TQT_NO_SVG + +#include "tqpainter.h" +#include "tqpaintdevicemetrics.h" +#include "tqfile.h" +#include "tqmap.h" +#include "tqregexp.h" +#include "tqvaluelist.h" +#include "tqtextstream.h" +#include "tqimage.h" +#include "tqpixmap.h" + +#include + +const double deg2rad = 0.017453292519943295769; // pi/180 +const char piData[] = "version=\"1.0\" standalone=\"no\""; +const char publicId[] = "-//W3C//DTD SVG 20001102//EN"; +const char systemId[] = "http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd"; + +struct TQM_EXPORT_SVG ImgElement { + TQDomElement element; + TQImage image; + TQ_DUMMY_COMPARISON_OPERATOR( ImgElement ) +}; + +struct TQM_EXPORT_SVG PixElement { + TQDomElement element; + TQPixmap pixmap; + TQ_DUMMY_COMPARISON_OPERATOR( PixElement ) +}; + +struct TQSvgDeviceState { + int textx, texty; // current text position + int textalign; // text alignment + TQ_DUMMY_COMPARISON_OPERATOR( TQSvgDeviceState ) +}; + +typedef TQValueList ImageList; +typedef TQValueList PixmapList; +typedef TQValueList StateList; + +class TQSvgDevicePrivate { +public: + ImageList images; + PixmapList pixmaps; + StateList stack; + int currentClip; + + uint justRestored : 1; + + TQMap clipPathTable; +}; + +enum ElementType { + InvalidElement = 0, + AnchorElement, + CircleElement, + ClipElement, + CommentElement, + DescElement, + EllipseElement, + GroupElement, + ImageElement, + LineElement, + PolylineElement, + PolygonElement, + PathElement, + RectElement, + SvgElement, + TextElement, + TitleElement, + TSpanElement +}; + +typedef TQMap TQSvgTypeMap; +static TQSvgTypeMap *qSvgTypeMap=0; // element types +static TQMap *qSvgColMap=0; // recognized color keyword names + +/*! + \class TQSvgDevice tqsvgdevice.h + \brief The TQSvgDevice class provides a paint device for SVG vector graphics. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \ingroup xml-tools + \module XML + \internal + + SVG is an XML vector graphics format. This class supports the + loading and saving of SVG files with load() and save(), and the + rendering of an SVG onto a TQPainter using play(). Use toString() + to put the SVG into a string. + + \sa TQPaintDevice TQPainter +*/ + +/*! + Creates a TQSvgDevice object. +*/ + +TQSvgDevice::TQSvgDevice() + : TQPaintDevice( TQInternal::ExternalDevice ), + pt( 0 ) +{ + d = new TQSvgDevicePrivate; + d->currentClip = 0; + d->justRestored = FALSE; +} + +/*! + Destroys the TQSvgDevice object and frees the resources it used. +*/ + +TQSvgDevice::~TQSvgDevice() +{ + delete qSvgTypeMap; qSvgTypeMap = 0; // static + delete qSvgColMap; qSvgColMap = 0; + delete d; +} + +/*! + Loads and parses a SVG from \a dev into the device. Returns TRUE + on success (i.e. loaded and parsed without error); otherwise + returns FALSE. +*/ + +bool TQSvgDevice::load( TQIODevice *dev ) +{ + return doc.setContent( dev ); +} + +/*! + Renders (replays) the SVG on the \a painter and returns TRUE if + successful (i.e. it is a valid SVG); otherwise returns FALSE. +*/ + +bool TQSvgDevice::play( TQPainter *painter ) +{ + if ( !painter ) { +#if defined(QT_CHECK_RANGE) + Q_ASSERT( painter ); +#endif + return FALSE; + } + pt = painter; + pt->setPen( TQt::NoPen ); // SVG default pen and brush + pt->setBrush( TQt::black ); + if ( doc.isNull() ) { + tqWarning( "TQSvgDevice::play: No SVG data set." ); + return FALSE; + } + + TQDomNode svg = doc.namedItem( "svg" ); + if ( svg.isNull() || !svg.isElement() ) { + tqWarning( "TQSvgDevice::play: Couldn't find any svg element." ); + return FALSE; + } + + // force transform to be activated in case our sequences + // are replayed later with a transformed painter + painter->setWorldXForm( TRUE ); + + TQDomNamedNodeMap attr = svg.attributes(); + int x = lenToInt( attr, "x" ); + int y = lenToInt( attr, "y" ); + brect.setX( x ); + brect.setY( y ); + TQString wstr = attr.contains( "width" ) + ? attr.namedItem( "width" ).nodeValue() : TQString( "100%" ); + TQString hstr = attr.contains( "height" ) + ? attr.namedItem( "height" ).nodeValue() : TQString( "100%" ); + double width = parseLen( wstr, 0, TRUE ); + double height = parseLen( hstr, 0, FALSE ); + // SVG doesn't respect x and y. But we want a proper bounding rect. + brect.setWidth( int(width) - x ); + brect.setHeight( int(height) - y ); + painter->setClipRect( brect, TQPainter::CoordPainter ); + + if ( attr.contains( "viewBox" ) ) { + TQRegExp re( TQString::fromLatin1("\\s*(\\S+)\\s*,?\\s*(\\S+)\\s*,?" + "\\s*(\\S+)\\s*,?\\s*(\\S+)\\s*") ); + if ( re.search( attr.namedItem( "viewBox" ).nodeValue() ) < 0 ) { + tqWarning( "TQSvgDevice::play: Invalid viewBox attribute."); + return FALSE; + } else { + double x = re.cap( 1 ).toDouble(); + double y = re.cap( 2 ).toDouble(); + double w = re.cap( 3 ).toDouble(); + double h = re.cap( 4 ).toDouble(); + if ( w < 0 || h < 0 ) { + tqWarning( "TQSvgDevice::play: Invalid viewBox dimension."); + return FALSE; + } else if ( w == 0 || h == 0 ) { + return TRUE; + } + painter->scale( width/w, height/h ); + painter->translate( -x, -y ); + } + } + + const struct ElementTable { + const char *name; + ElementType type; + } etab[] = { + { "a", AnchorElement }, + { "#comment", CommentElement }, + { "circle", CircleElement }, + { "clipPath", ClipElement }, + { "desc", DescElement }, + { "ellipse", EllipseElement }, + { "g", GroupElement }, + { "image", ImageElement }, + { "line", LineElement }, + { "polyline", PolylineElement }, + { "polygon", PolygonElement }, + { "path", PathElement }, + { "rect", RectElement }, + { "svg", SvgElement }, + { "text", TextElement }, + { "tspan", TSpanElement }, + { "title", TitleElement }, + { 0, InvalidElement } + }; + // initialize only once + if ( !qSvgTypeMap ) { + qSvgTypeMap = new TQSvgTypeMap; + const ElementTable *t = etab; + while ( t->name ) { + qSvgTypeMap->insert( t->name, t->type ); + t++; + } + } + + // initial state + TQSvgDeviceState st; + st.textx = st.texty = 0; + st.textalign = TQt::AlignLeft; + d->stack.append(st); + curr = &d->stack.last(); + // 'play' all elements recursively starting with 'svg' as root + bool b = play( svg ); + d->stack.remove( d->stack.begin() ); + return b; +} + +/*! + Returns the SVG as a single string of XML. +*/ +TQString TQSvgDevice::toString() const +{ + if ( doc.isNull() ) + return TQString(); + + return doc.toString(); +} + +/*! + Saves the SVG to \a fileName. +*/ + +bool TQSvgDevice::save( const TQString &fileName ) +{ + // guess svg id from fileName + TQString svgName = fileName.endsWith( ".svg" ) ? + fileName.left( fileName.length()-4 ) : fileName; + + // now we have the info about name and dimensions available + TQDomElement root = doc.documentElement(); + root.setAttribute( "id", svgName ); + // the standard doesn't take respect x and y. But we want a + // proper bounding rect. We make width and height bigger when + // writing out and subtract x and y when reading in. + root.setAttribute( "x", brect.x() ); + root.setAttribute( "y", brect.y() ); + root.setAttribute( "width", brect.width() + brect.x() ); + root.setAttribute( "height", brect.height() + brect.y() ); + + // ... and know how to name any image files to be written out + int icount = 0; + ImageList::Iterator iit = d->images.begin(); + for ( ; iit != d->images.end(); ++iit ) { + TQString href = TQString( "%1_%2.png" ).arg( svgName ).arg( icount ); + (*iit).image.save( href, "PNG" ); + (*iit).element.setAttribute( "xlink:href", href ); + icount++; + } + PixmapList::Iterator pit = d->pixmaps.begin(); + for ( ; pit != d->pixmaps.end(); ++pit ) { + TQString href = TQString( "%1_%2.png" ).arg( svgName ).arg( icount ); + (*pit).pixmap.save( href, "PNG" ); + (*pit).element.setAttribute( "xlink:href", href ); + icount++; + } + + TQFile f( fileName ); + if ( !f.open ( IO_WriteOnly ) ) + return FALSE; + TQTextStream s( &f ); + s.setEncoding( TQTextStream::UnicodeUTF8 ); + s << doc; + + return TRUE; +} + +/*! + \overload + + \a dev is the device to use for saving. +*/ + +bool TQSvgDevice::save( TQIODevice *dev ) +{ +#if defined(CHECK_RANGE) + if ( !d->images.isEmpty() || !d->pixmaps.isEmpty() ) + tqWarning( "TQSvgDevice::save: skipping external images" ); +#endif + + TQTextStream s( dev ); + s.setEncoding( TQTextStream::UnicodeUTF8 ); + s << doc; + + return TRUE; +} + +/*! + \fn TQRect TQSvgDevice::boundingRect() const + + Returns the bounding rectangle of the SVG. +*/ + +/*! + Sets the bounding rectangle of the SVG to rectangle \a r. +*/ + +void TQSvgDevice::setBoundingRect( const TQRect &r ) +{ + brect = r; +} + +/*! + Internal implementation of the virtual TQPaintDevice::metric() + function. + + \warning Use the TQPaintDeviceMetrics class instead. + + A TQSvgDevice has the following hard coded values: dpi=72, + numcolors=16777216 and depth=24. \a m is the metric to get. +*/ + +int TQSvgDevice::metric( int m ) const +{ + int val; + switch ( m ) { + case TQPaintDeviceMetrics::PdmWidth: + val = brect.width(); + break; + case TQPaintDeviceMetrics::PdmHeight: + val = brect.height(); + break; + case TQPaintDeviceMetrics::PdmWidthMM: + val = int(25.4/72.0*brect.width()); + break; + case TQPaintDeviceMetrics::PdmHeightMM: + val = int(25.4/72.0*brect.height()); + break; + case TQPaintDeviceMetrics::PdmDpiX: + val = 72; + break; + case TQPaintDeviceMetrics::PdmDpiY: + val = 72; + break; + case TQPaintDeviceMetrics::PdmNumColors: + val = 16777216; + break; + case TQPaintDeviceMetrics::PdmDepth: + val = 24; + break; + default: + val = 0; +#if defined(QT_CHECK_RANGE) + tqWarning( "TQSvgDevice::metric: Invalid metric command" ); +#endif + } + return val; +} + +/*! + \internal + + Records painter commands and stores them in the TQDomDocument doc. +*/ + +bool TQSvgDevice::cmd ( int c, TQPainter *painter, TQPDevCmdParam *p ) +{ + pt = painter; + + if ( c == PdcBegin ) { + TQDomImplementation domImpl; + TQDomDocumentType docType = domImpl.createDocumentType( "svg", + publicId, + systemId ); + doc = domImpl.createDocument( "http://www.w3.org/2000/svg", + "svg", docType ); + doc.insertBefore( doc.createProcessingInstruction( "xml", piData ), + doc.firstChild() ); + current = doc.documentElement(); + d->images.clear(); + d->pixmaps.clear(); + dirtyTransform = dirtyStyle = FALSE; // ### + return TRUE; + } else if ( c == PdcEnd ) { + return TRUE; + } + + TQDomElement e; + TQString str; + TQRect rect; + TQPointArray a; + int i, width, height, x, y; + switch ( c ) { + case PdcNOP: + break; + case PdcMoveTo: + curPt = *p[0].point; + break; + case PdcLineTo: + e = doc.createElement( "line" ); + e.setAttribute( "x1", curPt.x() ); + e.setAttribute( "y1", curPt.y() ); + e.setAttribute( "x2", p[0].point->x() ); + e.setAttribute( "y2", p[0].point->y() ); + break; + case PdcDrawPoint: + case PdcDrawLine: + e = doc.createElement( "line" ); + e.setAttribute( "x1", p[0].point->x() ); + e.setAttribute( "y1", p[0].point->y() ); + i = ( c == PdcDrawLine ) ? 1 : 0; + e.setAttribute( "x2", p[i].point->x() ); + e.setAttribute( "y2", p[i].point->y() ); + break; + case PdcDrawRect: + case PdcDrawRoundRect: + e = doc.createElement( "rect" ); + x = p[0].rect->x(); + y = p[0].rect->y(); + width = p[0].rect->width(); + height = p[0].rect->height(); + if ( width < 0 ) { + width = -width; + x -= width - 1; + } + if ( height < 0 ) { + height = -height; + y -= height - 1; + } + e.setAttribute( "x", x ); + e.setAttribute( "y", y ); + e.setAttribute( "width", width ); + e.setAttribute( "height", height ); + if ( c == PdcDrawRoundRect ) { + e.setAttribute( "rx", (p[1].ival*p[0].rect->width())/200 ); + e.setAttribute( "ry", (p[2].ival*p[0].rect->height())/200 ); + } + break; + case PdcDrawEllipse: + rect = *p[0].rect; + if ( rect.width() == rect.height() ) { + e = doc.createElement( "circle" ); + double cx = rect.x() + (rect.width() / 2.0); + double cy = rect.y() + (rect.height() / 2.0); + e.setAttribute( "cx", cx ); + e.setAttribute( "cy", cy ); + e.setAttribute( "r", cx - rect.x() ); + } else { + e = doc.createElement( "ellipse" ); + double cx = rect.x() + (rect.width() / 2.0); + double cy = rect.y() + (rect.height() / 2.0); + e.setAttribute( "cx", cx ); + e.setAttribute( "cy", cy ); + e.setAttribute( "rx", cx - rect.x() ); + e.setAttribute( "ry", cy - rect.y() ); + } + break; + case PdcDrawArc: + case PdcDrawPie: + case PdcDrawChord: { + rect = *p[0].rect; + double a = (double)p[1].ival / 16.0 * deg2rad; + double al = (double)p[2].ival / 16.0 * deg2rad; + double rx = rect.width() / 2.0; + double ry = rect.height() / 2.0; + double x0 = (double)rect.x() + rx; + double y0 = (double)rect.y() + ry; + double x1 = x0 + rx*cos(a); + double y1 = y0 - ry*sin(a); + double x2 = x0 + rx*cos(a+al); + double y2 = y0 - ry*sin(a+al); + int large = TQABS( al ) > ( 180.0 * deg2rad ) ? 1 : 0; + int sweep = al < 0.0 ? 1 : 0; + if ( c == PdcDrawPie ) + str = TQString( "M %1 %2 L %3 %4 " ).arg( x0 ).arg( y0 ) + .arg( x1 ).arg( y1 ); + else + str = TQString( "M %1 %2 " ).arg( x1 ).arg( y1 ); + str += TQString( "A %1 %2 %3 %4 %5 %6 %7" ) + .arg( rx ).arg( ry ).arg( a/deg2rad ). arg( large ).arg( sweep ) + .arg( x2 ).arg( y2 ); + if ( c != PdcDrawArc ) + str += "z"; + e = doc.createElement( "path" ); + e.setAttribute( "d", str ); + } + break; + case PdcDrawLineSegments: + { + a = *p[0].ptarr; + uint end = a.size() / 2; + for (uint i = 0; i < end; i++) { + e = doc.createElement( "line" ); + e.setAttribute( "x1", a[int(2*i)].x() ); + e.setAttribute( "y1", a[int(2*i)].y() ); + e.setAttribute( "x2", a[int(2*i+1)].x() ); + e.setAttribute( "y2", a[int(2*i+1)].y() ); + if ( i < end - 1 ) // The last one will be done at the end + appendChild( e, c ); + } + } + break; + case PdcDrawPolyline: + case PdcDrawPolygon: + { + a = *p[0].ptarr; + e = doc.createElement( ( c == PdcDrawPolyline ) ? + "polyline" : "polygon" ); + for (uint i = 0; i < a.size(); i++) { + TQString tmp; + tmp.sprintf( "%d %d ", a[ (int)i ].x(), a[ (int)i ].y() ); + str += tmp; + } + e.setAttribute( "points", str.stripWhiteSpace() ); + } + break; +#ifndef TQT_NO_BEZIER + case PdcDrawCubicBezier: + a = *p[0].ptarr; + e = doc.createElement( "path" ); + str.sprintf( "M %d %d C %d %d %d %d %d %d", a[0].x(), a[0].y(), + a[1].x(), a[1].y(), a[2].x(), a[2].y(), + a[3].x(), a[3].y() ); + e.setAttribute( "d", str ); + break; +#endif + case PdcDrawText2: + e = doc.createElement( "text" ); + if ( p[0].point->x() ) + e.setAttribute( "x", p[0].point->x() ); + if ( p[0].point->y() ) + e.setAttribute( "y", p[0].point->y() ); + e.appendChild( doc.createTextNode( *p[1].str ) ); + break; + case PdcDrawText2Formatted: { + e = doc.createElement( "text" ); + const TQRect *r = p[0].rect; + int tf = p[1].ival; + int x, y; + // horizontal text alignment + if ( ( tf & TQt::AlignHCenter ) != 0 ) { + x = r->x() + r->width() / 2; + e.setAttribute( "text-anchor", "middle" ); + } else if ( ( tf & TQt::AlignRight ) != 0 ) { + x = r->right(); + e.setAttribute( "text-anchor", "end" ); + } else { + x = r->x(); + } + // vertical text alignment + if ( ( tf & TQt::AlignVCenter ) != 0 ) + y = r->y() + ( r->height() + painter->fontMetrics().ascent() ) / 2; + else if ( ( tf & TQt::AlignBottom ) != 0 ) + y = r->bottom(); + else + y = r->y() + painter->fontMetrics().ascent(); + if ( x ) + e.setAttribute( "x", x ); + if ( y ) + e.setAttribute( "y", y ); + e.appendChild( doc.createTextNode( *p[2].str ) ); + } + break; + case PdcDrawPixmap: + case PdcDrawImage: + e = doc.createElement( "image" ); + e.setAttribute( "x", p[0].rect->x() ); + e.setAttribute( "y", p[0].rect->y() ); + e.setAttribute( "width", p[0].rect->width() ); + e.setAttribute( "height", p[0].rect->height() ); + if ( c == PdcDrawImage ) { + ImgElement ie; + ie.element = e; + ie.image = *p[1].image; + d->images.append( ie ); + } else { + PixElement pe; + pe.element = e; + pe.pixmap = *p[1].pixmap; + d->pixmaps.append( pe ); + } + // saving to disk and setting the xlink:href attribute will be + // done later in save() once we now the svg document name. + break; + case PdcSave: + e = doc.createElement( "g" ); + break; + case PdcRestore: + current = current.parentNode(); + dirtyTransform = !pt->worldMatrix().isIdentity(); + d->justRestored = TRUE; + // ### reset dirty flags + break; + case PdcSetBkColor: + case PdcSetBkMode: + case PdcSetROP: + case PdcSetBrushOrigin: + case PdcSetFont: + case PdcSetPen: + case PdcSetBrush: + dirtyStyle = TRUE; + break; + case PdcSetTabStops: + // ### + break; + case PdcSetTabArray: + // ### + break; + case PdcSetVXform: + case PdcSetWindow: + case PdcSetViewport: + case PdcSetWXform: + case PdcSetWMatrix: + case PdcSaveWMatrix: + case PdcRestoreWMatrix: + dirtyTransform = TRUE; + break; + case PdcSetClip: + // ### + break; + case PdcSetClipRegion: + { + // We skip the clip after restore, since restoring the clip is done automatically by + // the viewer as part of the tree structure. It doesn't hurt to write the region + // out, but it doubles the number of clipregions defined in the final svg. + if (d->justRestored) { + d->justRestored = FALSE; + return TRUE; + } + + TQMemArray rects = p[0].rgn->rects(); + if (rects.count() == 0) + return TRUE; + d->currentClip++; + e = doc.createElement( "clipPath" ); + e.setAttribute( "id", TQString("clip%1").arg(d->currentClip) ); + for (int i=0; i<(int)rects.count(); ++i) { + TQDomElement ce = doc.createElement("rect"); + ce.setAttribute( "x", rects.at(i).x() ); + ce.setAttribute( "y", rects.at(i).y() ); + ce.setAttribute( "width", rects.at(i).width() ); + ce.setAttribute( "height", rects.at(i).height() ); + e.appendChild(ce); + } + break; + } + default: +#if defined(CHECK_RANGE) + tqWarning( "TQSVGDevice::cmd: Invalid command %d", c ); +#endif + break; + } + + appendChild( e, c ); + + return TRUE; +} + +/*! + \internal + + Appends the child and applys any style and transformation. + +*/ + +void TQSvgDevice::appendChild( TQDomElement &e, int c ) +{ + if ( !e.isNull() ) { + current.appendChild( e ); + if ( c == PdcSave ) + current = e; + // ### optimize application of attributes utilizing + if ( c == PdcSetClipRegion ) { + TQDomElement ne; + ne = doc.createElement( "g" ); + ne.setAttribute( "style", TQString("clip-path:url(#clip%1)").arg(d->currentClip) ); + current.appendChild( ne ); + current = ne; + } else { + if ( dirtyStyle ) // only reset when entering + applyStyle( &e, c ); // or leaving a tag + if ( dirtyTransform && e.tagName() != "g" ) { + // same as above but not for tags + applyTransform( &e ); + if ( c == PdcSave ) + dirtyTransform = FALSE; + } + } + } +} + + +/*! + \internal + + Push the current drawing attributes on a stack. + + \sa restoreAttributes() +*/ + +void TQSvgDevice::saveAttributes() +{ + pt->save(); + // copy old state + TQSvgDeviceState st( *curr ); + d->stack.append( st ); + curr = &d->stack.last(); +} + +/*! + \internal + + Pop the current drawing attributes off the stack. + + \sa saveAttributes() +*/ + +void TQSvgDevice::restoreAttributes() +{ + pt->restore(); + Q_ASSERT( d->stack.count() > 1 ); + d->stack.remove( d->stack.fromLast() ); + curr = &d->stack.last(); +} + +/*! + \internal + + Evaluate \a node, drawing on \a p. Allows recursive calls. +*/ + +bool TQSvgDevice::play( const TQDomNode &node ) +{ + saveAttributes(); + + ElementType t = (*qSvgTypeMap)[ node.nodeName() ]; + + if ( t == LineElement && pt->pen().style() == TQt::NoPen ) { + TQPen p = pt->pen(); + p.setStyle( TQt::SolidLine ); + pt->setPen( p ); + } + TQDomNamedNodeMap attr = node.attributes(); + if ( attr.contains( "style" ) ) + setStyle( attr.namedItem( "style" ).nodeValue() ); + // ### might have to exclude more elements from transform + if ( t != SvgElement && attr.contains( "transform" ) ) + setTransform( attr.namedItem( "transform" ).nodeValue() ); + uint i = attr.length(); + if ( i > 0 ) { + TQPen pen = pt->pen(); + TQFont font = pt->font(); + while ( i-- ) { + TQDomNode n = attr.item( i ); + TQString a = n.nodeName(); + TQString val = n.nodeValue().lower().stripWhiteSpace(); + setStyleProperty( a, val, &pen, &font, &curr->textalign ); + } + pt->setPen( pen ); + pt->setFont( font ); + } + + int x1, y1, x2, y2, rx, ry, w, h; + double cx1, cy1, crx, cry; + switch ( t ) { + case CommentElement: + // ignore + break; + case RectElement: + rx = ry = 0; + x1 = lenToInt( attr, "x" ); + y1 = lenToInt( attr, "y" ); + w = lenToInt( attr, "width" ); + h = lenToInt( attr, "height" ); + if ( w == 0 || h == 0 ) // prevent div by zero below + break; + x2 = (int)attr.contains( "rx" ); // tiny abuse of x2 and y2 + y2 = (int)attr.contains( "ry" ); + if ( x2 ) + rx = lenToInt( attr, "rx" ); + if ( y2 ) + ry = lenToInt( attr, "ry" ); + if ( x2 && !y2 ) + ry = rx; + else if ( !x2 && y2 ) + rx = ry; + rx = int(200.0*double(rx)/double(w)); + ry = int(200.0*double(ry)/double(h)); + pt->drawRoundRect( x1, y1, w, h, rx, ry ); + break; + case CircleElement: + cx1 = lenToDouble( attr, "cx" ) + 0.5; + cy1 = lenToDouble( attr, "cy" ) + 0.5; + crx = lenToDouble( attr, "r" ); + pt->drawEllipse( (int)(cx1-crx), (int)(cy1-crx), (int)(2*crx), (int)(2*crx) ); + break; + case EllipseElement: + cx1 = lenToDouble( attr, "cx" ) + 0.5; + cy1 = lenToDouble( attr, "cy" ) + 0.5; + crx = lenToDouble( attr, "rx" ); + cry = lenToDouble( attr, "ry" ); + pt->drawEllipse( (int)(cx1-crx), (int)(cy1-cry), (int)(2*crx), (int)(2*cry) ); + break; + case LineElement: + { + x1 = lenToInt( attr, "x1" ); + x2 = lenToInt( attr, "x2" ); + y1 = lenToInt( attr, "y1" ); + y2 = lenToInt( attr, "y2" ); + TQPen p = pt->pen(); + w = p.width(); + p.setWidth( (unsigned int)(w * (TQABS(pt->worldMatrix().m11()) + TQABS(pt->worldMatrix().m22())) / 2) ); + pt->setPen( p ); + pt->drawLine( x1, y1, x2, y2 ); + p.setWidth( w ); + pt->setPen( p ); + } + break; + case PolylineElement: + case PolygonElement: + { + TQString pts = attr.namedItem( "points" ).nodeValue(); + pts = pts.simplifyWhiteSpace(); + TQStringList sl = TQStringList::split( TQRegExp( TQString::fromLatin1("[ ,]") ), pts ); + TQPointArray ptarr( (uint)sl.count() / 2); + for ( int i = 0; i < (int)sl.count() / 2; i++ ) { + double dx = sl[2*i].toDouble(); + double dy = sl[2*i+1].toDouble(); + ptarr.setPoint( i, int(dx), int(dy) ); + } + if ( t == PolylineElement ) { + if ( pt->brush().style() != TQt::NoBrush ) { + TQPen pn = pt->pen(); + pt->setPen( TQt::NoPen ); + pt->drawPolygon( ptarr ); + pt->setPen( pn ); + } + pt->drawPolyline( ptarr ); // ### closes when filled. bug ? + } else { + pt->drawPolygon( ptarr ); + } + } + break; + case SvgElement: + case GroupElement: + case AnchorElement: + { + TQDomNode child = node.firstChild(); + while ( !child.isNull() ) { + play( child ); + child = child.nextSibling(); + } + } + break; + case PathElement: + drawPath( attr.namedItem( "d" ).nodeValue() ); + break; + case TSpanElement: + case TextElement: + { + if ( attr.contains( "x" ) ) + curr->textx = lenToInt( attr, "x" ); + if ( attr.contains( "y" ) ) + curr->texty = lenToInt( attr, "y" ); + if ( t == TSpanElement ) { + curr->textx += lenToInt( attr, "dx" ); + curr->texty += lenToInt( attr, "dy" ); + } + // backup old colors + TQPen pn = pt->pen(); + TQColor pcolor = pn.color(); + TQColor bcolor = pt->brush().color(); + TQDomNode c = node.firstChild(); + while ( !c.isNull() ) { + if ( c.isText() ) { + // we have pen and brush reversed for text drawing + pn.setColor( bcolor ); + pt->setPen( pn ); + TQString text = c.toText().nodeValue(); + text = text.simplifyWhiteSpace(); // ### 'preserve' + w = pt->fontMetrics().width( text ); + if ( curr->textalign == TQt::AlignHCenter ) + curr->textx -= w / 2; + else if ( curr->textalign == TQt::AlignRight ) + curr->textx -= w; + pt->drawText( curr->textx, curr->texty, text ); + // restore pen + pn.setColor( pcolor ); + pt->setPen( pn ); + curr->textx += w; + } else if ( c.isElement() && + c.toElement().tagName() == "tspan" ) { + play( c ); + + } + c = c.nextSibling(); + } + if ( t == TSpanElement ) { + // move current text position in parent text element + StateList::Iterator it = --d->stack.fromLast(); + (*it).textx = curr->textx; + (*it).texty = curr->texty; + } + } + break; + case ImageElement: + { + x1 = lenToInt( attr, "x" ); + y1 = lenToInt( attr, "y" ); + w = lenToInt( attr, "width" ); + h = lenToInt( attr, "height" ); + TQString href = attr.namedItem( "xlink:href" ).nodeValue(); + // ### catch references to embedded .svg files + TQPixmap pix; + if ( !pix.load( href ) ) { + tqWarning( "TQSvgDevice::play: Couldn't load image %s", href.latin1() ); + break; + } + pt->drawPixmap( TQRect( x1, y1, w, h ), pix ); + } + break; + case DescElement: + case TitleElement: + // ignored for now + break; + case ClipElement: + { + TQDomNode child = node.firstChild(); + TQRegion region; + while (!child.isNull()) { + TQDomNamedNodeMap childAttr = child.attributes(); + if ( child.nodeName() == "rect" ) { + TQRect r; + r.setX(lenToInt( childAttr, "x" )); + r.setY(lenToInt( childAttr, "y" )); + r.setWidth(lenToInt( childAttr, "width" )); + r.setHeight(lenToInt( childAttr, "height" )); + region |= r; + } else if ( child.nodeName() == "ellipse" ) { + TQRect r; + int x = lenToInt( childAttr, "cx" ); + int y = lenToInt( childAttr, "cy" ); + int width = lenToInt( childAttr, "rx" ); + int height = lenToInt( childAttr, "ry" ); + r.setX( x - width ); + r.setY( y - height ); + r.setWidth( width * 2 ); + r.setHeight( height * 2 ); + TQRegion rgn( r, TQRegion::Ellipse ); + region |= rgn; + } + child = child.nextSibling(); + } + // Store the region in a named map so that it can be used when the + // group node is entered. + TQString idString = attr.namedItem("id").nodeValue(); + if (!idString.isEmpty()) + d->clipPathTable[idString] = region; + break; + } + case InvalidElement: + tqWarning( "TQSvgDevice::play: unknown element type %s", + node.nodeName().latin1() ); + break; + }; + + restoreAttributes(); + + return TRUE; +} + +/*! + \internal + + Parses a CSS2-compatible color specification. Either a keyword or + a numerical RGB specification like #ff00ff or rgb(255,0,50%). +*/ + +TQColor TQSvgDevice::parseColor( const TQString &col ) +{ + static const struct ColorTable { + const char *name; + const char *rgb; + } coltab[] = { + { "black", "#000000" }, + { "silver", "#c0c0c0" }, + { "gray", "#808080" }, + { "white", "#ffffff" }, + { "maroon", "#800000" }, + { "red", "#ff0000" }, + { "purple", "#800080" }, + { "fuchsia", "#ff00ff" }, + { "green", "#008000" }, + { "lime", "#00ff00" }, + { "olive", "#808000" }, + { "yellow", "#ffff00" }, + { "navy", "#000080" }, + { "blue", "#0000ff" }, + { "teal", "#008080" }, + { "aqua", "#00ffff" }, + // ### the latest spec has more + { 0, 0 } + }; + + // initialize color map on first use + if ( !qSvgColMap ) { + qSvgColMap = new TQMap; + const struct ColorTable *t = coltab; + while ( t->name ) { + qSvgColMap->insert( t->name, t->rgb ); + t++; + } + } + + // a keyword ? + if ( qSvgColMap->contains ( col ) ) + return TQColor( (*qSvgColMap)[ col ] ); + // in rgb(r,g,b) form ? + TQString c = col; + c.replace( TQRegExp( TQString::fromLatin1("\\s*") ), "" ); + TQRegExp reg( TQString::fromLatin1("^rgb\\((\\d+)(%?),(\\d+)(%?),(\\d+)(%?)\\)$") ); + if ( reg.search( c ) >= 0 ) { + int comp[3]; + for ( int i = 0; i < 3; i++ ) { + comp[ i ] = reg.cap( 2*i+1 ).toInt(); + if ( !reg.cap( 2*i+2 ).isEmpty() ) // percentage ? + comp[ i ] = int((double(255*comp[ i ])/100.0)); + } + return TQColor( comp[ 0 ], comp[ 1 ], comp[ 2 ] ); + } + + // check for predefined TQt color objects, #RRGGBB and #RGB + return TQColor( col ); +} + +/*! + \internal + + Parse a datatype consisting of a number followed by an + optional unit specifier. Can be used for type as + well. For relative units the value of \a horiz will determine + whether the horizontal or vertical dimension will be used. +*/ + +double TQSvgDevice::parseLen( const TQString &str, bool *ok, bool horiz ) const +{ + TQRegExp reg( TQString::fromLatin1("([+-]?\\d*\\.*\\d*[Ee]?[+-]?\\d*)(em|ex|px|%|pt|pc|cm|mm|in|)$") ); + if ( reg.search( str ) == -1 ) { + tqWarning( "TQSvgDevice::parseLen: couldn't parse %s ", str.latin1() ); + if ( ok ) + *ok = FALSE; + return 0.0; + } + + double dbl = reg.cap( 1 ).toDouble(); + TQString u = reg.cap( 2 ); + if ( !u.isEmpty() && u != "px" ) { + TQPaintDeviceMetrics m( pt->device() ); + if ( u == "em" ) { + TQFontInfo fi( pt->font() ); + dbl *= fi.pixelSize(); + } else if ( u == "ex" ) { + TQFontInfo fi( pt->font() ); + dbl *= 0.5 * fi.pixelSize(); + } else if ( u == "%" ) + dbl *= (horiz ? pt->window().width() : pt->window().height())/100.0; + else if ( u == "cm" ) + dbl *= m.logicalDpiX() / 2.54; + else if ( u == "mm" ) + dbl *= m.logicalDpiX() / 25.4; + else if ( u == "in" ) + dbl *= m.logicalDpiX(); + else if ( u == "pt" ) + dbl *= m.logicalDpiX() / 72.0; + else if ( u == "pc" ) + dbl *= m.logicalDpiX() / 6.0; + else + tqWarning( "TQSvgDevice::parseLen: Unknown unit %s", u.latin1() ); + } + if ( ok ) + *ok = TRUE; + return dbl; +} + +/*! + \internal + + Returns the length specified in attribute \a attr in \a map. If + the specified attribute doesn't exist or can't be parsed \a def is + returned. +*/ + +int TQSvgDevice::lenToInt( const TQDomNamedNodeMap &map, const TQString &attr, + int def ) const +{ + if ( map.contains( attr ) ) { + bool ok; + double dbl = parseLen( map.namedItem( attr ).nodeValue(), &ok ); + if ( ok ) + return tqRound( dbl ); + } + return def; +} + +double TQSvgDevice::lenToDouble( const TQDomNamedNodeMap &map, const TQString &attr, + int def ) const +{ + if ( map.contains( attr ) ) { + bool ok; + double d = parseLen( map.namedItem( attr ).nodeValue(), &ok ); + if ( ok ) + return d; + } + return def; +} + +void TQSvgDevice::setStyleProperty( const TQString &prop, const TQString &val, + TQPen *pen, TQFont *font, int *talign ) +{ + if ( prop == "stroke" ) { + if ( val == "none" ) { + pen->setStyle( TQt::NoPen ); + } else { + pen->setColor( parseColor( val )); + if ( pen->style() == TQt::NoPen ) + pen->setStyle( TQt::SolidLine ); + if ( pen->width() == 0 ) + pen->setWidth( 1 ); + } + } else if ( prop == "stroke-width" ) { + double w = parseLen( val ); + if ( w > 0.0001 ) + pen->setWidth( int(w) ); + else + pen->setStyle( TQt::NoPen ); + } else if ( prop == "stroke-linecap" ) { + if ( val == "butt" ) + pen->setCapStyle( TQt::FlatCap ); + else if ( val == "round" ) + pen->setCapStyle( TQt::RoundCap ); + else if ( val == "square" ) + pen->setCapStyle( TQt::SquareCap ); + } else if ( prop == "stroke-linejoin" ) { + if ( val == "miter" ) + pen->setJoinStyle( TQt::MiterJoin ); + else if ( val == "round" ) + pen->setJoinStyle( TQt::RoundJoin ); + else if ( val == "bevel" ) + pen->setJoinStyle( TQt::BevelJoin ); + } else if ( prop == "stroke-dasharray" ) { + if ( val == "18,6" ) + pen->setStyle( TQt::DashLine ); + else if ( val == "3" ) + pen->setStyle( TQt::DotLine ); + else if ( val == "9,6,3,6" ) + pen->setStyle( TQt::DashDotLine ); + else if ( val == "9,3,3" ) + pen->setStyle( TQt::DashDotDotLine ); + else + pen->setStyle( TQt::DotLine ); + } else if ( prop == "fill" ) { + if ( val == "none" ) + pt->setBrush( TQt::NoBrush ); + else + pt->setBrush( parseColor( val ) ); + } else if ( prop == "font-size" ) { + font->setPointSizeFloat( float(parseLen( val )) ); + } else if ( prop == "font-family" ) { + font->setFamily( val ); + } else if ( prop == "font-style" ) { + if ( val == "normal" ) + font->setItalic( FALSE ); + else if ( val == "italic" ) + font->setItalic( TRUE ); + else + tqWarning( "TQSvgDevice::setStyleProperty: unhandled " + "font-style: %s", val.latin1() ); + } else if ( prop == "font-weight" ) { + int w = font->weight(); + // no exact equivalents so we have to "round" a little bit + if ( val == "100" || val == "200" ) + w = TQFont::Light; + if ( val == "300" || val == "400" || val == "normal" ) + w = TQFont::Normal; + else if ( val == "500" || val == "600" ) + w = TQFont::DemiBold; + else if ( val == "700" || val == "bold" || val == "800" ) + w = TQFont::Bold; + else if ( val == "900" ) + w = TQFont::Black; + font->setWeight( w ); + } else if ( prop == "text-anchor" ) { + if ( val == "middle" ) + *talign = TQt::AlignHCenter; + else if ( val == "end" ) + *talign = TQt::AlignRight; + else + *talign = TQt::AlignLeft; + } else if ( prop == "clip-path" ) { + if (val.startsWith("url(#")) { + TQString clipName = val.mid(5, val.length() - 6); + if (!clipName.isEmpty()) { + TQRegion clipRegion = d->clipPathTable[clipName]; + if (!clipRegion.isEmpty()) + pt->setClipRegion(pt->clipRegion() & clipRegion, TQPainter::CoordPainter); + } + } + } +} + +void TQSvgDevice::setStyle( const TQString &s ) +{ + TQStringList rules = TQStringList::split( TQChar(';'), s ); + + TQPen pen = pt->pen(); + TQFont font = pt->font(); + + TQStringList::ConstIterator it = rules.begin(); + for ( ; it != rules.end(); it++ ) { + int col = (*it).find( ':' ); + if ( col > 0 ) { + TQString prop = (*it).left( col ).simplifyWhiteSpace(); + TQString val = (*it).right( (*it).length() - col - 1 ); + val = val.lower().stripWhiteSpace(); + setStyleProperty( prop, val, &pen, &font, &curr->textalign ); + } + } + + pt->setPen( pen ); + pt->setFont( font ); +} + +void TQSvgDevice::setTransform( const TQString &tr ) +{ + TQString t = tr.simplifyWhiteSpace(); + + TQRegExp reg( TQString::fromLatin1("\\s*([\\w]+)\\s*\\(([^\\(]*)\\)") ); + int index = 0; + while ( (index = reg.search(t, index)) >= 0 ) { + TQString command = reg.cap( 1 ); + TQString params = reg.cap( 2 ); + TQStringList plist = TQStringList::split( TQRegExp(TQString::fromLatin1("[,\\s]")), params ); + if ( command == "translate" ) { + double tx = 0, ty = 0; + tx = plist[0].toDouble(); + if ( plist.count() >= 2 ) + ty = plist[1].toDouble(); + pt->translate( tx, ty ); + } else if ( command == "rotate" ) { + pt->rotate( plist[0].toDouble() ); + } else if ( command == "scale" ) { + double sx, sy; + sx = sy = plist[0].toDouble(); + if ( plist.count() >= 2 ) + sy = plist[1].toDouble(); + pt->scale( sx, sy ); + } else if ( command == "matrix" && plist.count() >= 6 ) { + double m[ 6 ]; + for (int i = 0; i < 6; i++) + m[ i ] = plist[ i ].toDouble(); + TQWMatrix wm( m[ 0 ], m[ 1 ], m[ 2 ], + m[ 3 ], m[ 4 ], m[ 5 ] ); + pt->setWorldMatrix( wm, TRUE ); + } else if ( command == "skewX" ) { + pt->shear( 0.0, tan( plist[0].toDouble() * deg2rad ) ); + } else if ( command == "skewY" ) { + pt->shear( tan( plist[0].toDouble() * deg2rad ), 0.0 ); + } + + // move on to next command + index += reg.matchedLength(); + } +} + +void TQSvgDevice::drawPath( const TQString &data ) +{ + double x0 = 0, y0 = 0; // starting point + double x = 0, y = 0; // current point + double controlX = 0, controlY = 0; // last control point for curves + TQPointArray path( 500 ); // resulting path + TQValueList subIndex; // start indices for subpaths + TQPointArray quad( 4 ), bezier; // for curve calculations + int pcount = 0; // current point array index + uint idx = 0; // current data position + int mode = 0, lastMode = 0; // parser state + bool relative = FALSE; // e.g. 'h' vs. 'H' + TQString commands( "MZLHVCSTQTA" ); // recognized commands + int cmdArgs[] = { 2, 0, 2, 1, 1, 6, 4, 4, 2, 7 }; // no of arguments + TQRegExp reg( TQString::fromLatin1("\\s*,?\\s*([+-]?\\d*\\.?\\d*)") ); // floating point + + subIndex.append( 0 ); + // detect next command + while ( idx < data.length() ) { + TQChar ch = data[ (int)idx++ ]; + if ( ch.isSpace() ) + continue; + TQChar chUp = ch.upper(); + int cmd = commands.find( chUp ); + if ( cmd >= 0 ) { + // switch to new command mode + mode = cmd; + relative = ( ch != chUp ); // e.g. 'm' instead of 'M' + } else { + if ( mode && !ch.isLetter() ) { + cmd = mode; // continue in previous mode + idx--; + } else { + tqWarning( "TQSvgDevice::drawPath: Unknown command" ); + return; + } + } + + // read in the required number of arguments + const int maxArgs = 7; + double arg[ maxArgs ]; + int numArgs = cmdArgs[ cmd ]; + for ( int i = 0; i < numArgs; i++ ) { + int pos = reg.search( data, idx ); + if ( pos == -1 ) { + tqWarning( "TQSvgDevice::drawPath: Error parsing arguments" ); + return; + } + arg[ i ] = reg.cap( 1 ).toDouble(); + idx = pos + reg.matchedLength(); + }; + + // process command + double offsetX = relative ? x : 0; // correction offsets + double offsetY = relative ? y : 0; // for relative commands + switch ( mode ) { + case 0: // 'M' move to + if ( x != x0 || y != y0 ) + path.setPoint( pcount++, int(x0), int(y0) ); + x = x0 = arg[ 0 ] + offsetX; + y = y0 = arg[ 1 ] + offsetY; + subIndex.append( pcount ); + path.setPoint( pcount++, int(x0), int(y0) ); + mode = 2; // -> 'L' + break; + case 1: // 'Z' close path + path.setPoint( pcount++, int(x0), int(y0) ); + x = x0; + y = y0; + mode = 0; + break; + case 2: // 'L' line to + x = arg[ 0 ] + offsetX; + y = arg[ 1 ] + offsetY; + path.setPoint( pcount++, int(x), int(y) ); + break; + case 3: // 'H' horizontal line + x = arg[ 0 ] + offsetX; + path.setPoint( pcount++, int(x), int(y) ); + break; + case 4: // 'V' vertical line + y = arg[ 0 ] + offsetY; + path.setPoint( pcount++, int(x), int(y) ); + break; +#ifndef TQT_NO_BEZIER + case 5: // 'C' cubic bezier curveto + case 6: // 'S' smooth shorthand + case 7: // 'Q' quadratic bezier curves + case 8: { // 'T' smooth shorthand + quad.setPoint( 0, int(x), int(y) ); + // if possible, reflect last control point if smooth shorthand + if ( mode == 6 || mode == 8 ) { // smooth 'S' and 'T' + bool cont = mode == lastMode || + ( mode == 6 && lastMode == 5 ) || // 'S' and 'C' + ( mode == 8 && lastMode == 7 ); // 'T' and 'Q' + x = cont ? 2*x-controlX : x; + y = cont ? 2*y-controlY : y; + quad.setPoint( 1, int(x), int(y) ); + quad.setPoint( 2, int(x), int(y) ); + } + for ( int j = 0; j < numArgs/2; j++ ) { + x = arg[ 2*j ] + offsetX; + y = arg[ 2*j+1 ] + offsetY; + quad.setPoint( j+4-numArgs/2, int(x), int(y) ); + } + // remember last control point for next shorthand + controlX = quad[ 2 ].x(); + controlY = quad[ 2 ].y(); + // transform quadratic into cubic Bezier + if ( mode == 7 || mode == 8 ) { // cubic 'Q' and 'T' + int x31 = quad[0].x()+int(2.0*(quad[2].x()-quad[0].x())/3.0); + int y31 = quad[0].y()+int(2.0*(quad[2].y()-quad[0].y())/3.0); + int x32 = quad[2].x()+int(2.0*(quad[3].x()-quad[2].x())/3.0); + int y32 = quad[2].y()+int(2.0*(quad[3].y()-quad[2].y())/3.0); + quad.setPoint( 1, x31, y31 ); + quad.setPoint( 2, x32, y32 ); + } + // calculate points on curve + bezier = quad.cubicBezier(); + // reserve more space if needed + if ( bezier.size() > path.size() - pcount ) + path.resize( path.size() - pcount + bezier.size() ); + // copy + for ( int k = 0; k < (int)bezier.size(); k ++ ) + path.setPoint( pcount++, bezier[ k ] ); + break; + } +#endif // TQT_NO_BEZIER + case 9: // 'A' elliptical arc curve + // ### just a straight line + x = arg[ 5 ] + offsetX; + y = arg[ 6 ] + offsetY; + path.setPoint( pcount++, int(x), int(y) ); + break; + }; + lastMode = mode; + // array almost full ? expand for next loop + if ( pcount >= (int)path.size() - 4 ) + path.resize( 2 * path.size() ); + } + + subIndex.append( pcount ); // dummy marking the end + if ( pt->brush().style() != TQt::NoBrush ) { + // fill the area without stroke first + if ( x != x0 || y != y0 ) + path.setPoint( pcount++, int(x0), int(y0) ); + TQPen pen = pt->pen(); + pt->setPen( TQt::NoPen ); + pt->drawPolygon( path, FALSE, 0, pcount ); + pt->setPen( pen ); + } + // draw each subpath stroke seperately + TQValueListConstIterator it = subIndex.begin(); + int start = 0; + while ( it != subIndex.fromLast() ) { + int next = *++it; + // ### always joins ends if first and last point coincide. + // ### 'Z' can't have the desired effect + pt->drawPolyline( path, start, next-start ); + start = next; + } +} + +void TQSvgDevice::applyStyle( TQDomElement *e, int c ) const +{ + // ### do not write every attribute each time + TQColor pcol = pt->pen().color(); + TQColor bcol = pt->brush().color(); + TQString s; + if ( c == PdcDrawText2 || c == PdcDrawText2Formatted ) { + // TQPainter has a reversed understanding of pen/stroke vs. + // brush/fill for text + s += TQString( "fill:rgb(%1,%2,%3);" ) + .arg( pcol.red() ).arg( pcol.green() ).arg( pcol.blue() ); + s += TQString( "stroke-width:0;" ); + TQFont f = pt->font(); + TQFontInfo fi( f ); + s += TQString( "font-size:%1;" ).arg( fi.pointSize() ); + s += TQString( "font-style:%1;" ) + .arg( f.italic() ? "italic" : "normal" ); + // not a very scientific distribution + TQString fw; + if ( f.weight() <= TQFont::Light ) + fw = "100"; + else if ( f.weight() <= TQFont::Normal ) + fw = "400"; + else if ( f.weight() <= TQFont::DemiBold ) + fw = "600"; + else if ( f.weight() <= TQFont::Bold ) + fw = "700"; + else if ( f.weight() <= TQFont::Black ) + fw = "800"; + else + fw = "900"; + s += TQString( "font-weight:%1;" ).arg( fw ); + s += TQString( "font-family:%1;" ).arg( f.family() ); + } else { + s += TQString( "stroke:rgb(%1,%2,%3);" ) + .arg( pcol.red() ).arg( pcol.green() ).arg( pcol.blue() ); + double pw = pt->pen().width(); + if ( pw == 0 && pt->pen().style() != TQt::NoPen ) + pw = 0.9; + if ( c == PdcDrawLine ) + pw /= (TQABS(pt->worldMatrix().m11()) + TQABS(pt->worldMatrix().m22())) / 2.0; + s += TQString( "stroke-width:%1;" ).arg( pw ); + if ( pt->pen().style() == TQt::DashLine ) + s+= TQString( "stroke-dasharray:18,6;" ); + else if ( pt->pen().style() == TQt::DotLine ) + s+= TQString( "stroke-dasharray:3;" ); + else if ( pt->pen().style() == TQt::DashDotLine ) + s+= TQString( "stroke-dasharray:9,6,3,6;" ); + else if ( pt->pen().style() == TQt::DashDotDotLine ) + s+= TQString( "stroke-dasharray:9,3,3;" ); + if ( pt->brush().style() == TQt::NoBrush || c == PdcDrawPolyline || + c == PdcDrawCubicBezier ) + s += "fill:none;"; // TQt polylines use no brush, neither do Beziers + else + s += TQString( "fill:rgb(%1,%2,%3);" ) + .arg( bcol.red() ).arg( bcol.green() ).arg( bcol.blue() ); + } + e->setAttribute( "style", s ); +} + +void TQSvgDevice::applyTransform( TQDomElement *e ) const +{ + TQWMatrix m = pt->worldMatrix(); + + TQString s; + bool rot = ( m.m11() != 1.0 || m.m12() != 0.0 || + m.m21() != 0.0 || m.m22() != 1.0 ); + if ( !rot && ( m.dx() != 0.0 || m.dy() != 0.0 ) ) + s = TQString( "translate(%1,%2)" ).arg( m.dx() ).arg( m.dy() ); + else if ( rot ) { + if ( m.m12() == 0.0 && m.m21() == 0.0 && + m.dx() == 0.0 && m.dy() == 0.0 ) + s = TQString( "scale(%1,%2)" ).arg( m.m11() ).arg( m.m22() ); + else + s = TQString( "matrix(%1,%2,%3,%4,%5,%6)" ) + .arg( m.m11() ).arg( m.m12() ) + .arg( m.m21() ).arg( m.m22() ) + .arg( m.dx() ).arg( m.dy() ); + } + else + return; + + e->setAttribute( "transform", s ); +} + +#endif // TQT_NO_SVG diff --git a/src/xml/tqsvgdevice_p.h b/src/xml/tqsvgdevice_p.h new file mode 100644 index 000000000..ffdec75fd --- /dev/null +++ b/src/xml/tqsvgdevice_p.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Definition of the TQSvgDevice class +** +** Created : 001024 +** +** Copyright (C) 2000-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the xml module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +*****************************************************************************/ + +#ifndef TQSVGDEVICE_P_H +#define TQSVGDEVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. It exists for the convenience +// of the TQPicture class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// +// + +#ifndef QT_H +#include "tqpaintdevice.h" +#include "tqrect.h" +#include "tqdom.h" +#endif // QT_H + +#if !defined(TQT_MODULE_XML) || defined( QT_LICENSE_PROFESSIONAL ) || defined( QT_INTERNAL_XML ) +#define TQM_EXPORT_SVG +#else +#define TQM_EXPORT_SVG TQ_EXPORT +#endif + +#ifndef TQT_NO_SVG + +class TQPainter; +class TQDomNode; +class TQDomNamedNodeMap; +struct TQSvgDeviceState; +class TQSvgDevicePrivate; + +class TQM_EXPORT_SVG TQSvgDevice : public TQPaintDevice +{ +public: + TQSvgDevice(); + ~TQSvgDevice(); + + bool play( TQPainter *p ); + + TQString toString() const; + + bool load( TQIODevice *dev ); + bool save( TQIODevice *dev ); + bool save( const TQString &fileName ); + + TQRect boundingRect() const; + void setBoundingRect( const TQRect &r ); + +protected: + virtual bool cmd ( int, TQPainter*, TQPDevCmdParam* ); + virtual int metric( int ) const; + +private: + // reading + bool play( const TQDomNode &node ); + void saveAttributes(); + void restoreAttributes(); + TQColor parseColor( const TQString &col ); + double parseLen( const TQString &str, bool *ok=0, bool horiz=TRUE ) const; + int lenToInt( const TQDomNamedNodeMap &map, const TQString &attr, + int def=0 ) const; + double lenToDouble( const TQDomNamedNodeMap &map, const TQString &attr, + int def=0 ) const; + void setStyleProperty( const TQString &prop, const TQString &val, + TQPen *pen, TQFont *font, int *talign ); + void setStyle( const TQString &s ); + void setTransform( const TQString &tr ); + void drawPath( const TQString &data ); + + // writing + void appendChild( TQDomElement &e, int c ); + void applyStyle( TQDomElement *e, int c ) const; + void applyTransform( TQDomElement *e ) const; + + // reading + TQRect brect; // bounding rectangle + TQDomDocument doc; // document tree + TQDomNode current; + TQPoint curPt; + TQSvgDeviceState *curr; + TQPainter *pt; // used by play() et al + + // writing + bool dirtyTransform, dirtyStyle; + + TQSvgDevicePrivate *d; +}; + +inline TQRect TQSvgDevice::boundingRect() const +{ + return brect; +} + +#endif // TQT_NO_SVG + +#endif // TQSVGDEVICE_P_H diff --git a/tools/designer/designer/designer.pro b/tools/designer/designer/designer.pro index 5c5e0f353..da8c8cf29 100644 --- a/tools/designer/designer/designer.pro +++ b/tools/designer/designer/designer.pro @@ -64,7 +64,7 @@ SOURCES += command.cpp \ paletteeditoradvancedimpl.cpp \ sourcefile.cpp \ wizardeditorimpl.cpp \ - qcompletionedit.cpp \ + tqcompletionedit.cpp \ timestamp.cpp \ formfile.cpp \ widgetaction.cpp \ @@ -127,7 +127,7 @@ HEADERS += command.h \ pixmapcollection.h \ sourcefile.h \ wizardeditorimpl.h \ - qcompletionedit.h \ + tqcompletionedit.h \ timestamp.h \ formfile.h \ widgetaction.h \ diff --git a/tools/designer/designer/designer_pch.h b/tools/designer/designer/designer_pch.h index c65faea12..fd4fbe756 100644 --- a/tools/designer/designer/designer_pch.h +++ b/tools/designer/designer/designer_pch.h @@ -8,7 +8,7 @@ #if defined __cplusplus -#include +#include #include #include #include diff --git a/tools/designer/designer/hierarchyview.h b/tools/designer/designer/hierarchyview.h index 370eb41bf..039115558 100644 --- a/tools/designer/designer/hierarchyview.h +++ b/tools/designer/designer/hierarchyview.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "../interfaces/classbrowserinterface.h" class FormWindow; diff --git a/tools/designer/designer/mainwindow.cpp b/tools/designer/designer/mainwindow.cpp index 06ade5a3d..4cbca1130 100644 --- a/tools/designer/designer/mainwindow.cpp +++ b/tools/designer/designer/mainwindow.cpp @@ -56,7 +56,7 @@ #include "projectsettingsimpl.h" #include "tqwidgetfactory.h" #include "pixmapcollection.h" -#include "qcompletionedit.h" +#include "tqcompletionedit.h" #include "sourcefile.h" #include "orderindicator.h" #include diff --git a/tools/designer/designer/mainwindow.h b/tools/designer/designer/mainwindow.h index ddc99c07e..9e20f52a1 100644 --- a/tools/designer/designer/mainwindow.h +++ b/tools/designer/designer/mainwindow.h @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include class TQToolBox; diff --git a/tools/designer/designer/metadatabase.cpp b/tools/designer/designer/metadatabase.cpp index 1ff6a1c5a..b8385d056 100644 --- a/tools/designer/designer/metadatabase.cpp +++ b/tools/designer/designer/metadatabase.cpp @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tools/designer/designer/multilineeditorimpl.cpp b/tools/designer/designer/multilineeditorimpl.cpp index 9e9ecce35..cea8ad720 100644 --- a/tools/designer/designer/multilineeditorimpl.cpp +++ b/tools/designer/designer/multilineeditorimpl.cpp @@ -40,7 +40,7 @@ #include "widgetfactory.h" #include -#include <./private/qrichtext_p.h> +#include <./private/tqrichtext_p.h> #include #include #include diff --git a/tools/designer/designer/multilineeditorimpl.h b/tools/designer/designer/multilineeditorimpl.h index 22075a995..1e5dd8216 100644 --- a/tools/designer/designer/multilineeditorimpl.h +++ b/tools/designer/designer/multilineeditorimpl.h @@ -36,7 +36,7 @@ #include #include -#include +#include #include "multilineeditor.h" class FormWindow; diff --git a/tools/designer/designer/project.h b/tools/designer/designer/project.h index 80bdb505a..548195111 100644 --- a/tools/designer/designer/project.h +++ b/tools/designer/designer/project.h @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include "../interfaces/projectsettingsiface.h" #include "sourcefile.h" #include "formfile.h" diff --git a/tools/designer/designer/qcompletionedit.cpp b/tools/designer/designer/qcompletionedit.cpp deleted file mode 100644 index aba4dc872..000000000 --- a/tools/designer/designer/qcompletionedit.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/********************************************************************** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of TQt Designer. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** Licensees holding valid TQt Commercial licenses may use this file in -** accordance with the TQt Commercial License Agreement provided with -** the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include "qcompletionedit.h" -#include -#include -#include -#include - -TQCompletionEdit::TQCompletionEdit( TQWidget *parent, const char *name ) - : TQLineEdit( parent, name ), aAdd( FALSE ), caseSensitive( FALSE ) -{ - popup = new TQVBox( 0, 0, WType_Popup ); - popup->setFrameStyle( TQFrame::Box | TQFrame::Plain ); - popup->setLineWidth( 1 ); - popup->hide(); - - listbox = new TQListBox( popup ); - listbox->setFrameStyle( TQFrame::NoFrame ); - listbox->setLineWidth( 1 ); - listbox->installEventFilter( this ); - listbox->setHScrollBarMode( TQScrollView::AlwaysOn ); - listbox->setVScrollBarMode( TQScrollView::AlwaysOn ); - listbox->setCornerWidget( new TQSizeGrip( listbox, "completion sizegrip" ) ); - connect( this, TQ_SIGNAL( textChanged( const TQString & ) ), - this, TQ_SLOT( textDidChange( const TQString & ) ) ); - popup->setFocusProxy( listbox ); - installEventFilter( this ); -} - -bool TQCompletionEdit::autoAdd() const -{ - return aAdd; -} - -TQStringList TQCompletionEdit::completionList() const -{ - return compList; -} - -void TQCompletionEdit::setCompletionList( const TQStringList &l ) -{ - compList = l; -} - -void TQCompletionEdit::setAutoAdd( bool add ) -{ - aAdd = add; -} - -void TQCompletionEdit::textDidChange( const TQString &text ) -{ - if ( text.isEmpty() ) { - popup->close(); - return; - } - updateListBox(); - placeListBox(); -} - -void TQCompletionEdit::placeListBox() -{ - if ( listbox->count() == 0 ) { - popup->close(); - return; - } - - popup->resize( TQMAX( listbox->sizeHint().width() + listbox->verticalScrollBar()->width() + 4, width() ), - listbox->sizeHint().height() + listbox->horizontalScrollBar()->height() + 4 ); - - TQPoint p( mapToGlobal( TQPoint( 0, 0 ) ) ); - if ( p.y() + height() + popup->height() <= TQApplication::desktop()->height() ) - popup->move( p.x(), p.y() + height() ); - else - popup->move( p.x(), p.y() - listbox->height() ); - popup->show(); - listbox->setCurrentItem( 0 ); - listbox->setSelected( 0, TRUE ); - setFocus(); -} - -void TQCompletionEdit::updateListBox() -{ - listbox->clear(); - if ( compList.isEmpty() ) - return; - for ( TQStringList::Iterator it = compList.begin(); it != compList.end(); ++it ) { - if ( ( caseSensitive && (*it).left( text().length() ) == text() ) || - ( !caseSensitive && (*it).left( text().length() ).lower() == text().lower() ) ) - listbox->insertItem( *it ); - } -} - -bool TQCompletionEdit::eventFilter( TQObject *o, TQEvent *e ) -{ - if ( o == popup || o == listbox || o == listbox->viewport() ) { - if ( e->type() == TQEvent::KeyPress ) { - TQKeyEvent *ke = (TQKeyEvent*)e; - if ( ke->key() == Key_Enter || ke->key() == Key_Return || ke->key() == Key_Tab ) { - if ( ke->key() == Key_Tab && listbox->count() > 1 && - listbox->currentItem() < (int)listbox->count() - 1 ) { - listbox->setCurrentItem( listbox->currentItem() + 1 ); - return TRUE; - } - popup->close(); - setFocus(); - blockSignals( TRUE ); - setText( listbox->currentText() ); - blockSignals( FALSE ); - emit chosen( text() ); - return TRUE; - } else if ( ke->key() == Key_Left || ke->key() == Key_Right || - ke->key() == Key_Up || ke->key() == Key_Down || - ke->key() == Key_Home || ke->key() == Key_End || - ke->key() == Key_Prior || ke->key() == Key_Next ) { - return FALSE; - } else if ( ke->key() == Key_Escape ) { - popup->close(); - setFocus(); - } else if ( ke->key() != Key_Shift && ke->key() != Key_Control && - ke->key() != Key_Alt ) { - updateListBox(); - if ( listbox->count() == 0 || text().length() == 0 ) { - popup->close(); - setFocus(); - } - TQApplication::sendEvent( this, e ); - return TRUE; - } - } else if ( e->type() == TQEvent::MouseButtonDblClick ) { - popup->close(); - setFocus(); - blockSignals( TRUE ); - setText( listbox->currentText() ); - blockSignals( FALSE ); - emit chosen( text() ); - return TRUE; - } - } else if ( o == this ) { - if ( e->type() == TQEvent::KeyPress ) { - TQKeyEvent *ke = (TQKeyEvent*)e; - if ( ke->key() == Key_Up || - ke->key() == Key_Down || - ke->key() == Key_Prior || - ke->key() == Key_Next || - ke->key() == Key_Return || - ke->key() == Key_Enter || - ke->key() == Key_Tab || - ke->key() == Key_Escape ) { - TQApplication::sendEvent( listbox, e ); - return TRUE; - } - } - } - return TQLineEdit::eventFilter( o, e ); -} - -void TQCompletionEdit::addCompletionEntry( const TQString &entry ) -{ - if ( compList.find( entry ) == compList.end() ) { - compList << entry; - compList.sort(); - } -} - -void TQCompletionEdit::removeCompletionEntry( const TQString &entry ) -{ - TQStringList::Iterator it = compList.find( entry ); - if ( it != compList.end() ) - compList.remove( it ); -} - -void TQCompletionEdit::setCaseSensitive( bool b ) -{ - caseSensitive = b; -} - -bool TQCompletionEdit::isCaseSensitive() const -{ - return caseSensitive; -} - -void TQCompletionEdit::clear() -{ - TQLineEdit::clear(); - compList.clear(); -} diff --git a/tools/designer/designer/qcompletionedit.h b/tools/designer/designer/qcompletionedit.h deleted file mode 100644 index 792f74002..000000000 --- a/tools/designer/designer/qcompletionedit.h +++ /dev/null @@ -1,86 +0,0 @@ -/********************************************************************** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of TQt Designer. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** Licensees holding valid TQt Commercial licenses may use this file in -** accordance with the TQt Commercial License Agreement provided with -** the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#ifndef TQCOMPLETIONEDIT_H -#define TQCOMPLETIONEDIT_H - -#include -#include - -class TQListBox; -class TQVBox; - -class TQCompletionEdit : public TQLineEdit -{ - TQ_OBJECT - TQ_PROPERTY( bool autoAdd READ autoAdd WRITE setAutoAdd ) - TQ_PROPERTY( bool caseSensitive READ isCaseSensitive WRITE setCaseSensitive ) - -public: - TQCompletionEdit( TQWidget *parent = 0, const char *name = 0 ); - - bool autoAdd() const; - TQStringList completionList() const; - bool eventFilter( TQObject *o, TQEvent *e ); - bool isCaseSensitive() const; - -public slots: - void setCompletionList( const TQStringList &l ); - void setAutoAdd( bool add ); - void clear(); - void addCompletionEntry( const TQString &entry ); - void removeCompletionEntry( const TQString &entry ); - void setCaseSensitive( bool b ); - -signals: - void chosen( const TQString &text ); - -private slots: - void textDidChange( const TQString &text ); - -private: - void placeListBox(); - void updateListBox(); - -private: - bool aAdd; - TQStringList compList; - TQListBox *listbox; - TQVBox *popup; - bool caseSensitive; - -}; - - - -#endif diff --git a/tools/designer/designer/resource.cpp b/tools/designer/designer/resource.cpp index 278b0715d..d2f913b05 100644 --- a/tools/designer/designer/resource.cpp +++ b/tools/designer/designer/resource.cpp @@ -86,7 +86,7 @@ #include #include #include -#include +#include static TQString makeIndent( int indent ) { diff --git a/tools/designer/designer/syntaxhighlighter_html.h b/tools/designer/designer/syntaxhighlighter_html.h index 6173b6d58..fb208c8bf 100644 --- a/tools/designer/designer/syntaxhighlighter_html.h +++ b/tools/designer/designer/syntaxhighlighter_html.h @@ -34,7 +34,7 @@ #ifndef SYNTAXHIGHLIGHTER_HTML_H #define SYNTAXHIGHLIGHTER_HTML_H -#include <./private/qrichtext_p.h> +#include <./private/tqrichtext_p.h> class SyntaxHighlighter_HTML : public TQTextPreProcessor { diff --git a/tools/designer/designer/tqcompletionedit.cpp b/tools/designer/designer/tqcompletionedit.cpp new file mode 100644 index 000000000..02c3af5c5 --- /dev/null +++ b/tools/designer/designer/tqcompletionedit.cpp @@ -0,0 +1,217 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of TQt Designer. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid TQt Commercial licenses may use this file in +** accordance with the TQt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "tqcompletionedit.h" +#include +#include +#include +#include + +TQCompletionEdit::TQCompletionEdit( TQWidget *parent, const char *name ) + : TQLineEdit( parent, name ), aAdd( FALSE ), caseSensitive( FALSE ) +{ + popup = new TQVBox( 0, 0, WType_Popup ); + popup->setFrameStyle( TQFrame::Box | TQFrame::Plain ); + popup->setLineWidth( 1 ); + popup->hide(); + + listbox = new TQListBox( popup ); + listbox->setFrameStyle( TQFrame::NoFrame ); + listbox->setLineWidth( 1 ); + listbox->installEventFilter( this ); + listbox->setHScrollBarMode( TQScrollView::AlwaysOn ); + listbox->setVScrollBarMode( TQScrollView::AlwaysOn ); + listbox->setCornerWidget( new TQSizeGrip( listbox, "completion sizegrip" ) ); + connect( this, TQ_SIGNAL( textChanged( const TQString & ) ), + this, TQ_SLOT( textDidChange( const TQString & ) ) ); + popup->setFocusProxy( listbox ); + installEventFilter( this ); +} + +bool TQCompletionEdit::autoAdd() const +{ + return aAdd; +} + +TQStringList TQCompletionEdit::completionList() const +{ + return compList; +} + +void TQCompletionEdit::setCompletionList( const TQStringList &l ) +{ + compList = l; +} + +void TQCompletionEdit::setAutoAdd( bool add ) +{ + aAdd = add; +} + +void TQCompletionEdit::textDidChange( const TQString &text ) +{ + if ( text.isEmpty() ) { + popup->close(); + return; + } + updateListBox(); + placeListBox(); +} + +void TQCompletionEdit::placeListBox() +{ + if ( listbox->count() == 0 ) { + popup->close(); + return; + } + + popup->resize( TQMAX( listbox->sizeHint().width() + listbox->verticalScrollBar()->width() + 4, width() ), + listbox->sizeHint().height() + listbox->horizontalScrollBar()->height() + 4 ); + + TQPoint p( mapToGlobal( TQPoint( 0, 0 ) ) ); + if ( p.y() + height() + popup->height() <= TQApplication::desktop()->height() ) + popup->move( p.x(), p.y() + height() ); + else + popup->move( p.x(), p.y() - listbox->height() ); + popup->show(); + listbox->setCurrentItem( 0 ); + listbox->setSelected( 0, TRUE ); + setFocus(); +} + +void TQCompletionEdit::updateListBox() +{ + listbox->clear(); + if ( compList.isEmpty() ) + return; + for ( TQStringList::Iterator it = compList.begin(); it != compList.end(); ++it ) { + if ( ( caseSensitive && (*it).left( text().length() ) == text() ) || + ( !caseSensitive && (*it).left( text().length() ).lower() == text().lower() ) ) + listbox->insertItem( *it ); + } +} + +bool TQCompletionEdit::eventFilter( TQObject *o, TQEvent *e ) +{ + if ( o == popup || o == listbox || o == listbox->viewport() ) { + if ( e->type() == TQEvent::KeyPress ) { + TQKeyEvent *ke = (TQKeyEvent*)e; + if ( ke->key() == Key_Enter || ke->key() == Key_Return || ke->key() == Key_Tab ) { + if ( ke->key() == Key_Tab && listbox->count() > 1 && + listbox->currentItem() < (int)listbox->count() - 1 ) { + listbox->setCurrentItem( listbox->currentItem() + 1 ); + return TRUE; + } + popup->close(); + setFocus(); + blockSignals( TRUE ); + setText( listbox->currentText() ); + blockSignals( FALSE ); + emit chosen( text() ); + return TRUE; + } else if ( ke->key() == Key_Left || ke->key() == Key_Right || + ke->key() == Key_Up || ke->key() == Key_Down || + ke->key() == Key_Home || ke->key() == Key_End || + ke->key() == Key_Prior || ke->key() == Key_Next ) { + return FALSE; + } else if ( ke->key() == Key_Escape ) { + popup->close(); + setFocus(); + } else if ( ke->key() != Key_Shift && ke->key() != Key_Control && + ke->key() != Key_Alt ) { + updateListBox(); + if ( listbox->count() == 0 || text().length() == 0 ) { + popup->close(); + setFocus(); + } + TQApplication::sendEvent( this, e ); + return TRUE; + } + } else if ( e->type() == TQEvent::MouseButtonDblClick ) { + popup->close(); + setFocus(); + blockSignals( TRUE ); + setText( listbox->currentText() ); + blockSignals( FALSE ); + emit chosen( text() ); + return TRUE; + } + } else if ( o == this ) { + if ( e->type() == TQEvent::KeyPress ) { + TQKeyEvent *ke = (TQKeyEvent*)e; + if ( ke->key() == Key_Up || + ke->key() == Key_Down || + ke->key() == Key_Prior || + ke->key() == Key_Next || + ke->key() == Key_Return || + ke->key() == Key_Enter || + ke->key() == Key_Tab || + ke->key() == Key_Escape ) { + TQApplication::sendEvent( listbox, e ); + return TRUE; + } + } + } + return TQLineEdit::eventFilter( o, e ); +} + +void TQCompletionEdit::addCompletionEntry( const TQString &entry ) +{ + if ( compList.find( entry ) == compList.end() ) { + compList << entry; + compList.sort(); + } +} + +void TQCompletionEdit::removeCompletionEntry( const TQString &entry ) +{ + TQStringList::Iterator it = compList.find( entry ); + if ( it != compList.end() ) + compList.remove( it ); +} + +void TQCompletionEdit::setCaseSensitive( bool b ) +{ + caseSensitive = b; +} + +bool TQCompletionEdit::isCaseSensitive() const +{ + return caseSensitive; +} + +void TQCompletionEdit::clear() +{ + TQLineEdit::clear(); + compList.clear(); +} diff --git a/tools/designer/designer/tqcompletionedit.h b/tools/designer/designer/tqcompletionedit.h new file mode 100644 index 000000000..792f74002 --- /dev/null +++ b/tools/designer/designer/tqcompletionedit.h @@ -0,0 +1,86 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of TQt Designer. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid TQt Commercial licenses may use this file in +** accordance with the TQt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#ifndef TQCOMPLETIONEDIT_H +#define TQCOMPLETIONEDIT_H + +#include +#include + +class TQListBox; +class TQVBox; + +class TQCompletionEdit : public TQLineEdit +{ + TQ_OBJECT + TQ_PROPERTY( bool autoAdd READ autoAdd WRITE setAutoAdd ) + TQ_PROPERTY( bool caseSensitive READ isCaseSensitive WRITE setCaseSensitive ) + +public: + TQCompletionEdit( TQWidget *parent = 0, const char *name = 0 ); + + bool autoAdd() const; + TQStringList completionList() const; + bool eventFilter( TQObject *o, TQEvent *e ); + bool isCaseSensitive() const; + +public slots: + void setCompletionList( const TQStringList &l ); + void setAutoAdd( bool add ); + void clear(); + void addCompletionEntry( const TQString &entry ); + void removeCompletionEntry( const TQString &entry ); + void setCaseSensitive( bool b ); + +signals: + void chosen( const TQString &text ); + +private slots: + void textDidChange( const TQString &text ); + +private: + void placeListBox(); + void updateListBox(); + +private: + bool aAdd; + TQStringList compList; + TQListBox *listbox; + TQVBox *popup; + bool caseSensitive; + +}; + + + +#endif diff --git a/tools/designer/designer/workspace.cpp b/tools/designer/designer/workspace.cpp index d09328ce8..485f02ea4 100644 --- a/tools/designer/designer/workspace.cpp +++ b/tools/designer/designer/workspace.cpp @@ -53,7 +53,7 @@ #include #include #include -#include "qcompletionedit.h" +#include "tqcompletionedit.h" WorkspaceItem::WorkspaceItem( TQListView *parent, Project* p ) : TQListViewItem( parent ) diff --git a/tools/designer/editor/browser.cpp b/tools/designer/editor/browser.cpp index d32e8551c..1ec24ffb8 100644 --- a/tools/designer/editor/browser.cpp +++ b/tools/designer/editor/browser.cpp @@ -33,7 +33,7 @@ #include "browser.h" #include "editor.h" -#include +#include EditorBrowser::EditorBrowser( Editor *e ) diff --git a/tools/designer/editor/cindent.h b/tools/designer/editor/cindent.h index d5b98ddf3..6e7e12245 100644 --- a/tools/designer/editor/cindent.h +++ b/tools/designer/editor/cindent.h @@ -34,7 +34,7 @@ #ifndef CINDENT_H #define CINDENT_H -#include +#include class CIndent : public TQTextIndent { diff --git a/tools/designer/editor/completion.cpp b/tools/designer/editor/completion.cpp index ee9d77331..b8e71233b 100644 --- a/tools/designer/editor/completion.cpp +++ b/tools/designer/editor/completion.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include "arghintwidget.h" diff --git a/tools/designer/editor/editor.cpp b/tools/designer/editor/editor.cpp index fdf5f106d..86af88362 100644 --- a/tools/designer/editor/editor.cpp +++ b/tools/designer/editor/editor.cpp @@ -34,7 +34,7 @@ #include "editor.h" #include "parenmatcher.h" #include -#include +#include #include "conf.h" #include #include diff --git a/tools/designer/editor/markerwidget.cpp b/tools/designer/editor/markerwidget.cpp index c393d9c35..3ce1ae3fc 100644 --- a/tools/designer/editor/markerwidget.cpp +++ b/tools/designer/editor/markerwidget.cpp @@ -33,7 +33,7 @@ #include "markerwidget.h" #include "viewmanager.h" -#include +#include #include "editor.h" #include #include diff --git a/tools/designer/editor/paragdata.h b/tools/designer/editor/paragdata.h index 772aaede9..23ed6b52d 100644 --- a/tools/designer/editor/paragdata.h +++ b/tools/designer/editor/paragdata.h @@ -35,7 +35,7 @@ #define PARAGDATA_H #include "parenmatcher.h" -#include +#include struct ParagData : public TQTextParagraphData { diff --git a/tools/designer/editor/parenmatcher.cpp b/tools/designer/editor/parenmatcher.cpp index 9f72a65d6..5976fc0ff 100644 --- a/tools/designer/editor/parenmatcher.cpp +++ b/tools/designer/editor/parenmatcher.cpp @@ -35,7 +35,7 @@ #include "paragdata.h" #include "tqtextedit.h" -#include +#include #include ParenMatcher::ParenMatcher() diff --git a/tools/designer/editor/viewmanager.cpp b/tools/designer/editor/viewmanager.cpp index a57f2ddb9..a897b8ba6 100644 --- a/tools/designer/editor/viewmanager.cpp +++ b/tools/designer/editor/viewmanager.cpp @@ -35,7 +35,7 @@ #include "editor.h" #include "markerwidget.h" #include -#include +#include #include "paragdata.h" #include #include diff --git a/tools/designer/interfaces/actioninterface.h b/tools/designer/interfaces/actioninterface.h index ab2c4e9bb..bf77e59d9 100644 --- a/tools/designer/interfaces/actioninterface.h +++ b/tools/designer/interfaces/actioninterface.h @@ -34,7 +34,7 @@ #ifndef ACTIONINTERFACE_H #define ACTIONINTERFACE_H -#include +#include class TQAction; class TQObject; diff --git a/tools/designer/interfaces/classbrowserinterface.h b/tools/designer/interfaces/classbrowserinterface.h index 2b95e0679..6af8755f0 100644 --- a/tools/designer/interfaces/classbrowserinterface.h +++ b/tools/designer/interfaces/classbrowserinterface.h @@ -47,7 +47,7 @@ // // -#include +#include #include class TQListView; diff --git a/tools/designer/interfaces/designerinterface.h b/tools/designer/interfaces/designerinterface.h index 982d83145..05b829389 100644 --- a/tools/designer/interfaces/designerinterface.h +++ b/tools/designer/interfaces/designerinterface.h @@ -47,7 +47,7 @@ // // -#include +#include #include #include #include diff --git a/tools/designer/interfaces/editorinterface.h b/tools/designer/interfaces/editorinterface.h index e14d563d3..2349cc058 100644 --- a/tools/designer/interfaces/editorinterface.h +++ b/tools/designer/interfaces/editorinterface.h @@ -47,7 +47,7 @@ // // -#include +#include #include #include diff --git a/tools/designer/interfaces/filterinterface.h b/tools/designer/interfaces/filterinterface.h index 42e6cf998..7db2155cf 100644 --- a/tools/designer/interfaces/filterinterface.h +++ b/tools/designer/interfaces/filterinterface.h @@ -34,7 +34,7 @@ #ifndef FILTERINTERFACE_H #define FILTERINTERFACE_H -#include +#include // {ea8cb381-59b5-44a8-bae5-9bea8295762a} #ifndef IID_ImportFilter diff --git a/tools/designer/interfaces/interpreterinterface.h b/tools/designer/interfaces/interpreterinterface.h index 2bf3f008c..b88461e02 100644 --- a/tools/designer/interfaces/interpreterinterface.h +++ b/tools/designer/interfaces/interpreterinterface.h @@ -47,7 +47,7 @@ // // -#include +#include class TQObject; diff --git a/tools/designer/interfaces/languageinterface.h b/tools/designer/interfaces/languageinterface.h index 58f6d5dc9..5c586eed7 100644 --- a/tools/designer/interfaces/languageinterface.h +++ b/tools/designer/interfaces/languageinterface.h @@ -47,7 +47,7 @@ // // -#include +#include #include #include #include diff --git a/tools/designer/interfaces/preferenceinterface.h b/tools/designer/interfaces/preferenceinterface.h index 222a054ec..22e4f36d2 100644 --- a/tools/designer/interfaces/preferenceinterface.h +++ b/tools/designer/interfaces/preferenceinterface.h @@ -47,7 +47,7 @@ // // -#include +#include #include #include diff --git a/tools/designer/interfaces/projectsettingsiface.h b/tools/designer/interfaces/projectsettingsiface.h index c6f6a2c22..203d79665 100644 --- a/tools/designer/interfaces/projectsettingsiface.h +++ b/tools/designer/interfaces/projectsettingsiface.h @@ -47,7 +47,7 @@ // // -#include +#include #include #include diff --git a/tools/designer/interfaces/sourcetemplateiface.h b/tools/designer/interfaces/sourcetemplateiface.h index 5757f4f16..489254540 100644 --- a/tools/designer/interfaces/sourcetemplateiface.h +++ b/tools/designer/interfaces/sourcetemplateiface.h @@ -47,7 +47,7 @@ // // -#include +#include #include // {1b3446a4-1c71-424b-8789-1f34eb5697d8} diff --git a/tools/designer/interfaces/templatewizardiface.h b/tools/designer/interfaces/templatewizardiface.h index 7f882e238..1cd80eb8f 100644 --- a/tools/designer/interfaces/templatewizardiface.h +++ b/tools/designer/interfaces/templatewizardiface.h @@ -47,7 +47,7 @@ // // -#include +#include class TQWidget; struct DesignerFormWindow; diff --git a/tools/designer/plugins/cppeditor/cppbrowser.cpp b/tools/designer/plugins/cppeditor/cppbrowser.cpp index 2e05dd074..85d151553 100644 --- a/tools/designer/plugins/cppeditor/cppbrowser.cpp +++ b/tools/designer/plugins/cppeditor/cppbrowser.cpp @@ -33,7 +33,7 @@ **********************************************************************/ #include "cppbrowser.h" -#include +#include #include #include #include diff --git a/tools/designer/plugins/cppeditor/editorinterfaceimpl.cpp b/tools/designer/plugins/cppeditor/editorinterfaceimpl.cpp index f58b66b42..a7b60eae1 100644 --- a/tools/designer/plugins/cppeditor/editorinterfaceimpl.cpp +++ b/tools/designer/plugins/cppeditor/editorinterfaceimpl.cpp @@ -35,7 +35,7 @@ #include "editorinterfaceimpl.h" #include #include "cppeditor.h" -#include +#include #include #include "completion.h" #include diff --git a/tools/designer/plugins/cppeditor/syntaxhighliter_cpp.h b/tools/designer/plugins/cppeditor/syntaxhighliter_cpp.h index 45cd01350..92f0e4e79 100644 --- a/tools/designer/plugins/cppeditor/syntaxhighliter_cpp.h +++ b/tools/designer/plugins/cppeditor/syntaxhighliter_cpp.h @@ -35,7 +35,7 @@ #ifndef TQCPPSYNTAXHIGHLIGHTER_H #define TQCPPSYNTAXHIGHLIGHTER_H -#include +#include #include class SyntaxHighlighter_CPP : public TQTextPreProcessor diff --git a/tools/designer/shared/widgetdatabase.h b/tools/designer/shared/widgetdatabase.h index 234c7c974..9b083ba44 100644 --- a/tools/designer/shared/widgetdatabase.h +++ b/tools/designer/shared/widgetdatabase.h @@ -37,7 +37,7 @@ #include #include #include "../interfaces/widgetinterface.h" // up here for GCC 2.7.* compatibility -#include +#include extern TQPluginManager *widgetManager(); diff --git a/tools/designer/tools/tqtconv2ui/main.cpp b/tools/designer/tools/tqtconv2ui/main.cpp index 9ae6c558e..4044e1e4a 100644 --- a/tools/designer/tools/tqtconv2ui/main.cpp +++ b/tools/designer/tools/tqtconv2ui/main.cpp @@ -32,7 +32,7 @@ **********************************************************************/ #include -#include +#include #include #include #include diff --git a/tools/designer/uilib/tqwidgetfactory.cpp b/tools/designer/uilib/tqwidgetfactory.cpp index 7b47cbf02..a608eeaf8 100644 --- a/tools/designer/uilib/tqwidgetfactory.cpp +++ b/tools/designer/uilib/tqwidgetfactory.cpp @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include diff --git a/tools/linguist/linguist/msgedit.cpp b/tools/linguist/linguist/msgedit.cpp index 4de407bc8..06689d4ad 100644 --- a/tools/linguist/linguist/msgedit.cpp +++ b/tools/linguist/linguist/msgedit.cpp @@ -62,7 +62,7 @@ #include #include #include -#include +#include static const int MaxCandidates = 5; diff --git a/translations/qt_ar.ts b/translations/qt_ar.ts index ad788413a..4aaaca45e 100644 --- a/translations/qt_ar.ts +++ b/translations/qt_ar.ts @@ -1657,7 +1657,7 @@ to - QTitleBar + TQTitleBar System Menu قائمة خيارات النّظام diff --git a/translations/qt_ca.ts b/translations/qt_ca.ts index e19912815..456037552 100644 --- a/translations/qt_ca.ts +++ b/translations/qt_ca.ts @@ -1665,7 +1665,7 @@ per a més informació.</p> - QTitleBar + TQTitleBar System Menu Menú del sistema diff --git a/translations/qt_cs.ts b/translations/qt_cs.ts index 747b0268f..54c88118f 100644 --- a/translations/qt_cs.ts +++ b/translations/qt_cs.ts @@ -1665,7 +1665,7 @@ dalšími verzemi Unixu s grafickým prostředím X11. - QTitleBar + TQTitleBar System Menu Systémová nabídka diff --git a/translations/qt_de.ts b/translations/qt_de.ts index f997b0366..a97c8f3da 100644 --- a/translations/qt_de.ts +++ b/translations/qt_de.ts @@ -1756,7 +1756,7 @@ nach - QTitleBar + TQTitleBar System Menu System-Menü diff --git a/translations/qt_es.ts b/translations/qt_es.ts index 2570cb1b6..e220ddb27 100644 --- a/translations/qt_es.ts +++ b/translations/qt_es.ts @@ -1659,7 +1659,7 @@ a - QTitleBar + TQTitleBar System Menu Menú sistema diff --git a/translations/qt_fr.ts b/translations/qt_fr.ts index 9618ae8d4..45d2fa172 100644 --- a/translations/qt_fr.ts +++ b/translations/qt_fr.ts @@ -1782,7 +1782,7 @@ en - QTitleBar + TQTitleBar System Menu Menu système diff --git a/translations/qt_he.ts b/translations/qt_he.ts index 48bec70a8..f46b6d54a 100644 --- a/translations/qt_he.ts +++ b/translations/qt_he.ts @@ -1753,7 +1753,7 @@ to - QTitleBar + TQTitleBar System Menu תפריט מערכת diff --git a/translations/qt_it.ts b/translations/qt_it.ts index 905b57113..9a38a7ecc 100644 --- a/translations/qt_it.ts +++ b/translations/qt_it.ts @@ -1659,7 +1659,7 @@ in - QTitleBar + TQTitleBar System Menu Menu di sistema diff --git a/translations/qt_ja.ts b/translations/qt_ja.ts index efed90783..ea7b2065d 100644 --- a/translations/qt_ja.ts +++ b/translations/qt_ja.ts @@ -1657,7 +1657,7 @@ to - QTitleBar + TQTitleBar System Menu システムメニュー diff --git a/translations/qt_nb.ts b/translations/qt_nb.ts index 37397bff9..29d1e7db0 100644 --- a/translations/qt_nb.ts +++ b/translations/qt_nb.ts @@ -1659,7 +1659,7 @@ til - QTitleBar + TQTitleBar System Menu Systemmeny diff --git a/translations/qt_pt-br.ts b/translations/qt_pt-br.ts index 90ed5a4c9..298d3e37b 100644 --- a/translations/qt_pt-br.ts +++ b/translations/qt_pt-br.ts @@ -1659,7 +1659,7 @@ para - QTitleBar + TQTitleBar System Menu Menu do Sistema diff --git a/translations/qt_pt.ts b/translations/qt_pt.ts index aa728eb68..bcb9e2157 100644 --- a/translations/qt_pt.ts +++ b/translations/qt_pt.ts @@ -1659,7 +1659,7 @@ para - QTitleBar + TQTitleBar System Menu Menu do Sistema diff --git a/translations/qt_ru.ts b/translations/qt_ru.ts index e76288ff1..5cb9a411b 100644 --- a/translations/qt_ru.ts +++ b/translations/qt_ru.ts @@ -1880,7 +1880,7 @@ to - QTitleBar + TQTitleBar System Menu Системное меню diff --git a/translations/qt_sk.ts b/translations/qt_sk.ts index 0f8a78b6d..67386a60b 100644 --- a/translations/qt_sk.ts +++ b/translations/qt_sk.ts @@ -1666,7 +1666,7 @@ Mac&nbsp;OS&nbsp;X, Linux, a mnohé ďalšie komerčné verzie Unixu. - QTitleBar + TQTitleBar System Menu Systémová ponuka diff --git a/translations/qt_tr.ts b/translations/qt_tr.ts index 7ef64db17..7b6c4e6db 100644 --- a/translations/qt_tr.ts +++ b/translations/qt_tr.ts @@ -1640,7 +1640,7 @@ to - QTitleBar + TQTitleBar System Menu diff --git a/translations/qt_zh-cn.ts b/translations/qt_zh-cn.ts index dd132e36c..4a7622157 100644 --- a/translations/qt_zh-cn.ts +++ b/translations/qt_zh-cn.ts @@ -1656,7 +1656,7 @@ to - QTitleBar + TQTitleBar System Menu 系统菜单 diff --git a/translations/qt_zh-tw.ts b/translations/qt_zh-tw.ts index 18e42dbdd..7848b4545 100644 --- a/translations/qt_zh-tw.ts +++ b/translations/qt_zh-tw.ts @@ -1657,7 +1657,7 @@ to - QTitleBar + TQTitleBar System Menu 系統功能表 diff --git a/translations/template.ts b/translations/template.ts index 07432c421..61bc14dc1 100644 --- a/translations/template.ts +++ b/translations/template.ts @@ -1638,7 +1638,7 @@ to - QTitleBar + TQTitleBar System Menu -- cgit v1.2.1