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 --- 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 + 154 files changed, 44775 insertions(+), 44775 deletions(-) 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 (limited to 'src') 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 -- cgit v1.2.3